[User32|Win32k]

- Isolated Alt-Tab/Esc issues. Placed update_input_key_state when posting to a queue like wine. This fixed the shift key checks. The Alt-Space is handled after a Translate Message call (WM_SYSCHAR), developers need to check application code to help support it (ConCtrl32). Will move AltSwitch.c from win32csr and port patch from bug 5378 to User32. ReactOS registers the Switch Class in Win32k and it is not used.
- Implemented the rest of HotKey Support. ReactOS Explorer does not save hotkey actions.
- See related bugs 1091.

svn path=/trunk/; revision=51450
This commit is contained in:
James Tabor 2011-04-25 15:18:39 +00:00
parent 30fde9e816
commit 6c4a25f386
6 changed files with 250 additions and 64 deletions

View file

@ -753,12 +753,12 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
WINDOWPLACEMENT wp;
POINT Pt;
LRESULT lResult;
if (!IsWindowEnabled( hWnd )) return 0;
if (ISITHOOKED(WH_CBT))
{
LRESULT lResult;
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
if (lResult) return 0;
}
@ -795,7 +795,7 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
break;
case SC_CLOSE:
return SendMessageW(hWnd, WM_CLOSE, 0, 0);
// case SC_DEFAULT:
case SC_MOUSEMENU:
{
Pt.x = (short)LOWORD(lParam);
@ -815,9 +815,40 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
}
break;
case SC_SCREENSAVE:
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
break;
case SC_NEXTWINDOW:
case SC_PREVWINDOW:
FIXME("Implement Alt-Tab!!! wParam 0x%x lParam 0x%x\n",wParam,lParam);
break;
case SC_HOTKEY:
{
HWND hwnd, hWndLastActive;
hwnd = (HWND)lParam;
PWND pWnd = ValidateHwnd(hwnd);
if (pWnd)
{
hWndLastActive = GetLastActivePopup(hwnd);
if (hWndLastActive)
{
hwnd = hWndLastActive;
pWnd = ValidateHwnd(hwnd);
}
SetForegroundWindow(hwnd);
if (pWnd->style & WS_MINIMIZE)
{
PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
}
}
break;
default:
/* FIXME: Implement */
UNIMPLEMENTED;
FIXME("Unimplemented DefWndHandleSysCommand wParam 0x%x\n",wParam);
break;
}
@ -1380,39 +1411,49 @@ User32DefWindowProc(HWND hWnd,
if(wParam == VK_F10) iF10Key = VK_F10;
break;
/* FIXME: This is also incomplete. */
case WM_SYSKEYDOWN:
{
if (HIWORD(lParam) & KEYDATA_ALT)
{
HWND top = GetAncestor(hWnd, GA_ROOT);
/* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
if ( (wParam == VK_MENU || wParam == VK_LMENU
|| wParam == VK_RMENU) && !iMenuSysKey )
iMenuSysKey = 1;
else
iMenuSysKey = 0;
{ /* Previous state, if the key was down before this message,
this is a cheap way to ignore autorepeat keys. */
if ( !(HIWORD(lParam) & KEYDATA_PREVSTATE) )
{
if ( ( wParam == VK_MENU ||
wParam == VK_LMENU ||
wParam == VK_RMENU ) && !iMenuSysKey )
iMenuSysKey = 1;
else
iMenuSysKey = 0;
}
iF10Key = 0;
if (wParam == VK_F4) /* Try to close the window */
{
if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
{
if (bUnicode)
PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
else
PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
}
HWND top = GetAncestor(hWnd, GA_ROOT);
if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
}
else if (wParam == VK_SNAPSHOT)
else if (wParam == VK_SNAPSHOT) // Alt-VK_SNAPSHOT?
{
HWND hwnd = hWnd;
while (GetParent(hwnd) != NULL)
{
hwnd = GetParent(hwnd);
}
DefWndScreenshot(hwnd);
HWND hwnd = hWnd;
while (GetParent(hwnd) != NULL)
{
hwnd = GetParent(hwnd);
}
DefWndScreenshot(hwnd);
}
else if ( wParam == VK_ESCAPE || wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
{
WPARAM wParamTmp;
HWND Active = GetActiveWindow(); // Noticed MDI problem.
if (!Active)
{
FIXME("WM_SYSKEYDOWN VK_ESCAPE no active\n");
break;
}
wParamTmp = GetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
SendMessageW( Active, WM_SYSCOMMAND, wParamTmp, wParam );
}
}
else if( wParam == VK_F10 )
@ -1421,8 +1462,6 @@ User32DefWindowProc(HWND hWnd,
SendMessageW( hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, MAKELPARAM(-1, -1) );
iF10Key = 1;
}
else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
break;
}
@ -1440,38 +1479,24 @@ User32DefWindowProc(HWND hWnd,
case WM_SYSCHAR:
{
iMenuSysKey = 0;
if (wParam == '\r' && IsIconic(hWnd))
if (wParam == VK_RETURN && IsIconic(hWnd))
{
PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
break;
}
if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
{
if (wParam == '\t' || wParam == '\x1b') break;
if (wParam == ' ' && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
if (wParam == VK_SPACE && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
else
SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
}
else /* check for Ctrl-Esc */
if (wParam != '\x1b') MessageBeep(0);
if (wParam != VK_ESCAPE) MessageBeep(0);
break;
}
case WM_SHOWWINDOW:
{
if (lParam) // Call when it is necessary.
NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
break;
}
case WM_CLIENTSHUTDOWN:
{
LRESULT lResult;
NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
return lResult;
}
case WM_CANCELMODE:
{
iMenuSysKey = 0;
@ -1800,6 +1825,17 @@ User32DefWindowProc(HWND hWnd,
break;
}
/* Move to win32k !*/
case WM_SHOWWINDOW:
if (!lParam) break; // Call when it is necessary.
case WM_CLIENTSHUTDOWN:
case WM_GETHOTKEY:
case WM_SETHOTKEY:
{
LRESULT lResult;
NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, !bUnicode);
return lResult;
}
}
return 0;
}

View file

@ -13,6 +13,8 @@ typedef struct _HOT_KEY_ITEM
UINT vk;
} HOT_KEY_ITEM, *PHOT_KEY_ITEM;
#define IDHOT_REACTOS (-9)
INIT_FUNCTION
NTSTATUS
NTAPI
@ -33,5 +35,9 @@ UnregisterWindowHotKeys(PWND Window);
VOID FASTCALL
UnregisterThreadHotKeys(struct _ETHREAD *Thread);
UINT FASTCALL
DefWndGetHotKey(HWND hwnd);
INT FASTCALL
DefWndSetHotKey( PWND pWnd, WPARAM wParam);
/* EOF */

View file

@ -97,6 +97,34 @@ IntClientShutdown(
return lResult;
}
LRESULT FASTCALL
DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = 0;
BOOL Hook = FALSE;
if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)))
{
Hook = TRUE;
lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
if (lResult) return lResult;
}
switch (wParam & 0xfff0)
{
case SC_SCREENSAVE:
DPRINT1("Screensaver Called!\n");
break;
default:
UNIMPLEMENTED;
break;
}
return(Hook ? 1 : 0); // Don't call us again from user space.
}
/*
Win32k counterpart of User DefWindowProc
*/
@ -117,7 +145,7 @@ IntDefWindowProc(
case WM_SYSCOMMAND:
{
DPRINT1("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
lResult = DefWndHandleSysCommand(Wnd, wParam, lParam);
break;
}
case WM_SHOWWINDOW:
@ -142,6 +170,12 @@ IntDefWindowProc(
case WM_CLIENTSHUTDOWN:
return IntClientShutdown(Wnd, wParam, lParam);
case WM_GETHOTKEY:
return DefWndGetHotKey(UserHMGetHandle(Wnd));
case WM_SETHOTKEY:
return DefWndSetHotKey(Wnd, wParam);
/* ReactOS only. */
case WM_CBT:
{
switch (wParam)

View file

@ -61,7 +61,6 @@ InitHotkeyImpl(VOID)
return STATUS_SUCCESS;
}
#if 0 //not used
NTSTATUS FASTCALL
CleanupHotKeys(VOID)
@ -71,7 +70,6 @@ CleanupHotKeys(VOID)
}
#endif
BOOL FASTCALL
GetHotKey (UINT fsModifiers,
UINT vk,
@ -102,7 +100,6 @@ GetHotKey (UINT fsModifiers,
return FALSE;
}
VOID FASTCALL
UnregisterWindowHotKeys(PWND Window)
{
@ -119,7 +116,6 @@ UnregisterWindowHotKeys(PWND Window)
}
VOID FASTCALL
UnregisterThreadHotKeys(struct _ETHREAD *Thread)
{
@ -136,7 +132,6 @@ UnregisterThreadHotKeys(struct _ETHREAD *Thread)
}
static
BOOL FASTCALL
IsHotKey (UINT fsModifiers, UINT vk)
@ -154,7 +149,111 @@ IsHotKey (UINT fsModifiers, UINT vk)
return FALSE;
}
//
// Get/SetHotKey message support.
//
UINT FASTCALL
DefWndGetHotKey( HWND hwnd )
{
PHOT_KEY_ITEM HotKeyItem;
DPRINT1("DefWndGetHotKey\n");
if (IsListEmpty(&gHotkeyList)) return 0;
LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
{
if ( HotKeyItem->hWnd == hwnd &&
HotKeyItem->id == IDHOT_REACTOS )
{
return MAKELONG(HotKeyItem->vk, HotKeyItem->fsModifiers);
}
}
return 0;
}
INT FASTCALL
DefWndSetHotKey( PWND pWnd, WPARAM wParam )
{
UINT fsModifiers, vk;
PHOT_KEY_ITEM HotKeyItem;
HWND hWnd;
BOOL HaveSameWnd = FALSE;
INT Ret = 1;
DPRINT1("DefWndSetHotKey wParam 0x%x\n", wParam);
// A hot key cannot be associated with a child window.
if (pWnd->style & WS_CHILD) return 0;
// VK_ESCAPE, VK_SPACE, and VK_TAB are invalid hot keys.
if ( LOWORD(wParam) == VK_ESCAPE ||
LOWORD(wParam) == VK_SPACE ||
LOWORD(wParam) == VK_TAB ) return -1;
vk = LOWORD(wParam);
fsModifiers = HIWORD(wParam);
hWnd = UserHMGetHandle(pWnd);
if (wParam)
{
LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
{
if ( HotKeyItem->fsModifiers == fsModifiers &&
HotKeyItem->vk == vk &&
HotKeyItem->id == IDHOT_REACTOS )
{
if (HotKeyItem->hWnd != hWnd)
Ret = 2; // Another window already has the same hot key.
break;
}
}
}
LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
{
if ( HotKeyItem->hWnd == hWnd &&
HotKeyItem->id == IDHOT_REACTOS )
{
HaveSameWnd = TRUE;
break;
}
}
if (HaveSameWnd)
{
if (wParam == 0)
{ // Setting wParam to NULL removes the hot key associated with a window.
UnregisterWindowHotKeys(pWnd);
}
else
{ /* A window can only have one hot key. If the window already has a hot key
associated with it, the new hot key replaces the old one. */
HotKeyItem->fsModifiers = fsModifiers;
HotKeyItem->vk = vk;
}
}
else //
{
if (wParam == 0)
return 1; // Do nothing, exit.
HotKeyItem = ExAllocatePoolWithTag (PagedPool, sizeof(HOT_KEY_ITEM), USERTAG_HOTKEY);
if (HotKeyItem == NULL)
{
return 0;
}
HotKeyItem->Thread = pWnd->head.pti->pEThread;
HotKeyItem->hWnd = hWnd;
HotKeyItem->id = IDHOT_REACTOS; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey.
HotKeyItem->fsModifiers = fsModifiers;
HotKeyItem->vk = vk;
InsertHeadList (&gHotkeyList, &HotKeyItem->ListEntry);
}
return Ret;
}
/* SYSCALLS *****************************************************************/

View file

@ -735,7 +735,8 @@ co_IntPeekMessage( PMSG Msg,
}
/* Now check for normal messages. */
if ((ProcessMask & QS_POSTMESSAGE) &&
if (( (ProcessMask & QS_POSTMESSAGE) ||
(ProcessMask & QS_HOTKEY) ) &&
MsqPeekMessage( ThreadQueue,
RemoveMessages,
Window,

View file

@ -463,6 +463,7 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
Msg.pt = gpsi->ptCursor;
update_input_key_state(FocusMessageQueue, &Msg);
MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
}
else
@ -481,6 +482,8 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
MSG Mesg;
LARGE_INTEGER LargeTickCount;
NTSTATUS Status;
INT id;
DWORD Type;
Status = ObReferenceObjectByPointer (Thread,
THREAD_ALL_ACCESS,
@ -503,14 +506,17 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
return;
}
Mesg.hwnd = hWnd;
Mesg.message = WM_HOTKEY;
Mesg.wParam = wParam;
Mesg.lParam = lParam;
id = wParam; // Check for hot keys unrelated to the hot keys set by RegisterHotKey.
Mesg.hwnd = hWnd;
Mesg.message = id != IDHOT_REACTOS ? WM_HOTKEY : WM_SYSCOMMAND;
Mesg.wParam = id != IDHOT_REACTOS ? wParam : SC_HOTKEY;
Mesg.lParam = id != IDHOT_REACTOS ? lParam : (LPARAM)hWnd;
Type = id != IDHOT_REACTOS ? QS_HOTKEY : QS_POSTMESSAGE;
KeQueryTickCount(&LargeTickCount);
Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
Mesg.pt = gpsi->ptCursor;
MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
Mesg.pt = gpsi->ptCursor;
MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, Type);
UserDereferenceObject(Window);
ObDereferenceObject (Thread);
@ -543,8 +549,8 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
{
PUSER_SENT_MESSAGE SaveMsg, Message;
PLIST_ENTRY Entry;
LRESULT Result;
PTHREADINFO pti;
LRESULT Result = 0;
if (IsListEmpty(&MessageQueue->SentMessagesListHead))
{
@ -1321,6 +1327,10 @@ BOOL co_IntProcessKeyboardMessage(MSG* Msg, BOOL* RemoveMessages)
case VK_LMENU: case VK_RMENU:
Msg->wParam = VK_MENU;
break;
case VK_F10:
if (Msg->message == WM_KEYUP) Msg->message = WM_SYSKEYUP;
if (Msg->message == WM_KEYDOWN) Msg->message = WM_SYSKEYDOWN;
break;
}
}
@ -1450,7 +1460,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
{
update_input_key_state(MessageQueue, pMsg);
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, QS_INPUT);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
@ -1510,7 +1520,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
if (Remove)
{
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, QS_POSTMESSAGE);
ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
MsqDestroyMessage(CurrentMessage);
}
return(TRUE);