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)
{
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)) ||
*/
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);
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
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);
{
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)
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;
+ if (!self->session) return FALSE;
- it = g_list_find(session_saved_state, self->session);
- for (it = g_list_previous(it); it; it = g_list_previous(it)) {
+ mypos = g_list_find(session_saved_state, self->session);
+ if (!mypos) return FALSE;
+
+ /* 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)
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,
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;
}
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;
}
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,
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
/* 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);
}
}
}
old = self->wmstate;
- if (self->shaded || self->iconic || !frame_visible(self->frame))
+ if (self->shaded || !self->frame->visible)
self->wmstate = IconicState;
else
self->wmstate = NormalState;
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)
{
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)
if (changed) {
client_change_state(self);
- if (iconic) {
- if (ob_state() != OB_STATE_STARTING && config_animate_iconify) {
- /* delay the showhide until the window is done the animation */
- frame_begin_iconify_animation
- (self->frame, iconic,
- (ObFrameIconifyAnimateFunc)client_showhide, self);
- /* but focus a new window now please */
- focus_fallback(FALSE);
- } else
- client_showhide(self);
- } else {
- if (config_animate_iconify)
- /* the animation will show the window when it is hidden,
- but the window state needs to be adjusted after the
- animation finishes, so call showhide when it's done to make
- sure everything is updated appropriately
- */
- frame_begin_iconify_animation
- (self->frame, iconic,
- (ObFrameIconifyAnimateFunc)client_showhide, 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);
}
/* iconify all direct transients, and deiconify all transients
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);
}
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);
}
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;
}
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;
}
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;
}
}
/* choose the correct target */
self = client_focus_target(self);
- if (!frame_visible(self->frame))
+ if (!self->frame->visible)
return FALSE;
if (!(self->can_focus || self->focus_notify))
self = client_focus_target(self);
if (!client_can_focus(self)) {
- if (!frame_visible(self->frame)) {
+ if (!self->frame->visible) {
/* update the focus lists */
focus_order_to_top(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;
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, 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 (!frame_visible(self->frame))
- /* 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);
}
}
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)
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 */
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) {
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; \
for (it = stacking_list; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
- if (frame_visible(c->frame) &&
+ if (c->frame->visible &&
/* ignore all animating windows */
!frame_iconify_animating(c->frame) &&
RECT_CONTAINS(c->frame->area, x, y))