mirror of
https://github.com/reactos/reactos.git
synced 2025-05-30 22:49:12 +00:00
[SHELL32][NTUSER] Implement the SEE_MASK_HOTKEY/ICON/HMONITOR flags (#7947)
This commit is contained in:
parent
102c1db735
commit
6829350af9
6 changed files with 114 additions and 22 deletions
|
@ -2687,6 +2687,14 @@ HRESULT CShellLink::DoOpen(LPCMINVOKECOMMANDINFO lpici)
|
|||
else if (pszDirA && SHAnsiToUnicode(pszDirA, dir, _countof(dir)))
|
||||
sei.lpDirectory = dir;
|
||||
}
|
||||
|
||||
sei.dwHotKey = lpici->dwHotKey;
|
||||
sei.fMask |= CmicFlagsToSeeFlags(lpici->fMask & CMIC_MASK_HOTKEY);
|
||||
if (m_Header.wHotKey)
|
||||
{
|
||||
sei.dwHotKey = m_Header.wHotKey;
|
||||
sei.fMask |= SEE_MASK_HOTKEY;
|
||||
}
|
||||
return (ShellExecuteExW(&sei) ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(exec);
|
|||
|
||||
EXTERN_C BOOL PathIsExeW(LPCWSTR lpszPath);
|
||||
|
||||
#ifndef STARTF_SHELLPRIVATE
|
||||
#define STARTF_SHELLPRIVATE 0x400 // From kernel32.h
|
||||
#endif
|
||||
#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
|
||||
|
||||
typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
||||
|
@ -512,6 +515,27 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
|||
if (psei->fMask & SEE_MASK_HASLINKNAME)
|
||||
startup.dwFlags |= STARTF_TITLEISLINKNAME;
|
||||
|
||||
if (psei->fMask & SEE_MASK_HOTKEY)
|
||||
{
|
||||
startup.hStdInput = UlongToHandle(psei->dwHotKey);
|
||||
startup.dwFlags |= STARTF_USEHOTKEY;
|
||||
}
|
||||
|
||||
if (psei->fMask & SEE_MASK_ICON) // hIcon has higher precedence than hMonitor
|
||||
{
|
||||
startup.hStdOutput = psei->hIcon;
|
||||
startup.dwFlags |= STARTF_SHELLPRIVATE;
|
||||
}
|
||||
else if ((psei->fMask & SEE_MASK_HMONITOR) || psei->hwnd)
|
||||
{
|
||||
if (psei->fMask & SEE_MASK_HMONITOR)
|
||||
startup.hStdOutput = psei->hMonitor;
|
||||
else if (psei->hwnd)
|
||||
startup.hStdOutput = MonitorFromWindow(psei->hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
if (startup.hStdOutput)
|
||||
startup.dwFlags |= STARTF_SHELLPRIVATE;
|
||||
}
|
||||
|
||||
if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
|
||||
lpDirectory, &startup, &info))
|
||||
{
|
||||
|
@ -1942,9 +1966,7 @@ static WCHAR *expand_environment( const WCHAR *str )
|
|||
static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
||||
{
|
||||
static const DWORD unsupportedFlags =
|
||||
SEE_MASK_ICON | SEE_MASK_HOTKEY |
|
||||
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
|
||||
SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR;
|
||||
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_ASYNCOK;
|
||||
|
||||
DWORD len;
|
||||
UINT_PTR retval = SE_ERR_NOASSOC;
|
||||
|
|
|
@ -40,6 +40,8 @@ UINT gfsModOnlyCandidate;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
#define IsWindowHotKey(pHK) ( (pHK)->pti == NULL && (pHK)->id == IDHK_WNDKEY )
|
||||
|
||||
VOID FASTCALL
|
||||
StartDebugHotKeys(VOID)
|
||||
{
|
||||
|
@ -82,6 +84,18 @@ IntGetModifiers(PBYTE pKeyState)
|
|||
return fModifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
* IntSwapModHKF
|
||||
*
|
||||
* Maps to/from MOD_/HOTKEYF_ (swaps the SHIFT and ALT bits)
|
||||
*/
|
||||
static inline
|
||||
UCHAR
|
||||
IntSwapModHKF(UINT Input)
|
||||
{
|
||||
return (Input & 2) | ((Input & 1) << 2) | ((Input >> 2) & 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* UnregisterWindowHotKeys
|
||||
*
|
||||
|
@ -290,6 +304,17 @@ co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
|
|||
UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
|
||||
co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
|
||||
}
|
||||
else if (IsWindowHotKey(pHotKey))
|
||||
{
|
||||
/* WM_SETHOTKEY notifies with WM_SYSCOMMAND, not WM_HOTKEY */
|
||||
if (bIsDown)
|
||||
{
|
||||
if (gpqForeground && gpqForeground->spwndActive)
|
||||
pWnd = gpqForeground->spwndActive;
|
||||
UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND,
|
||||
SC_HOTKEY, (LPARAM)UserHMGetHandle(pHotKey->pWnd));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("UPM Hot key Id %d Key %u\n", pHotKey->id, wVk );
|
||||
|
@ -318,10 +343,10 @@ DefWndGetHotKey(PWND pWnd)
|
|||
|
||||
while (pHotKey)
|
||||
{
|
||||
if (pHotKey->pWnd == pWnd && pHotKey->id == IDHK_REACTOS)
|
||||
if (pHotKey->pWnd == pWnd && IsWindowHotKey(pHotKey))
|
||||
{
|
||||
/* We have found it */
|
||||
return MAKELONG(pHotKey->vk, pHotKey->fsModifiers);
|
||||
return MAKEWORD(pHotKey->vk, IntSwapModHKF(pHotKey->fsModifiers));
|
||||
}
|
||||
|
||||
/* Move to the next entry */
|
||||
|
@ -339,7 +364,8 @@ DefWndGetHotKey(PWND pWnd)
|
|||
INT FASTCALL
|
||||
DefWndSetHotKey(PWND pWnd, WPARAM wParam)
|
||||
{
|
||||
UINT fsModifiers, vk;
|
||||
const UINT fsModifiers = IntSwapModHKF(HIBYTE(wParam));
|
||||
const UINT vk = LOBYTE(wParam);
|
||||
PHOT_KEY pHotKey, *pLink;
|
||||
INT iRet = 1;
|
||||
|
||||
|
@ -349,17 +375,12 @@ DefWndSetHotKey(PWND pWnd, WPARAM wParam)
|
|||
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)
|
||||
// VK_ESCAPE, VK_SPACE, VK_TAB and VK_PACKET are invalid hot keys.
|
||||
if (vk == VK_ESCAPE || vk == VK_SPACE || vk == VK_TAB || vk == VK_PACKET)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vk = LOWORD(wParam);
|
||||
fsModifiers = HIWORD(wParam);
|
||||
|
||||
if (wParam)
|
||||
{
|
||||
pHotKey = gphkFirst;
|
||||
|
@ -367,7 +388,7 @@ DefWndSetHotKey(PWND pWnd, WPARAM wParam)
|
|||
{
|
||||
if (pHotKey->fsModifiers == fsModifiers &&
|
||||
pHotKey->vk == vk &&
|
||||
pHotKey->id == IDHK_REACTOS)
|
||||
IsWindowHotKey(pHotKey))
|
||||
{
|
||||
if (pHotKey->pWnd != pWnd)
|
||||
iRet = 2; // Another window already has the same hot key.
|
||||
|
@ -383,8 +404,7 @@ DefWndSetHotKey(PWND pWnd, WPARAM wParam)
|
|||
pLink = &gphkFirst;
|
||||
while (pHotKey)
|
||||
{
|
||||
if (pHotKey->pWnd == pWnd &&
|
||||
pHotKey->id == IDHK_REACTOS)
|
||||
if (pHotKey->pWnd == pWnd && IsWindowHotKey(pHotKey))
|
||||
{
|
||||
/* This window has already hotkey registered */
|
||||
break;
|
||||
|
@ -405,14 +425,14 @@ DefWndSetHotKey(PWND pWnd, WPARAM wParam)
|
|||
return 0;
|
||||
|
||||
pHotKey->pWnd = pWnd;
|
||||
pHotKey->id = IDHK_REACTOS; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey
|
||||
pHotKey->id = IDHK_WNDKEY; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey
|
||||
pHotKey->pNext = gphkFirst;
|
||||
gphkFirst = pHotKey;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
pHotKey->pti = NULL;
|
||||
pHotKey->pti = NULL; /* IsWindowHotKey */
|
||||
pHotKey->fsModifiers = fsModifiers;
|
||||
pHotKey->vk = vk;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ typedef struct _HOT_KEY
|
|||
#define IDHK_F12 -5
|
||||
#define IDHK_SHIFTF12 -6
|
||||
#define IDHK_WINKEY -7
|
||||
#define IDHK_REACTOS -8
|
||||
#define IDHK_WNDKEY -8 /* WM_SETHOTKEY */
|
||||
|
||||
/* Window Snap Hot Keys */
|
||||
#define IDHK_SNAP_LEFT -10
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
#include <debug.h>
|
||||
#include <kdros.h>
|
||||
|
||||
#ifndef STARTF_USEHOTKEY
|
||||
#define STARTF_USEHOTKEY 0x0200
|
||||
#endif
|
||||
#ifndef STARTF_SHELLPRIVATE
|
||||
#define STARTF_SHELLPRIVATE 0x0400
|
||||
#endif
|
||||
|
||||
HANDLE hModuleWin;
|
||||
|
||||
NTSTATUS ExitProcessCallback(PEPROCESS Process);
|
||||
|
@ -462,6 +469,7 @@ InitThreadCallback(PETHREAD Thread)
|
|||
PTEB pTeb;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParams;
|
||||
PKL pDefKL;
|
||||
BOOLEAN bFirstThread;
|
||||
|
||||
Process = Thread->ThreadsProcess;
|
||||
|
||||
|
@ -486,6 +494,7 @@ InitThreadCallback(PETHREAD Thread)
|
|||
pTeb->Win32ThreadInfo = ptiCurrent;
|
||||
ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
|
||||
ptiCurrent->pcti = &ptiCurrent->cti;
|
||||
bFirstThread = !(ptiCurrent->ppi->W32PF_flags & W32PF_THREADCONNECTED);
|
||||
|
||||
/* Mark the process as having threads */
|
||||
ptiCurrent->ppi->W32PF_flags |= W32PF_THREADCONNECTED;
|
||||
|
@ -578,6 +587,25 @@ InitThreadCallback(PETHREAD Thread)
|
|||
ptiCurrent->ppi->usi.wShowWindow = (WORD)ProcessParams->ShowWindowFlags;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFirstThread)
|
||||
{
|
||||
/* Note: Only initialize once so it can be set back to 0 after being used */
|
||||
if (ProcessParams->WindowFlags & STARTF_USEHOTKEY)
|
||||
ptiCurrent->ppi->dwHotkey = HandleToUlong(ProcessParams->StandardInput);
|
||||
/* TODO:
|
||||
else if (ProcessParams->ShellInfo.Buffer)
|
||||
..->dwHotkey = ParseShellInfo(ProcessParams->ShellInfo.Buffer, L"hotkey.");
|
||||
*/
|
||||
|
||||
if (ProcessParams->WindowFlags & STARTF_SHELLPRIVATE)
|
||||
{
|
||||
/* We need to validate this handle because it can also be a HICON */
|
||||
HMONITOR hMonitor = (HMONITOR)ProcessParams->StandardOutput;
|
||||
if (hMonitor && UserGetMonitorObject(hMonitor))
|
||||
ptiCurrent->ppi->hMonitor = hMonitor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1718,13 +1718,17 @@ IntFixWindowCoordinates(CREATESTRUCTW* Cs, PWND ParentWindow, DWORD* dwShowMode)
|
|||
/* default positioning for overlapped windows */
|
||||
if(!(Cs->style & (WS_POPUP | WS_CHILD)))
|
||||
{
|
||||
PMONITOR pMonitor;
|
||||
PMONITOR pMonitor = NULL;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParams;
|
||||
PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
|
||||
|
||||
pMonitor = UserGetPrimaryMonitor();
|
||||
if (ppi && ppi->hMonitor)
|
||||
pMonitor = UserGetMonitorObject(ppi->hMonitor);
|
||||
if (!pMonitor)
|
||||
pMonitor = UserGetPrimaryMonitor();
|
||||
|
||||
/* Check if we don't have a monitor attached yet */
|
||||
if(pMonitor == NULL)
|
||||
if (pMonitor == NULL)
|
||||
{
|
||||
Cs->x = Cs->y = 0;
|
||||
Cs->cx = 800;
|
||||
|
@ -2575,6 +2579,16 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
|
|||
co_IntUserManualGuiCheck(TRUE);
|
||||
}
|
||||
|
||||
/* Set the hotkey */
|
||||
if (!(Window->style & (WS_POPUP | WS_CHILD)) || (Window->ExStyle & WS_EX_APPWINDOW))
|
||||
{
|
||||
if (pti->ppi->dwHotkey)
|
||||
{
|
||||
co_IntSendMessage(UserHMGetHandle(Window), WM_SETHOTKEY, pti->ppi->dwHotkey, 0);
|
||||
pti->ppi->dwHotkey = 0; /* Only the first suitable window gets the hotkey */
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("co_UserCreateWindowEx(%wZ): Created window %p\n", ClassName, hWnd);
|
||||
ret = Window;
|
||||
|
||||
|
|
Loading…
Reference in a new issue