Nothing Special   »   [go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add window rules and actions for pcmanfm-qt --desktop #933

Merged
merged 3 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/labwc-actions.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ Actions are used in menus and keyboard/mouse bindings.
*<action name="ToggleAlwaysOnTop">*
Toggle always-on-top of focused window.

*<action name="ToggleAlwaysOnBottom">*
Toggle bewteen layers 'always-on-bottom' and 'normal'. When a window is
in the 'always-on-bottom' layer, it is rendered below all other
top-level windows. It is anticipated that this action will be useful
when defining window-rules for desktop-management tools that do not
support the wlr-layer-shell protocol.

*<action name="ToggleKeybinds">*
Stop handling keybinds other than ToggleKeybinds itself.
This can be used to allow A-Tab and similar keybinds to be delivered
Expand Down
9 changes: 9 additions & 0 deletions docs/labwc-config.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,15 @@ situation.
*serverDecoration* over-rules any other setting for server-side window
decoration on first map.

*<windowRules><windowRule skipTaskbar="">* [yes|no|default]
*skipTaskbar* removes window foreign-toplevel protocol handle so that
it does not appear in clients such as panels and taskbars using that
protocol.

*<windowRules><windowRule skipWindowSwitcher="">* [yes|no|default]
*skipWindowSwitcher* removes window from the Window Switcher (alt-tab
on-screen-display)

## ENVIRONMENT VARIABLES

*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme
Expand Down
10 changes: 9 additions & 1 deletion include/labwc.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,16 @@ struct server {

/* Tree for all non-layer xdg/xwayland-shell surfaces */
struct wlr_scene_tree *view_tree;
/* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top */

/*
* Popups need to be rendered above always-on-top views, so we reparent
* them to this dedicated tree
*/
struct wlr_scene_tree *xdg_popup_tree;

/* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top/below */
struct wlr_scene_tree *view_tree_always_on_top;
struct wlr_scene_tree *view_tree_always_on_bottom;
#if HAVE_XWAYLAND
/* Tree for unmanaged xsurfaces without initialized view (usually popups) */
struct wlr_scene_tree *unmanaged_tree;
Expand Down
5 changes: 4 additions & 1 deletion include/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,11 @@ void view_maximize(struct view *view, bool maximize,
void view_set_fullscreen(struct view *view, bool fullscreen);
void view_toggle_maximize(struct view *view);
void view_toggle_decorations(struct view *view);
void view_toggle_always_on_top(struct view *view);

bool view_is_always_on_top(struct view *view);
void view_toggle_always_on_top(struct view *view);
void view_toggle_always_on_bottom(struct view *view);

bool view_is_tiled(struct view *view);
bool view_is_floating(struct view *view);
void view_move_to_workspace(struct view *view, struct workspace *workspace);
Expand Down
2 changes: 2 additions & 0 deletions include/window-rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ struct window_rule {
struct wl_list actions;

enum property server_decoration;
enum property skip_taskbar;
enum property skip_window_switcher;

struct wl_list link; /* struct rcxml.window_rules */
};
Expand Down
7 changes: 7 additions & 0 deletions src/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum action_type {
ACTION_TYPE_TOGGLE_FULLSCREEN,
ACTION_TYPE_TOGGLE_DECORATIONS,
ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP,
ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM,
ACTION_TYPE_FOCUS,
ACTION_TYPE_ICONIFY,
ACTION_TYPE_MOVE,
Expand Down Expand Up @@ -93,6 +94,7 @@ const char *action_names[] = {
"ToggleFullscreen",
"ToggleDecorations",
"ToggleAlwaysOnTop",
"ToggleAlwaysOnBottom",
"Focus",
"Iconify",
"Move",
Expand Down Expand Up @@ -515,6 +517,11 @@ actions_run(struct view *activator, struct server *server,
view_toggle_always_on_top(view);
}
break;
case ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM:
if (view) {
view_toggle_always_on_bottom(view);
}
break;
case ACTION_TYPE_FOCUS:
if (view) {
desktop_focus_and_activate_view(&server->seat, view);
Expand Down
4 changes: 4 additions & 0 deletions src/config/rcxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ fill_window_rule(char *nodename, char *content)
/* Properties */
} else if (!strcasecmp(nodename, "serverDecoration")) {
set_property(content, &current_window_rule->server_decoration);
} else if (!strcasecmp(nodename, "skipTaskbar")) {
set_property(content, &current_window_rule->skip_taskbar);
} else if (!strcasecmp(nodename, "skipWindowSwitcher")) {
set_property(content, &current_window_rule->skip_window_switcher);

/* Actions */
} else if (!strcmp(nodename, "name.action")) {
Expand Down
5 changes: 4 additions & 1 deletion src/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "node.h"
#include "ssd.h"
#include "view.h"
#include "window-rules.h"
#include "workspaces.h"
#include "xwayland.h"

Expand Down Expand Up @@ -191,7 +192,9 @@ desktop_cycle_view(struct server *server, struct view *start_view,
continue;
}
view = node_view_from_node(node);
if (isfocusable(view)) {

enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
if (isfocusable(view) && skip != LAB_PROP_TRUE) {
return view;
}
} while (view != start_view);
Expand Down
7 changes: 5 additions & 2 deletions src/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "theme.h"
#include "node.h"
#include "view.h"
#include "window-rules.h"
#include "workspaces.h"

#define OSD_ITEM_HEIGHT (20)
Expand Down Expand Up @@ -69,7 +70,8 @@ get_osd_height(struct wl_list *node_list)
continue;
}
view = node_view_from_node(node);
if (!isfocusable(view)) {
enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
if (!isfocusable(view) || skip == LAB_PROP_TRUE) {
continue;
}
height += OSD_ITEM_HEIGHT;
Expand Down Expand Up @@ -344,7 +346,8 @@ render_osd(struct server *server, cairo_t *cairo, int w, int h,
continue;
}
struct view *view = node_view_from_node(node);
if (!isfocusable(view)) {
enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
if (!isfocusable(view) || skip == LAB_PROP_TRUE) {
continue;
}

Expand Down
24 changes: 24 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,32 @@ server_init(struct server *server)
wlr_log(WLR_ERROR, "unable to create scene");
exit(EXIT_FAILURE);
}

/*
* The order in which the scene-trees below are created determines the
* z-order for nodes which cover the whole work-area. For per-output
* scene-trees, see new_output_notify() in src/output.c
*
* | Type | Scene Tree | Per Output | Example
* | ----------------- | ---------------- | ---------- | -------
* | ext-session | lock-screen | Yes | swaylock
* | layer-shell | layer-popups | Yes |
* | layer-shell | overlay-layer | Yes |
* | layer-shell | top-layer | Yes | waybar
* | server | labwc-menus | No |
* | xwayland-OR | unmanaged | No | dmenu
* | xdg-popups | xdg-popups | No |
* | toplevels windows | always-on-top | No |
* | toplevels windows | normal | No | firefox
* | toplevels windows | always-on-bottom | No | pcmanfm-qt --desktop
* | layer-shell | bottom-layer | Yes | waybar
* | layer-shell | background-layer | Yes | swaybg
*/

server->view_tree_always_on_bottom = wlr_scene_tree_create(&server->scene->tree);
server->view_tree = wlr_scene_tree_create(&server->scene->tree);
server->view_tree_always_on_top = wlr_scene_tree_create(&server->scene->tree);
server->xdg_popup_tree = wlr_scene_tree_create(&server->scene->tree);
#if HAVE_XWAYLAND
server->unmanaged_tree = wlr_scene_tree_create(&server->scene->tree);
#endif
Expand Down
22 changes: 19 additions & 3 deletions src/view-impl-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,29 @@ view_impl_move_to_back(struct view *view)
void
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);
view_move_to_front(view);
view_update_title(view);
view_update_app_id(view);
if (!view->been_mapped) {
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
}

/*
* It's tempting to just never create the foreign-toplevel handle in the
* map handlers, but the app_id/title might not have been set at that
* point, so it's safer to process the property here
*/
enum property ret = window_rules_get_property(view, "skipTaskbar");
if (ret == LAB_PROP_TRUE) {
if (view->toplevel.handle) {
wlr_foreign_toplevel_handle_v1_destroy(view->toplevel.handle);
}
}
Consolatis marked this conversation as resolved.
Show resolved Hide resolved

wlr_log(WLR_DEBUG, "[map] identifier=%s, title=%s\n",
view_get_string_prop(view, "app_id"),
view_get_string_prop(view, "title"));
}

static bool
Expand Down
22 changes: 22 additions & 0 deletions src/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,28 @@ view_toggle_always_on_top(struct view *view)
}
}

static bool
view_is_always_on_bottom(struct view *view)
{
assert(view);
return view->scene_tree->node.parent ==
view->server->view_tree_always_on_bottom;
}

void
view_toggle_always_on_bottom(struct view *view)
{
assert(view);
if (view_is_always_on_bottom(view)) {
view->workspace = view->server->workspace_current;
wlr_scene_node_reparent(&view->scene_tree->node,
view->workspace->tree);
} else {
wlr_scene_node_reparent(&view->scene_tree->node,
view->server->view_tree_always_on_bottom);
}
}

void
view_move_to_workspace(struct view *view, struct workspace *workspace)
{
Expand Down
15 changes: 11 additions & 4 deletions src/window-rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,17 @@ window_rules_get_property(struct view *view, const char *property)
* for.
*/
if (view_matches_criteria(rule, view)) {
if (!strcasecmp(property, "serverDecoration")) {
if (rule->server_decoration) {
return rule->server_decoration;
}
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;
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion src/xdg-popup.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,18 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
* provide the proper parent scene node of the xdg popup. To enable
* this, we always set the user data field of xdg_surfaces to the
* corresponding scene node.
*
* xdg-popups live in server->xdg_popup_tree so that they can be
* rendered above always-on-top windows
*/
struct wlr_scene_tree *parent_tree = parent->surface->data;
struct wlr_scene_tree *parent_tree = NULL;
if (parent->role == WLR_XDG_SURFACE_ROLE_POPUP) {
parent_tree = parent->surface->data;
} else {
parent_tree = view->server->xdg_popup_tree;
wlr_scene_node_set_position(&view->server->xdg_popup_tree->node,
view->current.x, view->current.y);
}
wlr_popup->base->surface->data =
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
node_descriptor_create(wlr_popup->base->surface->data,
Expand Down