@@ -1,6 +1,6 @@ | |||||
all: sxiv | all: sxiv | ||||
VERSION=0.3 | VERSION=git-20110129 | ||||
CC?=gcc | CC?=gcc | ||||
PREFIX?=/usr/local | PREFIX?=/usr/local | ||||
@@ -230,7 +230,7 @@ int img_zoom_out(img_t *img) { | |||||
return 0; | return 0; | ||||
} | } | ||||
int img_pan(img_t *img, win_t *win, pandir_t dir) { | int img_move(img_t *img, win_t *win, int dx, int dy) { | ||||
int ox, oy; | int ox, oy; | ||||
if (!img || !win) | if (!img || !win) | ||||
@@ -239,24 +239,30 @@ int img_pan(img_t *img, win_t *win, pandir_t dir) { | |||||
ox = img->x; | ox = img->x; | ||||
oy = img->y; | oy = img->y; | ||||
img->x += dx; | |||||
img->y += dy; | |||||
img_check_pan(img, win); | |||||
return ox != img->x || oy != img->y; | |||||
} | |||||
int img_pan(img_t *img, win_t *win, pandir_t dir) { | |||||
if (!img || !win) | |||||
return 0; | |||||
switch (dir) { | switch (dir) { | ||||
case PAN_LEFT: | case PAN_LEFT: | ||||
img->x += win->w / 5; | return img_move(img, win, win->w / 5, 0); | ||||
break; | |||||
case PAN_RIGHT: | case PAN_RIGHT: | ||||
img->x -= win->w / 5; | return img_move(img, win, -win->w / 5, 0); | ||||
break; | |||||
case PAN_UP: | case PAN_UP: | ||||
img->y += win->h / 5; | return img_move(img, win, 0, win->h / 5); | ||||
break; | |||||
case PAN_DOWN: | case PAN_DOWN: | ||||
img->y -= win->h / 5; | return img_move(img, win, 0, -win->h / 5); | ||||
break; | |||||
} | } | ||||
img_check_pan(img, win); | return 0; | ||||
return ox != img->x || oy != img->y; | |||||
} | } | ||||
int img_rotate(img_t *img, win_t *win, int d) { | int img_rotate(img_t *img, win_t *win, int d) { | ||||
@@ -58,6 +58,7 @@ void img_center(img_t*, win_t*); | |||||
int img_zoom_in(img_t*); | int img_zoom_in(img_t*); | ||||
int img_zoom_out(img_t*); | int img_zoom_out(img_t*); | ||||
int img_move(img_t*, win_t*, int, int); | |||||
int img_pan(img_t*, win_t*, pandir_t); | int img_pan(img_t*, win_t*, pandir_t); | ||||
int img_rotate_left(img_t*, win_t*); | int img_rotate_left(img_t*, win_t*); | ||||
@@ -31,6 +31,8 @@ | |||||
void on_keypress(XEvent*); | void on_keypress(XEvent*); | ||||
void on_buttonpress(XEvent*); | void on_buttonpress(XEvent*); | ||||
void on_buttonrelease(XEvent*); | |||||
void on_motionnotify(XEvent*); | |||||
void on_configurenotify(XEvent*); | void on_configurenotify(XEvent*); | ||||
void update_title(); | void update_title(); | ||||
@@ -38,6 +40,8 @@ void update_title(); | |||||
static void (*handler[LASTEvent])(XEvent*) = { | static void (*handler[LASTEvent])(XEvent*) = { | ||||
[KeyPress] = on_keypress, | [KeyPress] = on_keypress, | ||||
[ButtonPress] = on_buttonpress, | [ButtonPress] = on_buttonpress, | ||||
[ButtonRelease] = on_buttonrelease, | |||||
[MotionNotify] = on_motionnotify, | |||||
[ConfigureNotify] = on_configurenotify | [ConfigureNotify] = on_configurenotify | ||||
}; | }; | ||||
@@ -49,6 +53,9 @@ int filecnt, fileidx; | |||||
unsigned char timeout; | unsigned char timeout; | ||||
int mox; | |||||
int moy; | |||||
#define TITLE_LEN 256 | #define TITLE_LEN 256 | ||||
char win_title[TITLE_LEN]; | char win_title[TITLE_LEN]; | ||||
@@ -276,6 +283,11 @@ void on_buttonpress(XEvent *ev) { | |||||
changed = 1; | changed = 1; | ||||
} | } | ||||
break; | break; | ||||
case Button2: | |||||
mox = ev->xbutton.x; | |||||
moy = ev->xbutton.y; | |||||
win_set_cursor(&win, CURSOR_HAND); | |||||
break; | |||||
case Button3: | case Button3: | ||||
if (fileidx > 0) { | if (fileidx > 0) { | ||||
img_load(&img, filenames[--fileidx]); | img_load(&img, filenames[--fileidx]); | ||||
@@ -313,6 +325,31 @@ void on_buttonpress(XEvent *ev) { | |||||
} | } | ||||
} | } | ||||
void on_buttonrelease(XEvent *ev) { | |||||
if (!ev) | |||||
return; | |||||
if (ev->xbutton.button == Button2) | |||||
win_set_cursor(&win, CURSOR_ARROW); | |||||
} | |||||
void on_motionnotify(XEvent *ev) { | |||||
XMotionEvent *m; | |||||
if (!ev) | |||||
return; | |||||
m = &ev->xmotion; | |||||
if (m->x >= 0 && m->x <= win.w && m->y >= 0 && m->y <= win.h) { | |||||
if (img_move(&img, &win, m->x - mox, m->y - moy)) | |||||
timeout = 1; | |||||
mox = m->x; | |||||
moy = m->y; | |||||
} | |||||
} | |||||
void on_configurenotify(XEvent *ev) { | void on_configurenotify(XEvent *ev) { | ||||
if (!ev) | if (!ev) | ||||
return; | return; | ||||
@@ -21,12 +21,16 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
#include <X11/cursorfont.h> | |||||
#include "sxiv.h" | #include "sxiv.h" | ||||
#include "options.h" | #include "options.h" | ||||
#include "window.h" | #include "window.h" | ||||
GC bgc; | static Cursor arrow; | ||||
static Cursor hand; | |||||
static GC bgc; | |||||
void win_open(win_t *win) { | void win_open(win_t *win) { | ||||
win_env_t *e; | win_env_t *e; | ||||
@@ -66,8 +70,11 @@ void win_open(win_t *win) { | |||||
if (win->xwin == None) | if (win->xwin == None) | ||||
DIE("could not create window"); | DIE("could not create window"); | ||||
XSelectInput(e->dpy, win->xwin, | XSelectInput(e->dpy, win->xwin, StructureNotifyMask | KeyPressMask | | ||||
StructureNotifyMask | KeyPressMask | ButtonPressMask); | ButtonPressMask | ButtonReleaseMask | Button2MotionMask); | ||||
arrow = XCreateFontCursor(e->dpy, XC_left_ptr); | |||||
hand = XCreateFontCursor(e->dpy, XC_fleur); | |||||
bgc = XCreateGC(e->dpy, win->xwin, 0, None); | bgc = XCreateGC(e->dpy, win->xwin, 0, None); | ||||
@@ -91,6 +98,11 @@ void win_close(win_t *win) { | |||||
if (!win) | if (!win) | ||||
return; | return; | ||||
XFreeCursor(win->env.dpy, arrow); | |||||
XFreeCursor(win->env.dpy, hand); | |||||
XFreeGC(win->env.dpy, bgc); | |||||
XDestroyWindow(win->env.dpy, win->xwin); | XDestroyWindow(win->env.dpy, win->xwin); | ||||
XCloseDisplay(win->env.dpy); | XCloseDisplay(win->env.dpy); | ||||
} | } | ||||
@@ -174,3 +186,18 @@ void win_draw(win_t *win) { | |||||
XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->pm); | XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->pm); | ||||
XClearWindow(win->env.dpy, win->xwin); | XClearWindow(win->env.dpy, win->xwin); | ||||
} | } | ||||
void win_set_cursor(win_t *win, win_cur_t cursor) { | |||||
if (!win) | |||||
return; | |||||
switch (cursor) { | |||||
case CURSOR_HAND: | |||||
XDefineCursor(win->env.dpy, win->xwin, hand); | |||||
break; | |||||
case CURSOR_ARROW: | |||||
default: | |||||
XDefineCursor(win->env.dpy, win->xwin, arrow); | |||||
break; | |||||
} | |||||
} |
@@ -23,6 +23,11 @@ | |||||
#define CLEANMASK(mask) ((mask) & ~LockMask) | #define CLEANMASK(mask) ((mask) & ~LockMask) | ||||
typedef enum win_cur_e { | |||||
CURSOR_ARROW = 0, | |||||
CURSOR_HAND | |||||
} win_cur_t; | |||||
typedef struct win_env_s { | typedef struct win_env_s { | ||||
Display *dpy; | Display *dpy; | ||||
int scr; | int scr; | ||||
@@ -59,4 +64,6 @@ void win_toggle_fullscreen(win_t*); | |||||
void win_clear(win_t*); | void win_clear(win_t*); | ||||
void win_draw(win_t*); | void win_draw(win_t*); | ||||
void win_set_cursor(win_t*, win_cur_t); | |||||
#endif /* WINDOW_H */ | #endif /* WINDOW_H */ |