[PATCH 09/13] win32u: Move NtUserTranslateAccelerator from user32.
Jacek Caban
wine at gitlab.winehq.org
Mon May 2 05:44:42 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/user32/menu.c | 204 +------------------------
dlls/user32/user32.spec | 2 +-
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/menu.c | 279 +++++++++++++++++++++++++++++++++++
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/wrappers.c | 6 +
7 files changed, 291 insertions(+), 204 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 9f51fa555f8..669d838bf61 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -56,7 +56,6 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(menu);
-WINE_DECLARE_DEBUG_CHANNEL(accel);
/* internal flags for menu tracking */
@@ -4768,170 +4767,6 @@ DWORD WINAPI CalcMenuBar(HWND hwnd, DWORD left, DWORD right, DWORD top, RECT *re
}
-/**********************************************************************
- * translate_accelerator
- */
-static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
- BYTE fVirt, WORD key, WORD cmd )
-{
- INT mask = 0;
- UINT mesg = 0;
-
- if (wParam != key) return FALSE;
-
- if (NtUserGetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
- if (NtUserGetKeyState(VK_MENU) & 0x8000) mask |= FALT;
- if (NtUserGetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
-
- if (message == WM_CHAR || message == WM_SYSCHAR)
- {
- if ( !(fVirt & FVIRTKEY) && (mask & FALT) == (fVirt & FALT) )
- {
- TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", LOWORD(wParam) & 0xff);
- goto found;
- }
- }
- else
- {
- if(fVirt & FVIRTKEY)
- {
- TRACE_(accel)("found accel for virt_key %04lx (scan %04x)\n",
- wParam, 0xff & HIWORD(lParam));
-
- if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
- TRACE_(accel)(", but incorrect SHIFT/CTRL/ALT-state\n");
- }
- else
- {
- if (!(lParam & 0x01000000)) /* no special_key */
- {
- if ((fVirt & FALT) && (lParam & 0x20000000))
- { /* ^^ ALT pressed */
- TRACE_(accel)("found accel for Alt-%c\n", LOWORD(wParam) & 0xff);
- goto found;
- }
- }
- }
- }
- return FALSE;
-
- found:
- if (message == WM_KEYUP || message == WM_SYSKEYUP)
- mesg = 1;
- else
- {
- HMENU hMenu, hSubMenu, hSysMenu;
- UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
- POPUPMENU *menu;
-
- hMenu = (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD) ? 0 : GetMenu(hWnd);
- hSysMenu = get_win_sys_menu( hWnd );
-
- /* find menu item and ask application to initialize it */
- /* 1. in the system menu */
- if ((menu = find_menu_item(hSysMenu, cmd, MF_BYCOMMAND, NULL)))
- {
- hSubMenu = menu->obj.handle;
- release_menu_ptr(menu);
-
- if (GetCapture())
- mesg = 2;
- if (!IsWindowEnabled(hWnd))
- mesg = 3;
- else
- {
- SendMessageW(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L);
- if(hSubMenu != hSysMenu)
- {
- nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu);
- TRACE_(accel)("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu, hSubMenu, nPos);
- SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
- }
- uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
- }
- }
- else /* 2. in the window's menu */
- {
- if ((menu = find_menu_item(hMenu, cmd, MF_BYCOMMAND, NULL)))
- {
- hSubMenu = menu->obj.handle;
- release_menu_ptr(menu);
-
- if (GetCapture())
- mesg = 2;
- if (!IsWindowEnabled(hWnd))
- mesg = 3;
- else
- {
- SendMessageW(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L);
- if(hSubMenu != hMenu)
- {
- nPos = MENU_FindSubMenu(&hMenu, hSubMenu);
- TRACE_(accel)("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu, hSubMenu, nPos);
- SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
- }
- uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
- }
- }
- }
-
- if (mesg == 0)
- {
- if (uSysStat != (UINT)-1)
- {
- if (uSysStat & (MF_DISABLED|MF_GRAYED))
- mesg=4;
- else
- mesg=WM_SYSCOMMAND;
- }
- else
- {
- if (uStat != (UINT)-1)
- {
- if (IsIconic(hWnd))
- mesg=5;
- else
- {
- if (uStat & (MF_DISABLED|MF_GRAYED))
- mesg=6;
- else
- mesg=WM_COMMAND;
- }
- }
- else
- mesg=WM_COMMAND;
- }
- }
- }
-
- if( mesg==WM_COMMAND )
- {
- TRACE_(accel)(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
- SendMessageW(hWnd, mesg, 0x10000 | cmd, 0L);
- }
- else if( mesg==WM_SYSCOMMAND )
- {
- TRACE_(accel)(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
- SendMessageW(hWnd, mesg, cmd, 0x00010000L);
- }
- else
- {
- /* some reasons for NOT sending the WM_{SYS}COMMAND message:
- * #0: unknown (please report!)
- * #1: for WM_KEYUP,WM_SYSKEYUP
- * #2: mouse is captured
- * #3: window is disabled
- * #4: it's a disabled system menu option
- * #5: it's a menu option, but window is iconic
- * #6: it's a menu option, but disabled
- */
- TRACE_(accel)(", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
- if(mesg==0)
- ERR_(accel)(" unknown reason - please report!\n");
- }
- return TRUE;
-}
-
/**********************************************************************
* TranslateAcceleratorA (USER32.@)
* TranslateAccelerator (USER32.@)
@@ -4942,7 +4777,7 @@ INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
- return TranslateAcceleratorW( hWnd, hAccel, msg );
+ return NtUserTranslateAccelerator( hWnd, hAccel, msg );
case WM_CHAR:
case WM_SYSCHAR:
@@ -4952,45 +4787,10 @@ INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
WCHAR wch;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
msgW.wParam = MAKEWPARAM(wch, HIWORD(msg->wParam));
- return TranslateAcceleratorW( hWnd, hAccel, &msgW );
+ return NtUserTranslateAccelerator( hWnd, hAccel, &msgW );
}
default:
return 0;
}
}
-
-/**********************************************************************
- * TranslateAcceleratorW (USER32.@)
- */
-INT WINAPI TranslateAcceleratorW( HWND hWnd, HACCEL hAccel, LPMSG msg )
-{
- ACCEL data[32], *ptr = data;
- int i, count;
-
- if (!hWnd) return 0;
-
- if (msg->message != WM_KEYDOWN &&
- msg->message != WM_SYSKEYDOWN &&
- msg->message != WM_CHAR &&
- msg->message != WM_SYSCHAR)
- return 0;
-
- TRACE_(accel)("hAccel %p, hWnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
- hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
-
- if (!(count = NtUserCopyAcceleratorTable( hAccel, NULL, 0 ))) return 0;
- if (count > ARRAY_SIZE( data ))
- {
- if (!(ptr = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ptr) ))) return 0;
- }
- count = NtUserCopyAcceleratorTable( hAccel, ptr, count );
- for (i = 0; i < count; i++)
- {
- if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
- ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
- break;
- }
- if (ptr != data) HeapFree( GetProcessHeap(), 0, ptr );
- return (i < count);
-}
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 298a0fa3150..26f2d1caf45 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -767,7 +767,7 @@
@ stdcall TrackPopupMenuEx(long long long long long ptr)
@ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA
@ stdcall TranslateAcceleratorA(long long ptr)
-@ stdcall TranslateAcceleratorW(long long ptr)
+@ stdcall TranslateAcceleratorW(long long ptr) NtUserTranslateAccelerator
@ stdcall TranslateMDISysAccel(long ptr)
@ stdcall TranslateMessage(ptr)
# @ stub TranslateMessageEx
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index c5db1bfcc30..ad04ba7ff78 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1224,6 +1224,7 @@ static struct unix_funcs unix_funcs =
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
NtUserTrackMouseEvent,
+ NtUserTranslateAccelerator,
NtUserTranslateMessage,
NtUserUnregisterClass,
NtUserUnregisterHotKey,
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 8544cca47b4..d41aba956f2 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -235,6 +235,23 @@ static BOOL is_menu( HMENU handle )
return is_menu;
}
+/***********************************************************************
+ * get_win_sys_menu
+ *
+ * Get the system menu of a window
+ */
+static HMENU get_win_sys_menu( HWND hwnd )
+{
+ HMENU ret = 0;
+ WND *win = get_win_ptr( hwnd );
+ if (win && win != WND_OTHER_PROCESS && win != WND_DESKTOP)
+ {
+ ret = win->hSysMenu;
+ release_win_ptr( win );
+ }
+ return ret;
+}
+
static POPUPMENU *find_menu_item( HMENU handle, UINT id, UINT flags, UINT *pos )
{
UINT fallback_pos = ~0u, i;
@@ -346,6 +363,48 @@ static BOOL is_win_menu_disallowed( HWND hwnd )
return (get_window_long(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
}
+/***********************************************************************
+ * find_submenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+static UINT find_submenu( HMENU *handle_ptr, HMENU target )
+{
+ POPUPMENU *menu;
+ MENUITEM *item;
+ UINT i;
+
+ if (*handle_ptr == (HMENU)0xffff || !(menu = grab_menu_ptr( *handle_ptr )))
+ return NO_SELECTED_ITEM;
+
+ item = menu->items;
+ for (i = 0; i < menu->nItems; i++, item++)
+ {
+ if(!(item->fType & MF_POPUP)) continue;
+ if (item->hSubMenu == target)
+ {
+ release_menu_ptr( menu );
+ return i;
+ }
+ else
+ {
+ HMENU hsubmenu = item->hSubMenu;
+ UINT pos = find_submenu( &hsubmenu, target );
+ if (pos != NO_SELECTED_ITEM)
+ {
+ *handle_ptr = hsubmenu;
+ release_menu_ptr( menu );
+ return pos;
+ }
+ }
+ }
+
+ release_menu_ptr( menu );
+ return NO_SELECTED_ITEM;
+}
+
/* see GetMenu */
HMENU get_menu( HWND hwnd )
{
@@ -932,6 +991,25 @@ BOOL WINAPI NtUserSetMenuContextHelpId( HMENU handle, DWORD id )
return TRUE;
}
+/* see GetSubMenu */
+static HMENU get_sub_menu( HMENU handle, INT pos )
+{
+ POPUPMENU *menu;
+ HMENU submenu;
+ UINT i;
+
+ if (!(menu = find_menu_item( handle, pos, MF_BYPOSITION, &i )))
+ return 0;
+
+ if (menu->items[i].fType & MF_POPUP)
+ submenu = menu->items[i].hSubMenu;
+ else
+ submenu = 0;
+
+ release_menu_ptr(menu);
+ return submenu;
+}
+
/**********************************************************************
* NtUserSetMenuDefaultItem (win32u.@)
*/
@@ -979,3 +1057,204 @@ BOOL WINAPI NtUserSetMenuDefaultItem( HMENU handle, UINT item, UINT bypos )
release_menu_ptr( menu );
return ret;
}
+
+/**********************************************************************
+ * translate_accelerator
+ */
+static BOOL translate_accelerator( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
+ BYTE virt, WORD key, WORD cmd )
+{
+ INT mask = 0;
+ UINT msg = 0;
+
+ if (wparam != key) return FALSE;
+
+ if (NtUserGetKeyState( VK_CONTROL ) & 0x8000) mask |= FCONTROL;
+ if (NtUserGetKeyState( VK_MENU ) & 0x8000) mask |= FALT;
+ if (NtUserGetKeyState( VK_SHIFT ) & 0x8000) mask |= FSHIFT;
+
+ if (message == WM_CHAR || message == WM_SYSCHAR)
+ {
+ if (!(virt & FVIRTKEY) && (mask & FALT) == (virt & FALT))
+ {
+ TRACE_(accel)( "found accel for WM_CHAR: ('%c')\n", LOWORD(wparam) & 0xff );
+ goto found;
+ }
+ }
+ else
+ {
+ if (virt & FVIRTKEY)
+ {
+ TRACE_(accel)( "found accel for virt_key %04lx (scan %04x)\n",
+ wparam, 0xff & HIWORD(lparam) );
+
+ if (mask == (virt & (FSHIFT | FCONTROL | FALT))) goto found;
+ TRACE_(accel)( ", but incorrect SHIFT/CTRL/ALT-state\n" );
+ }
+ else
+ {
+ if (!(lparam & 0x01000000)) /* no special_key */
+ {
+ if ((virt & FALT) && (lparam & 0x20000000)) /* ALT pressed */
+ {
+ TRACE_(accel)( "found accel for Alt-%c\n", LOWORD(wparam) & 0xff );
+ goto found;
+ }
+ }
+ }
+ }
+ return FALSE;
+
+found:
+ if (message == WM_KEYUP || message == WM_SYSKEYUP)
+ msg = 1;
+ else
+ {
+ HMENU menu_handle, submenu, sys_menu;
+ UINT sys_stat = ~0u, stat = ~0u, pos;
+ POPUPMENU *menu;
+
+ menu_handle = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) ? 0 : get_menu(hwnd);
+ sys_menu = get_win_sys_menu( hwnd );
+
+ /* find menu item and ask application to initialize it */
+ /* 1. in the system menu */
+ if ((menu = find_menu_item( sys_menu, cmd, MF_BYCOMMAND, NULL )))
+ {
+ submenu = menu->obj.handle;
+ release_menu_ptr( menu );
+
+ if (get_capture())
+ msg = 2;
+ if (!is_window_enabled( hwnd ))
+ msg = 3;
+ else
+ {
+ send_message( hwnd, WM_INITMENU, (WPARAM)sys_menu, 0 );
+ if (submenu != sys_menu)
+ {
+ pos = find_submenu( &sys_menu, submenu );
+ TRACE_(accel)( "sys_menu = %p, submenu = %p, pos = %d\n",
+ sys_menu, submenu, pos );
+ send_message( hwnd, WM_INITMENUPOPUP, (WPARAM)submenu, MAKELPARAM(pos, TRUE) );
+ }
+ sys_stat = get_menu_state( get_sub_menu( sys_menu, 0 ), cmd, MF_BYCOMMAND );
+ }
+ }
+ else /* 2. in the window's menu */
+ {
+ if ((menu = find_menu_item( menu_handle, cmd, MF_BYCOMMAND, NULL )))
+ {
+ submenu = menu->obj.handle;
+ release_menu_ptr( menu );
+
+ if (get_capture())
+ msg = 2;
+ if (!is_window_enabled( hwnd ))
+ msg = 3;
+ else
+ {
+ send_message( hwnd, WM_INITMENU, (WPARAM)menu_handle, 0 );
+ if(submenu != menu_handle)
+ {
+ pos = find_submenu( &menu_handle, submenu );
+ TRACE_(accel)( "menu_handle = %p, submenu = %p, pos = %d\n",
+ menu_handle, submenu, pos );
+ send_message( hwnd, WM_INITMENUPOPUP, (WPARAM)submenu,
+ MAKELPARAM(pos, FALSE) );
+ }
+ stat = get_menu_state( menu_handle, cmd, MF_BYCOMMAND );
+ }
+ }
+ }
+
+ if (msg == 0)
+ {
+ if (sys_stat != ~0u)
+ {
+ if (sys_stat & (MF_DISABLED|MF_GRAYED))
+ msg = 4;
+ else
+ msg = WM_SYSCOMMAND;
+ }
+ else
+ {
+ if (stat != ~0u)
+ {
+ if (is_iconic( hwnd ))
+ msg = 5;
+ else
+ {
+ if (stat & (MF_DISABLED|MF_GRAYED))
+ msg = 6;
+ else
+ msg = WM_COMMAND;
+ }
+ }
+ else
+ msg = WM_COMMAND;
+ }
+ }
+ }
+
+ if (msg == WM_COMMAND)
+ {
+ TRACE_(accel)( ", sending WM_COMMAND, wparam=%0x\n", 0x10000 | cmd );
+ send_message( hwnd, msg, 0x10000 | cmd, 0 );
+ }
+ else if (msg == WM_SYSCOMMAND)
+ {
+ TRACE_(accel)( ", sending WM_SYSCOMMAND, wparam=%0x\n", cmd );
+ send_message( hwnd, msg, cmd, 0x00010000 );
+ }
+ else
+ {
+ /* some reasons for NOT sending the WM_{SYS}COMMAND message:
+ * #0: unknown (please report!)
+ * #1: for WM_KEYUP,WM_SYSKEYUP
+ * #2: mouse is captured
+ * #3: window is disabled
+ * #4: it's a disabled system menu option
+ * #5: it's a menu option, but window is iconic
+ * #6: it's a menu option, but disabled
+ */
+ TRACE_(accel)( ", but won't send WM_{SYS}COMMAND, reason is #%d\n", msg );
+ if (!msg) ERR_(accel)( " unknown reason\n" );
+ }
+ return TRUE;
+}
+
+/**********************************************************************
+ * NtUserTranslateAccelerator (win32u.@)
+ */
+INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg )
+{
+ ACCEL data[32], *ptr = data;
+ int i, count;
+
+ if (!hwnd) return 0;
+
+ if (msg->message != WM_KEYDOWN &&
+ msg->message != WM_SYSKEYDOWN &&
+ msg->message != WM_CHAR &&
+ msg->message != WM_SYSCHAR)
+ return 0;
+
+ TRACE_(accel)("accel %p, hwnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
+ accel,hwnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
+
+ if (!(count = NtUserCopyAcceleratorTable( accel, NULL, 0 ))) return 0;
+ if (count > ARRAY_SIZE( data ))
+ {
+ if (!(ptr = malloc( count * sizeof(*ptr) ))) return 0;
+ }
+ count = NtUserCopyAcceleratorTable( accel, ptr, count );
+ for (i = 0; i < count; i++)
+ {
+ if (translate_accelerator( hwnd, msg->message, msg->wParam, msg->lParam,
+ ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
+ break;
+ }
+ if (ptr != data) free( ptr );
+ return (i < count);
+}
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 07da23f633a..483b3d52289 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1281,7 +1281,7 @@
@ stub NtUserTrackPopupMenuEx
@ stub NtUserTransformPoint
@ stub NtUserTransformRect
-@ stub NtUserTranslateAccelerator
+@ stdcall NtUserTranslateAccelerator(long long ptr)
@ stdcall NtUserTranslateMessage(ptr long)
@ stub NtUserUndelegateInput
@ stdcall -syscall NtUserUnhookWinEvent(long)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 537eec38a34..5a0787afca7 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -296,6 +296,7 @@ struct unix_funcs
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL (WINAPI *pNtUserTrackMouseEvent)( TRACKMOUSEEVENT *info );
+ INT (WINAPI *pNtUserTranslateAccelerator)( HWND hwnd, HACCEL accel, MSG *msg );
BOOL (WINAPI *pNtUserTranslateMessage)( const MSG *msg, UINT flags );
BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 05107352dfa..9a87bccbb7a 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1258,6 +1258,12 @@ BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
return unix_funcs->pNtUserTrackMouseEvent( info );
}
+INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg )
+{
+ if (!unix_funcs) return 0;
+ return unix_funcs->pNtUserTranslateAccelerator( hwnd, accel, msg );
+}
+
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags )
{
if (!unix_funcs) return 0;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/18
More information about the wine-devel
mailing list