Allow edge resistance at both sides of a window and also when edges don't

2006-01-09  Elijah Newren  <newren@gmail.com>

	Allow edge resistance at both sides of a window and also when
	edges don't overlap but are a single pixel away from doing so.
	Fixes one of the zillions of issues covered in #321905.

	* src/boxes.[ch]:
	(meta_rectangle_edges_align):
	new function to handle the overlap or off by one determining
	whether edge resistance should kick in for an edge.

	(meta_rectangle_edge_cmp_ignore_type):
	new function to sort edges but ignore the type so that e.g. left &
	right edges of windows can be used interchangeably.

	(meta_rectangle_edge_cmp):
	now uses meta_rectangle_edge_cmp_ignore_type() to do most the work
	and just adds an extra condition

	* src/edge-resistance.c:
	(find_nearest_position):
	use meta_rectangle_edges_align() now to determine whether the
	edges align,

	(apply_edge_resistance, apply_edge_resistance_to_each_side):
	have the edge resistance kick in if either the beginning or ending
	positions would cause overlap in the given direction -- fixes an
	uncommon but annoying corner case,

	(apply_edge_snapping, apply_edge_resistance_to_each_side,
	 meta_display_cleanup_edges,
	 stupid_sort_requiring_extra_pointer_dereference, cache_edges):
	mix edges from both sides now
This commit is contained in:
Elijah Newren
2006-01-10 04:33:58 +00:00
committed by Elijah Newren
parent 9eb56f151c
commit 9516694385
4 changed files with 148 additions and 87 deletions

View File

@@ -1012,6 +1012,30 @@ meta_rectangle_find_linepoint_closest_to_point (double x1,
/* */
/***************************************************************************/
gboolean
meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge)
{
/* The reason for the usage of <= below instead of < is because we are
* interested in in-the-way-or-adject'ness. So, a left (i.e. vertical
* edge) occupying y positions 0-9 (which has a y of 0 and a height of
* 10) and a rectangle with top at y=10 would be considered to "align" by
* this function.
*/
switch (edge->side_type)
{
case META_DIRECTION_LEFT:
case META_DIRECTION_RIGHT:
return BOX_TOP (*rect) <= BOX_BOTTOM (edge->rect) &&
BOX_TOP (edge->rect) <= BOX_BOTTOM (*rect);
case META_DIRECTION_TOP:
case META_DIRECTION_BOTTOM:
return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
}
g_assert_not_reached ();
}
static GList*
get_rect_minus_overlap (const GList *rect_in_list,
MetaRectangle *overlap)
@@ -1175,6 +1199,50 @@ get_disjoint_strut_list_in_region (const GSList *old_struts,
return struts;
}
gint
meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b)
{
const MetaEdge *a_edge_rect = (gconstpointer) a;
const MetaEdge *b_edge_rect = (gconstpointer) b;
/* Edges must be both vertical or both horizontal, or it doesn't make
* sense to compare them.
*/
g_assert ((a_edge_rect->rect.width == 0 && b_edge_rect->rect.width == 0) ||
(a_edge_rect->rect.height == 0 && b_edge_rect->rect.height == 0));
int a_compare, b_compare;
a_compare = b_compare = 0; /* gcc-3.4.2 sucks at figuring initialized'ness */
if (a_edge_rect->side_type == META_DIRECTION_LEFT ||
a_edge_rect->side_type == META_DIRECTION_RIGHT)
{
a_compare = a_edge_rect->rect.x;
b_compare = b_edge_rect->rect.x;
if (a_compare == b_compare)
{
a_compare = a_edge_rect->rect.y;
b_compare = b_edge_rect->rect.y;
}
}
else if (a_edge_rect->side_type == META_DIRECTION_TOP ||
a_edge_rect->side_type == META_DIRECTION_BOTTOM)
{
a_compare = a_edge_rect->rect.y;
b_compare = b_edge_rect->rect.y;
if (a_compare == b_compare)
{
a_compare = a_edge_rect->rect.x;
b_compare = b_edge_rect->rect.x;
}
}
else
g_assert ("Some idiot wanted to sort sides of different types.\n");
return a_compare - b_compare; /* positive value denotes a > b ... */
}
/* To make things easily testable, provide a nice way of sorting edges */
gint
meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b)
@@ -1188,32 +1256,7 @@ meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b)
b_compare = b_edge_rect->side_type;
if (a_compare == b_compare)
{
if (a_edge_rect->side_type == META_DIRECTION_LEFT ||
a_edge_rect->side_type == META_DIRECTION_RIGHT)
{
a_compare = a_edge_rect->rect.x;
b_compare = b_edge_rect->rect.x;
if (a_compare == b_compare)
{
a_compare = a_edge_rect->rect.y;
b_compare = b_edge_rect->rect.y;
}
}
else if (a_edge_rect->side_type == META_DIRECTION_TOP ||
a_edge_rect->side_type == META_DIRECTION_BOTTOM)
{
a_compare = a_edge_rect->rect.y;
b_compare = b_edge_rect->rect.y;
if (a_compare == b_compare)
{
a_compare = a_edge_rect->rect.x;
b_compare = b_edge_rect->rect.x;
}
}
else
g_assert ("Some idiot wanted to sort sides of different types.\n");
}
return meta_rectangle_edge_cmp_ignore_type (a, b);
return a_compare - b_compare; /* positive value denotes a > b ... */
}