This adds a new `wine/ime.h` header, to share the `IMEPRIVATE` structure between `imm32`, `winex11` and `winemac`. This structure will be internal to `imm32` ultimately, but I intend to keep the header to define a new internal interface for driver to call back into `imm32` (through the UI window), and for a new interface to call from `imm32` into host IME implemented by the drivers.
-- v2: imm32: Remove unnecessary HIMC check in IME UI window proc. imm32: Call DefWindowProcW from IME UI for unhandled messages. imm32: Cleanup default IME UI window proc traces. winemac: Use the default IME UI window proc implementation. winex11: Move IME UI proc to default IME implementation. winex11: Cleanup spaces in IME UI window proc.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/ime.c | 267 ++++++++++++++++++----------------------- 1 file changed, 115 insertions(+), 152 deletions(-)
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index a499c8d9dd6..931289b751b 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -998,26 +998,25 @@ NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG len ) /***** * Internal functions to help with IME window management */ -static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) +static void PaintDefaultIMEWnd( HIMC hIMC, HWND hwnd ) { PAINTSTRUCT ps; RECT rect; HDC hdc; HMONITOR monitor; MONITORINFO mon_info; - INT offX=0, offY=0; + INT offX = 0, offY = 0; LPINPUTCONTEXT lpIMC; WCHAR *str; UINT len;
- lpIMC = ImmLockIMC(hIMC); - if (lpIMC == NULL) - return; + lpIMC = ImmLockIMC( hIMC ); + if (lpIMC == NULL) return;
- hdc = BeginPaint(hwnd,&ps); + hdc = BeginPaint( hwnd, &ps );
- GetClientRect(hwnd,&rect); - FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1)); + GetClientRect( hwnd, &rect ); + FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) );
if ((str = input_context_get_comp_str( lpIMC, FALSE, &len ))) { @@ -1028,7 +1027,7 @@ static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) GetTextExtentPoint32W( hdc, str, len, &size ); pt.x = size.cx; pt.y = size.cy; - LPtoDP(hdc,&pt,1); + LPtoDP( hdc, &pt, 1 );
/* * How this works based on tests on windows: @@ -1045,12 +1044,12 @@ static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) { POINT cpt = lpIMC->cfCompForm.ptCurrentPos; - ClientToScreen(lpIMC->hWnd,&cpt); + ClientToScreen( lpIMC->hWnd, &cpt ); rect.left = cpt.x; rect.top = cpt.y; rect.right = rect.left + pt.x; rect.bottom = rect.top + pt.y; - monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY); + monitor = MonitorFromPoint( cpt, MONITOR_DEFAULTTOPRIMARY ); } else /* CFS_DEFAULT */ { @@ -1058,20 +1057,20 @@ static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) HWND target = lpIMC->hWnd; if (!target) target = GetFocus();
- GetWindowRect(target,&rect); + GetWindowRect( target, &rect ); rect.top = rect.bottom; rect.right = rect.left + pt.x + 20; rect.bottom = rect.top + pt.y + 20; - offX=offY=10; - monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY); + offX = offY = 10; + monitor = MonitorFromWindow( target, MONITOR_DEFAULTTOPRIMARY ); }
if (lpIMC->cfCompForm.dwStyle == CFS_RECT) { RECT client; - client =lpIMC->cfCompForm.rcArea; + client = lpIMC->cfCompForm.rcArea; MapWindowPoints( lpIMC->hWnd, 0, (POINT *)&client, 2 ); - IntersectRect(&rect,&rect,&client); + IntersectRect( &rect, &rect, &client ); /* TODO: Wrap the input if needed */ }
@@ -1079,7 +1078,7 @@ static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) { /* make sure we are on the desktop */ mon_info.cbSize = sizeof(mon_info); - GetMonitorInfoW(monitor, &mon_info); + GetMonitorInfoW( monitor, &mon_info );
if (rect.bottom > mon_info.rcWork.bottom) { @@ -1100,118 +1099,85 @@ static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) } }
- SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE); - + SetWindowPos( hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, SWP_NOACTIVATE ); TextOutW( hdc, offX, offY, str, len );
if (font) SelectObject( hdc, font ); free( str ); }
- EndPaint(hwnd,&ps); - ImmUnlockIMC(hIMC); + EndPaint( hwnd, &ps ); + ImmUnlockIMC( hIMC ); }
-static void UpdateDefaultIMEWindow(INPUTCONTEXT *lpIMC, HWND hwnd) +static void UpdateDefaultIMEWindow( INPUTCONTEXT *lpIMC, HWND hwnd ) { LPCOMPOSITIONSTRING compstr;
- if (lpIMC->hCompStr) - compstr = ImmLockIMCC(lpIMC->hCompStr); - else - compstr = NULL; + if (lpIMC->hCompStr) compstr = ImmLockIMCC( lpIMC->hCompStr ); + else compstr = NULL;
if (compstr == NULL || compstr->dwCompStrLen == 0) - ShowWindow(hwnd,SW_HIDE); + ShowWindow( hwnd, SW_HIDE ); else { - ShowWindow(hwnd,SW_SHOWNOACTIVATE); - RedrawWindow(hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE); + ShowWindow( hwnd, SW_SHOWNOACTIVATE ); + RedrawWindow( hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE ); }
- if (compstr != NULL) - ImmUnlockIMCC(lpIMC->hCompStr); + if (compstr != NULL) ImmUnlockIMCC( lpIMC->hCompStr );
lpIMC->hWnd = GetFocus(); }
-static void DefaultIMEComposition(HIMC hIMC, HWND hwnd, LPARAM lParam) +static void DefaultIMEComposition( HIMC hIMC, HWND hwnd, LPARAM lParam ) { INPUTCONTEXT *ctx; - TRACE("IME message WM_IME_COMPOSITION 0x%Ix\n", lParam); + TRACE( "IME message WM_IME_COMPOSITION 0x%Ix\n", lParam ); if (lParam & GCS_RESULTSTR) return; if (!(ctx = ImmLockIMC( hIMC ))) return; UpdateDefaultIMEWindow( ctx, hwnd ); - ImmUnlockIMC(hIMC); + ImmUnlockIMC( hIMC ); }
-static void DefaultIMEStartComposition(HIMC hIMC, HWND hwnd ) +static void DefaultIMEStartComposition( HIMC hIMC, HWND hwnd ) { INPUTCONTEXT *ctx; - TRACE("IME message WM_IME_STARTCOMPOSITION\n"); + TRACE( "IME message WM_IME_STARTCOMPOSITION\n" ); if (!(ctx = ImmLockIMC( hIMC ))) return; UpdateDefaultIMEWindow( ctx, hwnd ); - ImmUnlockIMC(hIMC); + ImmUnlockIMC( hIMC ); }
-static LRESULT ImeHandleNotify(HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam, - LPARAM lParam) +static LRESULT ImeHandleNotify( HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch (wParam) { - case IMN_OPENSTATUSWINDOW: - FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n"); - break; - case IMN_CLOSESTATUSWINDOW: - FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n"); - break; - case IMN_OPENCANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n"); - break; - case IMN_CHANGECANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n"); - break; - case IMN_CLOSECANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n"); - break; - case IMN_SETCONVERSIONMODE: - FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n"); - break; - case IMN_SETSENTENCEMODE: - FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n"); - break; - case IMN_SETOPENSTATUS: - TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n"); - break; - case IMN_SETCANDIDATEPOS: - FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n"); - break; - case IMN_SETCOMPOSITIONFONT: - FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n"); - break; - case IMN_SETCOMPOSITIONWINDOW: - FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n"); - break; - case IMN_GUIDELINE: - FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n"); - break; - case IMN_SETSTATUSWINDOWPOS: - FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n"); - break; - default: - FIXME("WM_IME_NOTIFY:<Unknown 0x%Ix>\n",wParam); - break; + case IMN_OPENSTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n" ); break; + case IMN_CLOSESTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n" ); break; + case IMN_OPENCANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_OPENCANDIDATE\n" ); break; + case IMN_CHANGECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n" ); break; + case IMN_CLOSECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n" ); break; + case IMN_SETCONVERSIONMODE: FIXME( "WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n" ); break; + case IMN_SETSENTENCEMODE: FIXME( "WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n" ); break; + case IMN_SETOPENSTATUS: TRACE( "WM_IME_NOTIFY:IMN_SETOPENSTATUS\n" ); break; + case IMN_SETCANDIDATEPOS: FIXME( "WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n" ); break; + case IMN_SETCOMPOSITIONFONT: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n" ); break; + case IMN_SETCOMPOSITIONWINDOW: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n" ); break; + case IMN_GUIDELINE: FIXME( "WM_IME_NOTIFY:IMN_GUIDELINE\n" ); break; + case IMN_SETSTATUSWINDOWPOS: FIXME( "WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n" ); break; + default: FIXME( "WM_IME_NOTIFY:<Unknown 0x%Ix>\n", wParam ); break; } return 0; }
-static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, - LPARAM lParam) +static LRESULT WINAPI IME_WindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { LRESULT rc = 0; - HIMC hIMC; + HIMC hIMC;
- TRACE("Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg, wParam, lParam); + TRACE( "Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg, wParam, lParam );
/* * Each UI window contains the current Input Context. @@ -1221,12 +1187,13 @@ static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, * messages. */
- hIMC = (HIMC)GetWindowLongPtrW(hwnd,IMMGWL_IMC); + hIMC = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC );
/* if we have no hIMC there are many messages we cannot process */ if (hIMC == NULL) { - switch (msg) { + switch (msg) + { case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: @@ -1234,104 +1201,100 @@ static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_IME_CONTROL: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: - case WM_IME_CHAR: - return 0L; - default: - break; + case WM_IME_CHAR: return 0L; + default: break; } }
- switch(msg) + switch (msg) { - case WM_CREATE: - { - LPIMEPRIVATE myPrivate; - LPINPUTCONTEXT lpIMC; - - SetWindowTextA(hwnd,"Wine Ime Active"); + case WM_CREATE: + { + LPIMEPRIVATE myPrivate; + LPINPUTCONTEXT lpIMC;
- lpIMC = ImmLockIMC(hIMC); - if (lpIMC) - { - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - myPrivate->hwndDefault = hwnd; - ImmUnlockIMCC(lpIMC->hPrivate); - } - ImmUnlockIMC(hIMC); + SetWindowTextA( hwnd, "Wine Ime Active" );
- return TRUE; + lpIMC = ImmLockIMC( hIMC ); + if (lpIMC) + { + myPrivate = ImmLockIMCC( lpIMC->hPrivate ); + myPrivate->hwndDefault = hwnd; + ImmUnlockIMCC( lpIMC->hPrivate ); } - case WM_PAINT: - PaintDefaultIMEWnd(hIMC, hwnd); - return FALSE; - - case WM_NCCREATE: - return TRUE; + ImmUnlockIMC( hIMC );
- case WM_SETFOCUS: - if (wParam) - SetFocus((HWND)wParam); - else - FIXME("Received focus, should never have focus\n"); - break; - case WM_IME_COMPOSITION: - DefaultIMEComposition(hIMC, hwnd, lParam); - break; - case WM_IME_STARTCOMPOSITION: - DefaultIMEStartComposition(hIMC, hwnd); - break; - case WM_IME_ENDCOMPOSITION: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", - "WM_IME_ENDCOMPOSITION", wParam, lParam); - ShowWindow(hwnd,SW_HIDE); - break; - case WM_IME_SELECT: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_SELECT", wParam, lParam); - break; - case WM_IME_CONTROL: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_CONTROL", wParam, lParam); - rc = 1; - break; - case WM_IME_NOTIFY: - rc = ImeHandleNotify(hIMC,hwnd,msg,wParam,lParam); - break; - default: - TRACE("Non-standard message 0x%x\n",msg); + return TRUE; + } + case WM_PAINT: + PaintDefaultIMEWnd( hIMC, hwnd ); + return FALSE; + case WM_NCCREATE: + return TRUE; + case WM_SETFOCUS: + if (wParam) SetFocus( (HWND)wParam ); + else FIXME( "Received focus, should never have focus\n" ); + break; + + case WM_IME_COMPOSITION: + DefaultIMEComposition( hIMC, hwnd, lParam ); + break; + case WM_IME_STARTCOMPOSITION: + DefaultIMEStartComposition( hIMC, hwnd ); + break; + case WM_IME_ENDCOMPOSITION: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_ENDCOMPOSITION", wParam, lParam ); + ShowWindow( hwnd, SW_HIDE ); + break; + case WM_IME_SELECT: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_SELECT", wParam, lParam ); + break; + case WM_IME_CONTROL: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_CONTROL", wParam, lParam ); + rc = 1; + break; + case WM_IME_NOTIFY: + rc = ImeHandleNotify( hIMC, hwnd, msg, wParam, lParam ); + break; + default: + TRACE( "Non-standard message 0x%x\n", msg ); } + /* check the MSIME messages */ if (msg == WM_MSIME_SERVICE) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_SERVICE", wParam, lParam); - rc = FALSE; + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_SERVICE", wParam, lParam ); + rc = FALSE; } else if (msg == WM_MSIME_RECONVERTOPTIONS) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTOPTIONS", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTOPTIONS", wParam, lParam ); } else if (msg == WM_MSIME_MOUSE) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_MOUSE", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_MOUSE", wParam, lParam ); } else if (msg == WM_MSIME_RECONVERTREQUEST) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTREQUEST", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTREQUEST", wParam, lParam ); } else if (msg == WM_MSIME_RECONVERT) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERT", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERT", wParam, lParam ); } else if (msg == WM_MSIME_QUERYPOSITION) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_QUERYPOSITION", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_QUERYPOSITION", wParam, lParam ); } else if (msg == WM_MSIME_DOCUMENTFEED) { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_DOCUMENTFEED", wParam, lParam); + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_DOCUMENTFEED", wParam, lParam ); } + /* DefWndProc if not an IME message */ if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || - (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) - rc = DefWindowProcW(hwnd,msg,wParam,lParam); + (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) + rc = DefWindowProcW( hwnd, msg, wParam, lParam );
return rc; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 351 ++++++++++++++++++++++++-- dlls/imm32/imm.c | 71 +++--- dlls/imm32/imm_private.h | 46 ++++ dlls/winex11.drv/ime.c | 393 ------------------------------ dlls/winex11.drv/winex11.drv.spec | 2 - include/ntuser.h | 11 + 6 files changed, 423 insertions(+), 451 deletions(-) create mode 100644 dlls/imm32/imm_private.h
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index c05ca6d0255..9bf1fdb6051 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -19,29 +19,352 @@ #include <stdarg.h> #include <stddef.h>
-#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "imm.h" -#include "immdev.h" - -#include "wine/debug.h" +#include "imm_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
+static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT *length ) +{ + COMPOSITIONSTRING *string; + WCHAR *text = NULL; + UINT len, off; + + if (!(string = ImmLockIMCC( ctx->hCompStr ))) return NULL; + len = result ? string->dwResultStrLen : string->dwCompStrLen; + off = result ? string->dwResultStrOffset : string->dwCompStrOffset; + + if (len && off && (text = malloc( (len + 1) * sizeof(WCHAR) ))) + { + memcpy( text, (BYTE *)string + off, len * sizeof(WCHAR) ); + text[len] = 0; + *length = len; + } + + ImmUnlockIMCC( ctx->hCompStr ); + return text; +} + +static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) +{ + struct ime_private *priv; + HFONT font = NULL; + if (!(priv = ImmLockIMCC( ctx->hPrivate ))) return NULL; + if (priv->textfont) font = SelectObject( hdc, priv->textfont ); + ImmUnlockIMCC( ctx->hPrivate ); + return font; +} + +static void ime_ui_paint( HIMC himc, HWND hwnd ) +{ + PAINTSTRUCT ps; + RECT rect; + HDC hdc; + HMONITOR monitor; + MONITORINFO mon_info; + INPUTCONTEXT *ctx; + POINT offset; + WCHAR *str; + UINT len; + + if (!(ctx = ImmLockIMC( himc ))) return; + + hdc = BeginPaint( hwnd, &ps ); + + GetClientRect( hwnd, &rect ); + FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) ); + + if ((str = input_context_get_comp_str( ctx, FALSE, &len ))) + { + HFONT font = input_context_select_ui_font( ctx, hdc ); + SIZE size; + POINT pt; + + GetTextExtentPoint32W( hdc, str, len, &size ); + pt.x = size.cx; + pt.y = size.cy; + LPtoDP( hdc, &pt, 1 ); + + /* + * How this works based on tests on windows: + * CFS_POINT: then we start our window at the point and grow it as large + * as it needs to be for the string. + * CFS_RECT: we still use the ptCurrentPos as a starting point and our + * window is only as large as we need for the string, but we do not + * grow such that our window exceeds the given rect. Wrapping if + * needed and possible. If our ptCurrentPos is outside of our rect + * then no window is displayed. + * CFS_FORCE_POSITION: appears to behave just like CFS_POINT + * maybe because the default MSIME does not do any IME adjusting. + */ + if (ctx->cfCompForm.dwStyle != CFS_DEFAULT) + { + POINT cpt = ctx->cfCompForm.ptCurrentPos; + ClientToScreen( ctx->hWnd, &cpt ); + rect.left = cpt.x; + rect.top = cpt.y; + rect.right = rect.left + pt.x; + rect.bottom = rect.top + pt.y; + monitor = MonitorFromPoint( cpt, MONITOR_DEFAULTTOPRIMARY ); + } + else /* CFS_DEFAULT */ + { + /* Windows places the default IME window in the bottom left */ + HWND target = ctx->hWnd; + if (!target) target = GetFocus(); + + GetWindowRect( target, &rect ); + rect.top = rect.bottom; + rect.right = rect.left + pt.x + 20; + rect.bottom = rect.top + pt.y + 20; + offset.x = offset.y = 10; + monitor = MonitorFromWindow( target, MONITOR_DEFAULTTOPRIMARY ); + } + + if (ctx->cfCompForm.dwStyle == CFS_RECT) + { + RECT client; + client = ctx->cfCompForm.rcArea; + MapWindowPoints( ctx->hWnd, 0, (POINT *)&client, 2 ); + IntersectRect( &rect, &rect, &client ); + /* TODO: Wrap the input if needed */ + } + + if (ctx->cfCompForm.dwStyle == CFS_DEFAULT) + { + /* make sure we are on the desktop */ + mon_info.cbSize = sizeof(mon_info); + GetMonitorInfoW( monitor, &mon_info ); + + if (rect.bottom > mon_info.rcWork.bottom) + { + int shift = rect.bottom - mon_info.rcWork.bottom; + rect.top -= shift; + rect.bottom -= shift; + } + if (rect.left < 0) + { + rect.right -= rect.left; + rect.left = 0; + } + if (rect.right > mon_info.rcWork.right) + { + int shift = rect.right - mon_info.rcWork.right; + rect.left -= shift; + rect.right -= shift; + } + } + + SetWindowPos( hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, SWP_NOACTIVATE ); + TextOutW( hdc, offset.x, offset.y, str, len ); + + if (font) SelectObject( hdc, font ); + free( str ); + } + + EndPaint( hwnd, &ps ); + ImmUnlockIMC( himc ); +} + +static void ime_ui_update_window( INPUTCONTEXT *ctx, HWND hwnd ) +{ + COMPOSITIONSTRING *string; + + if (ctx->hCompStr) string = ImmLockIMCC( ctx->hCompStr ); + else string = NULL; + + if (!string || string->dwCompStrLen == 0) + ShowWindow( hwnd, SW_HIDE ); + else + { + ShowWindow( hwnd, SW_SHOWNOACTIVATE ); + RedrawWindow( hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE ); + } + + if (string) ImmUnlockIMCC( ctx->hCompStr ); + + ctx->hWnd = GetFocus(); +} + +static void ime_ui_composition( HIMC himc, HWND hwnd, LPARAM lparam ) +{ + INPUTCONTEXT *ctx; + TRACE( "IME message WM_IME_COMPOSITION 0x%Ix\n", lparam ); + if (lparam & GCS_RESULTSTR) return; + if (!(ctx = ImmLockIMC( himc ))) return; + ime_ui_update_window( ctx, hwnd ); + ImmUnlockIMC( himc ); +} + +static void ime_ui_start_composition( HIMC himc, HWND hwnd ) +{ + INPUTCONTEXT *ctx; + TRACE( "IME message WM_IME_STARTCOMPOSITION\n" ); + if (!(ctx = ImmLockIMC( himc ))) return; + ime_ui_update_window( ctx, hwnd ); + ImmUnlockIMC( himc ); +} + +static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + switch (wparam) + { + case IMN_OPENSTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n" ); break; + case IMN_CLOSESTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n" ); break; + case IMN_OPENCANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_OPENCANDIDATE\n" ); break; + case IMN_CHANGECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n" ); break; + case IMN_CLOSECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n" ); break; + case IMN_SETCONVERSIONMODE: FIXME( "WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n" ); break; + case IMN_SETSENTENCEMODE: FIXME( "WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n" ); break; + case IMN_SETOPENSTATUS: TRACE( "WM_IME_NOTIFY:IMN_SETOPENSTATUS\n" ); break; + case IMN_SETCANDIDATEPOS: FIXME( "WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n" ); break; + case IMN_SETCOMPOSITIONFONT: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n" ); break; + case IMN_SETCOMPOSITIONWINDOW: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n" ); break; + case IMN_GUIDELINE: FIXME( "WM_IME_NOTIFY:IMN_GUIDELINE\n" ); break; + case IMN_SETSTATUSWINDOWPOS: FIXME( "WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n" ); break; + default: FIXME( "WM_IME_NOTIFY:<Unknown 0x%Ix>\n", wparam ); break; + } + return 0; +} + +static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); + INPUTCONTEXT *ctx; + LRESULT ret = 0; + + TRACE( "hwnd %p, himc %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, himc, msg, wparam, lparam ); + + /* if we have no himc there are many messages we cannot process */ + if (!himc) + { + switch (msg) + { + case WM_IME_STARTCOMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_IME_NOTIFY: + case WM_IME_CONTROL: + case WM_IME_COMPOSITIONFULL: + case WM_IME_SELECT: + case WM_IME_CHAR: return 0L; + default: break; + } + } + + switch (msg) + { + case WM_CREATE: + { + struct ime_private *priv; + + SetWindowTextA( hwnd, "Wine Ime Active" ); + + if (!(ctx = ImmLockIMC( himc ))) return TRUE; + if ((priv = ImmLockIMCC( ctx->hPrivate ))) + { + priv->hwndDefault = hwnd; + ImmUnlockIMCC( ctx->hPrivate ); + } + ImmUnlockIMC( himc ); + return TRUE; + } + case WM_PAINT: + ime_ui_paint( himc, hwnd ); + return FALSE; + case WM_NCCREATE: + return TRUE; + case WM_SETFOCUS: + if (wparam) SetFocus( (HWND)wparam ); + else FIXME( "Received focus, should never have focus\n" ); + break; + case WM_IME_COMPOSITION: + ime_ui_composition( himc, hwnd, lparam ); + break; + case WM_IME_STARTCOMPOSITION: + ime_ui_start_composition( himc, hwnd ); + break; + case WM_IME_ENDCOMPOSITION: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_ENDCOMPOSITION", wparam, lparam ); + ShowWindow( hwnd, SW_HIDE ); + break; + case WM_IME_SELECT: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_SELECT", wparam, lparam ); + break; + case WM_IME_CONTROL: + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_CONTROL", wparam, lparam ); + ret = 1; + break; + case WM_IME_NOTIFY: + ret = ime_ui_notify( himc, hwnd, msg, wparam, lparam ); + break; + default: + TRACE( "Non-standard message 0x%x\n", msg ); + break; + } + + /* check the MSIME messages */ + if (msg == WM_MSIME_SERVICE) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_SERVICE", wparam, lparam ); + else if (msg == WM_MSIME_RECONVERTOPTIONS) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTOPTIONS", wparam, lparam ); + else if (msg == WM_MSIME_MOUSE) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_MOUSE", wparam, lparam ); + else if (msg == WM_MSIME_RECONVERTREQUEST) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTREQUEST", wparam, lparam ); + else if (msg == WM_MSIME_RECONVERT) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERT", wparam, lparam ); + else if (msg == WM_MSIME_QUERYPOSITION) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_QUERYPOSITION", wparam, lparam ); + else if (msg == WM_MSIME_DOCUMENTFEED) + TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_DOCUMENTFEED", wparam, lparam ); + + /* DefWndProc if not an IME message */ + if (!ret && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || + (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) + ret = DefWindowProcW( hwnd, msg, wparam, lparam ); + + return ret; +} + +static WNDCLASSEXW ime_ui_class = +{ + .cbSize = sizeof(WNDCLASSEXW), + .style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW, + .lpfnWndProc = ime_ui_window_proc, + .cbWndExtra = 2 * sizeof(LONG_PTR), + .lpszClassName = WINE_IME_UI_CLASS, + .hbrBackground = (HBRUSH)(COLOR_WINDOW + 1), +}; + BOOL WINAPI ImeInquire( IMEINFO *info, WCHAR *ui_class, DWORD flags ) { - FIXME( "info %p, ui_class %p, flags %#lx stub!\n", info, ui_class, flags ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + TRACE( "info %p, ui_class %p, flags %#lx\n", info, ui_class, flags ); + + ime_ui_class.hInstance = imm32_module; + ime_ui_class.hCursor = LoadCursorW( NULL, (LPWSTR)IDC_ARROW ); + ime_ui_class.hIcon = LoadIconW( NULL, (LPWSTR)IDI_APPLICATION ); + RegisterClassExW( &ime_ui_class ); + + wcscpy( ui_class, ime_ui_class.lpszClassName ); + memset( info, 0, sizeof(*info) ); + info->dwPrivateDataSize = sizeof(IMEPRIVATE); + info->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; + info->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE; + info->fdwSentenceCaps = IME_SMODE_AUTOMATIC; + info->fdwUICaps = UI_CAP_2700; + /* Tell App we cannot accept ImeSetCompositionString calls */ + info->fdwSCSCaps = 0; + info->fdwSelectCaps = SELECT_CAP_CONVERSION; + + return TRUE; }
BOOL WINAPI ImeDestroy( UINT force ) { - FIXME( "force %u stub!\n", force ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + TRACE( "force %u\n", force ); + UnregisterClassW( ime_ui_class.lpszClassName, imm32_module ); + return TRUE; }
BOOL WINAPI ImeSelect( HIMC himc, BOOL select ) diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index e936bb27754..8eee8604bcf 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -20,37 +20,24 @@ */
#define COBJMACROS - -#include <stdarg.h> -#include <stdio.h> - #include "initguid.h" -#include "objbase.h" -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "ntuser.h" -#include "winerror.h" -#include "wine/debug.h" -#include "imm.h" -#include "immdev.h" -#include "winnls.h" -#include "winreg.h" -#include "wine/list.h" +#include "imm_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define IMM_INIT_MAGIC 0x19650412 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
+HMODULE imm32_module; + /* MSIME messages */ -static UINT WM_MSIME_SERVICE; -static UINT WM_MSIME_RECONVERTOPTIONS; -static UINT WM_MSIME_MOUSE; -static UINT WM_MSIME_RECONVERTREQUEST; -static UINT WM_MSIME_RECONVERT; -static UINT WM_MSIME_QUERYPOSITION; -static UINT WM_MSIME_DOCUMENTFEED; +UINT WM_MSIME_SERVICE; +UINT WM_MSIME_RECONVERTOPTIONS; +UINT WM_MSIME_MOUSE; +UINT WM_MSIME_RECONVERTREQUEST; +UINT WM_MSIME_RECONVERT; +UINT WM_MSIME_QUERYPOSITION; +UINT WM_MSIME_DOCUMENTFEED;
struct ime { @@ -709,28 +696,28 @@ static void IMM_FreeAllImmHkl(void) } }
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) +BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) { - TRACE("%p, %lx, %p\n",hInstDLL,fdwReason,lpReserved); - switch (fdwReason) + TRACE( "instance %p, reason %lx, reserved %p\n", instance, reason, reserved ); + + switch (reason) { - case DLL_PROCESS_ATTACH: - if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC)) - { - return FALSE; - } - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - IMM_FreeThreadData(); - break; - case DLL_PROCESS_DETACH: - if (lpReserved) break; - IMM_FreeThreadData(); - IMM_FreeAllImmHkl(); - break; + case DLL_PROCESS_ATTACH: + if (!User32InitializeImmEntryTable( IMM_INIT_MAGIC )) return FALSE; + imm32_module = instance; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + IMM_FreeThreadData(); + break; + case DLL_PROCESS_DETACH: + if (reserved) break; + IMM_FreeThreadData(); + IMM_FreeAllImmHkl(); + break; } + return TRUE; }
diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h new file mode 100644 index 00000000000..57b496ef434 --- /dev/null +++ b/dlls/imm32/imm_private.h @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <stddef.h> + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" + +#include "imm.h" +#include "immdev.h" +#include "ntuser.h" +#include "objbase.h" + +#include "wine/debug.h" +#include "wine/list.h" + +extern HMODULE imm32_module; + +/* MSIME messages */ +extern UINT WM_MSIME_SERVICE; +extern UINT WM_MSIME_RECONVERTOPTIONS; +extern UINT WM_MSIME_MOUSE; +extern UINT WM_MSIME_RECONVERTREQUEST; +extern UINT WM_MSIME_RECONVERT; +extern UINT WM_MSIME_QUERYPOSITION; +extern UINT WM_MSIME_DOCUMENTFEED; diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 931289b751b..55485bfbfcf 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -49,28 +49,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define FROM_X11 ((HIMC)0xcafe1337)
-typedef struct ime_private -{ - BOOL bInComposition; - BOOL bInternalState; - HFONT textfont; - HWND hwndDefault; -} IMEPRIVATE, *LPIMEPRIVATE; - -static const WCHAR UI_CLASS_NAME[] = {'W','i','n','e','X','1','1','I','M','E',0}; - static HIMC *hSelectedFrom = NULL; static INT hSelectedCount = 0;
-/* MSIME messages */ -static UINT WM_MSIME_SERVICE; -static UINT WM_MSIME_RECONVERTOPTIONS; -static UINT WM_MSIME_MOUSE; -static UINT WM_MSIME_RECONVERTREQUEST; -static UINT WM_MSIME_RECONVERT; -static UINT WM_MSIME_QUERYPOSITION; -static UINT WM_MSIME_DOCUMENTFEED; - static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT *length ) { COMPOSITIONSTRING *string; @@ -92,19 +73,6 @@ static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT * return text; }
-static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) -{ - struct ime_private *priv; - HFONT font = NULL; - if (!(priv = ImmLockIMCC( ctx->hPrivate ))) return NULL; - if (priv->textfont) font = SelectObject( hdc, priv->textfont ); - ImmUnlockIMCC( ctx->hPrivate ); - return font; -} - -static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); - static HIMC RealIMC(HIMC hIMC) { if (hIMC == FROM_X11) @@ -139,34 +107,6 @@ static BOOL UnlockRealIMC(HIMC hIMC) return FALSE; }
-static BOOL WINAPI register_classes( INIT_ONCE *once, void *param, void **context ) -{ - WNDCLASSW wndClass; - - ZeroMemory(&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = IME_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 2 * sizeof(LONG_PTR); - wndClass.hInstance = x11drv_module; - wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); - wndClass.hIcon = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1); - wndClass.lpszMenuName = 0; - wndClass.lpszClassName = UI_CLASS_NAME; - - RegisterClassW(&wndClass); - - WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); - WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); - WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); - WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); - WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); - WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); - WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); - return TRUE; -} - static HIMCC ImeCreateBlankCompStr(void) { HIMCC rc; @@ -537,35 +477,6 @@ static void IME_AddToSelected(HIMC hIMC) hSelectedFrom[hSelectedCount-1] = hIMC; }
-BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass, DWORD flags) -{ - static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; - - TRACE("\n"); - InitOnceExecuteOnce( &init_once, register_classes, NULL, NULL ); - lpIMEInfo->dwPrivateDataSize = sizeof (IMEPRIVATE); - lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; - lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE; - lpIMEInfo->fdwSentenceCaps = IME_SMODE_AUTOMATIC; - lpIMEInfo->fdwUICaps = UI_CAP_2700; - /* Tell App we cannot accept ImeSetCompositionString calls */ - lpIMEInfo->fdwSCSCaps = 0; - lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; - - lstrcpyW(lpszUIClass,UI_CLASS_NAME); - - return TRUE; -} - -BOOL WINAPI ImeDestroy(UINT uForce) -{ - TRACE("\n"); - HeapFree(GetProcessHeap(),0,hSelectedFrom); - hSelectedFrom = NULL; - hSelectedCount = 0; - return TRUE; -} - BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) { /* See the comment at the head of this file */ @@ -994,307 +905,3 @@ NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG len ) ImmUnlockIMC(imc); return 0; } - -/***** - * Internal functions to help with IME window management - */ -static void PaintDefaultIMEWnd( HIMC hIMC, HWND hwnd ) -{ - PAINTSTRUCT ps; - RECT rect; - HDC hdc; - HMONITOR monitor; - MONITORINFO mon_info; - INT offX = 0, offY = 0; - LPINPUTCONTEXT lpIMC; - WCHAR *str; - UINT len; - - lpIMC = ImmLockIMC( hIMC ); - if (lpIMC == NULL) return; - - hdc = BeginPaint( hwnd, &ps ); - - GetClientRect( hwnd, &rect ); - FillRect( hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1) ); - - if ((str = input_context_get_comp_str( lpIMC, FALSE, &len ))) - { - HFONT font = input_context_select_ui_font( lpIMC, hdc ); - SIZE size; - POINT pt; - - GetTextExtentPoint32W( hdc, str, len, &size ); - pt.x = size.cx; - pt.y = size.cy; - LPtoDP( hdc, &pt, 1 ); - - /* - * How this works based on tests on windows: - * CFS_POINT: then we start our window at the point and grow it as large - * as it needs to be for the string. - * CFS_RECT: we still use the ptCurrentPos as a starting point and our - * window is only as large as we need for the string, but we do not - * grow such that our window exceeds the given rect. Wrapping if - * needed and possible. If our ptCurrentPos is outside of our rect - * then no window is displayed. - * CFS_FORCE_POSITION: appears to behave just like CFS_POINT - * maybe because the default MSIME does not do any IME adjusting. - */ - if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) - { - POINT cpt = lpIMC->cfCompForm.ptCurrentPos; - ClientToScreen( lpIMC->hWnd, &cpt ); - rect.left = cpt.x; - rect.top = cpt.y; - rect.right = rect.left + pt.x; - rect.bottom = rect.top + pt.y; - monitor = MonitorFromPoint( cpt, MONITOR_DEFAULTTOPRIMARY ); - } - else /* CFS_DEFAULT */ - { - /* Windows places the default IME window in the bottom left */ - HWND target = lpIMC->hWnd; - if (!target) target = GetFocus(); - - GetWindowRect( target, &rect ); - rect.top = rect.bottom; - rect.right = rect.left + pt.x + 20; - rect.bottom = rect.top + pt.y + 20; - offX = offY = 10; - monitor = MonitorFromWindow( target, MONITOR_DEFAULTTOPRIMARY ); - } - - if (lpIMC->cfCompForm.dwStyle == CFS_RECT) - { - RECT client; - client = lpIMC->cfCompForm.rcArea; - MapWindowPoints( lpIMC->hWnd, 0, (POINT *)&client, 2 ); - IntersectRect( &rect, &rect, &client ); - /* TODO: Wrap the input if needed */ - } - - if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT) - { - /* make sure we are on the desktop */ - mon_info.cbSize = sizeof(mon_info); - GetMonitorInfoW( monitor, &mon_info ); - - if (rect.bottom > mon_info.rcWork.bottom) - { - int shift = rect.bottom - mon_info.rcWork.bottom; - rect.top -= shift; - rect.bottom -= shift; - } - if (rect.left < 0) - { - rect.right -= rect.left; - rect.left = 0; - } - if (rect.right > mon_info.rcWork.right) - { - int shift = rect.right - mon_info.rcWork.right; - rect.left -= shift; - rect.right -= shift; - } - } - - SetWindowPos( hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, SWP_NOACTIVATE ); - TextOutW( hdc, offX, offY, str, len ); - - if (font) SelectObject( hdc, font ); - free( str ); - } - - EndPaint( hwnd, &ps ); - ImmUnlockIMC( hIMC ); -} - -static void UpdateDefaultIMEWindow( INPUTCONTEXT *lpIMC, HWND hwnd ) -{ - LPCOMPOSITIONSTRING compstr; - - if (lpIMC->hCompStr) compstr = ImmLockIMCC( lpIMC->hCompStr ); - else compstr = NULL; - - if (compstr == NULL || compstr->dwCompStrLen == 0) - ShowWindow( hwnd, SW_HIDE ); - else - { - ShowWindow( hwnd, SW_SHOWNOACTIVATE ); - RedrawWindow( hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE ); - } - - if (compstr != NULL) ImmUnlockIMCC( lpIMC->hCompStr ); - - lpIMC->hWnd = GetFocus(); -} - -static void DefaultIMEComposition( HIMC hIMC, HWND hwnd, LPARAM lParam ) -{ - INPUTCONTEXT *ctx; - TRACE( "IME message WM_IME_COMPOSITION 0x%Ix\n", lParam ); - if (lParam & GCS_RESULTSTR) return; - if (!(ctx = ImmLockIMC( hIMC ))) return; - UpdateDefaultIMEWindow( ctx, hwnd ); - ImmUnlockIMC( hIMC ); -} - -static void DefaultIMEStartComposition( HIMC hIMC, HWND hwnd ) -{ - INPUTCONTEXT *ctx; - TRACE( "IME message WM_IME_STARTCOMPOSITION\n" ); - if (!(ctx = ImmLockIMC( hIMC ))) return; - UpdateDefaultIMEWindow( ctx, hwnd ); - ImmUnlockIMC( hIMC ); -} - -static LRESULT ImeHandleNotify( HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) -{ - switch (wParam) - { - case IMN_OPENSTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n" ); break; - case IMN_CLOSESTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n" ); break; - case IMN_OPENCANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_OPENCANDIDATE\n" ); break; - case IMN_CHANGECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n" ); break; - case IMN_CLOSECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n" ); break; - case IMN_SETCONVERSIONMODE: FIXME( "WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n" ); break; - case IMN_SETSENTENCEMODE: FIXME( "WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n" ); break; - case IMN_SETOPENSTATUS: TRACE( "WM_IME_NOTIFY:IMN_SETOPENSTATUS\n" ); break; - case IMN_SETCANDIDATEPOS: FIXME( "WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n" ); break; - case IMN_SETCOMPOSITIONFONT: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n" ); break; - case IMN_SETCOMPOSITIONWINDOW: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n" ); break; - case IMN_GUIDELINE: FIXME( "WM_IME_NOTIFY:IMN_GUIDELINE\n" ); break; - case IMN_SETSTATUSWINDOWPOS: FIXME( "WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n" ); break; - default: FIXME( "WM_IME_NOTIFY:<Unknown 0x%Ix>\n", wParam ); break; - } - return 0; -} - -static LRESULT WINAPI IME_WindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) -{ - LRESULT rc = 0; - HIMC hIMC; - - TRACE( "Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg, wParam, lParam ); - - /* - * Each UI window contains the current Input Context. - * This Input Context can be obtained by calling GetWindowLong - * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message. - * The UI window can refer to this Input Context and handles the - * messages. - */ - - hIMC = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); - - /* if we have no hIMC there are many messages we cannot process */ - if (hIMC == NULL) - { - switch (msg) - { - case WM_IME_STARTCOMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_COMPOSITION: - case WM_IME_NOTIFY: - case WM_IME_CONTROL: - case WM_IME_COMPOSITIONFULL: - case WM_IME_SELECT: - case WM_IME_CHAR: return 0L; - default: break; - } - } - - switch (msg) - { - case WM_CREATE: - { - LPIMEPRIVATE myPrivate; - LPINPUTCONTEXT lpIMC; - - SetWindowTextA( hwnd, "Wine Ime Active" ); - - lpIMC = ImmLockIMC( hIMC ); - if (lpIMC) - { - myPrivate = ImmLockIMCC( lpIMC->hPrivate ); - myPrivate->hwndDefault = hwnd; - ImmUnlockIMCC( lpIMC->hPrivate ); - } - ImmUnlockIMC( hIMC ); - - return TRUE; - } - case WM_PAINT: - PaintDefaultIMEWnd( hIMC, hwnd ); - return FALSE; - case WM_NCCREATE: - return TRUE; - case WM_SETFOCUS: - if (wParam) SetFocus( (HWND)wParam ); - else FIXME( "Received focus, should never have focus\n" ); - break; - - case WM_IME_COMPOSITION: - DefaultIMEComposition( hIMC, hwnd, lParam ); - break; - case WM_IME_STARTCOMPOSITION: - DefaultIMEStartComposition( hIMC, hwnd ); - break; - case WM_IME_ENDCOMPOSITION: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_ENDCOMPOSITION", wParam, lParam ); - ShowWindow( hwnd, SW_HIDE ); - break; - case WM_IME_SELECT: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_SELECT", wParam, lParam ); - break; - case WM_IME_CONTROL: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_CONTROL", wParam, lParam ); - rc = 1; - break; - case WM_IME_NOTIFY: - rc = ImeHandleNotify( hIMC, hwnd, msg, wParam, lParam ); - break; - default: - TRACE( "Non-standard message 0x%x\n", msg ); - } - - /* check the MSIME messages */ - if (msg == WM_MSIME_SERVICE) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_SERVICE", wParam, lParam ); - rc = FALSE; - } - else if (msg == WM_MSIME_RECONVERTOPTIONS) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTOPTIONS", wParam, lParam ); - } - else if (msg == WM_MSIME_MOUSE) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_MOUSE", wParam, lParam ); - } - else if (msg == WM_MSIME_RECONVERTREQUEST) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTREQUEST", wParam, lParam ); - } - else if (msg == WM_MSIME_RECONVERT) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERT", wParam, lParam ); - } - else if (msg == WM_MSIME_QUERYPOSITION) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_QUERYPOSITION", wParam, lParam ); - } - else if (msg == WM_MSIME_DOCUMENTFEED) - { - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_DOCUMENTFEED", wParam, lParam ); - } - - /* DefWndProc if not an IME message */ - if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || - (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) - rc = DefWindowProcW( hwnd, msg, wParam, lParam ); - - return rc; -} diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 0596d48c577..a753536eb3f 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -11,8 +11,6 @@ @ cdecl wine_notify_icon(long ptr)
#IME Interface -@ stdcall ImeInquire(ptr ptr wstr) -@ stdcall ImeDestroy(long) @ stdcall ImeSelect(long long) @ stdcall ImeToAsciiEx(long long ptr ptr long long) @ stdcall NotifyIME(long long long long) diff --git a/include/ntuser.h b/include/ntuser.h index 14e1f3757d4..22dbc40da25 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -490,6 +490,17 @@ enum wine_internal_message #define IME_INTERNAL_HKL_ACTIVATE 0x19 #define IME_INTERNAL_HKL_DEACTIVATE 0x20
+/* internal IME private */ +typedef struct ime_private +{ + BOOL bInComposition; + BOOL bInternalState; + HFONT textfont; + HWND hwndDefault; +} IMEPRIVATE, *LPIMEPRIVATE; + +static const WCHAR WINE_IME_UI_CLASS[] = {'W','i','n','e',' ','I','M','E',0}; + #define WM_SYSTIMER 0x0118
/* the various structures that can be sent in messages, in platform-independent layout */
From: Rémi Bernon rbernon@codeweavers.com
This slightly changes ime_ui_update_window to match what was previously in winex11.drv, since e5f0cdfcf6ba1595346c4c9ed1a7cbf3de418c8e, which seems to be a more recent change. --- dlls/winemac.drv/ime.c | 401 ------------------------------ dlls/winemac.drv/winemac.drv.spec | 2 - include/ntuser.h | 1 + 3 files changed, 1 insertion(+), 403 deletions(-)
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index 71062a357c5..059a5c443f3 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -43,30 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define FROM_MACDRV ((HIMC)0xcafe1337)
-typedef struct ime_private -{ - BOOL bInComposition; - BOOL bInternalState; - HFONT textfont; - HWND hwndDefault; - - UINT repeat; -} IMEPRIVATE, *LPIMEPRIVATE; - -static const WCHAR UI_CLASS_NAME[] = {'W','i','n','e',' ','M','a','c',' ','I','M','E',0}; - static HIMC *hSelectedFrom = NULL; static INT hSelectedCount = 0;
-/* MSIME messages */ -static UINT WM_MSIME_SERVICE; -static UINT WM_MSIME_RECONVERTOPTIONS; -static UINT WM_MSIME_MOUSE; -static UINT WM_MSIME_RECONVERTREQUEST; -static UINT WM_MSIME_RECONVERT; -static UINT WM_MSIME_QUERYPOSITION; -static UINT WM_MSIME_DOCUMENTFEED; - static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT *length ) { COMPOSITIONSTRING *string; @@ -554,15 +533,6 @@ static void UpdateDataInDefaultIMEWindow(INPUTCONTEXT *lpIMC, HWND hwnd, BOOL sh ImmUnlockIMCC(lpIMC->hCompStr); }
-BOOL WINAPI ImeDestroy(UINT uForce) -{ - TRACE("\n"); - HeapFree(GetProcessHeap(), 0, hSelectedFrom); - hSelectedFrom = NULL; - hSelectedCount = 0; - return TRUE; -} - BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) { LPINPUTCONTEXT lpIMC; @@ -959,377 +929,6 @@ static void IME_NotifyComplete(void* hIMC) NotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); }
-/***** - * Internal functions to help with IME window management - */ -static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd) -{ - PAINTSTRUCT ps; - RECT rect; - HDC hdc; - HMONITOR monitor; - MONITORINFO mon_info; - INT offX = 0, offY = 0; - LPINPUTCONTEXT lpIMC; - WCHAR *str; - UINT len; - - lpIMC = ImmLockIMC(hIMC); - if (lpIMC == NULL) - return; - - hdc = BeginPaint(hwnd, &ps); - - GetClientRect(hwnd, &rect); - FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1)); - - if ((str = input_context_get_comp_str( lpIMC, FALSE, &len ))) - { - HFONT font = input_context_select_ui_font( lpIMC, hdc ); - SIZE size; - POINT pt; - - GetTextExtentPoint32W( hdc, str, len, &size ); - pt.x = size.cx; - pt.y = size.cy; - LPtoDP(hdc, &pt, 1); - - /* - * How this works based on tests on windows: - * CFS_POINT: then we start our window at the point and grow it as large - * as it needs to be for the string. - * CFS_RECT: we still use the ptCurrentPos as a starting point and our - * window is only as large as we need for the string, but we do not - * grow such that our window exceeds the given rect. Wrapping if - * needed and possible. If our ptCurrentPos is outside of our rect - * then no window is displayed. - * CFS_FORCE_POSITION: appears to behave just like CFS_POINT - * maybe because the default MSIME does not do any IME adjusting. - */ - if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) - { - POINT cpt = lpIMC->cfCompForm.ptCurrentPos; - ClientToScreen(lpIMC->hWnd, &cpt); - rect.left = cpt.x; - rect.top = cpt.y; - rect.right = rect.left + pt.x; - rect.bottom = rect.top + pt.y; - monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY); - } - else /* CFS_DEFAULT */ - { - /* Windows places the default IME window in the bottom left */ - HWND target = lpIMC->hWnd; - if (!target) target = GetFocus(); - - GetWindowRect(target, &rect); - rect.top = rect.bottom; - rect.right = rect.left + pt.x + 20; - rect.bottom = rect.top + pt.y + 20; - offX=offY=10; - monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY); - } - - if (lpIMC->cfCompForm.dwStyle == CFS_RECT) - { - RECT client; - client =lpIMC->cfCompForm.rcArea; - MapWindowPoints(lpIMC->hWnd, 0, (POINT *)&client, 2); - IntersectRect(&rect, &rect, &client); - /* TODO: Wrap the input if needed */ - } - - if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT) - { - /* make sure we are on the desktop */ - mon_info.cbSize = sizeof(mon_info); - GetMonitorInfoW(monitor, &mon_info); - - if (rect.bottom > mon_info.rcWork.bottom) - { - int shift = rect.bottom - mon_info.rcWork.bottom; - rect.top -= shift; - rect.bottom -= shift; - } - if (rect.left < 0) - { - rect.right -= rect.left; - rect.left = 0; - } - if (rect.right > mon_info.rcWork.right) - { - int shift = rect.right - mon_info.rcWork.right; - rect.left -= shift; - rect.right -= shift; - } - } - - SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, SWP_NOACTIVATE); - - TextOutW( hdc, offX, offY, str, len ); - - if (font) SelectObject( hdc, font ); - free( str ); - } - - ImmUnlockIMCC(lpIMC->hCompStr); - - EndPaint(hwnd, &ps); - ImmUnlockIMC(hIMC); -} - -static void DefaultIMEComposition(HIMC hIMC, HWND hwnd, LPARAM lParam) -{ - INPUTCONTEXT *ctx; - TRACE("IME message WM_IME_COMPOSITION 0x%Ix\n", lParam); - if (lParam & GCS_RESULTSTR) return; - if (!(ctx = ImmLockIMC( hIMC ))) return; - UpdateDataInDefaultIMEWindow( ctx, hwnd, TRUE ); - ImmUnlockIMC(hIMC); -} - -static void DefaultIMEStartComposition(HIMC hIMC, HWND hwnd) -{ - LPINPUTCONTEXT lpIMC; - - lpIMC = ImmLockIMC(hIMC); - if (lpIMC == NULL) - return; - - TRACE("IME message WM_IME_STARTCOMPOSITION\n"); - lpIMC->hWnd = GetFocus(); - ShowWindow(hwnd, SW_SHOWNOACTIVATE); - ImmUnlockIMC(hIMC); -} - -static LRESULT ImeHandleNotify(HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (wParam) - { - case IMN_OPENSTATUSWINDOW: - FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n"); - break; - case IMN_CLOSESTATUSWINDOW: - FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n"); - break; - case IMN_OPENCANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n"); - break; - case IMN_CHANGECANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n"); - break; - case IMN_CLOSECANDIDATE: - FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n"); - break; - case IMN_SETCONVERSIONMODE: - FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n"); - break; - case IMN_SETSENTENCEMODE: - FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n"); - break; - case IMN_SETOPENSTATUS: - FIXME("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n"); - break; - case IMN_SETCANDIDATEPOS: - FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n"); - break; - case IMN_SETCOMPOSITIONFONT: - FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n"); - break; - case IMN_SETCOMPOSITIONWINDOW: - FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n"); - break; - case IMN_GUIDELINE: - FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n"); - break; - case IMN_SETSTATUSWINDOWPOS: - FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n"); - break; - default: - FIXME("WM_IME_NOTIFY:<Unknown 0x%Ix>\n", wParam); - break; - } - return 0; -} - -static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LRESULT rc = 0; - HIMC hIMC; - - TRACE("Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg, wParam, lParam); - - /* - * Each UI window contains the current Input Context. - * This Input Context can be obtained by calling GetWindowLong - * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message. - * The UI window can refer to this Input Context and handles the - * messages. - */ - - hIMC = (HIMC)GetWindowLongPtrW(hwnd, IMMGWL_IMC); - - /* if we have no hIMC there are many messages we cannot process */ - if (hIMC == NULL) - { - switch (msg) { - case WM_IME_STARTCOMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_COMPOSITION: - case WM_IME_NOTIFY: - case WM_IME_CONTROL: - case WM_IME_COMPOSITIONFULL: - case WM_IME_SELECT: - case WM_IME_CHAR: - return 0L; - default: - break; - } - } - - switch (msg) - { - case WM_CREATE: - { - LPIMEPRIVATE myPrivate; - LPINPUTCONTEXT lpIMC; - - SetWindowTextA(hwnd, "Wine Ime Active"); - - lpIMC = ImmLockIMC(hIMC); - if (lpIMC) - { - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - myPrivate->hwndDefault = hwnd; - ImmUnlockIMCC(lpIMC->hPrivate); - } - ImmUnlockIMC(hIMC); - - return TRUE; - } - case WM_PAINT: - PaintDefaultIMEWnd(hIMC, hwnd); - return FALSE; - - case WM_NCCREATE: - return TRUE; - - case WM_SETFOCUS: - if (wParam) - SetFocus((HWND)wParam); - else - FIXME("Received focus, should never have focus\n"); - break; - case WM_IME_COMPOSITION: - DefaultIMEComposition(hIMC, hwnd, lParam); - break; - case WM_IME_STARTCOMPOSITION: - DefaultIMEStartComposition(hIMC, hwnd); - break; - case WM_IME_ENDCOMPOSITION: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_ENDCOMPOSITION", wParam, lParam); - ShowWindow(hwnd, SW_HIDE); - break; - case WM_IME_SELECT: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_SELECT", wParam, lParam); - break; - case WM_IME_CONTROL: - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_CONTROL", wParam, lParam); - rc = 1; - break; - case WM_IME_NOTIFY: - rc = ImeHandleNotify(hIMC, hwnd, msg, wParam, lParam); - break; - default: - TRACE("Non-standard message 0x%x\n", msg); - } - /* check the MSIME messages */ - if (msg == WM_MSIME_SERVICE) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_SERVICE", wParam, lParam); - rc = FALSE; - } - else if (msg == WM_MSIME_RECONVERTOPTIONS) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTOPTIONS", wParam, lParam); - } - else if (msg == WM_MSIME_MOUSE) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_MOUSE", wParam, lParam); - } - else if (msg == WM_MSIME_RECONVERTREQUEST) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTREQUEST", wParam, lParam); - } - else if (msg == WM_MSIME_RECONVERT) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERT", wParam, lParam); - } - else if (msg == WM_MSIME_QUERYPOSITION) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_QUERYPOSITION", wParam, lParam); - } - else if (msg == WM_MSIME_DOCUMENTFEED) - { - TRACE("IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_DOCUMENTFEED", wParam, lParam); - } - /* DefWndProc if not an IME message */ - if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || - (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) - rc = DefWindowProcW(hwnd, msg, wParam, lParam); - - return rc; -} - -static BOOL WINAPI register_classes( INIT_ONCE *once, void *param, void **context ) -{ - WNDCLASSW wndClass; - ZeroMemory(&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 2 * sizeof(LONG_PTR); - wndClass.hInstance = macdrv_module; - wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); - wndClass.hIcon = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszMenuName = 0; - wndClass.lpszClassName = UI_CLASS_NAME; - - RegisterClassW(&wndClass); - - WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); - WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); - WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); - WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); - WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); - WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); - WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); - return TRUE; -} - -BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass, DWORD flags) -{ - static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; - - TRACE("\n"); - InitOnceExecuteOnce( &init_once, register_classes, NULL, NULL ); - lpIMEInfo->dwPrivateDataSize = sizeof(IMEPRIVATE); - lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; - lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE; - lpIMEInfo->fdwSentenceCaps = IME_SMODE_AUTOMATIC; - lpIMEInfo->fdwUICaps = UI_CAP_2700; - /* Tell App we cannot accept ImeSetCompositionString calls */ - /* FIXME: Can we? */ - lpIMEInfo->fdwSCSCaps = 0; - lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; - - lstrcpyW(lpszUIClass, UI_CLASS_NAME); - - return TRUE; -} - /* Interfaces to other parts of the Mac driver */
/*********************************************************************** diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index d5e94b53ce4..debaec8239d 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -2,8 +2,6 @@ @ cdecl wine_notify_icon(long ptr)
# IME -@ stdcall ImeDestroy(long) -@ stdcall ImeInquire(ptr wstr wstr) @ stdcall ImeProcessKey(long long long ptr) @ stdcall ImeSelect(long long) @ stdcall ImeSetCompositionString(long long ptr long ptr long) diff --git a/include/ntuser.h b/include/ntuser.h index 22dbc40da25..3e89556ee97 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -497,6 +497,7 @@ typedef struct ime_private BOOL bInternalState; HFONT textfont; HWND hwndDefault; + UINT repeat; } IMEPRIVATE, *LPIMEPRIVATE;
static const WCHAR WINE_IME_UI_CLASS[] = {'W','i','n','e',' ','I','M','E',0};
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 102 ++++++++++++++++++--------------------- dlls/imm32/imm.c | 3 ++ dlls/imm32/imm_private.h | 28 +++++++++++ 3 files changed, 79 insertions(+), 54 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 9bf1fdb6051..1ee2eec84d9 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -23,6 +23,45 @@
WINE_DEFAULT_DEBUG_CHANNEL(imm);
+static const char *debugstr_imn( WPARAM wparam ) +{ + switch (wparam) + { + case IMN_OPENSTATUSWINDOW: return "IMN_OPENSTATUSWINDOW"; + case IMN_CLOSESTATUSWINDOW: return "IMN_CLOSESTATUSWINDOW"; + case IMN_OPENCANDIDATE: return "IMN_OPENCANDIDATE"; + case IMN_CHANGECANDIDATE: return "IMN_CHANGECANDIDATE"; + case IMN_CLOSECANDIDATE: return "IMN_CLOSECANDIDATE"; + case IMN_SETCONVERSIONMODE: return "IMN_SETCONVERSIONMODE"; + case IMN_SETSENTENCEMODE: return "IMN_SETSENTENCEMODE"; + case IMN_SETOPENSTATUS: return "IMN_SETOPENSTATUS"; + case IMN_SETCANDIDATEPOS: return "IMN_SETCANDIDATEPOS"; + case IMN_SETCOMPOSITIONFONT: return "IMN_SETCOMPOSITIONFONT"; + case IMN_SETCOMPOSITIONWINDOW: return "IMN_SETCOMPOSITIONWINDOW"; + case IMN_GUIDELINE: return "IMN_GUIDELINE"; + case IMN_SETSTATUSWINDOWPOS: return "IMN_SETSTATUSWINDOWPOS"; + default: return wine_dbg_sprintf( "%#Ix", wparam ); + } +} + +static const char *debugstr_imc( WPARAM wparam ) +{ + switch (wparam) + { + case IMC_GETCANDIDATEPOS: return "IMC_GETCANDIDATEPOS"; + case IMC_SETCANDIDATEPOS: return "IMC_SETCANDIDATEPOS"; + case IMC_GETCOMPOSITIONFONT: return "IMC_GETCOMPOSITIONFONT"; + case IMC_SETCOMPOSITIONFONT: return "IMC_SETCOMPOSITIONFONT"; + case IMC_GETCOMPOSITIONWINDOW: return "IMC_GETCOMPOSITIONWINDOW"; + case IMC_SETCOMPOSITIONWINDOW: return "IMC_SETCOMPOSITIONWINDOW"; + case IMC_GETSTATUSWINDOWPOS: return "IMC_GETSTATUSWINDOWPOS"; + case IMC_SETSTATUSWINDOWPOS: return "IMC_SETSTATUSWINDOWPOS"; + case IMC_CLOSESTATUSWINDOW: return "IMC_CLOSESTATUSWINDOW"; + case IMC_OPENSTATUSWINDOW: return "IMC_OPENSTATUSWINDOW"; + default: return wine_dbg_sprintf( "%#Ix", wparam ); + } +} + static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT *length ) { COMPOSITIONSTRING *string; @@ -189,7 +228,6 @@ static void ime_ui_update_window( INPUTCONTEXT *ctx, HWND hwnd ) static void ime_ui_composition( HIMC himc, HWND hwnd, LPARAM lparam ) { INPUTCONTEXT *ctx; - TRACE( "IME message WM_IME_COMPOSITION 0x%Ix\n", lparam ); if (lparam & GCS_RESULTSTR) return; if (!(ctx = ImmLockIMC( himc ))) return; ime_ui_update_window( ctx, hwnd ); @@ -199,41 +237,19 @@ static void ime_ui_composition( HIMC himc, HWND hwnd, LPARAM lparam ) static void ime_ui_start_composition( HIMC himc, HWND hwnd ) { INPUTCONTEXT *ctx; - TRACE( "IME message WM_IME_STARTCOMPOSITION\n" ); if (!(ctx = ImmLockIMC( himc ))) return; ime_ui_update_window( ctx, hwnd ); ImmUnlockIMC( himc ); }
-static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -{ - switch (wparam) - { - case IMN_OPENSTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n" ); break; - case IMN_CLOSESTATUSWINDOW: FIXME( "WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n" ); break; - case IMN_OPENCANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_OPENCANDIDATE\n" ); break; - case IMN_CHANGECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n" ); break; - case IMN_CLOSECANDIDATE: FIXME( "WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n" ); break; - case IMN_SETCONVERSIONMODE: FIXME( "WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n" ); break; - case IMN_SETSENTENCEMODE: FIXME( "WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n" ); break; - case IMN_SETOPENSTATUS: TRACE( "WM_IME_NOTIFY:IMN_SETOPENSTATUS\n" ); break; - case IMN_SETCANDIDATEPOS: FIXME( "WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n" ); break; - case IMN_SETCOMPOSITIONFONT: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n" ); break; - case IMN_SETCOMPOSITIONWINDOW: FIXME( "WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n" ); break; - case IMN_GUIDELINE: FIXME( "WM_IME_NOTIFY:IMN_GUIDELINE\n" ); break; - case IMN_SETSTATUSWINDOWPOS: FIXME( "WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n" ); break; - default: FIXME( "WM_IME_NOTIFY:<Unknown 0x%Ix>\n", wparam ); break; - } - return 0; -} - static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); INPUTCONTEXT *ctx; LRESULT ret = 0;
- TRACE( "hwnd %p, himc %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, himc, msg, wparam, lparam ); + TRACE( "hwnd %p, himc %p, msg %s, wparam %#Ix, lparam %#Ix\n", + hwnd, himc, debugstr_wm_ime(msg), wparam, lparam );
/* if we have no himc there are many messages we cannot process */ if (!himc) @@ -285,40 +301,18 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP ime_ui_start_composition( himc, hwnd ); break; case WM_IME_ENDCOMPOSITION: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_ENDCOMPOSITION", wparam, lparam ); ShowWindow( hwnd, SW_HIDE ); break; - case WM_IME_SELECT: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_SELECT", wparam, lparam ); - break; - case WM_IME_CONTROL: - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_IME_CONTROL", wparam, lparam ); - ret = 1; - break; case WM_IME_NOTIFY: - ret = ime_ui_notify( himc, hwnd, msg, wparam, lparam ); - break; - default: - TRACE( "Non-standard message 0x%x\n", msg ); - break; + FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, + debugstr_wm_ime(msg), debugstr_imn(wparam), lparam ); + return 0; + case WM_IME_CONTROL: + FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, + debugstr_wm_ime(msg), debugstr_imc(wparam), lparam ); + return 1; }
- /* check the MSIME messages */ - if (msg == WM_MSIME_SERVICE) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_SERVICE", wparam, lparam ); - else if (msg == WM_MSIME_RECONVERTOPTIONS) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTOPTIONS", wparam, lparam ); - else if (msg == WM_MSIME_MOUSE) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_MOUSE", wparam, lparam ); - else if (msg == WM_MSIME_RECONVERTREQUEST) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERTREQUEST", wparam, lparam ); - else if (msg == WM_MSIME_RECONVERT) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_RECONVERT", wparam, lparam ); - else if (msg == WM_MSIME_QUERYPOSITION) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_QUERYPOSITION", wparam, lparam ); - else if (msg == WM_MSIME_DOCUMENTFEED) - TRACE( "IME message %s, 0x%Ix, 0x%Ix\n", "WM_MSIME_DOCUMENTFEED", wparam, lparam ); - /* DefWndProc if not an IME message */ if (!ret && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 8eee8604bcf..25d1df47a1c 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -3203,6 +3203,9 @@ LRESULT WINAPI __wine_ime_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp { HWND ui_hwnd;
+ TRACE( "hwnd %p, msg %s, wparam %#Ix, lparam %#Ix, ansi %u\n", + hwnd, debugstr_wm_ime(msg), wparam, lparam, ansi ); + switch (msg) { case WM_CREATE: diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 57b496ef434..8a957494ce9 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -44,3 +44,31 @@ extern UINT WM_MSIME_RECONVERTREQUEST; extern UINT WM_MSIME_RECONVERT; extern UINT WM_MSIME_QUERYPOSITION; extern UINT WM_MSIME_DOCUMENTFEED; + +static const char *debugstr_wm_ime( UINT msg ) +{ + switch (msg) + { + case WM_IME_STARTCOMPOSITION: return "WM_IME_STARTCOMPOSITION"; + case WM_IME_ENDCOMPOSITION: return "WM_IME_ENDCOMPOSITION"; + case WM_IME_COMPOSITION: return "WM_IME_COMPOSITION"; + case WM_IME_SETCONTEXT: return "WM_IME_SETCONTEXT"; + case WM_IME_NOTIFY: return "WM_IME_NOTIFY"; + case WM_IME_CONTROL: return "WM_IME_CONTROL"; + case WM_IME_COMPOSITIONFULL: return "WM_IME_COMPOSITIONFULL"; + case WM_IME_SELECT: return "WM_IME_SELECT"; + case WM_IME_CHAR: return "WM_IME_CHAR"; + case WM_IME_REQUEST: return "WM_IME_REQUEST"; + case WM_IME_KEYDOWN: return "WM_IME_KEYDOWN"; + case WM_IME_KEYUP: return "WM_IME_KEYUP"; + default: + if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; + else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; + else if (msg == WM_MSIME_MOUSE) return "WM_MSIME_MOUSE"; + else if (msg == WM_MSIME_RECONVERTREQUEST) return "WM_MSIME_RECONVERTREQUEST"; + else if (msg == WM_MSIME_RECONVERT) return "WM_MSIME_RECONVERT"; + else if (msg == WM_MSIME_QUERYPOSITION) return "WM_MSIME_QUERYPOSITION"; + else if (msg == WM_MSIME_DOCUMENTFEED) return "WM_MSIME_DOCUMENTFEED"; + return wine_dbg_sprintf( "%#x", msg ); + } +}
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 1ee2eec84d9..ae29a83fc66 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -246,7 +246,6 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); INPUTCONTEXT *ctx; - LRESULT ret = 0;
TRACE( "hwnd %p, himc %p, msg %s, wparam %#Ix, lparam %#Ix\n", hwnd, himc, debugstr_wm_ime(msg), wparam, lparam ); @@ -288,8 +287,6 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP case WM_PAINT: ime_ui_paint( himc, hwnd ); return FALSE; - case WM_NCCREATE: - return TRUE; case WM_SETFOCUS: if (wparam) SetFocus( (HWND)wparam ); else FIXME( "Received focus, should never have focus\n" ); @@ -313,12 +310,7 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return 1; }
- /* DefWndProc if not an IME message */ - if (!ret && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || - (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) - ret = DefWindowProcW( hwnd, msg, wparam, lparam ); - - return ret; + return DefWindowProcW( hwnd, msg, wparam, lparam ); }
static WNDCLASSEXW ime_ui_class =
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index ae29a83fc66..81ccb1cbd8e 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -250,23 +250,6 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP TRACE( "hwnd %p, himc %p, msg %s, wparam %#Ix, lparam %#Ix\n", hwnd, himc, debugstr_wm_ime(msg), wparam, lparam );
- /* if we have no himc there are many messages we cannot process */ - if (!himc) - { - switch (msg) - { - case WM_IME_STARTCOMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_COMPOSITION: - case WM_IME_NOTIFY: - case WM_IME_CONTROL: - case WM_IME_COMPOSITIONFULL: - case WM_IME_SELECT: - case WM_IME_CHAR: return 0L; - default: break; - } - } - switch (msg) { case WM_CREATE:
v2: Remove wine/ime.h for now, temporarily move the driver ime_private to ntuser.h instead.
Re-reading the comments I think I might have been slightly confused, but fwiw the PE->Unix calls are mostly just about passing ImmProcessKey to the drivers (and really just winemac at the moment).
Yes, I think the solution for Unix->PE is fine. Passing ImmProcessKey through win32u would need a bit of abuse, but I guess it could be something like `NtUserMessageCall( himc, IME_MSG_PROCESS_KEY, vkey, key_data, key_state, NtUserIMEMessage, FALSE )`. You could then have a single driver entry point like `LRESULT pProcessIMEMessage(void *handle, UINT msg, WPARAM wparam, LPARAM lparam, void *param)`, abstracting IME message details from core win32u.
I'm not sure what you mean by very integrated with win32u. Exposing builtin IMEs as "normal" IMEs is not affected by changes that I suggest. For driver interface, it would just replace one driver entry by another.