[gtk+] GDK W32: Improve AeroSnap - don't resize windows that fit



commit 2ea96cf9461474d9ffbe8efc64c5946d48441cf4
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date:   Tue Mar 8 03:17:09 2016 +0000

    GDK W32: Improve AeroSnap - don't resize windows that fit
    
    This is what AeroSnap does. If a window is being unsnapped on
    a new monitor, check if the work area is large enough for the
    window to fit in its normal size. If the window fits, just
    reposition it so that the ratio of
    left-window-edge-to-screen-edge / right-window-edge-to-screen-edge
    remains the same, without scaling the window.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763013

 gdk/win32/gdkwindow-win32.c |   68 ++++++++++++++++++++++++++++++++++++++----
 gdk/win32/gdkwindow-win32.h |    3 ++
 2 files changed, 64 insertions(+), 7 deletions(-)
---
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 2289927..4cf50c6 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -180,6 +180,9 @@ gdk_window_impl_win32_finalize (GObject *object)
 
   g_clear_object (&window_impl->cursor);
 
+  g_clear_pointer (&window_impl->snap_stash, g_free);
+  g_clear_pointer (&window_impl->snap_stash_int, g_free);
+
   if (window_impl->hicon_big != NULL)
     {
       GDI_CALL (DestroyIcon, (window_impl->hicon_big));
@@ -2940,13 +2943,55 @@ unsnap (GdkWindow  *window,
 
   GDK_NOTE (MISC, g_print ("Monitor work area %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, 
rect.y));
 
-  /* Calculate actual unsnapped window size based on its
-   * old relative size. Same for position.
-   */
-  rect.x += round (rect.width * impl->snap_stash->x);
-  rect.y += round (rect.height * impl->snap_stash->y);
-  rect.width = round (rect.width * impl->snap_stash->width);
-  rect.height = round (rect.height * impl->snap_stash->height);
+  if (rect.width >= impl->snap_stash_int->width &&
+      rect.height >= impl->snap_stash_int->height)
+    {
+      /* If the window fits into new work area without resizing it,
+       * place it into new work area without resizing it.
+       */
+      gdouble left, right, up, down, hratio, vratio;
+      gdouble hscale, vscale;
+      gdouble new_left, new_up;
+
+      left = impl->snap_stash->x;
+      right = 1.0 - (impl->snap_stash->x + impl->snap_stash->width);
+      up = impl->snap_stash->y;
+      down = 1.0 - (impl->snap_stash->y + impl->snap_stash->height);
+      hscale = 1.0;
+
+      if (right > 0.001)
+        {
+          hratio = left / right;
+          hscale = hratio / (1.0 + hratio);
+        }
+
+      new_left = (gdouble) (rect.width - impl->snap_stash_int->width) * hscale;
+
+      vscale = 1.0;
+
+      if (down > 0.001)
+        {
+          vratio = up / down;
+          vscale = vratio / (1.0 + vratio);
+        }
+
+      new_up = (gdouble) (rect.height - impl->snap_stash_int->height) * vscale;
+
+      rect.x = round (rect.x + new_left);
+      rect.y = round (rect.y + new_up);
+      rect.width = impl->snap_stash_int->width;
+      rect.height = impl->snap_stash_int->height;
+    }
+  else
+    {
+      /* Calculate actual unsnapped window size based on its
+       * old relative size. Same for position.
+       */
+      rect.x += round (rect.width * impl->snap_stash->x);
+      rect.y += round (rect.height * impl->snap_stash->y);
+      rect.width = round (rect.width * impl->snap_stash->width);
+      rect.height = round (rect.height * impl->snap_stash->height);
+    }
 
   GDK_NOTE (MISC, g_print ("Unsnapped window size %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, 
rect.y));
 
@@ -2954,6 +2999,7 @@ unsnap (GdkWindow  *window,
                           rect.width, rect.height);
 
   g_clear_pointer (&impl->snap_stash, g_free);
+  g_clear_pointer (&impl->snap_stash_int, g_free);
 }
 
 static void
@@ -2989,6 +3035,9 @@ stash_window (GdkWindow          *window,
   if (impl->snap_stash == NULL)
     impl->snap_stash = g_new0 (GdkRectangleDouble, 1);
 
+  if (impl->snap_stash_int == NULL)
+    impl->snap_stash_int = g_new0 (GdkRectangle, 1);
+
   GDK_NOTE (MISC, g_print ("monitor work area  %ld x %ld @ %ld : %ld\n",
                            hmonitor_info.rcWork.right - hmonitor_info.rcWork.left,
                            hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top,
@@ -3015,6 +3064,11 @@ stash_window (GdkWindow          *window,
   impl->snap_stash->width = (gdouble) width / (gdouble) (hmonitor_info.rcWork.right - 
hmonitor_info.rcWork.left);
   impl->snap_stash->height = (gdouble) height / (gdouble) (hmonitor_info.rcWork.bottom - 
hmonitor_info.rcWork.top);
 
+  impl->snap_stash_int->x = x;
+  impl->snap_stash_int->y = y;
+  impl->snap_stash_int->width = width;
+  impl->snap_stash_int->height = height;
+
   GDK_NOTE (MISC, g_print ("Stashed window %d x %d @ %d : %d as %f x %f @ %f : %f\n",
                            width, height, x, y,
                            impl->snap_stash->width, impl->snap_stash->height, impl->snap_stash->x, 
impl->snap_stash->y));
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
index 312e7f1..6910d7a 100644
--- a/gdk/win32/gdkwindow-win32.h
+++ b/gdk/win32/gdkwindow-win32.h
@@ -224,6 +224,9 @@ struct _GdkWindowImplWin32
    */
   GdkRectangleDouble *snap_stash;
 
+  /* Also remember the same position, but in absolute form. */
+  GdkRectangle *snap_stash_int;
+
   /* Decorations set by gdk_window_set_decorations() or NULL if unset */
   GdkWMDecoration* decorations;
 


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