[mutter] window: Introduce meta_window_get_tile_match()



commit 2926323a9a0defc2f9f845d80a5ec6b00a23d78e
Author: Rui Matos <tiagomatos gmail com>
Date:   Fri Feb 24 17:08:55 2012 +0100

    window: Introduce meta_window_get_tile_match()
    
    Returns the matching tiled window. This is the topmost tiled window in a
    complementary tile mode that is:
    
     - on the same monitor;
     - on the same workspace;
     - spanning the remaining monitor width;
     - there is no 3rd window stacked between both tiled windows that's
       partially visible in the common edge.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=643075

 src/core/stack.c          |   29 +++++++++++++
 src/core/stack.h          |    2 +
 src/core/window-private.h |    5 ++
 src/core/window.c         |  101 +++++++++++++++++++++++++++++++++++++++++++++
 src/meta/window.h         |    2 +
 5 files changed, 139 insertions(+), 0 deletions(-)
---
diff --git a/src/core/stack.c b/src/core/stack.c
index c3917c6..de1c9e0 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -121,6 +121,7 @@ meta_stack_add (MetaStack  *stack,
               window->desc, window->stack_position);
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 void
@@ -156,6 +157,7 @@ meta_stack_remove (MetaStack  *stack,
                                      GUINT_TO_POINTER (window->frame->xwindow));
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 void
@@ -165,6 +167,7 @@ meta_stack_update_layer (MetaStack  *stack,
   stack->need_relayer = TRUE;
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 void
@@ -174,6 +177,7 @@ meta_stack_update_transient (MetaStack  *stack,
   stack->need_constrain = TRUE;
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 /* raise/lower within a layer */
@@ -185,6 +189,7 @@ meta_stack_raise (MetaStack  *stack,
                                           stack->n_positions - 1);
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 void
@@ -194,6 +199,7 @@ meta_stack_lower (MetaStack  *stack,
   meta_window_set_stack_position_no_sync (window, 0);
   
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
 }
 
 void
@@ -209,6 +215,26 @@ meta_stack_thaw (MetaStack *stack)
   
   stack->freeze_count -= 1;
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, NULL);
+}
+
+void
+meta_stack_update_window_tile_matches (MetaStack     *stack,
+                                       MetaWorkspace *workspace)
+{
+  GList *windows;
+
+  if (stack->freeze_count > 0)
+    return;
+
+  windows = meta_stack_list_windows (stack, workspace);
+  while (windows)
+    {
+      meta_window_compute_tile_match ((MetaWindow *) windows->data);
+      windows = windows->next;
+    }
+
+  g_list_free (windows);
 }
 
 static gboolean
@@ -1656,6 +1682,7 @@ meta_stack_set_positions (MetaStack *stack,
               "Reset the stack positions of (nearly) all windows\n");
 
   stack_sync_to_server (stack);
+  meta_stack_update_window_tile_matches (stack, NULL);
 }
 
 void
@@ -1718,4 +1745,6 @@ meta_window_set_stack_position (MetaWindow *window,
 {
   meta_window_set_stack_position_no_sync (window, position);
   stack_sync_to_server (window->screen->stack);
+  meta_stack_update_window_tile_matches (window->screen->stack,
+                                         window->screen->active_workspace);
 }
diff --git a/src/core/stack.h b/src/core/stack.h
index e8b6310..4102cc6 100644
--- a/src/core/stack.h
+++ b/src/core/stack.h
@@ -383,4 +383,6 @@ GList* meta_stack_get_positions (MetaStack *stack);
 void   meta_stack_set_positions (MetaStack *stack,
                                  GList     *windows);
 
+void meta_stack_update_window_tile_matches (MetaStack     *stack,
+                                            MetaWorkspace *workspace);
 #endif
diff --git a/src/core/window-private.h b/src/core/window-private.h
index b425aed..d89924c 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -410,6 +410,9 @@ struct _MetaWindow
 
   /* Focused window that is (directly or indirectly) attached to this one */
   MetaWindow *attached_focus_window;
+
+  /* The currently complementary tiled window, if any */
+  MetaWindow *tile_match;
 };
 
 struct _MetaWindowClass
