summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2014-08-22 15:10:22 +0200
committerPierre Ossman <ossman@cendio.se>2014-08-22 15:10:22 +0200
commit4f3ac69a11b98aa7eea88a6336140bced4c66eae (patch)
tree195546fd1a02c65b86bf03c2d0b25e51552a767a
parent796580af8791db18cf95f32784c0270085f0b361 (diff)
downloadtigervnc-4f3ac69a11b98aa7eea88a6336140bced4c66eae.tar.gz
tigervnc-4f3ac69a11b98aa7eea88a6336140bced4c66eae.zip
Add xhandler hook
Boiler plate code to intercept system events from FLTK so that we can generate proper keyboard messages.
-rw-r--r--CMakeLists.txt3
-rw-r--r--config.h.in1
-rw-r--r--contrib/fltk/12-fltk-1.3.2-xhandlers.patch194
-rw-r--r--vncviewer/Viewport.cxx31
-rw-r--r--vncviewer/Viewport.h2
5 files changed, 231 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30520a51..f5a016ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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()
diff --git a/config.h.in b/config.h.in
index a88c31c5..bac626b7 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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
index 00000000..cf6cefbf
--- /dev/null
+++ b/contrib/fltk/12-fltk-1.3.2-xhandlers.patch
@@ -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:
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 16b34e6c..2b22a973 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -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;
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index d9eea353..30dacad4 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -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);