mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
Avoid new windows being obscured by the focus window (and thus possibly
2005-02-11 Elijah Newren <newren@gmail.com> Avoid new windows being obscured by the focus window (and thus possibly lost). Fixes #166524. * src/place.c: new MetaWindowDirection enum, (find_most_freespace): new function to find where there is the most space available around the focused window, (meta_window_place): if a window is denied focus and the window overlaps the focused window, retry the first-fit algorithm only paying attention to the focus window position and if that fails just find the location on the screen with the most space available. * src/window.h: (struct MetaWindow): new denied_focus_and_not_transient bitfield * src/window.c: (meta_window_new_with_attrs): initialize denied_focus_and_not_transient, (meta_window_show): set and unset the denied_focus_and_not_transient field appropriately
This commit is contained in:
parent
f8c41ca016
commit
d31a0829be
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
2005-02-11 Elijah Newren <newren@gmail.com>
|
||||
|
||||
Avoid new windows being obscured by the focus window (and thus
|
||||
possibly lost). Fixes #166524.
|
||||
|
||||
* src/place.c: new MetaWindowDirection enum,
|
||||
(find_most_freespace): new function to find where there is the
|
||||
most space available around the focused window,
|
||||
(meta_window_place): if a window is denied focus and the window
|
||||
overlaps the focused window, retry the first-fit algorithm only
|
||||
paying attention to the focus window position and if that fails
|
||||
just find the location on the screen with the most space
|
||||
available.
|
||||
|
||||
* src/window.h: (struct MetaWindow): new
|
||||
denied_focus_and_not_transient bitfield
|
||||
|
||||
* src/window.c: (meta_window_new_with_attrs): initialize
|
||||
denied_focus_and_not_transient, (meta_window_show): set and unset
|
||||
the denied_focus_and_not_transient field appropriately
|
||||
|
||||
2005-02-08 Aidan Delaney <adelaney@cs.may.ie>
|
||||
|
||||
Removed useless function call. #166730
|
||||
|
129
src/place.c
129
src/place.c
@ -30,6 +30,14 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_LEFT,
|
||||
META_RIGHT,
|
||||
META_TOP,
|
||||
META_BOTTOM
|
||||
} MetaWindowDirection;
|
||||
|
||||
static gint
|
||||
northwestcmp (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
@ -224,6 +232,80 @@ find_next_cascade (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_most_freespace (MetaWindow *window,
|
||||
MetaFrameGeometry *fgeom,
|
||||
/* visible windows on relevant workspaces */
|
||||
MetaWindow *focus_window,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
int *new_y)
|
||||
{
|
||||
MetaWindowDirection side;
|
||||
int max_area;
|
||||
int max_width, max_height, left, right, top, bottom;
|
||||
int frame_size_left, frame_size_top;
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle avoid;
|
||||
MetaRectangle outer;
|
||||
|
||||
frame_size_left = fgeom ? fgeom->left_width : 0;
|
||||
frame_size_top = fgeom ? fgeom->top_height : 0;
|
||||
|
||||
meta_window_get_work_area_current_xinerama (focus_window, &work_area);
|
||||
meta_window_get_outer_rect (focus_window, &avoid);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Find out which side of the focus_window can show the most of the window */
|
||||
side = META_LEFT;
|
||||
max_area = left*max_height;
|
||||
if (right*max_height > max_area)
|
||||
{
|
||||
side = META_RIGHT;
|
||||
max_area = right*max_height;
|
||||
}
|
||||
if (top*max_width > max_area)
|
||||
{
|
||||
side = META_TOP;
|
||||
max_area = top*max_width;
|
||||
}
|
||||
if (bottom*max_width > max_area)
|
||||
side = META_BOTTOM;
|
||||
|
||||
/* Place the window on the relevant side; convert coord to position of window,
|
||||
* not position of frame.
|
||||
*/
|
||||
switch (side)
|
||||
{
|
||||
case META_LEFT:
|
||||
*new_x = work_area.x + frame_size_left;
|
||||
*new_y = avoid.y + frame_size_top;
|
||||
break;
|
||||
case META_RIGHT:
|
||||
*new_x = work_area.x + work_area.width - outer.width + frame_size_left;
|
||||
*new_y = avoid.y + frame_size_top;
|
||||
break;
|
||||
case META_TOP:
|
||||
*new_x = avoid.x + frame_size_left;
|
||||
*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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
intcmp (const void* a, const void* b)
|
||||
{
|
||||
@ -774,7 +856,7 @@ meta_window_place (MetaWindow *window,
|
||||
if (find_first_fit (window, fgeom, windows,
|
||||
xineramas_list, n_xineramas,
|
||||
x, y, &x, &y))
|
||||
goto done;
|
||||
goto done_check_denied_focus;
|
||||
|
||||
/* This is a special-case origin-cascade so that windows that are
|
||||
* too large to fit onto a workspace (and which will be
|
||||
@ -841,6 +923,51 @@ meta_window_place (MetaWindow *window,
|
||||
window->maximize_after_placement = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
done_check_denied_focus:
|
||||
/* If the window is being denied focus and isn't a transient of the
|
||||
* focus window, we do NOT want it to overlap with the focus window
|
||||
* if at all possible. This is guaranteed to only be called if the
|
||||
* focus_window is non-NULL, and we try to avoid that window.
|
||||
*/
|
||||
if (window->denied_focus_and_not_transient)
|
||||
{
|
||||
gboolean found_fit;
|
||||
MetaWindow *focus_window;
|
||||
MetaRectangle overlap;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
g_assert (focus_window != NULL);
|
||||
|
||||
/* No need to do anything if the window doesn't overlap at all */
|
||||
found_fit = !meta_rectangle_intersect (&window->rect,
|
||||
&focus_window->rect,
|
||||
&overlap);
|
||||
|
||||
/* Try to do a first fit again, this time only taking into account the
|
||||
* focus window.
|
||||
*/
|
||||
if (!found_fit)
|
||||
{
|
||||
GList *focus_window_list;
|
||||
focus_window_list = g_list_prepend (NULL, focus_window);
|
||||
|
||||
/* Reset x and y ("origin" placement algorithm) */
|
||||
x = xi->x_origin;
|
||||
y = xi->y_origin;
|
||||
|
||||
found_fit = find_first_fit (window, fgeom, focus_window_list,
|
||||
xineramas_list, n_xineramas,
|
||||
x, y, &x, &y);
|
||||
g_list_free (focus_window_list);
|
||||
}
|
||||
|
||||
/* If that still didn't work, just place it where we can see as much
|
||||
* as possible.
|
||||
*/
|
||||
if (!found_fit)
|
||||
find_most_freespace (window, fgeom, focus_window, x, y, &x, &y);
|
||||
}
|
||||
|
||||
done:
|
||||
g_free (xineramas_list);
|
||||
|
@ -444,6 +444,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing window 0x%lx since it's already mapped\n",
|
||||
xwindow);
|
||||
window->denied_focus_and_not_transient = FALSE;
|
||||
window->unmanaging = FALSE;
|
||||
window->calc_showing_queued = FALSE;
|
||||
window->move_resize_queued = FALSE;
|
||||
@ -1678,6 +1679,8 @@ meta_window_show (MetaWindow *window)
|
||||
{
|
||||
meta_window_stack_just_below (window, window->display->focus_window);
|
||||
ensure_mru_position_after (window, window->display->focus_window);
|
||||
if (!window->placed)
|
||||
window->denied_focus_and_not_transient = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1701,6 +1704,11 @@ meta_window_show (MetaWindow *window)
|
||||
*/
|
||||
window->placed = TRUE;
|
||||
did_placement = TRUE;
|
||||
|
||||
/* Don't want to accidentally reuse the fact that we had been denied
|
||||
* focus in any future constraints unless we're denied focus again.
|
||||
*/
|
||||
window->denied_focus_and_not_transient = FALSE;
|
||||
}
|
||||
|
||||
/* Shaded means the frame is mapped but the window is not */
|
||||
|
@ -207,6 +207,9 @@ struct _MetaWindow
|
||||
/* Have we placed this window? */
|
||||
guint placed : 1;
|
||||
|
||||
/* Is this not a transient of the focus window which is being denied focus? */
|
||||
guint denied_focus_and_not_transient : 1;
|
||||
|
||||
/* Has this window not ever been shown yet? */
|
||||
guint showing_for_first_time : 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user