make stacking_add take care of raising also.
make new windows that dont get focus also not raise above the focused window.
XWindowAttributes attrib;
XSetWindowAttributes attrib_set;
XWMHints *wmhint;
+ gboolean activate = FALSE;
grab_server(TRUE);
client_apply_startup_state(self);
grab_server(FALSE);
-
+
+ /* add to client list/map */
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);
/* update the focus lists */
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? */
- if (ob_state != State_Starting) {
- Client *parent;
+ if (ob_state != State_Starting && config_focus_new) {
gboolean group_foc = FALSE;
- parent = NULL;
-
if (self->group) {
GSList *it;
break;
}
}
- if (!group_foc && self->transient_for) {
- if (self->transient_for != TRAN_GROUP) {/* transient of a window */
- parent = self->transient_for;
- } else { /* transient of a group */
- 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 ||
+ /* note the check against Type_Normal/Dialog, not client_normal(self),
+ which would also include other types. in this case we want more
+ strict rules for focus */
+ if (((self->type == Type_Normal ||
(self->type == Type_Dialog &&
(group_foc ||
- (!parent && (!self->group ||
- !self->group->members->next)))))) ||
- (parent && (client_focused(parent) ||
- client_search_focus_tree(parent)))) {
- client_focus(self);
+ (!self->transient_for && (!self->group ||
+ !self->group->members->next)))))) ||
+ client_search_focus_tree_full(self) ||
+ !focus_client ||
+ !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 */
- client_set_list();
+ screen_update_struts();
/* make sure the window is visible */
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);
g_message("Managed window 0x%lx", window);
g_hash_table_insert(menu_map, &self->items, 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));
return self;
opaque_window.win = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
render_depth, InputOutput, render_visual,
CWSaveUnder, &attrib);
- stacking_add(&opaque_window);
+ stacking_add(INTERNAL_AS_WINDOW(&opaque_window));
stacking_raise(INTERNAL_AS_WINDOW(&opaque_window));
/* a GC to invert stuff */
self->gravity = NorthWestGravity;
self->x = self->y = self->w = self->h = 0;
self->mapped = FALSE;
- stacking_add(self);
+ stacking_add(INTERNAL_AS_WINDOW(self));
stacking_raise(INTERNAL_AS_WINDOW(self));
return self;
}
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
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]));
}
}
if (WINDOW_IS_CLIENT(window)) {
Client *client = WINDOW_AS_CLIENT(window);
/* move up the transient chain as far as possible first */
- while (client->transient_for) {
+ if (client->transient_for) {
if (client->transient_for != TRAN_GROUP) {
- client = client->transient_for;
+ stacking_raise(CLIENT_AS_WINDOW(client->transient_for));
+ return;
} else {
GSList *it;
for (it = client->group->members; it; it = it->next) {
Client *c = it->data;
- if (c != client && c->transient_for != TRAN_GROUP) {
- client = it->data;
- break;
- }
+ if (c != client && c->transient_for != TRAN_GROUP)
+ stacking_raise(it->data);
}
- if (it == NULL) break;
+ if (it == NULL) return;
}
}
- window = CLIENT_AS_WINDOW(client);
}
raise_recursive(window);
/* move up the transient chain as far as possible first */
while (client->transient_for) {
if (client->transient_for != TRAN_GROUP) {
- client = client->transient_for;
+ stacking_lower(CLIENT_AS_WINDOW(client->transient_for));
+ return;
} else {
GSList *it;
for (it = client->group->members; it; it = it->next) {
Client *c = it->data;
- if (c != client && c->transient_for != TRAN_GROUP) {
- client = it->data;
- break;
- }
+ if (c != client && c->transient_for != TRAN_GROUP)
+ stacking_lower(it->data);
}
- if (it == NULL) break;
+ if (it == NULL) return;
}
}
window = CLIENT_AS_WINDOW(client);
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);
+ }
+}
stacking_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);
/*! Raises a window above all others in its stacking layer