win32u: Move ImeToAsciiEx implementation from winex11.
Using a new WINE_IME_POST_UPDATE NtUserMessageCall call for the drivers.
This commit is contained in:
parent
59820f0efb
commit
5f313c0fdb
7 changed files with 149 additions and 151 deletions
|
@ -731,7 +731,7 @@ static UINT nulldrv_ImeProcessKey( HIMC himc, UINT wparam, UINT lparam, const BY
|
|||
|
||||
static UINT nulldrv_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc )
|
||||
{
|
||||
return 0;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static void nulldrv_NotifyIMEStatus( HWND hwnd, UINT status )
|
||||
|
|
|
@ -34,6 +34,15 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
struct ime_update
|
||||
{
|
||||
struct list entry;
|
||||
DWORD id;
|
||||
DWORD cursor_pos;
|
||||
WCHAR *comp_str;
|
||||
WCHAR *result_str;
|
||||
WCHAR buffer[];
|
||||
};
|
||||
|
||||
struct imc
|
||||
{
|
||||
|
@ -53,6 +62,7 @@ struct imm_thread_data
|
|||
|
||||
static struct list thread_data_list = LIST_INIT( thread_data_list );
|
||||
static pthread_mutex_t imm_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct list ime_updates = LIST_INIT( ime_updates );
|
||||
static BOOL disable_ime;
|
||||
|
||||
static struct imc *get_imc_ptr( HIMC handle )
|
||||
|
@ -421,15 +431,147 @@ NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, U
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void post_ime_update( HWND hwnd, UINT cursor_pos, WCHAR *comp_str, WCHAR *result_str )
|
||||
{
|
||||
static UINT ime_update_count;
|
||||
UINT id, comp_len, result_len;
|
||||
struct ime_update *update;
|
||||
|
||||
TRACE( "hwnd %p, cursor_pos %u, comp_str %s, result_str %s\n", hwnd, cursor_pos,
|
||||
debugstr_w(comp_str), debugstr_w(result_str) );
|
||||
|
||||
comp_len = comp_str ? wcslen( comp_str ) + 1 : 0;
|
||||
result_len = result_str ? wcslen( result_str ) + 1 : 0;
|
||||
|
||||
if (!(update = malloc( offsetof(struct ime_update, buffer[comp_len + result_len]) ))) return;
|
||||
update->cursor_pos = cursor_pos;
|
||||
update->comp_str = comp_str ? memcpy( update->buffer, comp_str, comp_len * sizeof(WCHAR) ) : NULL;
|
||||
update->result_str = result_str ? memcpy( update->buffer + comp_len, result_str, result_len * sizeof(WCHAR) ) : NULL;
|
||||
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
id = update->id = ++ime_update_count;
|
||||
list_add_tail( &ime_updates, &update->entry );
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
|
||||
NtUserPostMessage( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_COMP_STRING, id );
|
||||
}
|
||||
|
||||
static struct ime_update *find_ime_update( UINT id )
|
||||
{
|
||||
struct ime_update *update;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( update, &ime_updates, struct ime_update, entry )
|
||||
if (update->id == id) return update;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT ime_to_tascii_ex( UINT vkey, UINT lparam, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc )
|
||||
{
|
||||
UINT needed = sizeof(COMPOSITIONSTRING), comp_len, result_len;
|
||||
struct ime_update *update;
|
||||
void *dst;
|
||||
|
||||
TRACE( "vkey %#x, lparam %#x, state %p, compstr %p, himc %p\n", vkey, lparam, state, compstr, himc );
|
||||
|
||||
pthread_mutex_lock( &imm_mutex );
|
||||
|
||||
if (!(update = find_ime_update( lparam )))
|
||||
{
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!update->comp_str) comp_len = 0;
|
||||
else
|
||||
{
|
||||
comp_len = wcslen( update->comp_str );
|
||||
needed += comp_len * sizeof(WCHAR); /* GCS_COMPSTR */
|
||||
needed += comp_len; /* GCS_COMPATTR */
|
||||
needed += 2 * sizeof(DWORD); /* GCS_COMPCLAUSE */
|
||||
}
|
||||
|
||||
if (!update->result_str) result_len = 0;
|
||||
else
|
||||
{
|
||||
result_len = wcslen( update->result_str );
|
||||
needed += result_len * sizeof(WCHAR); /* GCS_RESULTSTR */
|
||||
needed += 2 * sizeof(DWORD); /* GCS_RESULTCLAUSE */
|
||||
}
|
||||
|
||||
if (compstr->dwSize < needed)
|
||||
{
|
||||
compstr->dwSize = needed;
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
list_remove( &update->entry );
|
||||
pthread_mutex_unlock( &imm_mutex );
|
||||
|
||||
memset( compstr, 0, sizeof(*compstr) );
|
||||
compstr->dwSize = sizeof(*compstr);
|
||||
|
||||
if (update->comp_str)
|
||||
{
|
||||
compstr->dwCursorPos = update->cursor_pos;
|
||||
|
||||
compstr->dwCompStrLen = comp_len;
|
||||
compstr->dwCompStrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompStrOffset;
|
||||
memcpy( dst, update->comp_str, compstr->dwCompStrLen * sizeof(WCHAR) );
|
||||
compstr->dwSize += compstr->dwCompStrLen * sizeof(WCHAR);
|
||||
|
||||
compstr->dwCompClauseLen = 2 * sizeof(DWORD);
|
||||
compstr->dwCompClauseOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompClauseOffset;
|
||||
*((DWORD *)dst + 0) = 0;
|
||||
*((DWORD *)dst + 1) = compstr->dwCompStrLen;
|
||||
compstr->dwSize += compstr->dwCompClauseLen;
|
||||
|
||||
compstr->dwCompAttrLen = compstr->dwCompStrLen;
|
||||
compstr->dwCompAttrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompAttrOffset;
|
||||
memset( dst, ATTR_INPUT, compstr->dwCompAttrLen );
|
||||
compstr->dwSize += compstr->dwCompAttrLen;
|
||||
}
|
||||
|
||||
if (update->result_str)
|
||||
{
|
||||
compstr->dwResultStrLen = result_len;
|
||||
compstr->dwResultStrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwResultStrOffset;
|
||||
memcpy( dst, update->result_str, compstr->dwResultStrLen * sizeof(WCHAR) );
|
||||
compstr->dwSize += compstr->dwResultStrLen * sizeof(WCHAR);
|
||||
|
||||
compstr->dwResultClauseLen = 2 * sizeof(DWORD);
|
||||
compstr->dwResultClauseOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwResultClauseOffset;
|
||||
*((DWORD *)dst + 0) = 0;
|
||||
*((DWORD *)dst + 1) = compstr->dwResultStrLen;
|
||||
compstr->dwSize += compstr->dwResultClauseLen;
|
||||
}
|
||||
|
||||
free( update );
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPARAM lparam,
|
||||
struct ime_driver_call_params *params )
|
||||
{
|
||||
LRESULT res;
|
||||
|
||||
switch (call)
|
||||
{
|
||||
case WINE_IME_PROCESS_KEY:
|
||||
return user_driver->pImeProcessKey( params->himc, wparam, lparam, params->state );
|
||||
case WINE_IME_TO_ASCII_EX:
|
||||
return user_driver->pImeToAsciiEx( wparam, lparam, params->state, params->compstr, params->himc );
|
||||
res = user_driver->pImeToAsciiEx( wparam, lparam, params->state, params->compstr, params->himc );
|
||||
if ((NTSTATUS)res != STATUS_NOT_IMPLEMENTED) return res;
|
||||
return ime_to_tascii_ex( wparam, lparam, params->state, params->compstr, params->himc );
|
||||
case WINE_IME_POST_UPDATE:
|
||||
post_ime_update( hwnd, wparam, (WCHAR *)lparam, (WCHAR *)params );
|
||||
return 0;
|
||||
default:
|
||||
ERR( "Unknown IME driver call %#x\n", call );
|
||||
return 0;
|
||||
|
|
|
@ -397,7 +397,6 @@ static const struct user_driver_funcs x11drv_funcs =
|
|||
.pMapVirtualKeyEx = X11DRV_MapVirtualKeyEx,
|
||||
.pToUnicodeEx = X11DRV_ToUnicodeEx,
|
||||
.pVkKeyScanEx = X11DRV_VkKeyScanEx,
|
||||
.pImeToAsciiEx = X11DRV_ImeToAsciiEx,
|
||||
.pNotifyIMEStatus = X11DRV_NotifyIMEStatus,
|
||||
.pDestroyCursorIcon = X11DRV_DestroyCursorIcon,
|
||||
.pSetCursor = X11DRV_SetCursor,
|
||||
|
|
|
@ -208,8 +208,6 @@ extern INT X11DRV_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size );
|
|||
extern UINT X11DRV_MapVirtualKeyEx( UINT code, UINT map_type, HKL hkl );
|
||||
extern INT X11DRV_ToUnicodeEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
|
||||
LPWSTR bufW, int bufW_size, UINT flags, HKL hkl );
|
||||
extern UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state,
|
||||
COMPOSITIONSTRING *compstr, HIMC himc );
|
||||
extern SHORT X11DRV_VkKeyScanEx( WCHAR wChar, HKL hkl );
|
||||
extern void X11DRV_NotifyIMEStatus( HWND hwnd, UINT status );
|
||||
extern void X11DRV_DestroyCursorIcon( HCURSOR handle );
|
||||
|
|
|
@ -44,19 +44,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim);
|
|||
#define XICProc XIMProc
|
||||
#endif
|
||||
|
||||
struct ime_update
|
||||
{
|
||||
struct list entry;
|
||||
DWORD id;
|
||||
DWORD cursor_pos;
|
||||
WCHAR *comp_str;
|
||||
WCHAR *result_str;
|
||||
WCHAR buffer[];
|
||||
};
|
||||
|
||||
static pthread_mutex_t ime_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct list ime_updates = LIST_INIT(ime_updates);
|
||||
static DWORD ime_update_count;
|
||||
static WCHAR *ime_comp_buf;
|
||||
|
||||
static XIMStyle input_style = 0;
|
||||
|
@ -89,23 +76,8 @@ BOOL xim_in_compose_mode(void)
|
|||
|
||||
static void post_ime_update( HWND hwnd, UINT cursor_pos, WCHAR *comp_str, WCHAR *result_str )
|
||||
{
|
||||
UINT id, comp_len, result_len;
|
||||
struct ime_update *update;
|
||||
|
||||
comp_len = comp_str ? wcslen( comp_str ) + 1 : 0;
|
||||
result_len = result_str ? wcslen( result_str ) + 1 : 0;
|
||||
|
||||
if (!(update = malloc( offsetof(struct ime_update, buffer[comp_len + result_len]) ))) return;
|
||||
update->cursor_pos = cursor_pos;
|
||||
update->comp_str = comp_str ? memcpy( update->buffer, comp_str, comp_len * sizeof(WCHAR) ) : NULL;
|
||||
update->result_str = result_str ? memcpy( update->buffer + comp_len, result_str, result_len * sizeof(WCHAR) ) : NULL;
|
||||
|
||||
pthread_mutex_lock( &ime_mutex );
|
||||
id = update->id = ++ime_update_count;
|
||||
list_add_tail( &ime_updates, &update->entry );
|
||||
pthread_mutex_unlock( &ime_mutex );
|
||||
|
||||
NtUserPostMessage( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_COMP_STRING, id );
|
||||
NtUserMessageCall( hwnd, WINE_IME_POST_UPDATE, cursor_pos, (LPARAM)comp_str,
|
||||
result_str, NtUserImeDriverCall, FALSE );
|
||||
}
|
||||
|
||||
static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text, UINT new_len )
|
||||
|
@ -511,123 +483,8 @@ XIC X11DRV_get_ic( HWND hwnd )
|
|||
|
||||
void xim_set_focus( HWND hwnd, BOOL focus )
|
||||
{
|
||||
struct list updates = LIST_INIT(updates);
|
||||
struct ime_update *update, *next;
|
||||
XIC xic;
|
||||
|
||||
if (!(xic = X11DRV_get_ic( hwnd ))) return;
|
||||
|
||||
if ((xic = X11DRV_get_ic( hwnd ))) return;
|
||||
if (focus) XSetICFocus( xic );
|
||||
else XUnsetICFocus( xic );
|
||||
|
||||
pthread_mutex_lock( &ime_mutex );
|
||||
list_move_tail( &updates, &ime_updates );
|
||||
pthread_mutex_unlock( &ime_mutex );
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE( update, next, &updates, struct ime_update, entry ) free( update );
|
||||
}
|
||||
|
||||
static struct ime_update *find_ime_update( UINT id )
|
||||
{
|
||||
struct ime_update *update;
|
||||
LIST_FOR_EACH_ENTRY( update, &ime_updates, struct ime_update, entry )
|
||||
if (update->id == id) return update;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImeToAsciiEx (X11DRV.@)
|
||||
*
|
||||
* As XIM filters key events upfront, we don't use ImeProcessKey and ImeToAsciiEx is instead called
|
||||
* back from the IME UI window procedure when WM_IME_NOTIFY / IMN_WINE_SET_COMP_STRING messages are
|
||||
* sent to it, to retrieve composition string updates and generate WM_IME messages.
|
||||
*/
|
||||
UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT lparam, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc )
|
||||
{
|
||||
UINT needed = sizeof(COMPOSITIONSTRING), comp_len, result_len;
|
||||
struct ime_update *update;
|
||||
void *dst;
|
||||
|
||||
TRACE( "vkey %#x, lparam %#x, state %p, compstr %p, himc %p\n", vkey, lparam, state, compstr, himc );
|
||||
|
||||
pthread_mutex_lock( &ime_mutex );
|
||||
|
||||
if (!(update = find_ime_update( lparam )))
|
||||
{
|
||||
pthread_mutex_unlock( &ime_mutex );
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!update->comp_str) comp_len = 0;
|
||||
else
|
||||
{
|
||||
comp_len = wcslen( update->comp_str );
|
||||
needed += comp_len * sizeof(WCHAR); /* GCS_COMPSTR */
|
||||
needed += comp_len; /* GCS_COMPATTR */
|
||||
needed += 2 * sizeof(DWORD); /* GCS_COMPCLAUSE */
|
||||
}
|
||||
|
||||
if (!update->result_str) result_len = 0;
|
||||
else
|
||||
{
|
||||
result_len = wcslen( update->result_str );
|
||||
needed += result_len * sizeof(WCHAR); /* GCS_RESULTSTR */
|
||||
needed += 2 * sizeof(DWORD); /* GCS_RESULTCLAUSE */
|
||||
}
|
||||
|
||||
if (compstr->dwSize < needed)
|
||||
{
|
||||
compstr->dwSize = needed;
|
||||
pthread_mutex_unlock( &ime_mutex );
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
list_remove( &update->entry );
|
||||
pthread_mutex_unlock( &ime_mutex );
|
||||
|
||||
memset( compstr, 0, sizeof(*compstr) );
|
||||
compstr->dwSize = sizeof(*compstr);
|
||||
|
||||
if (update->comp_str)
|
||||
{
|
||||
compstr->dwCursorPos = update->cursor_pos;
|
||||
|
||||
compstr->dwCompStrLen = comp_len;
|
||||
compstr->dwCompStrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompStrOffset;
|
||||
memcpy( dst, update->comp_str, compstr->dwCompStrLen * sizeof(WCHAR) );
|
||||
compstr->dwSize += compstr->dwCompStrLen * sizeof(WCHAR);
|
||||
|
||||
compstr->dwCompClauseLen = 2 * sizeof(DWORD);
|
||||
compstr->dwCompClauseOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompClauseOffset;
|
||||
*((DWORD *)dst + 0) = 0;
|
||||
*((DWORD *)dst + 1) = compstr->dwCompStrLen;
|
||||
compstr->dwSize += compstr->dwCompClauseLen;
|
||||
|
||||
compstr->dwCompAttrLen = compstr->dwCompStrLen;
|
||||
compstr->dwCompAttrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwCompAttrOffset;
|
||||
memset( dst, ATTR_INPUT, compstr->dwCompAttrLen );
|
||||
compstr->dwSize += compstr->dwCompAttrLen;
|
||||
}
|
||||
|
||||
if (update->result_str)
|
||||
{
|
||||
compstr->dwResultStrLen = result_len;
|
||||
compstr->dwResultStrOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwResultStrOffset;
|
||||
memcpy( dst, update->result_str, compstr->dwResultStrLen * sizeof(WCHAR) );
|
||||
compstr->dwSize += compstr->dwResultStrLen * sizeof(WCHAR);
|
||||
|
||||
compstr->dwResultClauseLen = 2 * sizeof(DWORD);
|
||||
compstr->dwResultClauseOffset = compstr->dwSize;
|
||||
dst = (BYTE *)compstr + compstr->dwResultClauseOffset;
|
||||
*((DWORD *)dst + 0) = 0;
|
||||
*((DWORD *)dst + 1) = compstr->dwResultStrLen;
|
||||
compstr->dwSize += compstr->dwResultClauseLen;
|
||||
}
|
||||
|
||||
free( update );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3597,6 +3597,7 @@ NTSTATUS WINAPI wow64_NtUserMessageCall( UINT *args )
|
|||
ULONG compstr;
|
||||
} *params32 = result_info;
|
||||
struct ime_driver_call_params params;
|
||||
if (msg == WINE_IME_POST_UPDATE) ERR( "Unexpected WINE_IME_POST_UPDATE message\n" );
|
||||
params.himc = UlongToPtr( params32->himc );
|
||||
params.state = UlongToPtr( params32->state );
|
||||
params.compstr = UlongToPtr( params32->compstr );
|
||||
|
|
|
@ -511,6 +511,7 @@ enum wine_ime_call
|
|||
{
|
||||
WINE_IME_PROCESS_KEY,
|
||||
WINE_IME_TO_ASCII_EX,
|
||||
WINE_IME_POST_UPDATE, /* for the user drivers */
|
||||
};
|
||||
|
||||
/* NtUserImeDriverCall params */
|
||||
|
|
Loading…
Add table
Reference in a new issue