mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
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
This commit is contained in:
parent
e82ce26425
commit
08f51fdf94
58
ChangeLog
58
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>
|
2007-04-01 Bruno Boaventura <brunobol@gnome.org>
|
||||||
|
|
||||||
* src/theme.c (kill_window_question): Fallback to NORMAL state after
|
* src/theme.c (kill_window_question): Fallback to NORMAL state after
|
||||||
|
166
src/boxes.c
166
src/boxes.c
@ -547,10 +547,10 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
|||||||
ret = g_list_prepend (NULL, temp_rect);
|
ret = g_list_prepend (NULL, temp_rect);
|
||||||
|
|
||||||
strut_iter = all_struts;
|
strut_iter = all_struts;
|
||||||
while (strut_iter)
|
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
|
||||||
{
|
{
|
||||||
GList *rect_iter;
|
GList *rect_iter;
|
||||||
MetaRectangle *strut = (MetaRectangle*) strut_iter->data;
|
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
|
||||||
|
|
||||||
tmp_list = ret;
|
tmp_list = ret;
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
@ -558,45 +558,45 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
|||||||
while (rect_iter)
|
while (rect_iter)
|
||||||
{
|
{
|
||||||
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
|
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);
|
ret = g_list_prepend (ret, rect);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If there is area in rect left of strut */
|
/* 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 = g_new (MetaRectangle, 1);
|
||||||
*temp_rect = *rect;
|
*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);
|
ret = g_list_prepend (ret, temp_rect);
|
||||||
}
|
}
|
||||||
/* If there is area in rect right of strut */
|
/* 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;
|
int new_x;
|
||||||
temp_rect = g_new (MetaRectangle, 1);
|
temp_rect = g_new (MetaRectangle, 1);
|
||||||
*temp_rect = *rect;
|
*temp_rect = *rect;
|
||||||
new_x = strut->x + strut->width;
|
new_x = BOX_RIGHT (*strut_rect);
|
||||||
temp_rect->width = rect->x + rect->width - new_x;
|
temp_rect->width = BOX_RIGHT(*rect) - new_x;
|
||||||
temp_rect->x = new_x;
|
temp_rect->x = new_x;
|
||||||
ret = g_list_prepend (ret, temp_rect);
|
ret = g_list_prepend (ret, temp_rect);
|
||||||
}
|
}
|
||||||
/* If there is area in rect above strut */
|
/* 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 = g_new (MetaRectangle, 1);
|
||||||
*temp_rect = *rect;
|
*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);
|
ret = g_list_prepend (ret, temp_rect);
|
||||||
}
|
}
|
||||||
/* If there is area in rect below strut */
|
/* 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;
|
int new_y;
|
||||||
temp_rect = g_new (MetaRectangle, 1);
|
temp_rect = g_new (MetaRectangle, 1);
|
||||||
*temp_rect = *rect;
|
*temp_rect = *rect;
|
||||||
new_y = strut->y + strut->height;
|
new_y = BOX_BOTTOM (*strut_rect);
|
||||||
temp_rect->height = rect->y + rect->height - new_y;
|
temp_rect->height = BOX_BOTTOM (*rect) - new_y;
|
||||||
temp_rect->y = new_y;
|
temp_rect->y = new_y;
|
||||||
ret = g_list_prepend (ret, temp_rect);
|
ret = g_list_prepend (ret, temp_rect);
|
||||||
}
|
}
|
||||||
@ -605,7 +605,6 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
|||||||
rect_iter = rect_iter->next;
|
rect_iter = rect_iter->next;
|
||||||
}
|
}
|
||||||
g_list_free (tmp_list);
|
g_list_free (tmp_list);
|
||||||
strut_iter = strut_iter->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sort by maximal area, just because I feel like it... */
|
/* Sort by maximal area, just because I feel like it... */
|
||||||
@ -662,6 +661,76 @@ meta_rectangle_expand_region_conditionally (GList *region,
|
|||||||
return region;
|
return 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
|
void
|
||||||
meta_rectangle_free_list_and_elements (GList *filled_list)
|
meta_rectangle_free_list_and_elements (GList *filled_list)
|
||||||
{
|
{
|
||||||
@ -1075,9 +1144,9 @@ meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge)
|
|||||||
case META_DIRECTION_BOTTOM:
|
case META_DIRECTION_BOTTOM:
|
||||||
return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
|
return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
|
||||||
BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
|
BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList*
|
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
|
/* 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
|
* 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
|
* that aren't disjoint in a way that the overlapping part is only included
|
||||||
* once, so it's not really magic...).
|
* once, so it's not really magic...).
|
||||||
*/
|
*/
|
||||||
static GList*
|
static GList*
|
||||||
get_disjoint_strut_list_in_region (const GSList *old_struts,
|
get_disjoint_strut_rect_list_in_region (const GSList *old_struts,
|
||||||
const MetaRectangle *region)
|
const MetaRectangle *region)
|
||||||
{
|
{
|
||||||
GList *struts;
|
GList *strut_rects;
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
|
|
||||||
/* First, copy the list */
|
/* First, copy the list */
|
||||||
struts = NULL;
|
strut_rects = NULL;
|
||||||
while (old_struts)
|
while (old_struts)
|
||||||
{
|
{
|
||||||
MetaRectangle *cur = old_struts->data;
|
MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect;
|
||||||
MetaRectangle *copy = g_new (MetaRectangle, 1);
|
MetaRectangle *copy = g_new (MetaRectangle, 1);
|
||||||
*copy = *cur;
|
*copy = *cur;
|
||||||
if (meta_rectangle_intersect (copy, region, copy))
|
if (meta_rectangle_intersect (copy, region, copy))
|
||||||
struts = g_list_prepend (struts, copy);
|
strut_rects = g_list_prepend (strut_rects, copy);
|
||||||
else
|
else
|
||||||
g_free (copy);
|
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
|
/* Now, loop over the list and check for intersections, fixing things up
|
||||||
* where they do intersect.
|
* where they do intersect.
|
||||||
*/
|
*/
|
||||||
tmp = struts;
|
tmp = strut_rects;
|
||||||
while (tmp)
|
while (tmp)
|
||||||
{
|
{
|
||||||
GList *compare;
|
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);
|
cur_leftover = g_list_prepend (cur_leftover, overlap_allocated);
|
||||||
|
|
||||||
/* Fix up tmp, compare, and cur -- maybe struts too */
|
/* Fix up tmp, compare, and cur -- maybe struts too */
|
||||||
if (struts == tmp)
|
if (strut_rects == tmp)
|
||||||
{
|
{
|
||||||
struts = replace_rect_with_list (tmp, cur_leftover);
|
strut_rects = replace_rect_with_list (tmp, cur_leftover);
|
||||||
tmp = struts;
|
tmp = strut_rects;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmp = replace_rect_with_list (tmp, cur_leftover);
|
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;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return struts;
|
return strut_rects;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
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
|
/* Find out if the intersection is empty; have to do it this way since
|
||||||
* edges have a thickness of 0
|
* 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 && result->height == 0))
|
||||||
{
|
{
|
||||||
result->width = 0;
|
result->width = 0;
|
||||||
@ -1397,6 +1466,8 @@ rectangle_and_edge_intersection (const MetaRectangle *rect,
|
|||||||
else
|
else
|
||||||
*handle_type = 0;
|
*handle_type = 0;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return intersect;
|
return intersect;
|
||||||
@ -1503,23 +1574,25 @@ split_edge (GList *cur_list,
|
|||||||
cur_list = g_list_prepend (cur_list, temp_edge);
|
cur_list = g_list_prepend (cur_list, temp_edge);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return cur_list;
|
return cur_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split up edge and remove preliminary edges from strut_edges depending on
|
/* 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
|
static void
|
||||||
fix_up_edges (MetaRectangle *strut, MetaEdge *edge,
|
fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
|
||||||
GList **strut_edges, GList **edge_splits,
|
GList **strut_edges, GList **edge_splits,
|
||||||
gboolean *edge_needs_removal)
|
gboolean *edge_needs_removal)
|
||||||
{
|
{
|
||||||
MetaEdge overlap;
|
MetaEdge overlap;
|
||||||
int handle_type;
|
int handle_type;
|
||||||
|
|
||||||
if (!rectangle_and_edge_intersection (strut, edge, &overlap, &handle_type))
|
if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (handle_type == 0 || handle_type == 1)
|
if (handle_type == 0 || handle_type == 1)
|
||||||
@ -1628,9 +1701,9 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
|||||||
const GSList *all_struts)
|
const GSList *all_struts)
|
||||||
{
|
{
|
||||||
GList *ret;
|
GList *ret;
|
||||||
GList *fixed_struts;
|
GList *fixed_strut_rects;
|
||||||
GList *edge_iter;
|
GList *edge_iter;
|
||||||
const GList *strut_iter;
|
const GList *strut_rect_iter;
|
||||||
|
|
||||||
/* The algorithm is basically as follows:
|
/* The algorithm is basically as follows:
|
||||||
* Make sure the struts are disjoint
|
* 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 */
|
/* 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 */
|
/* Start off the list with the edges of basic_rect */
|
||||||
ret = add_edges (NULL, basic_rect, TRUE);
|
ret = add_edges (NULL, basic_rect, TRUE);
|
||||||
|
|
||||||
strut_iter = fixed_struts;
|
strut_rect_iter = fixed_strut_rects;
|
||||||
while (strut_iter)
|
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 */
|
/* 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;
|
edge_iter = ret;
|
||||||
while (edge_iter)
|
while (edge_iter)
|
||||||
@ -1668,7 +1742,7 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
|||||||
GList *splits_of_cur_edge = NULL;
|
GList *splits_of_cur_edge = NULL;
|
||||||
gboolean edge_needs_removal = FALSE;
|
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,
|
&new_strut_edges, &splits_of_cur_edge,
|
||||||
&edge_needs_removal);
|
&edge_needs_removal);
|
||||||
|
|
||||||
@ -1692,14 +1766,14 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = g_list_concat (new_strut_edges, ret);
|
ret = g_list_concat (new_strut_edges, ret);
|
||||||
strut_iter = strut_iter->next;
|
strut_rect_iter = strut_rect_iter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sort the list */
|
/* Sort the list */
|
||||||
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
|
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
|
||||||
|
|
||||||
/* Free the fixed struts list */
|
/* Free the fixed struts list */
|
||||||
meta_rectangle_free_list_and_elements (fixed_struts);
|
meta_rectangle_free_list_and_elements (fixed_strut_rects);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1716,6 +1790,7 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
|||||||
*/
|
*/
|
||||||
GList *ret;
|
GList *ret;
|
||||||
const GList *cur;
|
const GList *cur;
|
||||||
|
GSList *temp_rects;
|
||||||
|
|
||||||
/* Initialize the return list to be empty */
|
/* Initialize the return list to be empty */
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
@ -1823,8 +1898,13 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
|||||||
cur = cur->next;
|
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,
|
ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,
|
||||||
all_struts);
|
temp_rects);
|
||||||
|
g_slist_free (temp_rects);
|
||||||
|
|
||||||
/* Sort the list */
|
/* Sort the list */
|
||||||
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
|
ret = g_list_sort (ret, meta_rectangle_edge_cmp);
|
||||||
|
23
src/boxes.h
23
src/boxes.h
@ -28,7 +28,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
typedef struct _MetaRectangle MetaRectangle;
|
typedef struct _MetaRectangle MetaRectangle;
|
||||||
|
|
||||||
struct _MetaRectangle
|
struct _MetaRectangle
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
@ -37,6 +36,13 @@ struct _MetaRectangle
|
|||||||
int height;
|
int height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _MetaStrut MetaStrut;
|
||||||
|
struct _MetaStrut
|
||||||
|
{
|
||||||
|
MetaRectangle rect;
|
||||||
|
MetaDirection side;
|
||||||
|
};
|
||||||
|
|
||||||
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
|
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
|
||||||
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
|
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
|
||||||
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
|
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
|
||||||
@ -44,8 +50,9 @@ struct _MetaRectangle
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
FIXED_DIRECTION_X = 1 << 0,
|
FIXED_DIRECTION_NONE = 0,
|
||||||
FIXED_DIRECTION_Y = 1 << 1,
|
FIXED_DIRECTION_X = 1 << 0,
|
||||||
|
FIXED_DIRECTION_Y = 1 << 1,
|
||||||
} FixedDirections;
|
} FixedDirections;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -166,6 +173,16 @@ GList* meta_rectangle_expand_region_conditionally (
|
|||||||
const int min_x,
|
const int min_x,
|
||||||
const int min_y);
|
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
|
/* Free the list created by
|
||||||
* meta_rectangle_get_minimal_spanning_set_for_region()
|
* meta_rectangle_get_minimal_spanning_set_for_region()
|
||||||
* or
|
* or
|
||||||
|
24
src/common.h
24
src/common.h
@ -216,12 +216,24 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
META_DIRECTION_LEFT = 1 << 0,
|
META_DIRECTION_LEFT = 1 << 0,
|
||||||
META_DIRECTION_RIGHT = 1 << 1,
|
META_DIRECTION_RIGHT = 1 << 1,
|
||||||
META_DIRECTION_TOP = 1 << 2,
|
META_DIRECTION_TOP = 1 << 2,
|
||||||
META_DIRECTION_BOTTOM = 1 << 3,
|
META_DIRECTION_BOTTOM = 1 << 3,
|
||||||
META_DIRECTION_UP = 1 << 2, /* Alternate name for TOP */
|
|
||||||
META_DIRECTION_DOWN = 1 << 3 /* Alternate name for BOTTOM */
|
/* 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;
|
} MetaDirection;
|
||||||
|
|
||||||
/* Function a window button can have. Note, you can't add stuff here
|
/* Function a window button can have. Note, you can't add stuff here
|
||||||
|
@ -365,7 +365,7 @@ setup_constraint_info (ConstraintInfo *info,
|
|||||||
* and (b) ignored it for aspect ratio windows -- at least in those
|
* and (b) ignored it for aspect ratio windows -- at least in those
|
||||||
* cases where both directions do actually change size.
|
* 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 x directions don't change but either y direction does */
|
||||||
if ( orig->x == new->x && orig->x + orig->width == new->x + new->width &&
|
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))
|
(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.
|
* aren't explicit user interaction, though, so just clear it out.
|
||||||
*/
|
*/
|
||||||
if (!info->is_user_action)
|
if (!info->is_user_action)
|
||||||
info->fixed_directions = 0;
|
info->fixed_directions = FIXED_DIRECTION_NONE;
|
||||||
|
|
||||||
xinerama_info =
|
xinerama_info =
|
||||||
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
|
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
|
||||||
@ -441,7 +441,7 @@ setup_constraint_info (ConstraintInfo *info,
|
|||||||
"Freakin' Invalid Stupid",
|
"Freakin' Invalid Stupid",
|
||||||
(info->is_user_action) ? "true" : "false",
|
(info->is_user_action) ? "true" : "false",
|
||||||
meta_gravity_to_string (info->resize_gravity),
|
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_X) ? "X fixed" :
|
||||||
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
|
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
|
||||||
"Freakin' Invalid Stupid",
|
"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
|
/* Since we just barely placed the window, there's no reason to
|
||||||
* consider any of the directions fixed.
|
* consider any of the directions fixed.
|
||||||
*/
|
*/
|
||||||
info->fixed_directions = 0;
|
info->fixed_directions = FIXED_DIRECTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->placed || did_placement)
|
if (window->placed || did_placement)
|
||||||
@ -691,7 +691,8 @@ constrain_maximization (MetaWindow *window,
|
|||||||
ConstraintPriority priority,
|
ConstraintPriority priority,
|
||||||
gboolean check_only)
|
gboolean check_only)
|
||||||
{
|
{
|
||||||
MetaRectangle min_size, max_size, work_area;
|
MetaRectangle target_size;
|
||||||
|
MetaRectangle min_size, max_size;
|
||||||
gboolean hminbad, vminbad;
|
gboolean hminbad, vminbad;
|
||||||
gboolean horiz_equal, vert_equal;
|
gboolean horiz_equal, vert_equal;
|
||||||
gboolean constraint_already_satisfied;
|
gboolean constraint_already_satisfied;
|
||||||
@ -703,20 +704,51 @@ constrain_maximization (MetaWindow *window,
|
|||||||
if (!window->maximized_horizontally && !window->maximized_vertically)
|
if (!window->maximized_horizontally && !window->maximized_vertically)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
work_area = info->work_area_xinerama;
|
/* Calculate target_size = maximized size of (window + frame) */
|
||||||
unextend_by_frame (&work_area, info->fgeom);
|
if (window->maximized_horizontally && window->maximized_vertically)
|
||||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
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;
|
||||||
|
|
||||||
hminbad = work_area.width < min_size.width && window->maximized_horizontally;
|
if (window->maximized_horizontally)
|
||||||
vminbad = work_area.height < min_size.height && window->maximized_vertically;
|
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 = target_size.width < min_size.width && window->maximized_horizontally;
|
||||||
|
vminbad = target_size.height < min_size.height && window->maximized_vertically;
|
||||||
if (hminbad || vminbad)
|
if (hminbad || vminbad)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Determine whether constraint is already satisfied; exit if it is */
|
/* Determine whether constraint is already satisfied; exit if it is */
|
||||||
horiz_equal = work_area.x == info->current.x &&
|
horiz_equal = target_size.x == info->current.x &&
|
||||||
work_area.width == info->current.width;
|
target_size.width == info->current.width;
|
||||||
vert_equal = work_area.y == info->current.y &&
|
vert_equal = target_size.y == info->current.y &&
|
||||||
work_area.height == info->current.height;
|
target_size.height == info->current.height;
|
||||||
constraint_already_satisfied =
|
constraint_already_satisfied =
|
||||||
(horiz_equal || !window->maximized_horizontally) &&
|
(horiz_equal || !window->maximized_horizontally) &&
|
||||||
(vert_equal || !window->maximized_vertically);
|
(vert_equal || !window->maximized_vertically);
|
||||||
@ -726,13 +758,13 @@ constrain_maximization (MetaWindow *window,
|
|||||||
/*** Enforce constraint ***/
|
/*** Enforce constraint ***/
|
||||||
if (window->maximized_horizontally)
|
if (window->maximized_horizontally)
|
||||||
{
|
{
|
||||||
info->current.x = work_area.x;
|
info->current.x = target_size.x;
|
||||||
info->current.width = work_area.width;
|
info->current.width = target_size.width;
|
||||||
}
|
}
|
||||||
if (window->maximized_vertically)
|
if (window->maximized_vertically)
|
||||||
{
|
{
|
||||||
info->current.y = work_area.y;
|
info->current.y = target_size.y;
|
||||||
info->current.height = work_area.height;
|
info->current.height = target_size.height;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -300,9 +300,9 @@ movement_towards_edge (MetaDirection side, int increment)
|
|||||||
case META_DIRECTION_RIGHT:
|
case META_DIRECTION_RIGHT:
|
||||||
case META_DIRECTION_BOTTOM:
|
case META_DIRECTION_BOTTOM:
|
||||||
return increment > 0;
|
return increment > 0;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -58,6 +58,17 @@ new_meta_rect (int x, int y, int width, int height)
|
|||||||
return temporary;
|
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*
|
static MetaEdge*
|
||||||
new_screen_edge (int x, int y, int width, int height, int side_type)
|
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*
|
static GSList*
|
||||||
get_strut_list (int which)
|
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);
|
g_assert (which >=0 && which <= 6);
|
||||||
switch (which)
|
switch (which)
|
||||||
@ -238,36 +250,36 @@ get_strut_list (int which)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 400, 1160, 1600, 40));
|
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 800, 1100, 400, 100));
|
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 300, 1150, 150, 50));
|
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 800, 1100, 400, 100));
|
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 300, 1150, 80, 50));
|
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 700, 525, 200, 150));
|
ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 800, 1200));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 800, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 800, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 800, 1200));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 800, 10, 800, 1200));
|
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 40));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
|
||||||
struts = g_slist_prepend (struts, new_meta_rect ( 0, 0, 1600, 20));
|
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return struts;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList*
|
static GList*
|
||||||
|
@ -199,6 +199,15 @@ utf8_fputs (const char *str,
|
|||||||
return retval;
|
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
|
#ifdef WITH_VERBOSE_MODE
|
||||||
void
|
void
|
||||||
meta_debug_spew_real (const char *format, ...)
|
meta_debug_spew_real (const char *format, ...)
|
||||||
|
@ -95,6 +95,8 @@ const char* meta_gravity_to_string (int gravity);
|
|||||||
|
|
||||||
char* meta_g_utf8_strndup (const gchar *src, gsize n);
|
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 */
|
/* To disable verbose mode, we make these functions into no-ops */
|
||||||
#ifdef WITH_VERBOSE_MODE
|
#ifdef WITH_VERBOSE_MODE
|
||||||
|
|
||||||
|
243
src/window.c
243
src/window.c
@ -5675,86 +5675,74 @@ invalidate_work_areas (MetaWindow *window)
|
|||||||
void
|
void
|
||||||
meta_window_update_struts (MetaWindow *window)
|
meta_window_update_struts (MetaWindow *window)
|
||||||
{
|
{
|
||||||
|
GSList *old_struts;
|
||||||
|
GSList *new_struts;
|
||||||
|
GSList *old_iter, *new_iter;
|
||||||
gulong *struts = NULL;
|
gulong *struts = NULL;
|
||||||
int nitems;
|
int nitems;
|
||||||
gboolean old_has_struts;
|
gboolean changed;
|
||||||
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;
|
|
||||||
|
|
||||||
meta_verbose ("Updating struts for %s\n", window->desc);
|
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;
|
old_struts = window->struts;
|
||||||
new_left = window->screen->rect;
|
new_struts = NULL;
|
||||||
new_left.width = 0;
|
|
||||||
|
|
||||||
new_right = window->screen->rect;
|
|
||||||
new_right.width = 0;
|
|
||||||
new_right.x = window->screen->rect.width;
|
|
||||||
|
|
||||||
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,
|
if (meta_prop_get_cardinal_list (window->display,
|
||||||
window->xwindow,
|
window->xwindow,
|
||||||
window->display->atom_net_wm_strut_partial,
|
window->display->atom_net_wm_strut_partial,
|
||||||
&struts, &nitems))
|
&struts, &nitems))
|
||||||
{
|
{
|
||||||
if (nitems != 12)
|
if (nitems != 12)
|
||||||
{
|
meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead "
|
||||||
meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead of 12\n",
|
"of 12\n",
|
||||||
window->desc, nitems);
|
window->desc, nitems);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new_has_struts = TRUE;
|
/* Pull out the strut info for each side in the hint */
|
||||||
new_left.width = (int) struts[0];
|
int i;
|
||||||
new_right.width = (int) struts[1];
|
for (i=0; i<4; i++)
|
||||||
new_top.height = (int)struts[2];
|
{
|
||||||
new_bottom.height = (int)struts[3];
|
MetaStrut *temp;
|
||||||
new_right.x = window->screen->rect.width - new_right.width;
|
int thickness, strut_begin, strut_end;
|
||||||
new_bottom.y = window->screen->rect.height - new_bottom.height;
|
|
||||||
new_left.y = struts[4];
|
thickness = struts[i];
|
||||||
new_left.height = struts[5] - new_left.y + 1;
|
if (thickness == 0)
|
||||||
new_right.y = struts[6];
|
continue;
|
||||||
new_right.height = struts[7] - new_right.y + 1;
|
strut_begin = struts[4+(i*2)];
|
||||||
new_top.x = struts[8];
|
strut_end = struts[4+(i*2)+1];
|
||||||
new_top.width = struts[9] - new_top.x + 1;
|
|
||||||
new_bottom.x = struts[10];
|
temp = g_new (MetaStrut, 1);
|
||||||
new_bottom.width = struts[11] - new_bottom.x + 1;
|
temp->side = 1 << i; // See MetaDirection def. Matches nicely, eh?
|
||||||
|
temp->rect = window->screen->rect;
|
||||||
meta_verbose ("_NET_WM_STRUT_PARTIAL struts %d %d %d %d for window %s\n",
|
switch (temp->side)
|
||||||
new_left.width,
|
{
|
||||||
new_right.width,
|
case META_SIDE_RIGHT:
|
||||||
new_top.height,
|
temp->rect.x = BOX_RIGHT(temp->rect) - thickness;
|
||||||
new_bottom.height,
|
/* 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);
|
window->desc);
|
||||||
|
|
||||||
}
|
}
|
||||||
meta_XFree (struts);
|
meta_XFree (struts);
|
||||||
}
|
}
|
||||||
@ -5764,67 +5752,86 @@ meta_window_update_struts (MetaWindow *window)
|
|||||||
window->desc);
|
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,
|
if (nitems != 4)
|
||||||
window->xwindow,
|
meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
|
||||||
window->display->atom_net_wm_strut,
|
window->desc, nitems);
|
||||||
&struts, &nitems))
|
|
||||||
{
|
|
||||||
if (nitems != 4)
|
|
||||||
{
|
|
||||||
meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\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;
|
|
||||||
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
meta_verbose ("No _NET_WM_STRUT property for %s\n",
|
/* Pull out the strut info for each side in the hint */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n",
|
||||||
|
struts[0], struts[1], struts[2], struts[3],
|
||||||
window->desc);
|
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 ||
|
/* Determine whether old_struts and new_struts are the same */
|
||||||
(new_has_struts && old_has_struts &&
|
old_iter = old_struts;
|
||||||
(!meta_rectangle_equal(&old_left, &new_left) ||
|
new_iter = new_struts;
|
||||||
!meta_rectangle_equal(&old_right, &new_right) ||
|
while (old_iter && new_iter)
|
||||||
!meta_rectangle_equal(&old_top, &new_top) ||
|
{
|
||||||
!meta_rectangle_equal(&old_bottom, &new_bottom))))
|
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)
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
|
||||||
meta_topic (META_DEBUG_WORKAREA,
|
meta_topic (META_DEBUG_WORKAREA,
|
||||||
"Invalidating work areas of window %s due to struts update\n",
|
"Invalidating work areas of window %s due to struts update\n",
|
||||||
window->desc);
|
window->desc);
|
||||||
|
12
src/window.h
12
src/window.h
@ -36,7 +36,6 @@
|
|||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
typedef struct _MetaGroup MetaGroup;
|
typedef struct _MetaGroup MetaGroup;
|
||||||
typedef struct _MetaStruts MetaStruts;
|
|
||||||
|
|
||||||
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
|
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
|
||||||
void *data);
|
void *data);
|
||||||
@ -67,15 +66,6 @@ typedef enum {
|
|||||||
META_CLIENT_TYPE_MAX_RECOGNIZED = 2
|
META_CLIENT_TYPE_MAX_RECOGNIZED = 2
|
||||||
} MetaClientType;
|
} MetaClientType;
|
||||||
|
|
||||||
struct _MetaStruts
|
|
||||||
{
|
|
||||||
/* struts */
|
|
||||||
MetaRectangle left;
|
|
||||||
MetaRectangle right;
|
|
||||||
MetaRectangle top;
|
|
||||||
MetaRectangle bottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaWindow
|
struct _MetaWindow
|
||||||
{
|
{
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
@ -276,7 +266,7 @@ struct _MetaWindow
|
|||||||
guint calc_placement : 1;
|
guint calc_placement : 1;
|
||||||
|
|
||||||
/* Note: can be NULL */
|
/* Note: can be NULL */
|
||||||
MetaStruts *struts;
|
GSList *struts;
|
||||||
|
|
||||||
/* Transient parent is a root window */
|
/* Transient parent is a root window */
|
||||||
guint transient_parent_is_root_window : 1;
|
guint transient_parent_is_root_window : 1;
|
||||||
|
303
src/workspace.c
303
src/workspace.c
@ -493,17 +493,10 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
|
|||||||
static void
|
static void
|
||||||
ensure_work_areas_validated (MetaWorkspace *workspace)
|
ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||||
{
|
{
|
||||||
int left_strut = 0;
|
GList *windows;
|
||||||
int right_strut = 0;
|
GList *tmp;
|
||||||
int top_strut = 0;
|
MetaRectangle work_area;
|
||||||
int bottom_strut = 0;
|
int i; /* C89 absolutely sucks... */
|
||||||
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;
|
|
||||||
|
|
||||||
if (!workspace->work_areas_invalid)
|
if (!workspace->work_areas_invalid)
|
||||||
return;
|
return;
|
||||||
@ -513,183 +506,22 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
|||||||
g_assert (workspace->screen_region == NULL);
|
g_assert (workspace->screen_region == NULL);
|
||||||
g_assert (workspace->screen_edges == NULL);
|
g_assert (workspace->screen_edges == NULL);
|
||||||
g_assert (workspace->xinerama_edges == NULL);
|
g_assert (workspace->xinerama_edges == NULL);
|
||||||
|
|
||||||
|
/* STEP 1: Get the list of struts */
|
||||||
windows = meta_workspace_list_windows (workspace);
|
windows = meta_workspace_list_windows (workspace);
|
||||||
|
for (tmp = windows; tmp != NULL; tmp = tmp->next)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
left_strut = 0;
|
MetaWindow *win = tmp->data;
|
||||||
right_strut = 0;
|
GSList *s_iter;
|
||||||
top_strut = 0;
|
|
||||||
bottom_strut = 0;
|
|
||||||
|
|
||||||
tmp = windows;
|
for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next)
|
||||||
while (tmp != NULL)
|
workspace->all_struts = g_slist_prepend (workspace->all_struts,
|
||||||
{
|
s_iter->data);
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_list_free (windows);
|
g_list_free (windows);
|
||||||
|
|
||||||
if ((all_left_strut + all_right_strut) >
|
/* STEP 2: Get the maximal/spanning rects for the onscreen and
|
||||||
(workspace->screen->rect.width - MIN_SANE_AREA))
|
* on-single-xinerama regions
|
||||||
{
|
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
g_assert (workspace->xinerama_region == NULL);
|
g_assert (workspace->xinerama_region == NULL);
|
||||||
g_assert (workspace->screen_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 (
|
meta_rectangle_get_minimal_spanning_set_for_region (
|
||||||
&workspace->screen->rect,
|
&workspace->screen->rect,
|
||||||
workspace->all_struts);
|
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
|
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
|
||||||
* get_minimal_spanning_set_for_region() returns a very small region--all
|
* xineramas.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
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)
|
if (workspace->screen_region == NULL)
|
||||||
{
|
{
|
||||||
MetaRectangle *nonempty_region;
|
MetaRectangle *nonempty_region;
|
||||||
@ -722,7 +638,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
|||||||
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
|
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->screen_edges == NULL);
|
||||||
g_assert (workspace->xinerama_edges == NULL);
|
g_assert (workspace->xinerama_edges == NULL);
|
||||||
workspace->screen_edges =
|
workspace->screen_edges =
|
||||||
@ -736,17 +652,8 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
|||||||
workspace->all_struts);
|
workspace->all_struts);
|
||||||
g_list_free (tmp);
|
g_list_free (tmp);
|
||||||
|
|
||||||
|
|
||||||
/* We're all done, YAAY! Record that everything has been validated. */
|
/* We're all done, YAAY! Record that everything has been validated. */
|
||||||
workspace->work_areas_invalid = FALSE;
|
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
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user