Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package cage for openSUSE:Factory checked in at 2023-08-02 16:49:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cage (Old) and /work/SRC/openSUSE:Factory/.cage.new.22712 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cage" Wed Aug 2 16:49:01 2023 rev:2 rq:1101959 version:0.1.5+0.83ffc57 Changes: -------- --- /work/SRC/openSUSE:Factory/cage/cage.changes 2022-12-02 13:13:09.301857734 +0100 +++ /work/SRC/openSUSE:Factory/.cage.new.22712/cage.changes 2023-08-02 16:50:36.845561003 +0200 @@ -1,0 +2,12 @@ +Mon Jul 31 05:46:16 UTC 2023 - Michael Vetter <[email protected]> + +- Update to 0.1.5: + * Implement the following protocols: wlr-output-management-unstable-v1, + virtual-keyboard-unstable-v1, wlr-virtual-pointer-unstable-v1, + single-pixel-buffer-v1, presentation-time, viewporter. + * Use wlroots' scene-graph API, which should improve performance. + * Fall back to lower resolutions when the preferred output + mode cannot be used. +- Drop cage-wlroots-016-compat.patch + +------------------------------------------------------------------- Old: ---- cage-0.1.4+39.a81ab70.obscpio cage-0.1.4+39.a81ab70.tar.gz cage-wlroots-016-compat.patch New: ---- cage-0.1.5+0.83ffc57.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cage.spec ++++++ --- /var/tmp/diff_new_pack.jdTBjW/_old 2023-08-02 16:50:37.533565159 +0200 +++ /var/tmp/diff_new_pack.jdTBjW/_new 2023-08-02 16:50:37.537565184 +0200 @@ -1,7 +1,7 @@ # # spec file for package cage # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,14 +17,13 @@ Name: cage -Version: 0.1.4+39.a81ab70 +Version: 0.1.5+0.83ffc57 Release: 0 Summary: Wayland Kiosk License: MIT Group: System/GUI/Other URL: https://www.hjdskes.nl/projects/cage/ Source: %{name}-%{version}.tar.gz -Patch0: https://patch-diff.githubusercontent.com/raw/Hjdskes/cage/pull/244.patch#/cage-wlroots-016-compat.patch BuildRequires: meson >= 0.43.0 BuildRequires: pkgconfig BuildRequires: scdoc @@ -39,7 +38,6 @@ %prep %setup -q -n %{name}-%{version} -%patch0 -p1 %build %meson ++++++ _service ++++++ --- /var/tmp/diff_new_pack.jdTBjW/_old 2023-08-02 16:50:37.577565426 +0200 +++ /var/tmp/diff_new_pack.jdTBjW/_new 2023-08-02 16:50:37.581565449 +0200 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="disabled"> <param name="url">https://github.com/Hjdskes/cage.git</param> <param name="scm">git</param> - <param name="revision">a81ab70</param> + <param name="revision">v0.1.5</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@.%h</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> ++++++ cage-0.1.4+39.a81ab70.obscpio -> cage-0.1.5+0.83ffc57.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/.github/workflows/main.yml new/cage-0.1.5+0.83ffc57/.github/workflows/main.yml --- old/cage-0.1.4+39.a81ab70/.github/workflows/main.yml 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/.github/workflows/main.yml 2023-07-28 16:46:37.000000000 +0200 @@ -22,7 +22,7 @@ - name: Install dependencies (Alpine) if: "matrix.OS == 'alpine:edge'" - run: apk add build-base xcb-util-wm-dev libseat-dev clang git eudev-dev mesa-dev libdrm-dev libinput-dev libxkbcommon-dev pixman-dev wayland-dev meson wayland-protocols xwayland scdoc-doc + run: apk add build-base xcb-util-wm-dev libseat-dev clang git eudev-dev mesa-dev libdrm-dev libinput-dev libxkbcommon-dev pixman-dev wayland-dev meson wayland-protocols xwayland scdoc-doc hwdata - name: Install dependencies (Arch) if: "matrix.OS == 'archlinux:base-devel'" @@ -31,7 +31,7 @@ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc - name: Fetch wlroots as a subproject - run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0 + run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0 # TODO: use --fatal-meson-warnings when on wlroots 0.15.0 - name: Compile Cage (XWayland=${{ matrix.xwayland }}) @@ -48,9 +48,9 @@ - name: Install dependencies run: | pacman-key --init - pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc + pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc hwdata - name: Fetch wlroots as a subproject - run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0 + run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0 - name: Check for formatting changes run: | meson build-clang-format -Dxwayland=true @@ -67,9 +67,9 @@ - name: Install dependencies run: | pacman-key --init - pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc + pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc hwdata - name: Fetch wlroots as a subproject - run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0 + run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0 - name: Run scan-build run: | meson build-scan-build -Dxwayland=true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/README.md new/cage-0.1.5+0.83ffc57/README.md --- old/cage-0.1.4+39.a81ab70/README.md 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/README.md 2023-07-28 16:46:37.000000000 +0200 @@ -1,4 +1,4 @@ -# Cage: a Wayland kiosk [](https://builds.sr.ht/~hjdskes?) +# Cage: a Wayland kiosk <img src="https://www.hjdskes.nl/img/projects/cage/cage.svg" alt="Cage's logo" width="150px" align="right"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/cage.1.scd new/cage-0.1.5+0.83ffc57/cage.1.scd --- old/cage-0.1.4+39.a81ab70/cage.1.scd 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/cage.1.scd 2023-07-28 16:46:37.000000000 +0200 @@ -27,10 +27,6 @@ *last* Cage uses only the last connected monitor. *extend* Cage extends the display across all connected monitors. -*-r* - Rotate the output 90 degrees clockwise. This can be specified up to three - times, each resulting in an additional 90 degrees clockwise rotation. - *-s* Allow VT switching diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/cage.c new/cage-0.1.5+0.83ffc57/cage.c --- old/cage-0.1.4+39.a81ab70/cage.c 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/cage.c 2023-07-28 16:46:37.000000000 +0200 @@ -28,11 +28,16 @@ #include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_output_management_v1.h> #include <wlr/types/wlr_presentation_time.h> #include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_screencopy_v1.h> #include <wlr/types/wlr_server_decoration.h> +#include <wlr/types/wlr_single_pixel_buffer_v1.h> +#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_viewporter.h> +#include <wlr/types/wlr_virtual_keyboard_v1.h> +#include <wlr/types/wlr_virtual_pointer_v1.h> #if CAGE_HAS_XWAYLAND #include <wlr/types/wlr_xcursor_manager.h> #endif @@ -108,6 +113,8 @@ /* Close read, we only need write in the primary client process. */ close(fd[0]); execvp(argv[0], argv); + /* execvp() returns only on failure */ + wlr_log_errno(WLR_ERROR, "Failed to spawn client"); _exit(1); } else if (pid == -1) { wlr_log_errno(WLR_ERROR, "Unable to fork"); @@ -149,7 +156,12 @@ static bool drop_permissions(void) { + if (getuid() == 0 || getgid() == 0) { + wlr_log(WLR_INFO, "Running as root user, this is dangerous"); + return true; + } if (getuid() != geteuid() || getgid() != getegid()) { + wlr_log(WLR_INFO, "setuid/setgid bit detected, dropping permissions"); // Set the gid and uid in the correct order. if (setgid(getgid()) != 0 || setuid(getuid()) != 0) { wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); @@ -192,7 +204,6 @@ " -h\t Display this help message\n" " -m extend Extend the display across all connected outputs (default)\n" " -m last Use only the last connected output\n" - " -r\t Rotate the output 90 degrees clockwise, specify up to three times\n" " -s\t Allow VT switching\n" " -v\t Show the version number and exit\n" "\n" @@ -204,7 +215,7 @@ parse_args(struct cg_server *server, int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "dhm:rsv")) != -1) { + while ((c = getopt(argc, argv, "dhm:sv")) != -1) { switch (c) { case 'd': server->xdg_decoration = true; @@ -219,12 +230,6 @@ server->output_mode = CAGE_MULTI_OUTPUT_MODE_EXTEND; } break; - case 'r': - server->output_transform++; - if (server->output_transform > WL_OUTPUT_TRANSFORM_270) { - server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; - } - break; case 's': server->allow_vt_switch = true; break; @@ -254,13 +259,17 @@ struct wl_event_source *sigterm_source = NULL; struct wl_event_source *sigchld_source = NULL; struct wlr_compositor *compositor = NULL; + struct wlr_subcompositor *subcompositor = NULL; struct wlr_data_device_manager *data_device_manager = NULL; struct wlr_server_decoration_manager *server_decoration_manager = NULL; struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL; struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL; struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; + struct wlr_single_pixel_buffer_manager_v1 *single_pixel_buffer = NULL; struct wlr_xdg_output_manager_v1 *output_manager = NULL; struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; + struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard = NULL; + struct wlr_virtual_pointer_manager_v1 *virtual_pointer = NULL; struct wlr_viewporter *viewporter = NULL; struct wlr_presentation *presentation = NULL; struct wlr_xdg_shell *xdg_shell = NULL; @@ -334,6 +343,8 @@ ret = 1; goto end; } + server.output_layout_change.notify = handle_output_layout_change; + wl_signal_add(&server.output_layout->events.change, &server.output_layout_change); server.scene = wlr_scene_create(); if (!server.scene) { @@ -351,6 +362,13 @@ goto end; } + subcompositor = wlr_subcompositor_create(server.wl_display); + if (!subcompositor) { + wlr_log(WLR_ERROR, "Unable to create the wlroots subcompositor"); + ret = 1; + goto end; + } + data_device_manager = wlr_data_device_manager_create(server.wl_display); if (!data_device_manager) { wlr_log(WLR_ERROR, "Unable to create the data device manager"); @@ -388,7 +406,7 @@ wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1); wl_list_init(&server.inhibitors); - xdg_shell = wlr_xdg_shell_create(server.wl_display); + xdg_shell = wlr_xdg_shell_create(server.wl_display, 4); if (!xdg_shell) { wlr_log(WLR_ERROR, "Unable to create the XDG shell interface"); ret = 1; @@ -445,6 +463,13 @@ goto end; } + single_pixel_buffer = wlr_single_pixel_buffer_manager_v1_create(server.wl_display); + if (!single_pixel_buffer) { + wlr_log(WLR_ERROR, "Unable to create the single pixel buffer manager"); + ret = 1; + goto end; + } + output_manager = wlr_xdg_output_manager_v1_create(server.wl_display, server.output_layout); if (!output_manager) { wlr_log(WLR_ERROR, "Unable to create the output manager"); @@ -452,6 +477,17 @@ goto end; } + server.output_manager_v1 = wlr_output_manager_v1_create(server.wl_display); + if (!server.output_manager_v1) { + wlr_log(WLR_ERROR, "Unable to create the output manager"); + ret = 1; + goto end; + } + server.output_manager_apply.notify = handle_output_manager_apply; + wl_signal_add(&server.output_manager_v1->events.apply, &server.output_manager_apply); + server.output_manager_test.notify = handle_output_manager_test; + wl_signal_add(&server.output_manager_v1->events.test, &server.output_manager_test); + gamma_control_manager = wlr_gamma_control_manager_v1_create(server.wl_display); if (!gamma_control_manager) { wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); @@ -459,6 +495,22 @@ goto end; } + virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(server.wl_display); + if (!virtual_keyboard) { + wlr_log(WLR_ERROR, "Unable to create the virtual keyboard manager"); + ret = 1; + goto end; + } + wl_signal_add(&virtual_keyboard->events.new_virtual_keyboard, &server.new_virtual_keyboard); + + virtual_pointer = wlr_virtual_pointer_manager_v1_create(server.wl_display); + if (!virtual_pointer) { + wlr_log(WLR_ERROR, "Unable to create the virtual pointer manager"); + ret = 1; + goto end; + } + wl_signal_add(&virtual_pointer->events.new_virtual_pointer, &server.new_virtual_pointer); + #if CAGE_HAS_XWAYLAND xwayland = wlr_xwayland_create(server.wl_display, compositor, true); if (!xwayland) { @@ -522,8 +574,9 @@ } /* Place the cursor in the center of the output layout. */ - struct wlr_box *layout_box = wlr_output_layout_get_box(server.output_layout, NULL); - wlr_cursor_warp(server.seat->cursor, NULL, layout_box->width / 2, layout_box->height / 2); + struct wlr_box layout_box; + wlr_output_layout_get_box(server.output_layout, NULL, &layout_box); + wlr_cursor_warp(server.seat->cursor, NULL, layout_box.width / 2, layout_box.height / 2); wl_display_run(server.wl_display); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/meson.build new/cage-0.1.5+0.83ffc57/meson.build --- old/cage-0.1.4+39.a81ab70/meson.build 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/meson.build 2023-07-28 16:46:37.000000000 +0200 @@ -1,5 +1,5 @@ project('cage', 'c', - version: '0.1.4', + version: '0.1.5', license: 'MIT', meson_version: '>=0.58.1', default_options: [ @@ -35,7 +35,7 @@ ) endif -wlroots = dependency('wlroots', version: '>= 0.15.0', fallback: ['wlroots', 'wlroots']) +wlroots = dependency('wlroots', version: '>= 0.16.0', fallback: ['wlroots', 'wlroots']) wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') xkbcommon = dependency('xkbcommon') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/meson_options.txt new/cage-0.1.5+0.83ffc57/meson_options.txt --- old/cage-0.1.4+39.a81ab70/meson_options.txt 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/meson_options.txt 2023-07-28 16:46:37.000000000 +0200 @@ -1,2 +1,2 @@ option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') -option('xwayland', type: 'boolean', value: 'false', description: 'Enable support for X11 applications') +option('xwayland', type: 'boolean', value: false, description: 'Enable support for X11 applications') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/output.c new/cage-0.1.5+0.83ffc57/output.c --- old/cage-0.1.4+39.a81ab70/output.c 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/output.c 2023-07-28 16:46:37.000000000 +0200 @@ -22,13 +22,14 @@ #include <wlr/backend/x11.h> #endif #include <wlr/render/wlr_renderer.h> +#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_data_device.h> #include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_output_management_v1.h> #include <wlr/types/wlr_scene.h> -#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_xdg_shell.h> #include <wlr/util/log.h> #include <wlr/util/region.h> @@ -41,6 +42,32 @@ #include "xwayland.h" #endif +#define OUTPUT_CONFIG_UPDATED \ + (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_SCALE | WLR_OUTPUT_STATE_TRANSFORM | \ + WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) + +static void +update_output_manager_config(struct cg_server *server) +{ + struct wlr_output_configuration_v1 *config = wlr_output_configuration_v1_create(); + + struct cg_output *output; + wl_list_for_each (output, &server->outputs, link) { + struct wlr_output *wlr_output = output->wlr_output; + struct wlr_output_configuration_head_v1 *config_head = + wlr_output_configuration_head_v1_create(config, wlr_output); + struct wlr_box output_box; + + wlr_output_layout_get_box(server->output_layout, wlr_output, &output_box); + if (!wlr_box_empty(&output_box)) { + config_head->state.x = output_box.x; + config_head->state.y = output_box.y; + } + } + + wlr_output_manager_v1_set_configuration(server->output_manager_v1, config); +} + static void output_enable(struct cg_output *output) { @@ -57,6 +84,8 @@ output->scene_output = wlr_scene_get_scene_output(output->server->scene, wlr_output); assert(output->scene_output != NULL); + + update_output_manager_config(output->server); } static void @@ -77,6 +106,44 @@ wlr_output_commit(wlr_output); } +static bool +output_apply_config(struct cg_output *output, struct wlr_output_configuration_head_v1 *head, bool test_only) +{ + wlr_output_enable(output->wlr_output, head->state.enabled); + + if (head->state.enabled) { + /* Do not mess with these parameters for output to be disabled */ + wlr_output_set_scale(output->wlr_output, head->state.scale); + wlr_output_set_transform(output->wlr_output, head->state.transform); + + if (head->state.mode) { + wlr_output_set_mode(output->wlr_output, head->state.mode); + } else { + wlr_output_set_custom_mode(output->wlr_output, head->state.custom_mode.width, + head->state.custom_mode.height, head->state.custom_mode.refresh); + } + } + + if (test_only) { + bool ret = wlr_output_test(output->wlr_output); + wlr_output_rollback(output->wlr_output); + return ret; + } + + /* Apply output configuration */ + if (!wlr_output_commit(output->wlr_output)) { + return false; + } + + if (head->state.enabled) { + wlr_output_layout_add(output->server->output_layout, head->state.output, head->state.x, head->state.y); + } else { + wlr_output_layout_remove(output->server->output_layout, output->wlr_output); + } + + return true; +} + static void handle_output_frame(struct wl_listener *listener, void *data) { @@ -99,15 +166,21 @@ struct cg_output *output = wl_container_of(listener, output, commit); struct wlr_output_event_commit *event = data; - if (!output->wlr_output->enabled) { - return; + /* Notes: + * - output layout change will also be called if needed to position the views + * - always update output manager configuration even if the output is now disabled */ + + if (event->committed & WLR_OUTPUT_STATE_ENABLED) { + if (output->wlr_output->enabled) { + output->scene_output = wlr_scene_get_scene_output(output->server->scene, output->wlr_output); + assert(output->scene_output != NULL); + } else { + output->scene_output = NULL; + } } - if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) { - struct cg_view *view; - wl_list_for_each (view, &output->server->views, link) { - view_position(view); - } + if (event->committed & OUTPUT_CONFIG_UPDATED) { + update_output_manager_config(output->server); } } @@ -120,10 +193,17 @@ return; } - struct cg_view *view; - wl_list_for_each (view, &output->server->views, link) { - view_position(view); - } + view_position_all(output->server); + update_output_manager_config(output->server); +} + +void +handle_output_layout_change(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, output_layout_change); + + view_position_all(server); + update_output_manager_config(server); } static void @@ -145,16 +225,10 @@ if (wl_list_empty(&server->outputs)) { wl_display_terminate(server->wl_display); - } else if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST) { + } else if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST && !wl_list_empty(&server->outputs)) { struct cg_output *prev = wl_container_of(server->outputs.next, prev, link); - if (prev) { - output_enable(prev); - - struct cg_view *view; - wl_list_for_each (view, &server->views, link) { - view_position(view); - } - } + output_enable(prev); + view_position_all(server); } } @@ -217,13 +291,9 @@ } } - wlr_output_set_transform(wlr_output, output->server->output_transform); - - if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST) { + if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST && wl_list_length(&server->outputs) > 1) { struct cg_output *next = wl_container_of(output->link.next, next, link); - if (next) { - output_disable(next); - } + output_disable(next); } if (!wlr_xcursor_manager_load(server->seat->xcursor_manager, wlr_output->scale)) { @@ -232,11 +302,7 @@ } output_enable(output); - - struct cg_view *view; - wl_list_for_each (view, &output->server->views, link) { - view_position(view); - } + view_position_all(output->server); } void @@ -257,3 +323,49 @@ #endif } } + +static bool +output_config_apply(struct cg_server *server, struct wlr_output_configuration_v1 *config, bool test_only) +{ + struct wlr_output_configuration_head_v1 *head; + + wl_list_for_each (head, &config->heads, link) { + struct cg_output *output = head->state.output->data; + + if (!output_apply_config(output, head, test_only)) { + return false; + } + } + + return true; +} + +void +handle_output_manager_apply(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, output_manager_apply); + struct wlr_output_configuration_v1 *config = data; + + if (output_config_apply(server, config, false)) { + wlr_output_configuration_v1_send_succeeded(config); + } else { + wlr_output_configuration_v1_send_failed(config); + } + + wlr_output_configuration_v1_destroy(config); +} + +void +handle_output_manager_test(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, output_manager_test); + struct wlr_output_configuration_v1 *config = data; + + if (output_config_apply(server, config, true)) { + wlr_output_configuration_v1_send_succeeded(config); + } else { + wlr_output_configuration_v1_send_failed(config); + } + + wlr_output_configuration_v1_destroy(config); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/output.h new/cage-0.1.5+0.83ffc57/output.h --- old/cage-0.1.4+39.a81ab70/output.h 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/output.h 2023-07-28 16:46:37.000000000 +0200 @@ -21,6 +21,9 @@ struct wl_list link; // cg_server::outputs }; +void handle_output_manager_apply(struct wl_listener *listener, void *data); +void handle_output_manager_test(struct wl_listener *listener, void *data); +void handle_output_layout_change(struct wl_listener *listener, void *data); void handle_new_output(struct wl_listener *listener, void *data); void output_set_window_title(struct cg_output *output, const char *title); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/seat.c new/cage-0.1.5+0.83ffc57/seat.c --- old/cage-0.1.4+39.a81ab70/seat.c 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/seat.c 2023-07-28 16:46:37.000000000 +0200 @@ -6,11 +6,14 @@ * See the LICENSE file accompanying this file. */ +#define _POSIX_C_SOURCE 200809L + #include "config.h" #include <assert.h> #include <linux/input-event-codes.h> #include <stdlib.h> +#include <string.h> #include <wayland-server-core.h> #include <wlr/backend.h> #include <wlr/backend/multi.h> @@ -21,8 +24,9 @@ #include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_seat.h> -#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_touch.h> +#include <wlr/types/wlr_virtual_keyboard_v1.h> +#include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_xcursor_manager.h> #include <wlr/util/log.h> #if CAGE_HAS_XWAYLAND @@ -53,20 +57,31 @@ static struct cg_view * desktop_view_at(struct cg_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->node, lx, ly, sx, sy); - if (node == NULL || node->type != WLR_SCENE_NODE_SURFACE) { + struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy); + if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) { + return NULL; + } + + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_buffer(scene_buffer); + if (!scene_surface) { return NULL; } - *surface = wlr_scene_surface_from_node(node)->surface; + *surface = scene_surface->surface; /* Walk up the tree until we find a node with a data pointer. When done, * we've found the node representing the view. */ - while (node != NULL && node->data == NULL) { - node = node->parent; + while (!node->data) { + if (!node->parent) { + node = NULL; + break; + } + + node = &node->parent->node; } - assert(node != NULL); + assert(node != NULL); return node->data; } @@ -118,16 +133,16 @@ } static void -map_input_device_to_output(struct cg_seat *seat, struct wlr_input_device *device) +map_input_device_to_output(struct cg_seat *seat, struct wlr_input_device *device, const char *output_name) { - if (!device->output_name) { + if (!output_name) { wlr_log(WLR_INFO, "Input device %s cannot be mapped to an output device\n", device->name); return; } struct cg_output *output; wl_list_for_each (output, &seat->server->outputs, link) { - if (strcmp(device->output_name, output->wlr_output->name) == 0) { + if (strcmp(output_name, output->wlr_output->name) == 0) { wlr_log(WLR_INFO, "Mapping input device %s to output device %s\n", device->name, output->wlr_output->name); wlr_cursor_map_input_to_output(seat->cursor, device, output->wlr_output); @@ -145,7 +160,7 @@ struct cg_seat *seat = touch->seat; wl_list_remove(&touch->link); - wlr_cursor_detach_input_device(seat->cursor, touch->device); + wlr_cursor_detach_input_device(seat->cursor, &touch->touch->base); wl_list_remove(&touch->destroy.link); free(touch); @@ -153,7 +168,7 @@ } static void -handle_new_touch(struct cg_seat *seat, struct wlr_input_device *device) +handle_new_touch(struct cg_seat *seat, struct wlr_touch *wlr_touch) { struct cg_touch *touch = calloc(1, sizeof(struct cg_touch)); if (!touch) { @@ -162,14 +177,14 @@ } touch->seat = seat; - touch->device = device; - wlr_cursor_attach_input_device(seat->cursor, device); + touch->touch = wlr_touch; + wlr_cursor_attach_input_device(seat->cursor, &wlr_touch->base); wl_list_insert(&seat->touch, &touch->link); touch->destroy.notify = handle_touch_destroy; - wl_signal_add(&touch->device->events.destroy, &touch->destroy); + wl_signal_add(&wlr_touch->base.events.destroy, &touch->destroy); - map_input_device_to_output(seat, device); + map_input_device_to_output(seat, &wlr_touch->base, wlr_touch->output_name); } static void @@ -179,7 +194,7 @@ struct cg_seat *seat = pointer->seat; wl_list_remove(&pointer->link); - wlr_cursor_detach_input_device(seat->cursor, pointer->device); + wlr_cursor_detach_input_device(seat->cursor, &pointer->pointer->base); wl_list_remove(&pointer->destroy.link); free(pointer); @@ -187,7 +202,7 @@ } static void -handle_new_pointer(struct cg_seat *seat, struct wlr_input_device *device) +handle_new_pointer(struct cg_seat *seat, struct wlr_pointer *wlr_pointer) { struct cg_pointer *pointer = calloc(1, sizeof(struct cg_pointer)); if (!pointer) { @@ -196,21 +211,42 @@ } pointer->seat = seat; - pointer->device = device; - wlr_cursor_attach_input_device(seat->cursor, device); + pointer->pointer = wlr_pointer; + wlr_cursor_attach_input_device(seat->cursor, &wlr_pointer->base); wl_list_insert(&seat->pointers, &pointer->link); pointer->destroy.notify = handle_pointer_destroy; - wl_signal_add(&device->events.destroy, &pointer->destroy); + wl_signal_add(&wlr_pointer->base.events.destroy, &pointer->destroy); + + map_input_device_to_output(seat, &wlr_pointer->base, wlr_pointer->output_name); +} + +static void +handle_virtual_pointer(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, new_virtual_pointer); + struct cg_seat *seat = server->seat; + struct wlr_virtual_pointer_v1_new_pointer_event *event = data; + struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; + struct wlr_pointer *wlr_pointer = &pointer->pointer; - map_input_device_to_output(seat, device); + /* We'll want to map the device back to an output later, this is a bit + * sub-optimal (we could just keep the suggested_output), but just copy + * its name so we do like other devices + */ + if (event->suggested_output != NULL) { + wlr_pointer->output_name = strdup(event->suggested_output->name); + } + /* TODO: event->suggested_seat should be checked if we handle multiple seats */ + handle_new_pointer(seat, wlr_pointer); + update_capabilities(seat); } static void -handle_modifier_event(struct wlr_input_device *device, struct cg_seat *seat) +handle_modifier_event(struct wlr_keyboard *keyboard, struct cg_seat *seat) { - wlr_seat_set_keyboard(seat->seat, device); - wlr_seat_keyboard_notify_modifiers(seat->seat, &device->keyboard->modifiers); + wlr_seat_set_keyboard(seat->seat, keyboard); + wlr_seat_keyboard_notify_modifiers(seat->seat, &keyboard->modifiers); wlr_idle_notify_activity(seat->server->idle, seat->seat); } @@ -240,18 +276,18 @@ } static void -handle_key_event(struct wlr_input_device *device, struct cg_seat *seat, void *data) +handle_key_event(struct wlr_keyboard *keyboard, struct cg_seat *seat, void *data) { - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; /* Translate from libinput keycode to an xkbcommon keycode. */ xkb_keycode_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(device->keyboard->xkb_state, keycode, &syms); + int nsyms = xkb_state_key_get_syms(keyboard->xkb_state, keycode, &syms); bool handled = false; - uint32_t modifiers = wlr_keyboard_get_modifiers(device->keyboard); + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard); if ((modifiers & WLR_MODIFIER_ALT) && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { /* If Alt is held down and this button was pressed, we * attempt to process it as a compositor @@ -263,7 +299,7 @@ if (!handled) { /* Otherwise, we pass it along to the client. */ - wlr_seat_set_keyboard(seat->seat, device); + wlr_seat_set_keyboard(seat->seat, keyboard); wlr_seat_keyboard_notify_key(seat->seat, event->time_msec, event->keycode, event->state); } @@ -274,27 +310,32 @@ handle_keyboard_group_key(struct wl_listener *listener, void *data) { struct cg_keyboard_group *cg_group = wl_container_of(listener, cg_group, key); - handle_key_event(cg_group->wlr_group->input_device, cg_group->seat, data); + handle_key_event(&cg_group->wlr_group->keyboard, cg_group->seat, data); } static void handle_keyboard_group_modifiers(struct wl_listener *listener, void *data) { struct cg_keyboard_group *group = wl_container_of(listener, group, modifiers); - handle_modifier_event(group->wlr_group->input_device, group->seat); + handle_modifier_event(&group->wlr_group->keyboard, group->seat); } static void -cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat) +cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat, bool virtual) { - struct wlr_keyboard *wlr_keyboard = device->keyboard; - - struct cg_keyboard_group *group; - wl_list_for_each (group, &seat->keyboard_groups, link) { - struct wlr_keyboard_group *wlr_group = group->wlr_group; - if (wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard)) { - wlr_log(WLR_DEBUG, "Added new keyboard to existing group"); - return; + /* We apparently should not group virtual keyboards, + * so create a new group with it + */ + if (!virtual) { + struct cg_keyboard_group *group; + wl_list_for_each (group, &seat->keyboard_groups, link) { + if (group->is_virtual) + continue; + struct wlr_keyboard_group *wlr_group = group->wlr_group; + if (wlr_keyboard_group_add_keyboard(wlr_group, keyboard)) { + wlr_log(WLR_DEBUG, "Added new keyboard to existing group"); + return; + } } } @@ -306,6 +347,7 @@ return; } cg_group->seat = seat; + cg_group->is_virtual = virtual; cg_group->wlr_group = wlr_keyboard_group_create(); if (cg_group->wlr_group == NULL) { wlr_log(WLR_ERROR, "Failed to create wlr keyboard group."); @@ -313,14 +355,14 @@ } cg_group->wlr_group->data = cg_group; - wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, device->keyboard->keymap); + wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, keyboard->keymap); - wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard, wlr_keyboard->repeat_info.rate, - wlr_keyboard->repeat_info.delay); + wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard, keyboard->repeat_info.rate, + keyboard->repeat_info.delay); wlr_log(WLR_DEBUG, "Created keyboard group"); - wlr_keyboard_group_add_keyboard(cg_group->wlr_group, wlr_keyboard); + wlr_keyboard_group_add_keyboard(cg_group->wlr_group, keyboard); wl_list_insert(&seat->keyboard_groups, &cg_group->link); wl_signal_add(&cg_group->wlr_group->keyboard.events.key, &cg_group->key); @@ -338,7 +380,7 @@ } static void -handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device) +handle_new_keyboard(struct cg_seat *seat, struct wlr_keyboard *keyboard, bool virtual) { struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -353,15 +395,30 @@ return; } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); - wlr_keyboard_set_repeat_info(device->keyboard, 25, 600); + wlr_keyboard_set_repeat_info(keyboard, 25, 600); - cg_keyboard_group_add(device, seat); + cg_keyboard_group_add(keyboard, seat, virtual); - wlr_seat_set_keyboard(seat->seat, device); + wlr_seat_set_keyboard(seat->seat, keyboard); +} + +static void +handle_virtual_keyboard(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, new_virtual_keyboard); + struct cg_seat *seat = server->seat; + struct wlr_virtual_keyboard_v1 *keyboard = data; + struct wlr_keyboard *wlr_keyboard = &keyboard->keyboard; + + /* TODO: If multiple seats are supported, check keyboard->seat + * to select the appropriate one */ + + handle_new_keyboard(seat, wlr_keyboard, true); + update_capabilities(seat); } static void @@ -372,13 +429,13 @@ switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD: - handle_new_keyboard(seat, device); + handle_new_keyboard(seat, wlr_keyboard_from_input_device(device), false); break; case WLR_INPUT_DEVICE_POINTER: - handle_new_pointer(seat, device); + handle_new_pointer(seat, wlr_pointer_from_input_device(device)); break; case WLR_INPUT_DEVICE_TOUCH: - handle_new_touch(seat, device); + handle_new_touch(seat, wlr_touch_from_input_device(device)); break; case WLR_INPUT_DEVICE_SWITCH: wlr_log(WLR_DEBUG, "Switch input is not implemented"); @@ -433,10 +490,10 @@ handle_touch_down(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, touch_down); - struct wlr_event_touch_down *event = data; + struct wlr_touch_down_event *event = data; double lx, ly; - wlr_cursor_absolute_to_layout_coords(seat->cursor, event->device, event->x, event->y, &lx, &ly); + wlr_cursor_absolute_to_layout_coords(seat->cursor, &event->touch->base, event->x, event->y, &lx, &ly); double sx, sy; struct wlr_surface *surface; @@ -451,7 +508,7 @@ seat->touch_id = event->touch_id; seat->touch_lx = lx; seat->touch_ly = ly; - press_cursor_button(seat, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED, lx, ly); + press_cursor_button(seat, &event->touch->base, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED, lx, ly); } wlr_idle_notify_activity(seat->server->idle, seat->seat); @@ -461,14 +518,14 @@ handle_touch_up(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, touch_up); - struct wlr_event_touch_up *event = data; + struct wlr_touch_up_event *event = data; if (!wlr_seat_touch_get_point(seat->seat, event->touch_id)) { return; } if (wlr_seat_touch_num_points(seat->seat) == 1) { - press_cursor_button(seat, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED, + press_cursor_button(seat, &event->touch->base, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED, seat->touch_lx, seat->touch_ly); } @@ -480,14 +537,14 @@ handle_touch_motion(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, touch_motion); - struct wlr_event_touch_motion *event = data; + struct wlr_touch_motion_event *event = data; if (!wlr_seat_touch_get_point(seat->seat, event->touch_id)) { return; } double lx, ly; - wlr_cursor_absolute_to_layout_coords(seat->cursor, event->device, event->x, event->y, &lx, &ly); + wlr_cursor_absolute_to_layout_coords(seat->cursor, &event->touch->base, event->x, event->y, &lx, &ly); double sx, sy; struct wlr_surface *surface; @@ -521,7 +578,7 @@ handle_cursor_axis(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_axis); - struct wlr_event_pointer_axis *event = data; + struct wlr_pointer_axis_event *event = data; wlr_seat_pointer_notify_axis(seat->seat, event->time_msec, event->orientation, event->delta, event->delta_discrete, event->source); @@ -532,10 +589,10 @@ handle_cursor_button(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_button); - struct wlr_event_pointer_button *event = data; + struct wlr_pointer_button_event *event = data; wlr_seat_pointer_notify_button(seat->seat, event->time_msec, event->button, event->state); - press_cursor_button(seat, event->device, event->time_msec, event->button, event->state, seat->cursor->x, + press_cursor_button(seat, &event->pointer->base, event->time_msec, event->button, event->state, seat->cursor->x, seat->cursor->y); wlr_idle_notify_activity(seat->server->idle, seat->seat); } @@ -569,9 +626,9 @@ handle_cursor_motion_absolute(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion_absolute); - struct wlr_event_pointer_motion_absolute *event = data; + struct wlr_pointer_motion_absolute_event *event = data; - wlr_cursor_warp_absolute(seat->cursor, event->device, event->x, event->y); + wlr_cursor_warp_absolute(seat->cursor, &event->pointer->base, event->x, event->y); process_cursor_motion(seat, event->time_msec); wlr_idle_notify_activity(seat->server->idle, seat->seat); } @@ -580,9 +637,9 @@ handle_cursor_motion(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion); - struct wlr_event_pointer_motion *event = data; + struct wlr_pointer_motion_event *event = data; - wlr_cursor_move(seat->cursor, event->device, event->delta_x, event->delta_y); + wlr_cursor_move(seat->cursor, &event->pointer->base, event->delta_x, event->delta_y); process_cursor_motion(seat, event->time_msec); wlr_idle_notify_activity(seat->server->idle, seat->seat); } @@ -611,7 +668,7 @@ break; } - wlr_scene_node_set_position(drag_icon->scene_node, drag_icon->lx, drag_icon->ly); + wlr_scene_node_set_position(&drag_icon->scene_tree->node, drag_icon->lx, drag_icon->ly); } static void @@ -621,7 +678,7 @@ wl_list_remove(&drag_icon->link); wl_list_remove(&drag_icon->destroy.link); - wlr_scene_node_destroy(drag_icon->scene_node); + wlr_scene_node_destroy(&drag_icon->scene_tree->node); free(drag_icon); } @@ -664,8 +721,8 @@ } drag_icon->seat = seat; drag_icon->wlr_drag_icon = wlr_drag_icon; - drag_icon->scene_node = wlr_scene_subsurface_tree_create(&seat->server->scene->node, wlr_drag_icon->surface); - if (!drag_icon->scene_node) { + drag_icon->scene_tree = wlr_scene_subsurface_tree_create(&seat->server->scene->tree, wlr_drag_icon->surface); + if (!drag_icon->scene_tree) { free(drag_icon); return; } @@ -789,6 +846,9 @@ seat->new_input.notify = handle_new_input; wl_signal_add(&backend->events.new_input, &seat->new_input); + server->new_virtual_keyboard.notify = handle_virtual_keyboard; + server->new_virtual_pointer.notify = handle_virtual_pointer; + wl_list_init(&seat->drag_icons); seat->request_start_drag.notify = handle_request_start_drag; wl_signal_add(&seat->seat->events.request_start_drag, &seat->request_start_drag); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/seat.h new/cage-0.1.5+0.83ffc57/seat.h --- old/cage-0.1.4+39.a81ab70/seat.h 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/seat.h 2023-07-28 16:46:37.000000000 +0200 @@ -55,12 +55,13 @@ struct wl_listener key; struct wl_listener modifiers; struct wl_list link; // cg_seat::keyboard_groups + bool is_virtual; }; struct cg_pointer { struct wl_list link; // seat::pointers struct cg_seat *seat; - struct wlr_input_device *device; + struct wlr_pointer *pointer; struct wl_listener destroy; }; @@ -68,7 +69,7 @@ struct cg_touch { struct wl_list link; // seat::touch struct cg_seat *seat; - struct wlr_input_device *device; + struct wlr_touch *touch; struct wl_listener destroy; }; @@ -77,7 +78,7 @@ struct wl_list link; // seat::drag_icons struct cg_seat *seat; struct wlr_drag_icon *wlr_drag_icon; - struct wlr_scene_node *scene_node; + struct wlr_scene_tree *scene_tree; /* The drag icon has a position in layout coordinates. */ double lx, ly; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/server.h new/cage-0.1.5+0.83ffc57/server.h --- old/cage-0.1.4+39.a81ab70/server.h 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/server.h 2023-07-28 16:46:37.000000000 +0200 @@ -12,10 +12,6 @@ #include <wlr/xwayland.h> #endif -#include "output.h" -#include "seat.h" -#include "view.h" - enum cg_multi_output_mode { CAGE_MULTI_OUTPUT_MODE_EXTEND, CAGE_MULTI_OUTPUT_MODE_LAST, @@ -41,16 +37,22 @@ * some outputs may be disabled. */ struct wl_list outputs; // cg_output::link struct wl_listener new_output; + struct wl_listener output_layout_change; struct wl_listener xdg_toplevel_decoration; struct wl_listener new_xdg_shell_surface; + + struct wl_listener new_virtual_keyboard; + struct wl_listener new_virtual_pointer; #if CAGE_HAS_XWAYLAND struct wl_listener new_xwayland_surface; #endif + struct wlr_output_manager_v1 *output_manager_v1; + struct wl_listener output_manager_apply; + struct wl_listener output_manager_test; bool xdg_decoration; bool allow_vt_switch; - enum wl_output_transform output_transform; }; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/view.c new/cage-0.1.5+0.83ffc57/view.c --- old/cage-0.1.4+39.a81ab70/view.c 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/view.c 2023-07-28 16:46:37.000000000 +0200 @@ -15,7 +15,6 @@ #include <wayland-server-core.h> #include <wlr/types/wlr_output.h> #include <wlr/types/wlr_scene.h> -#include <wlr/types/wlr_surface.h> #include "output.h" #include "seat.h" @@ -68,7 +67,7 @@ view->lx = layout_box->x; view->ly = layout_box->y; - wlr_scene_node_set_position(view->scene_node, view->lx, view->ly); + wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); view->impl->maximize(view, layout_box->width, layout_box->height); } @@ -82,18 +81,28 @@ view->lx = (layout_box->width - width) / 2; view->ly = (layout_box->height - height) / 2; - wlr_scene_node_set_position(view->scene_node, view->lx, view->ly); + wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly); } void view_position(struct cg_view *view) { - struct wlr_box *layout_box = wlr_output_layout_get_box(view->server->output_layout, NULL); + struct wlr_box layout_box; + wlr_output_layout_get_box(view->server->output_layout, NULL, &layout_box); - if (view_is_primary(view) || view_extends_output_layout(view, layout_box)) { - view_maximize(view, layout_box); + if (view_is_primary(view) || view_extends_output_layout(view, &layout_box)) { + view_maximize(view, &layout_box); } else { - view_center(view, layout_box); + view_center(view, &layout_box); + } +} + +void +view_position_all(struct cg_server *server) +{ + struct cg_view *view; + wl_list_for_each (view, &server->views, link) { + view_position(view); } } @@ -102,7 +111,7 @@ { wl_list_remove(&view->link); - wlr_scene_node_destroy(view->scene_node); + wlr_scene_node_destroy(&view->scene_tree->node); view->wlr_surface->data = NULL; view->wlr_surface = NULL; @@ -111,12 +120,12 @@ void view_map(struct cg_view *view, struct wlr_surface *surface) { - view->scene_node = wlr_scene_subsurface_tree_create(&view->server->scene->node, surface); - if (!view->scene_node) { + view->scene_tree = wlr_scene_subsurface_tree_create(&view->server->scene->tree, surface); + if (!view->scene_tree) { wl_resource_post_no_memory(surface->resource); return; } - view->scene_node->data = view; + view->scene_tree->node.data = view; view->wlr_surface = surface; surface->data = view; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/view.h new/cage-0.1.5+0.83ffc57/view.h --- old/cage-0.1.4+39.a81ab70/view.h 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/view.h 2023-07-28 16:46:37.000000000 +0200 @@ -5,7 +5,7 @@ #include <stdbool.h> #include <wayland-server-core.h> -#include <wlr/types/wlr_surface.h> +#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_xdg_shell.h> #include <wlr/util/box.h> #if CAGE_HAS_XWAYLAND @@ -25,7 +25,7 @@ struct cg_server *server; struct wl_list link; // server::views struct wlr_surface *wlr_surface; - struct wlr_scene_node *scene_node; + struct wlr_scene_tree *scene_tree; /* The view has a position in layout coordinates. */ int lx, ly; @@ -49,6 +49,7 @@ bool view_is_transient_for(struct cg_view *child, struct cg_view *parent); void view_activate(struct cg_view *view, bool activate); void view_position(struct cg_view *view); +void view_position_all(struct cg_server *server); void view_unmap(struct cg_view *view); void view_map(struct cg_view *view, struct wlr_surface *surface); void view_destroy(struct cg_view *view); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/xdg_shell.c new/cage-0.1.5+0.83ffc57/xdg_shell.c --- old/cage-0.1.4+39.a81ab70/xdg_shell.c 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/xdg_shell.c 2023-07-28 16:46:37.000000000 +0200 @@ -67,18 +67,19 @@ popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup) { struct cg_server *server = view->server; - struct wlr_box *popup_box = &popup->geometry; + struct wlr_box *popup_box = &popup->current.geometry; struct wlr_output_layout *output_layout = server->output_layout; struct wlr_output *wlr_output = wlr_output_layout_output_at(output_layout, view->lx + popup_box->x, view->ly + popup_box->y); - struct wlr_box *output_box = wlr_output_layout_get_box(output_layout, wlr_output); + struct wlr_box output_box; + wlr_output_layout_get_box(output_layout, wlr_output, &output_box); struct wlr_box output_toplevel_box = { - .x = output_box->x - view->lx, - .y = output_box->y - view->ly, - .width = output_box->width, - .height = output_box->height, + .x = output_box.x - view->lx, + .y = output_box.y - view->ly, + .width = output_box.width, + .height = output_box.height, }; wlr_xdg_popup_unconstrain_from_box(popup, &output_toplevel_box); @@ -94,7 +95,7 @@ get_title(struct cg_view *view) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - return xdg_shell_view->xdg_surface->toplevel->title; + return xdg_shell_view->xdg_toplevel->title; } static void @@ -103,7 +104,7 @@ struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); struct wlr_box geom; - wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_surface, &geom); + wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_toplevel->base, &geom); *width_out = geom.width; *height_out = geom.height; } @@ -112,12 +113,9 @@ is_primary(struct cg_view *view) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - struct wlr_xdg_surface *xdg_surface = xdg_shell_view->xdg_surface; + struct wlr_xdg_toplevel *parent = xdg_shell_view->xdg_toplevel->parent; - struct wlr_xdg_surface *parent = xdg_surface->toplevel->parent; - enum wlr_xdg_surface_role role = xdg_surface->role; - - return parent == NULL && role == WLR_XDG_SURFACE_ROLE_TOPLEVEL; + return parent == NULL; } static bool @@ -127,14 +125,13 @@ return false; } struct cg_xdg_shell_view *_child = xdg_shell_view_from_view(child); - struct wlr_xdg_surface *xdg_surface = _child->xdg_surface; + struct wlr_xdg_toplevel *xdg_toplevel = _child->xdg_toplevel; struct cg_xdg_shell_view *_parent = xdg_shell_view_from_view(parent); - struct wlr_xdg_surface *parent_xdg_surface = _parent->xdg_surface; - while (xdg_surface) { - if (xdg_surface->toplevel->parent == parent_xdg_surface) { + while (xdg_toplevel) { + if (xdg_toplevel->parent == _parent->xdg_toplevel) { return true; } - xdg_surface = xdg_surface->toplevel->parent; + xdg_toplevel = xdg_toplevel->parent; } return false; } @@ -143,15 +140,15 @@ activate(struct cg_view *view, bool activate) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_toplevel_set_activated(xdg_shell_view->xdg_surface, activate); + wlr_xdg_toplevel_set_activated(xdg_shell_view->xdg_toplevel, activate); } static void maximize(struct cg_view *view, int output_width, int output_height) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface, output_width, output_height); - wlr_xdg_toplevel_set_maximized(xdg_shell_view->xdg_surface, true); + wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_toplevel, output_width, output_height); + wlr_xdg_toplevel_set_maximized(xdg_shell_view->xdg_toplevel, true); } static void @@ -165,16 +162,17 @@ handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, void *data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_fullscreen); - struct wlr_xdg_toplevel_set_fullscreen_event *event = data; /** * Certain clients do not like figuring out their own window geometry if they * display in fullscreen mode, so we set it here. */ - struct wlr_box *layout_box = wlr_output_layout_get_box(xdg_shell_view->view.server->output_layout, NULL); - wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface, layout_box->width, layout_box->height); + struct wlr_box layout_box; + wlr_output_layout_get_box(xdg_shell_view->view.server->output_layout, NULL, &layout_box); + wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_toplevel, layout_box.width, layout_box.height); - wlr_xdg_toplevel_set_fullscreen(xdg_shell_view->xdg_surface, event->fullscreen); + wlr_xdg_toplevel_set_fullscreen(xdg_shell_view->xdg_toplevel, + xdg_shell_view->xdg_toplevel->requested.fullscreen); } static void @@ -192,7 +190,7 @@ struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, map); struct cg_view *view = &xdg_shell_view->view; - view_map(view, xdg_shell_view->xdg_surface->surface); + view_map(view, xdg_shell_view->xdg_toplevel->base->surface); } static void @@ -205,7 +203,7 @@ wl_list_remove(&xdg_shell_view->unmap.link); wl_list_remove(&xdg_shell_view->destroy.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); - xdg_shell_view->xdg_surface = NULL; + xdg_shell_view->xdg_toplevel = NULL; view_destroy(view); } @@ -235,7 +233,7 @@ } view_init(&xdg_shell_view->view, server, CAGE_XDG_SHELL_VIEW, &xdg_shell_view_impl); - xdg_shell_view->xdg_surface = xdg_surface; + xdg_shell_view->xdg_toplevel = xdg_surface->toplevel; xdg_shell_view->map.notify = handle_xdg_shell_surface_map; wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); @@ -255,31 +253,31 @@ return; } - struct wlr_scene_node *parent_scene_node = NULL; + struct wlr_scene_tree *parent_scene_tree = NULL; struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface(popup->parent); switch (parent->role) { case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; - parent_scene_node = view->scene_node; + parent_scene_tree = view->scene_tree; break; case WLR_XDG_SURFACE_ROLE_POPUP: - parent_scene_node = parent->data; + parent_scene_tree = parent->data; break; case WLR_XDG_SURFACE_ROLE_NONE: break; } - if (parent_scene_node == NULL) { + if (parent_scene_tree == NULL) { return; } - struct wlr_scene_node *popup_scene_node = wlr_scene_xdg_surface_create(parent_scene_node, xdg_surface); - if (popup_scene_node == NULL) { + struct wlr_scene_tree *popup_scene_tree = wlr_scene_xdg_surface_create(parent_scene_tree, xdg_surface); + if (popup_scene_tree == NULL) { wlr_log(WLR_ERROR, "Failed to allocate scene-graph node for XDG popup"); return; } popup_unconstrain(view, popup); - xdg_surface->data = popup_scene_node; + xdg_surface->data = popup_scene_tree; break; case WLR_XDG_SURFACE_ROLE_NONE: assert(false); // unreachable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/xdg_shell.h new/cage-0.1.5+0.83ffc57/xdg_shell.h --- old/cage-0.1.4+39.a81ab70/xdg_shell.h 2022-08-19 11:59:41.000000000 +0200 +++ new/cage-0.1.5+0.83ffc57/xdg_shell.h 2023-07-28 16:46:37.000000000 +0200 @@ -9,7 +9,7 @@ struct cg_xdg_shell_view { struct cg_view view; - struct wlr_xdg_surface *xdg_surface; + struct wlr_xdg_toplevel *xdg_toplevel; struct wl_listener destroy; struct wl_listener unmap; ++++++ cage.obsinfo ++++++ --- /var/tmp/diff_new_pack.jdTBjW/_old 2023-08-02 16:50:37.713566247 +0200 +++ /var/tmp/diff_new_pack.jdTBjW/_new 2023-08-02 16:50:37.713566247 +0200 @@ -1,5 +1,5 @@ name: cage -version: 0.1.4+39.a81ab70 -mtime: 1660903181 -commit: a81ab701d73d0f43c9bb9747e5fdf3c5e226139c +version: 0.1.5+0.83ffc57 +mtime: 1690555597 +commit: 83ffc574be860527814c595756a558c228a3475d
