120 lines
3.9 KiB
Diff
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
|
||
|
}
|
||
|
|