Krolyxon
Commit e310136

Branches

Refs →

nsxive310136

Mouse drag translates pointer position to image area

This makes mouse panning more direct and faster.
Author
Bert Münnich
Date
2017-10-04 18:12 +0200
Committer
Bert Münnich · 2017-10-04 18:22 +0200
Parent
9b6acc7
Commit
e310136e02ada4862c250280034d36fbfa24fc61

+40 −64

7 files changed

  1. M Makefile +1 −1
  2. M commands.c +23 −54
  3. M image.c +8 −3
  4. M image.h +1 −0
  5. M main.c +1 −0
  6. M types.h +1 −1
  7. M window.c +5 −5
M Makefile View
@@ -1,4 +1,4 @@
1−VERSION := git-20170908
1+VERSION := git-20171004
22
33 all: sxiv
44
M commands.c View
@@ -320,72 +320,41 @@ bool ci_scroll_to_edge(arg_t dir)
320320 return img_pan_edge(&img, dir);
321321 }
322322
323−/* Xlib helper function for i_drag() */
324−Bool is_motionnotify(Display *d, XEvent *e, XPointer a)
325−{
326− return e != NULL && e->type == MotionNotify;
327−}
328−
329−#define WARP(x,y) \
330− XWarpPointer(win.env.dpy, None, win.xwin, 0, 0, 0, 0, x, y); \
331− ox = x, oy = y; \
332− break
333−
334323 bool ci_drag(arg_t _)
335324 {
336− int dx = 0, dy = 0, i, ox, oy, x, y;
325+ int i, x, y;
326+ float px, py;
337327 unsigned int ui;
338− bool dragging = true, next = false;
339328 XEvent e;
340329 Window w;
341330
342− if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
331+ if ((int)(img.w * img.zoom) < win.w && (int)(img.h * img.zoom) < win.h)
332+ return false;
333+ if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &x, &y, &ui))
343334 return false;
344335
345− win_set_cursor(&win, CURSOR_HAND);
346−
347− while (dragging) {
348− if (!next)
349− XMaskEvent(win.env.dpy,
350− ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
351− switch (e.type) {
352− case ButtonPress:
353− case ButtonRelease:
354− dragging = false;
355− break;
356− case MotionNotify:
357− x = e.xmotion.x;
358− y = e.xmotion.y;
359−
360− /* wrap the mouse around */
361− if (x <= 0) {
362− WARP(win.w - 2, y);
363− } else if (x >= win.w - 1) {
364− WARP(1, y);
365− } else if (y <= 0) {
366− WARP(x, win.h - 2);
367− } else if (y >= win.h - 1) {
368− WARP(x, 1);
369− }
370− dx += x - ox;
371− dy += y - oy;
372− ox = x;
373− oy = y;
374− break;
375− }
376− if (dragging)
377− next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None);
378− if ((!dragging || !next) && (dx != 0 || dy != 0)) {
379− if (img_move(&img, dx, dy)) {
380− img_render(&img);
381− win_draw(&win);
382− }
383− dx = dy = 0;
336+ win_set_cursor(&win, CURSOR_DRAG);
337+
338+ for (;;) {
339+ px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8)
340+ * (win.w - img.w * img.zoom);
341+ py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8)
342+ * (win.h - img.h * img.zoom);
343+
344+ if (img_pos(&img, px, py)) {
345+ img_render(&img);
346+ win_draw(&win);
384347 }
348+ XMaskEvent(win.env.dpy,
349+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
350+ if (e.type == ButtonPress || e.type == ButtonRelease)
351+ break;
352+ while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
353+ x = e.xmotion.x;
354+ y = e.xmotion.y;
385355 }
386356 win_set_cursor(&win, CURSOR_ARROW);
387357 set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
388− reset_timeout(redraw);
389358
390359 return true;
391360 }
M image.c View
@@ -567,15 +567,15 @@ bool img_zoom_out(img_t *img)
567567 return false;
568568 }
569569
570−bool img_move(img_t *img, float dx, float dy)
570+bool img_pos(img_t *img, float x, float y)
571571 {
572572 float ox, oy;
573573
574574 ox = img->x;
575575 oy = img->y;
576576
577− img->x += dx;
578− img->y += dy;
577+ img->x = x;
578+ img->y = y;
579579
580580 img_check_pan(img, true);
581581
@@ -587,6 +587,11 @@ bool img_move(img_t *img, float dx, float dy)
587587 }
588588 }
589589
590+bool img_move(img_t *img, float dx, float dy)
591+{
592+ return img_pos(img, img->x + dx, img->y + dy);
593+}
594+
590595 bool img_pan(img_t *img, direction_t dir, int d)
591596 {
592597 /* d < 0: screen-wise
M image.h View
@@ -80,6 +80,7 @@ bool img_zoom(img_t*, float);
8080 bool img_zoom_in(img_t*);
8181 bool img_zoom_out(img_t*);
8282
83+bool img_pos(img_t*, float, float);
8384 bool img_move(img_t*, float, float);
8485 bool img_pan(img_t*, direction_t, int);
8586 bool img_pan_edge(img_t*, direction_t);
M main.c View
@@ -741,6 +741,7 @@ void run(void)
741741 XPeekEvent(win.env.dpy, &nextev);
742742 switch (ev.type) {
743743 case ConfigureNotify:
744+ case MotionNotify:
744745 discard = ev.type == nextev.type;
745746 break;
746747 case KeyPress:
M types.h View
@@ -66,7 +66,7 @@ typedef enum {
6666 typedef enum {
6767 CURSOR_ARROW,
6868 CURSOR_NONE,
69− CURSOR_HAND,
69+ CURSOR_DRAG,
7070 CURSOR_WATCH
7171 } cursor_t;
7272
M window.c View
@@ -37,7 +37,7 @@ enum {
3737
3838 static Cursor carrow;
3939 static Cursor cnone;
40−static Cursor chand;
40+static Cursor cdrag;
4141 static Cursor cwatch;
4242 static GC gc;
4343
@@ -210,7 +210,7 @@ void win_open(win_t *win)
210210 PointerMotionMask | StructureNotifyMask);
211211
212212 carrow = XCreateFontCursor(e->dpy, XC_left_ptr);
213− chand = XCreateFontCursor(e->dpy, XC_fleur);
213+ cdrag = XCreateFontCursor(e->dpy, XC_dotbox);
214214 cwatch = XCreateFontCursor(e->dpy, XC_watch);
215215
216216 if (XAllocNamedColor(e->dpy, DefaultColormap(e->dpy, e->scr), "black",
@@ -277,7 +277,7 @@ CLEANUP void win_close(win_t *win)
277277 {
278278 XFreeCursor(win->env.dpy, carrow);
279279 XFreeCursor(win->env.dpy, cnone);
280− XFreeCursor(win->env.dpy, chand);
280+ XFreeCursor(win->env.dpy, cdrag);
281281 XFreeCursor(win->env.dpy, cwatch);
282282
283283 XFreeGC(win->env.dpy, gc);
@@ -465,8 +465,8 @@ void win_set_cursor(win_t *win, cursor_t cursor)
465465 case CURSOR_NONE:
466466 XDefineCursor(win->env.dpy, win->xwin, cnone);
467467 break;
468− case CURSOR_HAND:
469− XDefineCursor(win->env.dpy, win->xwin, chand);
468+ case CURSOR_DRAG:
469+ XDefineCursor(win->env.dpy, win->xwin, cdrag);
470470 break;
471471 case CURSOR_WATCH:
472472 XDefineCursor(win->env.dpy, win->xwin, cwatch);