X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fopenbox;a=blobdiff_plain;f=openbox%2Fclient.c;h=1478d840f832265471d208fac1fead0b3199ec64;hp=c9cd076334c3076d25149d2cb5ea70c1362b2acd;hb=9325c92056ff4268db2263cdf8c07bb529e158aa;hpb=aa15563feeee03d7748e7d5279decf60db23fda9 diff --git a/openbox/client.c b/openbox/client.c index c9cd0763..1478d840 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -112,6 +112,8 @@ static gboolean client_can_steal_focus(ObClient *self, gboolean allow_other_desktop, gboolean request_from_user, Time steal_time, Time launch_time); +static void client_setup_default_decor_and_functions(ObClient *self); +static void client_setup_decor_undecorated(ObClient *self); void client_startup(gboolean reconfig) { @@ -165,6 +167,21 @@ void client_remove_destroy_notify(ObClientCallback func) } } +void client_remove_destroy_notify_data(ObClientCallback func, gpointer data) +{ + GSList *it; + + for (it = client_destroy_notifies; it; it = g_slist_next(it)) { + ClientCallback *d = it->data; + if (d->func == func && d->data == data) { + g_slice_free(ClientCallback, d); + client_destroy_notifies = + g_slist_delete_link(client_destroy_notifies, it); + break; + } + } +} + void client_set_list(void) { Window *windows, *win_it; @@ -201,6 +218,7 @@ void client_manage(Window window, ObPrompt *prompt) Time launch_time; guint32 user_time; gboolean obplaced; + gulong ignore_start; ob_debug("Managing window: 0x%lx", window); @@ -232,12 +250,26 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Window group: 0x%x", self->group?self->group->leader:0); ob_debug("Window name: %s class: %s role: %s title: %s", self->name, self->class, self->role, self->title); + ob_debug("Window group name: %s group class: %s", + self->group_name, self->group_class); /* per-app settings override stuff from client_get_all, and return the settings for other uses too. the returned settings is a shallow copy, that needs to be freed with g_free(). */ settings = client_get_settings_state(self); + /* the session should get the last say though */ + client_restore_session_state(self); + + /* the per-app settings/session may have changed the decorations for + the window, so we setup decorations for that here. this is a special + case because we want to place the window according to these decoration + changes. + we do this before setting up the frame so that it will reflect the + decorations of the window as it will be placed on screen. + */ + client_setup_decor_undecorated(self); + /* specify that if we exit, the window should not be destroyed and should be reparented back to root automatically, unless we are managing an internal ObPrompt window */ @@ -253,9 +285,6 @@ void client_manage(Window window, ObPrompt *prompt) time now */ grab_server(FALSE); - /* the session should get the last say though */ - client_restore_session_state(self); - /* this needs to occur once we have a frame, since it sets a property on the frame */ client_update_opacity(self); @@ -341,8 +370,7 @@ void client_manage(Window window, ObPrompt *prompt) "program + user specified" : "BADNESS !?")))), place.width, place.height); - obplaced = place_client(self, do_activate, &place.x, &place.y, - settings); + obplaced = place_client(self, do_activate, &place, settings); /* watch for buggy apps that ask to be placed at (0,0) when there is a strut there */ @@ -457,19 +485,13 @@ void client_manage(Window window, ObPrompt *prompt) /* grab mouse bindings before showing the window */ mouse_grab_for_client(self, TRUE); + if (!config_focus_under_mouse) + ignore_start = event_start_ignore_all_enters(); + /* this has to happen before we try focus the window, but we want it to happen after the client's stacking has been determined or it looks bad */ - { - gulong ignore_start; - if (!config_focus_under_mouse) - ignore_start = event_start_ignore_all_enters(); - - client_show(self); - - if (!config_focus_under_mouse) - event_end_ignore_all_enters(ignore_start); - } + client_show(self); /* activate/hilight/raise the window */ if (try_activate) { @@ -497,6 +519,9 @@ void client_manage(Window window, ObPrompt *prompt) stacking_raise(CLIENT_AS_WINDOW(self)); } + if (!config_focus_under_mouse) + event_end_ignore_all_enters(ignore_start); + /* add to client list/map */ client_list = g_list_append(client_list, self); window_add(&self->window, CLIENT_AS_WINDOW(self)); @@ -699,6 +724,8 @@ void client_unmanage(ObClient *self) g_free(self->name); g_free(self->class); g_free(self->role); + g_free(self->group_name); + g_free(self->group_class); g_free(self->client_machine); g_free(self->sm_client_id); g_slice_free(ObClient, self); @@ -891,15 +918,25 @@ static ObAppSettings *client_get_settings_state(ObClient *self) g_assert(app->name != NULL || app->class != NULL || app->role != NULL || app->title != NULL || + app->group_name != NULL || app->group_class != NULL || (signed)app->type >= 0); if (app->name && !g_pattern_match(app->name, strlen(self->name), self->name, NULL)) match = FALSE; + else if (app->group_name && + !g_pattern_match(app->group_name, + strlen(self->group_name), self->group_name, NULL)) + match = FALSE; else if (app->class && !g_pattern_match(app->class, strlen(self->class), self->class, NULL)) match = FALSE; + else if (app->group_class && + !g_pattern_match(app->group_class, + strlen(self->group_class), self->group_class, + NULL)) + match = FALSE; else if (app->role && !g_pattern_match(app->role, strlen(self->role), self->role, NULL)) @@ -948,6 +985,9 @@ static ObAppSettings *client_get_settings_state(ObClient *self) self->desktop = settings->desktop - 1; } + if (settings->opacity != -1) + self->opacity = settings->opacity; + if (settings->layer == -1) { self->below = TRUE; self->above = FALSE; @@ -1006,6 +1046,8 @@ static void client_restore_session_state(ObClient *self) self->max_horz = self->session->max_horz; self->max_vert = self->session->max_vert; self->undecorated = self->session->undecorated; + + self->opacity = self->session->opacity; } static gboolean client_restore_session_stacking(ObClient *self) @@ -1177,11 +1219,8 @@ static void client_get_all(ObClient *self, gboolean real) client_get_type_and_transientness(self); client_update_normal_hints(self); - /* set up the decor/functions before getting the state. the states may - affect which functions are available, but we want to know the maximum - decor/functions are available to this window, so we can then apply them - in client_apply_startup_state() */ - client_setup_decor_and_functions(self, FALSE); + /* set up the maximum possible decor/functions */ + client_setup_default_decor_and_functions(self); client_get_state(self); @@ -1189,13 +1228,15 @@ static void client_get_all(ObClient *self, gboolean real) from per-app settings */ client_get_session_ids(self); - /* now we got everything that can affect the decorations */ + /* get this early so we have it for debugging, also this can be used + by app rule matching */ + client_update_title(self); + + /* now we got everything that can affect the decorations or app rule + matching */ if (!real) return; - /* get this early so we have it for debugging */ - client_update_title(self); - /* save the values of the variables used for app rule matching */ client_save_app_rule_values(self); @@ -1735,7 +1776,7 @@ void client_update_normal_hints(ObClient *self) ob_debug("Normal hints: not set"); } -void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) +static void client_setup_default_decor_and_functions(ObClient *self) { /* start with everything (cept fullscreen) */ self->decorations = @@ -1868,6 +1909,23 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) self->functions &= ~OB_CLIENT_FUNC_MAXIMIZE; self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE; } +} + +/*! Set up decor for a client based on its undecorated state. */ +static void client_setup_decor_undecorated(ObClient *self) +{ + /* If the user requested no decorations, then remove all the decorations, + except the border. But don't add a border if there wasn't one. */ + if (self->undecorated) + self->decorations &= (config_theme_keepborder ? + OB_FRAME_DECOR_BORDER : 0); +} + +void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) +{ + client_setup_default_decor_and_functions(self); + + client_setup_decor_undecorated(self); if (self->max_horz && self->max_vert) { /* once upon a time you couldn't resize maximized windows, that is not @@ -1877,12 +1935,6 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS); } - /* finally, the user can have requested no decorations, which overrides - everything (but doesnt give it a border if it doesnt have one) */ - if (self->undecorated) - self->decorations &= (config_theme_keepborder ? - OB_FRAME_DECOR_BORDER : 0); - /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) self->functions &= ~OB_CLIENT_FUNC_SHADE; @@ -2333,6 +2385,25 @@ static void client_get_session_ids(ObClient *self) if (self->name == NULL) self->name = g_strdup(""); if (self->class == NULL) self->class = g_strdup(""); + /* get the WM_CLASS (name and class) from the group leader. make them "" if + they are not provided */ + if (leader) + got = OBT_PROP_GETSS_TYPE(leader, WM_CLASS, STRING_NO_CC, &ss); + else + got = FALSE; + + if (got) { + if (ss[0]) { + self->group_name = g_strdup(ss[0]); + if (ss[1]) + self->group_class = g_strdup(ss[1]); + } + g_strfreev(ss); + } + + if (self->group_name == NULL) self->group_name = g_strdup(""); + if (self->group_class == NULL) self->group_class = g_strdup(""); + /* get the WM_WINDOW_ROLE. make it "" if it is not provided */ got = OBT_PROP_GETS_XPCS(self->window, WM_WINDOW_ROLE, &s); @@ -2402,6 +2473,8 @@ static void client_save_app_rule_values(ObClient *self) OBT_PROP_SETS(self->window, OB_APP_ROLE, self->role); OBT_PROP_SETS(self->window, OB_APP_NAME, self->name); OBT_PROP_SETS(self->window, OB_APP_CLASS, self->class); + OBT_PROP_SETS(self->window, OB_APP_GROUP_NAME, self->group_name); + OBT_PROP_SETS(self->window, OB_APP_GROUP_CLASS, self->group_class); OBT_PROP_SETS(self->window, OB_APP_TITLE, self->original_title); switch (self->type) { @@ -2742,6 +2815,12 @@ gboolean client_helper(ObClient *self) self->type == OB_CLIENT_TYPE_TOOLBAR); } +gboolean client_occupies_space(ObClient *self) +{ + return !(self->type == OB_CLIENT_TYPE_DESKTOP || + self->type == OB_CLIENT_TYPE_SPLASH); +} + gboolean client_mouse_focusable(ObClient *self) { return !(self->type == OB_CLIENT_TYPE_MENU || @@ -2768,6 +2847,7 @@ static void client_apply_startup_state(ObClient *self, gboolean demands_attention = self->demands_attention; gboolean max_horz = self->max_horz; gboolean max_vert = self->max_vert; + guint8 opacity = self->opacity; Rect oldarea; gint l; @@ -2814,6 +2894,12 @@ static void client_apply_startup_state(ObClient *self, if (fullscreen) client_fullscreen(self, TRUE); + /* make sure client_setup_decor_and_functions() is called at least once */ + client_setup_decor_and_functions(self, FALSE); + + /* make the client semi-transparent */ + client_set_opacity(self, opacity); + /* if the window hasn't been configured yet, then do so now, in fact the x,y,w,h may _not_ be the same as the area rect, which can end up meaning that the client isn't properly moved/resized by the fullscreen @@ -2908,10 +2994,11 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, /* cap any X windows at the size of an unsigned short */ *w = MIN(*w, - G_MAXUSHORT - self->frame->size.left - self->frame->size.right); + (gint)G_MAXUSHORT + - self->frame->size.left - self->frame->size.right); *h = MIN(*h, - G_MAXUSHORT - self->frame->size.top - self->frame->size.bottom); - + (gint)G_MAXUSHORT + - self->frame->size.top - self->frame->size.bottom); /* gets the frame's position */ frame_client_gravity(self->frame, x, y); @@ -3701,6 +3788,12 @@ void client_set_desktop(ObClient *self, guint target, focus_cycle_addremove(NULL, TRUE); } +void client_set_opacity(ObClient *self, guint8 opacity) +{ + OBT_PROP_SET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL, + opacity * 16777216); +} + gboolean client_is_direct_child(ObClient *parent, ObClient *child) { while (child != parent && (child = client_direct_parent(child)));