X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=c475fba309054982c873a1942fe258c556a75bbb;hb=02c7f2e8afbfe5ebc589415a87a2ac156c9ef5af;hp=a473fdb187b1f2c3f2f0007b72a42efd28d07939;hpb=8dfa16abaed94350a901dea0969752d0692753fe;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index a473fdb1..c475fba3 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1,4 +1,5 @@ #include "client.h" +#include "startup.h" #include "screen.h" #include "moveresize.h" #include "prop.h" @@ -26,9 +27,6 @@ GList *client_list = NULL; GHashTable *client_map = NULL; -static Window *client_startup_stack_order = NULL; -static guint client_startup_stack_size = 0; - static void client_get_all(Client *self); static void client_toggle_border(Client *self, gboolean show); static void client_get_area(Client *self); @@ -53,11 +51,6 @@ void client_startup() client_map = g_hash_table_new((GHashFunc)map_hash, (GEqualFunc)map_key_comp); - /* save the stacking order on startup! */ - PROP_GETA32(ob_root, net_client_list_stacking, window, - (guint32**)&client_startup_stack_order, - &client_startup_stack_size); - client_set_list(); } @@ -95,6 +88,7 @@ void client_manage_all() Window w, *children; XWMHints *wmhints; XWindowAttributes attrib; + Client *active; XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild); @@ -130,19 +124,22 @@ void client_manage_all() why with stacking_lower? Why, because then windows who aren't in the stacking list are on the top where you can see them instead of buried at the bottom! */ - for (i = client_startup_stack_size; i > 0; --i) { + for (i = startup_stack_size; i > 0; --i) { Client *c; - w = client_startup_stack_order[i-1]; + w = startup_stack_order[i-1]; c = g_hash_table_lookup(client_map, &w); if (c) stacking_lower(c); } - g_free(client_startup_stack_order); - client_startup_stack_order = NULL; - client_startup_stack_size = 0; + g_free(startup_stack_order); + startup_stack_order = NULL; + startup_stack_size = 0; - if (config_focus_new) - focus_fallback(Fallback_NoFocus); + if (config_focus_new) { + active = g_hash_table_lookup(client_map, &startup_active); + if (!active || !client_focus(active)) + focus_fallback(Fallback_NoFocus); + } } void client_manage(Window window) @@ -152,8 +149,6 @@ void client_manage(Window window) XWindowAttributes attrib; XSetWindowAttributes attrib_set; /* XWMHints *wmhint; */ - guint i; - Client *parent; grab_server(TRUE); @@ -223,13 +218,7 @@ void client_manage(Window window) g_hash_table_insert(client_map, &self->window, self); /* update the focus lists */ - if (self->desktop == DESKTOP_ALL) { - for (i = 0; i < screen_num_desktops; ++i) - focus_order[i] = g_list_insert(focus_order[i], self, 1); - } else { - i = self->desktop; - focus_order[i] = g_list_insert(focus_order[i], self, 1); - } + focus_order_add_new(self); stacking_raise(self); @@ -241,9 +230,21 @@ void client_manage(Window window) /* focus the new window? */ if (ob_state != State_Starting) { + Client *parent; + gboolean group_foc = FALSE; + parent = NULL; - if (self->transient_for) { + if (self->group) { + GSList *it; + + for (it = self->group->members; it; it = it->next) + if (client_focused(it->data)) { + group_foc = TRUE; + 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 */ @@ -258,7 +259,12 @@ void client_manage(Window window) /* 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) || + if ((config_focus_new && + (self->type == Type_Normal || + (self->type == Type_Dialog && + (group_foc || + (!parent && (!self->group || + !self->group->members->next)))))) || (parent && (client_focused(parent) || search_focus_tree(parent, parent)))) { client_focus(self); @@ -284,7 +290,6 @@ void client_unmanage_all() void client_unmanage(Client *self) { - guint i; int j; GSList *it; @@ -306,13 +311,7 @@ void client_unmanage(Client *self) g_hash_table_remove(client_map, &self->window); /* update the focus lists */ - if (self->desktop == DESKTOP_ALL) { - for (i = 0; i < screen_num_desktops; ++i) - focus_order[i] = g_list_remove(focus_order[i], self); - } else { - i = self->desktop; - focus_order[i] = g_list_remove(focus_order[i], self); - } + focus_order_remove(self); /* once the client is out of the list, update the struts to remove it's influence */ @@ -649,22 +648,24 @@ void client_update_transient_for(Client *self) Window t = None; Client *c = NULL; - if (XGetTransientForHint(ob_display, self->window, &t) && - t != self->window) { /* cant be transient to itself! */ + if (XGetTransientForHint(ob_display, self->window, &t)) { self->transient = TRUE; - c = g_hash_table_lookup(client_map, &t); - g_assert(c != self);/* if this happens then we need to check for it*/ - - if (!c && self->group) { - /* not transient to a client, see if it is transient for a - group */ - if (t == self->group->leader || - t == None || - t == ob_root) { - /* window is a transient for its group! */ - c = TRAN_GROUP; - } - } + if (t != self->window) { /* cant be transient to itself! */ + c = g_hash_table_lookup(client_map, &t); + /* if this happens then we need to check for it*/ + g_assert(c != self); + + if (!c && self->group) { + /* not transient to a client, see if it is transient for a + group */ + if (t == self->group->leader || + t == None || + t == ob_root) { + /* window is a transient for its group! */ + c = TRAN_GROUP; + } + } + } } else self->transient = FALSE; @@ -675,7 +676,8 @@ void client_update_transient_for(Client *self) /* remove from old parents */ for (it = self->group->members; it; it = it->next) - if (it->data != self) + if (it->data != self && + (((Client*)it->data)->transient_for != TRAN_GROUP)) ((Client*)it->data)->transients = g_slist_remove(((Client*)it->data)->transients, self); } else if (self->transient_for != NULL) { /* transient of window */ @@ -689,9 +691,22 @@ void client_update_transient_for(Client *self) /* add to new parents */ for (it = self->group->members; it; it = it->next) - if (it->data != self) + if (it->data != self && + (((Client*)it->data)->transient_for != TRAN_GROUP)) ((Client*)it->data)->transients = g_slist_append(((Client*)it->data)->transients, self); + + /* remove all transients which are in the group, that causes + circlular pointer hell of doom */ + for (it = self->group->members; it; it = it->next) { + GSList *sit, *next; + for (sit = self->transients; sit; sit = next) { + next = sit->next; + if (sit->data == it->data) + self->transients = g_slist_remove(self->transients, + sit->data); + } + } } else if (self->transient_for != NULL) { /* transient of window */ /* add to new parent */ self->transient_for->transients = @@ -1718,6 +1733,9 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk) /* we unmap the client itself so that we can get MapRequest events, and because the ICCCM tells us to! */ XUnmapWindow(ob_display, self->window); + + /* update the focus lists.. iconic windows go to the bottom */ + focus_order_to_bottom(self); } else { if (curdesk) client_set_desktop(self, screen_desktop, FALSE); @@ -1886,7 +1904,7 @@ void client_kill(Client *self) void client_set_desktop(Client *self, guint target, gboolean donthide) { - guint old, i; + guint old; if (target == self->desktop) return; @@ -1894,6 +1912,9 @@ void client_set_desktop(Client *self, guint target, gboolean donthide) g_assert(target < screen_num_desktops || target == DESKTOP_ALL); + /* remove from the old desktop(s) */ + focus_order_remove(self); + old = self->desktop; self->desktop = target; PROP_SET32(self->window, net_wm_desktop, cardinal, target); @@ -1907,25 +1928,11 @@ void client_set_desktop(Client *self, guint target, gboolean donthide) stacking_raise(self); screen_update_struts(); - /* update the focus lists */ - if (old == DESKTOP_ALL) { - for (i = 0; i < screen_num_desktops; ++i) - focus_order[i] = g_list_remove(focus_order[i], self); - } else - focus_order[old] = g_list_remove(focus_order[old], self); - if (target == DESKTOP_ALL) { - for (i = 0; i < screen_num_desktops; ++i) { - if (config_focus_new) - focus_order[i] = g_list_prepend(focus_order[i], self); - else - focus_order[i] = g_list_append(focus_order[i], self); - } - } else { - if (config_focus_new) - focus_order[target] = g_list_prepend(focus_order[target], self); - else - focus_order[target] = g_list_append(focus_order[target], self); - } + /* add to the new desktop(s) */ + if (config_focus_new) + focus_order_to_top(self); + else + focus_order_to_bottom(self); dispatch_client(Event_Client_Desktop, self, target, old); } @@ -2112,38 +2119,23 @@ Client *client_focus_target(Client *self) return self; } -gboolean client_focusable(Client *self) -{ - /* won't try focus if the client doesn't want it, or if the window isn't - visible on the screen */ - return self->frame->visible && - (self->can_focus || self->focus_notify); -} - gboolean client_focus(Client *self) { XEvent ev; - guint i; /* choose the correct target */ self = client_focus_target(self); if (self->desktop != DESKTOP_ALL && self->desktop != screen_desktop) { /* update the focus lists */ - if (self->desktop == DESKTOP_ALL) { - for (i = 0; i < screen_num_desktops; ++i) { - focus_order[i] = g_list_remove(focus_order[i], self); - focus_order[i] = g_list_prepend(focus_order[i], self); - } - } else { - i = self->desktop; - focus_order[i] = g_list_remove(focus_order[i], self); - focus_order[i] = g_list_prepend(focus_order[i], self); - } + focus_order_to_top(self); return FALSE; } - if (!client_focusable(self)) + if (!((self->can_focus || self->focus_notify) && + (self->desktop == screen_desktop || + self->desktop == DESKTOP_ALL) && + !self->iconic)) return FALSE; /* do a check to see if the window has already been unmapped or destroyed