mirror of
https://github.com/labwc/labwc.git
synced 2025-11-03 09:01:51 -05:00
query: support additional conditions for matching clients
Co-authored-by: Andrew J. Hesford <ajh@sideband.org> Closes: #2245.
This commit is contained in:
parent
f394d03600
commit
96da82c085
7 changed files with 217 additions and 34 deletions
|
|
@ -366,7 +366,7 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
case ACTION_TYPE_UNMAXIMIZE:
|
||||
if (!strcmp(argument, "direction")) {
|
||||
enum view_axis axis = view_axis_parse(content);
|
||||
if (axis == VIEW_AXIS_NONE) {
|
||||
if (axis == VIEW_AXIS_NONE || axis == VIEW_AXIS_INVALID) {
|
||||
wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s' (%s)",
|
||||
action_names[action->type], argument, content);
|
||||
} else {
|
||||
|
|
@ -378,7 +378,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
case ACTION_TYPE_SET_DECORATIONS:
|
||||
if (!strcmp(argument, "decorations")) {
|
||||
enum ssd_mode mode = ssd_mode_parse(content);
|
||||
action_arg_add_int(action, argument, mode);
|
||||
if (mode != LAB_SSD_MODE_INVALID) {
|
||||
action_arg_add_int(action, argument, mode);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s' (%s)",
|
||||
action_names[action->type], argument, content);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
if (!strcasecmp(argument, "forceSSD")) {
|
||||
|
|
|
|||
|
|
@ -473,6 +473,26 @@ fill_action_query(char *nodename, char *content, struct action *action)
|
|||
current_view_query->sandbox_engine = xstrdup(content);
|
||||
} else if (!strcasecmp(nodename, "sandboxAppId")) {
|
||||
current_view_query->sandbox_app_id = xstrdup(content);
|
||||
} else if (!strcasecmp(nodename, "shaded")) {
|
||||
current_view_query->shaded = parse_bool(content, -1);
|
||||
} else if (!strcasecmp(nodename, "maximized")) {
|
||||
current_view_query->maximized = view_axis_parse(content);
|
||||
} else if (!strcasecmp(nodename, "iconified")) {
|
||||
current_view_query->iconified = parse_bool(content, -1);
|
||||
} else if (!strcasecmp(nodename, "focused")) {
|
||||
current_view_query->focused = parse_bool(content, -1);
|
||||
} else if (!strcasecmp(nodename, "omnipresent")) {
|
||||
current_view_query->omnipresent = parse_bool(content, -1);
|
||||
} else if (!strcasecmp(nodename, "tiled")) {
|
||||
current_view_query->tiled = view_edge_parse(content);
|
||||
} else if (!strcasecmp(nodename, "tiled_region")) {
|
||||
current_view_query->tiled_region = xstrdup(content);
|
||||
} else if (!strcasecmp(nodename, "desktop")) {
|
||||
current_view_query->desktop = xstrdup(content);
|
||||
} else if (!strcasecmp(nodename, "decoration")) {
|
||||
current_view_query->decoration = ssd_mode_parse(content);
|
||||
} else if (!strcasecmp(nodename, "monitor")) {
|
||||
current_view_query->monitor = xstrdup(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,14 +350,16 @@ enum ssd_mode
|
|||
ssd_mode_parse(const char *mode)
|
||||
{
|
||||
if (!mode) {
|
||||
return LAB_SSD_MODE_FULL;
|
||||
return LAB_SSD_MODE_INVALID;
|
||||
}
|
||||
if (!strcasecmp(mode, "none")) {
|
||||
return LAB_SSD_MODE_NONE;
|
||||
} else if (!strcasecmp(mode, "border")) {
|
||||
return LAB_SSD_MODE_BORDER;
|
||||
} else {
|
||||
} else if (!strcasecmp(mode, "full")) {
|
||||
return LAB_SSD_MODE_FULL;
|
||||
} else {
|
||||
return LAB_SSD_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
163
src/view.c
163
src/view.c
|
|
@ -8,6 +8,7 @@
|
|||
#include "common/macros.h"
|
||||
#include "common/match.h"
|
||||
#include "common/mem.h"
|
||||
#include "common/parse-bool.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "input/keyboard.h"
|
||||
#include "labwc.h"
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
#include "ssd.h"
|
||||
#include "view.h"
|
||||
#include "window-rules.h"
|
||||
#include "wlr/util/log.h"
|
||||
#include "workspaces.h"
|
||||
#include "xwayland.h"
|
||||
|
||||
|
|
@ -76,53 +78,154 @@ void
|
|||
view_query_free(struct view_query *query)
|
||||
{
|
||||
wl_list_remove(&query->link);
|
||||
free(query->identifier);
|
||||
free(query->title);
|
||||
free(query->sandbox_engine);
|
||||
free(query->sandbox_app_id);
|
||||
free(query);
|
||||
zfree(query->identifier);
|
||||
zfree(query->title);
|
||||
zfree(query->sandbox_engine);
|
||||
zfree(query->sandbox_app_id);
|
||||
zfree(query->tiled_region);
|
||||
zfree(query->desktop);
|
||||
zfree(query->monitor);
|
||||
zfree(query);
|
||||
}
|
||||
|
||||
static enum three_state
|
||||
bool_to_tristate(bool b)
|
||||
{
|
||||
return b ? LAB_STATE_ENABLED : LAB_STATE_DISABLED;
|
||||
}
|
||||
|
||||
static enum three_state
|
||||
match_tristate(enum three_state desired, bool actual, enum three_state old_match)
|
||||
{
|
||||
switch (desired) {
|
||||
case LAB_STATE_ENABLED:
|
||||
return bool_to_tristate(actual);
|
||||
case LAB_STATE_DISABLED:
|
||||
return bool_to_tristate(!actual);
|
||||
default:
|
||||
return old_match;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
view_matches_query(struct view *view, struct view_query *query)
|
||||
{
|
||||
bool match = true;
|
||||
bool empty = true;
|
||||
enum three_state match = LAB_STATE_UNSPECIFIED;
|
||||
|
||||
const char *identifier = view_get_string_prop(view, "app_id");
|
||||
if (match && query->identifier) {
|
||||
empty = false;
|
||||
match &= identifier && match_glob(query->identifier, identifier);
|
||||
if (query->identifier) {
|
||||
const char *identifier = view_get_string_prop(view, "app_id");
|
||||
if (!(identifier && match_glob(query->identifier, identifier))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *title = view_get_string_prop(view, "title");
|
||||
if (match && query->title) {
|
||||
empty = false;
|
||||
match &= title && match_glob(query->title, title);
|
||||
if (query->title) {
|
||||
const char *title = view_get_string_prop(view, "title");
|
||||
if (!(title && match_glob(query->title, title))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match && query->window_type >= 0) {
|
||||
empty = false;
|
||||
match &= view_contains_window_type(view, query->window_type);
|
||||
if (query->window_type >= 0) {
|
||||
if (!view_contains_window_type(view, query->window_type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match && query->sandbox_engine) {
|
||||
if (query->sandbox_engine) {
|
||||
const struct wlr_security_context_v1_state *security_context =
|
||||
security_context_from_view(view);
|
||||
empty = false;
|
||||
match &= security_context && security_context->sandbox_engine
|
||||
&& match_glob(query->sandbox_engine, security_context->sandbox_engine);
|
||||
if (!(security_context && security_context->sandbox_engine &&
|
||||
match_glob(query->sandbox_engine, security_context->sandbox_engine))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match && query->sandbox_app_id) {
|
||||
if (query->sandbox_app_id) {
|
||||
const struct wlr_security_context_v1_state *security_context =
|
||||
security_context_from_view(view);
|
||||
empty = false;
|
||||
match &= security_context && security_context->app_id
|
||||
&& match_glob(query->sandbox_app_id, security_context->app_id);
|
||||
if (!(security_context && security_context->app_id &&
|
||||
match_glob(query->sandbox_app_id, security_context->app_id))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !empty && match;
|
||||
match = match_tristate(query->shaded, view->shaded, match);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (query->maximized != VIEW_AXIS_INVALID) {
|
||||
match = bool_to_tristate(view->maximized == query->maximized);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
match = match_tristate(query->iconified, view->minimized, match);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match = match_tristate(query->focused, view->server->active_view == view, match);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match = match_tristate(query->omnipresent, view->visible_on_all_workspaces, match);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (query->tiled != VIEW_EDGE_INVALID) {
|
||||
match = bool_to_tristate(query->tiled == view->tiled);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (query->tiled_region) {
|
||||
match = bool_to_tristate(view->tiled_region &&
|
||||
!strcasecmp(query->tiled_region, view->tiled_region->name));
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (query->desktop) {
|
||||
if (!strcasecmp(query->desktop, "other")) {
|
||||
struct workspace *current = view->server->workspaces.current;
|
||||
match = bool_to_tristate(strcasecmp(view->workspace->name, current->name));
|
||||
} else {
|
||||
// TODO: perhaps allow wrapping for "left" and "right" workspaces
|
||||
struct workspace *target =
|
||||
workspaces_find(view->server->workspaces.current,
|
||||
query->desktop, false);
|
||||
match = bool_to_tristate(target &&
|
||||
!strcasecmp(view->workspace->name, target->name));
|
||||
}
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum ssd_mode decoration = view_get_ssd_mode(view);
|
||||
if (query->decoration != LAB_SSD_MODE_INVALID) {
|
||||
match = bool_to_tristate(query->decoration == decoration);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (query->monitor) {
|
||||
struct output *target = output_from_name(view->server, query->monitor);
|
||||
match = bool_to_tristate(target == view->output);
|
||||
if (match == LAB_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return match == LAB_STATE_ENABLED;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1949,7 +2052,7 @@ enum view_axis
|
|||
view_axis_parse(const char *direction)
|
||||
{
|
||||
if (!direction) {
|
||||
return VIEW_AXIS_NONE;
|
||||
return VIEW_AXIS_INVALID;
|
||||
}
|
||||
if (!strcasecmp(direction, "horizontal")) {
|
||||
return VIEW_AXIS_HORIZONTAL;
|
||||
|
|
@ -1957,8 +2060,10 @@ view_axis_parse(const char *direction)
|
|||
return VIEW_AXIS_VERTICAL;
|
||||
} else if (!strcasecmp(direction, "both")) {
|
||||
return VIEW_AXIS_BOTH;
|
||||
} else {
|
||||
} else if (!strcasecmp(direction, "none")) {
|
||||
return VIEW_AXIS_NONE;
|
||||
} else {
|
||||
return VIEW_AXIS_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue