winex11.drv: Keep the state of XIM and IME consistent.

This commit is contained in:
Kusanagi Kouichi 2010-02-18 23:06:31 +09:00 committed by Alexandre Julliard
parent 10642e76db
commit f7b18148d4
3 changed files with 112 additions and 35 deletions

View File

@ -717,30 +717,36 @@ BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
} }
break; break;
case IMC_SETOPENSTATUS: case IMC_SETOPENSTATUS:
{
LPIMEPRIVATE myPrivate;
TRACE("IMC_SETOPENSTATUS\n"); TRACE("IMC_SETOPENSTATUS\n");
myPrivate = ImmLockIMCC(lpIMC->hPrivate); /* Indirectly called from XIM callbacks */
if (lpIMC->fOpen != myPrivate->bInternalState && if (ImmGetIMCCLockCount(lpIMC->hPrivate) > 0)
myPrivate->bInComposition)
{ {
if(lpIMC->fOpen == FALSE) bRet = TRUE;
break;
}
bRet = X11DRV_SetPreeditState(lpIMC->hWnd, lpIMC->fOpen);
if (bRet)
{
if (!lpIMC->fOpen)
{ {
X11DRV_ForceXIMReset(lpIMC->hWnd); LPIMEPRIVATE myPrivate;
GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION,0,0);
myPrivate->bInComposition = FALSE; myPrivate = ImmLockIMCC(lpIMC->hPrivate);
} if (myPrivate->bInComposition)
else {
{ X11DRV_ForceXIMReset(lpIMC->hWnd);
GenerateIMEMessage(hIMC,WM_IME_STARTCOMPOSITION,0,0); GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, 0, 0); myPrivate->bInComposition = FALSE;
}
ImmUnlockIMCC(lpIMC->hPrivate);
} }
} }
myPrivate->bInternalState = lpIMC->fOpen; else
bRet = TRUE; lpIMC->fOpen = !lpIMC->fOpen;
}
break; break;
default: FIXME("Unknown\n"); break; default: FIXME("Unknown\n"); break;
} }
break; break;
@ -951,35 +957,36 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
/* Interfaces to XIM and other parts of winex11drv */ /* Interfaces to XIM and other parts of winex11drv */
void IME_SetOpenStatus(BOOL fOpen) void IME_SetOpenStatus(BOOL fOpen, BOOL force)
{ {
HIMC imc;
LPINPUTCONTEXT lpIMC; LPINPUTCONTEXT lpIMC;
LPIMEPRIVATE myPrivate; LPIMEPRIVATE myPrivate;
lpIMC = LockRealIMC(FROM_X11); imc = RealIMC(FROM_X11);
lpIMC = ImmLockIMC(imc);
if (lpIMC == NULL) if (lpIMC == NULL)
return; return;
myPrivate = ImmLockIMCC(lpIMC->hPrivate); myPrivate = ImmLockIMCC(lpIMC->hPrivate);
if (myPrivate->bInternalState && fOpen == FALSE) if (!fOpen && myPrivate->bInComposition)
{ {
ShowWindow(myPrivate->hwndDefault, SW_HIDE); ShowWindow(myPrivate->hwndDefault, SW_HIDE);
ImmDestroyIMCC(lpIMC->hCompStr); ImmDestroyIMCC(lpIMC->hCompStr);
lpIMC->hCompStr = ImeCreateBlankCompStr(); lpIMC->hCompStr = ImeCreateBlankCompStr();
myPrivate->bInComposition = FALSE;
GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
} }
if (lpIMC->fOpen && fOpen)
ImmSetOpenStatus(imc, FALSE);
if (fOpen || force)
ImmSetOpenStatus(imc, fOpen);
ImmUnlockIMCC(lpIMC->hPrivate); ImmUnlockIMCC(lpIMC->hPrivate);
UnlockRealIMC(FROM_X11); ImmUnlockIMC(imc);
if (myPrivate->bInComposition && fOpen == FALSE)
{
GenerateIMEMessage(FROM_X11, WM_IME_ENDCOMPOSITION, 0, 0);
myPrivate->bInComposition = FALSE;
}
if (!myPrivate->bInternalState && fOpen == TRUE)
ImmSetOpenStatus(RealIMC(FROM_X11), fOpen);
} }
INT IME_GetCursorPos(void) INT IME_GetCursorPos(void)

View File

