Merge branch 'master' into hovericons

This commit is contained in:
Simon Long 2023-12-05 07:16:08 +00:00
commit 308aa39d21
15 changed files with 114 additions and 130 deletions

View file

@ -73,6 +73,13 @@ Actions are used in menus and keyboard/mouse bindings.
*<action name="MoveTo" x="" y="" />* *<action name="MoveTo" x="" y="" />*
Move to position (x, y) Move to position (x, y)
*<action name="ResizeTo" width="" height="" />*
Resize window
*width* The width to resize the window to in pixels.
*height* The height to resize the window to in pixels.
*<action name="MoveToCursor" />* *<action name="MoveToCursor" />*
Move to be centered on cursor. Move to be centered on cursor.
Tries to prevent any part of the window from going off-screen. Tries to prevent any part of the window from going off-screen.

View file

@ -5,13 +5,9 @@
#include <stdbool.h> #include <stdbool.h>
struct wlr_scene_node; struct wlr_scene_node;
struct wlr_scene_rect;
struct wlr_scene_tree;
struct wlr_surface; struct wlr_surface;
struct wlr_scene_output; struct wlr_scene_output;
struct wlr_scene_rect *lab_wlr_scene_get_rect(struct wlr_scene_node *node);
struct wlr_scene_tree *lab_scene_tree_from_node(struct wlr_scene_node *node);
struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node); struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node);
/** /**

View file

@ -5,19 +5,6 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
struct seat; struct seat;
struct wlr_drag_icon;
struct wlr_scene_tree;
struct drag_icon {
struct wlr_scene_tree *icon_tree;
struct wlr_drag_icon *icon;
struct {
struct wl_listener map;
struct wl_listener commit;
struct wl_listener unmap;
struct wl_listener destroy;
} events;
};
void dnd_init(struct seat *seat); void dnd_init(struct seat *seat);
void dnd_icons_show(struct seat *seat, bool show); void dnd_icons_show(struct seat *seat, bool show);

View file

@ -17,6 +17,7 @@
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h> #include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_foreign_toplevel_management_v1.h> #include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_device.h> #include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_keyboard.h> #include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_keyboard_group.h> #include <wlr/types/wlr_keyboard_group.h>
@ -291,6 +292,9 @@ struct server {
*/ */
int pending_output_layout_change; int pending_output_layout_change;
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
struct wl_listener gamma_control_set_gamma;
struct session_lock *session_lock; struct session_lock *session_lock;
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
@ -343,6 +347,7 @@ struct output {
struct wl_listener request_state; struct wl_listener request_state;
bool leased; bool leased;
bool gamma_lut_changed;
}; };
#undef LAB_NR_LAYERS #undef LAB_NR_LAYERS

View file

