[gtk/wip.win32.fixes: 63/63] gdk/win32: Fix window display and resizing




commit c1b67364db1459a718f6016277cb2b6cab85f3cc
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Thu Dec 31 16:36:41 2020 +0800

    gdk/win32: Fix window display and resizing
    
    Have a bare-bones implementation of ->request_layout() and
    ->compute_size() for the Win32 surface backend so that we can properly
    display and move and resize the windows, as we request from the Win32
    APIs.
    
    Hxndling Aerosnap properly is partly done, but can be better...

 gdk/win32/gdkevents-win32.c  |   1 +
 gdk/win32/gdksurface-win32.c | 187 ++++++++++++++++++++++++++++++-------------
 gdk/win32/gdksurface-win32.h |   7 ++
 3 files changed, 140 insertions(+), 55 deletions(-)
---
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 37b4f54ee6..09a4c63d7b 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -2347,6 +2347,7 @@ gdk_event_translate (MSG *msg,
       if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
         {
           gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
+          gdk_surface_request_layout (window);
         }
       else if (_gdk_input_ignore_core == 0)
        {
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index b581c2a4ca..29bb33ec0d 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -1090,6 +1090,8 @@ gdk_win32_surface_resize (GdkSurface *window,
                            outer_rect.bottom - outer_rect.top,
                            SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
   window->resize_count += 1;
+
+  gdk_surface_request_layout (window);
 }
 
 static void
@@ -1150,8 +1152,6 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
 {
   GdkWin32Surface *surface = GDK_WIN32_SURFACE (window);
 
-  surface->inhibit_configure = TRUE;
-
   /* We ignore changes to the window being moved or resized by the
      user, as we don't want to fight the user */
   if (GDK_SURFACE_HWND (window) == _modal_move_resize_window)
@@ -1176,8 +1176,6 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
     }
 
  out:
-  surface->inhibit_configure = FALSE;
-
   gdk_surface_request_layout (window);
 }
 
@@ -2271,6 +2269,7 @@ snap_up (GdkSurface *window)
   impl = GDK_WIN32_SURFACE (window);
 
   impl->snap_state = GDK_WIN32_AEROSNAP_STATE_FULLUP;
+  impl->resized = FALSE;
 
   stash_window (window, impl);
 
@@ -2300,6 +2299,7 @@ snap_left (GdkSurface  *window,
   impl = GDK_WIN32_SURFACE (window);
 
   impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
+  impl->resized = FALSE;
 
   gdk_win32_monitor_get_workarea (snap_monitor, &rect);
 
@@ -2328,6 +2328,7 @@ snap_right (GdkSurface  *window,
   impl = GDK_WIN32_SURFACE (window);
 
   impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
+  impl->resized = FALSE;
 
   gdk_win32_monitor_get_workarea (snap_monitor, &rect);
 
@@ -3931,6 +3932,17 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
        rect.top != new_rect.top ||
        rect.bottom != new_rect.bottom))
     {
+      if (GDK_IS_TOPLEVEL (window))
+        {
+          int scale = impl->surface_scale;
+
+          impl->unscaled_width = new_rect.right - new_rect.left;
+          impl->unscaled_height = new_rect.bottom - new_rect.top;
+          impl->next_layout.configured_width = (impl->unscaled_width + scale - 1) / scale;
+          impl->next_layout.configured_height = (impl->unscaled_height + scale - 1) / scale;
+          impl->resized = TRUE;
+        }
+
       context->native_move_resize_pending = TRUE;
       gdk_surface_request_layout (window);
     }
@@ -4448,6 +4460,116 @@ gdk_win32_surface_set_input_region (GdkSurface     *window,
    */
 }
 
+static void
+compute_toplevel_size (GdkSurface *surface,
+                       gboolean    update_geometry,
+                       int        *width,
+                       int        *height)
+{
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  GdkMonitor *monitor;
+  GdkToplevelSize size;
+  int bounds_width, bounds_height;
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+
+  GdkToplevelLayout *layout = impl->toplevel_layout;
+
+  monitor = gdk_display_get_monitor_at_surface (display, surface);
+  if (monitor)
+    {
+      GdkRectangle workarea;
+
+      gdk_win32_monitor_get_workarea (monitor, &workarea);
+      bounds_width = workarea.width;
+      bounds_height = workarea.height;
+    }
+  else
+    {
+      bounds_width = G_MAXINT;
+      bounds_height = G_MAXINT;
+    }
+
+  gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+  gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
+  g_warn_if_fail (size.width > 0);
+  g_warn_if_fail (size.height > 0);
+  *width = size.width;
+  *height = size.height;
+
+  if (update_geometry)
+    {
+      GdkGeometry geometry;
+      GdkSurfaceHints mask;
+
+      if (gdk_toplevel_layout_get_resizable (layout))
+        {
+          geometry.min_width = size.min_width;
+          geometry.min_height = size.min_height;
+          mask = GDK_HINT_MIN_SIZE;
+        }
+      else
+        {
+          geometry.max_width = geometry.min_width = *width;
+          geometry.max_height = geometry.min_height = *height;
+          mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
+        }
+      gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
+      gdk_surface_constrain_size (&geometry, mask, *width, *height, width, height);
+
+      if (size.shadow.is_valid)
+        {
+          gdk_win32_surface_set_shadow_width (surface,
+                                              size.shadow.left,
+                                              size.shadow.right,
+                                              size.shadow.top,
+                                              size.shadow.bottom);
+        }
+    }
+}
+
+static void
+_gdk_win32_surface_request_layout (GdkSurface *surface)
+{
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+  int scale = impl->surface_scale;
+  RECT rect;
+
+  if (GDK_IS_TOPLEVEL (surface) && impl->resized)
+    {
+      surface->width = impl->next_layout.configured_width;
+      surface->height = impl->next_layout.configured_height;
+    }
+  else
+    {
+      _gdk_win32_get_window_rect (surface, &rect);
+
+      impl->unscaled_width = rect.right - rect.left;
+      impl->unscaled_height = rect.bottom - rect.top;
+
+      impl->next_layout.configured_width = (impl->unscaled_width + scale - 1) / scale;
+      impl->next_layout.configured_height = (impl->unscaled_height + scale - 1) / scale;
+      surface->x = rect.left / scale;
+      surface->y = rect.top / scale;
+    }
+}
+
+static gboolean
+_gdk_win32_surface_compute_size (GdkSurface *surface)
+{
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+  int width, height;
+
+  if (GDK_IS_TOPLEVEL (surface))
+    compute_toplevel_size (surface, TRUE, &width, &height);
+
+  surface->width = impl->next_layout.configured_width;
+  surface->height = impl->next_layout.configured_height;
+
+  _gdk_surface_update_size (surface);
+
+  return FALSE;
+}
+
 static void
 gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
 {
@@ -4474,6 +4596,8 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
   impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
   impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
   impl_class->get_unscaled_size = _gdk_win32_surface_get_unscaled_size;
+  impl_class->request_layout = _gdk_win32_surface_request_layout;
+  impl_class->compute_size = _gdk_win32_surface_compute_size;
 }
 
 HGDIOBJ
@@ -4767,52 +4891,14 @@ gdk_win32_toplevel_present (GdkToplevel       *toplevel,
                             GdkToplevelLayout *layout)
 {
   GdkSurface *surface = GDK_SURFACE (toplevel);
-  GdkDisplay *display = gdk_surface_get_display (surface);
-  GdkMonitor *monitor;
-  GdkToplevelSize size;
-  int bounds_width, bounds_height;
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
   int width, height;
-  GdkGeometry geometry;
-  GdkSurfaceHints mask;
   gboolean maximize;
   gboolean fullscreen;
 
-  monitor = gdk_display_get_monitor_at_surface (display, surface);
-  if (monitor)
-    {
-      GdkRectangle workarea;
-
-      gdk_win32_monitor_get_workarea (monitor, &workarea);
-      bounds_width = workarea.width;
-      bounds_height = workarea.height;
-    }
-  else
-    {
-      bounds_width = G_MAXINT;
-      bounds_height = G_MAXINT;
-    }
-
-  gdk_toplevel_size_init (&size, bounds_width, bounds_height);
-  gdk_toplevel_notify_compute_size (toplevel, &size);
-  g_warn_if_fail (size.width > 0);
-  g_warn_if_fail (size.height > 0);
-  width = size.width;
-  height = size.height;
-
-  if (gdk_toplevel_layout_get_resizable (layout))
-    {
-      geometry.min_width = size.min_width;
-      geometry.min_height = size.min_height;
-      mask = GDK_HINT_MIN_SIZE;
-    }
-  else
-    {
-      geometry.max_width = geometry.min_width = width;
-      geometry.max_height = geometry.min_height = height;
-      mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
-    }
-  gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
-  gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
+  g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref);
+  impl->toplevel_layout = gdk_toplevel_layout_copy (layout);
+  compute_toplevel_size (surface, FALSE, &width, &height);
   gdk_win32_surface_resize (surface, width, height);
 
   if (gdk_toplevel_layout_get_maximized (layout, &maximize))
@@ -4833,15 +4919,6 @@ gdk_win32_toplevel_present (GdkToplevel       *toplevel,
 
   gdk_win32_surface_show (surface, FALSE);
   maybe_notify_mapped (surface);
-
-  if (size.shadow.is_valid)
-    {
-      gdk_win32_surface_set_shadow_width (surface,
-                                          size.shadow.left,
-                                          size.shadow.right,
-                                          size.shadow.top,
-                                          size.shadow.bottom);
-    }
 }
 
 static gboolean
diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h
index a8def428e0..1d0c9c6c7e 100644
--- a/gdk/win32/gdksurface-win32.h
+++ b/gdk/win32/gdksurface-win32.h
@@ -338,6 +338,13 @@ struct _GdkWin32Surface
   int unscaled_width;
   int unscaled_height;
 
+  GdkToplevelLayout *toplevel_layout;
+  struct {
+    int configured_width;
+    int configured_height;
+  } next_layout;
+  gboolean resized;
+
 #ifdef GDK_WIN32_ENABLE_EGL
   EGLSurface egl_surface;
   EGLSurface egl_dummy_surface;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]