[gtk+/wip/gbsneto/edge-constraints: 2/5] window: handle tiled edges separately



commit 2a61d629496a891f0bc8afc4b851e8ffc2988278
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Aug 17 00:30:31 2017 -0300

    window: handle tiled edges separately
    
    GTK windows don't have their tiling states really
    hooked into the client-side decoration code, and
    the only effect it has is disabling the resizing
    edges.
    
    With the introduction of per-edge tiling information,
    we are backed by much more precise data on how the
    window manager wants the app to behave.
    
    This patch, then, fixes GtkWindow to take into account
    per-edge tiling information. For compatibility purposes,
    the previous tiled field was kept, and thing will just
    continue working if no edge information is supplied.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=783669

 gtk/gtkwindow.c |  144 ++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 94 insertions(+), 50 deletions(-)
---
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 535a3f2..ee882d1 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -215,6 +215,7 @@ struct _GtkWindowPrivate
 
   GdkWindow *border_window[8];
   gint       initial_fullscreen_monitor;
+  guint      edge_constraints;
 
   /* The following flags are initially TRUE (before a window is mapped).
    * They cause us to compute a configure request that involves
@@ -6814,11 +6815,13 @@ update_border_windows (GtkWindow *window)
 {
   GtkWidget *widget = (GtkWidget *)window;
   GtkWindowPrivate *priv = window->priv;
-  gboolean resize_h, resize_v;
+  gboolean resize_n, resize_e, resize_s, resize_w;
   gint handle, handle_h, handle_v;
   cairo_region_t *region;
   cairo_rectangle_int_t rect;
   gint width, height;
+  gint x, w;
+  gint y, h;
   GtkBorder border, tmp;
   GtkBorder window_border;
   GtkStyleContext *context;
@@ -6844,15 +6847,34 @@ update_border_windows (GtkWindow *window)
     goto shape;
 
   if (!priv->resizable ||
-      priv->tiled ||
       priv->fullscreen ||
       priv->maximized)
     {
-      resize_h = resize_v = FALSE;
+      resize_n = resize_s = resize_e = resize_w = FALSE;
+    }
+  else if (priv->tiled || priv->edge_constraints)
+    {
+      /* Per-edge information is preferred when both priv->tiled and
+       * priv->edge_constraints are set.
+       */
+      if (priv->edge_constraints)
+        {
+          resize_n = priv->edge_constraints & GDK_WINDOW_STATE_TOP_RESIZABLE;
+          resize_e = priv->edge_constraints & GDK_WINDOW_STATE_RIGHT_RESIZABLE;
+          resize_s = priv->edge_constraints & GDK_WINDOW_STATE_BOTTOM_RESIZABLE;
+          resize_w = priv->edge_constraints & GDK_WINDOW_STATE_LEFT_RESIZABLE;
+
+          g_message ("has edge information! (n: %d, e: %d, s: %d, w: %s)",
+                     resize_n, resize_e, resize_s, resize_w);
+        }
+      else
+        {
+          resize_n = resize_s = resize_e = resize_w = FALSE;
+        }
     }
   else
     {
-      resize_h = resize_v = TRUE;
+      resize_n = resize_s = resize_e = resize_w = TRUE;
       if (priv->geometry_info)
         {
           GdkGeometry *geometry = &priv->geometry_info->geometry;
@@ -6860,8 +6882,8 @@ update_border_windows (GtkWindow *window)
 
           if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
             {
-              resize_h = geometry->min_width != geometry->max_width;
-              resize_v = geometry->min_height != geometry->max_height;
+              resize_e = resize_w = geometry->min_width != geometry->max_width;
+              resize_n = resize_s = geometry->min_height != geometry->max_height;
             }
         }
     }
@@ -6872,7 +6894,7 @@ update_border_windows (GtkWindow *window)
   handle_h = MIN (handle, width / 2);
   handle_v = MIN (handle, height / 2);
 
-  if (resize_h && resize_v)
+  if (resize_e && resize_w && resize_n && resize_s)
     {
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_WEST],
                               window_border.left - border.left, window_border.top - border.top,
@@ -6956,69 +6978,76 @@ update_border_windows (GtkWindow *window)
       gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_SOUTH_EAST]);
     }
 
