[PATCH] winex11.drv: Fix resizable window has not minsize

Zhipeng Zhao near2see at 163.com
Mon Jan 6 03:54:09 CST 2020


When resizing an resizable window, we can resize it smaller than it's
minsize show in Windows, I think it's a bug, and try to fix it.

Signed-off-by: Zhipeng Zhao <near2see at 163.com>
---
 dlls/winex11.drv/mouse.c  | 121 +++++++++++++++++++++++++++++++++++++-
 dlls/winex11.drv/window.c |  14 ++++-
 2 files changed, 131 insertions(+), 4 deletions(-)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 290732fa93..1c5766be09 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -1560,6 +1560,104 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
     return TRUE;
 }
 
+/***********************************************************************
+ *           set_window_minsize
+ */
+void set_window_minsize(HWND hwnd, RECT* sizingRect, int dir, int* minWidth, int* minHeight)
+{
+    Display *display = thread_display();
+    Window win = X11DRV_get_whole_window( hwnd );
+    POINT pos;
+    GetCursorPos(&pos);
+    switch (dir)
+    {
+        case 7: //_NET_WM_MOVERESIZE_SIZE_LEFT:
+        case 3: //_NET_WM_MOVERESIZE_SIZE_RIGHT:
+            if(*minWidth == 0)
+            {
+                FIXME("before top = %i, left = %i, right = %i, bottom = %i, width = %i\n", sizingRect->top, sizingRect->left, sizingRect->right, sizingRect->bottom, sizingRect->right-sizingRect->left);
+                if(dir == 3)
+                {
+                    if(pos.x > sizingRect->right) return;
+                    sizingRect->right = pos.x;
+                    SendMessageW(hwnd, WM_SIZING, WMSZ_RIGHT, sizingRect);
+                }
+                else if(dir == 7)
+                {
+                    if(pos.x < sizingRect->left) return;
+                    sizingRect->left = pos.x;
+                    SendMessageW(hwnd, WM_SIZING, WMSZ_LEFT, sizingRect);
+                }
+                FIXME("after top = %i, left = %i, right = %i, bottom = %i, width = %i\n", sizingRect->top, sizingRect->left, sizingRect->right, sizingRect->bottom, sizingRect->right-sizingRect->left);
+                if((dir == 3 ? sizingRect->right > pos.x : sizingRect->left < pos.x))
+                {
+                    *minWidth = sizingRect->right - sizingRect->left;
+                    XSizeHints* sizehints = XAllocSizeHints();
+                    LONG ret = -1;
+                    XGetWMNormalHints(display, win, sizehints, &ret);
+                    sizehints->flags |= PMinSize;
+                    sizehints->min_width = *minWidth;
+                    XSetWMNormalHints(display, win, sizehints);
+                    XFree(sizehints);
+                    FIXME("minWidth = %i\n", *minWidth);
+                }
+            }
+            break;
+        case  1: //_NET_WM_MOVERESIZE_SIZE_TOP:
+        case  5: //_NET_WM_MOVERESIZE_SIZE_BOTTOM:
+            if(*minHeight == 0)
+            {
+                FIXME("before top = %i, left = %i, right = %i, bottom = %i, width = %i\n", sizingRect->top, sizingRect->left, 
+                        sizingRect->right, sizingRect->bottom, sizingRect->right-sizingRect->left);
+                if(dir == 1)
+                {
+                    if(pos.y < sizingRect->top) return;
+                    sizingRect->top = pos.y;
+                    SendMessageW(hwnd, WM_SIZING, WMSZ_TOP, sizingRect);
+                }
+                else if(dir == 5)
+                {
+                    if(pos.y > sizingRect->top) return;
+                    sizingRect->bottom = pos.y;
+                    SendMessageW(hwnd, WM_SIZING, WMSZ_BOTTOM, sizingRect);
+                }
+                FIXME("after top = %i, left = %i, right = %i, bottom = %i, width = %i\n", sizingRect->top, sizingRect->left, 
+                        sizingRect->right, sizingRect->bottom, sizingRect->right-sizingRect->left);
+                if((dir == 1 ? sizingRect->top < pos.y : sizingRect->bottom > pos.y))
+                {
+                    *minHeight = sizingRect->bottom - sizingRect->top;
+                    XSizeHints* sizehints = XAllocSizeHints();
+                    LONG ret = -1;
+                    XGetWMNormalHints(display, win, sizehints, &ret);
+                    sizehints->flags |= PMinSize;
+                    sizehints->min_height = *minHeight;
+                    XSetWMNormalHints(display, win, sizehints);
+                    XFree(sizehints);
+                    FIXME("minHeight = %i\n", *minHeight);
+                }
+            }
+            break;
+        case 0: //_NET_WM_MOVERESIZE_SIZE_TOPLEFT
+            set_window_minsize(hwnd, sizingRect, 1, minWidth, minHeight);
+            set_window_minsize(hwnd, sizingRect, 7, minWidth, minHeight);
+            break;
+        case 2: //_NET_WM_MOVERESIZE_SIZE_TOPRIGHT
+            set_window_minsize(hwnd, sizingRect, 1, minWidth, minHeight);
+            set_window_minsize(hwnd, sizingRect, 3, minWidth, minHeight);
+            break;
+        case 4: //_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
+            set_window_minsize(hwnd, sizingRect, 5, minWidth, minHeight);
+            set_window_minsize(hwnd, sizingRect, 3, minWidth, minHeight);
+            break;
+        case 6: //_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
+            set_window_minsize(hwnd, sizingRect, 5, minWidth, minHeight);
+            set_window_minsize(hwnd, sizingRect, 7, minWidth, minHeight);
+            break;
+        default:
+            break;
+    }
+}
+
 /***********************************************************************
  *           move_resize_window
  */
@@ -1572,7 +1670,28 @@ void move_resize_window( HWND hwnd, int dir )
     XEvent xev;
     Window win, root, child;
     unsigned int xstate;
+    RECT sizingRect;
+    LONG minWidth = 0;
+    LONG minHeight = 0;
+    MINMAXINFO info;
+    info.ptMinTrackSize.x = 0;
+    info.ptMinTrackSize.y = 0;
+    SendMessageW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&info);
+    if(info.ptMinTrackSize.x !=0 && info.ptMinTrackSize.y != 0)
+    {
+        minWidth = info.ptMinTrackSize.x;
+        minHeight = info.ptMinTrackSize.y;
+        XSizeHints* sizehints = XAllocSizeHints();
+        LONG ret = -1;
+        XGetWMNormalHints(display, win, sizehints, &ret);
+        sizehints->flags |= PMinSize;
+        sizehints->min_height = minHeight;
+        sizehints->min_width = minWidth;
+        XSetWMNormalHints(display, win, sizehints);
+        XFree(sizehints);
+    }
 
+    GetWindowRect( hwnd, &sizingRect);
     if (!(win = X11DRV_get_whole_window( hwnd ))) return;
 
     pt = GetMessagePos();
@@ -1629,7 +1748,7 @@ void move_resize_window( HWND hwnd, int dir )
             input.u.mi.dwExtraInfo = 0;
             __wine_send_input( hwnd, &input );
         }
-
+        GetWindowRect( hwnd, &sizingRect);
         while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
         {
             if (!CallMsgFilterW( &msg, MSGF_SIZE ))
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 99e4094ebd..dcbebb801b 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -683,13 +683,21 @@ static void set_size_hints( struct x11drv_win_data *data, DWORD style )
 
         if (!is_window_resizable( data, style ))
         {
+            XSizeHints* sizehints = XAllocSizeHints();
+            long ret = 0;
+            XGetWMNormalHints(data->display, data->whole_window, sizehints, &ret);
             size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
             size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
             if (size_hints->max_width <= 0 ||size_hints->max_height <= 0)
                 size_hints->max_width = size_hints->max_height = 1;
-            size_hints->min_width = size_hints->max_width;
-            size_hints->min_height = size_hints->max_height;
-            size_hints->flags |= PMinSize | PMaxSize;
+            size_hints->flags |= PMaxSize ;
+            if(sizehints->min_height > 0 && sizehints->min_width > 0)
+            {
+                size_hints->min_width = sizehints->min_width;
+                size_hints->min_height = sizehints->min_height;
+                size_hints->flags |= PMinSize;
+            }
+            XFree(sizehints);
         }
     }
     XSetWMNormalHints( data->display, data->whole_window, size_hints );
-- 
2.24.1.windows.2





More information about the wine-devel mailing list