add anotehr stacking_add function.
make stacking_add take care of raising also. make new windows that dont get focus also not raise above the focused window.
This commit is contained in:
parent
8367ab14e8
commit
6e42b65bda
7 changed files with 112 additions and 58 deletions
|
@ -178,6 +178,7 @@ void client_manage(Window window)
|
||||||
XWindowAttributes attrib;
|
XWindowAttributes attrib;
|
||||||
XSetWindowAttributes attrib_set;
|
XSetWindowAttributes attrib_set;
|
||||||
XWMHints *wmhint;
|
XWMHints *wmhint;
|
||||||
|
gboolean activate = FALSE;
|
||||||
|
|
||||||
grab_server(TRUE);
|
grab_server(TRUE);
|
||||||
|
|
||||||
|
@ -241,30 +242,18 @@ void client_manage(Window window)
|
||||||
client_apply_startup_state(self);
|
client_apply_startup_state(self);
|
||||||
|
|
||||||
grab_server(FALSE);
|
grab_server(FALSE);
|
||||||
|
|
||||||
|
/* add to client list/map */
|
||||||
client_list = g_list_append(client_list, self);
|
client_list = g_list_append(client_list, self);
|
||||||
stacking_add(self);
|
|
||||||
g_assert(!g_hash_table_lookup(client_map, &self->window));
|
|
||||||
g_hash_table_insert(client_map, &self->window, self);
|
g_hash_table_insert(client_map, &self->window, self);
|
||||||
|
|
||||||
/* update the focus lists */
|
/* update the focus lists */
|
||||||
focus_order_add_new(self);
|
focus_order_add_new(self);
|
||||||
|
|
||||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
|
||||||
|
|
||||||
screen_update_struts();
|
|
||||||
|
|
||||||
dispatch_client(Event_Client_New, self, 0, 0);
|
|
||||||
|
|
||||||
client_showhide(self);
|
|
||||||
|
|
||||||
/* focus the new window? */
|
/* focus the new window? */
|
||||||
if (ob_state != State_Starting) {
|
if (ob_state != State_Starting && config_focus_new) {
|
||||||
Client *parent;
|
|
||||||
gboolean group_foc = FALSE;
|
gboolean group_foc = FALSE;
|
||||||
|
|
||||||
parent = NULL;
|
|
||||||
|
|
||||||
if (self->group) {
|
if (self->group) {
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
|
||||||
|
@ -274,39 +263,42 @@ void client_manage(Window window)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!group_foc && self->transient_for) {
|
/* note the check against Type_Normal/Dialog, not client_normal(self),
|
||||||
if (self->transient_for != TRAN_GROUP) {/* transient of a window */
|
which would also include other types. in this case we want more
|
||||||
parent = self->transient_for;
|
strict rules for focus */
|
||||||
} else { /* transient of a group */
|
if (((self->type == Type_Normal ||
|
||||||
GSList *it;
|
|
||||||
|
|
||||||
for (it = self->group->members; it; it = it->next)
|
|
||||||
if (it->data != self &&
|
|
||||||
((Client*)it->data)->transient_for != TRAN_GROUP)
|
|
||||||
parent = it->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* note the check against Type_Normal, not client_normal(self), which
|
|
||||||
would also include dialog types. in this case we want more strict
|
|
||||||
rules for focus */
|
|
||||||
if ((config_focus_new &&
|
|
||||||
(self->type == Type_Normal ||
|
|
||||||
(self->type == Type_Dialog &&
|
(self->type == Type_Dialog &&
|
||||||
(group_foc ||
|
(group_foc ||
|
||||||
(!parent && (!self->group ||
|
(!self->transient_for && (!self->group ||
|
||||||
!self->group->members->next)))))) ||
|
!self->group->members->next)))))) ||
|
||||||
(parent && (client_focused(parent) ||
|
client_search_focus_tree_full(self) ||
|
||||||
client_search_focus_tree(parent)))) {
|
!focus_client ||
|
||||||
client_focus(self);
|
!client_normal(focus_client)) {
|
||||||
|
/* activate the window */
|
||||||
|
stacking_add(CLIENT_AS_WINDOW(self));
|
||||||
|
activate = TRUE;
|
||||||
|
} else {
|
||||||
|
/* try to not get in the way */
|
||||||
|
stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
stacking_add(CLIENT_AS_WINDOW(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the list hints */
|
screen_update_struts();
|
||||||
client_set_list();
|
|
||||||
|
|
||||||
/* make sure the window is visible */
|
/* make sure the window is visible */
|
||||||
client_move_onscreen(self);
|
client_move_onscreen(self);
|
||||||
|
|
||||||
|
dispatch_client(Event_Client_New, self, 0, 0);
|
||||||
|
|
||||||
|
client_showhide(self);
|
||||||
|
|
||||||
|
if (activate) client_activate(self);
|
||||||
|
|
||||||
|
/* update the list hints */
|
||||||
|
client_set_list();
|
||||||
|
|
||||||
dispatch_client(Event_Client_Mapped, self, 0, 0);
|
dispatch_client(Event_Client_Mapped, self, 0, 0);
|
||||||
|
|
||||||
g_message("Managed window 0x%lx", window);
|
g_message("Managed window 0x%lx", window);
|
||||||
|
|
|
@ -200,7 +200,7 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
|
||||||
g_hash_table_insert(menu_map, &self->items, self);
|
g_hash_table_insert(menu_map, &self->items, self);
|
||||||
g_hash_table_insert(menu_hash, g_strdup(name), self);
|
g_hash_table_insert(menu_hash, g_strdup(name), self);
|
||||||
|
|
||||||
stacking_add(self);
|
stacking_add(MENU_AS_WINDOW(self));
|
||||||
stacking_raise(MENU_AS_WINDOW(self));
|
stacking_raise(MENU_AS_WINDOW(self));
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
|
@ -55,7 +55,7 @@ void moveresize_startup()
|
||||||
opaque_window.win = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
|
opaque_window.win = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
|
||||||
render_depth, InputOutput, render_visual,
|
render_depth, InputOutput, render_visual,
|
||||||
CWSaveUnder, &attrib);
|
CWSaveUnder, &attrib);
|
||||||
stacking_add(&opaque_window);
|
stacking_add(INTERNAL_AS_WINDOW(&opaque_window));
|
||||||
stacking_raise(INTERNAL_AS_WINDOW(&opaque_window));
|
stacking_raise(INTERNAL_AS_WINDOW(&opaque_window));
|
||||||
|
|
||||||
/* a GC to invert stuff */
|
/* a GC to invert stuff */
|
||||||
|
|
|
@ -34,7 +34,7 @@ Popup *popup_new(gboolean hasicon)
|
||||||
self->gravity = NorthWestGravity;
|
self->gravity = NorthWestGravity;
|
||||||
self->x = self->y = self->w = self->h = 0;
|
self->x = self->y = self->w = self->h = 0;
|
||||||
self->mapped = FALSE;
|
self->mapped = FALSE;
|
||||||
stacking_add(self);
|
stacking_add(INTERNAL_AS_WINDOW(self));
|
||||||
stacking_raise(INTERNAL_AS_WINDOW(self));
|
stacking_raise(INTERNAL_AS_WINDOW(self));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ void slit_startup()
|
||||||
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
|
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
|
||||||
|
|
||||||
g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
|
g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
|
||||||
stacking_add(&slit[i]);
|
stacking_add(SLIT_AS_WINDOW(&slit[i]));
|
||||||
stacking_raise(SLIT_AS_WINDOW(&slit[i]));
|
stacking_raise(SLIT_AS_WINDOW(&slit[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,9 +113,10 @@ void stacking_raise(ObWindow *window)
|
||||||
if (WINDOW_IS_CLIENT(window)) {
|
if (WINDOW_IS_CLIENT(window)) {
|
||||||
Client *client = WINDOW_AS_CLIENT(window);
|
Client *client = WINDOW_AS_CLIENT(window);
|
||||||
/* move up the transient chain as far as possible first */
|
/* move up the transient chain as far as possible first */
|
||||||
while (client->transient_for) {
|
if (client->transient_for) {
|
||||||
if (client->transient_for != TRAN_GROUP) {
|
if (client->transient_for != TRAN_GROUP) {
|
||||||
client = client->transient_for;
|
stacking_raise(CLIENT_AS_WINDOW(client->transient_for));
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
|
||||||
|
@ -125,15 +126,12 @@ void stacking_raise(ObWindow *window)
|
||||||
for (it = client->group->members; it; it = it->next) {
|
for (it = client->group->members; it; it = it->next) {
|
||||||
Client *c = it->data;
|
Client *c = it->data;
|
||||||
|
|
||||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
if (c != client && c->transient_for != TRAN_GROUP)
|
||||||
client = it->data;
|
stacking_raise(it->data);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (it == NULL) break;
|
if (it == NULL) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window = CLIENT_AS_WINDOW(client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
raise_recursive(window);
|
raise_recursive(window);
|
||||||
|
@ -180,7 +178,8 @@ void stacking_lower(ObWindow *window)
|
||||||
/* move up the transient chain as far as possible first */
|
/* move up the transient chain as far as possible first */
|
||||||
while (client->transient_for) {
|
while (client->transient_for) {
|
||||||
if (client->transient_for != TRAN_GROUP) {
|
if (client->transient_for != TRAN_GROUP) {
|
||||||
client = client->transient_for;
|
stacking_lower(CLIENT_AS_WINDOW(client->transient_for));
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
|
||||||
|
@ -190,12 +189,10 @@ void stacking_lower(ObWindow *window)
|
||||||
for (it = client->group->members; it; it = it->next) {
|
for (it = client->group->members; it; it = it->next) {
|
||||||
Client *c = it->data;
|
Client *c = it->data;
|
||||||
|
|
||||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
if (c != client && c->transient_for != TRAN_GROUP)
|
||||||
client = it->data;
|
stacking_lower(it->data);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (it == NULL) break;
|
if (it == NULL) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window = CLIENT_AS_WINDOW(client);
|
window = CLIENT_AS_WINDOW(client);
|
||||||
|
@ -205,3 +202,67 @@ void stacking_lower(ObWindow *window)
|
||||||
|
|
||||||
stacking_set_list();
|
stacking_set_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stacking_add(ObWindow *win)
|
||||||
|
{
|
||||||
|
stacking_list = g_list_append(stacking_list, win);
|
||||||
|
stacking_raise(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stacking_add_nonintrusive(ObWindow *win)
|
||||||
|
{
|
||||||
|
Window wins[2]; /* only ever restack 2 windows. */
|
||||||
|
|
||||||
|
if (!WINDOW_IS_CLIENT(win))
|
||||||
|
stacking_add(win); /* no special rules for others */
|
||||||
|
else {
|
||||||
|
Client *client = WINDOW_AS_CLIENT(win);
|
||||||
|
Client *parent = NULL;
|
||||||
|
GList *it_before = NULL;
|
||||||
|
|
||||||
|
/* insert above its highest parent */
|
||||||
|
if (client->transient_for) {
|
||||||
|
if (client->transient_for != TRAN_GROUP) {
|
||||||
|
parent = client->transient_for;
|
||||||
|
} else {
|
||||||
|
GSList *sit;
|
||||||
|
GList *it;
|
||||||
|
|
||||||
|
/* the check for TRAN_GROUP is to prevent an infinate loop with
|
||||||
|
2 transients of the same group at the head of the group's
|
||||||
|
members list */
|
||||||
|
for (it = stacking_list; !parent && it; it = it->next) {
|
||||||
|
for (sit = client->group->members; !parent && sit;
|
||||||
|
sit = sit->next) {
|
||||||
|
Client *c = sit->data;
|
||||||
|
if (sit->data == it->data &&
|
||||||
|
c->transient_for != TRAN_GROUP)
|
||||||
|
parent = it->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(it_before = g_list_find(stacking_list, parent))) {
|
||||||
|
/* no parent to put above, try find the focused client to go
|
||||||
|
under */
|
||||||
|
if ((it_before = g_list_find(stacking_list, focus_client)))
|
||||||
|
it_before = it_before->next;
|
||||||
|
else {
|
||||||
|
/* out of ideas, just add it normally... */
|
||||||
|
stacking_add(win);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacking_list = g_list_insert_before(stacking_list, it_before, win);
|
||||||
|
|
||||||
|
it_before = g_list_find(stacking_list, win)->prev;
|
||||||
|
if (!it_before)
|
||||||
|
wins[0] = focus_backup;
|
||||||
|
else
|
||||||
|
wins[0] = window_top(it_before->data);
|
||||||
|
wins[1] = window_top(win);
|
||||||
|
|
||||||
|
XRestackWindows(ob_display, wins, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ extern GList *stacking_list;
|
||||||
stacking_list */
|
stacking_list */
|
||||||
void stacking_set_list();
|
void stacking_set_list();
|
||||||
|
|
||||||
#define stacking_add(win) stacking_list = g_list_append(stacking_list, win);
|
void stacking_add(ObWindow *win);
|
||||||
|
void stacking_add_nonintrusive(ObWindow *win);
|
||||||
#define stacking_remove(win) stacking_list = g_list_remove(stacking_list, win);
|
#define stacking_remove(win) stacking_list = g_list_remove(stacking_list, win);
|
||||||
|
|
||||||
/*! Raises a window above all others in its stacking layer
|
/*! Raises a window above all others in its stacking layer
|
||||||
|
|
Loading…
Reference in a new issue