[mutter/meego-1.0: 9/30] Infrastructure allowing plugins to implement custom window constraints



commit 757f8ee8da0c85ca91aa76f86847d8b090eee885
Author: Tomas Frydrych <tf linux intel com>
Date:   Mon Jan 18 09:20:29 2010 +0000

    Infrastructure allowing plugins to implement custom window constraints
    
    This commit adds a constrain_window() vfunction to the plugin class, and hooks
    it onto the WM constraint mechanism.
    
    The constraints.h file is split into a public and private parts; the definition
    of the theme-specific version of MetaFrameGeometry struct was moved from its
    location in theme.h to frames.h to avoid redefinition when autogenerating type
    info for enums.
    
    Plugin API version is bumped to 4

 configure.in                                      |    2 +-
 src/Makefile.am                                   |    5 +-
 src/compositor/compositor.c                       |   22 +++
 src/compositor/mutter-plugin-manager.c            |   37 ++++-
 src/compositor/mutter-plugin-manager.h            |    9 +-
 src/core/{constraints.h => constraints-private.h} |   10 +-
 src/core/constraints.c                            |  207 +++++++++------------
 src/core/frame-private.h                          |   11 -
 src/core/window-private.h                         |    3 +
 src/core/window.c                                 |   22 +++
 src/include/compositor.h                          |    7 +
 src/include/constraints.h                         |   97 ++++++++++
 src/include/frame.h                               |    9 +
 src/include/mutter-plugin.h                       |    9 +-
 src/include/types.h                               |    1 +
 src/include/window.h                              |    2 +
 src/ui/frames.h                                   |   52 +++++
 src/ui/theme.c                                    |    1 +
 src/ui/theme.h                                    |   55 +------
 19 files changed, 369 insertions(+), 192 deletions(-)
---
diff --git a/configure.in b/configure.in
index 632b7f7..c31d1b5 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ m4_define([mutter_micro_version], [1])
 m4_define([mutter_version],
           [mutter_major_version.mutter_minor_version.mutter_micro_version])
 
-m4_define([mutter_plugin_api_version], [3])
+m4_define([mutter_plugin_api_version], [4])
 
 AC_INIT([mutter], [mutter_version],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
diff --git a/src/Makefile.am b/src/Makefile.am
index ae17abc..73b3653 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,7 +43,8 @@ mutter_SOURCES= 				\
 	include/mutter-window.h			\
 	include/compositor-mutter.h 		\
 	core/constraints.c			\
-	core/constraints.h			\
+	core/constraints-private.h		\
+	include/constraints.h			\
 	core/core.c				\
 	core/delete.c				\
 	core/display.c				\
@@ -168,6 +169,8 @@ libmutterinclude_base_headers =		\
 	include/display.h			\
 	include/group.h				\
 	include/keybindings.h			\
+	include/frame.h				\
+	include/constraints.h			\
 	include/mutter-plugin.h			\
 	include/mutter-window.h			\
 	include/mutter-shadow.h
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 7de1065..a346a80 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1021,6 +1021,28 @@ meta_compositor_sync_screen_size (MetaCompositor  *compositor,
 		width, height);
 }
 
