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_system_handler functions passed as parameters */ +typedef int (*Fl_System_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_system_handler(Fl_System_Handler h, void *data); + static void remove_system_handler(Fl_System_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 int fl_send_system_handlers(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_system_handlers(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,83 @@ static int send_handlers(int e) { return 0; } + +//////////////////////////////////////////////////////////////// +// System event handlers: + + +struct system_handler_link { + Fl_System_Handler handle; + void *data; + system_handler_link *next; +}; + + +static system_handler_link *sys_handlers = 0; + + +/** + \brief 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 + non-zero. If all functions return zero then the event is passed on + for normal handling by FLTK. + + Each function will be called with a pointer to the system event as + the first argument and \p data as the second argument. The system + event pointer will always be void *, but will point to different + objects depending on the platform: + - X11: XEvent + - Windows: MSG + - OS X: NSEvent + + \param ha The event handler function to register + \param data User data to include on each call + + \see Fl::remove_system_handler(Fl_System_Handler) +*/ +void Fl::add_system_handler(Fl_System_Handler ha, void *data) { + system_handler_link *l = new system_handler_link; + l->handle = ha; + l->data = data; + l->next = sys_handlers; + sys_handlers = l; +} + + +/** + Removes a previously added system event handler. + + \param ha The event handler function to remove + + \see Fl::add_system_handler(Fl_System_Handler) +*/ +void Fl::remove_system_handler(Fl_System_Handler ha) { + system_handler_link *l, *p; + + // Search for the handler in the list... + for (l = sys_handlers, 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 sys_handlers = l->next; + + // And free the record... + delete l; + } +} + +int fl_send_system_handlers(void *e) { + for (const system_handler_link *hl = sys_handlers; hl; hl = hl->next) { + if (hl->handle(e, hl->data)) + return 1; + } + return 0; +} + + //////////////////////////////////////////////////////////////// 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 int fl_send_system_handlers(void *e); + IActiveIMMApp *fl_aimm = NULL; MSG fl_msg; @@ -401,23 +403,21 @@ 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) { - 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_system_handlers(&fl_msg)) + continue; + + 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 int fl_send_system_handlers(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_system_handlers(&xevent)) + continue; fl_handle(xevent); } // we send FL_LEAVE only if the mouse did not enter some other window: