X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=f704ca1a61924dd41f5e4ef89d0c66ae6b18f621;hb=f7de8e5a59a4b0b2b92f9b88f0abd0db094b0fe5;hp=75a3bc251c729b214c4021df5ad9e6770d3e81ef;hpb=5a7953b36aa0e23ae21f707d9fb8b6b9e882946d;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 75a3bc25..f704ca1a 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1,5 +1,6 @@ #include "client.h" #include "dock.h" +#include "xerror.h" #include "startup.h" #include "screen.h" #include "moveresize.h" @@ -14,6 +15,7 @@ #include "openbox.h" #include "group.h" #include "config.h" +#include "menu.h" #include "render/render.h" #include @@ -252,26 +254,26 @@ void client_manage(Window window) focus_order_add_new(self); /* focus the new window? */ - if (ob_state != State_Starting && config_focus_new) { + if (ob_state != State_Starting && config_focus_new && + (self->type == Type_Normal || self->type == Type_Dialog)) { gboolean group_foc = FALSE; if (self->group) { GSList *it; - for (it = self->group->members; it; it = it->next) + for (it = self->group->members; it; it = it->next) { if (client_focused(it->data)) { group_foc = TRUE; break; } + } } /* 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 || - (!self->transient_for && (!self->group || - !self->group->members->next)))))) || + if ((group_foc || + (!self->transient_for && (!self->group || + !self->group->members->next))) || client_search_focus_tree_full(self) || !focus_client || !client_normal(focus_client)) { @@ -311,6 +313,13 @@ void client_unmanage_all() client_unmanage(client_list->data); } +/* called by client_unmanage() to close any menus referencing this client */ +void client_close_menus(gpointer key, gpointer value, gpointer self) +{ + if (((Menu *)value)->client == (Client *)self) + menu_hide((Menu *)value); +} + void client_unmanage(Client *self) { int j; @@ -364,6 +373,10 @@ void client_unmanage(Client *self) if (moveresize_client == self) moveresize_end(TRUE); + /* close any windows that are attached to this window */ + g_hash_table_foreach(menu_hash, client_close_menus, self); + + if (focus_client == self) { XEvent e; @@ -1018,7 +1031,7 @@ void client_setup_decor_and_functions(Client *self) we may also need to be repositioned */ frame_adjust_area(self->frame, TRUE, TRUE); /* with new decor, the window's maximized size may change */ - client_remaximize(self); + client_reconfigure(self); } else { /* this makes sure that these windows appear on all desktops */ if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL) @@ -1076,19 +1089,10 @@ static void client_change_allowed_actions(Client *self) } } -void client_remaximize(Client *self) +void client_reconfigure(Client *self) { - int dir; - if (self->max_horz && self->max_vert) - dir = 0; - else if (self->max_horz) - dir = 1; - else if (self->max_vert) - dir = 2; - else - return; /* not maximized */ - self->max_horz = self->max_vert = FALSE; - client_maximize(self, TRUE, dir, FALSE); + client_configure(self, Corner_TopLeft, self->area.x, self->area.y, + self->area.width, self->area.height, TRUE, TRUE); } void client_update_wmhints(Client *self) @@ -1128,18 +1132,20 @@ void client_update_wmhints(Client *self) group_remove(self->group, self); self->group = NULL; } - /* i can only have transients from the group if i am not transient - myself */ - if (hints->window_group != None && !self->transient_for) { + 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); + /* i can only have transients from the group if i am not + transient myself */ + if (!self->transient_for) { + /* 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); + } } /* the WM_HINTS can contain an icon */ @@ -1311,7 +1317,7 @@ void client_update_icons(Client *self) w = data[i++]; h = data[i++]; i += w * h; - if (i > num) break; + if (i > num || w*h == 0) break; ++self->nicons; } @@ -1325,6 +1331,8 @@ void client_update_icons(Client *self) w = self->icons[j].width = data[i++]; h = self->icons[j].height = data[i++]; + if (w*h == 0) continue; + self->icons[j].data = g_new(pixel32, w * h); for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) { if (x >= w) { @@ -1346,6 +1354,7 @@ void client_update_icons(Client *self) if (num == 2) { self->nicons++; self->icons = g_new(Icon, self->nicons); + xerror_set_ignore(TRUE); if (!render_pixmap_to_rgba(data[0], data[1], &self->icons[self->nicons-1].width, &self->icons[self->nicons-1].height, @@ -1353,6 +1362,7 @@ void client_update_icons(Client *self) g_free(&self->icons[self->nicons-1]); self->nicons--; } + xerror_set_ignore(FALSE); } g_free(data); } else { @@ -1362,6 +1372,7 @@ void client_update_icons(Client *self) if (hints->flags & IconPixmapHint) { self->nicons++; self->icons = g_new(Icon, self->nicons); + xerror_set_ignore(TRUE); if (!render_pixmap_to_rgba(hints->icon_pixmap, (hints->flags & IconMaskHint ? hints->icon_mask : None), @@ -1371,6 +1382,7 @@ void client_update_icons(Client *self) g_free(&self->icons[self->nicons-1]); self->nicons--; } + xerror_set_ignore(FALSE); } XFree(hints); } @@ -1597,10 +1609,25 @@ void client_configure(Client *self, Corner anchor, int x, int y, int w, int h, /* set the size and position if fullscreen */ if (self->fullscreen) { - x = 0; - y = 0; - w = screen_physical_size.width; - h = screen_physical_size.height; +#ifdef VIDMODE + int dot; + XF86VidModeModeLine mode; + + if (XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) { + w = mode.hdisplay; + h = mode.vdisplay; + if (mode.privsize) XFree(mode.private); + } else { +#else + w = screen_physical_size.width; + h = screen_physical_size.height; +#endif +#ifdef VIDMODE + } + if (!XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y)) { + x = y = 0; +#endif + } user = FALSE; /* ignore that increment etc shit when in fullscreen */ } else { /* set the size and position if maximized */ @@ -1846,6 +1873,11 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk) /* this puts it after the current focused window */ focus_order_remove(self); focus_order_add_new(self); + + /* this is here cuz with the VIDMODE extension, the viewport can change + while a fullscreen window is iconic, and when it uniconifies, it + would be nice if it did so to the new position of the viewport */ + client_reconfigure(self); } client_change_state(self); client_showhide(self); @@ -2013,7 +2045,7 @@ void client_set_desktop(Client *self, guint target, gboolean donthide) if (target == self->desktop) return; - g_message("Setting desktop %u", target); + g_message("Setting desktop %u", target+1); g_assert(target < screen_num_desktops || target == DESKTOP_ALL); @@ -2205,7 +2237,7 @@ void client_set_state(Client *self, Atom action, long data1, long data2) if (shaded != self->shaded) client_shade(self, shaded); client_calc_layer(self); - client_change_state(self); /* change the hint to relect these changes */ + client_change_state(self); /* change the hint to reflect these changes */ } Client *client_focus_target(Client *self) @@ -2218,18 +2250,15 @@ Client *client_focus_target(Client *self) return self; } -gboolean client_focus(Client *self) +gboolean client_can_focus(Client *self) { XEvent ev; /* choose the correct target */ self = client_focus_target(self); - if (self->desktop != DESKTOP_ALL && self->desktop != screen_desktop) { - /* update the focus lists */ - focus_order_to_top(self); + if (!self->frame->visible) return FALSE; - } if (!((self->can_focus || self->focus_notify) && (self->desktop == screen_desktop || @@ -2255,6 +2284,22 @@ gboolean client_focus(Client *self) } } + return TRUE; +} + +gboolean client_focus(Client *self) +{ + /* choose the correct target */ + self = client_focus_target(self); + + if (!client_can_focus(self)) { + if (!self->frame->visible) { + /* update the focus lists */ + focus_order_to_top(self); + } + return FALSE; + } + if (self->can_focus) /* RevertToPointerRoot causes much more headache than RevertToNone, so I choose to use it always, hopefully to find errors quicker, if any @@ -2439,3 +2484,18 @@ Client *client_find_directional(Client *c, Direction dir) return best_client; } + +void client_set_layer(Client *self, int layer) +{ + if (layer < 0) { + self->below = TRUE; + self->above = FALSE; + } else if (layer == 0) { + self->below = self->above = FALSE; + } else { + self->below = FALSE; + self->above = TRUE; + } + client_calc_layer(self); + client_change_state(self); /* reflect this in the state hints */ +}