summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2002-09-28 03:11:04 +0000
committerHavoc Pennington <hp@src.gnome.org>2002-09-28 03:11:04 +0000
commitefc82ee1b9b792ec8e7f8c4f9a2adc5afe0fafcd (patch)
treec6daf277af69f48242993d85dbb5e2da9de55595 /src
parent5ae85e9c070f9929ecf97b7fd561952152b4d7b6 (diff)
downloadmetacity-efc82ee1b9b792ec8e7f8c4f9a2adc5afe0fafcd.tar.gz
constrain placement to try to keep windows from going offscreen to the
2002-09-27 Havoc Pennington <hp@pobox.com> * src/place.c (constrain_placement): constrain placement to try to keep windows from going offscreen to the right/bottom * src/stack.c (compute_layer): rearrange the logic here to say that a window must always be in at least as high a layer as any of its transient parents or group members, rather than special-casing fullscreen. Also, group_member_is_fullscreen was leaking the list of group members every time, a fairly major memory leak.
Diffstat (limited to 'src')
-rw-r--r--src/place.c18
-rw-r--r--src/stack.c152
2 files changed, 128 insertions, 42 deletions
diff --git a/src/place.c b/src/place.c
index 3331409a..7c9a2a60 100644
--- a/src/place.c
+++ b/src/place.c
@@ -576,7 +576,11 @@ constrain_placement (MetaWindow *window,
*/
MetaRectangle work_area;
int nw_x, nw_y;
-
+ int offscreen_w, offscreen_h;
+ MetaRectangle outer_rect;
+
+ meta_window_get_outer_rect (window, &outer_rect);
+
/* FIXME this is bogus because we get the current xinerama
* for the window based on its position, but we haven't
* placed it yet.
@@ -591,7 +595,17 @@ constrain_placement (MetaWindow *window,
nw_y += fgeom->top_height;
}
- /* Keep window from going off left edge, though we don't have
+ /* Keep window from going off the bottom right, though we don't have
+ * this constraint once the window has been placed
+ */
+ offscreen_w = (outer_rect.x + outer_rect.width) - (work_area.x + work_area.width);
+ if (offscreen_w > 0)
+ nw_x -= offscreen_w;
+ offscreen_h = (outer_rect.y + outer_rect.height) - (work_area.y + work_area.height);
+ if (offscreen_h > 0)
+ nw_y -= offscreen_h;
+
+ /* Keep window from going off left edge, though again we don't have
* this constraint once the window has been placed.
*/
if (x < nw_x)
diff --git a/src/stack.c b/src/stack.c
index e9b4b466..aa9f0363 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -258,67 +258,130 @@ meta_stack_thaw (MetaStack *stack)
meta_stack_sync_to_server (stack);
}
-static gboolean
-group_member_is_fullscreen (MetaWindow *window)
+/* Get layer ignoring any transient or group relationships */
+static MetaStackLayer
+get_standalone_layer (MetaWindow *window)
+{
+ MetaStackLayer layer;
+
+ switch (window->type)
+ {
+ case META_WINDOW_DESKTOP:
+ layer = META_LAYER_DESKTOP;
+ break;
+
+ case META_WINDOW_DOCK:
+ /* still experimenting here */
+ layer = META_LAYER_DOCK;
+ break;
+
+ case META_WINDOW_SPLASHSCREEN:
+ layer = META_LAYER_SPLASH;
+ break;
+
+ default:
+ if (window->has_focus &&
+ meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
+ layer = META_LAYER_FOCUSED_WINDOW;
+ else if (window->fullscreen)
+ layer = META_LAYER_FULLSCREEN;
+ else
+ layer = META_LAYER_NORMAL;
+ break;
+ }
+
+ return layer;
+}
+
+static MetaStackLayer
+get_maximum_layer_of_ancestor (MetaWindow *window)
+{
+ MetaWindow *w;
+ MetaStackLayer max;
+ MetaStackLayer layer;
+
+ max = get_standalone_layer (window);
+
+ w = window;
+ while (w != NULL)
+ {
+ if (w->xtransient_for == None ||
+ w->transient_parent_is_root_window)
+ break;
+
+ w = meta_display_lookup_x_window (w->display, w->xtransient_for);
+
+ if (w == window)
+ break; /* Cute, someone thought they'd make a transient_for cycle */
+
+ /* w may be null... */
+ if (w != NULL)
+ {
+ layer = get_standalone_layer (w);
+ if (layer > max)
+ max = layer;
+ }
+ }
+
+ return max;
+}
+
+/* Note that this function can never use window->layer only
+ * get_standalone_layer, or we'd have issues.
+ */
+static MetaStackLayer
+get_maximum_layer_in_group_or_ancestor (MetaWindow *window)
{
GSList *members;
MetaGroup *group;
GSList *tmp;
- gboolean retval;
-
- if (window->fullscreen)
- return TRUE;
+ MetaStackLayer max;
+ MetaStackLayer layer;
+
+ max = META_LAYER_DESKTOP;
group = meta_window_get_group (window);
- if (group == NULL)
- return FALSE;
- retval = FALSE;
- members = meta_group_list_windows (group);
+ if (group != NULL)
+ members = meta_group_list_windows (group);
+ else
+ members = NULL;
+
tmp = members;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
- if (w->fullscreen)
- {
- retval = TRUE;
- break;
- }
-
+ layer = get_standalone_layer (w);
+ if (layer > max)
+ max = layer;
+
tmp = tmp->next;
}
- return retval;
+ g_slist_free (members);
+
+ layer = get_maximum_layer_of_ancestor (window);
+ if (layer > max)
+ max = layer;
+
+ return max;
}
static void
compute_layer (MetaWindow *window)
{
- switch (window->type)
- {
- case META_WINDOW_DESKTOP:
- window->layer = META_LAYER_DESKTOP;
- break;
+ MetaStackLayer group_max;
- case META_WINDOW_DOCK:
- /* still experimenting here */
- window->layer = META_LAYER_DOCK;
- break;
+ window->layer = get_standalone_layer (window);
+ group_max = get_maximum_layer_in_group_or_ancestor (window);
- case META_WINDOW_SPLASHSCREEN:
- window->layer = META_LAYER_SPLASH;
- break;
-
- default:
- if (window->has_focus &&
- meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
- window->layer = META_LAYER_FOCUSED_WINDOW;
- else if (group_member_is_fullscreen (window))
- window->layer = META_LAYER_FULLSCREEN;
- else
- window->layer = META_LAYER_NORMAL;
- break;
+ if (group_max > window->layer)
+ {
+ meta_topic (META_DEBUG_STACK,
+ "Promoting window %s from layer %d to %d due to group or transiency\n",
+ window->desc, window->layer, group_max);
+ window->layer = group_max;
}
meta_topic (META_DEBUG_STACK, "Window %s on layer %d type = %d has_focus = %d\n",
@@ -689,6 +752,15 @@ meta_stack_sync_to_server (MetaStack *stack)
if (op->update_layer)
{
+ /* FIXME when we move > 1 window into a new layer
+ * within a single stack freeze/thaw bracket,
+ * perhaps due to moving a whole window group,
+ * the ordering of the newly-added windows in the
+ * layer is not defined. So if you raise a whole group
+ * from the normal layer to the fullscreen layer, the
+ * windows in that group may get randomly reordered.
+ */
+
compute_layer (op->window);
if (op->window->layer != old_layer)
@@ -715,7 +787,7 @@ meta_stack_sync_to_server (MetaStack *stack)
/* We assume that ordering between changing layers
* and raise/lower is irrelevant; if you raise, then
* the layer turns out to be different, you still
- * raise inside the new layer
+ * raise inside the new layer.
*/
if (op->raised)
{