]> source.dussan.org Git - tigervnc.git/commitdiff
Implement a more robust method to handle the keyboard grab/focus voodoo as
authorPierre Ossman <ossman@cendio.se>
Tue, 14 Jun 2011 13:36:57 +0000 (13:36 +0000)
committerPierre Ossman <ossman@cendio.se>
Tue, 14 Jun 2011 13:36:57 +0000 (13:36 +0000)
it didn't catch some cases on OS X.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4496 3789f03b-4d11-0410-bbf8-ca57d06f2519

vncviewer/DesktopWindow.cxx
vncviewer/DesktopWindow.h
vncviewer/Viewport.cxx
vncviewer/cocoa.mm

index 52725ed204bc8d854d2c9d26fb0f60c293083cfb..456e372fb20328bedee7f1f809df0cea928499ef 100644 (file)
@@ -69,6 +69,9 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
 
   OptionsDialog::addCallback(handleOptions, this);
 
+  // Hack. See below...
+  Fl::event_dispatch(&fltkHandle);
+
 #ifdef HAVE_FLTK_FULLSCREEN
   if (fullScreen)
     fullscreen();
@@ -197,9 +200,6 @@ int DesktopWindow::handle(int event)
 {
   switch (event) {
 #ifdef HAVE_FLTK_FULLSCREEN
-  case FL_FOCUS:
-    // FIXME: We reassert the keyboard grabbing on focus/unfocus as FLTK
-    //        releases the grab when someone calls Fl::grab(0)
   case FL_FULLSCREEN:
     if (event == FL_FULLSCREEN)
       fullScreen.setParam(fullscreen_active());
@@ -212,12 +212,6 @@ int DesktopWindow::handle(int event)
     else
       ungrabKeyboard();
 
-    break;
-  case FL_UNFOCUS:
-    // FIXME: We need to relinquish control when the entire window loses
-    //        focus as it seems to interfere with the WM:s ability to handle
-    //        interactions with popups' window decorations.
-    ungrabKeyboard();
     break;
 #endif
   case FL_SHORTCUT:
@@ -234,6 +228,46 @@ int DesktopWindow::handle(int event)
 }
 
 
+int DesktopWindow::fltkHandle(int event, Fl_Window *win)
+{
+  int ret;
+
+  ret = Fl::handle_(event, win);
+
+#ifdef HAVE_FLTK_FULLSCREEN
+  // This is hackish and the result of the dodgy focus handling in FLTK.
+  // The basic problem is that FLTK's view of focus and the system's tend
+  // to differ, and as a result we do not see all the FL_FOCUS events we
+  // need. Fortunately we can grab them here...
+
+  DesktopWindow *dw = dynamic_cast<DesktopWindow*>(win);
+
+  if (dw && fullscreenSystemKeys) {
+    switch (event) {
+    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;
+    }
+  }
+#endif
+
+  return ret;
+}
+
+
 void DesktopWindow::grabKeyboard()
 {
   // Grabbing the keyboard is fairly safe as FLTK reroutes events to the
index 2be07680b69af5b768dbe1a60a4866bedacdae2d..0848306653ffe94e964ec18f59c6441e22fc9cb9 100644 (file)
@@ -72,6 +72,8 @@ public:
   int handle(int event);
 
 private:
+  static int fltkHandle(int event, Fl_Window *win);
+
   void grabKeyboard();
   void ungrabKeyboard();
 
index 139eb9a450906fe513bce8ad500876440a0dd000..ae9aa106ea3bbadbdfd491103b928027349aff5c 100644 (file)
@@ -740,13 +740,6 @@ void Viewport::popupContextMenu()
   const Fl_Menu_Item *m;
   char buffer[1024];
 
-  // FIXME: Hacky workaround for the fact that menus grab and ungrab the
-  //        keyboard. Releasing focus here triggers some events on ungrab
-  //        that DesktopWindow can catch and trigger some voodoo.
-  //        See DesktopWindow::handle().
-  if (window()->contains(Fl::focus()))
-    Fl::focus(NULL);
-
   // Make sure the menu is reset to its initial state between goes or
   // it will start up highlighting the previously selected entry.
   contextMenu->value(-1);
index 589da2d93447328cb98416ee88423577cbee1c61..6300d3c0988155ef477f206b72f82f3781c91f96 100644 (file)
 
 #import <Cocoa/Cocoa.h>
 
+static bool captured = false;
+
 int cocoa_capture_display(Fl_Window *win)
 {
   NSWindow *nsw;
 
   nsw = (NSWindow*)fl_xid(win);
 
-  // Already captured?
+  if (!captured) {
+    if (CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess)
+      return 1;
+
+    captured = true;
+  }
+
   if ([nsw level] == CGShieldingWindowLevel())
     return 0;
 
-  if (CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess)
-    return 1;
-
   [nsw setLevel:CGShieldingWindowLevel()];
 
   return 0;
@@ -45,7 +50,10 @@ void cocoa_release_display(Fl_Window *win)
   NSWindow *nsw;
   int newlevel;
 
-  CGDisplayRelease(kCGDirectMainDisplay);
+  if (captured)
+    CGDisplayRelease(kCGDirectMainDisplay);
+
+  captured = false;
 
   nsw = (NSWindow*)fl_xid(win);