summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElijah Newren <newren gmail com>2007-04-03 03:41:10 +0000
committerElijah Newren <newren@src.gnome.org>2007-04-03 03:41:10 +0000
commit08f51fdf9430cc96b01d72344ff4b36d38281f40 (patch)
tree3fa49ebc25e115155b4863f7539c08fc36a6d1df
parente82ce2642540cd2f9c3bb8fb33dcc41fb1e3ab11 (diff)
downloadmetacity-08f51fdf9430cc96b01d72344ff4b36d38281f40.tar.gz
Patch from Carlo Wood to fix handling of unidirectional maximization and
2007-04-02 Elijah Newren <newren gmail com> Patch from Carlo Wood to fix handling of unidirectional maximization and partial struts. #358311. * src/constraints.c (constrain_maximization): determine target size for unidirectionally maximized windows by determining how far they can be maximized without hitting orthogonal struts. Avoids weird "empty spaces". * src/boxes.[ch] (meta_rectangle_expand_to_avoiding_struts): new function 2007-04-02 Elijah Newren <newren gmail com> Make the strut lists (stored in workspaces) record both the rectangle and the side that the strut is on. Lots of code cleanups relating to struts. * src/boxes.h (struct MetaStrut): new struct for struts * src/window.[ch] (struct MetaStruts, struct MetaWindow, meta_window_update_struts): overhaul to make window's struts remember their side as well as their rectangular location, and just use a list instead of several copies of near-identical code for left/right/top/bottom (allowing us to nuke MetaStruts struct as well) * src/testboxes.c (new_meta_strut, get_strut_list): * src/workspace.c (ensure_work_areas_validated): * src/boxes.c (meta_rectangle_get_minimal_spanning_set_for_region, meta_rectangle_expand_to_avoiding_struts, get_disjoint_strut_rect_list_in_region, fix_up_edges, meta_rectangle_find_onscreen_edges, meta_rectangle_find_nonintersected_xinerama_edges): modify to handle struts being rectangle + side instead of just rectangle * src/workspace.c (ensure_work_areas_validated): simplify strut list creation considerably given MetaWindow change, modify work_area computations to take advantage of region computations being done (makes the code shorter as well as more robust against pathological cases). * src/util.[ch] (meta_free_gslist_and_elements): new convenience function * src/common.h (enum MetaDirection): * src/edge-resistance.c (movement_towards_edge): * src/boxes.c (meta_rectangle_edge_aligns, rectangle_and_edge_intersection, split_edge): Add more MetaDirection fields for convenience * src/boxes.h (enum FixedDirections): * src/constraints.c (setup_constraint_info, place_window_if_needed): add a FIXED_DIRECTION_NONE to the FixedDirections enum to make code more clear svn path=/trunk/; revision=3144
-rw-r--r--ChangeLog58
-rw-r--r--src/boxes.c166
-rw-r--r--src/boxes.h23
-rw-r--r--src/common.h24
-rw-r--r--src/constraints.c68
-rw-r--r--src/edge-resistance.c4
-rw-r--r--src/testboxes.c50
-rw-r--r--src/util.c9
-rw-r--r--src/util.h2
-rw-r--r--src/window.c241
-rw-r--r--src/window.h12
-rw-r--r--src/workspace.c303
12 files changed, 543 insertions, 417 deletions
diff --git a/ChangeLog b/ChangeLog
index aafd938d..2df40b11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+2007-04-02 Elijah Newren <newren gmail com>
+
+ Patch from Carlo Wood to fix handling of unidirectional
+ maximization and partial struts. #358311.
+
+ * src/constraints.c (constrain_maximization):
+ determine target size for unidirectionally maximized windows by
+ determining how far they can be maximized without hitting
+ orthogonal struts. Avoids weird "empty spaces".
+
+ * src/boxes.[ch] (meta_rectangle_expand_to_avoiding_struts):
+ new function
+
+2007-04-02 Elijah Newren <newren gmail com>
+
+ Make the strut lists (stored in workspaces) record both the
+ rectangle and the side that the strut is on. Lots of code
+ cleanups relating to struts.
+
+ * src/boxes.h (struct MetaStrut):
+ new struct for struts
+
+ * src/window.[ch] (struct MetaStruts, struct MetaWindow,
+ meta_window_update_struts):
+ overhaul to make window's struts remember their side as well as
+ their rectangular location, and just use a list instead of several
+ copies of near-identical code for left/right/top/bottom (allowing
+ us to nuke MetaStruts struct as well)
+
+ * src/testboxes.c (new_meta_strut, get_strut_list):
+ * src/workspace.c (ensure_work_areas_validated):
+ * src/boxes.c (meta_rectangle_get_minimal_spanning_set_for_region,
+ meta_rectangle_expand_to_avoiding_struts,
+ get_disjoint_strut_rect_list_in_region, fix_up_edges,
+ meta_rectangle_find_onscreen_edges,
+ meta_rectangle_find_nonintersected_xinerama_edges):
+ modify to handle struts being rectangle + side instead of just rectangle
+
+ * src/workspace.c (ensure_work_areas_validated):
+ simplify strut list creation considerably given MetaWindow change,
+ modify work_area computations to take advantage of region
+ computations being done (makes the code shorter as well as more
+ robust against pathological cases).
+
+ * src/util.[ch] (meta_free_gslist_and_elements):
+ new convenience function
+
+ * src/common.h (enum MetaDirection):
+ * src/edge-resistance.c (movement_towards_edge):
+ * src/boxes.c (meta_rectangle_edge_aligns,
+ rectangle_and_edge_intersection, split_edge):
+ Add more MetaDirection fields for convenience
+
+ * src/boxes.h (enum FixedDirections):
+ * src/constraints.c (setup_constraint_info, place_window_if_needed):
+ add a FIXED_DIRECTION_NONE to the FixedDirections enum to make
+ code more clear
+
2007-04-01 Bruno Boaventura <brunobol@gnome.org>
* src/theme.c (kill_window_question): Fallback to NORMAL state after
diff --git a/src/boxes.c b/src/boxes.c
index f40a085e..cc0fbac9 100644
--- a/src/boxes.c
+++ b/src/boxes.c
@@ -547,10 +547,10 @@ meta_rectangle_get_minimal_spanning_set_for_region (
ret = g_list_prepend (NULL, temp_rect);
strut_iter = all_struts;
- while (strut_iter)
+ for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
- MetaRectangle *strut = (MetaRectangle*) strut_iter->data;
+ MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
tmp_list = ret;
ret = NULL;
@@ -558,45 +558,45 @@ meta_rectangle_get_minimal_spanning_set_for_region (
while (rect_iter)
{
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
- if (!meta_rectangle_overlap (rect, strut))
+ if (!meta_rectangle_overlap (rect, strut_rect))
ret = g_list_prepend (ret, rect);
else
{
/* If there is area in rect left of strut */
- if (rect->x < strut->x)
+ if (BOX_LEFT (*rect) < BOX_LEFT (*strut_rect))
{
temp_rect = g_new (MetaRectangle, 1);
*temp_rect = *rect;
- temp_rect->width = strut->x - rect->x;
+ temp_rect->width = BOX_LEFT (*strut_rect) - BOX_LEFT (*rect);
ret = g_list_prepend (ret, temp_rect);
}
/* If there is area in rect right of strut */
- if (rect->x + rect->width > strut->x + strut->width)
+ if (BOX_RIGHT (*rect) > BOX_RIGHT (*strut_rect))
{
int new_x;
temp_rect = g_new (MetaRectangle, 1);
*temp_rect = *rect;
- new_x = strut->x + strut->width;
- temp_rect->width = rect->x + rect->width - new_x;
+ new_x = BOX_RIGHT (*strut_rect);
+ temp_rect->width = BOX_RIGHT(*rect) - new_x;
temp_rect->x = new_x;
ret = g_list_prepend (ret, temp_rect);
}
/* If there is area in rect above strut */
- if (rect->y < strut->y)
+ if (BOX_TOP (*rect) < BOX_TOP (*strut_rect))
{
temp_rect = g_new (MetaRectangle, 1);
*temp_rect = *rect;
- temp_rect->height = strut->y - rect->y;
+ temp_rect->height = BOX_TOP (*strut_rect) - BOX_TOP (*rect);
ret = g_list_prepend (ret, temp_rect);
}
/* If there is area in rect below strut */
- if (rect->y + rect->height > strut->y + strut->height)
+ if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*strut_rect))
{
int new_y;
temp_rect = g_new (MetaRectangle, 1);
*temp_rect = *rect;
- new_y = strut->y + strut->height;
- temp_rect->height = rect->y + rect->height - new_y;
+ new_y = BOX_BOTTOM (*strut_rect);
+ temp_rect->height = BOX_BOTTOM (*rect) - new_y;
temp_rect->y = new_y;
ret = g_list_prepend (ret, temp_rect);
}
@@ -605,7 +605,6 @@ meta_rectangle_get_minimal_spanning_set_for_region (
rect_iter = rect_iter->next;
}
g_list_free (tmp_list);
- strut_iter = strut_iter->next;
}
/* Sort by maximal area, just because I feel like it... */
@@ -663,6 +662,76 @@ meta_rectangle_expand_region_conditionally (GList *region,
}
void
+meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
+ const MetaRectangle *expand_to,
+ const MetaDirection direction,
+ const GSList *all_struts)
+{
+ const GSList *strut_iter;
+
+ /* If someone wants this function to handle more fine-grained
+ * direction expanding in the future (e.g. only left, or fully
+ * horizontal plus upward), feel free. But I'm hard-coding for both
+ * horizontal directions (exclusive-)or both vertical directions.
+ */
+ g_assert ((direction == META_DIRECTION_HORIZONTAL) ^
+ (direction == META_DIRECTION_VERTICAL ));
+
+ if (direction == META_DIRECTION_HORIZONTAL)
+ {
+ rect->x = expand_to->x;
+ rect->width = expand_to->width;
+ }
+ else
+ {
+ rect->y = expand_to->y;
+ rect->height = expand_to->height;
+ }
+
+
+ /* Run over all struts */
+ for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
+ {
+ MetaStrut *strut = (MetaStrut*) strut_iter->data;
+
+ /* Skip struts that don't overlap */
+ if (!meta_rectangle_overlap (&strut->rect, rect))
+ continue;
+
+ if (direction == META_DIRECTION_HORIZONTAL)
+ {
+ if (strut->side == META_SIDE_LEFT)
+ {
+ int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect);
+ rect->x += offset;
+ rect->width -= offset;
+ }
+ else if (strut->side == META_SIDE_RIGHT)
+ {
+ int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect);
+ rect->width -= offset;
+ }
+ /* else ignore the strut */
+ }
+ else /* direction == META_DIRECTION_VERTICAL */
+ {
+ if (strut->side == META_SIDE_TOP)
+ {
+ int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect);
+ rect->y += offset;
+ rect->height -= offset;
+ }
+ else if (strut->side == META_SIDE_BOTTOM)
+ {
+ int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect);
+ rect->height -= offset;
+ }
+ /* else ignore the strut */
+ }
+ } /* end loop over struts */
+} /* end meta_rectangle_expand_to_avoiding_struts */
+
+void
meta_rectangle_free_list_and_elements (GList *filled_list)
{
g_list_foreach (filled_list,
@@ -1075,9 +1144,9 @@ meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge)
case META_DIRECTION_BOTTOM:
return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
+ default:
+ g_assert_not_reached ();
}
-
- g_assert_not_reached ();
}
static GList*
@@ -1161,27 +1230,27 @@ replace_rect_with_list (GList *old_element,
}
/* Make a copy of the strut list, make sure that copy only contains parts
- * of the old_struts that intersect with the rection rect, and then do some
+ * of the old_struts that intersect with the region rect, and then do some
* magic to make all the new struts disjoint (okay, we we break up struts
* that aren't disjoint in a way that the overlapping part is only included
* once, so it's not really magic...).
*/
static GList*
-get_disjoint_strut_list_in_region (const GSList *old_struts,
- const MetaRectangle *region)
+get_disjoint_strut_rect_list_in_region (const GSList *old_struts,
+ const MetaRectangle *region)
{
- GList *struts;
+ GList *strut_rects;
GList *tmp;
/* First, copy the list */
- struts = NULL;
+ strut_rects = NULL;
while (old_struts)
{
- MetaRectangle *cur = old_struts->data;
+ MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect;
MetaRectangle *copy = g_new (MetaRectangle, 1);
*copy = *cur;
if (meta_rectangle_intersect (copy, region, copy))
- struts = g_list_prepend (struts, copy);
+ strut_rects = g_list_prepend (strut_rects, copy);
else
g_free (copy);
@@ -1191,7 +1260,7 @@ get_disjoint_strut_list_in_region (const GSList *old_struts,
/* Now, loop over the list and check for intersections, fixing things up
* where they do intersect.
*/
- tmp = struts;
+ tmp = strut_rects;
while (tmp)
{
GList *compare;
@@ -1218,10 +1287,10 @@ get_disjoint_strut_list_in_region (const GSList *old_struts,
cur_leftover = g_list_prepend (cur_leftover, overlap_allocated);
/* Fix up tmp, compare, and cur -- maybe struts too */
- if (struts == tmp)
+ if (strut_rects == tmp)
{
- struts = replace_rect_with_list (tmp, cur_leftover);
- tmp = struts;
+ strut_rects = replace_rect_with_list (tmp, cur_leftover);
+ tmp = strut_rects;
}
else
tmp = replace_rect_with_list (tmp, cur_leftover);
@@ -1239,7 +1308,7 @@ get_disjoint_strut_list_in_region (const GSList *old_struts,
tmp = tmp->next;
}
- return struts;
+ return strut_rects;
}
gint
@@ -1347,7 +1416,7 @@ rectangle_and_edge_intersection (const MetaRectangle *rect,
/* Find out if the intersection is empty; have to do it this way since
* edges have a thickness of 0
*/
- if ((result->width < 0 || result->height < 0) ||
+ if ((result->width < 0 || result->height < 0) ||
(result->width == 0 && result->height == 0))
{
result->width = 0;
@@ -1397,6 +1466,8 @@ rectangle_and_edge_intersection (const MetaRectangle *rect,
else
*handle_type = 0;
break;
+ default:
+ g_assert_not_reached ();
}
}
return intersect;
@@ -1503,23 +1574,25 @@ split_edge (GList *cur_list,
cur_list = g_list_prepend (cur_list, temp_edge);
}
break;
+ default:
+ g_assert_not_reached ();
}
return cur_list;
}
/* Split up edge and remove preliminary edges from strut_edges depending on
- * if and how strut and edge intersect.
+ * if and how rect and edge intersect.
*/
static void
-fix_up_edges (MetaRectangle *strut, MetaEdge *edge,
+fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
GList **strut_edges, GList **edge_splits,
gboolean *edge_needs_removal)
{
MetaEdge overlap;
int handle_type;
- if (!rectangle_and_edge_intersection (strut, edge, &overlap, &handle_type))
+ if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type))
return;
if (handle_type == 0 || handle_type == 1)
@@ -1628,9 +1701,9 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
const GSList *all_struts)
{
GList *ret;
- GList *fixed_struts;
+ GList *fixed_strut_rects;
GList *edge_iter;
- const GList *strut_iter;
+ const GList *strut_rect_iter;
/* The algorithm is basically as follows:
* Make sure the struts are disjoint
@@ -1648,18 +1721,19 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
*/
/* Make sure the struts are disjoint */
- fixed_struts = get_disjoint_strut_list_in_region (all_struts, basic_rect);
+ fixed_strut_rects =
+ get_disjoint_strut_rect_list_in_region (all_struts, basic_rect);
/* Start off the list with the edges of basic_rect */
ret = add_edges (NULL, basic_rect, TRUE);
- strut_iter = fixed_struts;
- while (strut_iter)
+ strut_rect_iter = fixed_strut_rects;
+ while (strut_rect_iter)
{
- MetaRectangle *strut = (MetaRectangle*) strut_iter->data;
+ MetaRectangle *strut_rect = (MetaRectangle*) strut_rect_iter->data;
/* Get the new possible edges we may need to add from the strut */
- GList *new_strut_edges = add_edges (NULL, strut, FALSE);
+ GList *new_strut_edges = add_edges (NULL, strut_rect, FALSE);
edge_iter = ret;
while (edge_iter)
@@ -1668,7 +1742,7 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
GList *splits_of_cur_edge = NULL;
gboolean edge_needs_removal = FALSE;
- fix_up_edges (strut, cur_edge,
+ fix_up_edges (strut_rect, cur_edge,
&new_strut_edges, &splits_of_cur_edge,
&edge_needs_removal);
@@ -1692,14 +1766,14 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
}
ret = g_list_concat (new_strut_edges, ret);
- strut_iter = strut_iter->next;
+ strut_rect_iter = strut_rect_iter->next;
}
/* Sort the list */
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
/* Free the fixed struts list */
- meta_rectangle_free_list_and_elements (fixed_struts);
+ meta_rectangle_free_list_and_elements (fixed_strut_rects);
return ret;
}
@@ -1716,6 +1790,7 @@ meta_rectangle_find_nonintersected_xinerama_edges (
*/
GList *ret;
const GList *cur;
+ GSList *temp_rects;
/* Initialize the return list to be empty */
ret = NULL;
@@ -1823,8 +1898,13 @@ meta_rectangle_find_nonintersected_xinerama_edges (
cur = cur->next;
}
+ temp_rects = NULL;
+ for (; all_struts; all_struts = all_struts->next)
+ temp_rects = g_slist_prepend (temp_rects,
+ &((MetaStrut*)all_struts->data)->rect);
ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,
- all_struts);
+ temp_rects);
+ g_slist_free (temp_rects);
/* Sort the list */
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
diff --git a/src/boxes.h b/src/boxes.h
index 5c9552da..145dbb05 100644
--- a/src/boxes.h
+++ b/src/boxes.h
@@ -28,7 +28,6 @@
#include "common.h"
typedef struct _MetaRectangle MetaRectangle;
-
struct _MetaRectangle
{
int x;
@@ -37,6 +36,13 @@ struct _MetaRectangle
int height;
};
+typedef struct _MetaStrut MetaStrut;
+struct _MetaStrut
+{
+ MetaRectangle rect;
+ MetaDirection side;
+};
+
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
@@ -44,8 +50,9 @@ struct _MetaRectangle
typedef enum
{
- FIXED_DIRECTION_X = 1 << 0,
- FIXED_DIRECTION_Y = 1 << 1,
+ FIXED_DIRECTION_NONE = 0,
+ FIXED_DIRECTION_X = 1 << 0,
+ FIXED_DIRECTION_Y = 1 << 1,
} FixedDirections;
typedef enum
@@ -166,6 +173,16 @@ GList* meta_rectangle_expand_region_conditionally (
const int min_x,
const int min_y);
+/* Expand rect in direction to the size of expand_to, and then clip out any
+ * overlapping struts oriented orthognal to the expansion direction. (Think
+ * horizontal or vertical maximization)
+ */
+void meta_rectangle_expand_to_avoiding_struts (
+ MetaRectangle *rect,
+ const MetaRectangle *expand_to,
+ const MetaDirection direction,
+ const GSList *all_struts);
+
/* Free the list created by
* meta_rectangle_get_minimal_spanning_set_for_region()
* or
diff --git a/src/common.h b/src/common.h
index 087798e0..c24def53 100644
--- a/src/common.h
+++ b/src/common.h
@@ -216,12 +216,24 @@ typedef enum
*/
typedef enum
{
- META_DIRECTION_LEFT = 1 << 0,
- META_DIRECTION_RIGHT = 1 << 1,
- META_DIRECTION_TOP = 1 << 2,
- META_DIRECTION_BOTTOM = 1 << 3,
- META_DIRECTION_UP = 1 << 2, /* Alternate name for TOP */
- META_DIRECTION_DOWN = 1 << 3 /* Alternate name for BOTTOM */
+ META_DIRECTION_LEFT = 1 << 0,
+ META_DIRECTION_RIGHT = 1 << 1,
+ META_DIRECTION_TOP = 1 << 2,
+ META_DIRECTION_BOTTOM = 1 << 3,
+
+ /* Some aliases for making code more readable for various circumstances. */
+ META_DIRECTION_UP = META_DIRECTION_TOP,
+ META_DIRECTION_DOWN = META_DIRECTION_BOTTOM,
+
+ /* A few more definitions using aliases */
+ META_DIRECTION_HORIZONTAL = META_DIRECTION_LEFT | META_DIRECTION_RIGHT,
+ META_DIRECTION_VERTICAL = META_DIRECTION_UP | META_DIRECTION_DOWN,
+
+ /* And a few more aliases */
+ META_SIDE_LEFT = META_DIRECTION_LEFT,
+ META_SIDE_RIGHT = META_DIRECTION_RIGHT,
+ META_SIDE_TOP = META_DIRECTION_TOP,
+ META_SIDE_BOTTOM = META_DIRECTION_BOTTOM
} MetaDirection;
/* Function a window button can have. Note, you can't add stuff here
diff --git a/src/constraints.c b/src/constraints.c
index c6044ef4..d868c964 100644
--- a/src/constraints.c
+++ b/src/constraints.c
@@ -365,7 +365,7 @@ setup_constraint_info (ConstraintInfo *info,
* and (b) ignored it for aspect ratio windows -- at least in those
* cases where both directions do actually change size.
*/
- info->fixed_directions = 0;
+ info->fixed_directions = FIXED_DIRECTION_NONE;
/* If x directions don't change but either y direction does */
if ( orig->x == new->x && orig->x + orig->width == new->x + new->width &&
(orig->y != new->y || orig->y + orig->height != new->y + new->height))
@@ -385,7 +385,7 @@ setup_constraint_info (ConstraintInfo *info,
* aren't explicit user interaction, though, so just clear it out.
*/
if (!info->is_user_action)
- info->fixed_directions = 0;
+ info->fixed_directions = FIXED_DIRECTION_NONE;
xinerama_info =
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
@@ -441,7 +441,7 @@ setup_constraint_info (ConstraintInfo *info,
"Freakin' Invalid Stupid",
(info->is_user_action) ? "true" : "false",
meta_gravity_to_string (info->resize_gravity),
- (info->fixed_directions == 0) ? "None" :
+ (info->fixed_directions == FIXED_DIRECTION_NONE) ? "None" :
(info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
"Freakin' Invalid Stupid",
@@ -500,7 +500,7 @@ place_window_if_needed(MetaWindow *window,
/* Since we just barely placed the window, there's no reason to
* consider any of the directions fixed.
*/
- info->fixed_directions = 0;
+ info->fixed_directions = FIXED_DIRECTION_NONE;
}
if (window->placed || did_placement)
@@ -691,7 +691,8 @@ constrain_maximization (MetaWindow *window,
ConstraintPriority priority,
gboolean check_only)
{
- MetaRectangle min_size, max_size, work_area;
+ MetaRectangle target_size;
+ MetaRectangle min_size, max_size;
gboolean hminbad, vminbad;
gboolean horiz_equal, vert_equal;
gboolean constraint_already_satisfied;
@@ -703,20 +704,51 @@ constrain_maximization (MetaWindow *window,
if (!window->maximized_horizontally && !window->maximized_vertically)
return TRUE;
- work_area = info->work_area_xinerama;
- unextend_by_frame (&work_area, info->fgeom);
+ /* Calculate target_size = maximized size of (window + frame) */
+ if (window->maximized_horizontally && window->maximized_vertically)
+ target_size = info->work_area_xinerama;
+ else
+ {
+ /* Amount of maximization possible in a single direction depends
+ * on which struts could occlude the window given its current
+ * position. For example, a vertical partial strut on the right
+ * is only relevant for a horizontally maximized window when the
+ * window is at a vertical position where it could be occluded
+ * by that partial strut.
+ */
+ MetaDirection direction;
+ GSList *active_workspace_struts;
+
+ if (window->maximized_horizontally)
+ direction = META_DIRECTION_HORIZONTAL;
+ else
+ direction = META_DIRECTION_VERTICAL;
+ active_workspace_struts = window->screen->active_workspace->all_struts;
+
+ target_size = info->current;
+ extend_by_frame (&target_size, info->fgeom);
+ meta_rectangle_expand_to_avoiding_struts (&target_size,
+ &info->entire_xinerama,
+ direction,
+ active_workspace_struts);
+ }
+ /* Now make target_size = maximized size of client window */
+ 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);
-
- hminbad = work_area.width < min_size.width && window->maximized_horizontally;
- vminbad = work_area.height < min_size.height && window->maximized_vertically;
+ hminbad = target_size.width < min_size.width && window->maximized_horizontally;
+ vminbad = target_size.height < min_size.height && window->maximized_vertically;
if (hminbad || vminbad)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
- horiz_equal = work_area.x == info->current.x &&
- work_area.width == info->current.width;
- vert_equal = work_area.y == info->current.y &&
- work_area.height == info->current.height;
+ horiz_equal = target_size.x == info->current.x &&
+ target_size.width == info->current.width;
+ vert_equal = target_size.y == info->current.y &&
+ target_size.height == info->current.height;
constraint_already_satisfied =
(horiz_equal || !window->maximized_horizontally) &&
(vert_equal || !window->maximized_vertically);
@@ -726,13 +758,13 @@ constrain_maximization (MetaWindow *window,
/*** Enforce constraint ***/
if (window->maximized_horizontally)
{
- info->current.x = work_area.x;
- info->current.width = work_area.width;
+ info->current.x = target_size.x;
+ info->current.width = target_size.width;
}
if (window->maximized_vertically)
{
- info->current.y = work_area.y;
- info->current.height = work_area.height;
+ info->current.y = target_size.y;
+ info->current.height = target_size.height;
}
return TRUE;
}
diff --git a/src/edge-resistance.c b/src/edge-resistance.c
index 3db21ab4..68806648 100644
--- a/src/edge-resistance.c
+++ b/src/edge-resistance.c
@@ -300,9 +300,9 @@ movement_towards_edge (MetaDirection side, int increment)
case META_DIRECTION_RIGHT:
case META_DIRECTION_BOTTOM:
return increment > 0;
+ default:
+ g_assert_not_reached ();
}
-
- g_assert_not_reached ();
}
static gboolean
diff --git a/src/testboxes.c b/src/testboxes.c
index 9e958b75..0da29750 100644
--- a/src/testboxes.c
+++ b/src/testboxes.c
@@ -58,6 +58,17 @@ new_meta_rect (int x, int y, int width, int height)
return temporary;
}
+static MetaStrut*
+new_meta_strut (int x, int y, int width, int height, int side)
+{
+ MetaStrut* temporary;
+ temporary = g_new (MetaStrut, 1);
+ temporary->rect = meta_rect(x, y, width, height);
+ temporary->side = side;
+
+ return temporary;
+}
+
static MetaEdge*
new_screen_edge (int x, int y, int width, int height, int side_type)
{
@@ -228,9 +239,10 @@ free_strut_list (GSList *struts)
static GSList*
get_strut_list (int which)
{
- GSList *struts;
+ GSList *ans;
+ MetaDirection wc = 0; /* wc == who cares? ;-) */
- struts = NULL;
+ ans = NULL;
g_assert (which >=0 && which <= 6);
switch (which)
@@ -238,36 +250,36 @@ get_strut_list (int which)
case 0:
break;
case 1:
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
- struts = g_slist_prepend (struts, new_meta_rect ( 400, 1160, 1600, 40));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
break;
case 2:
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
- struts = g_slist_prepend (struts, new_meta_rect ( 800, 1100, 400, 100));
- struts = g_slist_prepend (struts, new_meta_rect ( 300, 1150, 150, 50));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
break;
case 3:
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
- struts = g_slist_prepend (struts, new_meta_rect ( 800, 1100, 400, 100));
- struts = g_slist_prepend (struts, new_meta_rect ( 300, 1150, 80, 50));
- struts = g_slist_prepend (struts, new_meta_rect ( 700, 525, 200, 150));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
break;
case 4:
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 800, 1200));
- struts = g_slist_prepend (struts, new_meta_rect ( 800, 0, 1600, 20));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
break;
case 5:
- struts = g_slist_prepend (struts, new_meta_rect ( 800, 0, 1600, 20));
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 800, 1200));
- struts = g_slist_prepend (struts, new_meta_rect ( 800, 10, 800, 1200));
+ ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
break;
case 6:
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 40));
- struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
+ ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
break;
}
- return struts;
+ return ans;
}
static GList*
diff --git a/src/util.c b/src/util.c
index 9fdecd6f..ca2452f3 100644
--- a/src/util.c
+++ b/src/util.c
@@ -199,6 +199,15 @@ utf8_fputs (const char *str,
return retval;
}
+void
+meta_free_gslist_and_elements (GSList *list_to_deep_free)
+{
+ g_slist_foreach (list_to_deep_free,
+ (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */
+ NULL);
+ g_slist_free (list_to_deep_free);
+}
+
#ifdef WITH_VERBOSE_MODE
void
meta_debug_spew_real (const char *format, ...)
diff --git a/src/util.h b/src/util.h
index d88c7752..161ae938 100644
--- a/src/util.h
+++ b/src/util.h
@@ -95,6 +95,8 @@ const char* meta_gravity_to_string (int gravity);
char* meta_g_utf8_strndup (const gchar *src, gsize n);
+void meta_free_gslist_and_elements (GSList *list_to_deep_free);
+
/* To disable verbose mode, we make these functions into no-ops */
#ifdef WITH_VERBOSE_MODE
diff --git a/src/window.c b/src/window.c
index 0f2ac236..2f94a998 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5675,86 +5675,74 @@ invalidate_work_areas (MetaWindow *window)
void
meta_window_update_struts (MetaWindow *window)
{
+ GSList *old_struts;
+ GSList *new_struts;
+ GSList *old_iter, *new_iter;
gulong *struts = NULL;
int nitems;
- gboolean old_has_struts;
- gboolean new_has_struts;
-
- MetaRectangle old_left;
- MetaRectangle old_right;
- MetaRectangle old_top;
- MetaRectangle old_bottom;
-
- MetaRectangle new_left;
- MetaRectangle new_right;
- MetaRectangle new_top;
- MetaRectangle new_bottom;
+ gboolean changed;
meta_verbose ("Updating struts for %s\n", window->desc);
-
- if (window->struts)
- {
- old_has_struts = TRUE;
- old_left = window->struts->left;
- old_right = window->struts->right;
- old_top = window->struts->top;
- old_bottom = window->struts->bottom;
- }
- else
- {
- old_has_struts = FALSE;
- }
-
- new_has_struts = FALSE;
- new_left = window->screen->rect;
- new_left.width = 0;
- new_right = window->screen->rect;
- new_right.width = 0;
- new_right.x = window->screen->rect.width;
+ old_struts = window->struts;
+ new_struts = NULL;
- new_top = window->screen->rect;
- new_top.height = 0;
-
- new_bottom = window->screen->rect;
- new_bottom.height = 0;
- new_bottom.y = window->screen->rect.height;
-
if (meta_prop_get_cardinal_list (window->display,
window->xwindow,
window->display->atom_net_wm_strut_partial,
&struts, &nitems))
{
if (nitems != 12)
- {
- meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead of 12\n",
- window->desc, nitems);
- }
+ meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead "
+ "of 12\n",
+ window->desc, nitems);
else
{
- new_has_struts = TRUE;
- new_left.width = (int) struts[0];
- new_right.width = (int) struts[1];
- new_top.height = (int)struts[2];
- new_bottom.height = (int)struts[3];
- new_right.x = window->screen->rect.width - new_right.width;
- new_bottom.y = window->screen->rect.height - new_bottom.height;
- new_left.y = struts[4];
- new_left.height = struts[5] - new_left.y + 1;
- new_right.y = struts[6];
- new_right.height = struts[7] - new_right.y + 1;
- new_top.x = struts[8];
- new_top.width = struts[9] - new_top.x + 1;
- new_bottom.x = struts[10];
- new_bottom.width = struts[11] - new_bottom.x + 1;
-
- meta_verbose ("_NET_WM_STRUT_PARTIAL struts %d %d %d %d for window %s\n",
- new_left.width,
- new_right.width,
- new_top.height,
- new_bottom.height,
+ /* Pull out the strut info for each side in the hint */
+ int i;
+ for (i=0; i<4; i++)
+ {
+ MetaStrut *temp;
+ int thickness, strut_begin, strut_end;
+
+ thickness = struts[i];
+ if (thickness == 0)
+ continue;
+ strut_begin = struts[4+(i*2)];
+ strut_end = struts[4+(i*2)+1];
+
+ temp = g_new (MetaStrut, 1);
+ temp->side = 1 << i; // See MetaDirection def. Matches nicely, eh?
+ temp->rect = window->screen->rect;
+ switch (temp->side)
+ {
+ case META_SIDE_RIGHT:
+ temp->rect.x = BOX_RIGHT(temp->rect) - thickness;
+ /* Intentionally fall through without breaking */
+ case META_SIDE_LEFT:
+ temp->rect.width = thickness;
+ temp->rect.y = strut_begin;
+ temp->rect.height = strut_end - strut_begin + 1;
+ break;
+ case META_SIDE_BOTTOM:
+ temp->rect.y = BOX_BOTTOM(temp->rect) - thickness;
+ /* Intentionally fall through without breaking */
+ case META_SIDE_TOP:
+ temp->rect.height = thickness;
+ temp->rect.x = strut_begin;
+ temp->rect.width = strut_end - strut_begin + 1;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ new_struts = g_slist_prepend (new_struts, temp);
+ }
+
+ meta_verbose ("_NET_WM_STRUT_PARTIAL struts %lu %lu %lu %lu for "
+ "window %s\n",
+ struts[0], struts[1], struts[2], struts[3],
window->desc);
-
}
meta_XFree (struts);
}
@@ -5764,67 +5752,86 @@ meta_window_update_struts (MetaWindow *window)
window->desc);
}
- if (!new_has_struts)
+ if (!new_struts &&
+ meta_prop_get_cardinal_list (window->display,
+ window->xwindow,
+ window->display->atom_net_wm_strut,
+ &struts, &nitems))
{
- if (meta_prop_get_cardinal_list (window->display,
- window->xwindow,
- window->display->atom_net_wm_strut,
- &struts, &nitems))
+ if (nitems != 4)
+ meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
+ window->desc, nitems);
+ else
{
- if (nitems != 4)
+ /* Pull out the strut info for each side in the hint */
+ int i;
+ for (i=0; i<4; i++)
{
- meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
- window->desc, nitems);
+ MetaStrut *temp;
+ int thickness;
+
+ thickness = struts[i];
+ if (thickness == 0)
+ continue;
+
+ temp = g_new (MetaStrut, 1);
+ temp->side = 1 << i;
+ temp->rect = window->screen->rect;
+ switch (temp->side)
+ {
+ case META_SIDE_RIGHT:
+ temp->rect.x = BOX_RIGHT(temp->rect) - thickness;
+ /* Intentionally fall through without breaking */
+ case META_SIDE_LEFT:
+ temp->rect.width = thickness;
+ break;
+ case META_SIDE_BOTTOM:
+ temp->rect.y = BOX_BOTTOM(temp->rect) - thickness;
+ /* Intentionally fall through without breaking */
+ case META_SIDE_TOP:
+ temp->rect.height = thickness;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ new_struts = g_slist_prepend (new_struts, temp);
}
- else
- {
- new_has_struts = TRUE;
- new_left.width = (int) struts[0];
- new_right.width = (int) struts[1];
- new_top.height = (int)struts[2];
- new_bottom.height = (int)struts[3];
- new_right.x = window->screen->rect.width - new_right.width;
- new_bottom.y = window->screen->rect.height - new_bottom.height;
-
- meta_verbose ("_NET_WM_STRUT struts %d %d %d %d for window %s\n",
- new_left.width,
- new_right.width,
- new_top.height,
- new_bottom.height,
- window->desc);
- }
- meta_XFree (struts);
- }
- else
- {
- meta_verbose ("No _NET_WM_STRUT property for %s\n",
+ meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n",
+ struts[0], struts[1], struts[2], struts[3],
window->desc);
}
+ meta_XFree (struts);
+ }
+ else if (!new_struts)
+ {
+ meta_verbose ("No _NET_WM_STRUT property for %s\n",
+ window->desc);
}
- if (old_has_struts != new_has_struts ||
- (new_has_struts && old_has_struts &&
- (!meta_rectangle_equal(&old_left, &new_left) ||
- !meta_rectangle_equal(&old_right, &new_right) ||
- !meta_rectangle_equal(&old_top, &new_top) ||
- !meta_rectangle_equal(&old_bottom, &new_bottom))))
- {
- if (new_has_struts)
- {
- if (!window->struts)
- window->struts = g_new (MetaStruts, 1);
-
- window->struts->left = new_left;
- window->struts->right = new_right;
- window->struts->top = new_top;
- window->struts->bottom = new_bottom;
- }
- else
- {
- g_free (window->struts);
- window->struts = NULL;
- }
+ /* Determine whether old_struts and new_struts are the same */
+ old_iter = old_struts;
+ new_iter = new_struts;
+ while (old_iter && new_iter)
+ {
+ MetaStrut *old_strut = (MetaStrut*) old_iter->data;
+ MetaStrut *new_strut = (MetaStrut*) new_iter->data;
+
+ if (old_strut->side != new_strut->side ||
+ !meta_rectangle_equal (&old_strut->rect, &new_strut->rect))
+ break;
+
+ old_iter = old_iter->next;
+ new_iter = new_iter->next;
+ }
+ changed = (old_iter != NULL || new_iter != NULL);
+
+ /* Update appropriately */
+ meta_free_gslist_and_elements (old_struts);
+ window->struts = new_struts;
+ if (changed)
+ {
meta_topic (META_DEBUG_WORKAREA,
"Invalidating work areas of window %s due to struts update\n",
window->desc);
diff --git a/src/window.h b/src/window.h
index 0dac50d2..2fb271bb 100644
--- a/src/window.h
+++ b/src/window.h
@@ -36,7 +36,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct _MetaGroup MetaGroup;
-typedef struct _MetaStruts MetaStruts;
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
void *data);
@@ -67,15 +66,6 @@ typedef enum {
META_CLIENT_TYPE_MAX_RECOGNIZED = 2
} MetaClientType;
-struct _MetaStruts
-{
- /* struts */
- MetaRectangle left;
- MetaRectangle right;
- MetaRectangle top;
- MetaRectangle bottom;
-};
-
struct _MetaWindow
{
MetaDisplay *display;
@@ -276,7 +266,7 @@ struct _MetaWindow
guint calc_placement : 1;
/* Note: can be NULL */
- MetaStruts *struts;
+ GSList *struts;
/* Transient parent is a root window */
guint transient_parent_is_root_window : 1;
diff --git a/src/workspace.c b/src/workspace.c
index 8ea5e8eb..d11fcecd 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -493,17 +493,10 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
static void
ensure_work_areas_validated (MetaWorkspace *workspace)
{
- int left_strut = 0;
- int right_strut = 0;
- int top_strut = 0;
- int bottom_strut = 0;
- int all_left_strut = 0;
- int all_right_strut = 0;
- int all_top_strut = 0;
- int all_bottom_strut = 0;
- int i;
- GList *tmp;
- GList *windows;
+ GList *windows;
+ GList *tmp;
+ MetaRectangle work_area;
+ int i; /* C89 absolutely sucks... */
if (!workspace->work_areas_invalid)
return;
@@ -513,183 +506,22 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
g_assert (workspace->screen_region == NULL);
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
-
- windows = meta_workspace_list_windows (workspace);
- g_free (workspace->work_area_xinerama);
- workspace->work_area_xinerama = g_new (MetaRectangle,
- workspace->screen->n_xinerama_infos);
-
- i = 0;
- while (i < workspace->screen->n_xinerama_infos)
+ /* STEP 1: Get the list of struts */
+ windows = meta_workspace_list_windows (workspace);
+ for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
- left_strut = 0;
- right_strut = 0;
- top_strut = 0;
- bottom_strut = 0;
-
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (w->struts)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Merging win %s with %d %d %d %d "
- "with %d %d %d %d\n",
- w->desc,
- w->struts->left.width, w->struts->right.width,
- w->struts->top.height, w->struts->bottom.height,
- left_strut, right_strut,
- top_strut, bottom_strut);
-
- if ((i == 0) && (w->struts->left.width > 0))
- {
- workspace->all_struts = g_slist_prepend (workspace->all_struts,
- &w->struts->left);
- }
-
- if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
- &w->struts->left))
- {
- left_strut = MAX (left_strut,
- w->struts->left.width -
- workspace->screen->xinerama_infos[i].rect.x);
- all_left_strut = MAX (all_left_strut, w->struts->left.width);
- }
-
- if ((i == 0) && (w->struts->right.width > 0))
- {
- workspace->all_struts = g_slist_prepend (workspace->all_struts,
- &w->struts->right);
- }
-
- if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
- &w->struts->right))
- {
- right_strut = MAX (right_strut, w->struts->right.width -
- workspace->screen->rect.width +
- workspace->screen->xinerama_infos[i].rect.width +
- workspace->screen->xinerama_infos[i].rect.x);
- all_right_strut = MAX (all_right_strut, w->struts->right.width);
- }
-
- if ((i == 0) && (w->struts->top.height > 0))
- {
- workspace->all_struts = g_slist_prepend (workspace->all_struts,
- &w->struts->top);
- }
-
- if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
- &w->struts->top))
- {
- top_strut = MAX (top_strut,
- w->struts->top.height -
- workspace->screen->xinerama_infos[i].rect.y);
- all_top_strut = MAX (all_top_strut, w->struts->top.height);
- }
-
- if ((i == 0) && (w->struts->bottom.height > 0))
- {
- workspace->all_struts = g_slist_prepend (workspace->all_struts,
- &w->struts->bottom);
- }
-
- if (meta_rectangle_overlap (&w->screen->xinerama_infos[i].rect,
- &w->struts->bottom))
- {
- bottom_strut = MAX (bottom_strut, w->struts->bottom.height -
- workspace->screen->rect.height +
- workspace->screen->xinerama_infos[i].rect.height +
- workspace->screen->xinerama_infos[i].rect.y);
- all_bottom_strut = MAX (all_bottom_strut, w->struts->bottom.height);
- }
- }
-
- tmp = tmp->next;
- }
-
- /* Some paranoid robustness */
-#define MIN_SANE_AREA 100
-
- if ((left_strut + right_strut) >
- (workspace->screen->xinerama_infos[i].rect.width - MIN_SANE_AREA))
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Making left/right struts %d %d sane xinerama %d\n",
- left_strut, right_strut, i);
- left_strut = (workspace->screen->xinerama_infos[i].rect.width -
- MIN_SANE_AREA) / 2;
- right_strut = left_strut;
- }
-
- if ((top_strut + bottom_strut) >
- (workspace->screen->xinerama_infos[i].rect.height - MIN_SANE_AREA))
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Making top/bottom struts %d %d sane xinerama %d\n",
- top_strut, bottom_strut, i);
- top_strut = (workspace->screen->xinerama_infos[i].rect.height -
- MIN_SANE_AREA) / 2;
- bottom_strut = top_strut;
- }
-
- workspace->work_area_xinerama[i].x =
- left_strut + workspace->screen->xinerama_infos[i].rect.x;
- workspace->work_area_xinerama[i].y = top_strut +
- workspace->screen->xinerama_infos[i].rect.y;
- workspace->work_area_xinerama[i].width =
- workspace->screen->xinerama_infos[i].rect.width -
- left_strut - right_strut;
- workspace->work_area_xinerama[i].height =
- workspace->screen->xinerama_infos[i].rect.height -
- top_strut - bottom_strut;
+ MetaWindow *win = tmp->data;
+ GSList *s_iter;
- meta_topic (META_DEBUG_WORKAREA,
- "Computed work area for workspace %d "
- "xinerama %d: %d,%d %d x %d\n",
- meta_workspace_index (workspace),
- i,
- workspace->work_area_xinerama[i].x,
- workspace->work_area_xinerama[i].y,
- workspace->work_area_xinerama[i].width,
- workspace->work_area_xinerama[i].height);
-
- ++i;
+ for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next)
+ workspace->all_struts = g_slist_prepend (workspace->all_struts,
+ s_iter->data);
}
-
g_list_free (windows);
- if ((all_left_strut + all_right_strut) >
- (workspace->screen->rect.width - MIN_SANE_AREA))
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Making screen-wide left/right struts %d %d sane\n",
- all_left_strut, all_right_strut);
- all_left_strut = (workspace->screen->rect.width - MIN_SANE_AREA) / 2;
- all_right_strut = all_left_strut;
- }
-
- if ((all_top_strut + all_bottom_strut) >
- (workspace->screen->rect.height - MIN_SANE_AREA))
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Making top/bottom struts %d %d sane\n",
- all_top_strut, all_bottom_strut);
- all_top_strut = (workspace->screen->rect.height - MIN_SANE_AREA) / 2;
- all_bottom_strut = all_top_strut;
- }
-
- workspace->work_area_screen.x = all_left_strut;
- workspace->work_area_screen.y = all_top_strut;
- workspace->work_area_screen.width =
- workspace->screen->rect.width - all_left_strut - all_right_strut;
- workspace->work_area_screen.height =
- workspace->screen->rect.height - all_top_strut - all_bottom_strut;
-
- /* Now cache the spanning rects for the onscreen and
- * on-single-xinerama regions
+ /* STEP 2: Get the maximal/spanning rects for the onscreen and
+ * on-single-xinerama regions
*/
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->screen_region == NULL);
@@ -707,13 +539,97 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->rect,
workspace->all_struts);
- /* Since get_minimal_spanning_set_for_region() doesn't do the
- * MIN_SANE_AREA thing, manually account for it. Note that it's okay if
- * get_minimal_spanning_set_for_region() returns a very small region--all
- * we really need here is a 1x1 region that corresponds to somewhere on
- * the monitor for the partially onscreen constraint. If we don't get
- * anything, though, we use work_area_screen just for convenience.
+
+ /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
+ * xineramas.
*/
+ work_area = workspace->screen->rect; /* start with the screen */
+ if (workspace->screen_region == NULL)
+ work_area = meta_rect (0, 0, -1, -1);
+ else
+ meta_rectangle_clip_to_region (workspace->screen_region,
+ FIXED_DIRECTION_NONE,
+ &work_area);
+
+ /* Lots of paranoia checks, forcing work_area_screen to be sane */
+#define MIN_SANE_AREA 100
+ if (work_area.width < MIN_SANE_AREA)
+ {
+ meta_warning ("struts occupy an unusually large percentage of the screen; "
+ "available remaining width = %d < %d",
+ work_area.width, MIN_SANE_AREA);
+ if (work_area.width < 1)
+ {
+ work_area.x = (workspace->screen->rect.width - MIN_SANE_AREA)/2;
+ work_area.width = MIN_SANE_AREA;
+ }
+ else
+ {
+ int amount = (MIN_SANE_AREA - work_area.width)/2;
+ work_area.x -= amount;
+ work_area.width += 2*amount;
+ }
+ }
+ if (work_area.height < MIN_SANE_AREA)
+ {
+ meta_warning ("struts occupy an unusually large percentage of the screen; "
+ "available remaining height = %d < %d",
+ work_area.height, MIN_SANE_AREA);
+ if (work_area.height < 1)
+ {
+ work_area.y = (workspace->screen->rect.height - MIN_SANE_AREA)/2;
+ work_area.height = MIN_SANE_AREA;
+ }
+ else
+ {
+ int amount = (MIN_SANE_AREA - work_area.height)/2;
+ work_area.y -= amount;
+ work_area.height += 2*amount;
+ }
+ }
+ workspace->work_area_screen = work_area;
+ meta_topic (META_DEBUG_WORKAREA,
+ "Computed work area for workspace %d: %d,%d %d x %d\n",
+ meta_workspace_index (workspace),
+ workspace->work_area_screen.x,
+ workspace->work_area_screen.y,
+ workspace->work_area_screen.width,
+ workspace->work_area_screen.height);
+
+ /* Now find the work areas for each xinerama */
+ g_free (workspace->work_area_xinerama);
+ workspace->work_area_xinerama = g_new (MetaRectangle,
+ workspace->screen->n_xinerama_infos);
+
+ for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
+ {
+ work_area = workspace->screen->xinerama_infos[i].rect;
+
+ if (workspace->xinerama_region[i] == NULL)
+ /* FIXME: constraints.c untested with this, but it might be nice for
+ * a screen reader or magnifier.
+ */
+ work_area = meta_rect (work_area.x, work_area.y, -1, -1);
+ else
+ meta_rectangle_clip_to_region (workspace->xinerama_region[i],
+ FIXED_DIRECTION_NONE,
+ &work_area);
+
+ workspace->work_area_xinerama[i] = work_area;
+ meta_topic (META_DEBUG_WORKAREA,
+ "Computed work area for workspace %d "
+ "xinerama %d: %d,%d %d x %d\n",
+ meta_workspace_index (workspace),
+ i,
+ workspace->work_area_xinerama[i].x,
+ workspace->work_area_xinerama[i].y,
+ workspace->work_area_xinerama[i].width,
+ workspace->work_area_xinerama[i].height);
+ }
+
+ /* STEP 4: Make sure the screen_region is nonempty (separate from step 2
+ * since it relies on step 3).
+ */
if (workspace->screen_region == NULL)
{
MetaRectangle *nonempty_region;
@@ -722,7 +638,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
}
- /* Now cache the screen and xinerama edges for edge resistance and snapping */
+ /* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
workspace->screen_edges =
@@ -736,17 +652,8 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->all_struts);
g_list_free (tmp);
-
/* We're all done, YAAY! Record that everything has been validated. */
workspace->work_areas_invalid = FALSE;
-
- meta_topic (META_DEBUG_WORKAREA,
- "Computed work area for workspace %d: %d,%d %d x %d\n",
- meta_workspace_index (workspace),
- workspace->work_area_screen.x,
- workspace->work_area_screen.y,
- workspace->work_area_screen.width,
- workspace->work_area_screen.height);
}
void