Add methods to enable and disable the system's input methods.
This needs to be done from FLTK as it affects the window interaction, which FLTK is largely responsible for. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10314 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
5101a8ea1c
commit
1c7409e0a1
11
FL/Fl.H
11
FL/Fl.H
@ -757,6 +757,17 @@ public:
|
||||
static int event_inside(const Fl_Widget*);
|
||||
static int test_shortcut(Fl_Shortcut);
|
||||
|
||||
/**
|
||||
Enables the system input methods facilities. This is the default.
|
||||
\see disable_im()
|
||||
*/
|
||||
static void enable_im();
|
||||
/**
|
||||
Disables the system input methods facilities.
|
||||
\see enable_im()
|
||||
*/
|
||||
static void disable_im();
|
||||
|
||||
// event destinations:
|
||||
static int handle(int, Fl_Window*);
|
||||
static int handle_(int, Fl_Window*);
|
||||
|
||||
111
src/Fl_cocoa.mm
111
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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
67
src/Fl_x.cxx
67
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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user