mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
2003-12-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
* lib/user32/windows/accel.c (U32IsValidAccelMessage): Translate WM_KEYUP and WM_SYSKEYUP messages. (TranslateAcceleratorA): Returntype of RtlMultiByteToUnicodeN is NTSTATUS, so interpret it as such. * subsys/win32k/ntuser/accelerator.c (NtUserDestroyAcceleratorTable): Call ObmCloseHandle() before destroying the object. (IntTranslateAccelerator): New function. (NtUserTranslateAccelerator): Partial implementation. svn path=/trunk/; revision=6901
This commit is contained in:
parent
d85259d689
commit
13a5b00db7
3 changed files with 306 additions and 14 deletions
|
@ -1,3 +1,14 @@
|
|||
2003-12-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||
|
||||
* lib/user32/windows/accel.c (U32IsValidAccelMessage): Translate WM_KEYUP
|
||||
and WM_SYSKEYUP messages.
|
||||
(TranslateAcceleratorA): Returntype of RtlMultiByteToUnicodeN is NTSTATUS,
|
||||
so interpret it as such.
|
||||
* subsys/win32k/ntuser/accelerator.c (NtUserDestroyAcceleratorTable):
|
||||
Call ObmCloseHandle() before destroying the object.
|
||||
(IntTranslateAccelerator): New function.
|
||||
(NtUserTranslateAccelerator): Partial implementation.
|
||||
|
||||
2003-12-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||
|
||||
* subsys/win32k/include/accelerator.h: New file.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: accel.c,v 1.11 2003/07/23 20:39:45 gvg Exp $
|
||||
/* $Id: accel.c,v 1.12 2003/12/07 16:54:44 chorns Exp $
|
||||
*
|
||||
* PROJECT: ReactOS user32.dll
|
||||
* FILE: lib/user32/windows/input.c
|
||||
|
@ -162,9 +162,10 @@ BOOL WINAPI U32IsValidAccelMessage(UINT uMsg)
|
|||
switch(uMsg)
|
||||
{
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_CHAR:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSCHAR:
|
||||
case WM_SYSKEYUP:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
|
@ -352,16 +353,14 @@ int WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
|
|||
MSG mCopy = *lpMsg;
|
||||
CHAR cChar;
|
||||
WCHAR wChar;
|
||||
NTSTATUS nErrCode;
|
||||
NTSTATUS Status;
|
||||
|
||||
if(!U32IsValidAccelMessage(lpMsg->message)) return 0;
|
||||
|
||||
nErrCode =
|
||||
RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar));
|
||||
|
||||
if(!nErrCode)
|
||||
Status = RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar));
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastError(RtlNtStatusToDosError(nErrCode));
|
||||
SetLastError(RtlNtStatusToDosError(Status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: accelerator.c,v 1.2 2003/12/07 14:21:00 weiden Exp $
|
||||
/* $Id: accelerator.c,v 1.3 2003/12/07 16:54:44 chorns Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -26,6 +26,27 @@
|
|||
* REVISION HISTORY:
|
||||
* 06-06-2001 CSH Created
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1993 Martin Ayotte
|
||||
* Copyright 1994 Alexandre Julliard
|
||||
* Copyright 1997 Morten Welinder
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <roskrnl.h>
|
||||
|
@ -37,6 +58,7 @@
|
|||
#include <include/object.h>
|
||||
#include <include/guicheck.h>
|
||||
#include <include/window.h>
|
||||
#include <include/focus.h>
|
||||
#include <include/accelerator.h>
|
||||
|
||||
#define NDEBUG
|
||||
|
@ -193,7 +215,6 @@ NtUserDestroyAcceleratorTable(
|
|||
PWINSTATION_OBJECT WindowStation;
|
||||
PACCELERATOR_TABLE AcceleratorTable;
|
||||
NTSTATUS Status;
|
||||
HACCEL Handle;
|
||||
|
||||
/* FIXME: If the handle table is from a call to LoadAcceleratorTable, decrement it's
|
||||
usage count (and return TRUE).
|
||||
|
@ -220,19 +241,19 @@ NtUserDestroyAcceleratorTable(
|
|||
(PVOID*)&AcceleratorTable);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(STATUS_INVALID_HANDLE);
|
||||
SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE);
|
||||
ObDereferenceObject(WindowStation);
|
||||
DbgPrint("E2\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ObmCloseHandle(WindowStation->HandleTable, Table);
|
||||
|
||||
if (AcceleratorTable->Table != NULL)
|
||||
{
|
||||
ExFreePool(AcceleratorTable->Table);
|
||||
}
|
||||
|
||||
ObmCloseHandle(WindowStation->HandleTable, Handle);
|
||||
|
||||
ObDereferenceObject(WindowStation);
|
||||
|
||||
DbgPrint("NtUserDestroyAcceleratorTable(Table %x)\n",
|
||||
|
@ -241,6 +262,187 @@ NtUserDestroyAcceleratorTable(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
IntTranslateAccelerator(HWND hWnd,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
BYTE fVirt,
|
||||
WORD key,
|
||||
WORD cmd)
|
||||
{
|
||||
UINT mesg = 0;
|
||||
|
||||
DbgPrint("IntTranslateAccelerator(hWnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x)\n",
|
||||
hWnd, message, wParam, lParam, fVirt, key, cmd);
|
||||
|
||||
if (wParam != key)
|
||||
{
|
||||
DbgPrint("T0\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (message == WM_CHAR)
|
||||
{
|
||||
if (!(fVirt & FALT) && !(fVirt & FVIRTKEY))
|
||||
{
|
||||
DbgPrint("found accel for WM_CHAR: ('%c')\n", wParam & 0xff);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((fVirt & FVIRTKEY) > 0)
|
||||
{
|
||||
INT mask = 0;
|
||||
DbgPrint("found accel for virt_key %04x (scan %04x)\n",
|
||||
wParam, 0xff & HIWORD(lParam));
|
||||
|
||||
DbgPrint("NtUserGetKeyState(VK_SHIFT) = 0x%x\n",
|
||||
NtUserGetKeyState(VK_SHIFT));
|
||||
DbgPrint("NtUserGetKeyState(VK_CONTROL) = 0x%x\n",
|
||||
NtUserGetKeyState(VK_CONTROL));
|
||||
DbgPrint("NtUserGetKeyState(VK_MENU) = 0x%x\n",
|
||||
NtUserGetKeyState(VK_MENU));
|
||||
|
||||
if (NtUserGetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
|
||||
if (NtUserGetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
|
||||
if (NtUserGetKeyState(VK_MENU) & 0x8000) mask |= FALT;
|
||||
if (mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
|
||||
DbgPrint(", but incorrect SHIFT/CTRL/ALT-state\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(lParam & 0x01000000)) /* no special_key */
|
||||
{
|
||||
if ((fVirt & FALT) && (lParam & 0x20000000))
|
||||
{ /* ^^ ALT pressed */
|
||||
DbgPrint("found accel for Alt-%c\n", wParam & 0xff);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DbgPrint("IntTranslateAccelerator(hWnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = FALSE\n",
|
||||
hWnd, message, wParam, lParam, fVirt, key, cmd);
|
||||
|
||||
return FALSE;
|
||||
|
||||
found:
|
||||
if (message == WM_KEYUP || message == WM_SYSKEYUP)
|
||||
mesg = 1;
|
||||
else if (IntGetCaptureWindow())
|
||||
mesg = 2;
|
||||
else if (!IntIsWindowVisible(hWnd)) /* FIXME: WINE IsWindowEnabled == IntIsWindowVisible? */
|
||||
mesg = 3;
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
HMENU hMenu, hSubMenu, hSysMenu;
|
||||
UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
|
||||
|
||||
hMenu = (NtUserGetWindowLongW(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 */
|
||||
hSubMenu = hSysMenu;
|
||||
nPos = cmd;
|
||||
if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
|
||||
{
|
||||
NtUserSendMessage(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);
|
||||
NtUserSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
|
||||
}
|
||||
uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
|
||||
}
|
||||
else /* 2. in the window's menu */
|
||||
{
|
||||
hSubMenu = hMenu;
|
||||
nPos = cmd;
|
||||
if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
|
||||
{
|
||||
NtUserSendMessage(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);
|
||||
NtUserSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
|
||||
}
|
||||
uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
#else
|
||||
DPRINT1("menu search not implemented");
|
||||
mesg = WM_COMMAND;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mesg == WM_COMMAND)
|
||||
{
|
||||
DbgPrint(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
|
||||
NtUserSendMessage(hWnd, mesg, 0x10000 | cmd, 0L);
|
||||
}
|
||||
else if (mesg == WM_SYSCOMMAND)
|
||||
{
|
||||
DbgPrint(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
|
||||
NtUserSendMessage(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
|
||||
*/
|
||||
DbgPrint(", but won't send WM_{SYS}COMMAND, reason is #%d\n", mesg);
|
||||
if (mesg == 0)
|
||||
{
|
||||
DbgPrint(" unknown reason - please report!");
|
||||
}
|
||||
}
|
||||
|
||||
DbgPrint("IntTranslateAccelerator(hWnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x) = TRUE\n",
|
||||
hWnd, message, wParam, lParam, fVirt, key, cmd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
STDCALL
|
||||
NtUserTranslateAccelerator(
|
||||
|
@ -248,7 +450,87 @@ NtUserTranslateAccelerator(
|
|||
HACCEL Table,
|
||||
LPMSG Message)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
PWINSTATION_OBJECT WindowStation;
|
||||
PACCELERATOR_TABLE AcceleratorTable;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
|
||||
DbgPrint("NtUserTranslateAccelerator(Window %x, Table %x, Message %p)\n",
|
||||
Window, Table, Message);
|
||||
|
||||
if (Message == NULL)
|
||||
{
|
||||
SetLastNtError(STATUS_INVALID_PARAMETER);
|
||||
DbgPrint("E0a\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Table == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE);
|
||||
DbgPrint("E0b\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((Message->message != WM_KEYDOWN) &&
|
||||
(Message->message != WM_KEYUP) &&
|
||||
(Message->message != WM_SYSKEYDOWN) &&
|
||||
(Message->message != WM_SYSKEYUP) &&
|
||||
(Message->message != WM_CHAR))
|
||||
{
|
||||
DbgPrint("E0c\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = IntValidateWindowStationHandle(NtUserGetProcessWindowStation(),
|
||||
UserMode,
|
||||
0,
|
||||
&WindowStation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastNtError(STATUS_ACCESS_DENIED);
|
||||
DbgPrint("E1\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = ObmReferenceObjectByHandle(WindowStation->HandleTable,
|
||||
Table,
|
||||
otAcceleratorTable,
|
||||
(PVOID*)&AcceleratorTable);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE);
|
||||
ObDereferenceObject(WindowStation);
|
||||
DbgPrint("E2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Associate AcceleratorTable with the current thread */
|
||||
|
||||
/* FIXME: If Window is active and no window has focus, translate WM_SYSKEYUP and WM_SYSKEY_DOWN instead */
|
||||
|
||||
for (i = 0; i < AcceleratorTable->Count; i++)
|
||||
{
|
||||
if (IntTranslateAccelerator(Window, Message->message, Message->wParam, Message->lParam,
|
||||
AcceleratorTable->Table[i].fVirt, AcceleratorTable->Table[i].key,
|
||||
AcceleratorTable->Table[i].cmd))
|
||||
{
|
||||
ObDereferenceObject(WindowStation);
|
||||
DbgPrint("NtUserTranslateAccelerator(Window %x, Table %x, Message %p) = %i end\n",
|
||||
Window, Table, Message, 1);
|
||||
return 1;
|
||||
}
|
||||
if (((AcceleratorTable->Table[i].fVirt & 0x80) > 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
ObDereferenceObject(WindowStation);
|
||||
|
||||
DbgPrint("NtUserTranslateAccelerator(Window %x, Table %x, Message %p) = %i end\n",
|
||||
Window, Table, Message, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue