mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	window-rules: support title criteria
Example config:
    <windowRules>
      <windowRule identifier="foot" title="max">
        <action name="Maximize"/>
      </windowRule>
    </windowRules>
Observe that:
- `foot -T foo` starts maximized
- `xterm -T foo` starts normal
			
			
This commit is contained in:
		
							parent
							
								
									63db731cf4
								
							
						
					
					
						commit
						d37e705548
					
				
					 5 changed files with 90 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -88,9 +88,16 @@ fill_window_rule(char *nodename, char *content)
 | 
			
		|||
		/* nop */
 | 
			
		||||
	} else if (!current_window_rule) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "no window-rule");
 | 
			
		||||
 | 
			
		||||
	/* Criteria */
 | 
			
		||||
	} else if (!strcmp(nodename, "identifier")) {
 | 
			
		||||
		free(current_window_rule->identifier);
 | 
			
		||||
		current_window_rule->identifier = xstrdup(content);
 | 
			
		||||
	} else if (!strcmp(nodename, "title")) {
 | 
			
		||||
		free(current_window_rule->title);
 | 
			
		||||
		current_window_rule->title = xstrdup(content);
 | 
			
		||||
 | 
			
		||||
	/* Event */
 | 
			
		||||
	} else if (!strcmp(nodename, "event")) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * This is just in readiness for adding any other types of
 | 
			
		||||
| 
						 | 
				
			
			@ -99,8 +106,12 @@ fill_window_rule(char *nodename, char *content)
 | 
			
		|||
		if (!strcasecmp(content, "onFirstMap")) {
 | 
			
		||||
			current_window_rule->event = LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* Properties */
 | 
			
		||||
	} else if (!strcasecmp(nodename, "serverDecoration")) {
 | 
			
		||||
		set_property(content, ¤t_window_rule->server_decoration);
 | 
			
		||||
 | 
			
		||||
	/* Actions */
 | 
			
		||||
	} else if (!strcmp(nodename, "name.action")) {
 | 
			
		||||
		current_window_rule_action = action_create(content);
 | 
			
		||||
		if (current_window_rule_action) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1027,6 +1038,29 @@ post_processing(void)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rule_destroy(struct window_rule *rule)
 | 
			
		||||
{
 | 
			
		||||
	wl_list_remove(&rule->link);
 | 
			
		||||
	zfree(rule->identifier);
 | 
			
		||||
	zfree(rule->title);
 | 
			
		||||
	action_list_free(&rule->actions);
 | 
			
		||||
	zfree(rule);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
validate(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Window-rule criteria */
 | 
			
		||||
	struct window_rule *rule, *next;
 | 
			
		||||
	wl_list_for_each_safe(rule, next, &rc.window_rules, link) {
 | 
			
		||||
		if (!rule->identifier && !rule->title) {
 | 
			
		||||
			wlr_log(WLR_ERROR, "deleting rule %p as no criteria", rule);
 | 
			
		||||
			rule_destroy(rule);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rcxml_path(char *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1091,6 +1125,7 @@ rcxml_read(const char *filename)
 | 
			
		|||
	free(b.buf);
 | 
			
		||||
no_config:
 | 
			
		||||
	post_processing();
 | 
			
		||||
	validate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
| 
						 | 
				
			
			@ -1140,10 +1175,7 @@ rcxml_finish(void)
 | 
			
		|||
 | 
			
		||||
	struct window_rule *rule, *rule_tmp;
 | 
			
		||||
	wl_list_for_each_safe(rule, rule_tmp, &rc.window_rules, link) {
 | 
			
		||||
		wl_list_remove(&rule->link);
 | 
			
		||||
		zfree(rule->identifier);
 | 
			
		||||
		action_list_free(&rule->actions);
 | 
			
		||||
		zfree(rule);
 | 
			
		||||
		rule_destroy(rule);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Reset state vars for starting fresh when Reload is triggered */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
#define _POSIX_C_SOURCE 200809L
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <strings.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -13,20 +14,44 @@
 | 
			
		|||
#include "view.h"
 | 
			
		||||
#include "window-rules.h"
 | 
			
		||||
 | 
			
		||||
/* Try to match against identifier AND title (if set) */
 | 
			
		||||
static bool
 | 
			
		||||
view_matches_criteria(struct window_rule *rule, struct view *view)
 | 
			
		||||
{
 | 
			
		||||
	const char *id = view_get_string_prop(view, "app_id");
 | 
			
		||||
	const char *title = view_get_string_prop(view, "title");
 | 
			
		||||
 | 
			
		||||
	if (rule->identifier && rule->title) {
 | 
			
		||||
		if (!id || !title) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		return match_glob(rule->identifier, id)
 | 
			
		||||
			&& match_glob(rule->title, title);
 | 
			
		||||
	} else if (rule->identifier) {
 | 
			
		||||
		if (!id) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		return match_glob(rule->identifier, id);
 | 
			
		||||
	} else if (rule->title) {
 | 
			
		||||
		if (!title) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		return match_glob(rule->title, title);
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_log(WLR_ERROR, "rule has no identifier or title\n");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_rules_apply(struct view *view, enum window_rule_event event)
 | 
			
		||||
{
 | 
			
		||||
	const char *identifier = view_get_string_prop(view, "app_id");
 | 
			
		||||
	if (!identifier) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct window_rule *rule;
 | 
			
		||||
	wl_list_for_each(rule, &rc.window_rules, link) {
 | 
			
		||||
		if (!rule->identifier || rule->event != event) {
 | 
			
		||||
		if (rule->event != event) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (match_glob(rule->identifier, identifier)) {
 | 
			
		||||
		if (view_matches_criteria(rule, view)) {
 | 
			
		||||
			actions_run(view, view->server, &rule->actions, 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +62,6 @@ window_rules_get_property(struct view *view, const char *property)
 | 
			
		|||
{
 | 
			
		||||
	assert(property);
 | 
			
		||||
 | 
			
		||||
	const char *identifier = view_get_string_prop(view, "app_id");
 | 
			
		||||
	if (!identifier) {
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We iterate in reverse here because later items in list have higher
 | 
			
		||||
	 * priority. For example, in the config below we want the return value
 | 
			
		||||
| 
						 | 
				
			
			@ -54,16 +74,13 @@ window_rules_get_property(struct view *view, const char *property)
 | 
			
		|||
	 */
 | 
			
		||||
	struct window_rule *rule;
 | 
			
		||||
	wl_list_for_each_reverse(rule, &rc.window_rules, link) {
 | 
			
		||||
		if (!rule->identifier) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Only return if property != LAB_PROP_UNSPECIFIED otherwise a
 | 
			
		||||
		 * <windowRule> which does not set a particular property
 | 
			
		||||
		 * attribute would still return here if that property was asked
 | 
			
		||||
		 * for.
 | 
			
		||||
		 */
 | 
			
		||||
		if (match_glob(rule->identifier, identifier)) {
 | 
			
		||||
		if (view_matches_criteria(rule, view)) {
 | 
			
		||||
			if (!strcasecmp(property, "serverDecoration")) {
 | 
			
		||||
				if (rule->server_decoration) {
 | 
			
		||||
					return rule->server_decoration;
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +88,5 @@ window_rules_get_property(struct view *view, const char *property)
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	return LAB_PROP_UNSPECIFIED;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue