1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-09 04:16:08 +00:00

win32u: Move default IME window management from imm32.

This commit is contained in:
Jacek Caban 2022-07-09 01:17:54 +02:00 committed by Alexandre Julliard
parent f4f589c421
commit 047d74c4b1
17 changed files with 228 additions and 265 deletions

View File

@ -100,14 +100,6 @@ typedef struct _tagTRANSMSG {
LPARAM lParam;
} TRANSMSG, *LPTRANSMSG;
typedef struct _tagIMMThreadData {
struct list entry;
DWORD threadID;
HWND hwndDefault;
BOOL disableIME;
DWORD windowRefs;
} IMMThreadData;
struct coinit_spy
{
IInitializeSpy IInitializeSpy_iface;
@ -123,20 +115,9 @@ struct coinit_spy
};
static struct list ImmHklList = LIST_INIT(ImmHklList);
static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
static const WCHAR szImeRegFmt[] = L"System\\CurrentControlSet\\Control\\Keyboard Layouts\\%08lx";
static CRITICAL_SECTION threaddata_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &threaddata_cs,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
};
static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
static BOOL disable_ime;
static inline BOOL is_himc_ime_unicode(const InputContextData *data)
{
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
@ -412,38 +393,6 @@ static void imm_coinit_thread(void)
spy->apt_flags |= IMM_APT_CREATED;
}
static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
{
IMMThreadData *data;
DWORD process;
if (hwnd)
{
if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
if (process != GetCurrentProcessId()) return NULL;
}
else if (thread)
{
HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread);
if (!h) return NULL;
process = GetProcessIdOfThread(h);
CloseHandle(h);
if (process != GetCurrentProcessId()) return NULL;
}
else
thread = GetCurrentThreadId();
EnterCriticalSection(&threaddata_cs);
LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
if (data->threadID == thread) return data;
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
data->threadID = thread;
list_add_head(&ImmThreadDataList,&data->entry);
TRACE("Thread Data Created (%lx)\n",thread);
return data;
}
static BOOL IMM_IsDefaultContext(HIMC imc)
{
InputContextData *data = get_imc_data(imc);
@ -490,21 +439,6 @@ static BOOL free_input_context_data(HIMC hIMC)
static void IMM_FreeThreadData(void)
{
struct coinit_spy *spy;
IMMThreadData *data;
EnterCriticalSection(&threaddata_cs);
LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
{
if (data->threadID == GetCurrentThreadId())
{
list_remove(&data->entry);
LeaveCriticalSection(&threaddata_cs);
HeapFree(GetProcessHeap(),0,data);
TRACE("Thread Data Destroyed\n");
return;
}
}
LeaveCriticalSection(&threaddata_cs);
free_input_context_data(NtUserGetThreadInfo()->default_imc);
if ((spy = get_thread_coinit_spy()))
@ -981,62 +915,6 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
return FALSE;
}
static HWND imm_detach_default_window(IMMThreadData *thread_data)
{
HWND to_destroy;
to_destroy = thread_data->hwndDefault;
thread_data->hwndDefault = NULL;
thread_data->windowRefs = 0;
return to_destroy;
}
/***********************************************************************
* ImmDisableIME (IMM32.@)
*/
BOOL WINAPI ImmDisableIME(DWORD idThread)
{
IMMThreadData *thread_data;
HWND to_destroy;
if (idThread == (DWORD)-1)
{
disable_ime = TRUE;
while (1)
{
to_destroy = 0;
EnterCriticalSection(&threaddata_cs);
LIST_FOR_EACH_ENTRY(thread_data, &ImmThreadDataList, IMMThreadData, entry)
{
if (thread_data->hwndDefault)
{
to_destroy = imm_detach_default_window(thread_data);
break;
}
}
LeaveCriticalSection(&threaddata_cs);
if (!to_destroy)
break;
DestroyWindow(to_destroy);
}
}
else if (!idThread || idThread == GetCurrentThreadId())
{
thread_data = IMM_GetThreadData(NULL, idThread);
if (!thread_data) return FALSE;
thread_data->disableIME = TRUE;
to_destroy = imm_detach_default_window(thread_data);
LeaveCriticalSection(&threaddata_cs);
if (to_destroy)
DestroyWindow(to_destroy);
}
else return FALSE;
return TRUE;
}
/***********************************************************************
* ImmEnumRegisterWordA (IMM32.@)
*/
@ -1816,107 +1694,12 @@ BOOL WINAPI ImmGetConversionStatus(
return TRUE;
}
static BOOL needs_ime_window(HWND hwnd)
{
WCHAR classW[8];
if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !lstrcmpW(classW, L"IME"))
return FALSE;
if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
return TRUE;
}
/***********************************************************************
* __wine_register_window (IMM32.@)
*/
BOOL WINAPI __wine_register_window(HWND hwnd)
{
HWND new = NULL;
IMMThreadData *thread_data;
TRACE("(%p)\n", hwnd);
if (!needs_ime_window(hwnd))
return FALSE;
thread_data = IMM_GetThreadData(hwnd, 0);
if (!thread_data)
return FALSE;
if (thread_data->disableIME || disable_ime)
{
TRACE("IME for this thread is disabled\n");
LeaveCriticalSection(&threaddata_cs);
return FALSE;
}
thread_data->windowRefs++;
TRACE("windowRefs=%lu, hwndDefault=%p\n",
thread_data->windowRefs, thread_data->hwndDefault);
/* Create default IME window */
if (thread_data->windowRefs == 1)
{
/* Do not create the window inside of a critical section */
LeaveCriticalSection(&threaddata_cs);
new = CreateWindowExW( 0, L"IME", L"Default IME",
WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
0, 0, 1, 1, 0, 0, 0, 0);
/* thread_data is in the current thread so we can assume it's still valid */
EnterCriticalSection(&threaddata_cs);
/* See if anyone beat us */
if (thread_data->hwndDefault == NULL)
{
thread_data->hwndDefault = new;
new = NULL;
TRACE("Default is %p\n", thread_data->hwndDefault);
}
}
LeaveCriticalSection(&threaddata_cs);
/* Clean up an unused new window outside of the critical section */
if (new != NULL)
DestroyWindow(new);
return TRUE;
}
/***********************************************************************
* __wine_unregister_window (IMM32.@)
*/
void WINAPI __wine_unregister_window(HWND hwnd)
{
HWND to_destroy = 0;
IMMThreadData *thread_data;
TRACE("(%p)\n", hwnd);
thread_data = IMM_GetThreadData(hwnd, 0);
if (!thread_data) return;
thread_data->windowRefs--;
TRACE("windowRefs=%lu, hwndDefault=%p\n",
thread_data->windowRefs, thread_data->hwndDefault);
/* Destroy default IME window */
if (thread_data->windowRefs == 0)
to_destroy = imm_detach_default_window(thread_data);
LeaveCriticalSection(&threaddata_cs);
if (to_destroy) DestroyWindow( to_destroy );
}
/***********************************************************************
* ImmGetDefaultIMEWnd (IMM32.@)
*/
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
{
HWND ret;
IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
if (!thread_data)
return NULL;
ret = thread_data->hwndDefault;
LeaveCriticalSection(&threaddata_cs);
TRACE("Default is %p\n",ret);
return ret;
return NtUserGetDefaultImeWindow(hWnd);
}
/***********************************************************************

View File

@ -9,8 +9,8 @@
@ stdcall ImmDestroyContext(long)
@ stdcall ImmDestroyIMCC(long)
@ stdcall ImmDestroySoftKeyboard(long)
@ stdcall ImmDisableIME(long)
@ stdcall ImmDisableIme(long) ImmDisableIME
@ stdcall ImmDisableIME(long) NtUserDisableThreadIme
@ stdcall ImmDisableIme(long) NtUserDisableThreadIme
@ stdcall ImmDisableLegacyIME()
@ stdcall ImmDisableTextFrameService(long)
@ stdcall ImmEnumInputContext(long ptr long)
@ -115,5 +115,3 @@
################################################################
# Wine internal extensions
@ stdcall __wine_ime_wnd_proc(long long long long long)
@ stdcall __wine_register_window(long)
@ stdcall __wine_unregister_window(long)

View File

@ -2426,11 +2426,9 @@ static void test_ImmDisableIME(void)
ok(IsWindow(def), "not a window\n");
def2 = ImmGetDefaultIMEWnd(hwnd);
todo_wine
ok(def2 == def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def2);
ok(IsWindow(def), "not a window\n");
msg_spy_pump_msg_queue();
todo_wine
ok(!IsWindow(def), "window is still valid\n");
def = ImmGetDefaultIMEWnd(hwnd);
ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);

View File

@ -39,8 +39,6 @@ BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL);
#define IMM_INIT_MAGIC 0x19650412
static LRESULT (WINAPI *imm_ime_wnd_proc)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi);
BOOL (WINAPI *imm_register_window)(HWND) = NULL;
void (WINAPI *imm_unregister_window)(HWND) = NULL;
/* USER signal proc flags and codes */
/* See UserSignalProc for comments */
@ -328,8 +326,6 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
/* this part is not compatible with native imm32.dll */
imm_ime_wnd_proc = (void*)GetProcAddress(imm32, "__wine_ime_wnd_proc");
imm_register_window = (void*)GetProcAddress(imm32, "__wine_register_window");
imm_unregister_window = (void*)GetProcAddress(imm32, "__wine_unregister_window");
if (!imm_ime_wnd_proc)
FIXME("native imm32.dll not supported\n");
return TRUE;

View File

@ -119,22 +119,6 @@ static void dpiaware_init(void)
}
}
static void CDECL notify_ime( HWND hwnd, UINT param )
{
HWND ime_default = ImmGetDefaultIMEWnd( hwnd );
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
}
static BOOL WINAPI register_imm( HWND hwnd )
{
return imm_register_window( hwnd );
}
static void WINAPI unregister_imm( HWND hwnd )
{
imm_unregister_window( hwnd );
}
static NTSTATUS try_finally( NTSTATUS (CDECL *func)( void *), void *arg,
void (CALLBACK *finally_func)( BOOL ))
{
@ -152,11 +136,8 @@ static const struct user_callbacks user_funcs =
ImmProcessKey,
ImmTranslateMessage,
NtWaitForMultipleObjects,
notify_ime,
post_dde_message,
unpack_dde_message,
register_imm,
unregister_imm,
try_finally,
};

View File

@ -47,9 +47,6 @@ struct wm_char_mapping_data
MSG get_msg;
};
extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN;
extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
static inline struct user_thread_info *get_user_thread_info(void)
{
return (struct user_thread_info *)NtCurrentTeb()->Win32ClientInfo;

View File

@ -1007,6 +1007,18 @@ WORD get_class_word( HWND hwnd, INT offset )
return retvalue;
}
BOOL needs_ime_window( HWND hwnd )
{
static const WCHAR imeW[] = {'I','M','E',0};
CLASS *class;
BOOL ret;
if (!(class = get_class_ptr( hwnd, FALSE ))) return FALSE;
ret = !(class->style & CS_IME) && wcscmp( imeW, class->name );
release_class_ptr( class );
return ret;
}
static void register_builtins(void)
{
void *ret_ptr;

View File

@ -1157,6 +1157,7 @@ static struct unix_funcs unix_funcs =
NtUserDestroyCursor,
NtUserDestroyMenu,
NtUserDestroyWindow,
NtUserDisableThreadIme,
NtUserDispatchMessage,
NtUserDragDetect,
NtUserDrawCaptionTemp,

View File

@ -1,6 +1,8 @@
/*
* Input Context implementation
*
* Copyright 1998 Patrik Stridvall
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
* Copyright 2022 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
@ -22,6 +24,7 @@
#pragma makedep unix
#endif
#include <pthread.h>
#include "win32u_private.h"
#include "ntuser_private.h"
#include "wine/debug.h"
@ -36,6 +39,18 @@ struct imc
UINT_PTR client_ptr;
};
struct imm_thread_data
{
struct list entry;
DWORD thread_id;
HWND default_hwnd;
BOOL disable_ime;
UINT window_cnt;
};
static struct list thread_data_list = LIST_INIT( thread_data_list );
static pthread_mutex_t imm_mutex = PTHREAD_MUTEX_INITIALIZER;
static BOOL disable_ime;
static struct imc *get_imc_ptr( HIMC handle )
{
@ -215,3 +230,164 @@ HIMC get_window_input_context( HWND hwnd )
release_win_ptr( win );
return ret;
}
static HWND detach_default_window( struct imm_thread_data *thread_data )
{
HWND hwnd = thread_data->default_hwnd;
thread_data->default_hwnd = NULL;
thread_data->window_cnt = 0;
return hwnd;
}
static struct imm_thread_data *get_imm_thread_data(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
if (!thread_info->imm_thread_data)
{
struct imm_thread_data *data;
if (!(data = calloc( 1, sizeof( *data )))) return NULL;
data->thread_id = GetCurrentThreadId();
pthread_mutex_lock( &imm_mutex );
list_add_tail( &thread_data_list, &data->entry );
pthread_mutex_unlock( &imm_mutex );
thread_info->imm_thread_data = data;
}
return thread_info->imm_thread_data;
}
BOOL register_imm_window( HWND hwnd )
{
struct imm_thread_data *thread_data;
TRACE( "(%p)\n", hwnd );
if (disable_ime || !needs_ime_window( hwnd ))
return FALSE;
thread_data = get_imm_thread_data();
if (!thread_data || thread_data->disable_ime)
return FALSE;
TRACE( "window_cnt=%u, default_hwnd=%p\n", thread_data->window_cnt + 1, thread_data->default_hwnd );
/* Create default IME window */
if (!thread_data->window_cnt++)
{
UNICODE_STRING class_name, name;
static const WCHAR imeW[] = {'I','M','E',0};
static const WCHAR default_imeW[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
RtlInitUnicodeString( &class_name, imeW );
RtlInitUnicodeString( &name, default_imeW );
thread_data->default_hwnd = NtUserCreateWindowEx( 0, &class_name, &class_name, &name,
WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, FALSE );
}
return TRUE;
}
void unregister_imm_window( HWND hwnd )
{
struct imm_thread_data *thread_data = get_user_thread_info()->imm_thread_data;
if (!thread_data) return;
if (thread_data->default_hwnd == hwnd)
{
detach_default_window( thread_data );
return;
}
if (!(win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)) return;
/* destroy default IME window */
TRACE( "unregister IME window for %p\n", hwnd );
if (!--thread_data->window_cnt)
{
HWND destroy_hwnd = detach_default_window( thread_data );
if (destroy_hwnd) NtUserDestroyWindow( destroy_hwnd );
}
}
/***********************************************************************
* NtUserDisableThreadIme (win32u.@)
*/
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id )
{
struct imm_thread_data *thread_data;
if (thread_id == -1)
{
disable_ime = TRUE;
pthread_mutex_lock( &imm_mutex );
LIST_FOR_EACH_ENTRY( thread_data, &thread_data_list, struct imm_thread_data, entry )
{
if (thread_data->thread_id == GetCurrentThreadId()) continue;
if (!thread_data->default_hwnd) continue;
NtUserMessageCall( thread_data->default_hwnd, WM_WINE_DESTROYWINDOW, 0, 0,
0, NtUserSendNotifyMessage, FALSE );
}
pthread_mutex_unlock( &imm_mutex );
}
else if (!thread_id || thread_id == GetCurrentThreadId())
{
if (!(thread_data = get_imm_thread_data())) return FALSE;
thread_data->disable_ime = TRUE;
}
else return FALSE;
if ((thread_data = get_user_thread_info()->imm_thread_data))
{
HWND destroy_hwnd = detach_default_window( thread_data );
NtUserDestroyWindow( destroy_hwnd );
}
return TRUE;
}
HWND get_default_ime_window( HWND hwnd )
{
struct imm_thread_data *thread_data;
HWND ret = 0;
if (hwnd)
{
DWORD thread_id;
if (!(thread_id = get_window_thread( hwnd, NULL ))) return 0;
pthread_mutex_lock( &imm_mutex );
LIST_FOR_EACH_ENTRY( thread_data, &thread_data_list, struct imm_thread_data, entry )
{
if (thread_data->thread_id != thread_id) continue;
ret = thread_data->default_hwnd;
break;
}
pthread_mutex_unlock( &imm_mutex );
}
else if ((thread_data = get_user_thread_info()->imm_thread_data))
{
ret = thread_data->default_hwnd;
}
TRACE( "default for %p is %p\n", hwnd, ret );
return ret;
}
void cleanup_imm_thread(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
if (thread_info->imm_thread_data)
{
pthread_mutex_lock( &imm_mutex );
list_remove( &thread_info->imm_thread_data->entry );
pthread_mutex_unlock( &imm_mutex );
free( thread_info->imm_thread_data );
thread_info->imm_thread_data = NULL;
}
NtUserDestroyInputContext( thread_info->client_info.default_imc );
}

