Bind toplevel protos once before first screencast

Also style.
This commit is contained in:
vaxerski 2023-02-01 17:49:29 +00:00
parent b03b1c2f27
commit ee73fca9cc
3 changed files with 1232 additions and 1235 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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(&current->link); wl_list_remove(&current->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);