[WIN32SS:NTUSER] Implement "Window Snap" feature (#1226)
[reactos.git] / win32ss / user / ntuser / defwnd.c
index eb72841..d00d9aa 100644 (file)
@@ -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: