]> source.dussan.org Git - tigervnc.git/commitdiff
Add xhandler hook
authorPierre Ossman <ossman@cendio.se>
Fri, 22 Aug 2014 13:10:22 +0000 (15:10 +0200)
committerPierre Ossman <ossman@cendio.se>
Fri, 22 Aug 2014 13:10:22 +0000 (15:10 +0200)
Boiler plate code to intercept system events from FLTK so that
we can generate proper keyboard messages.

CMakeLists.txt
config.h.in
contrib/fltk/12-fltk-1.3.2-xhandlers.patch [new file with mode: 0644]
vncviewer/Viewport.cxx
vncviewer/Viewport.h

index 30520a51d88aa72d025d25205f5db6920e459a1a..f5a016ace3e22c8c617994d802e35667b9669601 100644 (file)
@@ -300,6 +300,9 @@ if(FLTK_FOUND)
   # FLTK STR #2860
   check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { void (Fl_Window::*foo)(int,int,int,int) = &Fl_Window::fullscreen_screens; return 0; }" HAVE_FLTK_FULLSCREEN_SCREENS)
 
+  # FLTK STR #xxxx
+  check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_xhandler(NULL, NULL); return 0; }" HAVE_FLTK_XHANDLERS)
+
   set(CMAKE_REQUIRED_INCLUDES)
   set(CMAKE_REQUIRED_LIBRARIES)
 endif()
index a88c31c591fda383b27a941372b57569937631a6..bac626b7f60c61735d94ecc3976ef9f8e70be881 100644 (file)
@@ -17,6 +17,7 @@
 #cmakedefine HAVE_FLTK_CURSOR
 #cmakedefine HAVE_FLTK_WORK_AREA
 #cmakedefine HAVE_FLTK_ICONS
+#cmakedefine HAVE_FLTK_XHANDLERS
 #cmakedefine HAVE_ACTIVE_DESKTOP_H
 #cmakedefine HAVE_ACTIVE_DESKTOP_L
 #cmakedefine ENABLE_NLS 1
