Get the window's title in the fake-managed case since we apply app rule matching...
[dana/openbox.git] / openbox / client.c
index f3b4bda..9e25135 100644 (file)
@@ -167,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;
@@ -203,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);
 
@@ -234,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,
@@ -468,19 +486,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) {
@@ -508,6 +520,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));
@@ -710,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);
@@ -902,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))
@@ -1197,13 +1224,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);
 
@@ -2352,6 +2381,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);
 
@@ -2421,6 +2469,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) {
@@ -2761,6 +2811,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 ||