https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7e396787ed00a39390314…
commit 7e396787ed00a3939031447725f79697a41878e1
Author: Denis Malikov <Getequ(a)users.noreply.github.com>
AuthorDate: Tue Jan 15 20:36:41 2019 +0700
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Jan 15 14:36:41 2019 +0100
[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
---
win32ss/user/ntuser/defwnd.c | 86 +++++++++++++++++++++++++++++++++++++++++
win32ss/user/ntuser/hotkey.c | 13 +++++++
win32ss/user/ntuser/hotkey.h | 6 +++
win32ss/user/ntuser/input.c | 5 +++
win32ss/user/ntuser/nonclient.c | 72 ++++++++++++++++++++++++++++++++--
5 files changed, 178 insertions(+), 4 deletions(-)
diff --git a/win32ss/user/ntuser/defwnd.c b/win32ss/user/ntuser/defwnd.c
index eb7284150c..d00d9aa853 100644
--- a/win32ss/user/ntuser/defwnd.c
+++ b/win32ss/user/ntuser/defwnd.c
@@ -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:
diff --git a/win32ss/user/ntuser/hotkey.c b/win32ss/user/ntuser/hotkey.c
index f393906b20..02b504fe66 100644
--- a/win32ss/user/ntuser/hotkey.c
+++ b/win32ss/user/ntuser/hotkey.c
@@ -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)
{
diff --git a/win32ss/user/ntuser/hotkey.h b/win32ss/user/ntuser/hotkey.h
index b965677417..e86452204c 100644
--- a/win32ss/user/ntuser/hotkey.h
+++ b/win32ss/user/ntuser/hotkey.h
@@ -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);
diff --git a/win32ss/user/ntuser/input.c b/win32ss/user/ntuser/input.c
index e4dbbabba0..520ccca9eb 100644
--- a/win32ss/user/ntuser/input.c
+++ b/win32ss/user/ntuser/input.c
@@ -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();
diff --git a/win32ss/user/ntuser/nonclient.c b/win32ss/user/ntuser/nonclient.c
index 8f45582142..7a5fcc445e 100644
--- a/win32ss/user/ntuser/nonclient.c
+++ b/win32ss/user/ntuser/nonclient.c
@@ -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);
}