GList *client_list = NULL;
static GSList *client_destructors = NULL;
-static GSList *client_desktop_notifies = NULL;
static void client_get_all(ObClient *self);
static void client_toggle_border(ObClient *self, gboolean show);
}
}
-void client_add_desktop_notify(ObClientCallback func, gpointer data)
-{
- ClientCallback *d = g_new(ClientCallback, 1);
- d->func = func;
- d->data = data;
- client_desktop_notifies = g_slist_prepend(client_desktop_notifies, d);
-}
-
-void client_remove_desktop_notify(ObClientCallback func)
-{
- GSList *it;
-
- for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
- ClientCallback *d = it->data;
- if (d->func == func) {
- g_free(d);
- client_desktop_notifies =
- g_slist_delete_link(client_desktop_notifies, it);
- break;
- }
- }
-}
-
void client_set_list()
{
Window *windows, *win_it;
self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE);
break;
+ case OB_CLIENT_TYPE_SPLASH:
+ /* these don't get get any decorations, and the only thing you can
+ do with them is move them */
+ self->decorations = 0;
+ self->functions = OB_CLIENT_FUNC_MOVE;
+
case OB_CLIENT_TYPE_DESKTOP:
case OB_CLIENT_TYPE_DOCK:
- case OB_CLIENT_TYPE_SPLASH:
- /* none of these windows are manipulated by the window manager */
+ /* these windows are not manipulated by the window manager */
self->decorations = 0;
self->functions = 0;
break;
self->type == OB_CLIENT_TYPE_SPLASH);
}
-gboolean client_application(ObClient *self)
+gboolean client_helper(ObClient *self)
{
- return (self->type == OB_CLIENT_TYPE_NORMAL ||
- self->type == OB_CLIENT_TYPE_DIALOG);
+ return (self->type == OB_CLIENT_TYPE_UTILITY ||
+ self->type == OB_CLIENT_TYPE_MENU ||
+ self->type == OB_CLIENT_TYPE_TOOLBAR);
}
+gboolean client_mouse_focusable(ObClient *self)
+{
+ return !(self->type == OB_CLIENT_TYPE_MENU ||
+ self->type == OB_CLIENT_TYPE_TOOLBAR ||
+ self->type == OB_CLIENT_TYPE_SPLASH ||
+ self->type == OB_CLIENT_TYPE_DOCK);
+}
+
+gboolean client_enter_focusable(ObClient *self)
+{
+ /* you can focus desktops but it shouldn't on enter */
+ return (client_mouse_focusable(self) &&
+ self->type != OB_CLIENT_TYPE_DESKTOP);
+}
+
+
static void client_apply_startup_state(ObClient *self, gint x, gint y)
{
gboolean pos = FALSE; /* has the window's position been configured? */
pos = TRUE;
}
- /* if the client didn't get positioned yet, then do so now
+ /* if the client didn't get positioned yet, then do so now.
call client_move even if the window is not being moved anywhere, because
when we reparent it and decorate it, it is getting moved and we need to
be telling it so with a ConfigureNotify event.
self->window);
if (iconic) {
- if (self->functions & OB_CLIENT_FUNC_ICONIFY) {
+ /* don't let non-normal windows iconify along with their parents
+ or whatever */
+ if (client_normal(self)) {
self->iconic = iconic;
/* update the focus lists.. iconic windows go to the bottom of
void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
{
- /* move up the transient chain as far as possible first */
- self = client_search_top_normal_parent(self);
- client_iconify_recursive(self, iconic, curdesk);
+ if (self->functions & OB_CLIENT_FUNC_ICONIFY || !iconic) {
+ /* move up the transient chain as far as possible first */
+ self = client_search_top_normal_parent(self);
+ client_iconify_recursive(self, iconic, curdesk);
+ }
}
void client_maximize(ObClient *self, gboolean max, gint dir)
}
void client_set_desktop_recursive(ObClient *self,
- guint target, gboolean donthide)
+ guint target,
+ gboolean donthide)
{
guint old;
GSList *it;
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);
client_raise(self);
if (STRUT_EXISTS(self->strut))
screen_update_areas();
-
- /* add to the new desktop(s) */
- if (config_focus_new)
- focus_order_to_top(self);
- else
- focus_order_to_bottom(self);
-
- /* call the notifies */
- GSList *it;
- for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
- ClientCallback *d = it->data;
- d->func(self, d->data);
- }
}
/* move all transients */
client_set_desktop_recursive(it->data, target, donthide);
}
-void client_set_desktop(ObClient *self, guint target, gboolean donthide)
+void client_set_desktop(ObClient *self, guint target,
+ gboolean donthide)
{
self = client_search_top_normal_parent(self);
client_set_desktop_recursive(self, target, donthide);
gboolean modal = self->modal;
gboolean iconic = self->iconic;
gboolean demands_attention = self->demands_attention;
+ gboolean above = self->above;
+ gboolean below = self->below;
gint i;
if (!(action == prop_atoms.net_wm_state_add ||
} else if (state == prop_atoms.net_wm_state_fullscreen) {
fullscreen = TRUE;
} else if (state == prop_atoms.net_wm_state_above) {
- self->above = TRUE;
- self->below = FALSE;
+ above = TRUE;
+ below = FALSE;
} else if (state == prop_atoms.net_wm_state_below) {
- self->above = FALSE;
- self->below = TRUE;
+ above = FALSE;
+ below = TRUE;
} else if (state == prop_atoms.net_wm_state_demands_attention) {
demands_attention = TRUE;
} else if (state == prop_atoms.openbox_wm_state_undecorated) {
} else if (state == prop_atoms.net_wm_state_fullscreen) {
fullscreen = FALSE;
} else if (state == prop_atoms.net_wm_state_above) {
- self->above = FALSE;
+ above = FALSE;
} else if (state == prop_atoms.net_wm_state_below) {
- self->below = FALSE;
+ below = FALSE;
} else if (state == prop_atoms.net_wm_state_demands_attention) {
demands_attention = FALSE;
} else if (state == prop_atoms.openbox_wm_state_undecorated) {
if (demands_attention != self->demands_attention)
client_hilite(self, demands_attention);
+ if (above != self->above || below != self->below) {
+ self->above = above;
+ self->below = below;
+ client_calc_layer(self);
+ }
+
client_change_state(self); /* change the hint to reflect these changes */
}
void client_activate(ObClient *self, gboolean here, gboolean user)
{
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
+ gboolean allow = FALSE;
- /* XXX do some stuff here if user is false to determine if we really want
- to activate it or not (a parent or group member is currently
- active)?
+ /* if the request came from the user, or if nothing is focused, then grant
+ the request.
+ if the currently focused app doesn't set a user_time, then it can't
+ benefit from any focus stealing prevention.
*/
+ if (user || !focus_client || !last_time)
+ allow = TRUE;
+ /* otherwise, if they didn't give a time stamp or if it is too old, they
+ don't get focus */
+ else
+ allow = event_curtime && event_time_after(event_curtime, last_time);
+
ob_debug_type(OB_DEBUG_FOCUS,
"Want to activate window 0x%x with time %u (last time %u), "
- "source=%s\n",
+ "source=%s allowing? %d\n",
self->window, event_curtime, last_time,
- (user ? "user" : "application"));
+ (user ? "user" : "application"), allow);
- if (!user && event_curtime && last_time &&
- !event_time_after(event_curtime, last_time))
- {
- client_hilite(self, TRUE);
- } else {
+ if (allow) {
if (event_curtime != CurrentTime)
self->user_time = event_curtime;
client_present(self, here, TRUE);
+ } else
+ /* don't focus it but tell the user it wants attention */
+ client_hilite(self, TRUE);
+}
+
+static void client_bring_helper_windows_recursive(ObClient *self,
+ guint desktop)
+{
+ GSList *it;
+
+ for (it = self->transients; it; it = g_slist_next(it))
+ client_bring_helper_windows_recursive(it->data, desktop);
+
+ if (client_helper(self) &&
+ self->desktop != desktop && self->desktop != DESKTOP_ALL)
+ {
+ client_set_desktop(self, desktop, FALSE);
}
}
+void client_bring_helper_windows(ObClient *self)
+{
+ client_bring_helper_windows_recursive(self, self->desktop);
+}
+
void client_raise(ObClient *self)
{
action_run_string("Raise", self, CurrentTime);
{
return self->group && self->group->members->next;
}
-
-gboolean client_has_application_group_siblings(ObClient *self)
-{
- GSList *it;
-
- if (!self->group) return FALSE;
-
- for (it = self->group->members; it; it = g_slist_next(it)) {
- ObClient *c = it->data;
- if (c != self && client_application(c))
- return TRUE;
- }
- return FALSE;
-}