View File

@ -1551,7 +1551,7 @@ HWND get_focus(void)
*/
static HWND set_focus_window( HWND hwnd )
{
HWND previous = 0;
HWND previous = 0, ime_hwnd;
BOOL ret;
SERVER_START_REQ( set_focus_window )
@ -1568,7 +1568,10 @@ static HWND set_focus_window( HWND hwnd )
{
send_message( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 );
if (user_callbacks) user_callbacks->notify_ime( previous, IME_INTERNAL_DEACTIVATE );
ime_hwnd = get_default_ime_window( previous );
if (ime_hwnd)
send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_DEACTIVATE,
HandleToUlong(previous) );
if (hwnd != get_focus()) return previous; /* changed by the message */
}
@ -1576,7 +1579,10 @@ static HWND set_focus_window( HWND hwnd )
{
user_driver->pSetFocus(hwnd);
if (user_callbacks) user_callbacks->notify_ime( hwnd, IME_INTERNAL_ACTIVATE );
ime_hwnd = get_default_ime_window( hwnd );
if (ime_hwnd)
send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_ACTIVATE,
HandleToUlong(hwnd) );
if (previous)
NtUserNotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 );

View File

@ -35,13 +35,10 @@ struct user_callbacks
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
void (CDECL *notify_ime)( HWND hwnd, UINT param );
BOOL (CDECL *post_dde_message)( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid,
DWORD type );
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size );
BOOL (WINAPI *register_imm)( HWND hwnd );
void (WINAPI *unregister_imm)( HWND hwnd );
NTSTATUS (CDECL *try_finally)( NTSTATUS (CDECL *func)( void *), void *arg,
void (CALLBACK *finally_func)( BOOL ));
};
@ -154,6 +151,7 @@ struct user_thread_info
struct received_message_info *receive_info; /* Message being currently received */
struct wm_char_mapping_data *wmchar_data; /* Data for WM_CHAR mappings */
struct user_key_state_info *key_state; /* Cache of global key state */
struct imm_thread_data *imm_thread_data; /* IMM thread data */
HKL kbd_layout; /* Current keyboard layout */
DWORD kbd_layout_id; /* Current keyboard layout ID */
struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
@ -273,6 +271,7 @@ WNDPROC get_winproc( WNDPROC proc, BOOL ansi ) DECLSPEC_HIDDEN;
void get_winproc_params( struct win_proc_params *params ) DECLSPEC_HIDDEN;
struct dce *get_class_dce( struct tagCLASS *class ) DECLSPEC_HIDDEN;
struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ) DECLSPEC_HIDDEN;
BOOL needs_ime_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern void register_builtin_classes(void) DECLSPEC_HIDDEN;
/* cursoricon.c */