+gboolean
+meta_compositor_constrain_window (MetaCompositor     *compositor,
+                                  MetaWindow         *window,
+                                  ConstraintInfo     *constraint_info,
+                                  ConstraintPriority  priority,
+                                  gboolean            check_only)
+{
+  MetaScreen	      *screen = meta_window_get_screen (window);
+  MetaCompScreen      *info   = meta_screen_get_compositor_data (screen);
+  MutterPluginManager *mgr;
+
+  g_return_val_if_fail (info, FALSE);
+
+  mgr = info->plugin_mgr;
+
+  if (!mgr)
+    return FALSE;
+
+  return mutter_plugin_manager_constrain_window (mgr, window, constraint_info,
+                                                 priority, check_only);
+}
+
 static void
 pre_paint_windows (MetaCompScreen *info)
 {
diff --git a/src/compositor/mutter-plugin-manager.c b/src/compositor/mutter-plugin-manager.c
index c8d3d86..2f7c543 100644
--- a/src/compositor/mutter-plugin-manager.c
+++ b/src/compositor/mutter-plugin-manager.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
 /*
- * Copyright (c) 2008 Intel Corp.
+ * Copyright (c) 2008, 2010 Intel Corp.
  *
  * Author: Tomas Frydrych <tf linux intel com>
  *
@@ -677,3 +677,38 @@ mutter_plugin_manager_get_shadow (MutterPluginManager *mgr,
 
   return NULL;
 }
+
+/*
+ * This function needs to return TRUE by default (meaning 'constraint already
+ * satisfied').
+ */
+gboolean
+mutter_plugin_manager_constrain_window (MutterPluginManager *mgr,
+                                        MetaWindow          *window,
+                                        ConstraintInfo      *info,
+                                        ConstraintPriority   priority,
+                                        gboolean             check_only)
+{
+  GList *l;
+
+  if (!mgr)
+    return TRUE;
+
+  l = mgr->plugins;
+
+  while (l)
+    {
+      MutterPlugin      *plugin = l->data;
+      MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
+
+      if (klass->constrain_window)
+        {
+          return klass->constrain_window (plugin, window, info, priority,
+                                          check_only);
+        }
+
+      l = l->next;
+    }
+
+  return TRUE;
+}
diff --git a/src/compositor/mutter-plugin-manager.h b/src/compositor/mutter-plugin-manager.h
index 690e61b..b6baadb 100644
--- a/src/compositor/mutter-plugin-manager.h
+++ b/src/compositor/mutter-plugin-manager.h
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
 /*
- * Copyright (c) 2008 Intel Corp.
+ * Copyright (c) 2008, 2010 Intel Corp.
  *
  * Author: Tomas Frydrych <tf linux intel com>
  *
@@ -63,4 +63,11 @@ gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
 MutterShadow * mutter_plugin_manager_get_shadow (MutterPluginManager *mgr,
                                                  MutterWindow *window);
 
+gboolean
+mutter_plugin_manager_constrain_window (MutterPluginManager *mgr,
+                                        MetaWindow          *window,
+                                        ConstraintInfo      *info,
+                                        ConstraintPriority   priority,
+                                        gboolean             check_only);
+
 #endif
diff --git a/src/core/constraints.h b/src/core/constraints-private.h
similarity index 95%
rename from src/core/constraints.h
rename to src/core/constraints-private.h
index fa3f039..1b5ca3f 100644
--- a/src/core/constraints.h
+++ b/src/core/constraints-private.h
@@ -2,10 +2,10 @@
 
 /* Mutter size/position constraints */
 
-/* 
+/*
  * Copyright (C) 2002 Red Hat, Inc.
  * Copyright (C) 2005 Elijah Newren
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -15,15 +15,15 @@
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  * 02111-1307, USA.
  */
 
-#ifndef META_CONSTRAINTS_H
-#define META_CONSTRAINTS_H
+#ifndef META_CONSTRAINTS_PRIVATE_H
+#define META_CONSTRAINTS_PRIVATE_H
 
 #include "util.h"
 #include "window-private.h"
diff --git a/src/core/constraints.c b/src/core/constraints.c
index 93c8864..88f302e 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -25,6 +25,7 @@
 
 #include <config.h>
 #include "constraints.h"
+#include "constraints-private.h"
 #include "workspace-private.h"
 #include "place.h"
 #include "prefs.h"
@@ -43,7 +44,7 @@
  //      "constrain_whatever".
  //   3) Add your function to the all_constraints and all_constraint_names
  //      arrays (the latter of which is for debugging purposes)
- // 
+ //
  // An example constraint function, constrain_whatever:
  //
  // /* constrain_whatever does the following:
@@ -90,56 +91,6 @@
  // }
 #endif
 
-typedef enum
-{
-  PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
-  PRIORITY_ASPECT_RATIO = 0,
-  PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
-  PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
-  PRIORITY_SIZE_HINTS_INCREMENTS = 1,
-  PRIORITY_MAXIMIZATION = 2,
-  PRIORITY_FULLSCREEN = 2,
-  PRIORITY_SIZE_HINTS_LIMITS = 3,
-  PRIORITY_TITLEBAR_VISIBLE = 4,
-  PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
-  PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */
-} ConstraintPriority;
-
-typedef enum
-{
-  ACTION_MOVE,
-  ACTION_RESIZE,
-  ACTION_MOVE_AND_RESIZE
-} ActionType;
-
-typedef struct
-{
-  MetaRectangle        orig;
-  MetaRectangle        current;
-  MetaFrameGeometry   *fgeom;
-  ActionType           action_type;
-  gboolean             is_user_action;
-
-  /* I know that these two things probably look similar at first, but they
-   * have much different uses.  See doc/how-constraints-works.txt for for
-   * explanation of the differences and similarity between resize_gravity
-   * and fixed_directions
-   */
-  int                  resize_gravity;
-  FixedDirections      fixed_directions;
-
-  /* work_area_monitor - current monitor region minus struts
-   * entire_monitor    - current monitor, including strut regions
-   */
-  MetaRectangle        work_area_monitor;
-  MetaRectangle        entire_monitor;
-
-  /* Spanning rectangles for the non-covered (by struts) region of the
-   * screen and also for just the current monitor
-   */
-  GList  *usable_screen_region;
-  GList  *usable_monitor_region;
-} ConstraintInfo;
 
 static gboolean constrain_maximization       (MetaWindow         *window,
                                               ConstraintInfo     *info,
@@ -178,6 +129,11 @@ static gboolean constrain_partially_onscreen (MetaWindow         *window,
                                               ConstraintPriority  priority,
                                               gboolean            check_only);
 
+static gboolean constrain_plugin (MetaWindow         *window,
+                                  ConstraintInfo     *info,
+                                  ConstraintPriority  priority,
+                                  gboolean            check_only);
+
 static void setup_constraint_info        (ConstraintInfo      *info,
                                           MetaWindow          *window,
                                           MetaFrameGeometry   *orig_fgeom,
@@ -189,15 +145,6 @@ static void place_window_if_needed       (MetaWindow     *window,
                                           ConstraintInfo *info);
 static void update_onscreen_requirements (MetaWindow     *window,
                                           ConstraintInfo *info);
-static void extend_by_frame              (MetaRectangle           *rect,
-                                          const MetaFrameGeometry *fgeom);
-static void unextend_by_frame            (MetaRectangle           *rect,
-                                          const MetaFrameGeometry *fgeom);
-static inline void get_size_limits       (const MetaWindow        *window,
-                                          const MetaFrameGeometry *fgeom,
-                                          gboolean include_frame,
-                                          MetaRectangle *min_size,
-                                          MetaRectangle *max_size);
 
 typedef gboolean (* ConstraintFunc) (MetaWindow         *window,
                                      ConstraintInfo     *info,
@@ -219,6 +166,8 @@ static const Constraint all_constraints[] = {
   {constrain_fully_onscreen,     "constrain_fully_onscreen"},
   {constrain_titlebar_visible,   "constrain_titlebar_visible"},
   {constrain_partially_onscreen, "constrain_partially_onscreen"},
+  {constrain_plugin,             "constrain_plugin"},
+
   {NULL,                         NULL}
 };
 
@@ -243,7 +192,7 @@ do_all_constraints (MetaWindow         *window,
           /* Log how the constraint modified the position */
           meta_topic (META_DEBUG_GEOMETRY,
                       "info->current is %d,%d +%d,%d after %s\n",
-                      info->current.x, info->current.y, 
+                      info->current.x, info->current.y,
                       info->current.width, info->current.height,
                       constraint->name);
         }
@@ -285,8 +234,8 @@ meta_window_constrain (MetaWindow          *window,
               new->x,  new->y,  new->width,  new->height);
 
   setup_constraint_info (&info,
-                         window, 
-                         orig_fgeom, 
+                         window,
+                         orig_fgeom,
                          flags,
                          resize_gravity,
                          orig,
@@ -299,7 +248,7 @@ meta_window_constrain (MetaWindow          *window,
     /* Individually enforce all the high-enough priority constraints */
     do_all_constraints (window, &info, priority, !check_only);
 
-    /* Check if all high-enough priority constraints are simultaneously 
+    /* Check if all high-enough priority constraints are simultaneously
      * satisfied
      */
     satisfied = do_all_constraints (window, &info, priority, check_only);
@@ -416,10 +365,10 @@ setup_constraint_info (ConstraintInfo      *info,
     }
 
   cur_workspace = window->screen->active_workspace;
-  info->usable_screen_region   = 
+  info->usable_screen_region   =
     meta_workspace_get_onscreen_region (cur_workspace);
-  info->usable_monitor_region = 
-    meta_workspace_get_onmonitor_region (cur_workspace, 
+  info->usable_monitor_region =
+    meta_workspace_get_onmonitor_region (cur_workspace,
                                          monitor_info->number);
 
 #if 0
@@ -455,7 +404,7 @@ setup_constraint_info (ConstraintInfo      *info,
               "  work_area_monitor: %d,%d +%d,%d\n"
               "  entire_monitor   : %d,%d +%d,%d\n",
               info->orig.x, info->orig.y, info->orig.width, info->orig.height,
-              info->current.x, info->current.y, 
+              info->current.x, info->current.y,
                 info->current.width, info->current.height,
               info->fgeom->left_width, info->fgeom->right_width,
                 info->fgeom->top_height, info->fgeom->bottom_height,
@@ -470,7 +419,7 @@ setup_constraint_info (ConstraintInfo      *info,
                 (info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
                 "Freakin' Invalid Stupid",
               info->work_area_monitor.x, info->work_area_monitor.y,
-                info->work_area_monitor.width, 
+                info->work_area_monitor.width,
                 info->work_area_monitor.height,
               info->entire_monitor.x, info->entire_monitor.y,
                 info->entire_monitor.width, info->entire_monitor.height);
@@ -513,8 +462,8 @@ place_window_if_needed(MetaWindow     *window,
                                              monitor_info->number,
                                              &info->work_area_monitor);
       cur_workspace = window->screen->active_workspace;
-      info->usable_monitor_region = 
-        meta_workspace_get_onmonitor_region (cur_workspace, 
+      info->usable_monitor_region =
+        meta_workspace_get_onmonitor_region (cur_workspace,
                                              monitor_info->number);
 
 
@@ -551,7 +500,7 @@ place_window_if_needed(MetaWindow     *window,
 
           if (window->maximize_horizontally_after_placement ||
               window->maximize_vertically_after_placement)
-            meta_window_maximize_internal (window,   
+            meta_window_maximize_internal (window,
                 (window->maximize_horizontally_after_placement ?
                  META_MAXIMIZE_HORIZONTAL : 0 ) |
                 (window->maximize_vertically_after_placement ?
@@ -620,7 +569,7 @@ update_onscreen_requirements (MetaWindow     *window,
   /* The require onscreen/on-single-monitor and titlebar_visible
    * stuff is relative to the outer window, not the inner
    */
-  extend_by_frame (&info->current, info->fgeom);
+  meta_constraints_extend_by_frame (&info->current, info->fgeom);
 
   /* Update whether we want future constraint runs to require the
    * window to be on fully onscreen.
@@ -645,7 +594,7 @@ update_onscreen_requirements (MetaWindow     *window,
   if (old ^ window->require_on_single_monitor)
     meta_topic (META_DEBUG_GEOMETRY,
                 "require_on_single_monitor for %s toggled to %s\n",
-                window->desc, 
+                window->desc,
                 window->require_on_single_monitor ? "TRUE" : "FALSE");
 
   /* Update whether we want future constraint runs to require the
@@ -669,12 +618,12 @@ update_onscreen_requirements (MetaWindow     *window,
     }
 
   /* Don't forget to restore the position of the window */
-  unextend_by_frame (&info->current, info->fgeom);
+  meta_constraints_unextend_by_frame (&info->current, info->fgeom);
 }
 
-static void
-extend_by_frame (MetaRectangle           *rect,
-                 const MetaFrameGeometry *fgeom)
+void
+meta_constraints_extend_by_frame (MetaRectangle           *rect,
+                                  const MetaFrameGeometry *fgeom)
 {
   rect->x -= fgeom->left_width;
   rect->y -= fgeom->top_height;
@@ -682,9 +631,9 @@ extend_by_frame (MetaRectangle           *rect,
   rect->height += fgeom->top_height + fgeom->bottom_height;
 }
 
-static void
-unextend_by_frame (MetaRectangle           *rect,
-                   const MetaFrameGeometry *fgeom)
+void
+meta_constraints_unextend_by_frame (MetaRectangle           *rect,
+                                    const MetaFrameGeometry *fgeom)
 {
   rect->x += fgeom->left_width;
   rect->y += fgeom->top_height;
@@ -692,12 +641,12 @@ unextend_by_frame (MetaRectangle           *rect,
   rect->height -= fgeom->top_height + fgeom->bottom_height;
 }
 
-static inline void
-get_size_limits (const MetaWindow        *window,
-                 const MetaFrameGeometry *fgeom,
-                 gboolean                 include_frame,
-                 MetaRectangle *min_size,
-                 MetaRectangle *max_size)
+void
+meta_constraints_get_size_limits (const MetaWindow        *window,
+                                  const MetaFrameGeometry *fgeom,
+                                  gboolean                 include_frame,
+                                  MetaRectangle *min_size,
+                                  MetaRectangle *max_size)
 {
   /* We pack the results into MetaRectangle structs just for convienience; we
    * don't actually use the position of those rects.
@@ -769,19 +718,20 @@ constrain_maximization (MetaWindow         *window,
       active_workspace_struts = window->screen->active_workspace->all_struts;
 
       target_size = info->current;
-      extend_by_frame (&target_size, info->fgeom);
+      meta_constraints_extend_by_frame (&target_size, info->fgeom);
       meta_rectangle_expand_to_avoiding_struts (&target_size,
                                                 &info->entire_monitor,
                                                 direction,
                                                 active_workspace_struts);
    }
   /* Now make target_size = maximized size of client window */
-  unextend_by_frame (&target_size, info->fgeom);
+  meta_constraints_unextend_by_frame (&target_size, info->fgeom);
 
   /* Check min size constraints; max size constraints are ignored for maximized
    * windows, as per bug 327543.
    */
-  get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
+  meta_constraints_get_size_limits (window, info->fgeom, FALSE,
+                                    &min_size, &max_size);
   hminbad = target_size.width < min_size.width && window->maximized_horizontally;
   vminbad = target_size.height < min_size.height && window->maximized_vertically;
   if (hminbad || vminbad)
@@ -830,7 +780,8 @@ constrain_fullscreen (MetaWindow         *window,
 
   monitor = info->entire_monitor;
 
-  get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
+  meta_constraints_get_size_limits (window, info->fgeom, FALSE,
+                                    &min_size, &max_size);
   too_big =   !meta_rectangle_could_fit_rect (&monitor, &min_size);
   too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
   if (too_big || too_small)
@@ -862,7 +813,7 @@ constrain_size_increments (MetaWindow         *window,
     return TRUE;
 
   /* Determine whether constraint applies; exit if it doesn't */
-  if (META_WINDOW_MAXIMIZED (window) || window->fullscreen || 
+  if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
       info->action_type == ACTION_MOVE)
     return TRUE;
 
@@ -879,7 +830,7 @@ constrain_size_increments (MetaWindow         *window,
   if (window->maximized_vertically)
     extra_height *= 0;
   /* constraint is satisfied iff there is no extra height or width */
-  constraint_already_satisfied = 
+  constraint_already_satisfied =
     (extra_height == 0 && extra_width == 0);
 
   if (check_only || constraint_already_satisfied)
@@ -905,10 +856,10 @@ constrain_size_increments (MetaWindow         *window,
     start_rect = &info->current;
   else
     start_rect = &info->orig;
-    
+
   /* Resize to the new size */
   meta_rectangle_resize_with_gravity (start_rect,
-                                      &info->current, 
+                                      &info->current,
                                       info->resize_gravity,
                                       new_width,
                                       new_height);
@@ -938,7 +889,8 @@ constrain_size_limits (MetaWindow         *window,
     return TRUE;
 
   /* Determine whether constraint is already satisfied; exit if it is */
-  get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
+  meta_constraints_get_size_limits (window, info->fgeom, FALSE,
+                                    &min_size, &max_size);
   /* We ignore max-size limits for maximized windows; see #327543 */
   if (window->maximized_horizontally)
     max_size.width = MAX (max_size.width, info->current.width);
@@ -953,7 +905,7 @@ constrain_size_limits (MetaWindow         *window,
   /*** Enforce constraint ***/
   new_width  = CLAMP (info->current.width,  min_size.width,  max_size.width);
   new_height = CLAMP (info->current.height, min_size.height, max_size.height);
-  
+
   /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
    * See bug 448183
    */
@@ -961,9 +913,9 @@ constrain_size_limits (MetaWindow         *window,
     start_rect = &info->current;
   else
     start_rect = &info->orig;
-  
+
   meta_rectangle_resize_with_gravity (start_rect,
-                                      &info->current, 
+                                      &info->current,
                                       info->resize_gravity,
                                       new_width,
                                       new_height);
@@ -993,7 +945,7 @@ constrain_aspect_ratio (MetaWindow         *window,
          (double)window->size_hints.max_aspect.y;
   constraints_are_inconsistent = minr > maxr;
   if (constraints_are_inconsistent ||
-      META_WINDOW_MAXIMIZED (window) || window->fullscreen || 
+      META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
       info->action_type == ACTION_MOVE)
     return TRUE;
 
@@ -1032,7 +984,7 @@ constrain_aspect_ratio (MetaWindow         *window,
       fudge = 1;
       break;
     }
-  constraint_already_satisfied = 
+  constraint_already_satisfied =
     info->current.width - (info->current.height * minr ) > -minr*fudge &&
     info->current.width - (info->current.height * maxr ) <  maxr*fudge;
   if (check_only || constraint_already_satisfied)
@@ -1096,7 +1048,7 @@ constrain_aspect_ratio (MetaWindow         *window,
     start_rect = &info->orig;
 
   meta_rectangle_resize_with_gravity (start_rect,
-                                      &info->current, 
+                                      &info->current,
                                       info->resize_gravity,
                                       new_width,
                                       new_height);
@@ -1129,8 +1081,9 @@ do_screen_and_monitor_relative_constraints (
 
   /* Determine whether constraint applies; exit if it doesn't */
   how_far_it_can_be_smushed = info->current;
-  get_size_limits (window, info->fgeom, TRUE, &min_size, &max_size);
-  extend_by_frame (&info->current, info->fgeom);
+  meta_constraints_get_size_limits (window, info->fgeom, TRUE,
+                                    &min_size, &max_size);
+  meta_constraints_extend_by_frame (&info->current, info->fgeom);
 
   if (info->action_type != ACTION_MOVE)
     {
@@ -1145,12 +1098,12 @@ do_screen_and_monitor_relative_constraints (
     exit_early = TRUE;
 
   /* Determine whether constraint is already satisfied; exit if it is */
-  constraint_satisfied = 
+  constraint_satisfied =
     meta_rectangle_contained_in_region (region_spanning_rectangles,
                                         &info->current);
   if (exit_early || constraint_satisfied || check_only)
     {
-      unextend_by_frame (&info->current, info->fgeom);
+      meta_constraints_unextend_by_frame (&info->current, info->fgeom);
       return constraint_satisfied;
     }
 
@@ -1174,7 +1127,7 @@ do_screen_and_monitor_relative_constraints (
                                       info->fixed_directions,
                                       &info->current);
 
-  unextend_by_frame (&info->current, info->fgeom);
+  meta_constraints_unextend_by_frame (&info->current, info->fgeom);
   return TRUE;
 }
 
@@ -1188,7 +1141,7 @@ constrain_to_single_monitor (MetaWindow         *window,
     return TRUE;
 
   /* Exit early if we know the constraint won't apply--note that this constraint
-   * is only meant for normal windows (e.g. we don't want docks to be shoved 
+   * is only meant for normal windows (e.g. we don't want docks to be shoved
    * "onscreen" by their own strut) and we can't apply it to frameless windows
    * or else users will be unable to move windows such as XMMS across monitors.
    */
@@ -1201,7 +1154,7 @@ constrain_to_single_monitor (MetaWindow         *window,
     return TRUE;
 
   /* Have a helper function handle the constraint for us */
-  return do_screen_and_monitor_relative_constraints (window, 
+  return do_screen_and_monitor_relative_constraints (window,
                                                      info->usable_monitor_region,
                                                      info,
                                                      check_only);
@@ -1217,18 +1170,18 @@ constrain_fully_onscreen (MetaWindow         *window,
     return TRUE;
 
   /* Exit early if we know the constraint won't apply--note that this constraint
-   * is only meant for normal windows (e.g. we don't want docks to be shoved 
+   * is only meant for normal windows (e.g. we don't want docks to be shoved
    * "onscreen" by their own strut).
    */
   if (window->type == META_WINDOW_DESKTOP ||
       window->type == META_WINDOW_DOCK    ||
       window->fullscreen                  ||
-      !window->require_fully_onscreen     || 
+      !window->require_fully_onscreen     ||
       info->is_user_action)
     return TRUE;
 
   /* Have a helper function handle the constraint for us */
-  return do_screen_and_monitor_relative_constraints (window, 
+  return do_screen_and_monitor_relative_constraints (window,
                                                      info->usable_screen_region,
                                                      info,
                                                      check_only);
@@ -1256,7 +1209,7 @@ constrain_titlebar_visible (MetaWindow         *window,
     info->is_user_action && !window->display->grab_frame_action;
 
   /* Exit early if we know the constraint won't apply--note that this constraint
-   * is only meant for normal windows (e.g. we don't want docks to be shoved 
+   * is only meant for normal windows (e.g. we don't want docks to be shoved
    * "onscreen" by their own strut).
    */
   if (window->type == META_WINDOW_DESKTOP ||
@@ -1298,13 +1251,13 @@ constrain_titlebar_visible (MetaWindow         *window,
    */
   meta_rectangle_expand_region_conditionally (info->usable_screen_region,
                                               horiz_amount_offscreen,
-                                              horiz_amount_offscreen, 
+                                              horiz_amount_offscreen,
                                               0, /* Don't let titlebar off */
                                               bottom_amount,
                                               horiz_amount_onscreen,
                                               vert_amount_onscreen);
   retval =
-    do_screen_and_monitor_relative_constraints (window, 
+    do_screen_and_monitor_relative_constraints (window,
                                                 info->usable_screen_region,
                                                 info,
                                                 check_only);
@@ -1334,7 +1287,7 @@ constrain_partially_onscreen (MetaWindow         *window,
     return TRUE;
 
   /* Exit early if we know the constraint won't apply--note that this constraint
-   * is only meant for normal windows (e.g. we don't want docks to be shoved 
+   * is only meant for normal windows (e.g. we don't want docks to be shoved
    * "onscreen" by their own strut).
    */
   if (window->type == META_WINDOW_DESKTOP ||
@@ -1373,13 +1326,13 @@ constrain_partially_onscreen (MetaWindow         *window,
    */
   meta_rectangle_expand_region_conditionally (info->usable_screen_region,
                                               horiz_amount_offscreen,
-                                              horiz_amount_offscreen, 
+                                              horiz_amount_offscreen,
                                               top_amount,
                                               bottom_amount,
                                               horiz_amount_onscreen,
                                               vert_amount_onscreen);
   retval =
-    do_screen_and_monitor_relative_constraints (window, 
+    do_screen_and_monitor_relative_constraints (window,
                                                 info->usable_screen_region,
                                                 info,
                                                 check_only);
@@ -1393,3 +1346,21 @@ constrain_partially_onscreen (MetaWindow         *window,
 
   return retval;
 }
+
+static gboolean
+constrain_plugin (MetaWindow         *window,
+                  ConstraintInfo     *info,
+                  ConstraintPriority  priority,
+                  gboolean            check_only)
+{
+  MetaDisplay *display = window->screen->display;
+
+  if (!display->compositor)
+    return FALSE;
+
+  return meta_compositor_constrain_window (display->compositor,
+                                           window,
+                                           info,
+                                           priority,
+                                           check_only);
+}
diff --git a/src/core/frame-private.h b/src/core/frame-private.h
index 89c3d42..b5687f3 100644
--- a/src/core/frame-private.h
+++ b/src/core/frame-private.h
@@ -27,17 +27,6 @@
 #include "frame.h"
 #include "window-private.h"
 
-typedef struct _MetaFrameGeometry MetaFrameGeometry;
-
-struct _MetaFrameGeometry
-{  
-  /* border sizes (space between frame and child) */
-  int left_width;
-  int right_width;
-  int top_height;
-  int bottom_height;
-};
-
 struct _MetaFrame
 {
   /* window we frame */
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 77759ec..a048491 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -136,6 +136,9 @@ struct _MetaWindow
   /* Whether we have to fullscreen after placement */
   guint fullscreen_after_placement : 1;
 
+  /* Set if the user moved/resized the window */
+  guint user_placed : 1;
+
   /* Area to cover when in fullscreen mode.  If _NET_WM_FULLSCREEN_MONITORS has
    * been overridden (via a client message), the window will cover the union of
    * these monitors.  If not, this is the single monitor which the window's
diff --git a/src/core/window.c b/src/core/window.c
index 3327d9f..145b467 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -42,6 +42,7 @@
 #include "group.h"
 #include "window-props.h"
 #include "constraints.h"
+#include "constraints-private.h"
 #include "mutter-enum-types.h"
 
 #include <X11/Xatom.h>
@@ -3850,6 +3851,9 @@ meta_window_move_resize_internal (MetaWindow          *window,
   /* The action has to be a move or a resize or both... */
   g_assert (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION));
 
+  if (is_user_action)
+    window->user_placed = TRUE;
+
   /* We don't need it in the idle queue anymore. */
   meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE);
 
@@ -9117,3 +9121,21 @@ meta_window_is_modal (MetaWindow *window)
 
   return window->wm_state_modal;
 }
+
+/**
+ * meta_window_is_user_placed:
+ * @window: a #MetaWindow
+ *
+ * Queries whether the size and position of the window was assigned by the
+ * window manager, or is due to user action.
+ *
+ * Return value: (transfer none): TRUE if the window was positioned or resized
+ * by the user.
+ */
+gboolean
+meta_window_is_user_placed (MetaWindow *window)
+{
+  g_return_val_if_fail (META_IS_WINDOW (window), FALSE);
+
+  return window->user_placed;
+}
diff --git a/src/include/compositor.h b/src/include/compositor.h
index 843ff55..5e5aa46 100644
--- a/src/include/compositor.h
+++ b/src/include/compositor.h
@@ -29,6 +29,7 @@
 #include "boxes.h"
 #include "window.h"
 #include "workspace.h"
+#include "constraints.h"
 
 typedef enum _MetaCompWindowType
 {
@@ -183,4 +184,10 @@ void meta_compositor_sync_screen_size          (MetaCompositor *compositor,
                                                 guint           width,
                                                 guint           height);
 
+gboolean meta_compositor_constrain_window (MetaCompositor     *compositor,
+                                           MetaWindow         *window,
+                                           ConstraintInfo     *info,
+                                           ConstraintPriority  priority,
+                                           gboolean            check_only);
+
 #endif /* META_COMPOSITOR_H */
diff --git a/src/include/constraints.h b/src/include/constraints.h
new file mode 100644
index 0000000..06c97dc
--- /dev/null
+++ b/src/include/constraints.h
@@ -0,0 +1,97 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* Mutter size/position constraints */
+
+/*
+ * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2005 Elijah Newren
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_CONSTRAINTS_H
+#define META_CONSTRAINTS_H
+
+#include "boxes.h"
+#include "frame.h"
+
+typedef enum
+{
+  PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
+  PRIORITY_ASPECT_RATIO = 0,
+  PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
+  PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
+  PRIORITY_SIZE_HINTS_INCREMENTS = 1,
+  PRIORITY_MAXIMIZATION = 2,
+  PRIORITY_FULLSCREEN = 2,
+  PRIORITY_SIZE_HINTS_LIMITS = 3,
+  PRIORITY_TITLEBAR_VISIBLE = 4,
+  PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
+  PRIORITY_MAXIMUM = 5 /* Value used for loop end = max(all priorities)
+                        * Compositor plugins can use this value to override
+                        * all other constraints
+                        */
+} ConstraintPriority;
+
+typedef enum
+{
+  ACTION_MOVE,
+  ACTION_RESIZE,
+  ACTION_MOVE_AND_RESIZE
+} ConstraintActionType;
+
+typedef struct
+{
+  MetaRectangle        orig;
+  MetaRectangle        current;
+  MetaFrameGeometry   *fgeom;
+  ConstraintActionType action_type;
+  gboolean             is_user_action;
+
+  /* I know that these two things probably look similar at first, but they
+   * have much different uses.  See doc/how-constraints-works.txt for for
+   * explanation of the differences and similarity between resize_gravity
+   * and fixed_directions
+   */
+  int                  resize_gravity;
+  FixedDirections      fixed_directions;
+
+  /* work_area_monitor - current monitor region minus struts
+   * entire_monitor    - current monitor, including strut regions
+   */
+  MetaRectangle        work_area_monitor;
+  MetaRectangle        entire_monitor;
+
+  /* Spanning rectangles for the non-covered (by struts) region of the
+   * screen and also for just the current monitor
+   */
+  GList  *usable_screen_region;
+  GList  *usable_monitor_region;
+} ConstraintInfo;
+
+void meta_constraints_unextend_by_frame (MetaRectangle           *rect,
+                                         const MetaFrameGeometry *fgeom);
+
+void meta_constraints_extend_by_frame (MetaRectangle           *rect,
+                                       const MetaFrameGeometry *fgeom);
+
+void meta_constraints_get_size_limits (const MetaWindow        *window,
+                                       const MetaFrameGeometry *fgeom,
+                                       gboolean include_frame,
+                                       MetaRectangle *min_size,
+                                       MetaRectangle *max_size);
+
+#endif
diff --git a/src/include/frame.h b/src/include/frame.h
index eeb5726..5db4d8f 100644
--- a/src/include/frame.h
+++ b/src/include/frame.h
@@ -26,6 +26,15 @@
 
 #include "types.h"
 
+struct _MetaFrameGeometry
+{
+  /* border sizes (space between frame and child) */
+  int left_width;
+  int right_width;
+  int top_height;
+  int bottom_height;
+};
+
 Window meta_frame_get_xwindow (MetaFrame *frame);
 
 #endif
diff --git a/src/include/mutter-plugin.h b/src/include/mutter-plugin.h
index cab678c..8778c5c 100644
--- a/src/include/mutter-plugin.h
+++ b/src/include/mutter-plugin.h
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
 /*
- * Copyright (c) 2008 Intel Corp.
+ * Copyright (c) 2008, 2010 Intel Corp.
  *
  * Author: Tomas Frydrych <tf linux intel com>
  *
@@ -25,6 +25,7 @@
 #define MUTTER_PLUGIN_H_
 
 #include "types.h"
+#include "constraints.h"
 #include "compositor.h"
 #include "compositor-mutter.h"
 #include "mutter-shadow.h"
@@ -119,6 +120,12 @@ struct _MutterPluginClass
 
   MutterShadow           * (*get_shadow) (MutterPlugin *plugin,
                                           MutterWindow *window);
+
+  gboolean (*constrain_window) (MutterPlugin       *plugin,
+                                MetaWindow         *window,
+                                ConstraintInfo     *info,
+                                ConstraintPriority  priority,
+                                gboolean            check_only);
 };
 
 struct _MutterPluginInfo
diff --git a/src/include/types.h b/src/include/types.h
index 3fc60c9..96ff612 100644
--- a/src/include/types.h
+++ b/src/include/types.h
@@ -25,6 +25,7 @@
 typedef struct _MetaCompositor  MetaCompositor;
 typedef struct _MetaDisplay     MetaDisplay;
 typedef struct _MetaFrame       MetaFrame;
+typedef struct _MetaFrameGeometry MetaFrameGeometry;
 typedef struct _MetaScreen      MetaScreen;
 typedef struct _MetaWindow      MetaWindow;
 typedef struct _MetaWorkspace   MetaWorkspace;
diff --git a/src/include/window.h b/src/include/window.h
index d14e76e..bf20454 100644
--- a/src/include/window.h
+++ b/src/include/window.h
@@ -125,4 +125,6 @@ guint32     meta_window_get_user_time (MetaWindow *window);
 int         meta_window_get_pid (MetaWindow *window);
 const char *meta_window_get_client_machine (MetaWindow *window);
 gboolean    meta_window_is_modal (MetaWindow *window);
+gboolean    meta_window_is_user_placed (MetaWindow *window);
+
 #endif
diff --git a/src/ui/frames.h b/src/ui/frames.h
index ad8d361..ed341aa 100644
--- a/src/ui/frames.h
+++ b/src/ui/frames.h
@@ -55,6 +55,58 @@ typedef enum
   META_FRAME_CONTROL_CLIENT_AREA
 } MetaFrameControl;
 
+/**
+ * Calculated actual geometry of the frame
+ */
+struct _MetaFrameGeometry
+{
+  int left_width;
+  int right_width;
+  int top_height;
+  int bottom_height;
+
+  int width;
+  int height;
+
+  GdkRectangle title_rect;
+
+  int left_titlebar_edge;
+  int right_titlebar_edge;
+  int top_titlebar_edge;
+  int bottom_titlebar_edge;
+
+  /* used for a memset hack */
+#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
+#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_right_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
+ 
+  /* The button rects (if changed adjust memset hack) */
+  MetaButtonSpace close_rect;
+  MetaButtonSpace max_rect;
+  MetaButtonSpace min_rect;
+  MetaButtonSpace menu_rect;
+  MetaButtonSpace shade_rect;
+  MetaButtonSpace above_rect;
+  MetaButtonSpace stick_rect;
+  MetaButtonSpace unshade_rect;
+  MetaButtonSpace unabove_rect;
+  MetaButtonSpace unstick_rect;
+
+#define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2)
+  GdkRectangle left_left_background;
+  GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
+  GdkRectangle left_right_background;
+  GdkRectangle right_left_background;
+  GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
+  GdkRectangle right_right_background;
+  /* End of button rects (if changed adjust memset hack) */
+
+  /* Round corners */
+  guint top_left_corner_rounded_radius;
+  guint top_right_corner_rounded_radius;
+  guint bottom_left_corner_rounded_radius;
+  guint bottom_right_corner_rounded_radius;
+};
+
 /* This is one widget that manages all the window frames
  * as subwindows.
  */
diff --git a/src/ui/theme.c b/src/ui/theme.c
index ae640d9..902a9b5 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -57,6 +57,7 @@
 #include "theme-parser.h"
 #include "util.h"
 #include "gradient.h"
+#include "frames.h"
 #include <gtk/gtk.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/src/ui/theme.h b/src/ui/theme.h
index ddf777d..6b3ea1d 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -27,6 +27,8 @@
 #include "boxes.h"
 #include "gradient.h"
 #include "common.h"
+#include "types.h"
+
 #include <gtk/gtk.h>
 
 typedef struct _MetaFrameStyle MetaFrameStyle;
@@ -38,7 +40,6 @@ typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
 typedef struct _MetaColorSpec MetaColorSpec;
 typedef struct _MetaFrameLayout MetaFrameLayout;
 typedef struct _MetaButtonSpace MetaButtonSpace;
-typedef struct _MetaFrameGeometry MetaFrameGeometry;
 typedef struct _MetaTheme MetaTheme;
 typedef struct _MetaPositionExprEnv MetaPositionExprEnv;
 typedef struct _MetaDrawInfo MetaDrawInfo;
@@ -163,58 +164,6 @@ struct _MetaButtonSpace
   GdkRectangle clickable;
 };
 
-/**
- * Calculated actual geometry of the frame
- */
-struct _MetaFrameGeometry
-{
-  int left_width;
-  int right_width;
-  int top_height;
-  int bottom_height;
-
-  int width;
-  int height;  
-
-  GdkRectangle title_rect;
-
-  int left_titlebar_edge;
-  int right_titlebar_edge;
-  int top_titlebar_edge;
-  int bottom_titlebar_edge;
-
-  /* used for a memset hack */
-#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
-#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_right_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
-  
-  /* The button rects (if changed adjust memset hack) */
-  MetaButtonSpace close_rect;
-  MetaButtonSpace max_rect;
-  MetaButtonSpace min_rect;
-  MetaButtonSpace menu_rect;
-  MetaButtonSpace shade_rect;
-  MetaButtonSpace above_rect;
-  MetaButtonSpace stick_rect;
-  MetaButtonSpace unshade_rect;
-  MetaButtonSpace unabove_rect;
-  MetaButtonSpace unstick_rect;
-
-#define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2)
-  GdkRectangle left_left_background;
-  GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
-  GdkRectangle left_right_background;
-  GdkRectangle right_left_background;
-  GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
-  GdkRectangle right_right_background;
-  /* End of button rects (if changed adjust memset hack) */
-  
-  /* Round corners */
-  guint top_left_corner_rounded_radius;
-  guint top_right_corner_rounded_radius;
-  guint bottom_left_corner_rounded_radius;
-  guint bottom_right_corner_rounded_radius;
-};
-
 typedef enum
 {
   META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */



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