mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-23 14:55:57 +01:00
initial impl
This commit is contained in:
parent
85f49f4d6c
commit
d16feeefbd
9 changed files with 944 additions and 396 deletions
|
@ -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;
|
||||
|
|
28
include/global_shortcuts.h
Normal file
28
include/global_shortcuts.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
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);
|
|
@ -10,9 +10,10 @@
|
|||
#include <basu/sd-bus.h>
|
||||
#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;
|
||||
|
@ -28,6 +29,7 @@ struct xdpw_state {
|
|||
int timer_poll_fd;
|
||||
struct wl_list timers;
|
||||
struct xdpw_timer *next_timer;
|
||||
struct globalShortcutsInstance shortcutsInstance;
|
||||
};
|
||||
|
||||
struct xdpw_request {
|
||||
|
@ -38,6 +40,7 @@ struct xdpw_session {
|
|||
struct wl_list link;
|
||||
sd_bus_slot *slot;
|
||||
char *session_handle;
|
||||
char *app_id;
|
||||
struct xdpw_screencast_instance *screencast_instance;
|
||||
};
|
||||
|
||||
|
@ -51,11 +54,7 @@ struct xdpw_timer {
|
|||
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);
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
112
protocols/hyprland-global-shortcuts-v1.xml
Normal file
112
protocols/hyprland-global-shortcuts-v1.xml
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="hyprland_global_shortcuts_v1">
|
||||
<copyright>
|
||||
Copyright © 2022 Vaxry
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
</copyright>
|
||||
|
||||
<description summary="registering global shortcuts">
|
||||
This protocol allows a client to register triggerable actions,
|
||||
meant to be global shortcuts.
|
||||
</description>
|
||||
|
||||
<interface name="hyprland_global_shortcuts_manager_v1" version="1">
|
||||
<description summary="manager to register global shortcuts">
|
||||
This object is a manager which offers requests to create global shortcuts.
|
||||
</description>
|
||||
|
||||
<request name="register_shortcut">
|
||||
<description summary="register a shortcut">
|
||||
Register a new global shortcut.
|
||||
|
||||
A global shortcut is anonymous, meaning the app does not know what key(s) trigger it.
|
||||
|
||||
The shortcut's keybinding shall be dealt with by the compositor.
|
||||
|
||||
In the case of a duplicate app_id + id combination, the already_taken protocol error is raised.
|
||||
</description>
|
||||
<arg name="shortcut" type="new_id" interface="hyprland_global_shortcut_v1"/>
|
||||
<arg name="id" type="string" summary="a unique id for the shortcut"/>
|
||||
<arg name="app_id" type="string" summary="the app_id of the application requesting the shortcut"/>
|
||||
<arg name="description" type="string" summary="user-readable text describing what the shortcut does."/>
|
||||
<arg name="trigger_description" type="string" summary="user-readable text describing how to trigger the shortcut for the client to render."/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the manager">
|
||||
All objects created by the manager will still remain valid, until their
|
||||
appropriate destroy request has been called.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_taken" value="0"
|
||||
summary="the app_id + id combination has already been registered."/>
|
||||
</enum>
|
||||
</interface>
|
||||
|
||||
<interface name="hyprland_global_shortcut_v1" version="1">
|
||||
<description summary="a shortcut">
|
||||
This object represents a single shortcut.
|
||||
</description>
|
||||
|
||||
<event name="pressed">
|
||||
<description summary="keystroke pressed">
|
||||
The keystroke was pressed.
|
||||
|
||||
tv_ values hold the timestamp of the occurrence.
|
||||
</description>
|
||||
<arg name="tv_sec_hi" type="uint"
|
||||
summary="high 32 bits of the seconds part of the timestamp"/>
|
||||
<arg name="tv_sec_lo" type="uint"
|
||||
summary="low 32 bits of the seconds part of the timestamp"/>
|
||||
<arg name="tv_nsec" type="uint"
|
||||
summary="nanoseconds part of the timestamp"/>
|
||||
</event>
|
||||
|
||||
<event name="released">
|
||||
<description summary="keystroke released">
|
||||
The keystroke was released.
|
||||
|
||||
tv_ values hold the timestamp of the occurrence.
|
||||
</description>
|
||||
<arg name="tv_sec_hi" type="uint"
|
||||
summary="high 32 bits of the seconds part of the timestamp"/>
|
||||
<arg name="tv_sec_lo" type="uint"
|
||||
summary="low 32 bits of the seconds part of the timestamp"/>
|
||||
<arg name="tv_nsec" type="uint"
|
||||
summary="nanoseconds part of the timestamp"/>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="delete this object, used or not">
|
||||
Destroys the shortcut. Can be sent at any time by the client.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -17,6 +17,7 @@ client_protocols = [
|
|||
hl_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
||||
'wlr-screencopy-unstable-v1.xml',
|
||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
||||
'hyprland-global-shortcuts-v1.xml',
|
||||
]
|
||||
|
||||
wl_proto_files = []
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <poll.h>
|
||||
#include <spa/utils/result.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xdpw.h"
|
||||
#include "logger.h"
|
||||
#include "xdpw.h"
|
||||
|
||||
enum event_loop_fd {
|
||||
EVENT_LOOP_DBUS,
|
||||
|
@ -49,13 +49,11 @@ int main(int argc, char *argv[]) {
|
|||
bool replace = false;
|
||||
|
||||
static const char *shortopts = "l:o:c:f:rh";
|
||||
static const struct option longopts[] = {
|
||||
{ "loglevel", required_argument, NULL, 'l' },
|
||||
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 }
|
||||
};
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
while (1) {
|
||||
int c = getopt_long(argc, argv, shortopts, longopts, NULL);
|
||||
|
@ -125,6 +123,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
wl_list_init(&state.xdpw_sessions);
|
||||
|
||||
initShortcutsInstance(&state, &state.shortcutsInstance);
|
||||
|
||||
ret = xdpw_screenshot_init(&state);
|
||||
if (ret < 0) {
|
||||
logprint(ERROR, "xdpw: failed to initialize screenshot");
|
||||
|
@ -156,7 +156,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static char match[1024];
|
||||
snprintf(match, sizeof(match), "sender='org.freedesktop.DBus',"
|
||||
snprintf(match, sizeof(match),
|
||||
"sender='org.freedesktop.DBus',"
|
||||
"type='signal',"
|
||||
"interface='org.freedesktop.DBus',"
|
||||
"member='NameOwnerChanged',"
|
||||
|
@ -174,24 +175,25 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
wl_list_init(&state.timers);
|
||||
|
||||
struct pollfd pollfds[] = {
|
||||
[EVENT_LOOP_DBUS] = {
|
||||
struct pollfd pollfds[] = {[EVENT_LOOP_DBUS] =
|
||||
{
|
||||
.fd = sd_bus_get_fd(state.bus),
|
||||
.events = POLLIN,
|
||||
},
|
||||
[EVENT_LOOP_WAYLAND] = {
|
||||
[EVENT_LOOP_WAYLAND] =
|
||||
{
|
||||
.fd = wl_display_get_fd(state.wl_display),
|
||||
.events = POLLIN,
|
||||
},
|
||||
[EVENT_LOOP_PIPEWIRE] = {
|
||||
[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,
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
state.timer_poll_fd = pollfds[EVENT_LOOP_TIMER].fd;
|
||||
|
||||
|
|
455
src/globalshortcuts/global_shortcuts.c
Normal file
455
src/globalshortcuts/global_shortcuts.c
Normal file
|
@ -0,0 +1,455 @@
|
|||
#include "include/global_shortcuts.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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) {
|
||||
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 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;
|
||||
|
||||
struct globalShortcut *curr;
|
||||
struct globalShortcutClient *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) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
found:
|
||||
|
||||
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;
|
||||
|
||||
struct globalShortcut *curr;
|
||||
struct globalShortcutClient *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) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
found:
|
||||
|
||||
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;
|
||||
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) {
|
||||
char *token;
|
||||
sd_bus_message_read(msg, "v", "s", &token);
|
||||
logprint(INFO, "dbus: option token: %s", 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);
|
||||
shortcut->description = calloc(1, 1); // todo
|
||||
wl_list_insert(&client->shortcuts, &shortcut->link);
|
||||
|
||||
// sd_bus_message_enter_container(msg, 'e', "sv");
|
||||
// sd_bus_message_exit_container(msg);
|
||||
sd_bus_message_skip(msg, "a{sv}");
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_handle);
|
||||
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);
|
||||
shortcut->description = calloc(1, 1); // todo
|
||||
wl_list_insert(&client->shortcuts, &shortcut->link);
|
||||
|
||||
// sd_bus_message_enter_container(msg, 'e', "sv");
|
||||
// sd_bus_message_exit_container(msg);
|
||||
sd_bus_message_skip(msg, "a{sv}");
|
||||
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);
|
||||
curr->hlShortcut = hyprland_global_shortcuts_manager_v1_register_shortcut(state->shortcutsInstance.manager, curr->name, client->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);
|
||||
|
||||
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_handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
|
@ -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,8 +281,7 @@ 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 ||
|
||||
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) {
|
||||
|
@ -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,8 +435,7 @@ 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 ||
|
||||
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) {
|
||||
|
@ -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,8 +507,7 @@ 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,
|
||||
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,
|
||||
|
@ -536,12 +518,12 @@ static const struct hyprland_toplevel_export_frame_v1_listener hyprland_frame_li
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue