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/doc/openbox-session.1.in b/doc/openbox-session.1.in
index 483cdfd..e69de29 100644
--- a/doc/openbox-session.1.in
+++ b/doc/openbox-session.1.in
@@ -1,42 +0,0 @@
-.TH "OPENBOX" "1"
-.SH "NAME"
-openbox-session \(em Runs an Openbox session without any session manager.
-
-.SH "DESCRIPTION"
-.PP
-\fBopenbox-session\fR runs an openbox session without
-any session manager. Without a session manager, you will not be able
-to save your state from one log in to the next.
-.PP
-\fBopenbox-session\fR does not take any command line
-arguments.
-.PP
-On log in, \fBopenbox-session\fR will run the
-~/.config/openbox/autostart.sh script if it exists, and will run the
-system-wide script @configdir@/openbox/autostart.sh otherwise. You may
-place anything you want to run automatically in those files, for example:
-
-.PP
-.RS
-.PP
-.nf
-xsetroot \-solid grey &
-gnome-settings-daemon &
-.fi
-.RE
-.PP
-Make sure that each line is followed by a "&" or else the script will
-stop there and further commands will not be executed. You can use the
-@configdir@/openbox/autostart.sh file as an example for creating your
-own.
-.SH "SEE ALSO"
-.PP
-openbox(1), openbox-session(1), openbox-gnome-session(1).
-
-.PP
-The program's full documentation is available on the website:
-\fBhttp://openbox.org/\fP
-.PP
-Please report bugs to: \fBhttp://bugzilla.icculus.org/
-\fP
-.\" created by instant / docbook-to-man, Wed 06 Jan 2010, 13:40
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;