make fullscreen windows more xinerama and multi-screen aware
instead of calling it every time a window loses focus, it is only called when a window gains focus. then, check fullscreen layered windows, if they should be moved to a lower layer. when moving a window between monitors, also check its layer and that of any fullscreen windows. let a window stay in the fullscreen layer even when it is not focused, if it is on a non-visible desktop, or if it is on a different monitor from the focused window, or if nothing else is focused
This commit is contained in:
parent
3b0f41dc66
commit
b1d4bbdb54
3 changed files with 61 additions and 11 deletions
|
@ -2471,7 +2471,15 @@ static ObStackingLayer calc_layer(ObClient *self)
|
|||
(self->decorations == 0 &&
|
||||
!(self->max_horz && self->max_vert) &&
|
||||
RECT_EQUAL(self->area, *monitor))) &&
|
||||
(client_focused(self) || client_search_focus_tree(self)))
|
||||
/* you are fullscreen while you or your children are focused.. */
|
||||
(client_focused(self) || client_search_focus_tree(self) ||
|
||||
/* you can be fullscreen if you're on another desktop */
|
||||
(self->desktop != screen_desktop &&
|
||||
self->desktop != DESKTOP_ALL) ||
|
||||
/* and you can also be fullscreen if the focused client is on
|
||||
another monitor, or nothing else is focused */
|
||||
(!focus_client ||
|
||||
client_monitor(focus_client) != client_monitor(self))))
|
||||
l = OB_STACKING_LAYER_FULLSCREEN;
|
||||
else if (self->above) l = OB_STACKING_LAYER_ABOVE;
|
||||
else if (self->below) l = OB_STACKING_LAYER_BELOW;
|
||||
|
@ -2497,23 +2505,54 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
|
|||
stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
|
||||
}
|
||||
|
||||
/* we've been restacked */
|
||||
self->visited = TRUE;
|
||||
|
||||
for (it = self->transients; it; it = g_slist_next(it))
|
||||
client_calc_layer_recursive(it->data, orig,
|
||||
self->layer);
|
||||
}
|
||||
|
||||
void client_calc_layer(ObClient *self)
|
||||
static void client_calc_layer_internal(ObClient *self)
|
||||
{
|
||||
ObClient *orig;
|
||||
GSList *it;
|
||||
|
||||
orig = self;
|
||||
GSList *sit;
|
||||
|
||||
/* transients take on the layer of their parents */
|
||||
it = client_search_all_top_parents(self);
|
||||
sit = client_search_all_top_parents(self);
|
||||
|
||||
for (; it; it = g_slist_next(it))
|
||||
client_calc_layer_recursive(it->data, orig, 0);
|
||||
for (; sit; sit = g_slist_next(sit))
|
||||
client_calc_layer_recursive(sit->data, self, 0);
|
||||
}
|
||||
|
||||
void client_calc_layer(ObClient *self)
|
||||
{
|
||||
GList *it;
|
||||
|
||||
/* skip over stuff above fullscreen layer */
|
||||
for (it = stacking_list; it; it = g_list_next(it))
|
||||
if (window_layer(it->data) <= OB_STACKING_LAYER_FULLSCREEN) break;
|
||||
|
||||
/* find the windows in the fullscreen layer, and mark them not-visited */
|
||||
for (; it; it = g_list_next(it)) {
|
||||
if (window_layer(it->data) < OB_STACKING_LAYER_FULLSCREEN) break;
|
||||
else if (WINDOW_IS_CLIENT(it->data))
|
||||
WINDOW_AS_CLIENT(it->data)->visited = FALSE;
|
||||
}
|
||||
|
||||
client_calc_layer_internal(self);
|
||||
|
||||
/* skip over stuff above fullscreen layer */
|
||||
for (it = stacking_list; it; it = g_list_next(it))
|
||||
if (window_layer(it->data) <= OB_STACKING_LAYER_FULLSCREEN) break;
|
||||
|
||||
/* now recalc any windows in the fullscreen layer which have not
|
||||
had their layer recalced already */
|
||||
for (; it; it = g_list_next(it)) {
|
||||
if (window_layer(it->data) < OB_STACKING_LAYER_FULLSCREEN) break;
|
||||
else if (WINDOW_IS_CLIENT(it->data) &&
|
||||
!WINDOW_AS_CLIENT(it->data)->visited)
|
||||
client_calc_layer_internal(it->data);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean client_should_show(ObClient *self)
|
||||
|
@ -2931,6 +2970,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
|
|||
void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
|
||||
gboolean user, gboolean final, gboolean force_reply)
|
||||
{
|
||||
Rect oldframe;
|
||||
gint oldw, oldh;
|
||||
gboolean send_resize_client;
|
||||
gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
|
||||
|
@ -2953,6 +2993,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
|
|||
|
||||
oldw = self->area.width;
|
||||
oldh = self->area.height;
|
||||
oldframe = self->frame->area;
|
||||
RECT_SET(self->area, x, y, w, h);
|
||||
|
||||
/* for app-requested resizes, always resize if 'resized' is true.
|
||||
|
@ -3057,6 +3098,14 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
|
|||
}
|
||||
|
||||
XFlush(ob_display);
|
||||
|
||||
/* if it moved between monitors, then this can affect the stacking
|
||||
layer of this window or others - for fullscreen windows */
|
||||
if (screen_find_monitor(&self->frame->area) !=
|
||||
screen_find_monitor(&oldframe))
|
||||
{
|
||||
client_calc_layer(self);
|
||||
}
|
||||
}
|
||||
|
||||
void client_fullscreen(ObClient *self, gboolean fs)
|
||||
|
|
|
@ -304,6 +304,9 @@ struct _ObClient
|
|||
|
||||
/*! Where the window should iconify to/from */
|
||||
Rect icon_geometry;
|
||||
|
||||
/*! A boolean used for algorithms which need to mark clients as visited */
|
||||
gboolean visited;
|
||||
};
|
||||
|
||||
extern GList *client_list;
|
||||
|
|
|
@ -519,7 +519,6 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
window with RevertToParent focus */
|
||||
frame_adjust_focus(client->frame, FALSE);
|
||||
/* focus_set_client(NULL) has already been called */
|
||||
client_calc_layer(client);
|
||||
}
|
||||
else if (e->xfocus.detail == NotifyPointerRoot ||
|
||||
e->xfocus.detail == NotifyDetailNone ||
|
||||
|
@ -629,7 +628,6 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
frame_adjust_focus(client->frame, FALSE);
|
||||
/* focus_set_client(NULL) has already been called in this
|
||||
section or by focus_fallback */
|
||||
client_calc_layer(client);
|
||||
}
|
||||
}
|
||||
else if (client)
|
||||
|
|
Loading…
Reference in a new issue