diff --git a/data/rc.xml b/data/rc.xml index 3e5554b..a9a7a35 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -734,6 +734,12 @@ true # 'Horizontal', 'Vertical' or boolean (yes/no) + + + # set a particular window property + desktop + # window type, currently supported: 'desktop','dock' + # end of the example diff --git a/openbox/client.c b/openbox/client.c index 3ff278a..f5153bf 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -115,6 +115,10 @@ static gboolean client_can_steal_focus(ObClient *self, static void client_setup_default_decor_and_functions(ObClient *self); static void client_setup_decor_undecorated(ObClient *self); +static Atom client_type_to_wmtype(ObClientType type); +static gboolean client_set_type(ObClient *self, gulong type); + + void client_startup(gboolean reconfig) { client_default_icon = RrImageNewFromData( @@ -912,7 +916,12 @@ static ObAppSettings *client_get_settings_state(ObClient *self) settings = config_create_app_settings(); - for (it = config_per_app_settings; it; it = g_slist_next(it)) { + + ob_debug("APPSET_MATCH: attempting to match window %s", self->name); + + + int rule_no = 0; + for (it = config_per_app_settings; it; it = g_slist_next(it), rule_no++) { ObAppSettings *app = it->data; gboolean match = TRUE; @@ -921,36 +930,59 @@ static ObAppSettings *client_get_settings_state(ObClient *self) app->group_name != NULL || app->group_class != NULL || (signed)app->type >= 0); + ob_debug("APPSET_MATCH: trying rule %d", rule_no); + + if (app->name && !g_pattern_match(app->name, strlen(self->name), self->name, NULL)) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on name"); + } else if (app->group_name && !g_pattern_match(app->group_name, strlen(self->group_name), self->group_name, NULL)) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on group_name"); + } else if (app->class && !g_pattern_match(app->class, strlen(self->class), self->class, NULL)) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on class"); + } else if (app->group_class && !g_pattern_match(app->group_class, strlen(self->group_class), self->group_class, NULL)) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on group_class"); + } else if (app->role && !g_pattern_match(app->role, strlen(self->role), self->role, NULL)) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on role"); + } else if (app->title && !g_pattern_match(app->title, strlen(self->title), self->title, NULL)) + { match = FALSE; - else if ((signed)app->type >= 0 && app->type != self->type) { + ob_debug("APPSET_MATCH: failed match on title"); + } + else if ((signed)app->type >= 0 && app->type != self->type) + { match = FALSE; + ob_debug("APPSET_MATCH: failed match on type"); } if (match) { - ob_debug("Window matching: %s", app->name); + ob_debug("APPSET_MATCH: Window matching: %s", self->name); /* copy the settings to our struct, overriding the existing settings if they are not defaults */ @@ -958,6 +990,14 @@ static ObAppSettings *client_get_settings_state(ObClient *self) } } + + if (settings->set_type != -1) { + self->type = settings->set_type; + if (client_set_type(self, client_type_to_wmtype(settings->set_type))) + ob_debug("Setting window type (for %s) to: %u", self->name, self->type); + else + ob_debug("Failed to set window type (for %s)", self->name); + } if (settings->shade != -1) self->shaded = !!settings->shade; if (settings->decor != -1) @@ -1565,6 +1605,30 @@ void client_get_mwm_hints(ObClient *self) } } +static gboolean client_set_type(ObClient *self, gulong type) +{ + guint num, i; + guint32 *orig_val; + gulong *set_val; + + if (OBT_PROP_GETA32(self->window, NET_WM_WINDOW_TYPE, ATOM, &orig_val, &num)) { + set_val = g_slice_alloc((num + 1) * sizeof(gulong)); + + set_val[0] = type; + for (i = 1; i <= num; i++) + set_val[i] = orig_val[i]; + + OBT_PROP_SETA32(self->window, NET_WM_WINDOW_TYPE, ATOM, set_val, num); + + g_slice_free1((num + 1) * sizeof(gulong), set_val); + + return TRUE; + } + + return FALSE; +} + + void client_get_type_and_transientness(ObClient *self) { guint num, i; @@ -2458,6 +2522,34 @@ static void client_get_session_ids(ObClient *self) } } +static Atom client_type_to_wmtype(ObClientType type) +{ + gulong wmtype; + + switch (type) { + case OB_CLIENT_TYPE_NORMAL: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_NORMAL); break; + case OB_CLIENT_TYPE_DIALOG: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG); break; + case OB_CLIENT_TYPE_UTILITY: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_UTILITY); break; + case OB_CLIENT_TYPE_MENU: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU); break; + case OB_CLIENT_TYPE_TOOLBAR: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_TOOLBAR); break; + case OB_CLIENT_TYPE_SPLASH: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_SPLASH); break; + case OB_CLIENT_TYPE_DESKTOP: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP); break; + case OB_CLIENT_TYPE_DOCK: + wmtype = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK); break; + case OB_CLIENT_TYPE_OVERRIDE: + wmtype = OBT_PROP_ATOM(KDE_NET_WM_WINDOW_TYPE_OVERRIDE); break; + } + + return wmtype; +} + const gchar *client_type_to_string(ObClient *self) { const gchar *type; diff --git a/openbox/client.h b/openbox/client.h index 11a0140..68d918c 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -51,7 +51,8 @@ typedef enum OB_CLIENT_TYPE_UTILITY, /*!< A small utility window such as a palette */ OB_CLIENT_TYPE_SPLASH, /*!< A splash screen window */ OB_CLIENT_TYPE_DIALOG, /*!< A dialog window */ - OB_CLIENT_TYPE_NORMAL /*!< A normal application window */ + OB_CLIENT_TYPE_NORMAL, /*!< A normal application window */ + OB_CLIENT_TYPE_OVERRIDE /*!< A window not subject to our management */ } ObClientType; /*! The things the user can do to the client window */ diff --git a/openbox/config.c b/openbox/config.c index dad5d1b..436c555 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -110,6 +110,7 @@ ObAppSettings* config_create_app_settings(void) { ObAppSettings *settings = g_slice_new0(ObAppSettings); settings->type = -1; + settings->set_type = -1; settings->decor = -1; settings->shade = -1; settings->monitor_type = OB_PLACE_MONITOR_ANY; @@ -135,6 +136,7 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src, g_assert(dst != NULL); copy_if(type, (ObClientType)-1); + copy_if(set_type, -1); copy_if(decor, -1); copy_if(shade, -1); copy_if(monitor_type, OB_PLACE_MONITOR_ANY); @@ -254,6 +256,19 @@ static void parse_single_per_app_settings(xmlNodePtr app, obt_xml_attr_bool(n, "force", &settings->pos_force); } + if ((n = obt_xml_find_node(app->children, "set_window_property"))) { + if ((c = obt_xml_find_node(n->children, "type"))) { + gchar *s = obt_xml_node_string(c); + if (!g_ascii_strcasecmp(s, "desktop")) + settings->set_type = OB_CLIENT_TYPE_DESKTOP; + else if (!g_ascii_strcasecmp(s, "dock")) + settings->set_type = OB_CLIENT_TYPE_DOCK; + else if (!g_ascii_strcasecmp(s, "override")) + settings->set_type = OB_CLIENT_TYPE_OVERRIDE; + g_free(s); + } + } + if ((n = obt_xml_find_node(app->children, "size"))) { if ((c = obt_xml_find_node(n->children, "width"))) { if (!obt_xml_node_contains(c, "default")) { diff --git a/openbox/config.h b/openbox/config.h index 96a66cf..5a694c0 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -42,6 +42,7 @@ struct _ObAppSettings GPatternSpec *group_name; GPatternSpec *title; ObClientType type; + ObClientType set_type; GravityPoint position; gboolean pos_given;