X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=0d74882ce87abf53cee7df2157d4f455d21665df;hb=280529221e9349aa07c6c498df6b80b3a8951198;hp=17d4c4a102bccd10216372b12272dc09a6fe743b;hpb=1bf9de380991206d4afa104cd31c567583f288c2;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 17d4c4a1..0d74882c 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -57,17 +57,19 @@ 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); @@ -75,7 +77,6 @@ static void client_get_layer(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); @@ -90,6 +91,9 @@ static void client_update_transient_tree(ObClient *self, 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) { @@ -102,20 +106,20 @@ void client_shutdown(gboolean reconfig) { } -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); @@ -124,6 +128,29 @@ void client_remove_destructor(ObClientDestructor func) } } +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; @@ -530,7 +557,7 @@ void client_unmanage(ObClient *self) 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); } @@ -609,6 +636,7 @@ void client_unmanage(ObClient *self) g_free(self->icons[j].data); if (self->nicons > 0) g_free(self->icons); + g_free(self->wm_command); g_free(self->title); g_free(self->icon_title); g_free(self->name); @@ -635,13 +663,13 @@ static ObAppSettings *client_get_settings_state(ObClient *self) || (app->class && app->name && !strcmp(app->class, self->class) && !strcmp(app->name, self->name))) { - ob_debug("Window matching: %s\n", app->name); /* Match if no role was specified in the per app setting, or if the * string matches the beginning of the role, since apps like to set * the role to things like browser-window-23c4b2f */ if (!app->role || !strncmp(app->role, self->role, strlen(app->role))) { + ob_debug("Window matching: %s\n", app->name); /* use this one */ settings = app; break; @@ -669,9 +697,13 @@ static ObAppSettings *client_get_settings_state(ObClient *self) 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; @@ -815,7 +847,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, @@ -829,20 +861,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; } @@ -984,11 +1018,12 @@ static void client_get_all(ObClient *self) #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_strut(self); client_update_icons(self); client_update_user_time(self); @@ -1243,11 +1278,13 @@ static void client_update_transient_tree(ObClient *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); @@ -1847,34 +1884,6 @@ void client_update_title(ObClient *self) 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; @@ -2061,18 +2070,95 @@ void client_update_icon_geometry(ObClient *self) } } -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; } } @@ -2083,9 +2169,11 @@ static void client_change_wm_state(ObClient *self) 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) { @@ -2178,15 +2266,22 @@ static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; - if (self->fullscreen && - (client_focused(self) || client_search_focus_tree(self))) - l = OB_STACKING_LAYER_FULLSCREEN; - else if (self->type == OB_CLIENT_TYPE_DESKTOP) + if (self->type == OB_CLIENT_TYPE_DESKTOP) l = OB_STACKING_LAYER_DESKTOP; else if (self->type == OB_CLIENT_TYPE_DOCK) { if (self->below) l = OB_STACKING_LAYER_NORMAL; else l = OB_STACKING_LAYER_ABOVE; } + else if ((self->fullscreen || + /* no decorations and fills the monitor = oldskool fullscreen */ + (self->frame != NULL && + (self->frame->size.right == 0 && self->frame->size.left == 0 && + self->frame->size.bottom == 0 && self->frame->size.top == 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->above) l = OB_STACKING_LAYER_ABOVE; else if (self->below) l = OB_STACKING_LAYER_BELOW; else l = OB_STACKING_LAYER_NORMAL; @@ -2236,23 +2331,6 @@ gboolean client_should_show(ObClient *self) 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; @@ -2763,7 +2841,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); } @@ -2947,6 +3025,12 @@ void client_set_desktop_recursive(ObClient *self, focus_order_to_top(self); else focus_order_to_bottom(self); + + /* call the notifies */ + for (it = client_desktop_notifies; it; it = g_slist_next(it)) { + ClientCallback *d = it->data; + d->func(self, d->data); + } } /* move all transients */ @@ -2958,7 +3042,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); } @@ -3295,7 +3379,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise) if (here) client_set_desktop(self, screen_desktop, FALSE); else - screen_set_desktop(self->desktop); + screen_set_desktop(self->desktop, FALSE); } else if (!self->frame->visible) /* if its not visible for other reasons, then don't mess with it */ @@ -3449,20 +3533,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) @@ -3475,8 +3563,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 */ @@ -3486,6 +3577,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) { @@ -3545,27 +3646,6 @@ ObClient *client_search_transient(ObClient *self, ObClient *search) 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) && - 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; \