// SPDX-License-Identifier: GPL-2.0-only #define _POSIX_C_SOURCE 200809L #include "window-rules.h" #include #include #include #include "action.h" #include "config/rcxml.h" #include "labwc.h" #include "view.h" static bool other_instances_exist(struct view *self, struct view_query *query) { struct wl_list *views = &self->server->views; struct view *view; wl_list_for_each(view, views, link) { if (view != self && view_matches_query(view, query)) { return true; } } return false; } static bool view_matches_criteria(struct window_rule *rule, struct view *view) { struct view_query query = { .identifier = rule->identifier, .title = rule->title, .window_type = rule->window_type, .sandbox_engine = rule->sandbox_engine, .sandbox_app_id = rule->sandbox_app_id, /* Must be synced with view_query_create() */ .maximized = VIEW_AXIS_INVALID, .decoration = LAB_SSD_MODE_INVALID, }; if (rule->match_once && other_instances_exist(view, &query)) { return false; } return view_matches_query(view, &query); } void window_rules_apply(struct view *view, enum window_rule_event event) { struct window_rule *rule; wl_list_for_each(rule, &rc.window_rules, link) { if (rule->event != event) { continue; } if (view_matches_criteria(rule, view)) { actions_run(view, view->server, &rule->actions, NULL); } } } enum property window_rules_get_property(struct view *view, const char *property) { assert(property); /* * 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". * * * * * */ struct window_rule *rule; wl_list_for_each_reverse(rule, &rc.window_rules, link) { /* * Only return if property != LAB_PROP_UNSPECIFIED otherwise a * which does not set a particular property * attribute would still return here if that property was asked * for. */ if (view_matches_criteria(rule, view)) { if (rule->server_decoration && !strcasecmp(property, "serverDecoration")) { return rule->server_decoration; } if (rule->skip_taskbar && !strcasecmp(property, "skipTaskbar")) { return rule->skip_taskbar; } if (rule->skip_window_switcher && !strcasecmp(property, "skipWindowSwitcher")) { return rule->skip_window_switcher; } if (rule->ignore_focus_request && !strcasecmp(property, "ignoreFocusRequest")) { return rule->ignore_focus_request; } if (rule->ignore_configure_request && !strcasecmp(property, "ignoreConfigureRequest")) { return rule->ignore_configure_request; } if (rule->fixed_position && !strcasecmp(property, "fixedPosition")) { return rule->fixed_position; } if (rule->icon_prefer_client && !strcasecmp(property, "iconPreferClient")) { return rule->icon_prefer_client; } } } return LAB_PROP_UNSPECIFIED; }