|
|
b0f0da |
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
|
|
|
b0f0da |
index 47fe8f8..8f387dc 100644
|
|
|
b0f0da |
--- a/vncviewer/DesktopWindow.cxx
|
|
|
b0f0da |
+++ b/vncviewer/DesktopWindow.cxx
|
|
|
b0f0da |
@@ -1,16 +1,16 @@
|
|
|
b0f0da |
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
|
|
b0f0da |
* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
|
|
b0f0da |
- *
|
|
|
b0f0da |
+ *
|
|
|
b0f0da |
* This is free software; you can redistribute it and/or modify
|
|
|
b0f0da |
* it under the terms of the GNU General Public License as published by
|
|
|
b0f0da |
* the Free Software Foundation; either version 2 of the License, or
|
|
|
b0f0da |
* (at your option) any later version.
|
|
|
b0f0da |
- *
|
|
|
b0f0da |
+ *
|
|
|
b0f0da |
* This software is distributed in the hope that it will be useful,
|
|
|
b0f0da |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
b0f0da |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
b0f0da |
* GNU General Public License for more details.
|
|
|
b0f0da |
- *
|
|
|
b0f0da |
+ *
|
|
|
b0f0da |
* You should have received a copy of the GNU General Public License
|
|
|
b0f0da |
* along with this software; if not, write to the Free Software
|
|
|
b0f0da |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
b0f0da |
@@ -662,20 +662,16 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
|
|
|
b0f0da |
|
|
|
b0f0da |
if (dw && fullscreenSystemKeys) {
|
|
|
b0f0da |
switch (event) {
|
|
|
b0f0da |
+ // Focus might not stay with us just because we have grabbed the
|
|
|
b0f0da |
+ // keyboard. E.g. we might have sub windows, or we're not using
|
|
|
b0f0da |
+ // all monitors and the user clicked on another application.
|
|
|
b0f0da |
+ // Make sure we update our grabs with the focus changes.
|
|
|
b0f0da |
case FL_FOCUS:
|
|
|
b0f0da |
- // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
|
|
|
b0f0da |
- // some issues we need to work around:
|
|
|
b0f0da |
- // a) Fl::grab(0) on X11 will release the keyboard grab for us.
|
|
|
b0f0da |
- // b) Gaining focus on the system level causes FLTK to switch
|
|
|
b0f0da |
- // window level on OS X.
|
|
|
b0f0da |
if (dw->fullscreen_active())
|
|
|
b0f0da |
dw->grabKeyboard();
|
|
|
b0f0da |
break;
|
|
|
b0f0da |
|
|
|
b0f0da |
case FL_UNFOCUS:
|
|
|
b0f0da |
- // FIXME: We need to relinquish control when the entire window loses
|
|
|
b0f0da |
- // focus as it is very tied to this specific window on some
|
|
|
b0f0da |
- // platforms and we want to be able to open subwindows.
|
|
|
b0f0da |
dw->ungrabKeyboard();
|
|
|
b0f0da |
break;
|
|
|
b0f0da |
}
|
|
|
b0f0da |
@@ -729,6 +725,23 @@ void DesktopWindow::fullscreen_on()
|
|
|
b0f0da |
fullscreen();
|
|
|
b0f0da |
}
|
|
|
b0f0da |
|
|
|
b0f0da |
+#if !defined(WIN32) && !defined(__APPLE__)
|
|
|
b0f0da |
+Bool eventIsFocusWithSerial(Display *display, XEvent *event, XPointer arg)
|
|
|
b0f0da |
+{
|
|
|
b0f0da |
+ unsigned long serial;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ serial = *(unsigned long*)arg;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ if (event->xany.serial != serial)
|
|
|
b0f0da |
+ return False;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ if ((event->type != FocusIn) && (event->type != FocusOut))
|
|
|
b0f0da |
+ return False;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ return True;
|
|
|
b0f0da |
+}
|
|
|
b0f0da |
+#endif
|
|
|
b0f0da |
+
|
|
|
b0f0da |
void DesktopWindow::grabKeyboard()
|
|
|
b0f0da |
{
|
|
|
b0f0da |
// Grabbing the keyboard is fairly safe as FLTK reroutes events to the
|
|
|
b0f0da |
@@ -739,19 +752,24 @@ void DesktopWindow::grabKeyboard()
|
|
|
b0f0da |
|
|
|
b0f0da |
#if defined(WIN32)
|
|
|
b0f0da |
int ret;
|
|
|
b0f0da |
-
|
|
|
b0f0da |
+
|
|
|
b0f0da |
ret = win32_enable_lowlevel_keyboard(fl_xid(this));
|
|
|
b0f0da |
if (ret != 0)
|
|
|
b0f0da |
vlog.error(_("Failure grabbing keyboard"));
|
|
|
b0f0da |
#elif defined(__APPLE__)
|
|
|
b0f0da |
int ret;
|
|
|
b0f0da |
-
|
|
|
b0f0da |
+
|
|
|
b0f0da |
ret = cocoa_capture_display(this, fullScreenAllMonitors);
|
|
|
b0f0da |
if (ret != 0)
|
|
|
b0f0da |
vlog.error(_("Failure grabbing keyboard"));
|
|
|
b0f0da |
#else
|
|
|
b0f0da |
int ret;
|
|
|
b0f0da |
|
|
|
b0f0da |
+ XEvent xev;
|
|
|
b0f0da |
+ unsigned long serial;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ serial = XNextRequest(fl_display);
|
|
|
b0f0da |
+
|
|
|
b0f0da |
ret = XGrabKeyboard(fl_display, fl_xid(this), True,
|
|
|
b0f0da |
GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
|
b0f0da |
if (ret) {
|
|
|
b0f0da |
@@ -774,6 +792,16 @@ void DesktopWindow::grabKeyboard()
|
|
|
b0f0da |
None, None, CurrentTime);
|
|
|
b0f0da |
if (ret)
|
|
|
b0f0da |
vlog.error(_("Failure grabbing mouse"));
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ // Xorg 1.20+ generates FocusIn/FocusOut even when there is no actual
|
|
|
b0f0da |
+ // change of focus. This causes us to get stuck in an endless loop
|
|
|
b0f0da |
+ // grabbing and ungrabbing the keyboard. Avoid this by filtering out
|
|
|
b0f0da |
+ // any focus events generated by XGrabKeyboard().
|
|
|
b0f0da |
+ XSync(fl_display, False);
|
|
|
b0f0da |
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
|
|
|
b0f0da |
+ (XPointer)&serial) == True) {
|
|
|
b0f0da |
+ vlog.debug("Ignored synthetic focus event cause by grab change");
|
|
|
b0f0da |
+ }
|
|
|
b0f0da |
#endif
|
|
|
b0f0da |
}
|
|
|
b0f0da |
|
|
|
b0f0da |
@@ -791,8 +819,20 @@ void DesktopWindow::ungrabKeyboard()
|
|
|
b0f0da |
if (Fl::grab())
|
|
|
b0f0da |
return;
|
|
|
b0f0da |
|
|
|
b0f0da |
+ XEvent xev;
|
|
|
b0f0da |
+ unsigned long serial;
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ serial = XNextRequest(fl_display);
|
|
|
b0f0da |
+
|
|
|
b0f0da |
XUngrabPointer(fl_display, fl_event_time);
|
|
|
b0f0da |
XUngrabKeyboard(fl_display, fl_event_time);
|
|
|
b0f0da |
+
|
|
|
b0f0da |
+ // See grabKeyboard()
|
|
|
b0f0da |
+ XSync(fl_display, False);
|
|
|
b0f0da |
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
|
|
|
b0f0da |
+ (XPointer)&serial) == True) {
|
|
|
b0f0da |
+ vlog.debug("Ignored synthetic focus event cause by grab change");
|
|
|
b0f0da |
+ }
|
|
|
b0f0da |
#endif
|
|
|
b0f0da |
}
|
|
|
b0f0da |
|