@@ -663,4 +666,6 @@ void meta_window_propagate_focus_appearance (MetaWindow *window,
 gboolean meta_window_should_attach_to_parent (MetaWindow *window);
 gboolean meta_window_can_tile_side_by_side   (MetaWindow *window);
 
+void meta_window_compute_tile_match (MetaWindow *window);
+
 #endif
diff --git a/src/core/window.c b/src/core/window.c
index 8c54839..ff09914 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1167,6 +1167,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
 
+  window->tile_match = NULL;
+
   if (window->override_redirect)
     {
       window->decorated = FALSE;
@@ -5022,6 +5024,9 @@ meta_window_move_resize_internal (MetaWindow          *window,
     }
 
   meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL);
+
+  meta_stack_update_window_tile_matches (window->screen->stack,
+                                         window->screen->active_workspace);
 }
 
 /**
@@ -10712,3 +10717,99 @@ meta_window_is_attached_dialog (MetaWindow *window)
 {
   return window->attached;
 }
+
+/**
+ * meta_window_get_tile_match:
+ *
+ * Returns the matching tiled window on the same monitor as @window. This is
+ * the topmost tiled window in a complementary tile mode that is:
+ *
+ *  - on the same monitor;
+ *  - on the same workspace;
+ *  - spanning the remaining monitor width;
+ *  - there is no 3rd window stacked between both tiled windows that's
+ *    partially visible in the common edge.
+ *
+ * Return value: (transfer none) (allow-none): the matching tiled window or
+ * %NULL if it doesn't exist.
+ */
+MetaWindow *
+meta_window_get_tile_match (MetaWindow *window)
+{
+  return window->tile_match;
+}
+
+void
+meta_window_compute_tile_match (MetaWindow *window)
+{
+  MetaWindow *match;
+  MetaTileMode match_tile_mode;
+  MetaStack *stack;
+
+  window->tile_match = NULL;
+
+  if (window->shaded ||
+      window->minimized ||
+      !META_WINDOW_TILED_SIDE_BY_SIDE (window))
+    return;
+
+  if (META_WINDOW_TILED_LEFT (window))
+    match_tile_mode = META_TILE_RIGHT;
+  else if (META_WINDOW_TILED_RIGHT (window))
+    match_tile_mode = META_TILE_LEFT;
+
+  stack = window->screen->stack;
+
+  for (match = meta_stack_get_top (stack);
+       match;
+       match = meta_stack_get_below (stack, match, FALSE))
+    {
+      if (!match->shaded &&
+          !match->minimized &&
+          match->tile_mode == match_tile_mode &&
+          match->monitor == window->monitor &&
+          meta_window_get_workspace (match) == meta_window_get_workspace (window))
+        break;
+    }
+
+  if (match)
+    {
+      MetaWindow *above, *bottommost, *topmost;
+      MetaRectangle above_rect, bottommost_rect, topmost_rect;
+
+      if (meta_stack_windows_cmp (window->screen->stack, match, window) > 0)
+        {
+          topmost = match;
+          bottommost = window;
+        }
+      else
+        {
+          topmost = window;
+          bottommost = match;
+        }
+
+      meta_window_get_outer_rect (bottommost, &bottommost_rect);
+      meta_window_get_outer_rect (topmost, &topmost_rect);
+      /*
+       * If there's a window stacked in between which is partially visible
+       * behind the topmost tile we don't consider the tiles to match.
+       */
+      for (above = meta_stack_get_above (stack, bottommost, FALSE);
+           above && above != topmost;
+           above = meta_stack_get_above (stack, above, FALSE))
+        {
+          if (above->minimized ||
+              above->monitor != window->monitor ||
+              meta_window_get_workspace (above) != meta_window_get_workspace (window))
+            continue;
+
+          meta_window_get_outer_rect (above, &above_rect);
+
+          if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
+              meta_rectangle_overlap (&above_rect, &topmost_rect))
+            return;
+        }
+
+      window->tile_match = match;
+    }
+}
diff --git a/src/meta/window.h b/src/meta/window.h
index 765ef28..5e09b59 100644
--- a/src/meta/window.h
+++ b/src/meta/window.h
@@ -169,4 +169,6 @@ MetaFrameType meta_window_get_frame_type (MetaWindow *window);
 
 cairo_region_t *meta_window_get_frame_bounds (MetaWindow *window);
 
+MetaWindow *meta_window_get_tile_match (MetaWindow *window);
+
 #endif



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