mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-25 23:45:58 +01:00
Bind toplevel protos once before first screencast
Also style.
This commit is contained in:
parent
b03b1c2f27
commit
ee73fca9cc
3 changed files with 1232 additions and 1235 deletions
|
@ -6,9 +6,9 @@
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include "hyprland-toplevel-export-v1-client-protocol.h"
|
|
||||||
|
|
||||||
#include "fps_limit.h"
|
#include "fps_limit.h"
|
||||||
|
#include "hyprland-toplevel-export-v1-client-protocol.h"
|
||||||
|
|
||||||
// this seems to be right based on
|
// this seems to be right based on
|
||||||
// https://github.com/flatpak/xdg-desktop-portal/blob/309a1fc0cf2fb32cceb91dbc666d20cf0a3202c2/src/screen-cast.c#L955
|
// https://github.com/flatpak/xdg-desktop-portal/blob/309a1fc0cf2fb32cceb91dbc666d20cf0a3202c2/src/screen-cast.c#L955
|
||||||
|
@ -105,7 +105,6 @@ struct xdpw_dmabuf_feedback_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xdpw_screencast_context {
|
struct xdpw_screencast_context {
|
||||||
|
|
||||||
// xdpw
|
// xdpw
|
||||||
struct xdpw_state *state;
|
struct xdpw_state *state;
|
||||||
|
|
||||||
|
@ -128,6 +127,7 @@ struct xdpw_screencast_context {
|
||||||
struct hyprland_toplevel_export_manager_v1 *hyprland_toplevel_manager;
|
struct hyprland_toplevel_export_manager_v1 *hyprland_toplevel_manager;
|
||||||
struct zwlr_foreign_toplevel_manager_v1 *wlroots_toplevel_manager;
|
struct zwlr_foreign_toplevel_manager_v1 *wlroots_toplevel_manager;
|
||||||
struct wl_list toplevel_resource_list;
|
struct wl_list toplevel_resource_list;
|
||||||
|
int toplevel_mgr_bind;
|
||||||
|
|
||||||
// gbm
|
// gbm
|
||||||
struct gbm_device *gbm;
|
struct gbm_device *gbm;
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
#include "screencast.h"
|
#include "screencast.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <spa/utils/result.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <drm_fourcc.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <spa/utils/result.h>
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
#include "pipewire_screencast.h"
|
#include "pipewire_screencast.h"
|
||||||
#include "wlr_screencast.h"
|
#include "wlr_screencast.h"
|
||||||
#include "xdpw.h"
|
#include "xdpw.h"
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
static const char object_path[] = "/org/freedesktop/portal/desktop";
|
static const char object_path[] = "/org/freedesktop/portal/desktop";
|
||||||
static const char interface_name[] = "org.freedesktop.impl.portal.ScreenCast";
|
static const char interface_name[] = "org.freedesktop.impl.portal.ScreenCast";
|
||||||
|
@ -49,7 +49,6 @@ void exec_with_shell(char *command) {
|
||||||
|
|
||||||
void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
|
void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
|
||||||
struct xdpw_screencast_instance *cast, struct xdpw_share out, bool with_cursor) {
|
struct xdpw_screencast_instance *cast, struct xdpw_share out, bool with_cursor) {
|
||||||
|
|
||||||
// only run exec_before if there's no other instance running that already ran it
|
// only run exec_before if there's no other instance running that already ran it
|
||||||
if (wl_list_empty(&ctx->screencast_instances)) {
|
if (wl_list_empty(&ctx->screencast_instances)) {
|
||||||
char *exec_before = ctx->state->config->screencast_conf.exec_before;
|
char *exec_before = ctx->state->config->screencast_conf.exec_before;
|
||||||
|
@ -65,8 +64,7 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
|
||||||
cast->max_framerate = 60; // dirty
|
cast->max_framerate = 60; // dirty
|
||||||
} else {
|
} else {
|
||||||
if (ctx->state->config->screencast_conf.max_fps > 0) {
|
if (ctx->state->config->screencast_conf.max_fps > 0) {
|
||||||
cast->max_framerate = ctx->state->config->screencast_conf.max_fps < (uint32_t)out.output->framerate ?
|
cast->max_framerate = ctx->state->config->screencast_conf.max_fps < (uint32_t)out.output->framerate ? ctx->state->config->screencast_conf.max_fps : (uint32_t)out.output->framerate;
|
||||||
ctx->state->config->screencast_conf.max_fps : (uint32_t)out.output->framerate;
|
|
||||||
} else {
|
} else {
|
||||||
cast->max_framerate = (uint32_t)out.output->framerate;
|
cast->max_framerate = (uint32_t)out.output->framerate;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +112,6 @@ void xdpw_screencast_instance_teardown(struct xdpw_screencast_instance *cast) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess, bool with_cursor) {
|
bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess, bool with_cursor) {
|
||||||
|
|
||||||
struct xdpw_wlr_output *output, *tmp_o;
|
struct xdpw_wlr_output *output, *tmp_o;
|
||||||
wl_list_for_each_reverse_safe(output, tmp_o, &ctx->output_list, link) {
|
wl_list_for_each_reverse_safe(output, tmp_o, &ctx->output_list, link) {
|
||||||
logprint(INFO, "wlroots: capturable output: %s model: %s: id: %i name: %s",
|
logprint(INFO, "wlroots: capturable output: %s model: %s: id: %i name: %s",
|
||||||
|
@ -164,9 +161,7 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
|
||||||
logprint(INFO, "hyprland: window handle %d", sess->screencast_instance->target.window_handle);
|
logprint(INFO, "hyprland: window handle %d", sess->screencast_instance->target.window_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_screencast(struct xdpw_screencast_instance *cast) {
|
static int start_screencast(struct xdpw_screencast_instance *cast) {
|
||||||
|
@ -175,6 +170,7 @@ static int start_screencast(struct xdpw_screencast_instance *cast) {
|
||||||
// process at least one frame so that we know
|
// process at least one frame so that we know
|
||||||
// some of the metadata required for the pipewire
|
// some of the metadata required for the pipewire
|
||||||
// remote state connected event
|
// remote state connected event
|
||||||
|
cast->ctx->toplevel_mgr_bind = 1;
|
||||||
wl_display_dispatch(cast->ctx->state->wl_display);
|
wl_display_dispatch(cast->ctx->state->wl_display);
|
||||||
wl_display_roundtrip(cast->ctx->state->wl_display);
|
wl_display_roundtrip(cast->ctx->state->wl_display);
|
||||||
|
|
||||||
|
@ -518,8 +514,7 @@ static const sd_bus_vtable screencast_vtable[] = {
|
||||||
SD_BUS_PROPERTY("version", "u", NULL,
|
SD_BUS_PROPERTY("version", "u", NULL,
|
||||||
offsetof(struct xdpw_state, screencast_version),
|
offsetof(struct xdpw_state, screencast_version),
|
||||||
SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END};
|
||||||
};
|
|
||||||
|
|
||||||
int xdpw_screencast_init(struct xdpw_state *state) {
|
int xdpw_screencast_init(struct xdpw_state *state) {
|
||||||
sd_bus_slot *slot = NULL;
|
sd_bus_slot *slot = NULL;
|
||||||
|
@ -527,6 +522,7 @@ int xdpw_screencast_init(struct xdpw_state *state) {
|
||||||
state->screencast = (struct xdpw_screencast_context){0};
|
state->screencast = (struct xdpw_screencast_context){0};
|
||||||
state->screencast.state = state;
|
state->screencast.state = state;
|
||||||
state->screencast.hyprland_toplevel_manager = NULL;
|
state->screencast.hyprland_toplevel_manager = NULL;
|
||||||
|
state->screencast.toplevel_mgr_bind = 0;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
err = xdpw_pwr_context_create(state);
|
err = xdpw_pwr_context_create(state);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
#include "wlr_screencast.h"
|
#include "wlr_screencast.h"
|
||||||
|
|
||||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
#include <assert.h>
|
||||||
#include "wlr-screencopy-unstable-v1-client-protocol.h"
|
|
||||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
|
||||||
#include "hyprland-toplevel-export-v1-client-protocol.h"
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -15,16 +11,19 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "screencast.h"
|
|
||||||
#include "pipewire_screencast.h"
|
|
||||||
#include "xdpw.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "fps_limit.h"
|
#include "fps_limit.h"
|
||||||
|
#include "hyprland-toplevel-export-v1-client-protocol.h"
|
||||||
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "pipewire_screencast.h"
|
||||||
|
#include "screencast.h"
|
||||||
|
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
||||||
|
#include "wlr-screencopy-unstable-v1-client-protocol.h"
|
||||||
|
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||||
|
#include "xdpw.h"
|
||||||
//
|
//
|
||||||
|
|
||||||
struct SToplevelEntry {
|
struct SToplevelEntry {
|
||||||
|
@ -58,6 +57,8 @@ void handleAppID(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, con
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logprint(DEBUG, "hyprland: toplevel app_id %s", app_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleOutputEnter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *output) {
|
void handleOutputEnter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *output) {
|
||||||
|
@ -86,6 +87,8 @@ void handleClosed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logprint(DEBUG, "hyprland: toplevel closed %s", current->clazz);
|
||||||
|
|
||||||
wl_list_remove(¤t->link);
|
wl_list_remove(¤t->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,10 +117,12 @@ void handleToplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager
|
||||||
wl_list_insert(&ctx->toplevel_resource_list, &entry->link);
|
wl_list_insert(&ctx->toplevel_resource_list, &entry->link);
|
||||||
|
|
||||||
zwlr_foreign_toplevel_handle_v1_add_listener(toplevel, &toplevelHandleListener, ctx);
|
zwlr_foreign_toplevel_handle_v1_add_listener(toplevel, &toplevelHandleListener, ctx);
|
||||||
|
|
||||||
|
logprint(DEBUG, "hyprland: toplevel handle created %lx", toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFinished(void *data, struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1) {
|
void handleFinished(void *data, struct zwlr_foreign_toplevel_manager_v1 *zwlr_foreign_toplevel_manager_v1) {
|
||||||
; // noop
|
logprint(ERROR, "hyprland: compositor called finished on zwlr_foreign_toplevel_manager_v1!");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zwlr_foreign_toplevel_manager_v1_listener toplevelListener = {
|
struct zwlr_foreign_toplevel_manager_v1_listener toplevelListener = {
|
||||||
|
@ -520,11 +525,9 @@ static const struct hyprland_toplevel_export_frame_v1_listener hyprland_frame_li
|
||||||
.flags = hyprland_frame_flags,
|
.flags = hyprland_frame_flags,
|
||||||
.ready = hyprland_frame_ready,
|
.ready = hyprland_frame_ready,
|
||||||
.failed = hyprland_frame_failed,
|
.failed = hyprland_frame_failed,
|
||||||
.damage = hyprland_frame_damage
|
.damage = hyprland_frame_damage};
|
||||||
};
|
|
||||||
|
|
||||||
void xdpw_wlr_register_cb(struct xdpw_screencast_instance *cast) {
|
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 == -1) {
|
if (cast->target.x != -1 && cast->target.y != -1 && cast->target.w != -1 && cast->target.h != -1 && cast->target.window_handle == -1) {
|
||||||
// capture region
|
// capture region
|
||||||
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output_region(
|
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output_region(
|
||||||
|
@ -671,12 +674,10 @@ char *getFormat(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buildWindowList(struct xdpw_screencast_context *ctx) {
|
char *buildWindowList(struct xdpw_screencast_context *ctx) {
|
||||||
|
|
||||||
char *rolling = calloc(1, 1);
|
char *rolling = calloc(1, 1);
|
||||||
|
|
||||||
struct SToplevelEntry *current;
|
struct SToplevelEntry *current;
|
||||||
wl_list_for_each(current, &ctx->toplevel_resource_list, link) {
|
wl_list_for_each(current, &ctx->toplevel_resource_list, link) {
|
||||||
|
|
||||||
char *oldRolling = rolling;
|
char *oldRolling = rolling;
|
||||||
|
|
||||||
rolling = getFormat("%s%u[HC\011]%s[HT\011]%s[HE\011]", rolling, (uint32_t)(((uint64_t)current->handle) & 0xFFFFFFFF), current->clazz, current->name);
|
rolling = getFormat("%s%u[HC\011]%s[HT\011]%s[HE\011]", rolling, (uint32_t)(((uint64_t)current->handle) & 0xFFFFFFFF), current->clazz, current->name);
|
||||||
|
@ -1052,7 +1053,7 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg,
|
||||||
reg, id, &zwlr_screencopy_manager_v1_interface, version);
|
reg, id, &zwlr_screencopy_manager_v1_interface, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(interface, hyprland_toplevel_export_manager_v1_interface.name)) {
|
if (!strcmp(interface, hyprland_toplevel_export_manager_v1_interface.name) && !ctx->hyprland_toplevel_manager) {
|
||||||
uint32_t version = ver;
|
uint32_t version = ver;
|
||||||
|
|
||||||
logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version);
|
logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version);
|
||||||
|
@ -1060,7 +1061,7 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg,
|
||||||
ctx->hyprland_toplevel_manager = wl_registry_bind(reg, id, &hyprland_toplevel_export_manager_v1_interface, version);
|
ctx->hyprland_toplevel_manager = wl_registry_bind(reg, id, &hyprland_toplevel_export_manager_v1_interface, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name)) {
|
if (!strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) && ctx->toplevel_mgr_bind && !ctx->wlroots_toplevel_manager) {
|
||||||
uint32_t version = ver;
|
uint32_t version = ver;
|
||||||
|
|
||||||
logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version);
|
logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version);
|
||||||
|
|
Loading…
Reference in a new issue