mirror of
https://github.com/labwc/labwc.git
synced 2026-02-05 04:06:33 -05:00
Before this commit, we assumed `ShowMenu` action is not bound to any buttons other than window menu button and always place the client-menu under the window-menu button when atCursor="no". Also, it was going to be difficult to distinguish whether the action is executed from the window menu button or the window icon, which will be added soon. This commit fixes it to open the menu under the actually-clicked button by passing `cursor_context` to `actions_run()`, with some refactoring: - `seat->pressed.resize_edges` is removed and it's calculated from the cursor position and `seat->pressed.type` just before running Resize action. This slightly changes the existing logic to determine the resizing edges with Alt-Right + Drag mousebinding, but `seat->pressed.type` is still stored on button press so it doesn't bring back the issue #543. - `seat->pressed.toplevel` is removed and `get_toplevel()` in `update_pressed_surface()` may be called more often, but its overhead will be negligible.
111 lines
2.9 KiB
C
111 lines
2.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#define _POSIX_C_SOURCE 200809L
|
|
#include <assert.h>
|
|
#include <stdbool.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"
|
|
|
|
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 = {0};
|
|
query.identifier = rule->identifier;
|
|
query.title = rule->title;
|
|
query.window_type = rule->window_type;
|
|
query.sandbox_engine = rule->sandbox_engine;
|
|
query.sandbox_app_id = rule->sandbox_app_id;
|
|
|
|
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".
|
|
*
|
|
* <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) {
|
|
/*
|
|
* 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 (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;
|
|
}
|
|
}
|
|
}
|
|
return LAB_PROP_UNSPECIFIED;
|
|
}
|