View File

@ -4818,7 +4818,7 @@ static void thread_detach(void)
free( thread_info->rawinput );
destroy_thread_windows();
NtUserDestroyInputContext( thread_info->client_info.default_imc );
cleanup_imm_thread();
NtClose( thread_info->server_queue );
exiting_thread_id = 0;

View File

@ -837,7 +837,7 @@
@ stdcall NtUserDestroyWindow(long)
@ stub NtUserDisableImmersiveOwner
@ stub NtUserDisableProcessWindowFiltering
@ stub NtUserDisableThreadIme
@ stdcall NtUserDisableThreadIme(long)
@ stub NtUserDiscardPointerFrameMessages
@ stdcall NtUserDispatchMessage(ptr)
@ stub NtUserDisplayConfigGetDeviceInfo

View File

@ -214,6 +214,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
BOOL (WINAPI *pNtUserDestroyMenu)( HMENU handle );
BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd );
BOOL (WINAPI *pNtUserDisableThreadIme)( DWORD thread_id );
LRESULT (WINAPI *pNtUserDispatchMessage)( const MSG *msg );
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
BOOL (WINAPI *pNtUserDrawCaptionTemp)( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
@ -393,8 +394,12 @@ extern LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL
extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
/* imm.c */
extern void cleanup_imm_thread(void) DECLSPEC_HIDDEN;
extern HWND get_default_ime_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HIMC get_default_input_context(void) DECLSPEC_HIDDEN;
extern HIMC get_window_input_context( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL register_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern void unregister_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
/* input.c */
extern BOOL destroy_caret(void) DECLSPEC_HIDDEN;

View File

@ -4680,12 +4680,7 @@ LRESULT destroy_window( HWND hwnd )
TRACE( "%p\n", hwnd );
/* destroy default IME window */
if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)
{
TRACE("unregister IME window for %p\n", hwnd);
if (user_callbacks) user_callbacks->unregister_imm( hwnd );
}
unregister_imm_window( hwnd );
/* free child windows */
if ((children = list_window_children( 0, hwnd, NULL, 0 )))
@ -5262,7 +5257,7 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name,
/* create default IME window */
if (!is_desktop_window( hwnd ) && parent != get_hwnd_message_parent() &&
user_callbacks && user_callbacks->register_imm( hwnd ))
register_imm_window( hwnd ))
{
TRACE( "register IME window for %p\n", hwnd );
win_set_flags( hwnd, WIN_HAS_IME_WIN, 0 );
@ -5377,6 +5372,9 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
case NtUserCallHwnd_DrawMenuBar:
return draw_menu_bar( hwnd );
case NtUserCallHwnd_GetDefaultImeWindow:
return HandleToUlong( get_default_ime_window( hwnd ));
case NtUserCallHwnd_GetDpiForWindow:
return get_dpi_for_window( hwnd );

View File

@ -849,6 +849,12 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
return unix_funcs->pNtUserDestroyWindow( hwnd );
}
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserDisableThreadIme( thread_id );
}
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
{
if (!unix_funcs) return 0;

View File

@ -599,6 +599,7 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
BOOL WINAPI NtUserDestroyInputContext( HIMC handle );
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
BOOL WINAPI NtUserDisableThreadIme( DWORD thread_id );
LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
BOOL WINAPI NtUserDrawCaptionTemp( HWND hwnd, HDC hdc, const RECT *rect, HFONT font,
@ -1055,6 +1056,7 @@ enum
{
NtUserCallHwnd_ArrangeIconicWindows,
NtUserCallHwnd_DrawMenuBar,
NtUserCallHwnd_GetDefaultImeWindow,
NtUserCallHwnd_GetDpiForWindow,
NtUserCallHwnd_GetParent,
NtUserCallHwnd_GetWindowContextHelpId,
@ -1083,6 +1085,11 @@ static inline DWORD NtUserGetWindowContextHelpId( HWND hwnd )
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetWindowContextHelpId );
}
static inline HWND NtUserGetDefaultImeWindow( HWND hwnd )
{
return UlongToHandle( NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDefaultImeWindow ));
}
static inline UINT NtUserGetDpiForWindow( HWND hwnd )
{
return NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDpiForWindow );