void-packages/srcpkgs/tigervnc/patches/xorg-1.20-ignore-fake-focus...

120 lines
3.9 KiB
Diff

From 46665b6c791597d5f4f7a0351c491e4dd38b0d71 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman@cendio.se>
Date: Tue, 12 Jun 2018 15:57:27 +0200
Subject: [PATCH 1/2] Update comment about keyboard grab on focus changes
It is no longer a workaround but rather intended behaviour.
From 1d94124f6854e73eef58c595b2b1a4d2a7333962 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman@cendio.se>
Date: Tue, 12 Jun 2018 15:58:34 +0200
Subject: [PATCH 2/2] Ignore fake focus events from XGrabKeyboard()
Grabbing (and ungrabbing) the keyboard generates fake focus events
with modern versions of Xorg. This causes an infinite loop since we
update the grab status on focus events.
Work around this by ignoring these fake events.
--- vncviewer/DesktopWindow.cxx
+++ vncviewer/DesktopWindow.cxx
@@ -662,20 +662,16 @@ int DesktopWindow::fltkHandle(int event,
if (dw && fullscreenSystemKeys) {
switch (event) {
+ // Focus might not stay with us just because we have grabbed the
+ // keyboard. E.g. we might have sub windows, or we're not using
+ // all monitors and the user clicked on another application.
+ // Make sure we update our grabs with the focus changes.
case FL_FOCUS:
- // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
- // some issues we need to work around:
- // a) Fl::grab(0) on X11 will release the keyboard grab for us.
- // b) Gaining focus on the system level causes FLTK to switch
- // window level on OS X.
if (dw->fullscreen_active())
dw->grabKeyboard();
break;
case FL_UNFOCUS:
- // FIXME: We need to relinquish control when the entire window loses
- // focus as it is very tied to this specific window on some
- // platforms and we want to be able to open subwindows.
dw->ungrabKeyboard();
break;
}
@@ -729,6 +725,23 @@ void DesktopWindow::fullscreen_on()
fullscreen();
}
+#if !defined(WIN32) && !defined(__APPLE__)
+Bool eventIsFocusWithSerial(Display *display, XEvent *event, XPointer arg)
+{
+ unsigned long serial;
+
+ serial = *(unsigned long*)arg;
+
+ if (event->xany.serial != serial)
+ return False;
+
+ if ((event->type != FocusIn) && (event->type != FocusOut))
+ return False;
+
+ return True;
+}
+#endif
+
void DesktopWindow::grabKeyboard()
{
// Grabbing the keyboard is fairly safe as FLTK reroutes events to the
@@ -752,6 +765,11 @@ void DesktopWindow::grabKeyboard()
#else
int ret;
+ XEvent xev;
+ unsigned long serial;
+
+ serial = XNextRequest(fl_display);
+
ret = XGrabKeyboard(fl_display, fl_xid(this), True,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (ret) {
@@ -774,6 +792,16 @@ void DesktopWindow::grabKeyboard()
None, None, CurrentTime);
if (ret)
vlog.error(_("Failure grabbing mouse"));
+
+ // Xorg 1.20+ generates FocusIn/FocusOut even when there is no actual
+ // change of focus. This causes us to get stuck in an endless loop
+ // grabbing and ungrabbing the keyboard. Avoid this by filtering out
+ // any focus events generated by XGrabKeyboard().
+ XSync(fl_display, False);
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
+ (XPointer)&serial) == True) {
+ vlog.debug("Ignored synthetic focus event cause by grab change");
+ }
#endif
}
@@ -791,8 +819,20 @@ void DesktopWindow::ungrabKeyboard()
if (Fl::grab())
return;
+ XEvent xev;
+ unsigned long serial;
+
+ serial = XNextRequest(fl_display);
+
XUngrabPointer(fl_display, fl_event_time);
XUngrabKeyboard(fl_display, fl_event_time);
+
+ // See grabKeyboard()
+ XSync(fl_display, False);
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
+ (XPointer)&serial) == True) {
+ vlog.debug("Ignored synthetic focus event cause by grab change");
+ }
#endif
}