summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl_cocoa.mm111
-rw-r--r--src/Fl_win32.cxx32
-rw-r--r--src/Fl_x.cxx67
3 files changed, 196 insertions, 14 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 9756c35dc..6b8e20ed6 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -92,6 +92,7 @@ static void cocoaMouseHandler(NSEvent *theEvent);
static int calc_mac_os_version();
static void clipboard_check(void);
static NSString *calc_utf8_format(void);
+static void im_update(void);
static unsigned make_current_counts = 0; // if > 0, then Fl_Window::make_current() can be called only once
static Fl_X *fl_x_to_redraw = NULL; // set by Fl_X::flush() to the Fl_X object of the window to be redrawn
@@ -116,6 +117,7 @@ static int main_screen_height; // height of menubar-containing screen used to co
// through_drawRect = YES means the drawRect: message was sent to the view,
// thus the graphics context was prepared by the system
static BOOL through_drawRect = NO;
+static int im_enabled = -1;
#if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
@@ -124,6 +126,29 @@ extern Fl_Window* fl_xmousewin;
enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
+// 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;
+
/* fltk-utf8 placekeepers */
void fl_reset_spot()
@@ -1222,10 +1247,12 @@ static void cocoaMouseHandler(NSEvent *theEvent)
#endif
{
void (*open_cb)(const char*);
+ TSMDocumentID currentDoc;
}
- (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;
@@ -1283,6 +1310,23 @@ static void cocoaMouseHandler(NSEvent *theEvent)
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
fl_unlock_function();
}
+- (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();
@@ -1420,6 +1464,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];
@@ -1494,6 +1545,66 @@ void fl_open_display() {
void fl_close_display() {
}
+// 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() {
+ fl_open_display();
+
+ im_enabled = 1;
+
+ if (fl_mac_os_version >= 100500)
+ [NSApp updateWindows];
+ else
+ im_update();
+}
+
+void Fl::disable_im() {
+ 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) {
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 776bce1c0..ff6da442d 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -119,6 +119,8 @@ static HMODULE get_wsock_mod() {
* size and link dependencies.
*/
static HMODULE s_imm_module = 0;
+typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
+static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
static flTypeImmGetContext flImmGetContext = 0;
typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
@@ -131,6 +133,7 @@ static void get_imm_module() {
if (!s_imm_module)
Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
"Please check your input method manager library accessibility.");
+ flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
@@ -460,6 +463,32 @@ public:
};
static Fl_Win32_At_Exit win32_at_exit;
+static char im_enabled = 1;
+
+void Fl::enable_im() {
+ fl_open_display();
+
+ Fl_X* i = Fl_X::first;
+ while (i) {
+ flImmAssociateContextEx(i->xid, 0, IACE_DEFAULT);
+ i = i->next;
+ }
+
+ im_enabled = 1;
+}
+
+void Fl::disable_im() {
+ fl_open_display();
+
+ Fl_X* i = Fl_X::first;
+ while (i) {
+ flImmAssociateContextEx(i->xid, 0, 0);
+ i = i->next;
+ }
+
+ im_enabled = 0;
+}
+
////////////////////////////////////////////////////////////////
int Fl::x()
@@ -1878,6 +1907,9 @@ Fl_X* Fl_X::make(Fl_Window* w) {
// Register all windows for potential drag'n'drop operations
RegisterDragDrop(x->xid, flIDropTarget);
+ if (!im_enabled)
+ flImmAssociateContextEx(x->xid, 0, 0);
+
return x;
}
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 20041dfec..982369758 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -319,6 +319,7 @@ XVisualInfo *fl_visual;
Colormap fl_colormap;
static XIM fl_xim_im = 0;
XIC fl_xim_ic = 0;
+static Window fl_xim_win = 0;
static char fl_is_over_the_spot = 0;
static XRectangle status_area;
@@ -614,6 +615,55 @@ static void fl_init_xim() {
if(xim_styles) XFree(xim_styles);
}
+void fl_xim_deactivate(void);
+
+void fl_xim_activate(Window xid) {
+ if (!fl_xim_im)
+ return;
+
+ // If the focused window has changed, then use the brute force method
+ // of completely recreating the input context.
+ if (fl_xim_win != xid) {
+ fl_xim_deactivate();
+
+ fl_new_ic();
+ fl_xim_win = xid;
+
+ XSetICValues(fl_xim_ic,
+ XNFocusWindow, fl_xim_win,
+ XNClientWindow, fl_xim_win,
+ NULL);
+ }
+
+ fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
+}
+
+void fl_xim_deactivate(void) {
+ if (!fl_xim_ic)
+ return;
+
+ XDestroyIC(fl_xim_ic);
+ fl_xim_ic = NULL;
+
+ fl_xim_win = 0;
+}
+
+void Fl::enable_im() {
+ Fl_Window *win;
+
+ win = Fl::first_window();
+ if (win && win->shown()) {
+ fl_xim_activate(fl_xid(win));
+ XSetICFocus(fl_xim_ic);
+ } else {
+ fl_new_ic();
+ }
+}
+
+void Fl::disable_im() {
+ fl_xim_deactivate();
+}
+
void fl_open_display() {
if (fl_display) return;
@@ -1259,10 +1309,9 @@ int fl_handle(const XEvent& thisevent)
XEvent xevent = thisevent;
fl_xevent = &thisevent;
Window xid = xevent.xany.window;
- static Window xim_win = 0;
if (fl_xim_ic && xevent.type == DestroyNotify &&
- xid != xim_win && !fl_find(xid))
+ xid != fl_xim_win && !fl_find(xid))
{
XIM xim_im;
xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
@@ -1278,19 +1327,9 @@ int fl_handle(const XEvent& thisevent)
}
if (fl_xim_ic && (xevent.type == FocusIn))
- {
- if (xim_win != xid) {
- xim_win = xid;
- XDestroyIC(fl_xim_ic);
- fl_xim_ic = NULL;
- fl_new_ic();
- XSetICValues(fl_xim_ic, XNFocusWindow, xevent.xclient.window,
- XNClientWindow, xid, NULL);
- }
- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
- }
+ fl_xim_activate(xid);
- if ( XFilterEvent((XEvent *)&xevent, 0) )
+ if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0))
return(1);
#if USE_XRANDR