mirror of
https://github.com/fltk/fltk.git
synced 2026-05-28 11:25:22 +08:00
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:
@@ -757,6 +757,17 @@ public:
|
|||||||
static int event_inside(const Fl_Widget*);
|
static int event_inside(const Fl_Widget*);
|
||||||
static int test_shortcut(Fl_Shortcut);
|
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:
|
// event destinations:
|
||||||
static int handle(int, Fl_Window*);
|
static int handle(int, Fl_Window*);
|
||||||
static int handle_(int, Fl_Window*);
|
static int handle_(int, Fl_Window*);
|
||||||
|
|||||||
+111
@@ -92,6 +92,7 @@ static void cocoaMouseHandler(NSEvent *theEvent);
|
|||||||
static int calc_mac_os_version();
|
static int calc_mac_os_version();
|
||||||
static void clipboard_check(void);
|
static void clipboard_check(void);
|
||||||
static NSString *calc_utf8_format(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 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
|
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,
|
// through_drawRect = YES means the drawRect: message was sent to the view,
|
||||||
// thus the graphics context was prepared by the system
|
// thus the graphics context was prepared by the system
|
||||||
static BOOL through_drawRect = NO;
|
static BOOL through_drawRect = NO;
|
||||||
|
static int im_enabled = -1;
|
||||||
|
|
||||||
#if CONSOLIDATE_MOTION
|
#if CONSOLIDATE_MOTION
|
||||||
static Fl_Window* send_motion;
|
static Fl_Window* send_motion;
|
||||||
@@ -124,6 +126,29 @@ extern Fl_Window* fl_xmousewin;
|
|||||||
|
|
||||||
enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
|
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 */
|
/* fltk-utf8 placekeepers */
|
||||||
void fl_reset_spot()
|
void fl_reset_spot()
|
||||||
@@ -1222,10 +1247,12 @@ static void cocoaMouseHandler(NSEvent *theEvent)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
void (*open_cb)(const char*);
|
void (*open_cb)(const char*);
|
||||||
|
TSMDocumentID currentDoc;
|
||||||
}
|
}
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
|
||||||
- (void)applicationDidBecomeActive:(NSNotification *)notify;
|
- (void)applicationDidBecomeActive:(NSNotification *)notify;
|
||||||
- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification;
|
- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification;
|
||||||
|
- (void)applicationDidUpdate:(NSNotification *)aNotification;
|
||||||
- (void)applicationWillResignActive:(NSNotification *)notify;
|
- (void)applicationWillResignActive:(NSNotification *)notify;
|
||||||
- (void)applicationWillHide:(NSNotification *)notify;
|
- (void)applicationWillHide:(NSNotification *)notify;
|
||||||
- (void)applicationWillUnhide:(NSNotification *)notify;
|
- (void)applicationWillUnhide:(NSNotification *)notify;
|
||||||
@@ -1283,6 +1310,23 @@ static void cocoaMouseHandler(NSEvent *theEvent)
|
|||||||
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
|
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
|
||||||
fl_unlock_function();
|
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
|
- (void)applicationWillResignActive:(NSNotification *)notify
|
||||||
{
|
{
|
||||||
fl_lock_function();
|
fl_lock_function();
|
||||||
@@ -1421,6 +1465,13 @@ void fl_open_display() {
|
|||||||
if ( !beenHereDoneThat ) {
|
if ( !beenHereDoneThat ) {
|
||||||
beenHereDoneThat = 1;
|
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);
|
BOOL need_new_nsapp = (NSApp == nil);
|
||||||
if (need_new_nsapp) [NSApplication sharedApplication];
|
if (need_new_nsapp) [NSApplication sharedApplication];
|
||||||
NSAutoreleasePool *localPool;
|
NSAutoreleasePool *localPool;
|
||||||
@@ -1494,6 +1545,66 @@ void fl_open_display() {
|
|||||||
void fl_close_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
|
// Gets the border sizes and the titlebar size
|
||||||
static void get_window_frame_sizes(int &bx, int &by, int &bt) {
|
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.
|
* size and link dependencies.
|
||||||
*/
|
*/
|
||||||
static HMODULE s_imm_module = 0;
|
static HMODULE s_imm_module = 0;
|
||||||
|
typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
|
||||||
|
static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
|
||||||
typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
|
typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
|
||||||
static flTypeImmGetContext flImmGetContext = 0;
|
static flTypeImmGetContext flImmGetContext = 0;
|
||||||
typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
|
typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
|
||||||
@@ -131,6 +133,7 @@ static void get_imm_module() {
|
|||||||
if (!s_imm_module)
|
if (!s_imm_module)
|
||||||
Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
|
Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
|
||||||
"Please check your input method manager library accessibility.");
|
"Please check your input method manager library accessibility.");
|
||||||
|
flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
|
||||||
flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
|
flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
|
||||||
flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
|
flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
|
||||||
flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
|
flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
|
||||||
@@ -460,6 +463,32 @@ public:
|
|||||||
};
|
};
|
||||||
static Fl_Win32_At_Exit win32_at_exit;
|
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()
|
int Fl::x()
|
||||||
@@ -1878,6 +1907,9 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
|||||||
// Register all windows for potential drag'n'drop operations
|
// Register all windows for potential drag'n'drop operations
|
||||||
RegisterDragDrop(x->xid, flIDropTarget);
|
RegisterDragDrop(x->xid, flIDropTarget);
|
||||||
|
|
||||||
|
if (!im_enabled)
|
||||||
|
flImmAssociateContextEx(x->xid, 0, 0);
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
-14
@@ -319,6 +319,7 @@ XVisualInfo *fl_visual;
|
|||||||
Colormap fl_colormap;
|
Colormap fl_colormap;
|
||||||
static XIM fl_xim_im = 0;
|
static XIM fl_xim_im = 0;
|
||||||
XIC fl_xim_ic = 0;
|
XIC fl_xim_ic = 0;
|
||||||
|
static Window fl_xim_win = 0;
|
||||||
static char fl_is_over_the_spot = 0;
|
static char fl_is_over_the_spot = 0;
|
||||||
static XRectangle status_area;
|
static XRectangle status_area;
|
||||||
|
|
||||||
@@ -614,6 +615,55 @@ static void fl_init_xim() {
|
|||||||
if(xim_styles) XFree(xim_styles);
|
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() {
|
void fl_open_display() {
|
||||||
if (fl_display) return;
|
if (fl_display) return;
|
||||||
|
|
||||||
@@ -1259,10 +1309,9 @@ int fl_handle(const XEvent& thisevent)
|
|||||||
XEvent xevent = thisevent;
|
XEvent xevent = thisevent;
|
||||||
fl_xevent = &thisevent;
|
fl_xevent = &thisevent;
|
||||||
Window xid = xevent.xany.window;
|
Window xid = xevent.xany.window;
|
||||||
static Window xim_win = 0;
|
|
||||||
|
|
||||||
if (fl_xim_ic && xevent.type == DestroyNotify &&
|
if (fl_xim_ic && xevent.type == DestroyNotify &&
|
||||||
xid != xim_win && !fl_find(xid))
|
xid != fl_xim_win && !fl_find(xid))
|
||||||
{
|
{
|
||||||
XIM xim_im;
|
XIM xim_im;
|
||||||
xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
|
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 (fl_xim_ic && (xevent.type == FocusIn))
|
||||||
{
|
fl_xim_activate(xid);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( XFilterEvent((XEvent *)&xevent, 0) )
|
if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0))
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
#if USE_XRANDR
|
#if USE_XRANDR
|
||||||
|
|||||||
Reference in New Issue
Block a user