diff --git a/data/rc.xml b/data/rc.xml index 209cc2dc..7c37928e 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -652,6 +652,8 @@ 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, @@ -723,6 +725,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); @@ -915,15 +919,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)) @@ -2365,6 +2379,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); @@ -2434,6 +2467,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) { diff --git a/openbox/client.h b/openbox/client.h index 5a20822f..0e55c59f 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -127,6 +127,10 @@ struct _ObClient gchar *class; /*! The specified role of the window, used for identification */ gchar *role; + /*! The application that created the window's group. */ + gchar *group_name; + /*! The class of the window's group, can used for grouping */ + gchar *group_class; /*! The session client id for the window. *This can be NULL!* */ gchar *sm_client_id; diff --git a/openbox/config.c b/openbox/config.c index 0d9eb689..d5ff8c45 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -215,8 +215,9 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d) { xmlNodePtr app = obt_xml_find_node(node->children, "application"); gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL, - *type_str = NULL; - gboolean name_set, class_set, type_set, role_set, title_set; + *type_str = NULL, *group_name = NULL, *group_class = NULL; + gboolean name_set, class_set, type_set, role_set, title_set, + group_name_set, group_class_set; ObClientType type; gboolean x_pos_given; @@ -225,6 +226,8 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d) class_set = obt_xml_attr_string(app, "class", &class); name_set = obt_xml_attr_string(app, "name", &name); + group_class_set = obt_xml_attr_string(app, "groupclass", &group_class); + group_name_set = obt_xml_attr_string(app, "groupname", &group_name); type_set = obt_xml_attr_string(app, "type", &type_str); role_set = obt_xml_attr_string(app, "role", &role); title_set = obt_xml_attr_string(app, "title", &title); @@ -251,7 +254,9 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d) type_set = FALSE; /* not valid! */ } - if (class_set || name_set || role_set || title_set || type_set) { + if (class_set || name_set || role_set || title_set || type_set || + group_class_set || group_name_set) + { xmlNodePtr n, c; ObAppSettings *settings = config_create_app_settings(); @@ -261,6 +266,12 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d) if (class_set) settings->class = g_pattern_spec_new(class); + if (group_name_set) + settings->group_name = g_pattern_spec_new(group_name); + + if (group_class_set) + settings->group_class = g_pattern_spec_new(group_class); + if (role_set) settings->role = g_pattern_spec_new(role); @@ -377,10 +388,13 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d) (gpointer) settings); g_free(name); g_free(class); + g_free(group_name); + g_free(group_class); g_free(role); g_free(title); g_free(type_str); - name = class = role = title = type_str = NULL; + name = class = group_name = group_class = role = title = type_str = + NULL; } app = obt_xml_find_node(app->next, "application"); @@ -1132,10 +1146,12 @@ void config_shutdown(void) for (it = config_per_app_settings; it; it = g_slist_next(it)) { ObAppSettings *itd = (ObAppSettings *)it->data; - if (itd->name) g_pattern_spec_free(itd->name); - if (itd->role) g_pattern_spec_free(itd->role); + if (itd->name) g_pattern_spec_free(itd->name); + if (itd->role) g_pattern_spec_free(itd->role); if (itd->title) g_pattern_spec_free(itd->title); if (itd->class) g_pattern_spec_free(itd->class); + if (itd->group_name) g_pattern_spec_free(itd->group_name); + if (itd->group_class) g_pattern_spec_free(itd->group_class); g_slice_free(ObAppSettings, it->data); } g_slist_free(config_per_app_settings); diff --git a/openbox/config.h b/openbox/config.h index 730dc39a..43386d3c 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -38,6 +38,8 @@ struct _ObAppSettings GPatternSpec *class; GPatternSpec *name; GPatternSpec *role; + GPatternSpec *group_class; + GPatternSpec *group_name; GPatternSpec *title; ObClientType type; diff --git a/openbox/screen.c b/openbox/screen.c index f4031f59..33acb4a1 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -305,6 +305,8 @@ gboolean screen_annex(void) supported[i++] = OBT_PROP_ATOM(OB_APP_TITLE); supported[i++] = OBT_PROP_ATOM(OB_APP_NAME); supported[i++] = OBT_PROP_ATOM(OB_APP_CLASS); + supported[i++] = OBT_PROP_ATOM(OB_APP_GROUP_NAME); + supported[i++] = OBT_PROP_ATOM(OB_APP_GROUP_CLASS); supported[i++] = OBT_PROP_ATOM(OB_APP_TYPE); g_assert(i == num_support);