From 510257c0e9a2311d1d4087b29a80eb57d25c6105 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 9 Apr 2023 13:47:05 +0100 Subject: [PATCH] [WIP] Global Shortcuts impl (#35) Implements the `GlobalShortcuts` portal via `hyprland-global-shortcuts-v1` --------- Co-authored-by: Mihai Fufezan --- flake.lock | 12 +- hyprland.portal | 2 +- include/global_shortcuts.h | 31 ++ include/xdpw.h | 60 ++- meson.build | 1 + protocols/meson.build | 1 + src/core/main.c | 464 ++++++++++----------- src/globalshortcuts/global_shortcuts.c | 537 +++++++++++++++++++++++++ src/screencast/wlr_screencast.c | 217 ++++------ subprojects/hyprland-protocols | 2 +- 10 files changed, 924 insertions(+), 403 deletions(-) create mode 100644 include/global_shortcuts.h create mode 100644 src/globalshortcuts/global_shortcuts.c diff --git a/flake.lock b/flake.lock index 9afc37e..7ab1e1f 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1671839510, - "narHash": "sha256-+PY1qqJfmZzzROgcIY4I7AkCwpnC+qBIYk2eFoA9RWc=", + "lastModified": 1680997116, + "narHash": "sha256-nNyoatiHmTMczrCoHCH2LIRfSF8n9ZPZ1O7WNMxcbR4=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "b8f55e02a328c47ed373133c52483bbfa20a1b75", + "rev": "d7d403b711b60e8136295b0d4229e89a115e80cc", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1669969257, - "narHash": "sha256-mOS13sK3v+kfgP+1Mh56ohiG8uVhLHAo7m/q9kqAehc=", + "lastModified": 1680945546, + "narHash": "sha256-8FuaH5t/aVi/pR1XxnF0qi4WwMYC+YxlfdsA0V+TEuQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b72b8b94cf0c012b0252a9100a636cad69696666", + "rev": "d9f759f2ea8d265d974a6e1259bd510ac5844c5d", "type": "github" }, "original": { diff --git a/hyprland.portal b/hyprland.portal index 72d5b32..d3e2cbe 100644 --- a/hyprland.portal +++ b/hyprland.portal @@ -1,4 +1,4 @@ [portal] DBusName=org.freedesktop.impl.portal.desktop.hyprland -Interfaces=org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.ScreenCast; +Interfaces=org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.ScreenCast;org.freedesktop.impl.portal.GlobalShortcuts; UseIn=wlroots;Hyprland;sway;Wayfire;river; diff --git a/include/global_shortcuts.h b/include/global_shortcuts.h new file mode 100644 index 0000000..4b8f1f7 --- /dev/null +++ b/include/global_shortcuts.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "protocols/hyprland-global-shortcuts-v1-client-protocol.h" + +struct xdpw_state; +struct xdpw_session; + +struct globalShortcut { + char* name; + char* description; + struct wl_list link; + struct hyprland_global_shortcut_v1* hlShortcut; + bool bound; +}; + +struct globalShortcutsClient { + struct xdpw_session* session; + struct wl_list shortcuts; // struct globalShortcut* + struct wl_list link; + char* parent_window; + bool sentShortcuts; +}; + +struct globalShortcutsInstance { + struct hyprland_global_shortcuts_manager_v1* manager; + struct wl_list shortcutClients; // struct globalShortcutsClient* +}; + +void initShortcutsInstance(struct xdpw_state* state, struct globalShortcutsInstance* instance); \ No newline at end of file diff --git a/include/xdpw.h b/include/xdpw.h index 5ae4167..e899786 100644 --- a/include/xdpw.h +++ b/include/xdpw.h @@ -10,52 +10,51 @@ #include #endif +#include "config.h" +#include "global_shortcuts.h" #include "screencast_common.h" #include "screenshot_common.h" -#include "config.h" struct xdpw_state { - struct wl_list xdpw_sessions; - sd_bus *bus; - struct wl_display *wl_display; - struct pw_loop *pw_loop; - struct xdpw_screencast_context screencast; - uint32_t screencast_source_types; // bitfield of enum source_types - uint32_t screencast_cursor_modes; // bitfield of enum cursor_modes - uint32_t screencast_version; - uint32_t screenshot_version; - struct xdpw_config *config; - int timer_poll_fd; - struct wl_list timers; - struct xdpw_timer *next_timer; + struct wl_list xdpw_sessions; + sd_bus *bus; + struct wl_display *wl_display; + struct pw_loop *pw_loop; + struct xdpw_screencast_context screencast; + uint32_t screencast_source_types; // bitfield of enum source_types + uint32_t screencast_cursor_modes; // bitfield of enum cursor_modes + uint32_t screencast_version; + uint32_t screenshot_version; + struct xdpw_config *config; + int timer_poll_fd; + struct wl_list timers; + struct xdpw_timer *next_timer; + struct globalShortcutsInstance shortcutsInstance; }; struct xdpw_request { - sd_bus_slot *slot; + sd_bus_slot *slot; }; struct xdpw_session { - struct wl_list link; - sd_bus_slot *slot; - char *session_handle; - struct xdpw_screencast_instance *screencast_instance; + struct wl_list link; + sd_bus_slot *slot; + char *session_handle; + char *app_id; + struct xdpw_screencast_instance *screencast_instance; }; typedef void (*xdpw_event_loop_timer_func_t)(void *data); struct xdpw_timer { - struct xdpw_state *state; - xdpw_event_loop_timer_func_t func; - void *user_data; - struct timespec at; - struct wl_list link; // xdpw_state::timers + struct xdpw_state *state; + xdpw_event_loop_timer_func_t func; + void *user_data; + struct timespec at; + struct wl_list link; // xdpw_state::timers }; -enum { - PORTAL_RESPONSE_SUCCESS = 0, - PORTAL_RESPONSE_CANCELLED = 1, - PORTAL_RESPONSE_ENDED = 2 -}; +enum { PORTAL_RESPONSE_SUCCESS = 0, PORTAL_RESPONSE_CANCELLED = 1, PORTAL_RESPONSE_ENDED = 2 }; int xdpw_screenshot_init(struct xdpw_state *state); int xdpw_screencast_init(struct xdpw_state *state); @@ -66,8 +65,7 @@ void xdpw_request_destroy(struct xdpw_request *req); struct xdpw_session *xdpw_session_create(struct xdpw_state *state, sd_bus *bus, char *object_path); void xdpw_session_destroy(struct xdpw_session *req); -struct xdpw_timer *xdpw_add_timer(struct xdpw_state *state, - uint64_t delay_ns, xdpw_event_loop_timer_func_t func, void *data); +struct xdpw_timer *xdpw_add_timer(struct xdpw_state *state, uint64_t delay_ns, xdpw_event_loop_timer_func_t func, void *data); void xdpw_destroy_timer(struct xdpw_timer *timer); diff --git a/meson.build b/meson.build index 01abab6..de03518 100644 --- a/meson.build +++ b/meson.build @@ -84,6 +84,7 @@ xdpw_files = files([ 'src/screencast/wlr_screencast.c', 'src/screencast/pipewire_screencast.c', 'src/screencast/fps_limit.c', + 'src/globalshortcuts/global_shortcuts.c' ]) executable( diff --git a/protocols/meson.build b/protocols/meson.build index 9314d5f..cda43b8 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -15,6 +15,7 @@ client_protocols = [ wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', hl_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', + hl_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', 'wlr-screencopy-unstable-v1.xml', 'wlr-foreign-toplevel-management-unstable-v1.xml', ] diff --git a/src/core/main.c b/src/core/main.c index 2d63524..f59544d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1,288 +1,290 @@ #include -#include -#include -#include #include -#include #include +#include #include +#include +#include +#include #include -#include "xdpw.h" #include "logger.h" +#include "xdpw.h" enum event_loop_fd { - EVENT_LOOP_DBUS, - EVENT_LOOP_WAYLAND, - EVENT_LOOP_PIPEWIRE, - EVENT_LOOP_TIMER, + EVENT_LOOP_DBUS, + EVENT_LOOP_WAYLAND, + EVENT_LOOP_PIPEWIRE, + EVENT_LOOP_TIMER, }; static const char service_name[] = "org.freedesktop.impl.portal.desktop.hyprland"; static int xdpw_usage(FILE *stream, int rc) { - static const char *usage = - "Usage: xdg-desktop-portal-hyprland [options]\n" - "\n" - " -l, --loglevel= Select log level (default is ERROR).\n" - " QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n" - " -c, --config= Select config file.\n" - " (default is $XDG_CONFIG_HOME/xdg-desktop-portal-hyprland/config)\n" - " -r, --replace Replace a running instance.\n" - " -h, --help Get help (this text).\n" - "\n"; + static const char *usage = + "Usage: xdg-desktop-portal-hyprland [options]\n" + "\n" + " -l, --loglevel= Select log level (default is ERROR).\n" + " QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n" + " -c, --config= Select config file.\n" + " (default is $XDG_CONFIG_HOME/xdg-desktop-portal-hyprland/config)\n" + " -r, --replace Replace a running instance.\n" + " -h, --help Get help (this text).\n" + "\n"; - fprintf(stream, "%s", usage); - return rc; + fprintf(stream, "%s", usage); + return rc; } static int handle_name_lost(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - logprint(INFO, "dbus: lost name, closing connection"); - sd_bus_close(sd_bus_message_get_bus(m)); - return 1; + logprint(INFO, "dbus: lost name, closing connection"); + sd_bus_close(sd_bus_message_get_bus(m)); + return 1; } int main(int argc, char *argv[]) { - struct xdpw_config config = {0}; - char *configfile = NULL; - enum LOGLEVEL loglevel = DEFAULT_LOGLEVEL; - bool replace = false; + struct xdpw_config config = {0}; + char *configfile = NULL; + enum LOGLEVEL loglevel = DEFAULT_LOGLEVEL; + bool replace = false; - static const char *shortopts = "l:o:c:f:rh"; - static const struct option longopts[] = { - { "loglevel", required_argument, NULL, 'l' }, - { "config", required_argument, NULL, 'c' }, - { "replace", no_argument, NULL, 'r' }, - { "help", no_argument, NULL, 'h' }, - { NULL, 0, NULL, 0 } - }; + static const char *shortopts = "l:o:c:f:rh"; + static const struct option longopts[] = {{"loglevel", required_argument, NULL, 'l'}, + {"config", required_argument, NULL, 'c'}, + {"replace", no_argument, NULL, 'r'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}}; - while (1) { - int c = getopt_long(argc, argv, shortopts, longopts, NULL); - if (c < 0) { - break; - } + while (1) { + int c = getopt_long(argc, argv, shortopts, longopts, NULL); + if (c < 0) { + break; + } - switch (c) { - case 'l': - loglevel = get_loglevel(optarg); - break; - case 'c': - configfile = strdup(optarg); - break; - case 'r': - replace = true; - break; - case 'h': - return xdpw_usage(stdout, EXIT_SUCCESS); - default: - return xdpw_usage(stderr, EXIT_FAILURE); - } - } + switch (c) { + case 'l': + loglevel = get_loglevel(optarg); + break; + case 'c': + configfile = strdup(optarg); + break; + case 'r': + replace = true; + break; + case 'h': + return xdpw_usage(stdout, EXIT_SUCCESS); + default: + return xdpw_usage(stderr, EXIT_FAILURE); + } + } - init_logger(stderr, loglevel); - init_config(&configfile, &config); - print_config(DEBUG, &config); + init_logger(stderr, loglevel); + init_config(&configfile, &config); + print_config(DEBUG, &config); - int ret = 0; + int ret = 0; - sd_bus *bus = NULL; - ret = sd_bus_open_user(&bus); - if (ret < 0) { - logprint(ERROR, "dbus: failed to connect to user bus: %s", strerror(-ret)); - return EXIT_FAILURE; - } - logprint(DEBUG, "dbus: connected"); + sd_bus *bus = NULL; + ret = sd_bus_open_user(&bus); + if (ret < 0) { + logprint(ERROR, "dbus: failed to connect to user bus: %s", strerror(-ret)); + return EXIT_FAILURE; + } + logprint(DEBUG, "dbus: connected"); - struct wl_display *wl_display = wl_display_connect(NULL); - if (!wl_display) { - logprint(ERROR, "wayland: failed to connect to display"); - sd_bus_unref(bus); - return EXIT_FAILURE; - } - logprint(DEBUG, "wlroots: wl_display connected"); + struct wl_display *wl_display = wl_display_connect(NULL); + if (!wl_display) { + logprint(ERROR, "wayland: failed to connect to display"); + sd_bus_unref(bus); + return EXIT_FAILURE; + } + logprint(DEBUG, "wlroots: wl_display connected"); - pw_init(NULL, NULL); - struct pw_loop *pw_loop = pw_loop_new(NULL); - if (!pw_loop) { - logprint(ERROR, "pipewire: failed to create loop"); - wl_display_disconnect(wl_display); - sd_bus_unref(bus); - return EXIT_FAILURE; - } - logprint(DEBUG, "pipewire: pw_loop created"); + pw_init(NULL, NULL); + struct pw_loop *pw_loop = pw_loop_new(NULL); + if (!pw_loop) { + logprint(ERROR, "pipewire: failed to create loop"); + wl_display_disconnect(wl_display); + sd_bus_unref(bus); + return EXIT_FAILURE; + } + logprint(DEBUG, "pipewire: pw_loop created"); - struct xdpw_state state = { - .bus = bus, - .wl_display = wl_display, - .pw_loop = pw_loop, - .screencast_source_types = MONITOR, - .screencast_cursor_modes = HIDDEN | EMBEDDED | METADATA, - .screencast_version = XDP_CAST_PROTO_VER, - .screenshot_version = XDP_SHOT_PROTO_VER, - .config = &config, - }; + struct xdpw_state state = { + .bus = bus, + .wl_display = wl_display, + .pw_loop = pw_loop, + .screencast_source_types = MONITOR, + .screencast_cursor_modes = HIDDEN | EMBEDDED, + .screencast_version = XDP_CAST_PROTO_VER, + .screenshot_version = XDP_SHOT_PROTO_VER, + .config = &config, + }; - wl_list_init(&state.xdpw_sessions); + wl_list_init(&state.xdpw_sessions); - ret = xdpw_screenshot_init(&state); - if (ret < 0) { - logprint(ERROR, "xdpw: failed to initialize screenshot"); - goto error; - } + initShortcutsInstance(&state, &state.shortcutsInstance); - ret = xdpw_screencast_init(&state); - if (ret < 0) { - logprint(ERROR, "xdpw: failed to initialize screencast"); - goto error; - } + ret = xdpw_screenshot_init(&state); + if (ret < 0) { + logprint(ERROR, "xdpw: failed to initialize screenshot"); + goto error; + } - uint64_t flags = SD_BUS_NAME_ALLOW_REPLACEMENT; - if (replace) { - flags |= SD_BUS_NAME_REPLACE_EXISTING; - } + ret = xdpw_screencast_init(&state); + if (ret < 0) { + logprint(ERROR, "xdpw: failed to initialize screencast"); + goto error; + } - ret = sd_bus_request_name(bus, service_name, flags); - if (ret < 0) { - logprint(ERROR, "dbus: failed to acquire service name: %s", strerror(-ret)); - goto error; - } + uint64_t flags = SD_BUS_NAME_ALLOW_REPLACEMENT; + if (replace) { + flags |= SD_BUS_NAME_REPLACE_EXISTING; + } - const char *unique_name; - ret = sd_bus_get_unique_name(bus, &unique_name); - if (ret < 0) { - logprint(ERROR, "dbus: failed to get unique bus name: %s", strerror(-ret)); - goto error; - } + ret = sd_bus_request_name(bus, service_name, flags); + if (ret < 0) { + logprint(ERROR, "dbus: failed to acquire service name: %s", strerror(-ret)); + goto error; + } - static char match[1024]; - snprintf(match, sizeof(match), "sender='org.freedesktop.DBus'," - "type='signal'," - "interface='org.freedesktop.DBus'," - "member='NameOwnerChanged'," - "path='/org/freedesktop/DBus'," - "arg0='%s'," - "arg1='%s'", - service_name, unique_name); + const char *unique_name; + ret = sd_bus_get_unique_name(bus, &unique_name); + if (ret < 0) { + logprint(ERROR, "dbus: failed to get unique bus name: %s", strerror(-ret)); + goto error; + } - sd_bus_slot *slot; - ret = sd_bus_add_match(bus, &slot, match, handle_name_lost, NULL); - if (ret < 0) { - logprint(ERROR, "dbus: failed to add NameOwnerChanged signal match: %s", strerror(-ret)); - goto error; - } + static char match[1024]; + snprintf(match, sizeof(match), + "sender='org.freedesktop.DBus'," + "type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "path='/org/freedesktop/DBus'," + "arg0='%s'," + "arg1='%s'", + service_name, unique_name); - wl_list_init(&state.timers); + sd_bus_slot *slot; + ret = sd_bus_add_match(bus, &slot, match, handle_name_lost, NULL); + if (ret < 0) { + logprint(ERROR, "dbus: failed to add NameOwnerChanged signal match: %s", strerror(-ret)); + goto error; + } - struct pollfd pollfds[] = { - [EVENT_LOOP_DBUS] = { - .fd = sd_bus_get_fd(state.bus), - .events = POLLIN, - }, - [EVENT_LOOP_WAYLAND] = { - .fd = wl_display_get_fd(state.wl_display), - .events = POLLIN, - }, - [EVENT_LOOP_PIPEWIRE] = { - .fd = pw_loop_get_fd(state.pw_loop), - .events = POLLIN, - }, - [EVENT_LOOP_TIMER] = { - .fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC), - .events = POLLIN, - } - }; + wl_list_init(&state.timers); - state.timer_poll_fd = pollfds[EVENT_LOOP_TIMER].fd; + struct pollfd pollfds[] = {[EVENT_LOOP_DBUS] = + { + .fd = sd_bus_get_fd(state.bus), + .events = POLLIN, + }, + [EVENT_LOOP_WAYLAND] = + { + .fd = wl_display_get_fd(state.wl_display), + .events = POLLIN, + }, + [EVENT_LOOP_PIPEWIRE] = + { + .fd = pw_loop_get_fd(state.pw_loop), + .events = POLLIN, + }, + [EVENT_LOOP_TIMER] = { + .fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC), + .events = POLLIN, + }}; - while (1) { - ret = poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), -1); - if (ret < 0) { - logprint(ERROR, "poll failed: %s", strerror(errno)); - goto error; - } + state.timer_poll_fd = pollfds[EVENT_LOOP_TIMER].fd; - if (pollfds[EVENT_LOOP_DBUS].revents & POLLHUP) { - logprint(INFO, "event-loop: disconnected from dbus"); - break; - } - if (pollfds[EVENT_LOOP_WAYLAND].revents & POLLHUP) { - logprint(INFO, "event-loop: disconnected from wayland"); - break; - } - if (pollfds[EVENT_LOOP_PIPEWIRE].revents & POLLHUP) { - logprint(INFO, "event-loop: disconnected from pipewire"); - break; - } + while (1) { + ret = poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), -1); + if (ret < 0) { + logprint(ERROR, "poll failed: %s", strerror(errno)); + goto error; + } - if (pollfds[EVENT_LOOP_DBUS].revents & POLLIN) { - logprint(TRACE, "event-loop: got dbus event"); - do { - ret = sd_bus_process(state.bus, NULL); - } while (ret > 0); - if (ret < 0) { - logprint(ERROR, "sd_bus_process failed: %s", strerror(-ret)); - goto error; - } - } + if (pollfds[EVENT_LOOP_DBUS].revents & POLLHUP) { + logprint(INFO, "event-loop: disconnected from dbus"); + break; + } + if (pollfds[EVENT_LOOP_WAYLAND].revents & POLLHUP) { + logprint(INFO, "event-loop: disconnected from wayland"); + break; + } + if (pollfds[EVENT_LOOP_PIPEWIRE].revents & POLLHUP) { + logprint(INFO, "event-loop: disconnected from pipewire"); + break; + } - if (pollfds[EVENT_LOOP_WAYLAND].revents & POLLIN) { - logprint(TRACE, "event-loop: got wayland event"); - ret = wl_display_dispatch(state.wl_display); - if (ret < 0) { - logprint(ERROR, "wl_display_dispatch failed: %s", strerror(errno)); - goto error; - } - } + if (pollfds[EVENT_LOOP_DBUS].revents & POLLIN) { + logprint(TRACE, "event-loop: got dbus event"); + do { + ret = sd_bus_process(state.bus, NULL); + } while (ret > 0); + if (ret < 0) { + logprint(ERROR, "sd_bus_process failed: %s", strerror(-ret)); + goto error; + } + } - if (pollfds[EVENT_LOOP_PIPEWIRE].revents & POLLIN) { - logprint(TRACE, "event-loop: got pipewire event"); - ret = pw_loop_iterate(state.pw_loop, 0); - if (ret < 0) { - logprint(ERROR, "pw_loop_iterate failed: %s", spa_strerror(ret)); - goto error; - } - } + if (pollfds[EVENT_LOOP_WAYLAND].revents & POLLIN) { + logprint(TRACE, "event-loop: got wayland event"); + ret = wl_display_dispatch(state.wl_display); + if (ret < 0) { + logprint(ERROR, "wl_display_dispatch failed: %s", strerror(errno)); + goto error; + } + } - if (pollfds[EVENT_LOOP_TIMER].revents & POLLIN) { - logprint(TRACE, "event-loop: got a timer event"); + if (pollfds[EVENT_LOOP_PIPEWIRE].revents & POLLIN) { + logprint(TRACE, "event-loop: got pipewire event"); + ret = pw_loop_iterate(state.pw_loop, 0); + if (ret < 0) { + logprint(ERROR, "pw_loop_iterate failed: %s", spa_strerror(ret)); + goto error; + } + } - int timer_fd = pollfds[EVENT_LOOP_TIMER].fd; - uint64_t expirations; - ssize_t n = read(timer_fd, &expirations, sizeof(expirations)); - if (n < 0) { - logprint(ERROR, "failed to read from timer FD\n"); - goto error; - } + if (pollfds[EVENT_LOOP_TIMER].revents & POLLIN) { + logprint(TRACE, "event-loop: got a timer event"); - struct xdpw_timer *timer = state.next_timer; - if (timer != NULL) { - xdpw_event_loop_timer_func_t func = timer->func; - void *user_data = timer->user_data; - xdpw_destroy_timer(timer); + int timer_fd = pollfds[EVENT_LOOP_TIMER].fd; + uint64_t expirations; + ssize_t n = read(timer_fd, &expirations, sizeof(expirations)); + if (n < 0) { + logprint(ERROR, "failed to read from timer FD\n"); + goto error; + } - func(user_data); - } - } + struct xdpw_timer *timer = state.next_timer; + if (timer != NULL) { + xdpw_event_loop_timer_func_t func = timer->func; + void *user_data = timer->user_data; + xdpw_destroy_timer(timer); - do { - ret = wl_display_dispatch_pending(state.wl_display); - wl_display_flush(state.wl_display); - } while (ret > 0); + func(user_data); + } + } - sd_bus_flush(state.bus); - } + do { + ret = wl_display_dispatch_pending(state.wl_display); + wl_display_flush(state.wl_display); + } while (ret > 0); - // TODO: cleanup - finish_config(&config); - free(configfile); + sd_bus_flush(state.bus); + } - return EXIT_SUCCESS; + // TODO: cleanup + finish_config(&config); + free(configfile); + + return EXIT_SUCCESS; error: - sd_bus_unref(bus); - pw_loop_leave(state.pw_loop); - pw_loop_destroy(state.pw_loop); - wl_display_disconnect(state.wl_display); - return EXIT_FAILURE; + sd_bus_unref(bus); + pw_loop_leave(state.pw_loop); + pw_loop_destroy(state.pw_loop); + wl_display_disconnect(state.wl_display); + return EXIT_FAILURE; } diff --git a/src/globalshortcuts/global_shortcuts.c b/src/globalshortcuts/global_shortcuts.c new file mode 100644 index 0000000..ceed39c --- /dev/null +++ b/src/globalshortcuts/global_shortcuts.c @@ -0,0 +1,537 @@ +#include "include/global_shortcuts.h" + +#include + +#include "include/xdpw.h" + +static void wlr_registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, const char *interface, uint32_t ver) { + struct globalShortcutsInstance *instance = data; + + if (!strcmp(interface, hyprland_global_shortcuts_manager_v1_interface.name) && instance->manager == NULL) { + uint32_t version = ver; + + logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version); + + instance->manager = wl_registry_bind(reg, id, &hyprland_global_shortcuts_manager_v1_interface, version); + } +} + +static void wlr_registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id) { + ; // ignored +} + +static const struct wl_registry_listener wlr_registry_listener = { + .global = wlr_registry_handle_add, + .global_remove = wlr_registry_handle_remove, +}; + +static const char object_path[] = "/org/freedesktop/portal/desktop"; +static const char interface_name[] = "org.freedesktop.impl.portal.GlobalShortcuts"; + +static int method_gs_create_session(sd_bus_message *msg, void *data, sd_bus_error *ret_error); +static int method_gs_bind_shortcuts(sd_bus_message *msg, void *data, sd_bus_error *ret_error); +static int method_gs_list_shortcuts(sd_bus_message *msg, void *data, sd_bus_error *ret_error); + +static const sd_bus_vtable gs_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("CreateSession", "oosa{sv}", "ua{sv}", method_gs_create_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("BindShortcuts", "ooa(sa{sv})sa{sv}", "ua{sv}", method_gs_bind_shortcuts, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListShortcuts", "oo", "ua{sv}", method_gs_list_shortcuts, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("Activated", "osta{sv}", NULL), + SD_BUS_SIGNAL("Deactivated", "osta{sv}", NULL), + SD_BUS_SIGNAL("ShortcutsChanged", "oa(sa{sv})", NULL), + SD_BUS_VTABLE_END}; + +static void handleActivated(void *data, struct hyprland_global_shortcut_v1 *hyprland_global_shortcut_v1, uint32_t tv_sec_hi, uint32_t tv_sec_lo, + uint32_t tv_nsec) { + struct xdpw_state *state = data; + + bool found = false; + + struct globalShortcut *curr; + struct globalShortcutsClient *currc; + wl_list_for_each(currc, &state->shortcutsInstance.shortcutClients, link) { + wl_list_for_each(curr, &currc->shortcuts, link) { + if (curr->hlShortcut == hyprland_global_shortcut_v1) { + found = true; + goto found; + } + } + } +found: + + if (!found) return; + + sd_bus_emit_signal(state->bus, object_path, interface_name, "Activated", "osta{sv}", currc->session->session_handle, curr->name, + ((uint64_t)tv_sec_hi << 32) | (uint64_t)(tv_sec_lo), 0); +} + +static void handleDeactivated(void *data, struct hyprland_global_shortcut_v1 *hyprland_global_shortcut_v1, uint32_t tv_sec_hi, uint32_t tv_sec_lo, + uint32_t tv_nsec) { + struct xdpw_state *state = data; + + bool found = false; + + struct globalShortcut *curr; + struct globalShortcutsClient *currc; + wl_list_for_each(currc, &state->shortcutsInstance.shortcutClients, link) { + wl_list_for_each(curr, &currc->shortcuts, link) { + if (curr->hlShortcut == hyprland_global_shortcut_v1) { + found = true; + goto found; + } + } + } +found: + + if (!found) return; + + sd_bus_emit_signal(state->bus, object_path, interface_name, "Deactivated", "osta{sv}", currc->session->session_handle, curr->name, + ((uint64_t)tv_sec_hi << 32) | (uint64_t)(tv_sec_lo), 0); +} + +static const struct hyprland_global_shortcut_v1_listener shortcutListener = { + .pressed = handleActivated, + .released = handleDeactivated, +}; + +static int method_gs_create_session(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { + struct xdpw_state *state = data; + struct globalShortcutsClient *client = calloc(1, sizeof(struct globalShortcutsClient)); + wl_list_insert(&state->shortcutsInstance.shortcutClients, &client->link); + wl_list_init(&client->shortcuts); + + int ret = 0; + + logprint(INFO, "dbus: create session method invoked"); + + char *request_handle, *session_handle, *app_id; + ret = sd_bus_message_read(msg, "oos", &request_handle, &session_handle, &app_id); + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_enter_container(msg, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + + logprint(INFO, "dbus: request_handle: %s", request_handle); + logprint(INFO, "dbus: session_handle: %s", session_handle); + logprint(INFO, "dbus: app_id: %s", app_id); + + char *key; + char *option_token; + int innerRet = 0; + while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { + innerRet = sd_bus_message_read(msg, "s", &key); + if (innerRet < 0) { + return innerRet; + } + + if (strcmp(key, "session_handle_token") == 0) { + sd_bus_message_read(msg, "v", "s", &option_token); + logprint(INFO, "dbus: option token: %s", option_token); + } else if (strcmp(key, "shortcuts") == 0) { + // init shortcuts + client->sentShortcuts = true; + + innerRet = sd_bus_message_enter_container(msg, 'v', "a(sa{sv})"); + if (innerRet < 0) { + return innerRet; + } + + innerRet = sd_bus_message_enter_container(msg, 'a', "(sa{sv})"); + + while (innerRet > 0) { + char type; + char *container; + sd_bus_message_peek_type(msg, &type, &container); + + if (type != 'r') break; + + innerRet = sd_bus_message_enter_container(msg, 'r', "sa{sv}"); + if (innerRet == -ENXIO) break; + + sd_bus_message_peek_type(msg, &type, &container); + + innerRet = sd_bus_message_read(msg, "s", &key); + + if (innerRet == -ENXIO) break; + + if (innerRet < 0) { + return innerRet; + } + + logprint(DEBUG, "shortcut name %s", key); + + struct globalShortcut *shortcut = calloc(1, sizeof(struct globalShortcut)); + shortcut->name = malloc(strlen(key) + 1); + strcpy(shortcut->name, key); + + ret = sd_bus_message_enter_container(msg, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + + while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { + innerRet = sd_bus_message_read(msg, "s", &key); + if (innerRet < 0) { + return innerRet; + } + + if (strcmp(key, "description") == 0) { + sd_bus_message_read(msg, "v", "s", &key); + shortcut->description = malloc(strlen(key) + 1); + strcpy(shortcut->description, key); + } else { + sd_bus_message_skip(msg, "v"); + } + + innerRet = sd_bus_message_exit_container(msg); + if (innerRet < 0) { + return innerRet; + } + } + + sd_bus_message_exit_container(msg); + + if (shortcut->description == NULL) { + shortcut->description = calloc(1, 1); + } + + wl_list_insert(&client->shortcuts, &shortcut->link); + + sd_bus_message_exit_container(msg); + } + + innerRet = sd_bus_message_exit_container(msg); + innerRet = sd_bus_message_exit_container(msg); + if (innerRet < 0) { + return innerRet; + } + + } else { + logprint(WARN, "dbus: unknown option: %s", key); + sd_bus_message_skip(msg, "v"); + } + + innerRet = sd_bus_message_exit_container(msg); + if (innerRet < 0) { + return innerRet; + } + } + if (ret < 0) { + return ret; + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + return ret; + } + + struct xdpw_request *req = xdpw_request_create(sd_bus_message_get_bus(msg), request_handle); + if (req == NULL) { + return -ENOMEM; + } + + struct xdpw_session *sess = xdpw_session_create(state, sd_bus_message_get_bus(msg), strdup(session_handle)); + if (sess == NULL) { + return -ENOMEM; + } + + client->session = sess; + + sess->app_id = malloc(strlen(app_id) + 1); + strcpy(sess->app_id, app_id); + + sd_bus_message *reply = NULL; + ret = sd_bus_message_new_method_return(msg, &reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_append(reply, "u", PORTAL_RESPONSE_SUCCESS, 0); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + sd_bus_message_open_container(reply, 'e', "sv"); + sd_bus_message_append(reply, "s", "shortcuts"); + sd_bus_message_open_container(reply, 'v', "a(sa{sv})"); + sd_bus_message_open_container(reply, 'a', "(sa{sv})"); + struct globalShortcut *curr; + wl_list_for_each(curr, &client->shortcuts, link) { + sd_bus_message_append(reply, "(sa{sv})", curr->name, 1, "description", "s", curr->description); + curr->hlShortcut = hyprland_global_shortcuts_manager_v1_register_shortcut( + state->shortcutsInstance.manager, curr->name, (strlen(app_id) == 0 ? option_token : app_id), curr->description, ""); + hyprland_global_shortcut_v1_add_listener(curr->hlShortcut, &shortcutListener, state); + curr->bound = true; + } + + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_send(NULL, reply, NULL); + if (ret < 0) { + return ret; + } + + sd_bus_message_unref(reply); + return 0; +} + +static int method_gs_bind_shortcuts(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { + struct xdpw_state *state = data; + + int ret = 0; + + logprint(INFO, "dbus: bind shortcuts invoked"); + + char *request_handle, *session_handle; + ret = sd_bus_message_read(msg, "oo", &request_handle, &session_handle); + if (ret < 0) { + return ret; + } + + logprint(INFO, "dbus: request_handle: %s", request_handle); + logprint(INFO, "dbus: session_handle: %s", session_handle); + + struct xdpw_session *session, *tmp_session; + wl_list_for_each_reverse_safe(session, tmp_session, &state->xdpw_sessions, link) { + if (strcmp(session->session_handle, session_handle) == 0) { + logprint(DEBUG, "dbus: bind shortcuts: found matching session %s", session->session_handle); + break; + } + } + + struct globalShortcutsClient *client, *tmp_client; + wl_list_for_each_reverse_safe(client, tmp_client, &state->shortcutsInstance.shortcutClients, link) { + if (strcmp(client->session, session_handle) == 0) { + logprint(DEBUG, "dbus: bind shortcuts: found matching client %s", client->session); + break; + } + } + + if (!client->sentShortcuts) { + char *key; + int innerRet = 0; + client->sentShortcuts = true; + + innerRet = sd_bus_message_enter_container(msg, 'a', "(sa{sv})"); + + while (innerRet > 0) { + char type; + char *container; + sd_bus_message_peek_type(msg, &type, &container); + + if (type != 'r') break; + + innerRet = sd_bus_message_enter_container(msg, 'r', "sa{sv}"); + if (innerRet == -ENXIO) break; + + sd_bus_message_peek_type(msg, &type, &container); + + innerRet = sd_bus_message_read(msg, "s", &key); + + if (innerRet == -ENXIO) break; + + if (innerRet < 0) { + return innerRet; + } + + logprint(DEBUG, "shortcut name %s", key); + + struct globalShortcut *shortcut = calloc(1, sizeof(struct globalShortcut)); + shortcut->name = malloc(strlen(key) + 1); + strcpy(shortcut->name, key); + + ret = sd_bus_message_enter_container(msg, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + + while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { + innerRet = sd_bus_message_read(msg, "s", &key); + if (innerRet < 0) { + return innerRet; + } + + if (strcmp(key, "description") == 0) { + sd_bus_message_read(msg, "v", "s", &key); + shortcut->description = malloc(strlen(key) + 1); + strcpy(shortcut->description, key); + } else { + sd_bus_message_skip(msg, "v"); + } + + innerRet = sd_bus_message_exit_container(msg); + if (innerRet < 0) { + return innerRet; + } + } + + sd_bus_message_exit_container(msg); + + if (shortcut->description == NULL) { + shortcut->description = calloc(1, 1); + } + + wl_list_insert(&client->shortcuts, &shortcut->link); + + sd_bus_message_exit_container(msg); + } + + innerRet = sd_bus_message_exit_container(msg); + if (innerRet < 0) { + return innerRet; + } + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + return ret; + } + + char *parent_window; + ret = sd_bus_message_read(msg, "s", &parent_window); + + logprint(DEBUG, "dbus: parent_window %s", parent_window); + + client->parent_window = malloc(strlen(parent_window) + 1); + strcpy(client->parent_window, parent_window); + + sd_bus_message *reply = NULL; + ret = sd_bus_message_new_method_return(msg, &reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_append(reply, "u", PORTAL_RESPONSE_SUCCESS, 0); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + sd_bus_message_open_container(reply, 'e', "sv"); + sd_bus_message_append(reply, "s", "shortcuts"); + sd_bus_message_open_container(reply, 'v', "a(sa{sv})"); + sd_bus_message_open_container(reply, 'a', "(sa{sv})"); + struct globalShortcut *curr; + wl_list_for_each(curr, &client->shortcuts, link) { + sd_bus_message_append(reply, "(sa{sv})", curr->name, 1, "description", "s", curr->description); + if (!curr->bound) { + curr->hlShortcut = hyprland_global_shortcuts_manager_v1_register_shortcut(state->shortcutsInstance.manager, curr->name, parent_window, + curr->description, ""); + hyprland_global_shortcut_v1_add_listener(curr->hlShortcut, &shortcutListener, state); + } + } + + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_send(NULL, reply, NULL); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int method_gs_list_shortcuts(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { + struct xdpw_state *state = data; + + int ret = 0; + + logprint(INFO, "dbus: list shortcuts invoked"); + + char *request_handle, *session_handle; + ret = sd_bus_message_read(msg, "oo", &request_handle, &session_handle); + if (ret < 0) { + return ret; + } + + logprint(INFO, "dbus: request_handle: %s", request_handle); + logprint(INFO, "dbus: session_handle: %s", session_handle); + + bool foundClient = false; + struct globalShortcutsClient *client, *tmp_client; + wl_list_for_each(client, &state->shortcutsInstance.shortcutClients, link) { + if (strcmp(client->session, session_handle) == 0) { + logprint(DEBUG, "dbus: bind shortcuts: found matching client %s", client->session); + foundClient = true; + break; + } + } + + if (!foundClient || !client->sentShortcuts) return 0; + + sd_bus_message *reply = NULL; + ret = sd_bus_message_new_method_return(msg, &reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_append(reply, "u", PORTAL_RESPONSE_SUCCESS, 0); + if (ret < 0) { + return ret; + } + ret = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (ret < 0) { + return ret; + } + sd_bus_message_open_container(reply, 'e', "sv"); + sd_bus_message_append(reply, "s", "shortcuts"); + sd_bus_message_open_container(reply, 'v', "a(sa{sv})"); + sd_bus_message_open_container(reply, 'a', "(sa{sv})"); + struct globalShortcut *curr; + wl_list_for_each(curr, &client->shortcuts, link) { + sd_bus_message_append(reply, "(sa{sv})", curr->name, 1, "description", "s", curr->description); + } + + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + ret = sd_bus_message_close_container(reply); + if (ret < 0) { + return ret; + } + ret = sd_bus_send(NULL, reply, NULL); + if (ret < 0) { + return ret; + } + + return 0; +} + +void initShortcutsInstance(struct xdpw_state *state, struct globalShortcutsInstance *instance) { + instance->manager = NULL; + wl_list_init(&instance->shortcutClients); + + struct wl_registry *registry = wl_display_get_registry(state->wl_display); + wl_registry_add_listener(registry, &wlr_registry_listener, instance); + + wl_display_roundtrip(state->wl_display); + + if (instance->manager == NULL) { + logprint(ERROR, "hyprland shortcut protocol unavailable!"); + return; + } + + sd_bus_slot *slot = NULL; + int ret = sd_bus_add_object_vtable(state->bus, &slot, object_path, interface_name, gs_vtable, state); + + logprint(DEBUG, "dbus: gs: ret bind %d", ret); + + // register to hl +} \ No newline at end of file diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index be23a16..67cc908 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -41,8 +41,7 @@ void handleTitle(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, con if (current->handle == handle) { strncpy(current->name, title, 255); for (int i = 0; i < 255; ++i) - if (current->name[i] == '\"' || current->name[i] == '>' || current->name[i] == '\'') - current->name[i] = ' '; + if (current->name[i] == '\"' || current->name[i] == '>' || current->name[i] == '\'') current->name[i] = ' '; current->name[255] = '\0'; break; } @@ -57,8 +56,7 @@ void handleAppID(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, con if (current->handle == handle) { strncpy(current->clazz, app_id, 255); for (int i = 0; i < 255; ++i) - if (current->clazz[i] == '\"' || current->clazz[i] == '>' || current->clazz[i] == '\'') - current->clazz[i] = ' '; + if (current->clazz[i] == '\"' || current->clazz[i] == '>' || current->clazz[i] == '\'') current->clazz[i] = ' '; current->name[255] = '\0'; break; } @@ -187,8 +185,7 @@ void xdpw_wlr_frame_finish(struct xdpw_screencast_instance *cast) { xdpw_pwr_enqueue_buffer(cast); uint64_t delay_ns = fps_limit_measure_end(&cast->fps_limit, cast->framerate); if (delay_ns > 0) { - xdpw_add_timer(cast->ctx->state, delay_ns, - (xdpw_event_loop_timer_func_t)xdpw_wlr_frame_start, cast); + xdpw_add_timer(cast->ctx->state, delay_ns, (xdpw_event_loop_timer_func_t)xdpw_wlr_frame_start, cast); return; } } @@ -211,11 +208,9 @@ void xdpw_wlr_frame_start(struct xdpw_screencast_instance *cast) { xdpw_wlr_register_cb(cast); } -static void wlr_frame_buffer_done(void *data, - struct zwlr_screencopy_frame_v1 *frame); +static void wlr_frame_buffer_done(void *data, struct zwlr_screencopy_frame_v1 *frame); -static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { +static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -235,9 +230,7 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, } } -static void wlr_frame_linux_dmabuf(void *data, - struct zwlr_screencopy_frame_v1 *frame, - uint32_t format, uint32_t width, uint32_t height) { +static void wlr_frame_linux_dmabuf(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -250,8 +243,7 @@ static void wlr_frame_linux_dmabuf(void *data, cast->screencopy_frame_info[DMABUF].format = format; } -static void wlr_frame_buffer_done(void *data, - struct zwlr_screencopy_frame_v1 *frame) { +static void wlr_frame_buffer_done(void *data, struct zwlr_screencopy_frame_v1 *frame) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -266,7 +258,8 @@ static void wlr_frame_buffer_done(void *data, // Check if announced screencopy information is compatible with pipewire meta if ((cast->pwr_format.format != xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format) && - cast->pwr_format.format != xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format))) || + cast->pwr_format.format != + xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format))) || cast->pwr_format.size.width != cast->screencopy_frame_info[cast->buffer_type].width || cast->pwr_format.size.height != cast->screencopy_frame_info[cast->buffer_type].height) { logprint(DEBUG, "wlroots: pipewire and wlroots metadata are incompatible. Renegotiate stream"); @@ -288,9 +281,8 @@ static void wlr_frame_buffer_done(void *data, assert(cast->current_frame.xdpw_buffer); // Check if dequeued buffer is compatible with announced buffer - if ((cast->buffer_type == WL_SHM && - (cast->current_frame.xdpw_buffer->size[0] != cast->screencopy_frame_info[cast->buffer_type].size || - cast->current_frame.xdpw_buffer->stride[0] != cast->screencopy_frame_info[cast->buffer_type].stride)) || + if ((cast->buffer_type == WL_SHM && (cast->current_frame.xdpw_buffer->size[0] != cast->screencopy_frame_info[cast->buffer_type].size || + cast->current_frame.xdpw_buffer->stride[0] != cast->screencopy_frame_info[cast->buffer_type].stride)) || cast->current_frame.xdpw_buffer->width != cast->screencopy_frame_info[cast->buffer_type].width || cast->current_frame.xdpw_buffer->height != cast->screencopy_frame_info[cast->buffer_type].height) { logprint(DEBUG, "wlroots: pipewire buffer has wrong dimensions"); @@ -305,8 +297,7 @@ static void wlr_frame_buffer_done(void *data, fps_limit_measure_start(&cast->fps_limit, cast->framerate); } -static void wlr_frame_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t flags) { +static void wlr_frame_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t flags) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -316,8 +307,7 @@ static void wlr_frame_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, cast->current_frame.y_invert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT; } -static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t x, uint32_t y, uint32_t width, uint32_t height) { +static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -331,8 +321,7 @@ static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame, cast->current_frame.damage.height = height; } -static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) { +static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -349,8 +338,7 @@ static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, xdpw_wlr_frame_finish(cast); } -static void wlr_frame_failed(void *data, - struct zwlr_screencopy_frame_v1 *frame) { +static void wlr_frame_failed(void *data, struct zwlr_screencopy_frame_v1 *frame) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -373,11 +361,10 @@ static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = { .damage = wlr_frame_damage, }; -static void hyprland_frame_buffer_done(void *data, - struct hyprland_toplevel_export_frame_v1 *frame); +static void hyprland_frame_buffer_done(void *data, struct hyprland_toplevel_export_frame_v1 *frame); -static void hyprland_frame_buffer(void *data, struct hyprland_toplevel_export_frame_v1 *frame, - uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { +static void hyprland_frame_buffer(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, + uint32_t stride) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -396,9 +383,8 @@ static void hyprland_frame_buffer(void *data, struct hyprland_toplevel_export_fr hyprland_frame_buffer_done(cast, frame); } -static void hyprland_frame_linux_dmabuf(void *data, - struct hyprland_toplevel_export_frame_v1 *frame, - uint32_t format, uint32_t width, uint32_t height) { +static void hyprland_frame_linux_dmabuf(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t format, uint32_t width, + uint32_t height) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -411,8 +397,7 @@ static void hyprland_frame_linux_dmabuf(void *data, cast->screencopy_frame_info[DMABUF].format = format; } -static void hyprland_frame_buffer_done(void *data, - struct hyprland_toplevel_export_frame_v1 *frame) { +static void hyprland_frame_buffer_done(void *data, struct hyprland_toplevel_export_frame_v1 *frame) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -427,7 +412,8 @@ static void hyprland_frame_buffer_done(void *data, // Check if announced screencopy information is compatible with pipewire meta if ((cast->pwr_format.format != xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format) && - cast->pwr_format.format != xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format))) || + cast->pwr_format.format != + xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format))) || cast->pwr_format.size.width != cast->screencopy_frame_info[cast->buffer_type].width || cast->pwr_format.size.height != cast->screencopy_frame_info[cast->buffer_type].height) { logprint(DEBUG, "hyprland: pipewire and wlroots metadata are incompatible. Renegotiate stream"); @@ -449,9 +435,8 @@ static void hyprland_frame_buffer_done(void *data, assert(cast->current_frame.xdpw_buffer); // Check if dequeued buffer is compatible with announced buffer - if ((cast->buffer_type == WL_SHM && - (cast->current_frame.xdpw_buffer->size[0] != cast->screencopy_frame_info[cast->buffer_type].size || - cast->current_frame.xdpw_buffer->stride[0] != cast->screencopy_frame_info[cast->buffer_type].stride)) || + if ((cast->buffer_type == WL_SHM && (cast->current_frame.xdpw_buffer->size[0] != cast->screencopy_frame_info[cast->buffer_type].size || + cast->current_frame.xdpw_buffer->stride[0] != cast->screencopy_frame_info[cast->buffer_type].stride)) || cast->current_frame.xdpw_buffer->width != cast->screencopy_frame_info[cast->buffer_type].width || cast->current_frame.xdpw_buffer->height != cast->screencopy_frame_info[cast->buffer_type].height) { logprint(DEBUG, "hyprland: pipewire buffer has wrong dimensions"); @@ -466,8 +451,7 @@ static void hyprland_frame_buffer_done(void *data, fps_limit_measure_start(&cast->fps_limit, cast->framerate); } -static void hyprland_frame_flags(void *data, struct hyprland_toplevel_export_frame_v1 *frame, - uint32_t flags) { +static void hyprland_frame_flags(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t flags) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -477,8 +461,8 @@ static void hyprland_frame_flags(void *data, struct hyprland_toplevel_export_fra cast->current_frame.y_invert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT; } -static void hyprland_frame_damage(void *data, struct hyprland_toplevel_export_frame_v1 *frame, - uint32_t x, uint32_t y, uint32_t width, uint32_t height) { +static void hyprland_frame_damage(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t x, uint32_t y, uint32_t width, + uint32_t height) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -492,8 +476,8 @@ static void hyprland_frame_damage(void *data, struct hyprland_toplevel_export_fr cast->current_frame.damage.height = height; } -static void hyprland_frame_ready(void *data, struct hyprland_toplevel_export_frame_v1 *frame, - uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) { +static void hyprland_frame_ready(void *data, struct hyprland_toplevel_export_frame_v1 *frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, + uint32_t tv_nsec) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -510,8 +494,7 @@ static void hyprland_frame_ready(void *data, struct hyprland_toplevel_export_fra xdpw_wlr_frame_finish(cast); } -static void hyprland_frame_failed(void *data, - struct hyprland_toplevel_export_frame_v1 *frame) { +static void hyprland_frame_failed(void *data, struct hyprland_toplevel_export_frame_v1 *frame) { struct xdpw_screencast_instance *cast = data; if (!frame) { return; @@ -524,24 +507,23 @@ static void hyprland_frame_failed(void *data, xdpw_wlr_frame_finish(cast); } -static const struct hyprland_toplevel_export_frame_v1_listener hyprland_frame_listener = { - .buffer = hyprland_frame_buffer, - .buffer_done = hyprland_frame_buffer_done, - .linux_dmabuf = hyprland_frame_linux_dmabuf, - .flags = hyprland_frame_flags, - .ready = hyprland_frame_ready, - .failed = hyprland_frame_failed, - .damage = hyprland_frame_damage}; +static const struct hyprland_toplevel_export_frame_v1_listener hyprland_frame_listener = {.buffer = hyprland_frame_buffer, + .buffer_done = hyprland_frame_buffer_done, + .linux_dmabuf = hyprland_frame_linux_dmabuf, + .flags = hyprland_frame_flags, + .ready = hyprland_frame_ready, + .failed = hyprland_frame_failed, + .damage = hyprland_frame_damage}; void xdpw_wlr_register_cb(struct xdpw_screencast_instance *cast) { if (cast->target.x != -1 && cast->target.y != -1 && cast->target.w != -1 && cast->target.h != -1 && cast->target.window_handle <= 0) { // capture region - cast->frame_callback = zwlr_screencopy_manager_v1_capture_output_region( - cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output, cast->target.x, - cast->target.y, cast->target.w, cast->target.h); + cast->frame_callback = + zwlr_screencopy_manager_v1_capture_output_region(cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output, + cast->target.x, cast->target.y, cast->target.w, cast->target.h); } else if (cast->target.window_handle == -1) { - cast->frame_callback = zwlr_screencopy_manager_v1_capture_output( - cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output); + cast->frame_callback = + zwlr_screencopy_manager_v1_capture_output(cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output); } else { // share window struct SToplevelEntry *entry = toplevelEntryFromID(cast->ctx, cast->target.window_handle); @@ -554,41 +536,34 @@ void xdpw_wlr_register_cb(struct xdpw_screencast_instance *cast) { cast->frame_callback_hyprland = hyprland_toplevel_export_manager_v1_capture_toplevel_with_wlr_toplevel_handle( cast->ctx->hyprland_toplevel_manager, cast->with_cursor, entry->handle); - hyprland_toplevel_export_frame_v1_add_listener(cast->frame_callback_hyprland, - &hyprland_frame_listener, cast); + hyprland_toplevel_export_frame_v1_add_listener(cast->frame_callback_hyprland, &hyprland_frame_listener, cast); logprint(TRACE, "hyprland: callbacks registered"); return; } - zwlr_screencopy_frame_v1_add_listener(cast->frame_callback, - &wlr_frame_listener, cast); + zwlr_screencopy_frame_v1_add_listener(cast->frame_callback, &wlr_frame_listener, cast); logprint(TRACE, "wlroots: callbacks registered"); } -static void wlr_output_handle_geometry(void *data, struct wl_output *wl_output, - int32_t x, int32_t y, int32_t phys_width, int32_t phys_height, +static void wlr_output_handle_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t phys_width, int32_t phys_height, int32_t subpixel, const char *make, const char *model, int32_t transform) { struct xdpw_wlr_output *output = data; output->make = strdup(make); output->model = strdup(model); } -static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, - uint32_t flags, int32_t width, int32_t height, int32_t refresh) { +static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { if (flags & WL_OUTPUT_MODE_CURRENT) { struct xdpw_wlr_output *output = data; output->framerate = (float)refresh / 1000; } } -static void wlr_output_handle_done(void *data, struct wl_output *wl_output) { - /* Nothing to do */ +static void wlr_output_handle_done(void *data, struct wl_output *wl_output) { /* Nothing to do */ } -static void wlr_output_handle_scale(void *data, struct wl_output *wl_output, - int32_t factor) { - /* Nothing to do */ +static void wlr_output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { /* Nothing to do */ } static const struct wl_output_listener wlr_output_listener = { @@ -598,8 +573,7 @@ static const struct wl_output_listener wlr_output_listener = { .scale = wlr_output_handle_scale, }; -static void wlr_xdg_output_name(void *data, struct zxdg_output_v1 *xdg_output, - const char *name) { +static void wlr_xdg_output_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name) { struct xdpw_wlr_output *output = data; output->name = strdup(name); @@ -617,18 +591,13 @@ static const struct zxdg_output_v1_listener wlr_xdg_output_listener = { .name = wlr_xdg_output_name, }; -static void wlr_add_xdg_output_listener(struct xdpw_wlr_output *output, - struct zxdg_output_v1 *xdg_output) { +static void wlr_add_xdg_output_listener(struct xdpw_wlr_output *output, struct zxdg_output_v1 *xdg_output) { output->xdg_output = xdg_output; - zxdg_output_v1_add_listener(output->xdg_output, &wlr_xdg_output_listener, - output); + zxdg_output_v1_add_listener(output->xdg_output, &wlr_xdg_output_listener, output); } -static void wlr_init_xdg_output(struct xdpw_screencast_context *ctx, - struct xdpw_wlr_output *output) { - struct zxdg_output_v1 *xdg_output = - zxdg_output_manager_v1_get_xdg_output(ctx->xdg_output_manager, - output->output); +static void wlr_init_xdg_output(struct xdpw_screencast_context *ctx, struct xdpw_wlr_output *output) { + struct zxdg_output_v1 *xdg_output = zxdg_output_manager_v1_get_xdg_output(ctx->xdg_output_manager, output->output); wlr_add_xdg_output_listener(output, xdg_output); } @@ -682,8 +651,7 @@ char *getFormat(const char *fmt, ...) { char *buildWindowList(struct xdpw_screencast_context *ctx) { char *rolling = calloc(1, 1); - if (!ctx->wlroots_toplevel_manager) - return rolling; + if (!ctx->wlroots_toplevel_manager) return rolling; struct SToplevelEntry *current; wl_list_for_each(current, &ctx->toplevel_resource_list, link) { @@ -695,8 +663,7 @@ char *buildWindowList(struct xdpw_screencast_context *ctx) { } for (size_t i = 0; i < strlen(rolling); ++i) { - if (rolling[i] == '\"') - rolling[i] = ' '; + if (rolling[i] == '\"') rolling[i] = ' '; } return rolling; @@ -713,7 +680,10 @@ struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) { char *windowList = buildWindowList(ctx); - char *cmd = getFormat("WAYLAND_DISPLAY=%s QT_QPA_PLATFORM=\"wayland\" XCURSOR_SIZE=%s HYPRLAND_INSTANCE_SIGNATURE=%s XDPH_WINDOW_SHARING_LIST=\"%s\" hyprland-share-picker", WAYLAND_DISPLAY, XCURSOR_SIZE ? XCURSOR_SIZE : "24", HYPRLAND_INSTANCE_SIGNATURE ? HYPRLAND_INSTANCE_SIGNATURE : "0", windowList); + char *cmd = getFormat( + "WAYLAND_DISPLAY=%s QT_QPA_PLATFORM=\"wayland\" XCURSOR_SIZE=%s HYPRLAND_INSTANCE_SIGNATURE=%s XDPH_WINDOW_SHARING_LIST=\"%s\" " + "hyprland-share-picker", + WAYLAND_DISPLAY, XCURSOR_SIZE ? XCURSOR_SIZE : "24", HYPRLAND_INSTANCE_SIGNATURE ? HYPRLAND_INSTANCE_SIGNATURE : "0", windowList); free(windowList); @@ -756,8 +726,7 @@ struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) { free(display_name); - if (!found) - return res; + if (!found) return res; res.output = out; return res; @@ -832,14 +801,11 @@ struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) { struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list) { struct xdpw_wlr_output *output, *tmp; - wl_list_for_each_safe(output, tmp, output_list, link) { - return output; - } + wl_list_for_each_safe(output, tmp, output_list, link) { return output; } return NULL; } -struct xdpw_wlr_output *xdpw_wlr_output_find_by_name(struct wl_list *output_list, - const char *name) { +struct xdpw_wlr_output *xdpw_wlr_output_find_by_name(struct wl_list *output_list, const char *name) { struct xdpw_wlr_output *output, *tmp; wl_list_for_each_safe(output, tmp, output_list, link) { if (strcmp(output->name, name) == 0) { @@ -849,8 +815,7 @@ struct xdpw_wlr_output *xdpw_wlr_output_find_by_name(struct wl_list *output_list return NULL; } -struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx, - struct wl_output *out, uint32_t id) { +struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx, struct wl_output *out, uint32_t id) { struct xdpw_wlr_output *output, *tmp; wl_list_for_each_safe(output, tmp, &ctx->output_list, link) { if ((output->output == out) || (output->id == id)) { @@ -870,8 +835,7 @@ static void wlr_remove_output(struct xdpw_wlr_output *out) { free(out); } -static void wlr_format_modifier_pair_add(struct xdpw_screencast_context *ctx, - uint32_t format, uint64_t modifier) { +static void wlr_format_modifier_pair_add(struct xdpw_screencast_context *ctx, uint32_t format, uint64_t modifier) { struct xdpw_format_modifier_pair *fm_pair; wl_array_for_each(fm_pair, &ctx->format_modifier_pairs) { if (fm_pair->fourcc == format && fm_pair->modifier == modifier) { @@ -886,9 +850,8 @@ static void wlr_format_modifier_pair_add(struct xdpw_screencast_context *ctx, logprint(TRACE, "wlroots: format %u (%lu)", fm_pair->fourcc, fm_pair->modifier); } -static void linux_dmabuf_handle_modifier(void *data, - struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1, - uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) { +static void linux_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1, uint32_t format, uint32_t modifier_hi, + uint32_t modifier_lo) { struct xdpw_screencast_context *ctx = data; logprint(TRACE, "wlroots: linux_dmabuf_handle_modifier called"); @@ -902,8 +865,8 @@ static const struct zwp_linux_dmabuf_v1_listener linux_dmabuf_listener = { .modifier = linux_dmabuf_handle_modifier, }; -static void linux_dmabuf_feedback_handle_main_device(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, struct wl_array *device_arr) { +static void linux_dmabuf_feedback_handle_main_device(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *device_arr) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_handle_main_device called"); @@ -923,8 +886,7 @@ static void linux_dmabuf_feedback_handle_main_device(void *data, ctx->gbm = xdpw_gbm_device_create(drmDev); } -static void linux_dmabuf_feedback_format_table(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, int fd, uint32_t size) { +static void linux_dmabuf_feedback_format_table(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, int fd, uint32_t size) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_format_table called"); @@ -941,8 +903,7 @@ static void linux_dmabuf_feedback_format_table(void *data, ctx->feedback_data.format_table_size = size; } -static void linux_dmabuf_feedback_handle_done(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) { +static void linux_dmabuf_feedback_handle_done(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_handle_done called"); @@ -954,8 +915,8 @@ static void linux_dmabuf_feedback_handle_done(void *data, ctx->feedback_data.format_table_size = 0; } -static void linux_dmabuf_feedback_tranche_target_devices(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, struct wl_array *device_arr) { +static void linux_dmabuf_feedback_tranche_target_devices(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *device_arr) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_tranche_target_devices called"); @@ -979,13 +940,12 @@ static void linux_dmabuf_feedback_tranche_target_devices(void *data, } } -static void linux_dmabuf_feedback_tranche_flags(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, uint32_t flags) { +static void linux_dmabuf_feedback_tranche_flags(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, uint32_t flags) { logprint(DEBUG, "wlroots: linux_dmabuf_feedback_tranche_flags called"); } -static void linux_dmabuf_feedback_tranche_formats(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, struct wl_array *indices) { +static void linux_dmabuf_feedback_tranche_formats(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *indices) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_tranche_formats called"); @@ -1012,8 +972,7 @@ static void linux_dmabuf_feedback_tranche_formats(void *data, } } -static void linux_dmabuf_feedback_tranche_done(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) { +static void linux_dmabuf_feedback_tranche_done(void *data, struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: linux_dmabuf_feedback_tranche_done called"); @@ -1031,8 +990,7 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_listener_ .tranche_done = linux_dmabuf_feedback_tranche_done, }; -static void wlr_registry_handle_add(void *data, struct wl_registry *reg, - uint32_t id, const char *interface, uint32_t ver) { +static void wlr_registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, const char *interface, uint32_t ver) { struct xdpw_screencast_context *ctx = data; logprint(DEBUG, "wlroots: interface to register %s (Version: %u)", interface, ver); @@ -1058,8 +1016,7 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg, version = SC_MANAGER_VERSION_MIN; } logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, version); - ctx->screencopy_manager = wl_registry_bind( - reg, id, &zwlr_screencopy_manager_v1_interface, version); + ctx->screencopy_manager = wl_registry_bind(reg, id, &zwlr_screencopy_manager_v1_interface, version); } if (!strcmp(interface, hyprland_toplevel_export_manager_v1_interface.name) && !ctx->hyprland_toplevel_manager) { @@ -1088,8 +1045,7 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg, if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, XDG_OUTPUT_MANAGER_VERSION); - ctx->xdg_output_manager = - wl_registry_bind(reg, id, &zxdg_output_manager_v1_interface, XDG_OUTPUT_MANAGER_VERSION); + ctx->xdg_output_manager = wl_registry_bind(reg, id, &zxdg_output_manager_v1_interface, XDG_OUTPUT_MANAGER_VERSION); } if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) { uint32_t version = ver; @@ -1111,8 +1067,7 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg, } } -static void wlr_registry_handle_remove(void *data, struct wl_registry *reg, - uint32_t id) { +static void wlr_registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id) { struct xdpw_screencast_context *ctx = data; struct xdpw_wlr_output *output = xdpw_wlr_output_find(ctx, NULL, id); if (output) { @@ -1164,8 +1119,7 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) { // make sure our wlroots supports xdg_output_manager if (!ctx->xdg_output_manager) { - logprint(ERROR, "Compositor doesn't support %s!", - zxdg_output_manager_v1_interface.name); + logprint(ERROR, "Compositor doesn't support %s!", zxdg_output_manager_v1_interface.name); return -1; } @@ -1183,8 +1137,7 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) { // make sure our wlroots supports screencopy protocol if (!ctx->screencopy_manager) { - logprint(ERROR, "Compositor doesn't support %s!", - zwlr_screencopy_manager_v1_interface.name); + logprint(ERROR, "Compositor doesn't support %s!", zwlr_screencopy_manager_v1_interface.name); return -1; } @@ -1210,9 +1163,7 @@ void xdpw_wlr_screencopy_finish(struct xdpw_screencast_context *ctx) { } struct xdpw_screencast_instance *cast, *tmp_c; - wl_list_for_each_safe(cast, tmp_c, &ctx->screencast_instances, link) { - cast->quit = true; - } + wl_list_for_each_safe(cast, tmp_c, &ctx->screencast_instances, link) { cast->quit = true; } if (ctx->screencopy_manager) { zwlr_screencopy_manager_v1_destroy(ctx->screencopy_manager); diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index b8f55e0..d7d403b 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit b8f55e02a328c47ed373133c52483bbfa20a1b75 +Subproject commit d7d403b711b60e8136295b0d4229e89a115e80cc