X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=98f3dea4913b13e3fc693b65f6244e82d9d0e28b;hb=6a9e7dea8e9c20a65e5bb513ca9d7a92f3db47d3;hp=d86e42532bf627e7941d735adbc0fcbee5c5afb2;hpb=d4b2de21809110290b825538f29986b170e4dc16;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index d86e4253..98f3dea4 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1,5 +1,6 @@ #include "client.h" #include "screen.h" +#include "moveresize.h" #include "prop.h" #include "extensions.h" #include "frame.h" @@ -152,6 +153,7 @@ void client_manage(Window window) XSetWindowAttributes attrib_set; /* XWMHints *wmhint; */ guint i; + Client *parent; grab_server(TRUE); @@ -223,10 +225,10 @@ void client_manage(Window window) /* update the focus lists */ if (self->desktop == DESKTOP_ALL) { for (i = 0; i < screen_num_desktops; ++i) - focus_order[i] = g_list_append(focus_order[i], self); + focus_order[i] = g_list_insert(focus_order[i], self, 1); } else { i = self->desktop; - focus_order[i] = g_list_append(focus_order[i], self); + focus_order[i] = g_list_insert(focus_order[i], self, 1); } stacking_raise(self); @@ -237,26 +239,30 @@ void client_manage(Window window) client_showhide(self); - dispatch_client(Event_Client_Mapped, self, 0, 0); - /* focus the new window? */ if (ob_state != State_Starting && client_normal(self)) { - if (config_focus_new) - client_focus(self); - else if (self->transient_for) { + parent = NULL; + + if (self->transient_for) { if (self->transient_for != TRAN_GROUP) {/* transient of a window */ - if (focus_client == self->transient_for) - client_focus(self); + parent = self->transient_for; } else { /* transient of a group */ GSList *it; for (it = self->group->members; it; it = it->next) - if (focus_client == it->data) { - client_focus(self); - break; - } + 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) || + (parent && (client_focused(parent) || + search_focus_tree(parent, parent)))) { + client_focus(self); + } } /* update the list hints */ @@ -265,6 +271,8 @@ void client_manage(Window window) /* make sure the window is visible */ client_move_onscreen(self); + dispatch_client(Event_Client_Mapped, self, 0, 0); + g_message("Managed window 0x%lx", window); } @@ -331,8 +339,17 @@ void client_unmanage(Client *self) } } - if (focus_client == self) + if (moveresize_client == self) + moveresize_end(TRUE); + + if (focus_client == self) { + XEvent e; + + /* focus the last focused window on the desktop, and ignore enter + events from the unmap so it doesnt mess with the focus */ + while (XCheckTypedEvent(ob_display, EnterNotify, &e)); client_unfocus(self); + } /* remove from its group */ if (self->group) { @@ -363,6 +380,7 @@ void client_unmanage(Client *self) XMapWindow(ob_display, self->window); } + g_message("Unmanaged window 0x%lx", self->window); /* free all data allocated in the client struct */ @@ -492,11 +510,12 @@ static void client_get_all(Client *self) self->nicons = 0; client_get_area(self); + client_update_transient_for(self); + client_update_wmhints(self); client_get_desktop(self); client_get_state(self); client_get_shaped(self); - client_update_transient_for(self); client_get_mwm_hints(self); client_get_type(self);/* this can change the mwmhints for special cases */ @@ -510,7 +529,6 @@ static void client_get_all(Client *self) (min/max sizes), so we're ready to set up the decorations/functions */ client_setup_decor_and_functions(self); - client_update_wmhints(self); client_update_title(self); client_update_icon_title(self); client_update_class(self); @@ -518,14 +536,6 @@ static void client_get_all(Client *self) client_update_icons(self); client_update_kwm_icon(self); - /* this makes sure that these windows appear on all desktops */ - if (self->type == Type_Desktop) - self->desktop = DESKTOP_ALL; - - /* set the desktop hint, to make sure that it always exists, and to - reflect any changes we've made here */ - PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); - client_change_state(self); } @@ -549,9 +559,31 @@ static void client_get_desktop(Client *self) if (d >= screen_num_desktops && d != DESKTOP_ALL) d = screen_num_desktops - 1; self->desktop = d; - } else { - /* defaults to the current desktop */ - self->desktop = screen_desktop; + } else { + gboolean trdesk = FALSE; + + if (self->transient_for) { + if (self->transient_for != TRAN_GROUP) { + self->desktop = self->transient_for->desktop; + trdesk = TRUE; + } else { + GSList *it; + + for (it = self->group->members; it; it = it->next) + if (it->data != self && + ((Client*)it->data)->transient_for != TRAN_GROUP) { + self->desktop = ((Client*)it->data)->desktop; + trdesk = TRUE; + break; + } + } + } + if (!trdesk) + /* defaults to the current desktop */ + self->desktop = screen_desktop; + + /* set the desktop hint, to make sure that it always exists */ + PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); } } @@ -735,6 +767,10 @@ void client_get_type(Client *self) else self->type = Type_Normal; } + + /* this makes sure that these windows appear on all desktops */ + if (self->type == Type_Desktop) + self->desktop = DESKTOP_ALL; } void client_update_protocols(Client *self) @@ -1034,9 +1070,11 @@ void client_update_wmhints(Client *self) ur = TRUE; if (!(hints->flags & WindowGroupHint)) - hints->window_group = None; /* no group */ + hints->window_group = None; + /* did the group state change? */ - if (hints->window_group != (self->group ? self->group->leader : None)){ + if (hints->window_group != + (self->group ? self->group->leader : None)) { /* remove from the old group if there was one */ if (self->group != NULL) { /* remove transients of the group */ @@ -1049,36 +1087,40 @@ void client_update_wmhints(Client *self) group_remove(self->group, self); self->group = NULL; } - if (hints->window_group != None) + if (hints->window_group != None) { self->group = group_add(hints->window_group, self); - /* add other transients of the group that are already set up */ - for (it = self->group->members; it; it = it->next) - if (it->data != self && - ((Client*)it->data)->transient_for == TRAN_GROUP) - self->transients = g_slist_append(self->transients, - it->data); + /* add other transients of the group that are already + set up */ + for (it = self->group->members; it; it = it->next) + if (it->data != self && + ((Client*)it->data)->transient_for == TRAN_GROUP) + self->transients = g_slist_append(self->transients, + it->data); + } /* because the self->transient flag wont change from this call, we don't need to update the window's type and such, only its - transient_for, and the transients lists of other windows in the - group may be affected */ + transient_for, and the transients lists of other windows in + the group may be affected */ client_update_transient_for(self); } - if (hints->flags & IconPixmapHint) { - client_update_kwm_icon(self); - /* try get the kwm icon first, this is a fallback only */ - if (self->pixmap_icon == None) { - self->pixmap_icon = hints->icon_pixmap; - if (hints->flags & IconMaskHint) - self->pixmap_icon_mask = hints->icon_mask; - else - self->pixmap_icon_mask = None; - - if (self->frame) - frame_adjust_icon(self->frame); - } + client_update_kwm_icon(self); + /* try get the kwm icon first, this is a fallback only */ + if (self->pixmap_icon == None) { + if (hints->flags & IconPixmapHint) { + if (self->pixmap_icon == None) { + self->pixmap_icon = hints->icon_pixmap; + if (hints->flags & IconMaskHint) + self->pixmap_icon_mask = hints->icon_mask; + else + self->pixmap_icon_mask = None; + + if (self->frame) + frame_adjust_icon(self->frame); + } + } } XFree(hints); @@ -2081,10 +2123,26 @@ gboolean client_focusable(Client *self) 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); + } + return FALSE; + } + if (!client_focusable(self)) return FALSE; @@ -2107,7 +2165,7 @@ gboolean client_focus(Client *self) } if (self->can_focus) - /* RevertToPointerRoot causes much more headache than TevertToNone, so + /* RevertToPointerRoot causes much more headache than RevertToNone, so I choose to use it always, hopefully to find errors quicker, if any are left. (I hate X. I hate focus events.) */ XSetInputFocus(ob_display, self->window, RevertToPointerRoot, @@ -2129,7 +2187,9 @@ gboolean client_focus(Client *self) } #ifdef DEBUG_FOCUS - g_message("focusing %lx", self->window); + g_message("%sively focusing %lx at %d", (self->can_focus ? "act" : "pass"), + self->window, (int) + event_lasttime); #endif /* Cause the FocusIn to come back to us. Important for desktop switches, @@ -2143,7 +2203,7 @@ void client_unfocus(Client *self) { g_assert(focus_client == self); #ifdef DEBUG_FOCUS - g_message("client_unfocus"); + g_message("client_unfocus for %lx", self->window); #endif focus_fallback(Fallback_Unfocusing); }