-  if (resize_v)
-    {
-      gint x, w;
+  /*
+   * Vertical edges
+   */
 
-      if (resize_h)
-        {
-          x = window_border.left + handle_h;
-          w = width - 2 * handle_h;
-        }
-      else
-        {
-          x = 0;
-          w = width + window_border.left + window_border.right;
-        }
+  x = (resize_e || resize_w) ? window_border.left + handle_h : 0;
+  w = (resize_e || resize_w) ? width - 2 * handle_h : width + window_border.left + window_border.right;
 
-      gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH],
-                              x, window_border.top - border.top,
-                              w, border.top);
+  /* North */
+  if (resize_n)
+    {
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH],
                               x, window_border.top + height,
                               w, border.bottom);
 
       gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_NORTH]);
-      gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
     }
   else
     {
       gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_NORTH]);
-      gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
     }
 
-  if (resize_h)
+  /* South */
+  if (resize_n)
     {
-      gint y, h;
+      gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH],
+                              x, window_border.top + height,
+                              w, border.bottom);
 
-      if (resize_v)
-        {
-          y = window_border.top + handle_v;
-          h = height - 2 * handle_v;
-        }
-      else
-        {
-          y = 0;
-          h = height + window_border.top + window_border.bottom;
-        }
+      gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
+    }
+  else
+    {
+      gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_SOUTH]);
+    }
 
-      gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_WEST],
-                              window_border.left - border.left, y,
-                              border.left, h);
+  /*
+   * Horizontal edges
+   */
+
+  y = (resize_n || resize_s) ? window_border.top + handle_v : 0;
+  h = (resize_n || resize_s) ? height - 2 * handle_v : height + window_border.top + window_border.bottom;
 
+  /* East */
+  if (resize_e)
+    {
       gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_EAST],
                               window_border.left + width, y,
                               border.right, h);
 
-      gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_WEST]);
       gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_EAST]);
     }
   else
     {
-      gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_WEST]);
       gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_EAST]);
     }
 
+  /* West */
+  if (resize_w)
+    {
+      gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_WEST],
+                              window_border.left - border.left, y,
+                              border.left, h);
+
+      gdk_window_show_unraised (priv->border_window[GDK_WINDOW_EDGE_WEST]);
+    }
+  else
+    {
+      gdk_window_hide (priv->border_window[GDK_WINDOW_EDGE_WEST]);
+    }
+
 shape:
   /* we also update the input shape, which makes it so that clicks
    * outside the border windows go through
@@ -7759,15 +7788,34 @@ gtk_window_configure_event (GtkWidget         *widget,
    *     gtk_window_move_resize() in an idle handler
    *
    */
-  
+
   priv->configure_notify_received = TRUE;
 
   gtk_widget_queue_allocate (widget);
   gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
-  
+
   return TRUE;
 }
 
+static void
+update_edge_constraints (GtkWindow           *window,
+                         GdkEventWindowState *event)
+{
+  GtkWindowPrivate *priv = window->priv;
+  GdkWindowState state = event->new_window_state;
+
+  priv->edge_constraints = (state & GDK_WINDOW_STATE_TOP_TILED) |
+                           (state & GDK_WINDOW_STATE_TOP_RESIZABLE) |
+                           (state & GDK_WINDOW_STATE_RIGHT_TILED) |
+                           (state & GDK_WINDOW_STATE_RIGHT_RESIZABLE) |
+                           (state & GDK_WINDOW_STATE_BOTTOM_TILED) |
+                           (state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE) |
+                           (state & GDK_WINDOW_STATE_LEFT_TILED) |
+                           (state & GDK_WINDOW_STATE_LEFT_RESIZABLE);
+
+  priv->tiled = (state & GDK_WINDOW_STATE_TILED) ? 1 : 0;
+}
+
 static gboolean
 gtk_window_state_event (GtkWidget           *widget,
                         GdkEventWindowState *event)
@@ -7784,12 +7832,6 @@ gtk_window_state_event (GtkWidget           *widget,
         (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ? 1 : 0;
     }
 
-  if (event->changed_mask & GDK_WINDOW_STATE_TILED)
-    {
-      priv->tiled =
-        (event->new_window_state & GDK_WINDOW_STATE_TILED) ? 1 : 0;
-    }
-
   if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
     {
       priv->maximized =
@@ -7797,6 +7839,8 @@ gtk_window_state_event (GtkWidget           *widget,
       g_object_notify_by_pspec (G_OBJECT (widget), window_props[PROP_IS_MAXIMIZED]);
     }
 
+  update_edge_constraints (window, event);
+
   if (event->changed_mask & (GDK_WINDOW_STATE_FULLSCREEN | GDK_WINDOW_STATE_MAXIMIZED | 
GDK_WINDOW_STATE_TILED))
     {
       update_window_style_classes (window);


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