diff --git a/contrib/fltk/12-fltk-1.3.2-xhandlers.patch b/contrib/fltk/12-fltk-1.3.2-xhandlers.patch
new file mode 100644 (file)
index 0000000..cf6cefb
--- /dev/null
@@ -0,0 +1,194 @@
+diff -up fltk-1.3.2/FL/Fl.H.xhandlers fltk-1.3.2/FL/Fl.H
+--- fltk-1.3.2/FL/Fl.H.xhandlers       2014-07-22 15:23:18.087334467 +0200
++++ fltk-1.3.2/FL/Fl.H 2014-07-22 15:23:18.094334589 +0200
+@@ -96,6 +96,9 @@ typedef void (*Fl_FD_Handler)(FL_SOCKET
+ /** Signature of add_handler functions passed as parameters */
+ typedef int (*Fl_Event_Handler)(int event);
++/** Signature of add_xhandler functions passed as parameters */
++typedef bool (*Fl_XEvent_Handler)(void *event, void *data);
++
+ /** Signature of set_abort functions passed as parameters */
+ typedef void (*Fl_Abort_Handler)(const char *format,...);
+@@ -712,6 +715,8 @@ public:
+   static void focus(Fl_Widget*);
+   static void add_handler(Fl_Event_Handler h);
+   static void remove_handler(Fl_Event_Handler h);
++  static void add_xhandler(Fl_XEvent_Handler h, void *data);
++  static void remove_xhandler(Fl_XEvent_Handler h);
+   static void event_dispatch(Fl_Event_Dispatch d);
+   static Fl_Event_Dispatch event_dispatch();
+   /** @} */
+diff -up fltk-1.3.2/src/Fl_cocoa.mm.xhandlers fltk-1.3.2/src/Fl_cocoa.mm
+--- fltk-1.3.2/src/Fl_cocoa.mm.xhandlers       2014-07-22 15:23:18.089334502 +0200
++++ fltk-1.3.2/src/Fl_cocoa.mm 2014-07-22 15:23:18.095334607 +0200
+@@ -1269,6 +1269,8 @@ void fl_open_callback(void (*cb)(const c
+ }
+ @end
++extern bool fl_send_xhandlers(void *e);
++
+ static void clipboard_check(void);
+ @implementation FLApplication
+@@ -1276,6 +1278,10 @@ static void clipboard_check(void);
+ {
+   // update clipboard status
+   clipboard_check();
++
++  if (fl_send_xhandlers(theEvent))
++    return;
++
+   NSEventType type = [theEvent type];  
+   if (type == NSLeftMouseDown) {
+     fl_lock_function();
+diff -up fltk-1.3.2/src/Fl.cxx.xhandlers fltk-1.3.2/src/Fl.cxx
+--- fltk-1.3.2/src/Fl.cxx.xhandlers    2014-07-22 15:23:18.085334432 +0200
++++ fltk-1.3.2/src/Fl.cxx      2014-07-22 15:23:18.095334607 +0200
+@@ -891,6 +891,67 @@ static int send_handlers(int e) {
+   return 0;
+ }
++
++////////////////////////////////////////////////////////////////
++// System event handlers:
++
++
++struct xhandler_link {
++  Fl_XEvent_Handler handle;
++  void *data;
++  xhandler_link *next;
++};
++
++
++static xhandler_link *xhandlers = 0;
++
++
++/**
++  Install a function to intercept system events. FLTK calls each of
++  these functions as soon as a new system event is received. The
++  processing will stop at the first function to return true. If all
++  functions return false then the event is passed on for normal
++  handling by FLTK.
++
++ \see Fl::remove_xhandler(Fl_XEvent_Handler)
++*/
++void Fl::add_xhandler(Fl_XEvent_Handler ha, void *data) {
++  xhandler_link *l = new xhandler_link;
++  l->handle = ha;
++  l->data = data;
++  l->next = xhandlers;
++  xhandlers = l;
++}
++
++
++/**
++ Removes a previously added system event handler.
++*/
++void Fl::remove_xhandler(Fl_XEvent_Handler ha) {
++  xhandler_link *l, *p;
++
++  // Search for the handler in the list...
++  for (l = xhandlers, p = 0; l && l->handle != ha; p = l, l = l->next);
++
++  if (l) {
++    // Found it, so remove it from the list...
++    if (p) p->next = l->next;
++    else xhandlers = l->next;
++
++    // And free the record...
++    delete l;
++  }
++}
++
++bool fl_send_xhandlers(void *e) {
++  for (const xhandler_link *hl = xhandlers; hl; hl = hl->next) {
++    if (hl->handle(e, hl->data))
++      return true;
++  }
++  return false;
++}
++
++
+ ////////////////////////////////////////////////////////////////
+ Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
+diff -up fltk-1.3.2/src/Fl_win32.cxx.xhandlers fltk-1.3.2/src/Fl_win32.cxx
+--- fltk-1.3.2/src/Fl_win32.cxx.xhandlers      2014-07-22 15:23:18.092334554 +0200
++++ fltk-1.3.2/src/Fl_win32.cxx        2014-07-22 15:24:44.682843610 +0200
+@@ -336,6 +336,8 @@ void* Fl::thread_message() {
+   return r;
+ }
++extern bool fl_send_xhandlers(void *e);
++
+ IActiveIMMApp *fl_aimm = NULL;
+ MSG fl_msg;
+@@ -401,26 +403,25 @@ int fl_wait(double time_to_wait) {
+   // Execute the message we got, and all other pending messages:
+   // have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+-  have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
+-  if (have_message > 0) {
+-    while (have_message != 0 && have_message != -1) {
+-      // Let applications treat WM_QUIT identical to SIGTERM on *nix
+-      if (fl_msg.message == WM_QUIT)
+-        raise(SIGTERM);
+-      if (fl_msg.message == fl_wake_msg) {
+-        // Used for awaking wait() from another thread
+-      thread_message_ = (void*)fl_msg.wParam;
+-        Fl_Awake_Handler func;
+-        void *data;
+-        while (Fl::get_awake_handler_(func, data)==0) {
+-          func(data);
+-        }
+-      }
+-
+-      TranslateMessage(&fl_msg);
+-      DispatchMessageW(&fl_msg);
+-      have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
++  while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) {
++    if (fl_send_xhandlers(&fl_msg))
++      continue;
++
++    // Let applications treat WM_QUIT identical to SIGTERM on *nix
++    if (fl_msg.message == WM_QUIT)
++      raise(SIGTERM);
++
++    if (fl_msg.message == fl_wake_msg) {
++      // Used for awaking wait() from another thread
++      thread_message_ = (void*)fl_msg.wParam;
++      Fl_Awake_Handler func;
++      void *data;
++      while (Fl::get_awake_handler_(func, data)==0)
++        func(data);
+     }
++
++    TranslateMessage(&fl_msg);
++    DispatchMessageW(&fl_msg);
+   }
+   Fl::flush();
+diff -up fltk-1.3.2/src/Fl_x.cxx.xhandlers fltk-1.3.2/src/Fl_x.cxx
+--- fltk-1.3.2/src/Fl_x.cxx.xhandlers  2014-07-22 15:23:18.093334572 +0200
++++ fltk-1.3.2/src/Fl_x.cxx    2014-07-22 15:23:18.096334624 +0200
+@@ -188,6 +188,8 @@ void Fl::remove_fd(int n) {
+   remove_fd(n, -1);
+ }
++extern bool fl_send_xhandlers(void *e);
++
+ #if CONSOLIDATE_MOTION
+ static Fl_Window* send_motion;
+ extern Fl_Window* fl_xmousewin;
+@@ -198,6 +200,8 @@ static void do_queued_events() {
+   while (XEventsQueued(fl_display,QueuedAfterReading)) {
+     XEvent xevent;
+     XNextEvent(fl_display, &xevent);
++    if (fl_send_xhandlers(&xevent))
++      continue;
+     fl_handle(xevent);
+   }
+   // we send FL_LEAVE only if the mouse did not enter some other window:
index 16b34e6cb14181b034db2fe8f4ecd21afe6b659b..2b22a9738779f5adfc013d67c14906301c748368 100644 (file)
@@ -100,6 +100,11 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
   Fl::add_clipboard_notify(handleClipboardChange, this);
 #endif
 
+#ifdef HAVE_FLTK_XHANDLERS
+  // We need to intercept keyboard events early
+  Fl::add_xhandler(handleXEvent, this);
+#endif
+
   frameBuffer = createFramebuffer(w, h);
   assert(frameBuffer);
 
@@ -132,6 +137,10 @@ Viewport::~Viewport()
   // again later when this object is already gone.
   Fl::remove_timeout(handlePointerTimeout, this);
 
+#ifdef HAVE_FLTK_XHANDLERS
+  Fl::remove_xhandler(handleXEvent);
+#endif
+
 #ifdef HAVE_FLTK_CLIPBOARD
   Fl::remove_clipboard_notify(handleClipboardChange);
 #endif
@@ -620,6 +629,28 @@ void Viewport::handleKeyRelease(int keyCode)
 }
 
 
+bool Viewport::handleXEvent(void *event, void *data)
+{
+  Viewport *self = (Viewport *)data;
+  Fl_Widget *focus;
+
+  assert(self);
+
+  focus = Fl::grab();
+  if (!focus)
+    focus = Fl::focus();
+  if (!focus)
+    return false;
+
+  if (focus != self)
+    return false;
+
+  assert(event);
+
+  return false;
+}
+
+
 rdr::U32 Viewport::translateKeyEvent(void)
 {
   unsigned ucs;
index d9eea353ba5548dda7c26c85b543d4accd0ec54a..30dacad4532d4b8cfb6ef0891c48a54f4c608e55 100644 (file)
@@ -73,6 +73,8 @@ private:
   void handleKeyPress(int keyCode, rdr::U32 keySym);
   void handleKeyRelease(int keyCode);
 
+  static bool handleXEvent(void *event, void *data);
+
   rdr::U32 translateKeyEvent(void);
   void handleFLTKKeyPress(void);