mirror of
https://github.com/reactos/reactos.git
synced 2024-12-01 23:43:32 +08:00
[WIN32SS:NTUSER] Implement "Window Snap" feature (#1226)
Implemented the following actions: stick the window on the left/right or maximize it, with the following shortcuts: - Win key + Arrows; - drag to left/right screen border; - double-click on top/bottom. CORE-12845
This commit is contained in:
parent
c95f335893
commit
7e396787ed
@ -781,6 +781,92 @@ IntDefWindowProc(
|
||||
co_IntSendMessage(UserHMGetHandle(Wnd), WM_CONTEXTMENU, (WPARAM)UserHMGetHandle(Wnd), MAKELPARAM(-1, -1));
|
||||
}
|
||||
}
|
||||
if (IS_KEY_DOWN(gafAsyncKeyState, VK_LWIN) || IS_KEY_DOWN(gafAsyncKeyState, VK_RWIN))
|
||||
{
|
||||
PWND topWnd = UserGetWindowObject(UserGetForegroundWindow());
|
||||
|
||||
if (topWnd)
|
||||
{
|
||||
if (wParam == VK_DOWN)
|
||||
{
|
||||
co_IntSendMessage(UserHMGetHandle(topWnd), WM_SYSCOMMAND, (topWnd->style & WS_MAXIMIZE) ? SC_RESTORE : SC_MINIMIZE, lParam);
|
||||
}
|
||||
else
|
||||
if (wParam == VK_UP)
|
||||
{
|
||||
RECT currentRect = (topWnd->InternalPos.NormalRect.right == topWnd->InternalPos.NormalRect.left) ||
|
||||
(topWnd->InternalPos.NormalRect.top == topWnd->InternalPos.NormalRect.bottom)
|
||||
? topWnd->rcWindow
|
||||
: topWnd->InternalPos.NormalRect;
|
||||
co_IntSendMessage(UserHMGetHandle(topWnd), WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
||||
|
||||
// save normal rect if maximazing snapped window
|
||||
topWnd->InternalPos.NormalRect = currentRect;
|
||||
}
|
||||
else
|
||||
if (wParam == VK_LEFT || wParam == VK_RIGHT)
|
||||
{
|
||||
RECT snapRect;
|
||||
RECT normalRect;
|
||||
RECT windowRect;
|
||||
BOOL snapped = FALSE;
|
||||
normalRect = topWnd->InternalPos.NormalRect;
|
||||
snapped = (normalRect.left != 0
|
||||
&& normalRect.right != 0
|
||||
&& normalRect.top != 0
|
||||
&& normalRect.bottom != 0);
|
||||
|
||||
if (topWnd->style & WS_MAXIMIZE)
|
||||
{
|
||||
co_IntSendMessage(UserHMGetHandle(topWnd), WM_SYSCOMMAND, SC_RESTORE, lParam);
|
||||
snapped = FALSE;
|
||||
}
|
||||
|
||||
windowRect = topWnd->rcWindow;
|
||||
|
||||
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &snapRect, 0);
|
||||
if (wParam == VK_LEFT)
|
||||
{
|
||||
snapRect.right = (snapRect.right - snapRect.left) / 2 + snapRect.left;
|
||||
}
|
||||
else // VK_RIGHT
|
||||
{
|
||||
snapRect.left = (snapRect.right - snapRect.left) / 2 + snapRect.left;
|
||||
}
|
||||
|
||||
if (snapped)
|
||||
{
|
||||
// if window was snapped but moved to other location - restore normal size
|
||||
if (snapRect.left != windowRect.left ||
|
||||
snapRect.right != windowRect.right ||
|
||||
snapRect.top != windowRect.top ||
|
||||
snapRect.bottom != windowRect.bottom)
|
||||
{
|
||||
RECT empty = {0, 0, 0, 0};
|
||||
co_WinPosSetWindowPos(topWnd,
|
||||
0,
|
||||
normalRect.left,
|
||||
normalRect.top,
|
||||
normalRect.right - normalRect.left,
|
||||
normalRect.bottom - normalRect.top,
|
||||
0);
|
||||
topWnd->InternalPos.NormalRect = empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
co_WinPosSetWindowPos(topWnd,
|
||||
0,
|
||||
snapRect.left,
|
||||
snapRect.top,
|
||||
snapRect.right - snapRect.left,
|
||||
snapRect.bottom - snapRect.top,
|
||||
0);
|
||||
topWnd->InternalPos.NormalRect = windowRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
|
@ -250,6 +250,19 @@ co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (pHotKey->id == IDHK_SNAP_LEFT ||
|
||||
pHotKey->id == IDHK_SNAP_RIGHT ||
|
||||
pHotKey->id == IDHK_SNAP_UP ||
|
||||
pHotKey->id == IDHK_SNAP_DOWN)
|
||||
{
|
||||
HWND topWnd = UserGetForegroundWindow();
|
||||
if (topWnd)
|
||||
{
|
||||
UserPostMessage(topWnd, WM_KEYDOWN, wVk, 0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!pHotKey->pWnd)
|
||||
{
|
||||
|
@ -16,6 +16,12 @@ typedef struct _HOT_KEY
|
||||
#define IDHK_WINKEY -7
|
||||
#define IDHK_REACTOS -8
|
||||
|
||||
/* Window Snap Hot Keys */
|
||||
#define IDHK_SNAP_LEFT -10
|
||||
#define IDHK_SNAP_RIGHT -11
|
||||
#define IDHK_SNAP_UP -12
|
||||
#define IDHK_SNAP_DOWN -13
|
||||
|
||||
VOID FASTCALL UnregisterWindowHotKeys(PWND Window);
|
||||
VOID FASTCALL UnregisterThreadHotKeys(PTHREADINFO pti);
|
||||
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown);
|
||||
|
@ -202,6 +202,11 @@ RawInputThreadMain(VOID)
|
||||
UserEnterExclusive();
|
||||
// Register the Window hotkey.
|
||||
UserRegisterHotKey(PWND_BOTTOM, IDHK_WINKEY, MOD_WIN, 0);
|
||||
// Register the Window Snap hotkey.
|
||||
UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_LEFT, MOD_WIN, VK_LEFT);
|
||||
UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_RIGHT, MOD_WIN, VK_RIGHT);
|
||||
UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_UP, MOD_WIN, VK_UP);
|
||||
UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_DOWN, MOD_WIN, VK_DOWN);
|
||||
// Register the debug hotkeys.
|
||||
StartDebugHotKeys();
|
||||
UserLeave();
|
||||
|
@ -391,10 +391,59 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
|
||||
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
|
||||
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
|
||||
|
||||
/* Exit on button-up, Return, or Esc */
|
||||
if ((msg.message == WM_LBUTTONUP) ||
|
||||
((msg.message == WM_KEYDOWN) &&
|
||||
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
|
||||
/* Exit on button-up */
|
||||
if (msg.message == WM_LBUTTONUP)
|
||||
{
|
||||
// check for snapping if was moved by caption
|
||||
if (hittest == HTCAPTION)
|
||||
{
|
||||
RECT snapRect;
|
||||
BOOL doSideSnap = FALSE;
|
||||
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &snapRect, 0);
|
||||
|
||||
// snap to left
|
||||
if (pt.x <= snapRect.left)
|
||||
{
|
||||
snapRect.right = (snapRect.right - snapRect.left) / 2 + snapRect.left;
|
||||
doSideSnap = TRUE;
|
||||
}
|
||||
// snap to right
|
||||
if (pt.x >= snapRect.right-1)
|
||||
{
|
||||
snapRect.left = (snapRect.right - snapRect.left) / 2 + snapRect.left;
|
||||
doSideSnap = TRUE;
|
||||
}
|
||||
|
||||
if (doSideSnap)
|
||||
{
|
||||
co_WinPosSetWindowPos(pwnd,
|
||||
0,
|
||||
snapRect.left,
|
||||
snapRect.top,
|
||||
snapRect.right - snapRect.left,
|
||||
snapRect.bottom - snapRect.top,
|
||||
0);
|
||||
pwnd->InternalPos.NormalRect = origRect;
|
||||
}
|
||||
else
|
||||
{
|
||||
// maximize if on dragged to top
|
||||
if (pt.y <= snapRect.top)
|
||||
{
|
||||
co_IntSendMessage(UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
||||
pwnd->InternalPos.NormalRect = origRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Exit on Return or Esc */
|
||||
if (msg.message == WM_KEYDOWN &&
|
||||
(msg.wParam == VK_RETURN || msg.wParam == VK_ESCAPE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
|
||||
{
|
||||
@ -1565,6 +1614,21 @@ NC_HandleNCLButtonDblClk(PWND pWnd, WPARAM wParam, LPARAM lParam)
|
||||
co_IntSendMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_CLOSE, lParam);
|
||||
break;
|
||||
}
|
||||
case HTTOP:
|
||||
case HTBOTTOM:
|
||||
{
|
||||
RECT sizingRect = pWnd->rcWindow, mouseRect;
|
||||
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
|
||||
|
||||
co_WinPosSetWindowPos(pWnd,
|
||||
0,
|
||||
sizingRect.left,
|
||||
mouseRect.top,
|
||||
sizingRect.right - sizingRect.left,
|
||||
mouseRect.bottom - mouseRect.top,
|
||||
0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NC_HandleNCLButtonDown(pWnd, wParam, lParam);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user