From e310136e02ada4862c250280034d36fbfa24fc61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Wed, 4 Oct 2017 18:12:27 +0200 Subject: [PATCH] Mouse drag translates pointer position to image area This makes mouse panning more direct and faster. --- Makefile | 2 +- commands.c | 73 ++++++++++++++++-------------------------------------- image.c | 11 +++++--- image.h | 1 + main.c | 1 + types.h | 2 +- window.c | 10 ++++---- 7 files changed, 38 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index 8a893c6..cc447de 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION := git-20170908 +VERSION := git-20171004 all: sxiv diff --git a/commands.c b/commands.c index 44a6cf5..2e1d66c 100644 --- a/commands.c +++ b/commands.c @@ -320,72 +320,41 @@ bool ci_scroll_to_edge(arg_t dir) return img_pan_edge(&img, dir); } -/* Xlib helper function for i_drag() */ -Bool is_motionnotify(Display *d, XEvent *e, XPointer a) -{ - return e != NULL && e->type == MotionNotify; -} - -#define WARP(x,y) \ - XWarpPointer(win.env.dpy, None, win.xwin, 0, 0, 0, 0, x, y); \ - ox = x, oy = y; \ - break - bool ci_drag(arg_t _) { - int dx = 0, dy = 0, i, ox, oy, x, y; + int i, x, y; + float px, py; unsigned int ui; - bool dragging = true, next = false; XEvent e; Window w; - if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui)) + if ((int)(img.w * img.zoom) < win.w && (int)(img.h * img.zoom) < win.h) + return false; + if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &x, &y, &ui)) return false; - win_set_cursor(&win, CURSOR_HAND); + win_set_cursor(&win, CURSOR_DRAG); - while (dragging) { - if (!next) - XMaskEvent(win.env.dpy, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); - switch (e.type) { - case ButtonPress: - case ButtonRelease: - dragging = false; - break; - case MotionNotify: - x = e.xmotion.x; - y = e.xmotion.y; + for (;;) { + px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8) + * (win.w - img.w * img.zoom); + py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8) + * (win.h - img.h * img.zoom); - /* wrap the mouse around */ - if (x <= 0) { - WARP(win.w - 2, y); - } else if (x >= win.w - 1) { - WARP(1, y); - } else if (y <= 0) { - WARP(x, win.h - 2); - } else if (y >= win.h - 1) { - WARP(x, 1); - } - dx += x - ox; - dy += y - oy; - ox = x; - oy = y; - break; - } - if (dragging) - next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None); - if ((!dragging || !next) && (dx != 0 || dy != 0)) { - if (img_move(&img, dx, dy)) { - img_render(&img); - win_draw(&win); - } - dx = dy = 0; + if (img_pos(&img, px, py)) { + img_render(&img); + win_draw(&win); } + XMaskEvent(win.env.dpy, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); + if (e.type == ButtonPress || e.type == ButtonRelease) + break; + while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e)); + x = e.xmotion.x; + y = e.xmotion.y; } win_set_cursor(&win, CURSOR_ARROW); set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - reset_timeout(redraw); return true; } diff --git a/image.c b/image.c index 36a232e..6ace9bd 100644 --- a/image.c +++ b/image.c @@ -567,15 +567,15 @@ bool img_zoom_out(img_t *img) return false; } -bool img_move(img_t *img, float dx, float dy) +bool img_pos(img_t *img, float x, float y) { float ox, oy; ox = img->x; oy = img->y; - img->x += dx; - img->y += dy; + img->x = x; + img->y = y; img_check_pan(img, true); @@ -587,6 +587,11 @@ bool img_move(img_t *img, float dx, float dy) } } +bool img_move(img_t *img, float dx, float dy) +{ + return img_pos(img, img->x + dx, img->y + dy); +} + bool img_pan(img_t *img, direction_t dir, int d) { /* d < 0: screen-wise diff --git a/image.h b/image.h index 2813c9b..37bc4a2 100644 --- a/image.h +++ b/image.h @@ -80,6 +80,7 @@ bool img_zoom(img_t*, float); bool img_zoom_in(img_t*); bool img_zoom_out(img_t*); +bool img_pos(img_t*, float, float); bool img_move(img_t*, float, float); bool img_pan(img_t*, direction_t, int); bool img_pan_edge(img_t*, direction_t); diff --git a/main.c b/main.c index aa11616..f7e5762 100644 --- a/main.c +++ b/main.c @@ -741,6 +741,7 @@ void run(void) XPeekEvent(win.env.dpy, &nextev); switch (ev.type) { case ConfigureNotify: + case MotionNotify: discard = ev.type == nextev.type; break; case KeyPress: diff --git a/types.h b/types.h index 6c87105..57402e0 100644 --- a/types.h +++ b/types.h @@ -66,7 +66,7 @@ typedef enum { typedef enum { CURSOR_ARROW, CURSOR_NONE, - CURSOR_HAND, + CURSOR_DRAG, CURSOR_WATCH } cursor_t; diff --git a/window.c b/window.c index c6d22d6..6ed4bfc 100644 --- a/window.c +++ b/window.c @@ -37,7 +37,7 @@ enum { static Cursor carrow; static Cursor cnone; -static Cursor chand; +static Cursor cdrag; static Cursor cwatch; static GC gc; @@ -210,7 +210,7 @@ void win_open(win_t *win) PointerMotionMask | StructureNotifyMask); carrow = XCreateFontCursor(e->dpy, XC_left_ptr); - chand = XCreateFontCursor(e->dpy, XC_fleur); + cdrag = XCreateFontCursor(e->dpy, XC_dotbox); cwatch = XCreateFontCursor(e->dpy, XC_watch); if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), "black", @@ -277,7 +277,7 @@ CLEANUP void win_close(win_t *win) { XFreeCursor(win->env.dpy, carrow); XFreeCursor(win->env.dpy, cnone); - XFreeCursor(win->env.dpy, chand); + XFreeCursor(win->env.dpy, cdrag); XFreeCursor(win->env.dpy, cwatch); XFreeGC(win->env.dpy, gc); @@ -465,8 +465,8 @@ void win_set_cursor(win_t *win, cursor_t cursor) case CURSOR_NONE: XDefineCursor(win->env.dpy, win->xwin, cnone); break; - case CURSOR_HAND: - XDefineCursor(win->env.dpy, win->xwin, chand); + case CURSOR_DRAG: + XDefineCursor(win->env.dpy, win->xwin, cdrag); break; case CURSOR_WATCH: XDefineCursor(win->env.dpy, win->xwin, cwatch);