summaryrefslogtreecommitdiff
path: root/src/window-props.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window-props.c')
-rw-r--r--src/window-props.c291
1 files changed, 213 insertions, 78 deletions
diff --git a/src/window-props.c b/src/window-props.c
index ff08734..8e2d1b0 100644
--- a/src/window-props.c
+++ b/src/window-props.c
@@ -909,9 +909,14 @@ spew_size_hints_differences (const XSizeHints *old,
void
meta_set_normal_hints (MetaWindow *window,
- XSizeHints *hints)
+ XSizeHints *hints)
{
int x, y, w, h;
+ double minr, maxr;
+ /* Some convenience vars */
+ int minw, minh, maxw, maxh; /* min/max width/height */
+ int basew, baseh, winc, hinc; /* base width/height, width/height increment */
+
/* Save the last ConfigureRequest, which we put here.
* Values here set in the hints are supposed to
* be ignored.
@@ -944,12 +949,13 @@ meta_set_normal_hints (MetaWindow *window,
window->size_hints.width = w;
window->size_hints.height = h;
+ /* Get base size hints */
if (window->size_hints.flags & PBaseSize)
{
meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d\n",
- window->desc,
- window->size_hints.base_width,
- window->size_hints.base_height);
+ window->desc,
+ window->size_hints.base_width,
+ window->size_hints.base_height);
}
else if (window->size_hints.flags & PMinSize)
{
@@ -963,12 +969,13 @@ meta_set_normal_hints (MetaWindow *window,
}
window->size_hints.flags |= PBaseSize;
+ /* Get min size hints */
if (window->size_hints.flags & PMinSize)
{
meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n",
- window->desc,
- window->size_hints.min_width,
- window->size_hints.min_height);
+ window->desc,
+ window->size_hints.min_width,
+ window->size_hints.min_height);
}
else if (window->size_hints.flags & PBaseSize)
{
@@ -982,12 +989,13 @@ meta_set_normal_hints (MetaWindow *window,
}
window->size_hints.flags |= PMinSize;
+ /* Get max size hints */
if (window->size_hints.flags & PMaxSize)
{
meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n",
- window->desc,
- window->size_hints.max_width,
- window->size_hints.max_height);
+ window->desc,
+ window->size_hints.max_width,
+ window->size_hints.max_height);
}
else
{
@@ -996,121 +1004,248 @@ meta_set_normal_hints (MetaWindow *window,
window->size_hints.flags |= PMaxSize;
}
- if (window->size_hints.max_width < window->size_hints.min_width)
+ /* Get resize increment hints */
+ if (window->size_hints.flags & PResizeInc)
{
- /* someone is on crack */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max width %d less than min width %d, disabling resize\n",
- window->desc,
- window->size_hints.max_width,
- window->size_hints.min_width);
- window->size_hints.max_width = window->size_hints.min_width;
+ "Window %s sets resize width inc: %d height inc: %d\n",
+ window->desc,
+ window->size_hints.width_inc,
+ window->size_hints.height_inc);
+ }
+ else
+ {
+ window->size_hints.width_inc = 1;
+ window->size_hints.height_inc = 1;
+ window->size_hints.flags |= PResizeInc;
}
- if (window->size_hints.max_height < window->size_hints.min_height)
+ /* Get aspect ratio hints */
+ if (window->size_hints.flags & PAspect)
{
- /* another cracksmoker */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max height %d less than min height %d, disabling resize\n",
- window->desc,
- window->size_hints.max_height,
- window->size_hints.min_height);
- window->size_hints.max_height = window->size_hints.min_height;
+ "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n",
+ window->desc,
+ window->size_hints.min_aspect.x,
+ window->size_hints.min_aspect.y,
+ window->size_hints.max_aspect.x,
+ window->size_hints.max_aspect.y);
+ }
+ else
+ {
+ window->size_hints.min_aspect.x = 1;
+ window->size_hints.min_aspect.y = G_MAXINT;
+ window->size_hints.max_aspect.x = G_MAXINT;
+ window->size_hints.max_aspect.y = 1;
+ window->size_hints.flags |= PAspect;
}
+ /* Get gravity hint */
+ if (window->size_hints.flags & PWinGravity)
+ {
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n",
+ window->desc,
+ window->size_hints.win_gravity);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s doesn't set gravity, using NW\n",
+ window->desc);
+ window->size_hints.win_gravity = NorthWestGravity;
+ window->size_hints.flags |= PWinGravity;
+ }
+
+ /*** Lots of sanity checking ***/
+
+ /* Verify all min & max hints are at least 1 pixel */
if (window->size_hints.min_width < 1)
{
- /* another cracksmoker */
+ /* someone is on crack */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets min width to 0, which makes no sense\n",
- window->desc);
+ "Window %s sets min width to 0, which makes no sense\n",
+ window->desc);
window->size_hints.min_width = 1;
}
if (window->size_hints.max_width < 1)
{
/* another cracksmoker */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max width to 0, which makes no sense\n",
- window->desc);
+ "Window %s sets max width to 0, which makes no sense\n",
+ window->desc);
window->size_hints.max_width = 1;
}
if (window->size_hints.min_height < 1)
{
/* another cracksmoker */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets min height to 0, which makes no sense\n",
- window->desc);
+ "Window %s sets min height to 0, which makes no sense\n",
+ window->desc);
window->size_hints.min_height = 1;
}
if (window->size_hints.max_height < 1)
{
/* another cracksmoker */
meta_topic (META_DEBUG_GEOMETRY,
- "Window %s sets max height to 0, which makes no sense\n",
- window->desc);
+ "Window %s sets max height to 0, which makes no sense\n",
+ window->desc);
window->size_hints.max_height = 1;
}
- if (window->size_hints.flags & PResizeInc)
+ /* Verify size increment hints are at least 1 pixel */
+ if (window->size_hints.width_inc < 1)
{
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets resize width inc: %d height inc: %d\n",
- window->desc,
- window->size_hints.width_inc,
- window->size_hints.height_inc);
- if (window->size_hints.width_inc == 0)
- {
- window->size_hints.width_inc = 1;
- meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n");
- }
- if (window->size_hints.height_inc == 0)
- {
- window->size_hints.height_inc = 1;
- meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n");
- }
+ /* app authors find so many ways to smoke crack */
+ window->size_hints.width_inc = 1;
+ meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n");
}
- else
+ if (window->size_hints.height_inc < 1)
{
- window->size_hints.width_inc = 1;
+ /* another cracksmoker */
window->size_hints.height_inc = 1;
- window->size_hints.flags |= PResizeInc;
+ meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n");
+ }
+ /* divide by 0 cracksmokers; note that x & y in (min|max)_aspect are
+ * numerator & denominator
+ */
+ if (window->size_hints.min_aspect.y < 1)
+ window->size_hints.min_aspect.y = 1;
+ if (window->size_hints.max_aspect.y < 1)
+ window->size_hints.max_aspect.y = 1;
+
+ minw = window->size_hints.min_width; minh = window->size_hints.min_height;
+ maxw = window->size_hints.max_width; maxh = window->size_hints.max_height;
+ basew = window->size_hints.base_width; baseh = window->size_hints.base_height;
+ winc = window->size_hints.width_inc; hinc = window->size_hints.height_inc;
+
+ /* Make sure min and max size hints are consistent with the base + increment
+ * size hints. If they're not, it's not a real big deal, but it means the
+ * effective min and max size are more restrictive than the application
+ * specified values.
+ */
+ if ((minw - basew) % winc != 0)
+ {
+ /* Take advantage of integer division throwing away the remainder... */
+ window->size_hints.min_width = basew + ((minw - basew)/winc + 1)*winc;
+
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s has width_inc (%d) that does not evenly divide "
+ "min_width - base_width (%d - %d); thus effective "
+ "min_width is really %d\n",
+ window->desc,
+ winc, minw, basew, window->size_hints.min_width);
+ minw = window->size_hints.min_width;
}
+ if (maxw != G_MAXINT && (maxw - basew) % winc != 0)
+ {
+ /* Take advantage of integer division throwing away the remainder... */
+ window->size_hints.max_width = basew + ((maxw - basew)/winc)*winc;
- if (window->size_hints.flags & PAspect)
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s has width_inc (%d) that does not evenly divide "
+ "max_width - base_width (%d - %d); thus effective "
+ "max_width is really %d\n",
+ window->desc,
+ winc, maxw, basew, window->size_hints.max_width);
+ maxw = window->size_hints.max_width;
+ }
+ if ((minh - baseh) % hinc != 0)
{
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n",
- window->desc,
- window->size_hints.min_aspect.x,
- window->size_hints.min_aspect.y,
- window->size_hints.max_aspect.x,
- window->size_hints.max_aspect.y);
-
- /* don't divide by 0 */
- if (window->size_hints.min_aspect.y < 1)
- window->size_hints.min_aspect.y = 1;
- if (window->size_hints.max_aspect.y < 1)
- window->size_hints.max_aspect.y = 1;
+ /* Take advantage of integer division throwing away the remainder... */
+ window->size_hints.min_height = baseh + ((minh - baseh)/hinc + 1)*hinc;
+
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s has height_inc (%d) that does not evenly divide "
+ "min_height - base_height (%d - %d); thus effective "
+ "min_height is really %d\n",
+ window->desc,
+ hinc, minh, baseh, window->size_hints.min_height);
+ minh = window->size_hints.min_height;
}
- else
+ if (maxh != G_MAXINT && (maxh - baseh) % hinc != 0)
{
+ /* Take advantage of integer division throwing away the remainder... */
+ window->size_hints.max_height = baseh + ((maxh - baseh)/hinc)*hinc;
+
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s has height_inc (%d) that does not evenly divide "
+ "max_height - base_height (%d - %d); thus effective "
+ "max_height is really %d\n",
+ window->desc,
+ hinc, maxh, baseh, window->size_hints.max_height);
+ maxh = window->size_hints.max_height;
+ }
+
+ /* make sure maximum size hints are compatible with minimum size hints; min
+ * size hints take precedence.
+ */
+ if (window->size_hints.max_width < window->size_hints.min_width)
+ {
+ /* another cracksmoker */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets max width %d less than min width %d, "
+ "disabling resize\n",
+ window->desc,
+ window->size_hints.max_width,
+ window->size_hints.min_width);
+ maxw = window->size_hints.max_width = window->size_hints.min_width;
+ }
+ if (window->size_hints.max_height < window->size_hints.min_height)
+ {
+ /* another cracksmoker */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets max height %d less than min height %d, "
+ "disabling resize\n",
+ window->desc,
+ window->size_hints.max_height,
+ window->size_hints.min_height);
+ maxh = window->size_hints.max_height = window->size_hints.min_height;
+ }
+
+ /* Make sure the aspect ratio hints are sane. */
+ minr = window->size_hints.min_aspect.x /
+ (double)window->size_hints.min_aspect.y;
+ maxr = window->size_hints.max_aspect.x /
+ (double)window->size_hints.max_aspect.y;
+ if (minr > maxr)
+ {
+ /* another cracksmoker; not even minimally (self) consistent */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets min aspect ratio larger than max aspect "
+ "ratio; disabling aspect ratio constraints.\n",
+ window->desc);
window->size_hints.min_aspect.x = 1;
window->size_hints.min_aspect.y = G_MAXINT;
window->size_hints.max_aspect.x = G_MAXINT;
window->size_hints.max_aspect.y = 1;
- window->size_hints.flags |= PAspect;
}
-
- if (window->size_hints.flags & PWinGravity)
+ else /* check consistency of aspect ratio hints with other hints */
{
- meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n",
- window->desc,
- window->size_hints.win_gravity);
- }
- else
- {
- meta_topic (META_DEBUG_GEOMETRY, "Window %s doesn't set gravity, using NW\n",
- window->desc);
- window->size_hints.win_gravity = NorthWestGravity;
- window->size_hints.flags |= PWinGravity;
+ if (minh > 0 && minr > (maxw / (double)minh))
+ {
+ /* another cracksmoker */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets min aspect ratio larger than largest "
+ "aspect ratio possible given min/max size constraints; "
+ "disabling min aspect ratio constraint.\n",
+ window->desc);
+ window->size_hints.min_aspect.x = 1;
+ window->size_hints.min_aspect.y = G_MAXINT;
+ }
+ if (maxr < (minw / (double)maxh))
+ {
+ /* another cracksmoker */
+ meta_topic (META_DEBUG_GEOMETRY,
+ "Window %s sets max aspect ratio smaller than smallest "
+ "aspect ratio possible given min/max size constraints; "
+ "disabling max aspect ratio constraint.\n",
+ window->desc);
+ window->size_hints.max_aspect.x = G_MAXINT;
+ window->size_hints.max_aspect.y = 1;
+ }
+ /* FIXME: Would be nice to check that aspect ratios are
+ * consistent with base and size increment constraints.
+ */
}
}