@ -88,6 +88,7 @@ enum action_type {
ACTION_TYPE_RESIZE, ACTION_TYPE_RESIZE,
ACTION_TYPE_RESIZE_RELATIVE, ACTION_TYPE_RESIZE_RELATIVE,
ACTION_TYPE_MOVETO, ACTION_TYPE_MOVETO,
ACTION_TYPE_RESIZETO,
ACTION_TYPE_MOVETO_CURSOR, ACTION_TYPE_MOVETO_CURSOR,
ACTION_TYPE_MOVE_RELATIVE, ACTION_TYPE_MOVE_RELATIVE,
ACTION_TYPE_SEND_TO_DESKTOP, ACTION_TYPE_SEND_TO_DESKTOP,
@ -131,6 +132,7 @@ const char *action_names[] = {
"Resize", "Resize",
"ResizeRelative", "ResizeRelative",
"MoveTo", "MoveTo",
"ResizeTo",
"MoveToCursor", "MoveToCursor",
"MoveRelative", "MoveRelative",
"SendToDesktop", "SendToDesktop",
@ -327,6 +329,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
goto cleanup; goto cleanup;
} }
break; break;
case ACTION_TYPE_RESIZETO:
if (!strcmp(argument, "width") || !strcmp(argument, "height")) {
action_arg_add_int(action, argument, atoi(content));
goto cleanup;
}
break;
case ACTION_TYPE_SEND_TO_DESKTOP: case ACTION_TYPE_SEND_TO_DESKTOP:
if (!strcmp(argument, "follow")) { if (!strcmp(argument, "follow")) {
action_arg_add_bool(action, argument, parse_bool(content, true)); action_arg_add_bool(action, argument, parse_bool(content, true));
@ -801,6 +809,25 @@ actions_run(struct view *activator, struct server *server,
view_move(view, x, y); view_move(view, x, y);
} }
break; break;
case ACTION_TYPE_RESIZETO:
if (view) {
int width = action_get_int(action, "width", 0);
int height = action_get_int(action, "height", 0);
/*
* To support only setting one of width/height
* in <action name="ResizeTo" width="" height=""/>
* we fall back to current dimension when unset.
*/
struct wlr_box box = {
.x = view->pending.x,
.y = view->pending.y,
.width = width ? : view->pending.width,
.height = height ? : view->pending.height,
};
view_move_resize(view, box);
}
break;
case ACTION_TYPE_MOVE_RELATIVE: case ACTION_TYPE_MOVE_RELATIVE:
if (view) { if (view) {
int x = action_get_int(action, "x", 0); int x = action_get_int(action, "x", 0);

View file

@ -6,20 +6,6 @@
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "common/scene-helpers.h" #include "common/scene-helpers.h"
struct wlr_scene_rect *
lab_wlr_scene_get_rect(struct wlr_scene_node *node)
{
assert(node->type == WLR_SCENE_NODE_RECT);
return (struct wlr_scene_rect *)node;
}
struct wlr_scene_tree *
lab_scene_tree_from_node(struct wlr_scene_node *node)
{
assert(node->type == WLR_SCENE_NODE_TREE);
return (struct wlr_scene_tree *)node;
}
struct wlr_surface * struct wlr_surface *
lab_wlr_surface_from_node(struct wlr_scene_node *node) lab_wlr_surface_from_node(struct wlr_scene_node *node)
{ {

View file

@ -170,7 +170,7 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
if (node->type == WLR_SCENE_NODE_TREE) { if (node->type == WLR_SCENE_NODE_TREE) {
struct wlr_scene_node *child; struct wlr_scene_node *child;
struct wlr_scene_tree *tree = lab_scene_tree_from_node(node); struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
wl_list_for_each(child, &tree->children, link) { wl_list_for_each(child, &tree->children, link) {
dump_tree(server, child, pos + INDENT_SIZE, dump_tree(server, child, pos + INDENT_SIZE,
x + child->x, y + child->y); x + child->x, y + child->y);

View file

@ -9,92 +9,6 @@
#include "labwc.h" /* for struct seat */ #include "labwc.h" /* for struct seat */
#include "view.h" #include "view.h"
/* Internal DnD icon handlers */
static void
handle_icon_map(struct wl_listener *listener, void *data)
{
struct drag_icon *self = wl_container_of(listener, self, events.map);
struct wlr_drag_icon *icon = self->icon;
if (icon->data) {
struct wlr_scene_tree *surface_tree = icon->data;
wlr_scene_node_set_enabled(&surface_tree->node, true);
} else {
icon->data = wlr_scene_subsurface_tree_create(
self->icon_tree, icon->surface);
}
}
static void
handle_surface_commit(struct wl_listener *listener, void *data)
{
struct drag_icon *self = wl_container_of(listener, self, events.commit);
struct wlr_surface *surface = data;
struct wlr_scene_tree *surface_tree = self->icon->data;
if (surface_tree) {
wlr_scene_node_set_position(&surface_tree->node,
surface_tree->node.x + surface->current.dx,
surface_tree->node.y + surface->current.dy);
}
}
static void
handle_icon_unmap(struct wl_listener *listener, void *data)
{
struct drag_icon *self = wl_container_of(listener, self, events.unmap);
struct wlr_drag_icon *icon = self->icon;
struct wlr_scene_tree *surface_tree = icon->data;
if (surface_tree) {
wlr_scene_node_set_enabled(&surface_tree->node, false);
}
}
static void
handle_icon_destroy(struct wl_listener *listener, void *data)
{
struct drag_icon *self = wl_container_of(listener, self, events.destroy);
wl_list_remove(&self->events.map.link);
wl_list_remove(&self->events.commit.link);
wl_list_remove(&self->events.unmap.link);
wl_list_remove(&self->events.destroy.link);
if (self->icon->data) {
struct wlr_scene_tree *tree = self->icon->data;
wlr_scene_node_destroy(&tree->node);
}
self->icon = NULL;
self->icon_tree = NULL;
free(self);
}
static void
drag_icon_create(struct seat *seat, struct wlr_drag_icon *wlr_icon)
{
assert(seat);
assert(wlr_icon);
struct drag_icon *self = znew(*self);
self->icon = wlr_icon;
self->icon_tree = seat->drag.icons;
/* Position will be updated by cursor movement */
wlr_scene_node_set_position(&self->icon_tree->node,
seat->cursor->x, seat->cursor->y);
wlr_scene_node_raise_to_top(&self->icon_tree->node);
/* Set up events */
self->events.map.notify = handle_icon_map;
self->events.commit.notify = handle_surface_commit;
self->events.unmap.notify = handle_icon_unmap;
self->events.destroy.notify = handle_icon_destroy;
wl_signal_add(&wlr_icon->surface->events.map, &self->events.map);
wl_signal_add(&wlr_icon->surface->events.commit, &self->events.commit);
wl_signal_add(&wlr_icon->surface->events.unmap, &self->events.unmap);
wl_signal_add(&wlr_icon->events.destroy, &self->events.destroy);
}
/* Internal DnD handlers */ /* Internal DnD handlers */
static void static void
handle_drag_request(struct wl_listener *listener, void *data) handle_drag_request(struct wl_listener *listener, void *data)
@ -122,8 +36,8 @@ handle_drag_start(struct wl_listener *listener, void *data)
seat->drag.active = true; seat->drag.active = true;
seat_reset_pressed(seat); seat_reset_pressed(seat);
if (drag->icon) { if (drag->icon) {
/* Cleans up automatically on drag->icon->events.detroy */ /* Cleans up automatically on drag->icon->events.destroy */
drag_icon_create(seat, drag->icon); wlr_scene_drag_icon_create(seat->drag.icons, drag->icon);
wlr_scene_node_set_enabled(&seat->drag.icons->node, true); wlr_scene_node_set_enabled(&seat->drag.icons->node, true);
} }
wl_signal_add(&drag->events.destroy, &seat->drag.events.destroy); wl_signal_add(&drag->events.destroy, &seat->drag.events.destroy);

View file

@ -87,19 +87,19 @@ menu_update_width(struct menu *menu)
/* Update all items for the new size */ /* Update all items for the new size */
wl_list_for_each(item, &menu->menuitems, link) { wl_list_for_each(item, &menu->menuitems, link) {
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
lab_wlr_scene_get_rect(item->normal.background), wlr_scene_rect_from_node(item->normal.background),
menu->size.width, item->height); menu->size.width, item->height);
if (!item->selected.background) { if (!item->selected.background) {
/* This is a separator. They don't have a selected background. */ /* This is a separator. They don't have a selected background. */
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
lab_wlr_scene_get_rect(item->normal.text), wlr_scene_rect_from_node(item->normal.text),
menu->size.width - 2 * theme->menu_separator_padding_width, menu->size.width - 2 * theme->menu_separator_padding_width,
theme->menu_separator_line_thickness); theme->menu_separator_line_thickness);
} else { } else {
/* Usual menu item */ /* Usual menu item */
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
lab_wlr_scene_get_rect(item->selected.background), wlr_scene_rect_from_node(item->selected.background),
menu->size.width, item->height); menu->size.width, item->height);
if (item->native_width > max_width || item->submenu) { if (item->native_width > max_width || item->submenu) {
scaled_font_buffer_set_max_width(item->normal.buffer, scaled_font_buffer_set_max_width(item->normal.buffer,

View file

@ -33,6 +33,36 @@ output_frame_notify(struct wl_listener *listener, void *data)
if (!output_is_usable(output)) { if (!output_is_usable(output)) {
return; return;
} }
struct wlr_output *wlr_output = output->wlr_output;
struct server *server = output->server;
if (output->gamma_lut_changed) {
struct wlr_output_state pending;
wlr_output_state_init(&pending);
if (!wlr_scene_output_build_state(output->scene_output, &pending, NULL)) {
return;
}
output->gamma_lut_changed = false;
struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control(
server->gamma_control_manager_v1, wlr_output);
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
wlr_output_state_finish(&pending);
return;
}
if (!wlr_output_commit_state(output->wlr_output, &pending)) {
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
wlr_output_state_finish(&pending);
return;
}
wlr_damage_ring_rotate(&output->scene_output->damage_ring);
wlr_output_state_finish(&pending);
return;
}
if (lab_wlr_scene_output_commit(output->scene_output)) { if (lab_wlr_scene_output_commit(output->scene_output)) {
struct timespec now = { 0 }; struct timespec now = { 0 };
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
@ -69,6 +99,14 @@ output_destroy_notify(struct wl_listener *listener, void *data)
view_on_output_destroy(view); view_on_output_destroy(view);
} }
} }
/*
* Ensure that we don't accidentally try to dereference
* the output pointer in some output event handler like
* set_gamma.
*/
output->wlr_output->data = NULL;
/* /*
* output->scene_output (if still around at this point) is * output->scene_output (if still around at this point) is
* destroyed automatically when the wlr_output is destroyed * destroyed automatically when the wlr_output is destroyed
@ -314,6 +352,9 @@ new_output_notify(struct wl_listener *listener, void *data)
void void
output_init(struct server *server) output_init(struct server *server)
{ {
server->gamma_control_manager_v1 =
wlr_gamma_control_manager_v1_create(server->wl_display);
server->new_output.notify = new_output_notify; server->new_output.notify = new_output_notify;
wl_signal_add(&server->backend->events.new_output, &server->new_output); wl_signal_add(&server->backend->events.new_output, &server->new_output);
@ -529,6 +570,20 @@ handle_output_layout_change(struct wl_listener *listener, void *data)
do_output_layout_change(server); do_output_layout_change(server);
} }
static void
handle_gamma_control_set_gamma(struct wl_listener *listener, void *data)
{
struct server *server = wl_container_of(listener, server, gamma_control_set_gamma);
const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
struct output *output = event->output->data;
if (!output_is_usable(output)) {
return;
}
output->gamma_lut_changed = true;
wlr_output_schedule_frame(output->wlr_output);
}
void void
output_manager_init(struct server *server) output_manager_init(struct server *server)
{ {
@ -541,6 +596,10 @@ output_manager_init(struct server *server)
server->output_manager_apply.notify = handle_output_manager_apply; server->output_manager_apply.notify = handle_output_manager_apply;
wl_signal_add(&server->output_manager->events.apply, wl_signal_add(&server->output_manager->events.apply,
&server->output_manager_apply); &server->output_manager_apply);
server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
&server->gamma_control_set_gamma);
} }
struct output * struct output *

View file

@ -5,6 +5,7 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <wlr/types/wlr_data_control_v1.h> #include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_export_dmabuf_v1.h> #include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_inhibitor.h> #include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_presentation_time.h> #include <wlr/types/wlr_presentation_time.h>
@ -30,7 +31,8 @@
#include "workspaces.h" #include "workspaces.h"
#include "xwayland.h" #include "xwayland.h"
#define LAB_WLR_COMPOSITOR_VERSION (5) #define LAB_WLR_COMPOSITOR_VERSION 5
#define LAB_WLR_FRACTIONAL_SCALE_V1_VERSION 1
static struct wlr_compositor *compositor; static struct wlr_compositor *compositor;
static struct wl_event_source *sighup_source; static struct wl_event_source *sighup_source;
@ -375,9 +377,10 @@ server_init(struct server *server)
wlr_export_dmabuf_manager_v1_create(server->wl_display); wlr_export_dmabuf_manager_v1_create(server->wl_display);
wlr_screencopy_manager_v1_create(server->wl_display); wlr_screencopy_manager_v1_create(server->wl_display);
wlr_data_control_manager_v1_create(server->wl_display); wlr_data_control_manager_v1_create(server->wl_display);
wlr_gamma_control_manager_v1_create(server->wl_display);
wlr_viewporter_create(server->wl_display); wlr_viewporter_create(server->wl_display);
wlr_single_pixel_buffer_manager_v1_create(server->wl_display); wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
wlr_fractional_scale_manager_v1_create(server->wl_display,
LAB_WLR_FRACTIONAL_SCALE_V1_VERSION);
idle_manager_create(server->wl_display, server->seat.seat); idle_manager_create(server->wl_display, server->seat.seat);

View file

@ -339,7 +339,7 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
: rc.theme->window_active_border_color; : rc.theme->window_active_border_color;
struct ssd_part *part = ssd_get_part(&ssd->border.active.parts, LAB_SSD_PART_TOP); struct ssd_part *part = ssd_get_part(&ssd->border.active.parts, LAB_SSD_PART_TOP);
struct wlr_scene_rect *rect = lab_wlr_scene_get_rect(part->node); struct wlr_scene_rect *rect = wlr_scene_rect_from_node(part->node);
wlr_scene_rect_set_color(rect, color); wlr_scene_rect_set_color(rect, color);
} }

View file

@ -91,7 +91,7 @@ ssd_border_update(struct ssd *ssd)
struct ssd_sub_tree *subtree; struct ssd_sub_tree *subtree;
FOR_EACH_STATE(ssd, subtree) { FOR_EACH_STATE(ssd, subtree) {
wl_list_for_each(part, &subtree->parts, link) { wl_list_for_each(part, &subtree->parts, link) {
rect = lab_wlr_scene_get_rect(part->node); rect = wlr_scene_rect_from_node(part->node);
switch (part->type) { switch (part->type) {
case LAB_SSD_PART_LEFT: case LAB_SSD_PART_LEFT:
wlr_scene_rect_set_size(rect, wlr_scene_rect_set_size(rect,

View file

@ -138,7 +138,7 @@ ssd_extents_update(struct ssd *ssd)
struct wlr_box *target; struct wlr_box *target;
wl_list_for_each(part, &ssd->extents.parts, link) { wl_list_for_each(part, &ssd->extents.parts, link) {
rect = lab_wlr_scene_get_rect(part->node); rect = wlr_scene_rect_from_node(part->node);
target = part->geometry; target = part->geometry;
switch (part->type) { switch (part->type) {
case LAB_SSD_PART_TOP: case LAB_SSD_PART_TOP:

View file

@ -131,7 +131,7 @@ set_squared_corners(struct ssd *ssd, bool enable)
struct ssd_button *button = node_ssd_button_from_node(part->node); struct ssd_button *button = node_ssd_button_from_node(part->node);
/* Toggle background between invisible and titlebar background color */ /* Toggle background between invisible and titlebar background color */
struct wlr_scene_rect *rect = lab_wlr_scene_get_rect(button->background); struct wlr_scene_rect *rect = wlr_scene_rect_from_node(button->background);
wlr_scene_rect_set_color(rect, !enable ? (float[4]) {0, 0, 0, 0} : ( wlr_scene_rect_set_color(rect, !enable ? (float[4]) {0, 0, 0, 0} : (
subtree == &ssd->titlebar.active subtree == &ssd->titlebar.active
? rc.theme->window_active_title_bg_color ? rc.theme->window_active_title_bg_color
@ -170,7 +170,7 @@ ssd_titlebar_update(struct ssd *ssd)
switch (part->type) { switch (part->type) {
case LAB_SSD_PART_TITLEBAR: case LAB_SSD_PART_TITLEBAR:
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
lab_wlr_scene_get_rect(part->node), wlr_scene_rect_from_node(part->node),
width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT, width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT,
theme->title_height); theme->title_height);
continue; continue;