summaryrefslogtreecommitdiff
path: root/src/external/LooplessSizeMove.c
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrik.ramaekers@protonmail.com>2020-02-05 18:58:55 +0100
committerAldrik Ramaekers <aldrik.ramaekers@protonmail.com>2020-02-05 18:58:55 +0100
commit8c2f35bd1f18b62fff609f3a7d77d4e85b706916 (patch)
tree93e504989bd6182b1b381f1c9bd1b46e0732169a /src/external/LooplessSizeMove.c
parentec901c42d7d5dee13b4c69e4b65fc385d8ffd3a8 (diff)
refactor
Diffstat (limited to 'src/external/LooplessSizeMove.c')
-rw-r--r--src/external/LooplessSizeMove.c864
1 files changed, 0 insertions, 864 deletions
diff --git a/src/external/LooplessSizeMove.c b/src/external/LooplessSizeMove.c
deleted file mode 100644
index 1843cb9..0000000
--- a/src/external/LooplessSizeMove.c
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- LooplessSizeMove.c
- Implements functions for modal-less window resizing and movement in Windows
-
- Author: Nathaniel J Fries
-
- The author asserts no copyright, this work is released into the public domain.
-*/
-
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#ifdef TIME_LOOP
-#include <stdio.h>
-#endif /* TIME_LOOP */
-
-/* fills the MINMAXINFO structure pointed to by the second argument with
- default MIMAX values, then sends WM_GETMINMAXINFO to allow the
- user's Window Procedure to modify it.
-*/
-void GetMinMaxInfo(HWND hwnd, PMINMAXINFO info);
-/* begins the loopless resize/move process */
-LRESULT PrepareSizeMove(HWND hwnd, WPARAM action, DWORD dwPos);
-/* stops the loopless resize/move process.
- if cancel is TRUE, restores window size and position to
- what they were before resizing/moving.
-*/
-void StopSizing(BOOL cancel);
-/* see LooplessSizeMove.h */
-LRESULT CALLBACK LSMProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-BOOLEAN SizingCheck(const MSG *lpmsg);
-
-#define GetWindowLongAW(hwnd, lp)\
-(IsWindowUnicode(hwnd)) ? \
-(GetWindowLongW(hwnd, lp)) : \
-(GetWindowLongA(hwnd, lp))
-#define SendMessageAW(hwnd, msg, wParam, lParam)\
-(IsWindowUnicode(hwnd)) ? \
-(SendMessageW(hwnd, msg, wParam, lParam)) : \
-(SendMessageA(hwnd, msg, wParam, lParam))
-#define PostMessageAW(hwnd, msg, wParam, lParam)\
-(IsWindowUnicode(hwnd)) ? \
-(PostMessageW(hwnd, msg, wParam, lParam)) : \
-(PostMessageA(hwnd, msg, wParam, lParam))
-#define DefWindowProcAW(hwnd, msg, wParam, lParam)\
-(IsWindowUnicode(hwnd)) ? \
-(DefWindowProcW(hwnd, msg, wParam, lParam)) : \
-(DefWindowProcA(hwnd, msg, wParam, lParam))
-
-#define RECTWIDTH(r) ((r).right - (r).left)
-#define RECTHEIGHT(r) ((r).bottom - (r).top)
-
-#define LSM_LEFT 0x01
-#define LSM_TOP 0x02
-#define LSM_RIGHT 0x04
-#define LSM_BOTTOM 0x08
-#define LSM_CAPTION 0x00
-#define LSM_NOGRAB 0xF0
-
-#define LSM_SHAKE_MINTIME 20 /* minimum time between bothering */
-#define LSM_SHAKE_MAXTIME 1000 /* maximum time between movements for "shake" effect */
-#define LSM_SHAKE_STATE_MAXIMIZED 1
-#define LSM_SNAP_HELPER_CLASS "LSM_SNAP_HELPER"
-/*
- information required to reverse a "shake" action.
-*/
-typedef struct _SHAKERESTORENODE
-{
- HWND hwnd;
- WINDOWPLACEMENT place;
- struct _SHAKERESTORENODE *next;
-} SHAKERESTORENODE, *PSHAKERESTORENODE;
-typedef struct
-{
- DWORD dwPrevTime;
- WORD wDir;
- WORD wCount;
- SHAKERESTORENODE *restoreList;
-} SHAKEDATA;
-typedef BOOL (*SHAKEFOREACHFN)(PSHAKERESTORENODE, LPARAM);
-
-typedef struct
-{
- HWND helperWindow;
- WORD isSnapped;
- WORD snapType; /* LSM_TOP, LSM_LEFT, LSM_RIGHT */
- RECT rcWork;
- RECT rcRestore;
-} SNAPDATA;
-
-/* holds all data that needs to be held on to for resizing */
-typedef struct
-{
- HWND hwnd;
- MINMAXINFO minmax;
- RECT rcWin;
- RECT rcOrig;
- POINT ptCapture;
- LONG grab;
- SHAKEDATA shake;
- SNAPDATA snap;
-} SIZEMOVEDATA;
-
-DWORD dwSizeMoveTlsIndex = 0;
-#define LSMTlsCheck() if(dwSizeMoveTlsIndex == 0){ dwSizeMoveTlsIndex = TlsAlloc(); }
-#define LSMSet(data) TlsSetValue(dwSizeMoveTlsIndex, data)
-#define LSMGet() TlsGetValue(dwSizeMoveTlsIndex)
-
-void GetMinMaxInfo(HWND hwnd, PMINMAXINFO info)
-{
- RECT rc;
- LONG style = GetWindowLongAW(hwnd, GWL_STYLE);
- LONG altStyle = ((style & WS_CAPTION) == WS_CAPTION)?
- (style & ~WS_BORDER):(style);
-
- /* calculate the default values in case WindowProc does not respond */
- GetClientRect(GetParent(hwnd), &rc);
- AdjustWindowRectEx(&rc, altStyle, ((style & WS_POPUP) && GetMenu(hwnd)),
- GetWindowLongAW(hwnd, GWL_EXSTYLE));
- info->ptMaxPosition.x = rc.left;
- info->ptMaxPosition.y = rc.top;
- info->ptMaxSize.x = rc.right - rc.left;
- info->ptMaxSize.y = rc.bottom - rc.top;
- if(style & WS_CAPTION)
- {
- info->ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
- info->ptMaxTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
- }
- else
- {
- /* why not zero? this is what ReactOS and presumably Wine do,
- and they're the experts at replicating Windows UI behavior */
- info->ptMinTrackSize.x = info->ptMaxPosition.x * -2;
- info->ptMaxTrackSize.y = info->ptMaxPosition.y * -2;
- }
- info->ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
- info->ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
-
- /* ask Window proc to make any changes */
- SendMessageAW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)info);
-}
-
-BOOL ForEachShakeNodeFree(PSHAKERESTORENODE node, LPARAM ignore)
-{
- LocalFree(node);
- return TRUE;
-}
-BOOL ForEachShakeNode(SHAKEDATA *pShake, SHAKEFOREACHFN fn, LPARAM lParam)
-{
- SHAKERESTORENODE *next, *curr;
- BOOL res = TRUE;
- if(pShake->restoreList)
- {
- curr = pShake->restoreList;
- while(res && curr)
- {
- next = curr->next;
- fn(curr, lParam);
- curr = next;
- }
- }
- return res;
-}
-
-void SnapCleanup(SIZEMOVEDATA *sizemove)
-{
- ShowWindow(sizemove->snap.helperWindow, SW_HIDE);
- ZeroMemory(&sizemove->snap.rcWork, sizeof(RECT));
-}
-
-LRESULT WINAPI SnapHelperWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch(msg)
- {
- case WM_PAINT:
- {
- SIZEMOVEDATA *sizemove = LSMGet();
- HDC hDC = GetDC(hwnd);
- HPEN hPen = CreatePen(PS_INSIDEFRAME, 1, GetSysColor(COLOR_HIGHLIGHT));
- LOGBRUSH blog = { BS_HOLLOW, 0, 0 };
- HBRUSH hBrush = CreateBrushIndirect(&blog);
- if(!sizemove || !hDC || !hPen || !hBrush)
- break;
-
- SelectObject(hDC, hPen);
- SelectObject(hDC, hBrush);
-
- Rectangle(hDC, 0, 0, RECTWIDTH(sizemove->snap.rcWork), RECTHEIGHT(sizemove->snap.rcWork));
-
- DeleteObject(hBrush);
- DeleteObject(hPen);
- break;
- }
- default:
- {
- break;
- }
- }
- return DefWindowProcA(hwnd, msg, wParam, lParam);
-}
-
-LRESULT PrepareSizeMove(HWND hwnd, WPARAM action, DWORD dwPos)
-{
- WINDOWINFO winfo;
- SIZEMOVEDATA *sm;
- RECT rcClipCursor;
-
- winfo.cbSize = sizeof(WINDOWINFO);
- /* most likely not a valid window */
- if(GetWindowInfo(hwnd, &winfo) == FALSE)
- return 0;
- /* can't move or resize an invisible window */
- if(!IsWindowVisible(hwnd))
- return 0;
- /* can't resize a window without the resizing border */
- if((action & 0xfff0) == SC_MOVE && !(winfo.dwStyle & WS_SIZEBOX))
- return 0;
-
- /*
- if another window on this thread has capture,
- it might be using this too...
- tell it to clean up before setting the tls value
- */
- ReleaseCapture();
-
- if(!(sm = LSMGet()))
- {
- WNDCLASSA wndcls;
- HINSTANCE hInstance = GetModuleHandleA(NULL);
- sm = LocalAlloc(0, sizeof(SIZEMOVEDATA));
- if(!sm)
- {
- /* error */
- return 1;
- }
- if(!LSMSet(sm))
- {
- LocalFree(sm);
- return 2;
- }
- /* prevent potential crashes and bad initialization bugs */
- ZeroMemory(sm, sizeof(SIZEMOVEDATA));
-
- if(!GetClassInfoA(hInstance, LSM_SNAP_HELPER_CLASS, &wndcls))
- {
- ZeroMemory(&wndcls, sizeof(WNDCLASSA));
- wndcls.style = CS_SAVEBITS;
- wndcls.hbrBackground = GetSysColorBrush(COLOR_HOTLIGHT);
- wndcls.lpszClassName = LSM_SNAP_HELPER_CLASS;
- wndcls.lpfnWndProc = SnapHelperWinProc;
- wndcls.hInstance = hInstance;
- RegisterClassA(&wndcls);
- }
- /* WS_EX_LAYERED: window is not fully opaque
- WS_EX_TRANSPARENT: mouse events pass through layered window
- ES_EX_NOACTIVATE: window cannot be activated by user (no loss of mouse capture or keyboard focus)
- */
- sm->snap.helperWindow = CreateWindowExA(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE,
- LSM_SNAP_HELPER_CLASS, "", WS_POPUP /* no borders */, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
- if(sm->snap.helperWindow)
- {
- SetLayeredWindowAttributes(sm->snap.helperWindow, 0, 75, LWA_ALPHA);
- }
- }
- else if(sm->hwnd != hwnd)
- {
- /* forget shake data, consistent with Windows 7 behavior */
- ForEachShakeNode(&sm->shake, ForEachShakeNodeFree, 0);
- SnapCleanup(sm);
- sm->shake.restoreList = NULL;
- }
- sm->grab = action & 0x000f;
- sm->hwnd = hwnd;
- GetMinMaxInfo(hwnd, &sm->minmax);
- sm->rcWin = winfo.rcWindow;
- if(winfo.dwStyle & WS_CHILD)
- {
- /* map points into the parent's coordinate space */
- HWND parent = GetParent(hwnd);
- MapWindowPoints(0, parent, (LPPOINT)&sm->rcWin, 2);
- GetWindowRect(parent, &rcClipCursor);
- MapWindowPoints(parent, HWND_DESKTOP, (LPPOINT)&rcClipCursor, 2);
- }
- else if(!(winfo.dwExStyle & WS_EX_TOPMOST))
- {
- SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcClipCursor, 0);
- }
- else
- {
- rcClipCursor.left = rcClipCursor.top = 0;
- rcClipCursor.right = GetSystemMetrics(SM_CXSCREEN);
- rcClipCursor.bottom = GetSystemMetrics(SM_CYSCREEN);
- }
- sm->rcOrig = sm->rcWin;
-
- sm->ptCapture.x = (short)LOWORD(dwPos);
- sm->ptCapture.y = (short)HIWORD(dwPos);
- //ClipCursor(&rcClipCursor);
-
-
- /* notify WinProc we're beginning, but return instead of looping */
- SendMessageAW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
- if(GetCapture() != hwnd)
- {
- SetCapture(hwnd);
- }
- return 0;
-}
-
-LRESULT CALLBACK LSMProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- LSMTlsCheck();
- switch(msg)
- {
- case WM_NCLBUTTONDOWN:
- {
- switch(wParam)
- {
- case HTLEFT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_LEFT, lParam);
- case HTTOPLEFT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_LEFT | LSM_TOP, lParam);
- case HTBOTTOMLEFT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_LEFT | LSM_BOTTOM, lParam);
- case HTRIGHT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_RIGHT, lParam);
- case HTTOPRIGHT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_RIGHT | LSM_TOP, lParam);
- case HTBOTTOMRIGHT:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_RIGHT | LSM_BOTTOM, lParam);
- case HTTOP:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_TOP, lParam);
- case HTBOTTOM:
- return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_SIZE | LSM_BOTTOM, lParam);
- case HTCAPTION:
- //return SendMessageAW(hwnd, WM_SYSCOMMAND, SC_MOVE | LSM_CAPTION, lParam);
- default:
- break;
- }
- }
- case WM_SYSCOMMAND:
- {
- switch(wParam & 0xfff0)
- {
- case SC_SIZE:
- /* begin resize 'loop' */
- return PrepareSizeMove(hwnd, wParam, lParam);
- default:
- break;
- }
- break;
- }
- case WM_CAPTURECHANGED:
- {
- /* nothing we can do; stop resizing & do clean-up */
- SIZEMOVEDATA *sizemove = LSMGet();
- if(sizemove && (HWND)lParam != sizemove->hwnd)
- {
- SendMessageAW(sizemove->hwnd, WM_EXITSIZEMOVE, 0, 0);
- ClipCursor(NULL);
- /* no longer unset LSM data:
- 1) never really needed to
- 2) necessary to hold onto shake data
- */
- if(GetForegroundWindow() != sizemove->hwnd)
- {
- /* forget shake data, consistent with Windows 7 behavior */
- ForEachShakeNode(&sizemove->shake, ForEachShakeNodeFree, 0);
- sizemove->shake.restoreList = NULL;
- }
- sizemove->shake.wCount = 0;
- sizemove->shake.wDir = 0;
- sizemove->shake.dwPrevTime = 0;
- SnapCleanup(sizemove);
-
- sizemove->grab = LSM_NOGRAB;
- }
- }
- default:
- break;
- }
- return DefWindowProcAW(hwnd, msg, wParam, lParam);
-}
-
-BOOL CALLBACK EnumWindowsShakeMinimize(HWND hwnd, LPARAM lParam)
-{
- SIZEMOVEDATA *sizemove = (SIZEMOVEDATA *)(lParam);
- if(hwnd != sizemove->hwnd && IsWindowVisible(hwnd) && !IsIconic(hwnd))
- {
- SHAKERESTORENODE *pNode = 0;
- WINDOWPLACEMENT tPlace;
- /* note: there are a few shell-created windows that glitch up graphically if you try to minimize them */
- DWORD dwProcID, dwShellPID;
- GetWindowThreadProcessId(hwnd, &dwProcID);
- GetWindowThreadProcessId(GetShellWindow(), &dwShellPID);
- if(dwProcID == dwShellPID)
- {
- return TRUE;
- }
- /* note: not supposed to minimize "parent application" windows. I assume this means windows of
- the window's application?
- See: http://social.technet.microsoft.com/Forums/windows/en-US/b047378c-2a5a-4661-a871-cec459cb9bdc/aeroshake-not-working?forum=w7itproui
- */
- GetWindowThreadProcessId(sizemove->hwnd, &dwShellPID);
- if(dwProcID == dwShellPID)
- {
- return TRUE;
- }
-
-
- pNode = LocalAlloc(0, sizeof(SHAKERESTORENODE));
- if(!pNode)
- return FALSE;
-
- pNode->hwnd = hwnd;
-
- pNode->place.length = sizeof(WINDOWPLACEMENT);
- pNode->place.flags = WPF_ASYNCWINDOWPLACEMENT;
- GetWindowPlacement(hwnd, &pNode->place);
- tPlace = pNode->place;
- tPlace.showCmd = SW_SHOWMINNOACTIVE;
- SetWindowPlacement(hwnd, &tPlace);
-
- pNode->next = sizemove->shake.restoreList;
- sizemove->shake.restoreList = pNode;
- }
- return TRUE;
-}
-
-BOOL ForEachShakeNodeRestore(PSHAKERESTORENODE node, LPARAM ignore)
-{
- if(node)
- {
- SetWindowPlacement(node->hwnd, &node->place);
- LocalFree(node);
- return TRUE;
- }
- return FALSE;
-}
-
-void ShakeCheck(const MSG *lpmsg, SIZEMOVEDATA *sizemove)
-{
- static DWORD dwShakeDisabled = 2;
- WORD dir = 0;
- int dx, dy;
- if(lpmsg->message != WM_MOUSEMOVE && lpmsg->message != WM_NCMOUSEMOVE)
- return;
- if(dwShakeDisabled == 2)
- {
- HKEY hKey;
- DWORD dwSizeDW = 4;
- DWORD dwType = REG_DWORD;
- if(/* major version number */LOBYTE(LOWORD(GetVersion())) < 6)
- {
- dwShakeDisabled = 1;
- }
- else
- {
- dwShakeDisabled = 0;
- if(RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Policies\\Microsoft\\Windows\\Explorer", 0, KEY_READ, &hKey)
- == ERROR_SUCCESS)
- {
- RegQueryValueExA(hKey, "NoWindowMinimizingShortcuts", 0, &dwType, (LPBYTE)&dwShakeDisabled, &dwSizeDW);
- RegCloseKey(hKey);
- }
- }
- }
- if(dwShakeDisabled)
- return;
- if(lpmsg->time - sizemove->shake.dwPrevTime < LSM_SHAKE_MINTIME)
- return;
-
- dx = lpmsg->pt.x - sizemove->ptCapture.x;
- dy = lpmsg->pt.y - sizemove->ptCapture.y;
- if(dx > 8)
- dir |= LSM_LEFT;
- else if(dx < -8)
- dir |= LSM_RIGHT;
- if(dy > 8)
- dir |= LSM_TOP;
- else if(dy < -8)
- dir |= LSM_BOTTOM;
-
- if(dir && ((lpmsg->time - sizemove->shake.dwPrevTime) < LSM_SHAKE_MAXTIME) && (dir != sizemove->shake.wDir))
- {
- /* Do Shake */
- sizemove->shake.wCount++;
- if(sizemove->shake.wCount >= 3)
- {
- if(sizemove->shake.restoreList)
- {
- ForEachShakeNode(&sizemove->shake, ForEachShakeNodeRestore, (LPARAM)sizemove);
- sizemove->shake.restoreList = 0;
- }
- else
- {
- EnumWindows(EnumWindowsShakeMinimize, (LPARAM)(sizemove));
- }
- RedrawWindow(GetDesktopWindow(), NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE
- | RDW_ALLCHILDREN | RDW_UPDATENOW);
- sizemove->shake.wCount = 0;
- }
- }
- else
- {
- sizemove->shake.wCount = 0;
- }
- sizemove->shake.dwPrevTime = lpmsg->time;
- sizemove->shake.wDir = dir;
-}
-
-void SnapCheck(POINT pt, SIZEMOVEDATA *sizemove)
-{
- static DWORD dwSnapActive = 2;
- HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
- MONITORINFO minfo;
-
- if(dwSnapActive == 2)
- {
- HKEY hKey;
- DWORD dwSizeDW = 4;
- DWORD dwType = REG_DWORD;
- dwSnapActive = 0;
- if(/* major version number */LOBYTE(LOWORD(GetVersion())) >= 6)
- {
- if(RegOpenKeyExA(HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_READ, &hKey)
- == ERROR_SUCCESS)
- {
- RegQueryValueExA(hKey, "WindowArrangementActive", 0, &dwType, (LPBYTE)&dwSnapActive, &dwSizeDW);
- RegCloseKey(hKey);
- }
- }
- }
- if(!dwSnapActive)
- return;
-
- minfo.cbSize = sizeof(MONITORINFO);
- if(monitor == NULL)
- return;
- if(!GetMonitorInfo(monitor, (LPMONITORINFO)&minfo))
- return;
- /* unsnap maximized windows */
- if(IsZoomed(sizemove->hwnd))
- {
- WINDOWPLACEMENT place;
- int dx, w;
- place.length = sizeof(WINDOWPLACEMENT);
- GetWindowPlacement(sizemove->hwnd, &place);
- place.showCmd = SW_RESTORE;
- OffsetRect(&place.rcNormalPosition, (sizemove->rcWin.left - place.rcNormalPosition.left),
- (sizemove->rcWin.top - place.rcNormalPosition.top));
- w = RECTWIDTH(place.rcNormalPosition);
- if((dx = (place.rcNormalPosition.left - sizemove->ptCapture.x)) > 0)
- {
- place.rcNormalPosition.left += dx << 1;
- place.rcNormalPosition.right = place.rcNormalPosition.left + w;
- }
- if((dx = (sizemove->ptCapture.x - place.rcNormalPosition.right)) > 0)
- {
- place.rcNormalPosition.left += dx << 1;
- place.rcNormalPosition.right = place.rcNormalPosition.left + w;
- }
- sizemove->rcWin = place.rcNormalPosition;
- SetWindowPlacement(sizemove->hwnd, &place);
- /* don't return here, it's possible to unsnap without leaving the top of the screen */
- }
- else if(sizemove->snap.isSnapped)
- {
- /* TODO: Aero snap lets you drag half-screen snapped windows across the top of the screen */
-
- sizemove->rcWin.right = sizemove->snap.rcRestore.right;
- sizemove->rcWin.bottom = sizemove->snap.rcRestore.bottom;
- sizemove->snap.isSnapped = 0;
- return;
- }
- sizemove->snap.rcWork = minfo.rcWork;
- if(pt.x <= minfo.rcWork.left)
- {
- /* left side stretch */
- sizemove->snap.rcWork.right = (RECTWIDTH(minfo.rcWork) - GetSystemMetrics(SM_CXFRAME)) >> 1;
- sizemove->snap.snapType = LSM_LEFT;
- }
- else if(pt.x+1 >= minfo.rcWork.right)
- {
- /* right side stretch */
- sizemove->snap.rcWork.left = (minfo.rcWork.left + RECTWIDTH(minfo.rcWork) + GetSystemMetrics(SM_CXFRAME)) >> 1;
- sizemove->snap.snapType = LSM_RIGHT;
- }
- else if(pt.y <= minfo.rcWork.top)
- {
- /* full stretch */
- sizemove->snap.snapType = LSM_TOP;
- }
- else
- {
- /* not snapping, clean up snap state */
- SnapCleanup(sizemove);
- return;
- }
- SetWindowPos(sizemove->snap.helperWindow, HWND_TOPMOST,
- sizemove->snap.rcWork.left, sizemove->snap.rcWork.top,
- RECTWIDTH(sizemove->snap.rcWork), RECTHEIGHT(sizemove->snap.rcWork),
- SWP_NOACTIVATE);
- ShowWindow(sizemove->snap.helperWindow, SW_SHOWNA);
-}
-
-void SnapFinalize(SIZEMOVEDATA *sizemove)
-{
- if(sizemove->snap.rcWork.left != sizemove->snap.rcWork.right
- && sizemove->snap.rcWork.top != sizemove->snap.rcWork.bottom)
- {
- if(sizemove->snap.snapType == LSM_TOP)
- {
- /* Aero appears to animate this... so we will too */
- ShowWindow(sizemove->hwnd, SW_MAXIMIZE);
- }
- else
- {
- SetWindowPos(sizemove->hwnd, 0, sizemove->snap.rcWork.left, sizemove->snap.rcWork.top,
- RECTWIDTH(sizemove->snap.rcWork), RECTHEIGHT(sizemove->snap.rcWork), 0);
- ZeroMemory(&sizemove->snap.rcRestore, sizeof(RECT));
- sizemove->snap.rcRestore.right = RECTWIDTH(sizemove->rcWin);
- sizemove->snap.rcRestore.bottom = RECTWIDTH(sizemove->rcWin);
- sizemove->snap.isSnapped = 1;
- }
- }
- SnapCleanup(sizemove);
-}
-
-BOOLEAN SizingCheck(const MSG *lpmsg)
-{
- SIZEMOVEDATA *sizemove = LSMGet();
- POINT pt = lpmsg->pt;
- int dx = 0, dy = 0;
- /*
- Discussion of rev3 changes.
- There was a bug in previous revisions that would cause
- the resize state to continue even if the Window lost
- mouse capture. Windows provides notification of losing
- mouse capture, but it crashes the program to take capture
- back while processing that message.
- So, we choose to yield to this other program and stop resizing.
- This is probably user32 behavior anyway.
- Windows also sends this notification in response to calling ReleaseCapture,
- so all clean-up code has been moved to the handler.
- This also allowed us to eliminate the function StopSizing.
- */
- if(!sizemove) /* not sizing */
- return 0;
- if(sizemove->grab == LSM_NOGRAB) /* not sizing */
- return 0;
- if(lpmsg->hwnd != sizemove->hwnd) /* wrong window */
- return 0;
- if(lpmsg->message == WM_NCLBUTTONUP || lpmsg->message == WM_LBUTTONUP)
- {
- SnapFinalize(sizemove);
- ReleaseCapture();
- return 1;
- }
- if(lpmsg->message == WM_KEYDOWN)
- {
- switch(lpmsg->wParam)
- {
- case VK_RETURN:
- ReleaseCapture();
- return 1;
- case VK_ESCAPE:
- {
- SetWindowPos(sizemove->hwnd, 0, sizemove->rcOrig.left, sizemove->rcOrig.top,
- RECTWIDTH(sizemove->rcOrig), RECTHEIGHT(sizemove->rcOrig), 0);
- ReleaseCapture();
- return 1;
- }
- case VK_UP:
- pt.y-=8;
- break;
- case VK_DOWN:
- pt.y+=8;
- break;
- case VK_LEFT:
- pt.x-=8;
- break;
- case VK_RIGHT:
- pt.x+=8;
- break;
- default:
- break;
- }
- }
-
- /* used to handle WM_MOUSEMOVE. This was unnecessary code */
-
- dx = pt.x - sizemove->ptCapture.x;
- dy = pt.y - sizemove->ptCapture.y;
- if(dx || dy)
- {
- BOOL changeCursor = (lpmsg->message == WM_KEYDOWN);
- WPARAM wpHit = 0;
-#ifdef TIME_LOOP
- LARGE_INTEGER pfBegin;
- LARGE_INTEGER pfDraw;
- LARGE_INTEGER pfFinal;
- LARGE_INTEGER pfFreq;
- QueryPerformanceFrequency(&pfFreq);
- QueryPerformanceCounter(&pfBegin);
-#endif
-
- if(sizemove->grab == LSM_CAPTION)
- {
- ShakeCheck(lpmsg, sizemove);
- SnapCheck(pt, sizemove);
- OffsetRect(&sizemove->rcWin, dx, dy);
- }
- else
- {
- /* note on minmax correction
- if you do not correct the capture pos (set later from `pt`),
- window will expand massively if user pulls back mouse
- after failing to shrink when resizing from the
- bottom or the right borders.
- */
- /* when resizing using keys, Windows also moves the cursor */
- if(sizemove->grab & LSM_LEFT)
- {
- int lmax = sizemove->rcWin.right - sizemove->minmax.ptMaxTrackSize.x;
- int lmin = sizemove->rcWin.right - sizemove->minmax.ptMinTrackSize.x;
- if(sizemove->rcWin.left + dx < lmax)
- {
- sizemove->rcWin.left = lmax;
- }
- else if(sizemove->rcWin.left + dx > lmin)
- {
- sizemove->rcWin.left = lmin;
- }
- else
- {
- sizemove->rcWin.left += dx;
- }
- pt.x = sizemove->rcWin.left;
- wpHit = WMSZ_LEFT;
- }
- else if(sizemove->grab & LSM_RIGHT)
- {
- int rmax = sizemove->rcWin.left + sizemove->minmax.ptMaxTrackSize.x;
- int rmin = sizemove->rcWin.left + sizemove->minmax.ptMinTrackSize.x;
- if(sizemove->rcWin.right + dx > rmax)
- {
- sizemove->rcWin.right = rmax;
- }
- else if(sizemove->rcWin.right + dx < rmin)
- {
- sizemove->rcWin.right = rmin;
- }
- else
- {
- sizemove->rcWin.right += dx;
- }
- pt.x = sizemove->rcWin.right;
- wpHit = WMSZ_RIGHT;
- }
- if(sizemove->grab & LSM_TOP)
- {
- int tmax = sizemove->rcWin.bottom - sizemove->minmax.ptMaxTrackSize.y;
- int tmin = sizemove->rcWin.bottom - sizemove->minmax.ptMinTrackSize.y;
- if(sizemove->rcWin.top + dy < tmax)
- {
- sizemove->rcWin.top = tmax;
- }
- else if(sizemove->rcWin.top + dy > tmin)
- {
- sizemove->rcWin.top = tmin;
- }
- else
- {
- sizemove->rcWin.top += dy;
- }
- pt.y = sizemove->rcWin.top;
- if(wpHit == WMSZ_LEFT)
- {
- wpHit = WMSZ_TOPLEFT;
- }
- else if(wpHit == WMSZ_RIGHT)
- {
- wpHit = WMSZ_TOPRIGHT;
- }
- else
- {
- wpHit = WMSZ_TOP;
- }
- }
- else if(sizemove->grab & LSM_BOTTOM)
- {
- int bmax = sizemove->rcWin.top + sizemove->minmax.ptMaxTrackSize.y;
- int bmin = sizemove->rcWin.top + sizemove->minmax.ptMinTrackSize.y;
- if(sizemove->rcWin.bottom + dy > bmax)
- {
- sizemove->rcWin.bottom = bmax;
- }
- else if(sizemove->rcWin.bottom + dy < bmin)
- {
- sizemove->rcWin.bottom = bmin;
- }
- else
- {
- sizemove->rcWin.bottom += dy;
- }
- pt.y = sizemove->rcWin.bottom;
- if(wpHit == WMSZ_LEFT)
- {
- wpHit = WMSZ_BOTTOMLEFT;
- }
- else if(wpHit == WMSZ_RIGHT)
- {
- wpHit = WMSZ_BOTTOMRIGHT;
- }
- else
- {
- wpHit = WMSZ_BOTTOM;
- }
- }
- }
-#ifdef TIME_LOOP
- QueryPerformanceCounter(&pfDraw);
-#endif
- SendMessageAW(sizemove->hwnd, WM_SIZING, wpHit, (LPARAM)&sizemove->rcWin);
- SetWindowPos(sizemove->hwnd, 0, sizemove->rcWin.left, sizemove->rcWin.top,
- RECTWIDTH(sizemove->rcWin), RECTHEIGHT(sizemove->rcWin), 0);
-
- sizemove->ptCapture = pt;
- /* when resizing using keys, Windows also moves the cursor */
- if(changeCursor)
- SetCursorPos(pt.x, pt.y);
-#ifdef TIME_LOOP
- QueryPerformanceCounter(&pfFinal);
- if(1)
- {
- double msTotal, msDraw;
- msTotal = (double)(*(long long*)(&pfFinal) - *(long long *)(&pfBegin)) / (*(long long *)(&pfFreq) / 1000);
- msDraw = (double)(*(long long*)(&pfFinal) - *(long long *)(&pfDraw)) / (*(long long *)(&pfFreq) / 1000);
- printf("draw time: %.03fms\ntotal: %.03fms\n", msDraw, msTotal);
- }
-#endif
- }
- return 1;
-}
-
-void LSMCleanup()
-{
- SIZEMOVEDATA *sm = LSMGet();
- if(sm)
- {
- if(sm->shake.restoreList)
- {
- ForEachShakeNode(&sm->shake, ForEachShakeNodeFree, 0);
- }
- if(sm->snap.helperWindow)
- {
- DestroyWindow(sm->snap.helperWindow);
- }
- LocalFree(sm);
- LSMSet(NULL);
- }
-}