X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=4672b8cb2189310361f65dba855efa8869eaac50;hb=277db2822d79a6000d31b93ec963ae87286d6ade;hp=c0323c2628d15f0b993f9b0cb587cfdbeba6a3fd;hpb=fce7d9b21ed039f32cde5f4fb6caa179e8c7e922;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index c0323c26..4672b8cb 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -83,12 +83,16 @@ static void client_change_state(ObClient *self); static void client_change_wm_state(ObClient *self); static void client_apply_startup_state(ObClient *self, gint x, gint y); static void client_restore_session_state(ObClient *self); -static void client_restore_session_stacking(ObClient *self); +static gboolean client_restore_session_stacking(ObClient *self); static ObAppSettings *client_get_settings_state(ObClient *self); static void client_update_transient_tree(ObClient *self, ObGroup *oldgroup, ObGroup *newgroup, ObClient* oldparent, ObClient *newparent); +static void client_present(ObClient *self, gboolean here, gboolean raise); +static GSList *client_search_all_top_parents_internal(ObClient *self, + gboolean bylayer, + ObStackingLayer layer); void client_startup(gboolean reconfig) { @@ -321,10 +325,10 @@ void client_manage(Window window) grab_server(FALSE); stacking_add_nonintrusive(CLIENT_AS_WINDOW(self)); - client_restore_session_stacking(self); /* focus the new window? */ if (ob_state() != OB_STATE_STARTING && + (!self->session || self->session->focused) && !self->iconic && /* this means focus=true for window is same as config_focus_new=true */ ((config_focus_new || (settings && settings->focus == 1)) || @@ -377,6 +381,10 @@ void client_manage(Window window) */ ob_debug("placing window 0x%x at %d, %d with size %d x %d\n", self->window, newx, newy, self->area.width, self->area.height); + if (self->session) + ob_debug("session requested %d %d\n", + self->session->x, self->session->y); + client_apply_startup_state(self, newx, newy); mouse_grab_for_client(self, TRUE); @@ -443,7 +451,8 @@ void client_manage(Window window) Also if you don't have focus_new enabled, then it's going to get raised to the top. Legacy begets legacy I guess? */ - client_raise(self); + if (!client_restore_session_stacking(self)) + client_raise(self); } /* this has to happen before we try focus the window, but we want it to @@ -456,8 +465,10 @@ void client_manage(Window window) a window maps since its not based on an action from the user like clicking a window to activate it. so keep the new window out of the way but do focus it. */ - if (activate) - client_activate(self, FALSE, TRUE); + if (activate) { + gboolean stacked = client_restore_session_stacking(self); + client_present(self, FALSE, !stacked); + } /* add to client list/map */ client_list = g_list_append(client_list, self); @@ -685,13 +696,22 @@ static void client_restore_session_state(ObClient *self) { GList *it; - if (!(it = session_state_find(self))) + ob_debug_type(OB_DEBUG_SM, + "Restore session for client %s\n", self->title); + + if (!(it = session_state_find(self))) { + ob_debug_type(OB_DEBUG_SM, + "Session data not found for client %s\n", self->title); return; + } self->session = it->data; + ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s\n", + self->title); + RECT_SET_POINT(self->area, self->session->x, self->session->y); - self->positioned = PPosition; + self->positioned = USPosition; if (self->session->w > 0) self->area.width = self->session->w; if (self->session->h > 0) @@ -713,28 +733,33 @@ static void client_restore_session_state(ObClient *self) self->below = self->session->below; self->max_horz = self->session->max_horz; self->max_vert = self->session->max_vert; + self->undecorated = self->session->undecorated; } -static void client_restore_session_stacking(ObClient *self) +static gboolean client_restore_session_stacking(ObClient *self) { - GList *it; + GList *it, *mypos; + + if (!self->session) return FALSE; - if (!self->session) return; + mypos = g_list_find(session_saved_state, self->session); + if (!mypos) return FALSE; - it = g_list_find(session_saved_state, self->session); - for (it = g_list_previous(it); it; it = g_list_previous(it)) { + /* start above me and look for the first client */ + for (it = g_list_previous(mypos); it; it = g_list_previous(it)) { GList *cit; - for (cit = client_list; cit; cit = g_list_next(cit)) - if (session_state_cmp(it->data, cit->data)) - break; - if (cit) { - client_calc_layer(self); - stacking_below(CLIENT_AS_WINDOW(self), - CLIENT_AS_WINDOW(cit->data)); - break; + for (cit = client_list; cit; cit = g_list_next(cit)) { + ObClient *c = cit->data; + /* found a client that was in the session, so go below it */ + if (c->session == it->data) { + stacking_below(CLIENT_AS_WINDOW(self), + CLIENT_AS_WINDOW(cit->data)); + return TRUE; + } } } + return FALSE; } void client_move_onscreen(ObClient *self, gboolean rude) @@ -793,7 +818,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, if (!rude) { Point oldtl, oldtr, oldbl, oldbr; Point newtl, newtr, newbl, newbr; - gboolean stationary; + gboolean stationary_l, stationary_r, stationary_t, stationary_b; POINT_SET(oldtl, self->frame->area.x, self->frame->area.y); POINT_SET(oldbr, self->frame->area.x + self->frame->area.width - 1, @@ -807,20 +832,22 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, POINT_SET(newbl, newtl.x, newbr.y); /* is it moving or just resizing from some corner? */ - stationary = (POINT_EQUAL(oldtl, newtl) || POINT_EQUAL(oldtr, newtr) || - POINT_EQUAL(oldbl, newbl) || POINT_EQUAL(oldbr, newbr)); + stationary_l = oldtl.x == oldtl.x; + stationary_r = oldtr.x == oldtr.x; + stationary_t = oldtl.y == oldtl.y; + stationary_b = oldbl.y == oldbl.y; - /* if left edge is growing */ - if (stationary && newtl.x < oldtl.x) + /* if left edge is growing and didnt move right edge */ + if (stationary_r && newtl.x < oldtl.x) rudel = TRUE; - /* if right edge is growing */ - if (stationary && newtr.x > oldtr.x) + /* if right edge is growing and didnt move left edge */ + if (stationary_l && newtr.x > oldtr.x) ruder = TRUE; - /* if top edge is growing */ - if (stationary && newtl.y < oldtl.y) + /* if top edge is growing and didnt move bottom edge */ + if (stationary_b && newtl.y < oldtl.y) rudet = TRUE; - /* if bottom edge is growing */ - if (stationary && newbl.y > oldbl.y) + /* if bottom edge is growing and didnt move top edge */ + if (stationary_t && newbl.y > oldbl.y) rudeb = TRUE; } @@ -970,6 +997,7 @@ static void client_get_all(ObClient *self) client_update_strut(self); client_update_icons(self); client_update_user_time(self); + client_update_icon_geometry(self); } static void client_get_startup_id(ObClient *self) @@ -1102,7 +1130,7 @@ static void client_get_state(ObClient *self) self->below = TRUE; else if (state[i] == prop_atoms.net_wm_state_demands_attention) self->demands_attention = TRUE; - else if (state[i] == prop_atoms.ob_wm_state_undecorated) + else if (state[i] == prop_atoms.openbox_wm_state_undecorated) self->undecorated = TRUE; } @@ -1265,7 +1293,7 @@ static void client_update_transient_tree(ObClient *self, c = it->data; if (c != self && (!c->transient_for || c->transient_for != OB_TRAN_GROUP)) - c->transients = g_slist_append(c->transients, self); + c->transients = g_slist_prepend(c->transients, self); } } /* If we are now transient for a single window which we weren't before, @@ -1278,7 +1306,7 @@ static void client_update_transient_tree(ObClient *self, newparent != oldparent && /* don't make ourself its child if it is already our child */ !client_is_direct_child(self, newparent)) - newparent->transients = g_slist_append(newparent->transients, self); + newparent->transients = g_slist_prepend(newparent->transients, self); /* If the group changed then we need to add any new group transient windows to our children. But if we're transient for the group, then @@ -1297,7 +1325,7 @@ static void client_update_transient_tree(ObClient *self, /* Don't make it our child if it is already our parent */ !client_is_direct_child(c, self)) { - self->transients = g_slist_append(self->transients, c); + self->transients = g_slist_prepend(self->transients, c); } } } @@ -2022,6 +2050,22 @@ void client_update_user_time(ObClient *self) } } +void client_update_icon_geometry(ObClient *self) +{ + guint num; + guint32 *data; + + RECT_SET(self->icon_geometry, 0, 0, 0, 0); + + if (PROP_GETA32(self->window, net_wm_icon_geometry, cardinal, &data, &num) + && num == 4) + { + /* don't let them set it with an area < 0 */ + RECT_SET(self->icon_geometry, data[0], data[1], + MAX(data[2],0), MAX(data[3],0)); + } +} + static void client_get_client_machine(ObClient *self) { gchar *data = NULL; @@ -2044,7 +2088,7 @@ static void client_change_wm_state(ObClient *self) old = self->wmstate; - if (self->shaded || self->iconic || !self->frame->visible) + if (self->shaded || !self->frame->visible) self->wmstate = IconicState; else self->wmstate = NormalState; @@ -2088,7 +2132,7 @@ static void client_change_state(ObClient *self) if (self->demands_attention) netstate[num++] = prop_atoms.net_wm_state_demands_attention; if (self->undecorated) - netstate[num++] = prop_atoms.ob_wm_state_undecorated; + netstate[num++] = prop_atoms.openbox_wm_state_undecorated; PROP_SETA32(self->window, net_wm_state, atom, netstate, num); if (self->frame) @@ -2139,7 +2183,14 @@ static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; - if (self->fullscreen && + if ((self->fullscreen || + /* no decorations and fills the monitor means oldskool fullscreen */ + (self->frame != NULL && + (self->frame->size.top == 0 && self->frame->size.left == 0 && + self->frame->size.bottom == 0 && self->frame->size.right == 0 && + RECT_EQUAL(self->area, + *screen_physical_area_monitor(client_monitor(self)))))) + && (client_focused(self) || client_search_focus_tree(self))) l = OB_STACKING_LAYER_FULLSCREEN; else if (self->type == OB_CLIENT_TYPE_DESKTOP) @@ -2707,9 +2758,10 @@ static void client_iconify_recursive(ObClient *self, if (changed) { client_change_state(self); + if (ob_state() != OB_STATE_STARTING && config_animate_iconify) + frame_begin_iconify_animation(self->frame, iconic); + /* do this after starting the animation so it doesn't flash */ client_showhide(self); - if (STRUT_EXISTS(self->strut)) - screen_update_areas(); } /* iconify all direct transients, and deiconify all transients @@ -2723,7 +2775,7 @@ static void client_iconify_recursive(ObClient *self, void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk) { /* move up the transient chain as far as possible first */ - self = client_search_top_parent(self); + self = client_search_top_normal_parent(self); client_iconify_recursive(self, iconic, curdesk); } @@ -2918,7 +2970,7 @@ void client_set_desktop_recursive(ObClient *self, void client_set_desktop(ObClient *self, guint target, gboolean donthide) { - self = client_search_top_parent(self); + self = client_search_top_normal_parent(self); client_set_desktop_recursive(self, target, donthide); } @@ -3035,7 +3087,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) action = self->demands_attention ? prop_atoms.net_wm_state_remove : prop_atoms.net_wm_state_add; - else if (state == prop_atoms.ob_wm_state_undecorated) + else if (state == prop_atoms.openbox_wm_state_undecorated) action = undecorated ? prop_atoms.net_wm_state_remove : prop_atoms.net_wm_state_add; } @@ -3065,7 +3117,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) self->below = TRUE; } else if (state == prop_atoms.net_wm_state_demands_attention) { demands_attention = TRUE; - } else if (state == prop_atoms.ob_wm_state_undecorated) { + } else if (state == prop_atoms.openbox_wm_state_undecorated) { undecorated = TRUE; } @@ -3092,7 +3144,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) self->below = FALSE; } else if (state == prop_atoms.net_wm_state_demands_attention) { demands_attention = FALSE; - } else if (state == prop_atoms.ob_wm_state_undecorated) { + } else if (state == prop_atoms.openbox_wm_state_undecorated) { undecorated = FALSE; } } @@ -3234,6 +3286,47 @@ gboolean client_focus(ObClient *self) return TRUE; } +/*! Present the client to the user. + @param raise If the client should be raised or not. You should only set + raise to false if you don't care if the window is completely + hidden. +*/ +static void client_present(ObClient *self, gboolean here, gboolean raise) +{ + /* if using focus_delay, stop the timer now so that focus doesn't + go moving on us */ + event_halt_focus_delay(); + + if (client_normal(self) && screen_showing_desktop) + screen_show_desktop(FALSE, FALSE); + if (self->iconic) + client_iconify(self, FALSE, here); + if (self->desktop != DESKTOP_ALL && + self->desktop != screen_desktop) + { + if (here) + client_set_desktop(self, screen_desktop, FALSE); + else + screen_set_desktop(self->desktop, FALSE); + } else if (!self->frame->visible) + /* if its not visible for other reasons, then don't mess + with it */ + return; + if (self->shaded) + client_shade(self, FALSE); + + client_focus(self); + + if (raise) { + /* we do this as an action here. this is rather important. this is + because we want the results from the focus change to take place + BEFORE we go about raising the window. when a fullscreen window + loses focus, we need this or else the raise wont be able to raise + above the to-lose-focus fullscreen window. */ + client_raise(self); + } +} + void client_activate(ObClient *self, gboolean here, gboolean user) { guint32 last_time = focus_client ? focus_client->user_time : CurrentTime; @@ -3256,36 +3349,7 @@ void client_activate(ObClient *self, gboolean here, gboolean user) if (event_curtime != CurrentTime) self->user_time = event_curtime; - /* if using focus_delay, stop the timer now so that focus doesn't - go moving on us */ - event_halt_focus_delay(); - - if (client_normal(self) && screen_showing_desktop) - screen_show_desktop(FALSE); - if (self->iconic) - client_iconify(self, FALSE, here); - if (self->desktop != DESKTOP_ALL && - self->desktop != screen_desktop) - { - if (here) - client_set_desktop(self, screen_desktop, FALSE); - else - screen_set_desktop(self->desktop); - } else if (!self->frame->visible) - /* if its not visible for other reasons, then don't mess - with it */ - return; - if (self->shaded) - client_shade(self, FALSE); - - client_focus(self); - - /* we do this as an action here. this is rather important. this is - because we want the results from the focus change to take place - BEFORE we go about raising the window. when a fullscreen window - loses focus, we need this or else the raise wont be able to raise - above the to-lose-focus fullscreen window. */ - client_raise(self); + client_present(self, here, TRUE); } } @@ -3397,20 +3461,24 @@ guint client_monitor(ObClient *self) return screen_find_monitor(&self->frame->area); } -ObClient *client_search_top_parent(ObClient *self) +ObClient *client_search_top_normal_parent(ObClient *self) { while (self->transient_for && self->transient_for != OB_TRAN_GROUP && - client_normal(self)) + client_normal(self->transient_for)) self = self->transient_for; return self; } -GSList *client_search_all_top_parents(ObClient *self) +static GSList *client_search_all_top_parents_internal(ObClient *self, + gboolean bylayer, + ObStackingLayer layer) { GSList *ret = NULL; - + /* move up the direct transient chain as far as possible */ - while (self->transient_for && self->transient_for != OB_TRAN_GROUP) + while (self->transient_for && self->transient_for != OB_TRAN_GROUP && + (!bylayer || self->transient_for->layer == layer) && + client_normal(self->transient_for)) self = self->transient_for; if (!self->transient_for) @@ -3423,8 +3491,11 @@ GSList *client_search_all_top_parents(ObClient *self) for (it = self->group->members; it; it = g_slist_next(it)) { ObClient *c = it->data; - if (!c->transient_for && client_normal(c)) + if (!c->transient_for && client_normal(c) && + (!bylayer || c->layer == layer)) + { ret = g_slist_prepend(ret, c); + } } if (ret == NULL) /* no group parents */ @@ -3434,6 +3505,16 @@ GSList *client_search_all_top_parents(ObClient *self) return ret; } +GSList *client_search_all_top_parents(ObClient *self) +{ + return client_search_all_top_parents_internal(self, FALSE, 0); +} + +GSList *client_search_all_top_parents_layer(ObClient *self) +{ + return client_search_all_top_parents_internal(self, TRUE, self->layer); +} + ObClient *client_search_focus_parent(ObClient *self) { if (self->transient_for) { @@ -3499,15 +3580,25 @@ void client_update_sm_client_id(ObClient *self) self->sm_client_id = NULL; if (!PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id) && - self->group) - PROP_GETS(self->group->leader, sm_client_id, locale, - &self->sm_client_id); + self->group) { + ob_debug_type(OB_DEBUG_SM, "Client %s does not have session id\n", + self->title); + if (!PROP_GETS(self->group->leader, sm_client_id, locale, + &self->sm_client_id)) { + ob_debug_type(OB_DEBUG_SM, "Client %s does not have session id on " + "group window\n", self->title); + } else + ob_debug_type(OB_DEBUG_SM, "Client %s has session id on " + "group window\n", self->title); + } else + ob_debug_type(OB_DEBUG_SM, "Client %s has session id\n", + self->title); } #define WANT_EDGE(cur, c) \ if(cur == c) \ continue; \ - if(!client_normal(cur)) \ + if(!client_normal(cur)) \ continue; \ if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \ continue; \ @@ -3699,7 +3790,10 @@ ObClient* client_under_pointer() if (WINDOW_IS_CLIENT(it->data)) { ObClient *c = WINDOW_AS_CLIENT(it->data); if (c->frame->visible && - RECT_CONTAINS(c->frame->area, x, y)) { + /* ignore all animating windows */ + !frame_iconify_animating(c->frame) && + RECT_CONTAINS(c->frame->area, x, y)) + { ret = c; break; }