X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=ded81e3893a843eb2c24e3787de80457a8d9b83e;hb=f0fdba8ad36010280fc84c2425010c195b76562a;hp=f84291c14e6fbc5dc87ce9d25b3cbf78ca19b9a8;hpb=2c507a72070c2eba4a7bfa743a2b6d330539711f;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index f84291c1..ded81e38 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -57,17 +57,18 @@ 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 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 +76,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); @@ -105,20 +105,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); @@ -533,7 +533,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); } @@ -994,12 +994,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_command(self); client_update_strut(self); client_update_icons(self); client_update_user_time(self); @@ -1254,11 +1254,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); @@ -1573,10 +1575,15 @@ void client_setup_decor_and_functions(ObClient *self) 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; @@ -1858,34 +1865,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; @@ -2072,18 +2051,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; } } @@ -2094,9 +2150,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) { @@ -2254,23 +2312,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; @@ -2327,12 +2368,29 @@ gboolean client_normal(ObClient *self) { 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? */ @@ -2737,7 +2795,9 @@ static void client_iconify_recursive(ObClient *self, 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 @@ -2780,9 +2840,11 @@ 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_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) @@ -2932,7 +2994,8 @@ void client_hilite(ObClient *self, gboolean hilite) } void client_set_desktop_recursive(ObClient *self, - guint target, gboolean donthide) + guint target, + gboolean donthide) { guint old; GSList *it; @@ -2943,9 +3006,6 @@ void client_set_desktop_recursive(ObClient *self, 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); @@ -2959,12 +3019,6 @@ void client_set_desktop_recursive(ObClient *self, 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); } /* move all transients */ @@ -2974,7 +3028,8 @@ void client_set_desktop_recursive(ObClient *self, 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); @@ -3040,6 +3095,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) 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 || @@ -3116,11 +3173,11 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) } 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) { @@ -3145,9 +3202,9 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) } 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) { @@ -3192,6 +3249,12 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) 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 */ } @@ -3336,29 +3399,56 @@ static void client_present(ObClient *self, gboolean here, gboolean raise) 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); @@ -3580,43 +3670,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)) - 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; \ @@ -3829,17 +3882,3 @@ gboolean client_has_group_siblings(ObClient *self) { 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; -}