typedef struct
{
- ObClientDestructor func;
+ ObClientCallback func;
gpointer data;
-} Destructor;
+} ClientCallback;
-GList *client_list = NULL;
+GList *client_list = NULL;
-static GSList *client_destructors = 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);
static void client_get_startup_id(ObClient *self);
+static void client_get_session_ids(ObClient *self);
static void client_get_area(ObClient *self);
static void client_get_desktop(ObClient *self);
static void client_get_state(ObClient *self);
static void client_get_shaped(ObClient *self);
static void client_get_mwm_hints(ObClient *self);
static void client_get_gravity(ObClient *self);
-static void client_get_client_machine(ObClient *self);
static void client_get_colormap(ObClient *self);
static void client_get_transientness(ObClient *self);
static void client_change_allowed_actions(ObClient *self);
{
}
-void client_add_destructor(ObClientDestructor func, gpointer data)
+void client_add_destructor(ObClientCallback func, gpointer data)
{
- Destructor *d = g_new(Destructor, 1);
+ ClientCallback *d = g_new(ClientCallback, 1);
d->func = func;
d->data = data;
client_destructors = g_slist_prepend(client_destructors, d);
}
-void client_remove_destructor(ObClientDestructor func)
+void client_remove_destructor(ObClientCallback func)
{
GSList *it;
for (it = client_destructors; it; it = g_slist_next(it)) {
- Destructor *d = it->data;
+ ClientCallback *d = it->data;
if (d->func == func) {
g_free(d);
client_destructors = g_slist_delete_link(client_destructors, it);
}
}
+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;
screen_update_areas();
for (it = client_destructors; it; it = g_slist_next(it)) {
- Destructor *d = it->data;
+ ClientCallback *d = it->data;
d->func(self, d->data);
}
if (settings->fullscreen != -1)
self->fullscreen = !!settings->fullscreen;
- if (settings->desktop < screen_num_desktops
- || settings->desktop == DESKTOP_ALL)
- self->desktop = settings->desktop;
+ if (settings->desktop) {
+ if (settings->desktop == DESKTOP_ALL)
+ self->desktop = settings->desktop;
+ else if (settings->desktop > 0 &&
+ settings->desktop <= screen_num_desktops)
+ self->desktop = settings->desktop - 1;
+ }
if (settings->layer == -1) {
self->below = TRUE;
#ifdef SYNC
client_update_sync_request_counter(self);
#endif
- client_get_client_machine(self);
+
+ /* get the session related properties */
+ client_get_session_ids(self);
+
client_get_colormap(self);
client_update_title(self);
- client_update_class(self);
- client_update_sm_client_id(self);
- client_update_command(self);
client_update_strut(self);
client_update_icons(self);
client_update_user_time(self);
}
- /* If the group changed then we need to remove any old group transient
- windows from our children. But if we're transient for the group, then
+ /* If the group changed, or if we are just becoming transient for the
+ group, then we need to remove any old group transient windows
+ from our children. But if we were already transient for the group, then
other group transients are not our children. */
- if (oldgroup != newgroup && oldgroup != NULL &&
- oldparent != OB_TRAN_GROUP)
+ if ((oldgroup != newgroup ||
+ (newparent == OB_TRAN_GROUP && oldparent != newparent)) &&
+ oldgroup != NULL && oldparent != OB_TRAN_GROUP)
{
for (it = self->transients; it; it = next) {
next = g_slist_next(it);
self->icon_title = data;
}
-void client_update_class(ObClient *self)
-{
- gchar **data;
- gchar *s;
-
- if (self->name) g_free(self->name);
- if (self->class) g_free(self->class);
- if (self->role) g_free(self->role);
-
- self->name = self->class = self->role = NULL;
-
- if (PROP_GETSS(self->window, wm_class, locale, &data)) {
- if (data[0]) {
- self->name = g_strdup(data[0]);
- if (data[1])
- self->class = g_strdup(data[1]);
- }
- g_strfreev(data);
- }
-
- if (PROP_GETS(self->window, wm_window_role, locale, &s))
- self->role = s;
-
- if (self->name == NULL) self->name = g_strdup("");
- if (self->class == NULL) self->class = g_strdup("");
- if (self->role == NULL) self->role = g_strdup("");
-}
-
void client_update_strut(ObClient *self)
{
guint num;
}
}
-static void client_get_client_machine(ObClient *self)
+static void client_get_session_ids(ObClient *self)
{
- gchar *data = NULL;
- gchar localhost[128];
+ guint32 leader;
+ gboolean got;
+ gchar *s;
+ gchar **ss;
- g_free(self->client_machine);
+ if (!PROP_GET32(self->window, wm_client_leader, window, &leader))
+ leader = None;
+
+ /* get the SM_CLIENT_ID */
+ got = FALSE;
+ if (leader)
+ got = PROP_GETS(leader, sm_client_id, locale, &self->sm_client_id);
+ if (!got)
+ PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id);
+
+ /* get the WM_CLASS (name and class). make them "" if they are not
+ provided */
+ got = FALSE;
+ if (leader)
+ got = PROP_GETSS(leader, wm_class, locale, &ss);
+ if (!got)
+ got = PROP_GETSS(self->window, wm_class, locale, &ss);
+
+ if (got) {
+ if (ss[0]) {
+ self->name = g_strdup(ss[0]);
+ if (ss[1])
+ self->class = g_strdup(ss[1]);
+ }
+ g_strfreev(ss);
+ }
+
+ if (self->name == NULL) self->name = g_strdup("");
+ if (self->class == NULL) self->class = g_strdup("");
+
+ /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
+ got = FALSE;
+ if (leader)
+ got = PROP_GETS(leader, wm_window_role, locale, &s);
+ if (!got)
+ got = PROP_GETS(self->window, wm_window_role, locale, &s);
+
+ if (got)
+ self->role = s;
+ else
+ self->role = g_strdup("");
+
+ /* get the WM_COMMAND */
+ got = FALSE;
+
+ if (leader)
+ got = PROP_GETSS(leader, wm_command, locale, &ss);
+ if (!got)
+ got = PROP_GETSS(self->window, wm_command, locale, &ss);
+
+ if (got) {
+ /* merge/mash them all together */
+ gchar *merge = NULL;
+ gint i;
+
+ for (i = 0; ss[i]; ++i) {
+ gchar *tmp = merge;
+ if (merge)
+ merge = g_strconcat(merge, ss[i], NULL);
+ else
+ merge = g_strconcat(ss[i], NULL);
+ g_free(tmp);
+ }
+ g_strfreev(ss);
+
+ self->wm_command = merge;
+ }
+
+ /* get the WM_CLIENT_MACHINE */
+ got = FALSE;
+ if (leader)
+ got = PROP_GETS(leader, wm_client_machine, locale, &s);
+ if (!got)
+ got = PROP_GETS(self->window, wm_client_machine, locale, &s);
+
+ if (got) {
+ gchar localhost[128];
- if (PROP_GETS(self->window, wm_client_machine, locale, &data)) {
gethostname(localhost, 127);
localhost[127] = '\0';
- if (strcmp(localhost, data))
- self->client_machine = data;
+ if (strcmp(localhost, s) != 0)
+ self->client_machine = s;
}
}
old = self->wmstate;
- if (self->shaded || !self->frame->visible)
+ if (self->shaded || self->iconic ||
+ (self->desktop != DESKTOP_ALL && self->desktop != screen_desktop))
+ {
self->wmstate = IconicState;
- else
+ } else
self->wmstate = NormalState;
if (old != self->wmstate) {
return FALSE;
if (client_normal(self) && screen_showing_desktop)
return FALSE;
- /*
- if (self->transient_for) {
- if (self->transient_for != OB_TRAN_GROUP)
- return client_should_show(self->transient_for);
- else {
- GSList *it;
-
- for (it = self->group->members; it; it = g_slist_next(it)) {
- ObClient *c = it->data;
- if (c != self && !c->transient_for) {
- if (client_should_show(c))
- return TRUE;
- }
- }
- }
- }
- */
if (self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
return TRUE;
if (curdesk && self->desktop != screen_desktop &&
self->desktop != DESKTOP_ALL)
- client_set_desktop(self, screen_desktop, FALSE);
+ client_set_desktop(self, screen_desktop, FALSE, FALSE);
/* this puts it after the current focused window */
focus_order_remove(self);
}
void client_set_desktop_recursive(ObClient *self,
- guint target, gboolean donthide)
+ guint target,
+ gboolean donthide,
+ gboolean focus_nonintrusive)
{
guint old;
GSList *it;
g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
/* remove from the old desktop(s) */
- focus_order_remove(self);
+ if (!focus_nonintrusive)
+ focus_order_remove(self);
old = self->desktop;
self->desktop = target;
screen_update_areas();
/* add to the new desktop(s) */
- if (config_focus_new)
- focus_order_to_top(self);
- else
- focus_order_to_bottom(self);
+ if (!focus_nonintrusive) {
+ 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 */
for (it = self->transients; it; it = g_slist_next(it))
if (it->data != self)
if (client_is_direct_child(self, it->data))
- client_set_desktop_recursive(it->data, target, donthide);
+ client_set_desktop_recursive(it->data, target,
+ donthide, focus_nonintrusive);
}
-void client_set_desktop(ObClient *self, guint target, gboolean donthide)
+void client_set_desktop(ObClient *self, guint target,
+ gboolean donthide, gboolean focus_nonintrusive)
{
self = client_search_top_normal_parent(self);
- client_set_desktop_recursive(self, target, donthide);
+ client_set_desktop_recursive(self, target, donthide, focus_nonintrusive);
}
gboolean client_is_direct_child(ObClient *parent, ObClient *child)
self->desktop != screen_desktop)
{
if (here)
- client_set_desktop(self, screen_desktop, FALSE);
+ client_set_desktop(self, screen_desktop, FALSE, FALSE);
else
screen_set_desktop(self->desktop, FALSE);
} else if (!self->frame->visible)
}
}
+static void client_bring_non_application_windows_recursive(ObClient *self,
+ guint desktop)
+{
+ GSList *it;
+
+ for (it = self->transients; it; it = g_slist_next(it))
+ client_bring_non_application_windows_recursive(it->data, desktop);
+
+ if (client_normal(self) && !client_application(self) &&
+ self->desktop != desktop && self->desktop != DESKTOP_ALL)
+ {
+ client_set_desktop(self, desktop, FALSE, TRUE);
+ }
+}
+
+void client_bring_non_application_windows(ObClient *self)
+{
+ client_bring_non_application_windows_recursive(self, self->desktop);
+}
+
void client_raise(ObClient *self)
{
action_run_string("Raise", self, CurrentTime);
return NULL;
}
-void client_update_sm_client_id(ObClient *self)
-{
- g_free(self->sm_client_id);
- self->sm_client_id = NULL;
-
- if (!PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id))
- if (self->group)
- PROP_GETS(self->group->leader, sm_client_id, locale,
- &self->sm_client_id);
-}
-
-void client_update_command(ObClient *self)
-{
- gchar **data;
-
- g_free(self->wm_command);
- self->wm_command = NULL;
-
- if (PROP_GETSS(self->window, wm_command, locale, &data)) {
- /* merge/mash them all together */
- gchar *merge = NULL;
- gint i;
-
- for (i = 0; data[i]; ++i) {
- gchar *tmp = merge;
- if (merge)
- merge = g_strconcat(merge, data[i], NULL);
- else
- merge = g_strconcat(data[i], NULL);
- g_free(tmp);
- }
- g_strfreev(data);
-
- self->wm_command = merge;
- }
-}
-
#define WANT_EDGE(cur, c) \
if(cur == c) \
continue; \