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>
|
2005-02-08 Aidan Delaney <adelaney@cs.may.ie>
|
||||||
|
|
||||||
Removed useless function call. #166730
|
Removed useless function call. #166730
|
||||||
|
129
src/place.c
129
src/place.c
@ -30,6 +30,14 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_LEFT,
|
||||||
|
META_RIGHT,
|
||||||
|
META_TOP,
|
||||||
|
META_BOTTOM
|
||||||
|
} MetaWindowDirection;
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
northwestcmp (gconstpointer a, gconstpointer b)
|
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
|
static int
|
||||||
intcmp (const void* a, const void* b)
|
intcmp (const void* a, const void* b)
|
||||||
{
|
{
|
||||||
@ -774,7 +856,7 @@ meta_window_place (MetaWindow *window,
|
|||||||
if (find_first_fit (window, fgeom, windows,
|
if (find_first_fit (window, fgeom, windows,
|
||||||
xineramas_list, n_xineramas,
|
xineramas_list, n_xineramas,
|
||||||
x, y, &x, &y))
|
x, y, &x, &y))
|
||||||
goto done;
|
goto done_check_denied_focus;
|
||||||
|
|
||||||
/* This is a special-case origin-cascade so that windows that are
|
/* This is a special-case origin-cascade so that windows that are
|
||||||
* too large to fit onto a workspace (and which will be
|
* 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;
|
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:
|
done:
|
||||||
g_free (xineramas_list);
|
g_free (xineramas_list);
|
||||||
|
@ -444,6 +444,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
meta_topic (META_DEBUG_PLACEMENT,
|
meta_topic (META_DEBUG_PLACEMENT,
|
||||||
"Not placing window 0x%lx since it's already mapped\n",
|
"Not placing window 0x%lx since it's already mapped\n",
|
||||||
xwindow);
|
xwindow);
|
||||||
|
window->denied_focus_and_not_transient = FALSE;
|
||||||
window->unmanaging = FALSE;
|
window->unmanaging = FALSE;
|
||||||
window->calc_showing_queued = FALSE;
|
window->calc_showing_queued = FALSE;
|
||||||
window->move_resize_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);
|
meta_window_stack_just_below (window, window->display->focus_window);
|
||||||
ensure_mru_position_after (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;
|
window->placed = TRUE;
|
||||||
did_placement = 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 */
|
/* Shaded means the frame is mapped but the window is not */
|
||||||
|
@ -207,6 +207,9 @@ struct _MetaWindow
|
|||||||
/* Have we placed this window? */
|
/* Have we placed this window? */
|
||||||
guint placed : 1;
|
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? */
|
/* Has this window not ever been shown yet? */
|
||||||
guint showing_for_first_time : 1;
|
guint showing_for_first_time : 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user