|
|
@@ -684,23 +684,18 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) |
|
|
|
|
|
|
|
if (dw) { |
|
|
|
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: |
|
|
|
if (fullscreenSystemKeys) { |
|
|
|
// 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: |
|
|
|
if (fullscreenSystemKeys) { |
|
|
|
// 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; |
|
|
@@ -766,6 +761,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 |
|
|
@@ -793,6 +805,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) { |
|
|
@@ -806,6 +823,16 @@ void DesktopWindow::grabKeyboard() |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 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 |
|
|
|
|
|
|
|
keyboardGrabbed = true; |
|
|
@@ -832,7 +859,19 @@ void DesktopWindow::ungrabKeyboard() |
|
|
|
if (Fl::grab()) |
|
|
|
return; |
|
|
|
|
|
|
|
XEvent xev; |
|
|
|
unsigned long serial; |
|
|
|
|
|
|
|
serial = XNextRequest(fl_display); |
|
|
|
|
|
|
|
XUngrabKeyboard(fl_display, CurrentTime); |
|
|
|
|
|
|
|
// 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 |
|
|
|
} |
|
|
|
|