--- /dev/null
+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: