use simple pattern matching for per-app settings. all rules that match are applied to a window rather than just the first

This commit is contained in:
Dana Jansens 2007-05-21 03:42:25 +00:00
parent add9c3c1bb
commit fd8ce9414a
6 changed files with 129 additions and 55 deletions

View file

@ -506,11 +506,15 @@
want to use it --> want to use it -->
<applications> <applications>
<!-- the name or the class can be set, or both. this is used to match <!-- the name or the class can be set, or both. this is used to match
windows when they appear windows when they appear. role can optionally be set as well, to
further restrict your matches
role can optionally be set, and only as much as you provide will be the name, class, and role use simple globbing rules such as those
checked to see if it matches, eg. if you set role="abc" and the window's used by a shell. you can use * to match any characters and ? to match
role is actually "abcde" it would match. any single character.
when multiple rules match a window, they will all be applied, in the
order that they appear in this list
--> -->
<application name="first element of window's WM_CLASS property (see xprop)" <application name="first element of window's WM_CLASS property (see xprop)"
class="second element of window's WM_CLASS property (see xprop)" class="second element of window's WM_CLASS property (see xprop)"
@ -520,6 +524,7 @@
change that attribute of the window --> change that attribute of the window -->
<decor>yes</decor> <decor>yes</decor>
<!-- enable or disable window decorations -->
<shade>no</shade> <shade>no</shade>

View file

@ -153,6 +153,7 @@
<xsd:complexType name="window_position"> <xsd:complexType name="window_position">
<xsd:element name="x" type="ob:center_or_int"/> <xsd:element name="x" type="ob:center_or_int"/>
<xsd:element name="y" type="ob:center_or_int"/> <xsd:element name="y" type="ob:center_or_int"/>
<xsd:element name="monitor" type="ob:mouse_or_int"/>
<xsd:element minOccurs="0" name="head" type="xsd:string"/> <xsd:element minOccurs="0" name="head" type="xsd:string"/>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="application"> <xsd:complexType name="application">
@ -330,6 +331,13 @@
<xsd:pattern value="center|0|[1-9][0-9]*"/> <xsd:pattern value="center|0|[1-9][0-9]*"/>
</xsd:restriction> </xsd:restriction>
</xsd:simpleType> </xsd:simpleType>
<xsd:simpleType name="mouse_or_int">
<xsd:restriction base="xsd:string">
<!-- ob: atoi($_) unless $_ eq 'center'; -->
<!-- I think the regexp DTRT WRT atoi. -->
<xsd:pattern value="mouse|0|[1-9][0-9]*"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="contextname"> <xsd:simpleType name="contextname">
<xsd:restriction base="xsd:string"> <xsd:restriction base="xsd:string">
<xsd:enumeration value="Desktop"/> <xsd:enumeration value="Desktop"/>

View file

@ -314,7 +314,8 @@ void client_manage(Window window)
grab_server(FALSE); grab_server(FALSE);
/* per-app settings override stuff from client_get_all, and return the /* per-app settings override stuff from client_get_all, and return the
settings for other uses too */ settings for other uses too. the returned settings is a shallow copy,
that needs to be freed with g_free(). */
settings = client_get_settings_state(self); settings = client_get_settings_state(self);
/* the session should get the last say thought */ /* the session should get the last say thought */
client_restore_session_state(self); client_restore_session_state(self);
@ -506,6 +507,9 @@ void client_manage(Window window)
/* update the list hints */ /* update the list hints */
client_set_list(); client_set_list();
/* free the ObAppSettings shallow copy */
g_free(settings);
ob_debug("Managed window 0x%lx plate 0x%x (%s)\n", ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
window, self->frame->plate, self->class); window, self->frame->plate, self->class);
@ -527,7 +531,7 @@ ObClient *client_fake_manage(Window window)
client_get_all(self, FALSE); client_get_all(self, FALSE);
/* per-app settings override stuff, and return the settings for other /* per-app settings override stuff, and return the settings for other
uses too */ uses too. this returns a shallow copy that needs to be freed */
settings = client_get_settings_state(self); settings = client_get_settings_state(self);
client_setup_decor_and_functions(self); client_setup_decor_and_functions(self);
@ -535,6 +539,10 @@ ObClient *client_fake_manage(Window window)
/* create the decoration frame for the client window and adjust its size */ /* create the decoration frame for the client window and adjust its size */
self->frame = frame_new(self); self->frame = frame_new(self);
frame_adjust_area(self->frame, FALSE, TRUE, TRUE); frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
/* free the ObAppSettings shallow copy */
g_free(settings);
return self; return self;
} }
@ -694,30 +702,39 @@ void client_fake_unmanage(ObClient *self)
g_free(self); g_free(self);
} }
/*! Returns a new structure containing the per-app settings for this client.
The returned structure needs to be freed with g_free. */
static ObAppSettings *client_get_settings_state(ObClient *self) static ObAppSettings *client_get_settings_state(ObClient *self)
{ {
ObAppSettings *settings = NULL; ObAppSettings *settings;
GSList *it; GSList *it;
settings = config_create_app_settings();
for (it = config_per_app_settings; it; it = g_slist_next(it)) { for (it = config_per_app_settings; it; it = g_slist_next(it)) {
ObAppSettings *app = it->data; ObAppSettings *app = it->data;
gboolean match = TRUE;
if ((app->name && !app->class && !strcmp(app->name, self->name))
|| (app->class && !app->name && !strcmp(app->class, self->class)) g_assert(app->name != NULL || app->class != NULL);
|| (app->class && app->name && !strcmp(app->class, self->class)
&& !strcmp(app->name, self->name))) /* we know that either name or class is not NULL so it will have to
{ match to use the rule */
/* Match if no role was specified in the per app setting, or if the if (app->name &&
* string matches the beginning of the role, since apps like to set !g_pattern_match(app->name, strlen(self->name), self->name, NULL))
* the role to things like browser-window-23c4b2f */ match = FALSE;
if (!app->role if (app->class &&
|| !strncmp(app->role, self->role, strlen(app->role))) !g_pattern_match(app->class, strlen(self->class),self->class,NULL))
{ match = FALSE;
ob_debug("Window matching: %s\n", app->name); if (app->role &&
/* use this one */ !g_pattern_match(app->role, strlen(self->role), self->role, NULL))
settings = app; match = FALSE;
break;
} if (match) {
ob_debug("Window matching: %s\n", app->name);
/* copy the settings to our struct, overriding the existing
settings if they are not defaults */
config_app_settings_copy_non_defaults(app, settings);
} }
} }

View file

@ -35,7 +35,6 @@ struct _ObSessionState;
typedef struct _ObClient ObClient; typedef struct _ObClient ObClient;
typedef struct _ObClientIcon ObClientIcon; typedef struct _ObClientIcon ObClientIcon;
typedef struct _ObAppSettings ObAppSettings;
/* The value in client.transient_for indicating it is a transient for its /* The value in client.transient_for indicating it is a transient for its
group instead of for a single window */ group instead of for a single window */

View file

@ -89,6 +89,54 @@ gint config_resist_edge;
GSList *config_per_app_settings; GSList *config_per_app_settings;
ObAppSettings* config_create_app_settings()
{
ObAppSettings *settings = g_new0(ObAppSettings, 1);
settings->decor = -1;
settings->shade = -1;
settings->monitor = -1;
settings->focus = -1;
settings->desktop = 0;
settings->layer = -2;
settings->iconic = -1;
settings->skip_pager = -1;
settings->skip_taskbar = -1;
settings->fullscreen = -1;
settings->max_horz = -1;
settings->max_vert = -1;
return settings;
}
#define copy_if(setting, default) \
if (src->setting != default) dst->setting = src->setting
void config_app_settings_copy_non_defaults(const ObAppSettings *src,
ObAppSettings *dst)
{
g_assert(src != NULL);
g_assert(dst != NULL);
copy_if(decor, -1);
copy_if(shade, -1);
copy_if(focus, -1);
copy_if(desktop, 0);
copy_if(layer, -2);
copy_if(iconic, -1);
copy_if(skip_pager, -1);
copy_if(skip_taskbar, -1);
copy_if(fullscreen, -1);
copy_if(max_horz, -1);
copy_if(max_vert, -1);
if (src->pos_given) {
dst->pos_given = TRUE;
dst->center_x = src->center_x;
dst->center_y = src->center_y;
dst->position.x = src->position.x;
dst->position.y = src->position.y;
dst->monitor = src->monitor;
}
}
/* /*
<applications> <applications>
<application name="aterm"> <application name="aterm">
@ -121,7 +169,7 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
xmlNodePtr node, gpointer d) xmlNodePtr node, gpointer d)
{ {
xmlNodePtr app = parse_find_node("application", node->children); xmlNodePtr app = parse_find_node("application", node->children);
gchar *name, *class; gchar *name = NULL, *class = NULL, *role = NULL;
gboolean name_set, class_set; gboolean name_set, class_set;
gboolean x_pos_given; gboolean x_pos_given;
@ -132,33 +180,25 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
name_set = parse_attr_string("name", app, &name); name_set = parse_attr_string("name", app, &name);
if (class_set || name_set) { if (class_set || name_set) {
xmlNodePtr n, c; xmlNodePtr n, c;
ObAppSettings *settings = g_new0(ObAppSettings, 1); ObAppSettings *settings = config_create_app_settings();;
if (name_set) if (name_set)
settings->name = name; settings->name = g_pattern_spec_new(name);
else
settings->name = NULL;
if (class_set) if (class_set)
settings->class = class; settings->class = g_pattern_spec_new(class);
else
settings->class = NULL;
if (!parse_attr_string("role", app, &settings->role)) if (parse_attr_string("role", app, &role))
settings->role = NULL; settings->role = g_pattern_spec_new(role);
settings->decor = -1;
if ((n = parse_find_node("decor", app->children))) if ((n = parse_find_node("decor", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->decor = parse_bool(doc, n); settings->decor = parse_bool(doc, n);
settings->shade = -1;
if ((n = parse_find_node("shade", app->children))) if ((n = parse_find_node("shade", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->shade = parse_bool(doc, n); settings->shade = parse_bool(doc, n);
settings->position.x = settings->position.y = 0;
settings->pos_given = FALSE;
if ((n = parse_find_node("position", app->children))) { if ((n = parse_find_node("position", app->children))) {
if ((c = parse_find_node("x", n->children))) if ((c = parse_find_node("x", n->children)))
if (!parse_contains("default", doc, c)) { if (!parse_contains("default", doc, c)) {
@ -198,7 +238,6 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
} }
} }
settings->focus = -1;
if ((n = parse_find_node("focus", app->children))) if ((n = parse_find_node("focus", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->focus = parse_bool(doc, n); settings->focus = parse_bool(doc, n);
@ -214,11 +253,9 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
settings->desktop = i; settings->desktop = i;
} }
g_free(s); g_free(s);
} else }
settings->desktop = 0;
} }
settings->layer = -2;
if ((n = parse_find_node("layer", app->children))) if ((n = parse_find_node("layer", app->children)))
if (!parse_contains("default", doc, n)) { if (!parse_contains("default", doc, n)) {
gchar *s = parse_string(doc, n); gchar *s = parse_string(doc, n);
@ -231,28 +268,22 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
g_free(s); g_free(s);
} }
settings->iconic = -1;
if ((n = parse_find_node("iconic", app->children))) if ((n = parse_find_node("iconic", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->iconic = parse_bool(doc, n); settings->iconic = parse_bool(doc, n);
settings->skip_pager = -1;
if ((n = parse_find_node("skip_pager", app->children))) if ((n = parse_find_node("skip_pager", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->skip_pager = parse_bool(doc, n); settings->skip_pager = parse_bool(doc, n);
settings->skip_taskbar = -1;
if ((n = parse_find_node("skip_taskbar", app->children))) if ((n = parse_find_node("skip_taskbar", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->skip_taskbar = parse_bool(doc, n); settings->skip_taskbar = parse_bool(doc, n);
settings->fullscreen = -1;
if ((n = parse_find_node("fullscreen", app->children))) if ((n = parse_find_node("fullscreen", app->children)))
if (!parse_contains("default", doc, n)) if (!parse_contains("default", doc, n))
settings->fullscreen = parse_bool(doc, n); settings->fullscreen = parse_bool(doc, n);
settings->max_horz = -1;
settings->max_vert = -1;
if ((n = parse_find_node("maximized", app->children))) if ((n = parse_find_node("maximized", app->children)))
if (!parse_contains("default", doc, n)) { if (!parse_contains("default", doc, n)) {
gchar *s = parse_string(doc, n); gchar *s = parse_string(doc, n);
@ -274,6 +305,10 @@ static void parse_per_app_settings(ObParseInst *i, xmlDocPtr doc,
app = parse_find_node("application", app->next); app = parse_find_node("application", app->next);
} }
g_free(name);
g_free(class);
g_free(role);
} }
/* /*
@ -917,9 +952,9 @@ void config_shutdown()
for (it = config_per_app_settings; it; it = g_slist_next(it)) { for (it = config_per_app_settings; it; it = g_slist_next(it)) {
ObAppSettings *itd = (ObAppSettings *)it->data; ObAppSettings *itd = (ObAppSettings *)it->data;
g_free(itd->name); if (itd->name) g_pattern_spec_free(itd->name);
g_free(itd->role); if (itd->role) g_pattern_spec_free(itd->role);
g_free(itd->class); if (itd->class) g_pattern_spec_free(itd->class);
g_free(it->data); g_free(it->data);
} }
g_slist_free(config_per_app_settings); g_slist_free(config_per_app_settings);

View file

@ -30,11 +30,13 @@
struct _ObParseInst; struct _ObParseInst;
typedef struct _ObAppSettings ObAppSettings;
struct _ObAppSettings struct _ObAppSettings
{ {
gchar *class; GPatternSpec *class;
gchar *name; GPatternSpec *name;
gchar *role; GPatternSpec *role;
Point position; Point position;
gboolean center_x; gboolean center_x;
@ -166,4 +168,12 @@ extern GSList *config_per_app_settings;
void config_startup(struct _ObParseInst *i); void config_startup(struct _ObParseInst *i);
void config_shutdown(); void config_shutdown();
/*! Create an ObAppSettings structure with the default values */
ObAppSettings* config_create_app_settings();
/*! Copies any settings in src to dest, if they are their default value in
src. */
void config_app_settings_copy_non_defaults(const ObAppSettings *src,
ObAppSettings *dest);
#endif #endif