@ -300,7 +300,7 @@ extern BOOL destroy_glxpixmap(Display *display, XID glxpixmap);
/* IME support */ /* IME support */
extern void IME_UnregisterClasses(void); 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 INT IME_GetCursorPos(void);
extern void IME_SetCursorPos(DWORD pos); extern void IME_SetCursorPos(DWORD pos);
extern void IME_UpdateAssociation(HWND focus); 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_SetupXIM(void) DECLSPEC_HIDDEN;
extern void X11DRV_XIMLookupChars( const char *str, DWORD count ) DECLSPEC_HIDDEN; extern void X11DRV_XIMLookupChars( const char *str, DWORD count ) DECLSPEC_HIDDEN;
extern void X11DRV_ForceXIMReset(HWND hwnd) DECLSPEC_HIDDEN; extern void X11DRV_ForceXIMReset(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL X11DRV_SetPreeditState(HWND hwnd, BOOL fOpen);
/* FIXME: private functions imported from user32 */ /* FIXME: private functions imported from user32 */
extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ); extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode );

View File

@ -120,10 +120,30 @@ void X11DRV_XIMLookupChars( const char *str, DWORD count )
HeapFree(GetProcessHeap(), 0, wcOutput); 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) static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
{ {
TRACE("PreEditStartCallback %p\n",ic); TRACE("PreEditStartCallback %p\n",ic);
IME_SetOpenStatus(TRUE); IME_SetOpenStatus(TRUE, FALSE);
ximInComposeMode = TRUE; ximInComposeMode = TRUE;
return -1; return -1;
} }
@ -137,7 +157,7 @@ static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_d
dwCompStringSize = 0; dwCompStringSize = 0;
dwCompStringLength = 0; dwCompStringLength = 0;
CompositionString = NULL; CompositionString = NULL;
IME_SetOpenStatus(FALSE); IME_SetOpenStatus(FALSE, FALSE);
} }
static void XIMPreEditDrawCallback(XIM ic, XPointer client_data, 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 * X11DRV_InitXIM
* *
@ -446,7 +511,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
XVaNestedList status = NULL; XVaNestedList status = NULL;
XIC xic; XIC xic;
XICCallback destroy = {(XPointer)data, (XICProc)X11DRV_DestroyIC}; 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())); LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
Window win = data->whole_window; Window win = data->whole_window;
XFontSet fontSet = x11drv_thread_data()->font_set; XFontSet fontSet = x11drv_thread_data()->font_set;
@ -472,10 +537,12 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
} }
/* create callbacks */ /* create callbacks */
P_StateNotifyCB.client_data = (XPointer)data;
P_StartCB.client_data = NULL; P_StartCB.client_data = NULL;
P_DoneCB.client_data = NULL; P_DoneCB.client_data = NULL;
P_DrawCB.client_data = NULL; P_DrawCB.client_data = NULL;
P_CaretCB.client_data = NULL; P_CaretCB.client_data = NULL;
P_StateNotifyCB.callback = (XICProc)XIMPreEditStateNotifyCallback;
P_StartCB.callback = (XICProc)XIMPreEditStartCallback; P_StartCB.callback = (XICProc)XIMPreEditStartCallback;
P_DoneCB.callback = (XICProc)XIMPreEditDoneCallback; P_DoneCB.callback = (XICProc)XIMPreEditDoneCallback;
P_DrawCB.callback = (XICProc)XIMPreEditDrawCallback; P_DrawCB.callback = (XICProc)XIMPreEditDrawCallback;
@ -486,6 +553,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
preedit = XVaCreateNestedList(0, preedit = XVaCreateNestedList(0,
XNFontSet, fontSet, XNFontSet, fontSet,
XNSpotLocation, &spot, XNSpotLocation, &spot,
XNPreeditStateNotifyCallback, &P_StateNotifyCB,
XNPreeditStartCallback, &P_StartCB, XNPreeditStartCallback, &P_StartCB,
XNPreeditDoneCallback, &P_DoneCB, XNPreeditDoneCallback, &P_DoneCB,
XNPreeditDrawCallback, &P_DrawCB, XNPreeditDrawCallback, &P_DrawCB,
@ -496,6 +564,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
else else
{ {
preedit = XVaCreateNestedList(0, preedit = XVaCreateNestedList(0,
XNPreeditStateNotifyCallback, &P_StateNotifyCB,
XNPreeditStartCallback, &P_StartCB, XNPreeditStartCallback, &P_StartCB,
XNPreeditDoneCallback, &P_DoneCB, XNPreeditDoneCallback, &P_DoneCB,
XNPreeditDrawCallback, &P_DrawCB, XNPreeditDrawCallback, &P_DrawCB,