mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	Support window-rules
Two types of window rules are supported, actions and properties. They are
defined as shown below.
    <windowRules>
      <!-- Action -->
      <windowRule identifier="some-application">
        <action name="Maximize"/>
      </windowRule>
      <!-- Property -->
      <windowRule identifier="foo*" serverDecoration="yes|no"/>
    </windowRules>
Rules are applied if windows match the criteria defined by the
'identifier' attribute which relates to app_id for native Wayland windows
and WM_CLASS for XWayland clients.
Matching against patterns with '*' (wildcard) and '?' (joker) is
supported.
Add 'serverDecoration' property.
			
			
This commit is contained in:
		
							parent
							
								
									d0aafb684f
								
							
						
					
					
						commit
						d609c9e3f9
					
				
					 12 changed files with 281 additions and 3 deletions
				
			
		| 
						 | 
					@ -330,6 +330,48 @@ The rest of this man page describes configuration options.
 | 
				
			||||||
	any motion events while a keyboard is typing, and for a short while
 | 
						any motion events while a keyboard is typing, and for a short while
 | 
				
			||||||
	after as well.
 | 
						after as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## WINDOW RULES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Two types of window rules are supported, actions and properties. They are
 | 
				
			||||||
 | 
					defined as shown below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					<windowRules>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- Action -->
 | 
				
			||||||
 | 
					  <windowRule identifier="">
 | 
				
			||||||
 | 
					    <action name=""/>
 | 
				
			||||||
 | 
					  </windowRule>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- Property -->
 | 
				
			||||||
 | 
					  <windowRule identifier="" serverDecoration="" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</windowRules>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*Actions*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*<windowRules><windowRule identifier="">*
 | 
				
			||||||
 | 
						Define a window rule for any window which matches the criteria defined
 | 
				
			||||||
 | 
						by the attribute *identifier*. Matching against patterns with '\*'
 | 
				
			||||||
 | 
						(wildcard) and '?' (joker) is supported. Pattern matching is
 | 
				
			||||||
 | 
						case-insensitive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*identifier* relates to app_id for native Wayland windows and WM_CLASS
 | 
				
			||||||
 | 
						for XWayland clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*Properties*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Property values can be *yes*, *no* or *default*.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a window matches criteria for multiple rules which set the same property,
 | 
				
			||||||
 | 
					later config entries have higher priority. *default* can be useful in this
 | 
				
			||||||
 | 
					situation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*<windowRules><windowRule serverDecoration="">* [yes|no|default]
 | 
				
			||||||
 | 
						*serverDecoration* over-rules any other setting for server-side window
 | 
				
			||||||
 | 
						decoration on first map.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## ENVIRONMENT VARIABLES
 | 
					## ENVIRONMENT VARIABLES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme
 | 
					*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -374,4 +374,13 @@
 | 
				
			||||||
    </device>
 | 
					    </device>
 | 
				
			||||||
  </libinput>
 | 
					  </libinput>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!--
 | 
				
			||||||
 | 
					  <windowRules>
 | 
				
			||||||
 | 
					    <windowRule identifier="*">
 | 
				
			||||||
 | 
					      <action name="Maximize" />
 | 
				
			||||||
 | 
					    </windowRule>
 | 
				
			||||||
 | 
					    <windowRule identifier="some-application" serverDecoration="yes" />
 | 
				
			||||||
 | 
					  </windowRules>
 | 
				
			||||||
 | 
					  -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</labwc_config>
 | 
					</labwc_config>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,6 +80,8 @@ struct rcxml {
 | 
				
			||||||
		bool outlines;
 | 
							bool outlines;
 | 
				
			||||||
		struct wl_list fields;  /* struct window_switcher_field.link */
 | 
							struct wl_list fields;  /* struct window_switcher_field.link */
 | 
				
			||||||
	} window_switcher;
 | 
						} window_switcher;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_list window_rules; /* struct window_rule.link */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct rcxml rc;
 | 
					extern struct rcxml rc;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								include/window-rules.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								include/window-rules.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-only */
 | 
				
			||||||
 | 
					#ifndef __WINDOW_RULES_H
 | 
				
			||||||
 | 
					#define __WINDOW_RULES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum window_rule_event {
 | 
				
			||||||
 | 
						LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP = 0,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum property {
 | 
				
			||||||
 | 
						LAB_PROP_UNSPECIFIED = 0,
 | 
				
			||||||
 | 
						LAB_PROP_UNSET,
 | 
				
			||||||
 | 
						LAB_PROP_FALSE,
 | 
				
			||||||
 | 
						LAB_PROP_TRUE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 'identifier' represents:
 | 
				
			||||||
 | 
					 *   - 'app_id' for native Wayland windows
 | 
				
			||||||
 | 
					 *   - 'WM_CLASS' for XWayland clients
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct window_rule {
 | 
				
			||||||
 | 
						char *identifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum window_rule_event event;
 | 
				
			||||||
 | 
						struct wl_list actions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum property server_decoration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_list link; /* struct rcxml.window_rules */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void window_rules_apply(struct view *view, enum window_rule_event event);
 | 
				
			||||||
 | 
					enum property window_rules_get_property(struct view *view, const char *property);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __WINDOW_RULES_H */
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-only
 | 
					// SPDX-License-Identifier: GPL-2.0-only
 | 
				
			||||||
#define _POSIX_C_SOURCE 200809L
 | 
					#define _POSIX_C_SOURCE 200809L
 | 
				
			||||||
#include <glib.h>
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include "common/match.h"
 | 
					#include "common/match.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
#include "config/mousebind.h"
 | 
					#include "config/mousebind.h"
 | 
				
			||||||
#include "config/rcxml.h"
 | 
					#include "config/rcxml.h"
 | 
				
			||||||
#include "regions.h"
 | 
					#include "regions.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
#include "workspaces.h"
 | 
					#include "workspaces.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool in_regions;
 | 
					static bool in_regions;
 | 
				
			||||||
| 
						 | 
					@ -32,6 +33,7 @@ static bool in_keybind;
 | 
				
			||||||
static bool in_mousebind;
 | 
					static bool in_mousebind;
 | 
				
			||||||
static bool in_libinput_category;
 | 
					static bool in_libinput_category;
 | 
				
			||||||
static bool in_window_switcher_field;
 | 
					static bool in_window_switcher_field;
 | 
				
			||||||
 | 
					static bool in_window_rules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct keybind *current_keybind;
 | 
					static struct keybind *current_keybind;
 | 
				
			||||||
static struct mousebind *current_mousebind;
 | 
					static struct mousebind *current_mousebind;
 | 
				
			||||||
| 
						 | 
					@ -41,6 +43,8 @@ static struct action *current_keybind_action;
 | 
				
			||||||
static struct action *current_mousebind_action;
 | 
					static struct action *current_mousebind_action;
 | 
				
			||||||
static struct region *current_region;
 | 
					static struct region *current_region;
 | 
				
			||||||
static struct window_switcher_field *current_field;
 | 
					static struct window_switcher_field *current_field;
 | 
				
			||||||
 | 
					static struct window_rule *current_window_rule;
 | 
				
			||||||
 | 
					static struct action *current_window_rule_action;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum font_place {
 | 
					enum font_place {
 | 
				
			||||||
	FONT_PLACE_NONE = 0,
 | 
						FONT_PLACE_NONE = 0,
 | 
				
			||||||
| 
						 | 
					@ -54,6 +58,63 @@ enum font_place {
 | 
				
			||||||
static void load_default_key_bindings(void);
 | 
					static void load_default_key_bindings(void);
 | 
				
			||||||
static void load_default_mouse_bindings(void);
 | 
					static void load_default_mouse_bindings(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Does a boolean-parse but also allows 'default' */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					set_property(const char *str, enum property *variable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!str || !strcasecmp(str, "default")) {
 | 
				
			||||||
 | 
							*variable = LAB_PROP_UNSET;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						int ret = parse_bool(str, -1);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*variable = ret ? LAB_PROP_TRUE : LAB_PROP_FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					fill_window_rule(char *nodename, char *content)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!strcasecmp(nodename, "windowRule.windowRules")) {
 | 
				
			||||||
 | 
							current_window_rule = znew(*current_window_rule);
 | 
				
			||||||
 | 
							wl_list_append(&rc.window_rules, ¤t_window_rule->link);
 | 
				
			||||||
 | 
							wl_list_init(¤t_window_rule->actions);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string_truncate_at_pattern(nodename, ".windowrule.windowrules");
 | 
				
			||||||
 | 
						if (!content) {
 | 
				
			||||||
 | 
							/* nop */
 | 
				
			||||||
 | 
						} else if (!current_window_rule) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "no window-rule");
 | 
				
			||||||
 | 
						} else if (!strcmp(nodename, "identifier")) {
 | 
				
			||||||
 | 
							free(current_window_rule->identifier);
 | 
				
			||||||
 | 
							current_window_rule->identifier = xstrdup(content);
 | 
				
			||||||
 | 
						} else if (!strcmp(nodename, "event")) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * This is just in readiness for adding any other types of
 | 
				
			||||||
 | 
							 * events in the future. We default to onFirstMap anyway.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (!strcasecmp(content, "onFirstMap")) {
 | 
				
			||||||
 | 
								current_window_rule->event = LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (!strcasecmp(nodename, "serverDecoration")) {
 | 
				
			||||||
 | 
							set_property(content, ¤t_window_rule->server_decoration);
 | 
				
			||||||
 | 
						} else if (!strcmp(nodename, "name.action")) {
 | 
				
			||||||
 | 
							current_window_rule_action = action_create(content);
 | 
				
			||||||
 | 
							if (current_window_rule_action) {
 | 
				
			||||||
 | 
								wl_list_append(¤t_window_rule->actions,
 | 
				
			||||||
 | 
									¤t_window_rule_action->link);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (!current_window_rule_action) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
 | 
				
			||||||
 | 
								"nodename: '%s' content: '%s'", nodename, content);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							action_arg_from_xml_node(current_window_rule_action, nodename, content);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
fill_window_switcher_field(char *nodename, char *content)
 | 
					fill_window_switcher_field(char *nodename, char *content)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -417,6 +478,10 @@ entry(xmlNode *node, char *nodename, char *content)
 | 
				
			||||||
		fill_window_switcher_field(nodename, content);
 | 
							fill_window_switcher_field(nodename, content);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (in_window_rules) {
 | 
				
			||||||
 | 
							fill_window_rule(nodename, content);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* handle nodes without content, e.g. <keyboard><default /> */
 | 
						/* handle nodes without content, e.g. <keyboard><default /> */
 | 
				
			||||||
	if (!strcmp(nodename, "default.keyboard")) {
 | 
						if (!strcmp(nodename, "default.keyboard")) {
 | 
				
			||||||
| 
						 | 
					@ -600,6 +665,12 @@ xml_tree_walk(xmlNode *node)
 | 
				
			||||||
			in_window_switcher_field = false;
 | 
								in_window_switcher_field = false;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (!strcasecmp((char *)n->name, "windowRules")) {
 | 
				
			||||||
 | 
								in_window_rules = true;
 | 
				
			||||||
 | 
								traverse(n);
 | 
				
			||||||
 | 
								in_window_rules = false;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		traverse(n);
 | 
							traverse(n);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -638,6 +709,7 @@ rcxml_init(void)
 | 
				
			||||||
		wl_list_init(&rc.workspace_config.workspaces);
 | 
							wl_list_init(&rc.workspace_config.workspaces);
 | 
				
			||||||
		wl_list_init(&rc.regions);
 | 
							wl_list_init(&rc.regions);
 | 
				
			||||||
		wl_list_init(&rc.window_switcher.fields);
 | 
							wl_list_init(&rc.window_switcher.fields);
 | 
				
			||||||
 | 
							wl_list_init(&rc.window_rules);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	has_run = true;
 | 
						has_run = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1059,6 +1131,14 @@ rcxml_finish(void)
 | 
				
			||||||
		zfree(field);
 | 
							zfree(field);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Reset state vars for starting fresh when Reload is triggered */
 | 
						/* Reset state vars for starting fresh when Reload is triggered */
 | 
				
			||||||
	current_keybind = NULL;
 | 
						current_keybind = NULL;
 | 
				
			||||||
	current_mousebind = NULL;
 | 
						current_mousebind = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1068,4 +1148,6 @@ rcxml_finish(void)
 | 
				
			||||||
	current_mousebind_action = NULL;
 | 
						current_mousebind_action = NULL;
 | 
				
			||||||
	current_region = NULL;
 | 
						current_region = NULL;
 | 
				
			||||||
	current_field = NULL;
 | 
						current_field = NULL;
 | 
				
			||||||
 | 
						current_window_rule = NULL;
 | 
				
			||||||
 | 
						current_window_rule_action = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ labwc_sources = files(
 | 
				
			||||||
  'theme.c',
 | 
					  'theme.c',
 | 
				
			||||||
  'view.c',
 | 
					  'view.c',
 | 
				
			||||||
  'view-impl-common.c',
 | 
					  'view-impl-common.c',
 | 
				
			||||||
 | 
					  'window-rules.c',
 | 
				
			||||||
  'workspaces.c',
 | 
					  'workspaces.c',
 | 
				
			||||||
  'xdg.c',
 | 
					  'xdg.c',
 | 
				
			||||||
  'xdg-popup.c',
 | 
					  'xdg-popup.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include "labwc.h"
 | 
					#include "labwc.h"
 | 
				
			||||||
#include "view.h"
 | 
					#include "view.h"
 | 
				
			||||||
#include "view-impl-common.h"
 | 
					#include "view-impl-common.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
view_impl_move_to_front(struct view *view)
 | 
					view_impl_move_to_front(struct view *view)
 | 
				
			||||||
| 
						 | 
					@ -26,6 +27,9 @@ view_impl_move_to_back(struct view *view)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
view_impl_map(struct view *view)
 | 
					view_impl_map(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!view->been_mapped) {
 | 
				
			||||||
 | 
							window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	desktop_focus_and_activate_view(&view->server->seat, view);
 | 
						desktop_focus_and_activate_view(&view->server->seat, view);
 | 
				
			||||||
	view_move_to_front(view);
 | 
						view_move_to_front(view);
 | 
				
			||||||
	view_update_title(view);
 | 
						view_update_title(view);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include "regions.h"
 | 
					#include "regions.h"
 | 
				
			||||||
#include "ssd.h"
 | 
					#include "ssd.h"
 | 
				
			||||||
#include "view.h"
 | 
					#include "view.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
#include "workspaces.h"
 | 
					#include "workspaces.h"
 | 
				
			||||||
#include "xwayland.h"
 | 
					#include "xwayland.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,6 +659,7 @@ void
 | 
				
			||||||
view_set_decorations(struct view *view, bool decorations)
 | 
					view_set_decorations(struct view *view, bool decorations)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	assert(view);
 | 
						assert(view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->ssd_enabled != decorations && !view->fullscreen) {
 | 
						if (view->ssd_enabled != decorations && !view->fullscreen) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Set view->ssd_enabled first since it is referenced
 | 
							 * Set view->ssd_enabled first since it is referenced
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										76
									
								
								src/window-rules.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/window-rules.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,76 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-only
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 200809L
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <cairo.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <strings.h>
 | 
				
			||||||
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					#include "action.h"
 | 
				
			||||||
 | 
					#include "common/match.h"
 | 
				
			||||||
 | 
					#include "config/rcxml.h"
 | 
				
			||||||
 | 
					#include "labwc.h"
 | 
				
			||||||
 | 
					#include "view.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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) {
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (match_glob(rule->identifier, identifier)) {
 | 
				
			||||||
 | 
								actions_run(view, view->server, &rule->actions, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum property
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
						 * for foot's "serverDecoration" property to be "default".
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 *     <windowRules>
 | 
				
			||||||
 | 
						 *       <windowRule identifier="*" serverDecoration="no"/>
 | 
				
			||||||
 | 
						 *       <windowRule identifier="foot" serverDecoration="default"/>
 | 
				
			||||||
 | 
						 *     </windowRules>
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						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 (!strcasecmp(property, "serverDecoration")) {
 | 
				
			||||||
 | 
									if (rule->server_decoration) {
 | 
				
			||||||
 | 
										return rule->server_decoration;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return LAB_PROP_UNSPECIFIED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/xdg.c
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/xdg.c
									
										
									
									
									
								
							| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include "node.h"
 | 
					#include "node.h"
 | 
				
			||||||
#include "view.h"
 | 
					#include "view.h"
 | 
				
			||||||
#include "view-impl-common.h"
 | 
					#include "view-impl-common.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
#include "workspaces.h"
 | 
					#include "workspaces.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIGURE_TIMEOUT_MS 100
 | 
					#define CONFIGURE_TIMEOUT_MS 100
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,16 @@ handle_new_xdg_popup(struct wl_listener *listener, void *data)
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
has_ssd(struct view *view)
 | 
					has_ssd(struct view *view)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						/* Window-rules take priority if they exist for this view */
 | 
				
			||||||
 | 
						switch (window_rules_get_property(view, "serverDecoration")) {
 | 
				
			||||||
 | 
						case LAB_PROP_TRUE:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case LAB_PROP_FALSE:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * view->ssd_preference may be set by the decoration implementation
 | 
						 * view->ssd_preference may be set by the decoration implementation
 | 
				
			||||||
	 * e.g. src/decorations/xdg-deco.c or src/decorations/kde-deco.c.
 | 
						 * e.g. src/decorations/xdg-deco.c or src/decorations/kde-deco.c.
 | 
				
			||||||
| 
						 | 
					@ -425,13 +436,13 @@ xdg_toplevel_view_map(struct view *view)
 | 
				
			||||||
		view->current.y = view->pending.y;
 | 
							view->current.y = view->pending.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		view_moved(view);
 | 
							view_moved(view);
 | 
				
			||||||
		view->been_mapped = true;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view->commit.notify = handle_commit;
 | 
						view->commit.notify = handle_commit;
 | 
				
			||||||
	wl_signal_add(&xdg_surface->surface->events.commit, &view->commit);
 | 
						wl_signal_add(&xdg_surface->surface->events.commit, &view->commit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view_impl_map(view);
 | 
						view_impl_map(view);
 | 
				
			||||||
 | 
						view->been_mapped = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include "ssd.h"
 | 
					#include "ssd.h"
 | 
				
			||||||
#include "view.h"
 | 
					#include "view.h"
 | 
				
			||||||
#include "view-impl-common.h"
 | 
					#include "view-impl-common.h"
 | 
				
			||||||
 | 
					#include "window-rules.h"
 | 
				
			||||||
#include "workspaces.h"
 | 
					#include "workspaces.h"
 | 
				
			||||||
#include "xwayland.h"
 | 
					#include "xwayland.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,6 +104,18 @@ ensure_initial_geometry_and_output(struct view *view)
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
want_deco(struct wlr_xwayland_surface *xwayland_surface)
 | 
					want_deco(struct wlr_xwayland_surface *xwayland_surface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct view *view = (struct view *)xwayland_surface->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Window-rules take priority if they exist for this view */
 | 
				
			||||||
 | 
						switch (window_rules_get_property(view, "serverDecoration")) {
 | 
				
			||||||
 | 
						case LAB_PROP_TRUE:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case LAB_PROP_FALSE:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return xwayland_surface->decorations ==
 | 
						return xwayland_surface->decorations ==
 | 
				
			||||||
		WLR_XWAYLAND_SURFACE_DECORATIONS_ALL;
 | 
							WLR_XWAYLAND_SURFACE_DECORATIONS_ALL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -464,7 +477,6 @@ xwayland_view_map(struct view *view)
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		view->current = view->pending;
 | 
							view->current = view->pending;
 | 
				
			||||||
		view_moved(view);
 | 
							view_moved(view);
 | 
				
			||||||
		view->been_mapped = true;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->ssd_enabled && view_is_floating(view)) {
 | 
						if (view->ssd_enabled && view_is_floating(view)) {
 | 
				
			||||||
| 
						 | 
					@ -476,6 +488,7 @@ xwayland_view_map(struct view *view)
 | 
				
			||||||
	view->commit.notify = handle_commit;
 | 
						view->commit.notify = handle_commit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view_impl_map(view);
 | 
						view_impl_map(view);
 | 
				
			||||||
 | 
						view->been_mapped = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue