From c7b78a6e35dddf23951730bca13f647b7ad1ae85 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Sun, 18 Sep 2011 23:45:11 +0000 Subject: [PATCH] Only grab mouse click on unfocused windows Prevents accidentally stealing all clicks --- sys-x11.c | 23 +++++++++++++++++++---- sys.h | 2 ++ wm-wmii.c | 20 ++++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/sys-x11.c b/sys-x11.c index 8d3887e..69b5bcb 100644 --- a/sys-x11.c +++ b/sys-x11.c @@ -258,9 +258,18 @@ static void process_event(int type, XEvent *ev, win_t *root) //printf("release: %d\n", type); } else if (type == ButtonPress) { - wm_handle_key(win, x2btn(ev->xbutton.button), mod, ptr); - XGrabPointer(dpy, ev->xbutton.root, True, PointerMotionMask|ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + if (wm_handle_key(win, x2btn(ev->xbutton.button), mod, ptr)) + XGrabPointer(dpy, ev->xbutton.root, True, PointerMotionMask|ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + else { + printf("resending event\n"); + XSendEvent(win->sys->dpy, ev->xbutton.window, True, NoEventMask, ev); + XSendEvent(win->sys->dpy, ev->xbutton.window, False, NoEventMask, ev); + XSendEvent(win->sys->dpy, ev->xbutton.root, True, NoEventMask, ev); + XSendEvent(win->sys->dpy, ev->xbutton.root, False, NoEventMask, ev); + XSendEvent(win->sys->dpy, ev->xbutton.subwindow, True, NoEventMask, ev); + XSendEvent(win->sys->dpy, ev->xbutton.subwindow, False, NoEventMask, ev); + } } else if (type == ButtonRelease) { XUngrabPointer(dpy, CurrentTime); @@ -392,7 +401,7 @@ void sys_watch(win_t *win, Key_t key, mod_t mod) XGetWindowAttributes(win->sys->dpy, win->sys->xid, &attr); long mask = attr.your_event_mask; if (key_mouse0 <= key && key <= key_mouse7) - XGrabButton(win->sys->dpy, btn2x(key), mod2x(mod), win->sys->xid, True, + XGrabButton(win->sys->dpy, btn2x(key), mod2x(mod), win->sys->xid, False, mod.up ? ButtonReleaseMask : ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); else if (key == key_enter) @@ -406,6 +415,12 @@ void sys_watch(win_t *win, Key_t key, mod_t mod) mod2x(mod), win->sys->xid, True, GrabModeAsync, GrabModeAsync); } +void sys_unwatch(win_t *win, Key_t key, mod_t mod) +{ + if (key_mouse0 <= key && key <= key_mouse7) + XUngrabButton(win->sys->dpy, btn2x(key), mod2x(mod), win->sys->xid); +} + win_t *sys_init(void) { Display *dpy; diff --git a/sys.h b/sys.h index 5e2d926..d70c893 100644 --- a/sys.h +++ b/sys.h @@ -51,6 +51,8 @@ typedef struct { void sys_watch(win_t *win, Key_t key, mod_t mod); +void sys_unwatch(win_t *win, Key_t key, mod_t mod); + void sys_move(win_t *win, int x, int y, int w, int h); void sys_raise(win_t *win); diff --git a/wm-wmii.c b/wm-wmii.c index 3ad2d8c..e202518 100644 --- a/wm-wmii.c +++ b/wm-wmii.c @@ -61,6 +61,17 @@ static void set_focus(win_t *win) { if (win->wm && win->wm->col) ((col_t*)win->wm->col->data)->focus = win; + + /* - Only grab mouse button on unfocused window, + * this prevents stealing all mouse clicks from client windows, + * - A better way may be to re-send mouse clicks to client windows + * using the return value from wm_handle_key */ + for (int i = key_mouse1; i < key_mouse7; i++) { + if (wm_focus) + sys_watch(wm_focus, i, MOD()); + sys_unwatch(win, i, MOD()); + } + wm_focus = win; sys_focus(win); } @@ -313,8 +324,11 @@ int wm_handle_key(win_t *win, Key_t key, mod_t mod, ptr_t ptr) return set_move(resize,win,ptr), 1; /* Focus change */ - if (key == key_enter || (key_mouse0 <= key && key <= key_mouse7)) - set_focus(win); + if (key == key_enter) + return set_focus(win), 1; + + if (key_mouse0 <= key && key <= key_mouse7) + return set_focus(win), 0; /* Reset focus after after focus change, * not sure what is causing the focus change in the first place @@ -417,6 +431,4 @@ void wm_init(win_t *root) sys_watch(root, keys_m[i], MOD(.MODKEY=1)); for (int i = 0; i < countof(keys_s); i++) sys_watch(root, keys_s[i], MOD(.MODKEY=1,.shift=1)); - for (int i = key_mouse1; i < key_mouse7; i++) - sys_watch(root, i, MOD()); } -- 2.43.2