From 2c6647112667109b109e578ffd55ae8409c9e1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Mon, 4 Jul 2016 21:55:23 +0200 Subject: Replay toolbar button events NOTICE!!!! THIS IS HIGHLY EXPERIMENTAL! The patch alters the button grab mode to GrabSync in order to ReplayPointer the event. THIS CAN FREEZE ANY INPUT TO FLUXBOX!!! The toolbar (and other things?) grab buttons in order to handle MouseN events for the entire bar, INCLUDING all child windows. This causes two problems: 1. The bar handles events which are not meant for fluxbox at all (but the systray icons) BUG: 940 2. The bar will intercept (and suck) *every* press, even if only doubleclicks are desired BUG: 949 The problem with this patch is that an oversight here has the potential to completely freeze input event processing in fluxbox (ie. the process needs to be killed from outside), SO IT NEEDS TESTING! As much as possible. --- src/FbTk/KeyUtil.cc | 2 +- src/SystemTray.cc | 13 +++++++++++++ src/SystemTray.hh | 2 ++ src/Toolbar.cc | 30 ++++++++++++++++++++++++++++-- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/FbTk/KeyUtil.cc b/src/FbTk/KeyUtil.cc index 6661bb7..10bc118 100644 --- a/src/FbTk/KeyUtil.cc +++ b/src/FbTk/KeyUtil.cc @@ -144,7 +144,7 @@ void KeyUtil::grabButton(unsigned int button, unsigned int mod, Window win, for (int i = 0; i < 8; i++) { XGrabButton(display, button, mod | (i & 1 ? LockMask : 0) | (i & 2 ? nummod : 0) | (i & 4 ? scrollmod : 0), - win, False, event_mask, GrabModeAsync, GrabModeAsync, + win, False, event_mask, GrabModeSync, GrabModeAsync, None, cursor); } diff --git a/src/SystemTray.cc b/src/SystemTray.cc index e45669e..4fa9da3 100644 --- a/src/SystemTray.cc +++ b/src/SystemTray.cc @@ -77,6 +77,8 @@ void getScreenCoordinates(Window win, int x, int y, int &screen_x, int &screen_y }; +static SystemTray *s_theoneandonly = 0; + /// helper class for tray windows, so we dont call XDestroyWindow class SystemTray::TrayWindow : public FbTk::FbWindow { public: @@ -220,6 +222,8 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, // set owner XSetSelectionOwner(disp, tray_atom, m_selection_owner.window(), CurrentTime); + s_theoneandonly = this; + m_handler.reset(new SystemTrayHandler(*this)); m_handler.get()->setName(atom_name); @@ -247,6 +251,8 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, SystemTray::~SystemTray() { // remove us, else fluxbox might delete the memory too + if (s_theoneandonly == this) + s_theoneandonly = 0; Fluxbox* fluxbox = Fluxbox::instance(); fluxbox->removeAtomHandler(m_handler.get()); Display *disp = fluxbox->display(); @@ -589,3 +595,10 @@ string SystemTray::getNetSystemTrayAtom(int screen_nr) { return atom_name; } + +bool SystemTray::doesControl(Window win) { + if (win == None || !s_theoneandonly) + return false; + return win == s_theoneandonly->window().window() || + s_theoneandonly->findClient(win) != s_theoneandonly->m_clients.end(); +} diff --git a/src/SystemTray.hh b/src/SystemTray.hh index 61cd1bb..470f9b9 100644 --- a/src/SystemTray.hh +++ b/src/SystemTray.hh @@ -87,6 +87,8 @@ public: static Atom getXEmbedInfoAtom(); + static bool doesControl(Window win); + private: void update(); diff --git a/src/Toolbar.cc b/src/Toolbar.cc index 92ab81a..bfaec94 100644 --- a/src/Toolbar.cc +++ b/src/Toolbar.cc @@ -31,6 +31,7 @@ #include "Keys.hh" #include "Screen.hh" #include "ScreenPlacement.hh" +#include "SystemTray.hh" #include "WindowCmd.hh" #include "Strut.hh" @@ -512,14 +513,39 @@ void Toolbar::reconfigure() { void Toolbar::buttonPressEvent(XButtonEvent &be) { + Display *dpy = Fluxbox::instance()->display(); + if (be.subwindow) { + // Do not intercept mouse events that are meant for the tray icon + if (SystemTray::doesControl(be.subwindow)) { + XAllowEvents(dpy, ReplayPointer, CurrentTime); + return; + } +#if 0 + // Unfortunately, the subwindow isn't exactly a reliable source here, so + // we COULD query the pointer (what will usually return the systray itself) and + // check that as well. NOTICE that due to the async nature of X11, the + // pointer might have moved and the result isn't correct either. + Window wr, wc; int junk; unsigned int ujunk; + XQueryPointer(dpy, be.window, &wr, &wc, &junk, &junk, &junk, &junk, &ujunk); + if (SystemTray::doesControl(wc)) { + XAllowEvents(dpy, ReplayPointer, CurrentTime); + return; + } +#endif + } + if (Fluxbox::instance()->keys()->doAction(be.type, be.state, be.button, - Keys::ON_TOOLBAR, 0, be.time)) + Keys::ON_TOOLBAR, 0, be.time)) { + XAllowEvents(dpy, SyncPointer, CurrentTime); return; + } if (be.button == 1) raise(); - if (be.button != 2) + if (be.button != 2 || be.subwindow) { // only handle direct toolbar MMBs + XAllowEvents(dpy, ReplayPointer, CurrentTime); return; + } screen() .placementStrategy() -- cgit v0.11.2