/** 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 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,...);
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 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();
/** @} */
}
@end
-+extern bool fl_send_xhandlers(void *e);
++extern int fl_send_system_handlers(void *e);
+
static void clipboard_check(void);
// update clipboard status
clipboard_check();
+
-+ if (fl_send_xhandlers(theEvent))
++ if (fl_send_system_handlers(theEvent))
+ return;
+
NSEventType type = [theEvent type];
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) {
+@@ -891,6 +891,83 @@ static int send_handlers(int e) {
return 0;
}
+// System event handlers:
+
+
-+struct xhandler_link {
-+ Fl_XEvent_Handler handle;
++struct system_handler_link {
++ Fl_System_Handler handle;
+ void *data;
-+ xhandler_link *next;
++ system_handler_link *next;
+};
+
+
-+static xhandler_link *xhandlers = 0;
++static system_handler_link *sys_handlers = 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.
++ \brief Install a function to intercept system events.
+
-+ \see Fl::remove_xhandler(Fl_XEvent_Handler)
++ 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_xhandler(Fl_XEvent_Handler ha, void *data) {
-+ xhandler_link *l = new xhandler_link;
++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 = xhandlers;
-+ xhandlers = l;
++ 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_xhandler(Fl_XEvent_Handler ha) {
-+ xhandler_link *l, *p;
++void Fl::remove_system_handler(Fl_System_Handler ha) {
++ system_handler_link *l, *p;
+
+ // Search for the handler in the list...
-+ for (l = xhandlers, p = 0; l && l->handle != ha; p = l, l = l->next);
++ 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 xhandlers = l->next;
++ else sys_handlers = l->next;
+
+ // And free the record...
+ delete l;
+ }
+}
+
-+bool fl_send_xhandlers(void *e) {
-+ for (const xhandler_link *hl = xhandlers; hl; hl = hl->next) {
++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 true;
++ return 1;
+ }
-+ return false;
++ return 0;
+}
+
+
return r;
}
-+extern bool fl_send_xhandlers(void *e);
++extern int fl_send_system_handlers(void *e);
+
IActiveIMMApp *fl_aimm = NULL;
MSG 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))
++ if (fl_send_system_handlers(&fl_msg))
+ continue;
+
+ // Let applications treat WM_QUIT identical to SIGTERM on *nix
remove_fd(n, -1);
}
-+extern bool fl_send_xhandlers(void *e);
++extern int fl_send_system_handlers(void *e);
+
#if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
while (XEventsQueued(fl_display,QueuedAfterReading)) {
XEvent xevent;
XNextEvent(fl_display, &xevent);
-+ if (fl_send_xhandlers(&xevent))
++ if (fl_send_system_handlers(&xevent))
+ continue;
fl_handle(xevent);
}
diff -up fltk-1.3.2/FL/Fl.H.im fltk-1.3.2/FL/Fl.H
---- fltk-1.3.2/FL/Fl.H.im 2014-07-25 14:28:52.771417210 +0200
-+++ fltk-1.3.2/FL/Fl.H 2014-07-25 14:28:52.774417261 +0200
+--- fltk-1.3.2/FL/Fl.H.im 2014-09-10 14:40:05.193265424 +0200
++++ fltk-1.3.2/FL/Fl.H 2014-09-10 14:40:05.196265471 +0200
@@ -699,6 +699,17 @@ public:
static int event_inside(const Fl_Widget*);
static int test_shortcut(Fl_Shortcut);
static int handle(int, Fl_Window*);
static int handle_(int, Fl_Window*);
diff -up fltk-1.3.2/FL/win32.H.im fltk-1.3.2/FL/win32.H
---- fltk-1.3.2/FL/win32.H.im 2014-07-25 14:28:52.765417109 +0200
-+++ fltk-1.3.2/FL/win32.H 2014-07-25 14:28:52.774417261 +0200
+--- fltk-1.3.2/FL/win32.H.im 2014-09-10 14:40:05.186265315 +0200
++++ fltk-1.3.2/FL/win32.H 2014-09-10 14:40:05.196265471 +0200
@@ -102,6 +102,8 @@ extern FL_EXPORT void fl_save_dc( HWND w
inline Window fl_xid(const Fl_Window* w) { Fl_X *temp = Fl_X::i(w); return temp ? temp->xid : 0; }
FL_EXPORT Window fl_xid_(const Fl_Window* w);
#define fl_xid(w) fl_xid_(w)
diff -up fltk-1.3.2/src/Fl_cocoa.mm.im fltk-1.3.2/src/Fl_cocoa.mm
---- fltk-1.3.2/src/Fl_cocoa.mm.im 2014-07-25 14:37:30.656153283 +0200
-+++ fltk-1.3.2/src/Fl_cocoa.mm 2014-07-25 14:38:03.540708006 +0200
-@@ -53,6 +53,7 @@ extern "C" {
- #include <math.h>
-
- #import <Cocoa/Cocoa.h>
-+#import <Carbon/Carbon.h>
-
- #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
- #if defined(__LP64__) && __LP64__
-@@ -1391,6 +1392,35 @@ void fl_close_display() {
+--- fltk-1.3.2/src/Fl_cocoa.mm.im 2014-09-10 14:40:05.193265424 +0200
++++ fltk-1.3.2/src/Fl_cocoa.mm 2014-09-10 14:43:41.103642243 +0200
+@@ -88,6 +88,7 @@ static void createAppleMenu(void);
+ static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h);
+ static void cocoaMouseHandler(NSEvent *theEvent);
+ static int calc_mac_os_version();
++static void im_update(void);
+
+ static Fl_Quartz_Graphics_Driver fl_quartz_driver;
+ static Fl_Display_Device fl_quartz_display(&fl_quartz_driver);
+@@ -108,6 +109,30 @@ int fl_mac_os_version = calc_mac_os_vers
+ static int got_events = 0;
+ static Fl_Window* resize_from_system;
+ static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates
++static int im_enabled = -1;
++
++// Carbon functions and definitions
++
++typedef void *TSMDocumentID;
++
++extern "C" enum {
++ kTSMDocumentEnabledInputSourcesPropertyTag = 'enis' // from Carbon/TextServices.h
++};
++
++// Undocumented voodoo. Taken from Mozilla.
++static const int smEnableRomanKybdsOnly = -23;
++
++typedef TSMDocumentID (*TSMGetActiveDocument_type)(void);
++static TSMGetActiveDocument_type TSMGetActiveDocument;
++typedef OSStatus (*TSMSetDocumentProperty_type)(TSMDocumentID, OSType, UInt32, void*);
++static TSMSetDocumentProperty_type TSMSetDocumentProperty;
++typedef OSStatus (*TSMRemoveDocumentProperty_type)(TSMDocumentID, OSType);
++static TSMRemoveDocumentProperty_type TSMRemoveDocumentProperty;
++typedef CFArrayRef (*TISCreateASCIICapableInputSourceList_type)(void);
++static TISCreateASCIICapableInputSourceList_type TISCreateASCIICapableInputSourceList;
++
++typedef void (*KeyScript_type)(short);
++static KeyScript_type KeyScript;
+
+ #if CONSOLIDATE_MOTION
+ static Fl_Window* send_motion;
+@@ -978,6 +1003,7 @@ void fl_open_callback(void (*cb)(const c
+ #endif
+ {
+ BOOL seen_open_file;
++ TSMDocumentID currentDoc;
+ }
+ - (void)windowDidMove:(NSNotification *)notif;
+ - (void)windowDidResize:(NSNotification *)notif;
+@@ -991,6 +1017,7 @@ void fl_open_callback(void (*cb)(const c
+ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
+ - (void)applicationDidBecomeActive:(NSNotification *)notify;
+ - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification;
++- (void)applicationDidUpdate:(NSNotification *)aNotification;
+ - (void)applicationWillResignActive:(NSNotification *)notify;
+ - (void)applicationWillHide:(NSNotification *)notify;
+ - (void)applicationWillUnhide:(NSNotification *)notify;
+@@ -1175,6 +1202,23 @@ void fl_open_callback(void (*cb)(const c
+ }
+ Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
+ }
++- (void)applicationDidUpdate:(NSNotification *)aNotification
++{
++ if ((fl_mac_os_version >= 100500) && (im_enabled != -1) &&
++ (TSMGetActiveDocument != NULL)) {
++ TSMDocumentID newDoc;
++ // It is extremely unclear when Cocoa decides to create/update
++ // the input context, but debugging reveals that it is done
++ // by NSApplication:updateWindows. So check if the input context
++ // has shifted after each such run so that we can update our
++ // input methods status.
++ newDoc = TSMGetActiveDocument();
++ if (newDoc != currentDoc) {
++ im_update();
++ currentDoc = newDoc;
++ }
++ }
++}
+ - (void)applicationWillResignActive:(NSNotification *)notify
+ {
+ fl_lock_function();
+@@ -1322,6 +1365,13 @@ void fl_open_display() {
+ static char beenHereDoneThat = 0;
+ if ( !beenHereDoneThat ) {
+ beenHereDoneThat = 1;
++
++ TSMGetActiveDocument = (TSMGetActiveDocument_type)Fl_X::get_carbon_function("TSMGetActiveDocument");
++ TSMSetDocumentProperty = (TSMSetDocumentProperty_type)Fl_X::get_carbon_function("TSMSetDocumentProperty");
++ TSMRemoveDocumentProperty = (TSMRemoveDocumentProperty_type)Fl_X::get_carbon_function("TSMRemoveDocumentProperty");
++ TISCreateASCIICapableInputSourceList = (TISCreateASCIICapableInputSourceList_type)Fl_X::get_carbon_function("TISCreateASCIICapableInputSourceList");
++
++ KeyScript = (KeyScript_type)Fl_X::get_carbon_function("KeyScript");
+
+ BOOL need_new_nsapp = (NSApp == nil);
+ if (need_new_nsapp) [NSApplication sharedApplication];
+@@ -1390,6 +1440,66 @@ void fl_open_display() {
+ void fl_close_display() {
}
-
-+// Undocumented voodoo. Taken from Mozilla.
-+#define ENABLE_ROMAN_KYBDS_ONLY -23
++// Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
++// Safari people seem to think implies turning off advanced IME stuff
++// (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
++// in Safari/Webcore). Should be good enough for us then...
++
++static void im_update(void) {
++ if (fl_mac_os_version >= 100500) {
++ TSMDocumentID doc;
++
++ if ((TSMGetActiveDocument == NULL) ||
++ (TSMSetDocumentProperty == NULL) ||
++ (TSMRemoveDocumentProperty == NULL) ||
++ (TISCreateASCIICapableInputSourceList == NULL))
++ return;
++
++ doc = TSMGetActiveDocument();
++
++ if (im_enabled)
++ TSMRemoveDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag);
++ else {
++ CFArrayRef inputSources;
++
++ inputSources = TISCreateASCIICapableInputSourceList();
++ TSMSetDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag,
++ sizeof(CFArrayRef), &inputSources);
++ CFRelease(inputSources);
++ }
++ } else {
++ if (KeyScript == NULL)
++ return;
++
++ if (im_enabled)
++ KeyScript(smKeyEnableKybds);
++ else
++ KeyScript(smEnableRomanKybdsOnly);
++ }
++}
+
+void Fl::enable_im() {
-+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
-+ TSMRemoveDocumentProperty(TSMGetActiveDocument(),
-+ kTSMDocumentEnabledInputSourcesPropertyTag);
-+#else
-+ KeyScript(smKeyEnableKybds);
-+#endif
++ fl_open_display();
++
++ im_enabled = 1;
++
++ if (fl_mac_os_version >= 100500)
++ [NSApp updateWindows];
++ else
++ im_update();
+}
+
+void Fl::disable_im() {
-+ // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
-+ // Safari people seem to think implies turning off advanced IME stuff
-+ // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
-+ // in Safari/Webcore). Should be good enough for us then...
-+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
-+ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
-+ TSMSetDocumentProperty(TSMGetActiveDocument(),
-+ kTSMDocumentEnabledInputSourcesPropertyTag,
-+ sizeof(CFArrayRef), &inputSources);
-+ CFRelease(inputSources);
-+#else
-+ KeyScript(ENABLE_ROMAN_KYBDS_ONLY);
-+#endif
-+}
++ fl_open_display();
++
++ im_enabled = 0;
+
++ if (fl_mac_os_version >= 100500)
++ [NSApp updateWindows];
++ else
++ im_update();
++}
+
+
// Gets the border sizes and the titlebar size
static void get_window_frame_sizes(int &bx, int &by, int &bt) {
- static bool first = true;
diff -up fltk-1.3.2/src/Fl.cxx.im fltk-1.3.2/src/Fl.cxx
---- fltk-1.3.2/src/Fl.cxx.im 2014-07-25 14:28:52.772417227 +0200
-+++ fltk-1.3.2/src/Fl.cxx 2014-07-25 14:28:52.774417261 +0200
+--- fltk-1.3.2/src/Fl.cxx.im 2014-09-10 14:40:05.194265440 +0200
++++ fltk-1.3.2/src/Fl.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -593,45 +593,6 @@ int Fl::run() {
return 0;
}
repeatedly to "run" your program. You can also check what happened
diff -up fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx.im fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx
--- fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx.im 2012-06-26 09:03:46.000000000 +0200
-+++ fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx 2014-07-25 14:28:52.774417261 +0200
++++ fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -34,6 +34,7 @@ LPCWSTR utf8towchar(const char *in); //M
char *wchartoutf8(LPCWSTR in); //MG
clear_pathnames();
// PARENT WINDOW
diff -up fltk-1.3.2/src/Fl_win32.cxx.im fltk-1.3.2/src/Fl_win32.cxx
---- fltk-1.3.2/src/Fl_win32.cxx.im 2014-07-25 14:28:52.772417227 +0200
-+++ fltk-1.3.2/src/Fl_win32.cxx 2014-07-25 14:28:52.775417277 +0200
+--- fltk-1.3.2/src/Fl_win32.cxx.im 2014-09-10 14:40:05.194265440 +0200
++++ fltk-1.3.2/src/Fl_win32.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -60,8 +60,6 @@
#include <ole2.h>
#include <shellapi.h>
if (himc) {
@@ -338,7 +335,6 @@ void* Fl::thread_message() {
- extern bool fl_send_xhandlers(void *e);
+ extern int fl_send_system_handlers(void *e);
-IActiveIMMApp *fl_aimm = NULL;
MSG fl_msg;
return x;
}
diff -up fltk-1.3.2/src/Fl_x.cxx.im fltk-1.3.2/src/Fl_x.cxx
---- fltk-1.3.2/src/Fl_x.cxx.im 2014-07-25 14:28:52.773417244 +0200
-+++ fltk-1.3.2/src/Fl_x.cxx 2014-07-25 14:28:52.775417277 +0200
+--- fltk-1.3.2/src/Fl_x.cxx.im 2014-09-10 14:40:05.194265440 +0200
++++ fltk-1.3.2/src/Fl_x.cxx 2014-09-10 14:40:05.198265502 +0200
@@ -313,6 +313,7 @@ XVisualInfo *fl_visual;
Colormap fl_colormap;
XIM fl_xim_im = 0;
#ifdef HAVE_FLTK_XHANDLERS
// We need to intercept keyboard events early
- Fl::add_xhandler(handleXEvent, this);
+ Fl::add_system_handler(handleSystemEvent, this);
#endif
frameBuffer = createFramebuffer(w, h);
Fl::remove_timeout(handlePointerTimeout, this);
#ifdef HAVE_FLTK_XHANDLERS
- Fl::remove_xhandler(handleXEvent);
+ Fl::remove_system_handler(handleSystemEvent);
#endif
#ifdef HAVE_FLTK_CLIPBOARD
}
-bool Viewport::handleXEvent(void *event, void *data)
+int Viewport::handleSystemEvent(void *event, void *data)
{
Viewport *self = (Viewport *)data;
Fl_Widget *focus;
if (!focus)
focus = Fl::focus();
if (!focus)
- return false;
+ return 0;
if (focus != self)
- return false;
+ return 0;
assert(event);
if (keyCode == 0x00) {
vlog.error(_("No scan code for %svirtual key 0x%02x"),
isExtended?"extended ":"", (int)vKey);
- return true;
+ return 1;
}
}
if (keySym == NoSymbol) {
vlog.error(_("No symbol for %svirtual key 0x%02x"),
isExtended?"extended ":"", (int)vKey);
- return true;
+ return 1;
}
self->handleKeyPress(keyCode, keySym);
- return true;
+ return 1;
} else if ((msg->message == WM_KEYUP) || (msg->message == WM_SYSKEYUP)) {
UINT vKey;
bool isExtended;
self->handleKeyRelease(keyCode);
- return true;
+ return 1;
}
#elif defined(__APPLE__)
if (cocoa_is_keyboard_event(event)) {
if (keySym == NoSymbol) {
vlog.error(_("No symbol for key code 0x%02x (in the current state)"),
(int)keyCode);
- return true;
+ return 1;
}
self->handleKeyPress(keyCode, keySym);
self->handleKeyRelease(keyCode);
}
- return true;
+ return 1;
}
#else
XEvent *xevent = (XEvent*)event;
if (keysym == NoSymbol) {
vlog.error(_("No symbol for key code %d (in the current state)"),
(int)xevent->xkey.keycode);
- return true;
+ return 1;
}
switch (keysym) {
}
self->handleKeyPress(xevent->xkey.keycode, keysym);
- return true;
+ return 1;
} else if (xevent->type == KeyRelease) {
self->handleKeyRelease(xevent->xkey.keycode);
- return true;
+ return 1;
}
#endif
- return false;
+ return 0;
}