Kusanagi Kouichi : winex11.drv: Keep the state of XIM and IME consistent.
Alexandre Julliard
julliard at winehq.org
Mon Feb 22 08:46:48 CST 2010
Module: wine
Branch: master
Commit: f7b18148d4787adbd9b0993da366e09c1230e53b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f7b18148d4787adbd9b0993da366e09c1230e53b
Author: Kusanagi Kouichi <slash at ac.auone-net.jp>
Date: Thu Feb 18 23:06:31 2010 +0900
winex11.drv: Keep the state of XIM and IME consistent.
---
dlls/winex11.drv/ime.c | 67 ++++++++++++++++++++++------------------
dlls/winex11.drv/x11drv.h | 3 +-
dlls/winex11.drv/xim.c | 75 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 111 insertions(+), 34 deletions(-)
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c
index 0f99ad6..4e821ad 100644
--- a/dlls/winex11.drv/ime.c
+++ b/dlls/winex11.drv/ime.c
@@ -717,30 +717,36 @@ BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
}
break;
case IMC_SETOPENSTATUS:
- {
- LPIMEPRIVATE myPrivate;
TRACE("IMC_SETOPENSTATUS\n");
- myPrivate = ImmLockIMCC(lpIMC->hPrivate);
- if (lpIMC->fOpen != myPrivate->bInternalState &&
- myPrivate->bInComposition)
+ /* Indirectly called from XIM callbacks */
+ if (ImmGetIMCCLockCount(lpIMC->hPrivate) > 0)
{
- if(lpIMC->fOpen == FALSE)
- {
- X11DRV_ForceXIMReset(lpIMC->hWnd);
- GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION,0,0);
- myPrivate->bInComposition = FALSE;
- }
- else
+ bRet = TRUE;
+ break;
+ }
+
+ bRet = X11DRV_SetPreeditState(lpIMC->hWnd, lpIMC->fOpen);
+ if (bRet)
+ {
+ if (!lpIMC->fOpen)
{
- GenerateIMEMessage(hIMC,WM_IME_STARTCOMPOSITION,0,0);
- GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, 0, 0);
+ LPIMEPRIVATE myPrivate;
+
+ myPrivate = ImmLockIMCC(lpIMC->hPrivate);
+ if (myPrivate->bInComposition)
+ {
+ X11DRV_ForceXIMReset(lpIMC->hWnd);
+ GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
+ myPrivate->bInComposition = FALSE;
+ }
+ ImmUnlockIMCC(lpIMC->hPrivate);
}
}
- myPrivate->bInternalState = lpIMC->fOpen;
- bRet = TRUE;
- }
- break;
+ else
+ lpIMC->fOpen = !lpIMC->fOpen;
+
+ break;
default: FIXME("Unknown\n"); break;
}
break;
@@ -951,35 +957,36 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
/* Interfaces to XIM and other parts of winex11drv */
-void IME_SetOpenStatus(BOOL fOpen)
+void IME_SetOpenStatus(BOOL fOpen, BOOL force)
{
+ HIMC imc;
LPINPUTCONTEXT lpIMC;
LPIMEPRIVATE myPrivate;
- lpIMC = LockRealIMC(FROM_X11);
+ imc = RealIMC(FROM_X11);
+ lpIMC = ImmLockIMC(imc);
if (lpIMC == NULL)
return;
myPrivate = ImmLockIMCC(lpIMC->hPrivate);
- if (myPrivate->bInternalState && fOpen == FALSE)
+ if (!fOpen && myPrivate->bInComposition)
{
ShowWindow(myPrivate->hwndDefault, SW_HIDE);
ImmDestroyIMCC(lpIMC->hCompStr);
lpIMC->hCompStr = ImeCreateBlankCompStr();
+ myPrivate->bInComposition = FALSE;
+ GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
}
- ImmUnlockIMCC(lpIMC->hPrivate);
- UnlockRealIMC(FROM_X11);
+ if (lpIMC->fOpen && fOpen)
+ ImmSetOpenStatus(imc, FALSE);
- if (myPrivate->bInComposition && fOpen == FALSE)
- {
- GenerateIMEMessage(FROM_X11, WM_IME_ENDCOMPOSITION, 0, 0);
- myPrivate->bInComposition = FALSE;
- }
+ if (fOpen || force)
+ ImmSetOpenStatus(imc, fOpen);
- if (!myPrivate->bInternalState && fOpen == TRUE)
- ImmSetOpenStatus(RealIMC(FROM_X11), fOpen);
+ ImmUnlockIMCC(lpIMC->hPrivate);
+ ImmUnlockIMC(imc);
}
INT IME_GetCursorPos(void)
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 1173d31..6db410a 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -300,7 +300,7 @@ extern BOOL destroy_glxpixmap(Display *display, XID glxpixmap);
/* IME support */
extern void IME_UnregisterClasses(void);
-extern void IME_SetOpenStatus(BOOL fOpen);
+extern void IME_SetOpenStatus(BOOL fOpen, BOOL force);
extern INT IME_GetCursorPos(void);
extern void IME_SetCursorPos(DWORD pos);
extern void IME_UpdateAssociation(HWND focus);
@@ -809,6 +809,7 @@ extern XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data) DECLSPEC_HIDDE
extern void X11DRV_SetupXIM(void) DECLSPEC_HIDDEN;
extern void X11DRV_XIMLookupChars( const char *str, DWORD count ) DECLSPEC_HIDDEN;
extern void X11DRV_ForceXIMReset(HWND hwnd) DECLSPEC_HIDDEN;
+extern BOOL X11DRV_SetPreeditState(HWND hwnd, BOOL fOpen);
/* FIXME: private functions imported from user32 */
extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode );
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c
index 0e32513..ee2bd15 100644
--- a/dlls/winex11.drv/xim.c
+++ b/dlls/winex11.drv/xim.c
@@ -120,10 +120,30 @@ void X11DRV_XIMLookupChars( const char *str, DWORD count )
HeapFree(GetProcessHeap(), 0, wcOutput);
}
+static BOOL XIMPreEditStateNotifyCallback(XIC xic, XPointer p, XPointer data)
+{
+ const struct x11drv_win_data * const win_data = (struct x11drv_win_data *)p;
+ const XIMPreeditState state = ((XIMPreeditStateNotifyCallbackStruct *)data)->state;
+
+ TRACE("xic = %p, win = %lx, state = %lu\n", xic, win_data->whole_window, state);
+ switch (state)
+ {
+ case XIMPreeditEnable:
+ IME_SetOpenStatus(TRUE, TRUE);
+ break;
+ case XIMPreeditDisable:
+ IME_SetOpenStatus(FALSE, TRUE);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
{
TRACE("PreEditStartCallback %p\n",ic);
- IME_SetOpenStatus(TRUE);
+ IME_SetOpenStatus(TRUE, FALSE);
ximInComposeMode = TRUE;
return -1;
}
@@ -137,7 +157,7 @@ static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_d
dwCompStringSize = 0;
dwCompStringLength = 0;
CompositionString = NULL;
- IME_SetOpenStatus(FALSE);
+ IME_SetOpenStatus(FALSE, FALSE);
}
static void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
@@ -244,6 +264,51 @@ void X11DRV_ForceXIMReset(HWND hwnd)
}
}
+BOOL X11DRV_SetPreeditState(HWND hwnd, BOOL fOpen)
+{
+ XIC ic;
+ XIMPreeditState state;
+ XVaNestedList attr_set, attr_get;
+ BOOL ret;
+
+ ic = X11DRV_get_ic(hwnd);
+ if (!ic)
+ return FALSE;
+
+ if (fOpen)
+ state = XIMPreeditEnable;
+ else
+ state = XIMPreeditDisable;
+
+ ret = FALSE;
+ wine_tsx11_lock();
+
+ attr_set = XVaCreateNestedList(0, XNPreeditState, state, NULL);
+ if (attr_set == NULL)
+ goto error1;
+
+ attr_get = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
+ if (attr_get == NULL)
+ goto error2;
+
+ if (XSetICValues(ic, XNPreeditAttributes, attr_set, NULL) != NULL)
+ goto error3;
+
+ /* SCIM claims it supports XNPreeditState, but seems to ignore */
+ state = XIMPreeditUnKnown;
+ ret = XGetICValues(ic, XNPreeditAttributes, attr_get, NULL) == NULL &&
+ ((fOpen && state == XIMPreeditEnable) ||
+ (!fOpen && state == XIMPreeditDisable));
+error3:
+ XFree(attr_get);
+error2:
+ XFree(attr_set);
+error1:
+ wine_tsx11_unlock();
+ return ret;
+}
+
+
/***********************************************************************
* X11DRV_InitXIM
*
@@ -446,7 +511,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
XVaNestedList status = NULL;
XIC xic;
XICCallback destroy = {(XPointer)data, (XICProc)X11DRV_DestroyIC};
- XICCallback P_StartCB, P_DoneCB, P_DrawCB, P_CaretCB;
+ XICCallback P_StateNotifyCB, P_StartCB, P_DoneCB, P_DrawCB, P_CaretCB;
LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
Window win = data->whole_window;
XFontSet fontSet = x11drv_thread_data()->font_set;
@@ -472,10 +537,12 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
}
/* create callbacks */
+ P_StateNotifyCB.client_data = (XPointer)data;
P_StartCB.client_data = NULL;
P_DoneCB.client_data = NULL;
P_DrawCB.client_data = NULL;
P_CaretCB.client_data = NULL;
+ P_StateNotifyCB.callback = (XICProc)XIMPreEditStateNotifyCallback;
P_StartCB.callback = (XICProc)XIMPreEditStartCallback;
P_DoneCB.callback = (XICProc)XIMPreEditDoneCallback;
P_DrawCB.callback = (XICProc)XIMPreEditDrawCallback;
@@ -486,6 +553,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
preedit = XVaCreateNestedList(0,
XNFontSet, fontSet,
XNSpotLocation, &spot,
+ XNPreeditStateNotifyCallback, &P_StateNotifyCB,
XNPreeditStartCallback, &P_StartCB,
XNPreeditDoneCallback, &P_DoneCB,
XNPreeditDrawCallback, &P_DrawCB,
@@ -496,6 +564,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
else
{
preedit = XVaCreateNestedList(0,
+ XNPreeditStateNotifyCallback, &P_StateNotifyCB,
XNPreeditStartCallback, &P_StartCB,
XNPreeditDoneCallback, &P_DoneCB,
XNPreeditDrawCallback, &P_DrawCB,
More information about the wine-cvs
mailing list