summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2005-07-25 02:12:58 +0000
committerElijah Newren <newren@src.gnome.org>2005-07-25 02:12:58 +0000
commit266f78d9a80e2d6a900e24da3d81f1616339f06f (patch)
tree5b1c728c37a5b8db3a4a96e567fb6bba669179db
parentc25b8ec616e69de4357dcbc1cbef0062e77d6c40 (diff)
downloadmetacity-266f78d9a80e2d6a900e24da3d81f1616339f06f.tar.gz
try to place windows denied focus near the focus window and fix a xinerama
2005-07-24 Elijah Newren <newren@gmail.com> * src/place.c (find_most_freespace): try to place windows denied focus near the focus window and fix a xinerama bug with the placement, (avoid_being_obscured_as_a_second_modal_dialog): avoid modal dialogs being obscured in somewhat pathologically strange circumstances that Eclipse seems to be good at triggering, (meta_window_place): have dialog windows make use of avoid_being_obscured_as_a_second_modal_dialog(). Fixes one of the issues found in #307875.
-rw-r--r--ChangeLog11
-rw-r--r--src/place.c104
2 files changed, 104 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 1a7cef95..62c330cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2005-07-24 Elijah Newren <newren@gmail.com>
+ * src/place.c (find_most_freespace): try to place windows denied
+ focus near the focus window and fix a xinerama bug with the
+ placement, (avoid_being_obscured_as_a_second_modal_dialog): avoid
+ modal dialogs being obscured in somewhat pathologically strange
+ circumstances that Eclipse seems to be good at triggering,
+ (meta_window_place): have dialog windows make use of
+ avoid_being_obscured_as_a_second_modal_dialog(). Fixes one of the
+ issues found in #307875.
+
+2005-07-24 Elijah Newren <newren@gmail.com>
+
* src/window.c (meta_window_raise): raise the window as well as
its ancestor; fixes a stacking bug with an ancestor that has more
than one child window. Fixes one of the issues in #307875.
diff --git a/src/place.c b/src/place.c
index d1357fab..d042026e 100644
--- a/src/place.c
+++ b/src/place.c
@@ -245,6 +245,7 @@ find_most_freespace (MetaWindow *window,
MetaWindowDirection side;
int max_area;
int max_width, max_height, left, right, top, bottom;
+ int left_space, right_space, top_space, bottom_space;
int frame_size_left, frame_size_top;
MetaRectangle work_area;
MetaRectangle avoid;
@@ -260,10 +261,14 @@ find_most_freespace (MetaWindow *window,
/* Find the areas of choosing the various sides of the focus window */
max_width = MIN (avoid.width, outer.width);
max_height = MIN (avoid.height, outer.height);
- left = MIN (avoid.x, outer.width);
- right = MIN (work_area.width - (avoid.x + avoid.width), outer.width);
- top = MIN (avoid.y, outer.height);
- bottom = MIN (work_area.height - (avoid.y + avoid.height), outer.height);
+ left_space = avoid.x - work_area.x;
+ right_space = work_area.width - (avoid.x + avoid.width - work_area.x);
+ top_space = avoid.y - work_area.y;
+ bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y);
+ left = MIN (left_space, outer.width);
+ right = MIN (right_space, outer.width);
+ top = MIN (top_space, outer.height);
+ bottom = MIN (bottom_space, outer.height);
/* Find out which side of the focus_window can show the most of the window */
side = META_LEFT;
@@ -279,32 +284,106 @@ find_most_freespace (MetaWindow *window,
max_area = top*max_width;
}
if (bottom*max_width > max_area)
- side = META_BOTTOM;
+ {
+ side = META_BOTTOM;
+ max_area = bottom*max_width;
+ }
+
+ /* Give up if there's no where to put it (i.e. focus window is maximized) */
+ if (max_area == 0)
+ return;
- /* Place the window on the relevant side; convert coord to position of window,
- * not position of frame.
+ /* Place the window on the relevant side; if the whole window fits,
+ * make it adjacent to the focus window; if not, make sure the
+ * window doesn't go off the edge of the screen.
*/
switch (side)
{
case META_LEFT:
- *new_x = work_area.x + frame_size_left;
*new_y = avoid.y + frame_size_top;
+ if (left_space > outer.width)
+ *new_x = avoid.x - outer.width + frame_size_left;
+ else
+ *new_x = work_area.x + frame_size_left;
break;
case META_RIGHT:
- *new_x = work_area.x + work_area.width - outer.width + frame_size_left;
*new_y = avoid.y + frame_size_top;
+ if (right_space > outer.width)
+ *new_x = avoid.x + avoid.width + frame_size_left;
+ else
+ *new_x = work_area.x + work_area.width - outer.width + frame_size_left;
break;
case META_TOP:
*new_x = avoid.x + frame_size_left;
- *new_y = work_area.y + frame_size_top;
+ if (top_space > outer.height)
+ *new_y = avoid.y - outer.height + frame_size_top;
+ else
+ *new_y = work_area.y + frame_size_top;
break;
case META_BOTTOM:
*new_x = avoid.x + frame_size_left;
- *new_y = work_area.y + work_area.height - outer.height + frame_size_top;
+ if (bottom_space > outer.height)
+ *new_y = avoid.y + avoid.height + frame_size_top;
+ else
+ *new_y = work_area.y + work_area.height - outer.height + frame_size_top;
break;
}
}
+static void
+avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
+ int *x,
+ int *y)
+{
+ /* We can't center this dialog if it was denied focus and it
+ * overlaps with the focus window and this dialog is modal and this
+ * dialog is in the same app as the focus window (*phew*...please
+ * don't make me say that ten times fast). See bug 307875 comment 11
+ * and 12 for details, but basically it means this is probably a
+ * second modal dialog for some app while the focus window is the
+ * first modal dialog. We should probably make them simultaneously
+ * visible in general, but it becomes mandatory to do so due to
+ * buggy apps (e.g. those using gtk+ *sigh*) because in those cases
+ * this second modal dialog also happens to be modal to the first
+ * dialog in addition to the main window, while it has only let us
+ * know about the modal-to-the-main-window part.
+ */
+
+ MetaWindow *focus_window;
+ MetaRectangle overlap;
+
+ focus_window = window->display->focus_window;
+
+ if (window->denied_focus_and_not_transient &&
+ window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
+ meta_window_same_application (window, focus_window) &&
+ meta_rectangle_intersect (&window->rect,
+ &focus_window->rect,
+ &overlap))
+ {
+ find_most_freespace (window, fgeom, focus_window, *x, *y, x, y);
+ meta_topic (META_DEBUG_PLACEMENT,
+ "Dialog window %s was denied focus but may be modal "
+ "to the focus window; had to move it to avoid the "
+ "focus window\n",
+ window->desc);
+ }
+
+ meta_topic (META_DEBUG_PLACEMENT,
+ "Status:\n"
+ " denied focus: %d\n"
+ " modal: %d\n"
+ " same app: %d\n"
+ " overlaps %d\n",
+ window->denied_focus_and_not_transient,
+ window->wm_state_modal,
+ meta_window_same_application (window, focus_window),
+ meta_rectangle_intersect (&window->rect,
+ &focus_window->rect,
+ &overlap)
+ );
+}
static int
intcmp (const void* a, const void* b)
@@ -731,6 +810,7 @@ meta_window_place (MetaWindow *window,
{
meta_topic (META_DEBUG_PLACEMENT,
"Not placing window with PPosition or USPosition set\n");
+ avoid_being_obscured_as_second_modal_dialog (window, fgeom, &x, &y);
goto done_no_constraints;
}
}
@@ -782,6 +862,8 @@ meta_window_place (MetaWindow *window,
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
window->desc);
+ avoid_being_obscured_as_second_modal_dialog (window, fgeom, &x, &y);
+
goto done;
}
}