]> Dogcows Code - chaz/openbox/commitdiff
Allow window matching based on the group leader's name and class (Fix bug 5721)
authorDana Jansens <danakj@orodu.net>
Mon, 1 Oct 2012 02:16:10 +0000 (22:16 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 7 Oct 2012 01:56:56 +0000 (21:56 -0400)
In Openbox 3.4 we used the group leader's WM_CLASS value when it was available.
This prevents windows in the group from overriding with a specific value,
however which is bad. More rationale can be found in
http://icculus.org/pipermail/openbox/2010-September/006790.html

Some applications (eg. Firefox) use command line flags to set the WM_CLASS
property on the group leader but do not change the property on the mapped
windows themselves. This makes matching these windows not possible in Openbox
3.5.

We resolve this by exposing the group's WM_CLASS values alongside the individual
window's values. We add _OB_APP_GROUP_NAME and _OB_APP_GROUP_CLASS properties
along with "groupname" and "classname" attributes for the rc.xml application
tag.

data/rc.xml
obt/prop.c
obt/prop.h
openbox/client.c
openbox/client.h
openbox/config.c
openbox/config.h
openbox/screen.c

index 209cc2dc9a9d416e0c04842060b7cb6f6dbb2be8..7c37928eefb5e6a2eba5f7414b88201c15759b8b 100644 (file)
 
   <application name="the window's _OB_APP_NAME property (see obxprop)"
               class="the window's _OB_APP_CLASS property (see obxprop)"
+          groupname="the window's _OB_APP_GROUP_NAME property (see obxprop)"
+         groupclass="the window's _OB_APP_GROUP_CLASS property (see obxprop)"
                role="the window's _OB_APP_ROLE property (see obxprop)"
               title="the window's _OB_APP_TITLE property (see obxprop)"
                type="the window's _OB_APP_TYPE property (see obxprob)..
index 638373fdfd531173a7868e49348ce8ef1d0bdce9..f7919d6c380a64d919d2d909a5f6cede435f5490 100644 (file)
@@ -197,6 +197,8 @@ void obt_prop_startup(void)
     CREATE_(OB_APP_TITLE);
     CREATE_(OB_APP_NAME);
     CREATE_(OB_APP_CLASS);
+    CREATE_(OB_APP_GROUP_NAME);
+    CREATE_(OB_APP_GROUP_CLASS);
     CREATE_(OB_APP_TYPE);
 }
 
index b30232e9d8282d455e1ae78ae3d18d6614eebd18..acb5c956ede42d3c1ca2182de40218e5d071df1c 100644 (file)
@@ -219,6 +219,8 @@ typedef enum {
     OBT_PROP_OB_APP_TITLE,
     OBT_PROP_OB_APP_NAME,
     OBT_PROP_OB_APP_CLASS,
+    OBT_PROP_OB_APP_GROUP_NAME,
+    OBT_PROP_OB_APP_GROUP_CLASS,
     OBT_PROP_OB_APP_TYPE,
 
     OBT_PROP_NUM_ATOMS
index c54b21fba3e0a135e3b50a1c60ff61913af30273..cd93ba590111a56a32ea5de9e5ed423b97f8d9a2 100644 (file)
@@ -250,6 +250,8 @@ 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,
@@ -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) {
index 5a20822fc4ce55afe9ce4d239f7e0a4f867e592e..0e55c59f7399cbd07aaef1993f3917b1676b1182 100644 (file)
@@ -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;
 
index 0d9eb689f2e7f4e7ad8ecc4073529413c1541371..d5ff8c45c9b7e12608cc7d825ed3322b5fb14b31 100644 (file)
@@ -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);
index 730dc39a5f8040d1a3ca5460dd087d4bf9c33f34..43386d3c319a02d4a191204bc41a4cbd19758fb2 100644 (file)
@@ -38,6 +38,8 @@ struct _ObAppSettings
     GPatternSpec *class;
     GPatternSpec *name;
     GPatternSpec *role;
+    GPatternSpec *group_class;
+    GPatternSpec *group_name;
     GPatternSpec *title;
     ObClientType  type;
 
index f4031f59591cf430edd1b93eaddcc7130c80536b..33acb4a16a2828f62bcd5bb769807be32f0eeff3 100644 (file)
@@ -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);
 
This page took 0.04553 seconds and 4 git commands to generate.