mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-24 15:15:58 +01:00
Window sharing (#2)
* added window sharing support * nix: add hyprland-protocols and streamline build Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
This commit is contained in:
parent
1d70c4600b
commit
3c850a0336
11 changed files with 277 additions and 20 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "protocols/hyprland-protocols"]
|
||||||
|
path = protocols/hyprland-protocols
|
||||||
|
url = https://github.com/hyprwm/hyprland-protocols
|
17
flake.lock
17
flake.lock
|
@ -1,5 +1,21 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"hyprland-protocols": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1670185345,
|
||||||
|
"narHash": "sha256-hxWGqlPecqEsE6nOHDV29KFBKePbY2Ipeac6lrChMKY=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprland-protocols",
|
||||||
|
"rev": "4623a404c091e64743ba310199bb380ec52f1936",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprland-protocols",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1669969257,
|
"lastModified": 1669969257,
|
||||||
|
@ -18,6 +34,7 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprland-protocols": "hyprland-protocols",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
flake.nix
12
flake.nix
|
@ -1,13 +1,20 @@
|
||||||
{
|
{
|
||||||
description = "xdg-desktop-portal-hyprland";
|
description = "xdg-desktop-portal-hyprland";
|
||||||
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
hyprland-protocols = {
|
||||||
|
url = "github:hyprwm/hyprland-protocols";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
...
|
...
|
||||||
}: let
|
} @ inputs: let
|
||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
genSystems = lib.genAttrs [
|
genSystems = lib.genAttrs [
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
|
@ -23,6 +30,7 @@
|
||||||
overlays.default = _: prev: {
|
overlays.default = _: prev: {
|
||||||
xdg-desktop-portal-hyprland = prev.callPackage ./nix/default.nix {
|
xdg-desktop-portal-hyprland = prev.callPackage ./nix/default.nix {
|
||||||
version = "0.pre" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
version = "0.pre" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||||
|
inherit (inputs) hyprland-protocols;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
std::cout << "screen:" << ID << "\n";
|
std::cout << "screen:" << ID << "\n";
|
||||||
pickerPtr->quit();
|
pickerPtr->quit();
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +106,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
std::cout << "window:" << HANDLE << "\n";
|
std::cout << "window:" << HANDLE << "\n";
|
||||||
pickerPtr->quit();
|
pickerPtr->quit();
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
windowIterator++;
|
windowIterator++;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
@ -123,6 +124,9 @@ struct xdpw_screencast_context {
|
||||||
struct xdpw_dmabuf_feedback_data feedback_data;
|
struct xdpw_dmabuf_feedback_data feedback_data;
|
||||||
struct wl_array format_modifier_pairs;
|
struct wl_array format_modifier_pairs;
|
||||||
|
|
||||||
|
// hyprland
|
||||||
|
struct hyprland_toplevel_export_manager_v1 *hyprland_toplevel_manager;
|
||||||
|
|
||||||
// gbm
|
// gbm
|
||||||
struct gbm_device *gbm;
|
struct gbm_device *gbm;
|
||||||
|
|
||||||
|
@ -149,6 +153,7 @@ struct xdpw_share {
|
||||||
int y;
|
int y;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
|
int window_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xdpw_screencast_instance {
|
struct xdpw_screencast_instance {
|
||||||
|
@ -185,6 +190,10 @@ struct xdpw_screencast_instance {
|
||||||
bool teardown;
|
bool teardown;
|
||||||
enum buffer_type buffer_type;
|
enum buffer_type buffer_type;
|
||||||
|
|
||||||
|
// hyprland
|
||||||
|
struct hyprland_toplevel_export_frame_v1 *frame_callback_hyprland;
|
||||||
|
struct hyprland_toplevel_export_frame_v1 *hyprland_frame;
|
||||||
|
|
||||||
// fps limit
|
// fps limit
|
||||||
struct fps_limit_state fps_limit;
|
struct fps_limit_state fps_limit;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
wayland-protocols,
|
wayland-protocols,
|
||||||
wayland-scanner,
|
wayland-scanner,
|
||||||
grim,
|
grim,
|
||||||
|
hyprland-protocols,
|
||||||
inih,
|
inih,
|
||||||
libdrm,
|
libdrm,
|
||||||
mesa,
|
mesa,
|
||||||
|
@ -32,6 +33,12 @@ in
|
||||||
nativeBuildInputs = [meson ninja pkg-config wayland-scanner makeWrapper];
|
nativeBuildInputs = [meson ninja pkg-config wayland-scanner makeWrapper];
|
||||||
buildInputs = [inih libdrm mesa pipewire systemd wayland wayland-protocols];
|
buildInputs = [inih libdrm mesa pipewire systemd wayland wayland-protocols];
|
||||||
|
|
||||||
|
preConfigure = ''
|
||||||
|
rmdir protocols/hyprland-protocols
|
||||||
|
|
||||||
|
ln -s ${hyprland-protocols.outPath}/ protocols/hyprland-protocols
|
||||||
|
'';
|
||||||
|
|
||||||
mesonFlags = [
|
mesonFlags = [
|
||||||
"-Dsd-bus-provider=libsystemd"
|
"-Dsd-bus-provider=libsystemd"
|
||||||
];
|
];
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
lib,
|
lib,
|
||||||
cmake,
|
cmake,
|
||||||
qtbase,
|
qtbase,
|
||||||
|
makeShellWrapper,
|
||||||
wrapQtAppsHook,
|
wrapQtAppsHook,
|
||||||
|
grim,
|
||||||
|
slurp,
|
||||||
version ? "git",
|
version ? "git",
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
@ -12,6 +15,14 @@ stdenv.mkDerivation {
|
||||||
inherit version;
|
inherit version;
|
||||||
src = ../hyprland-share-picker;
|
src = ../hyprland-share-picker;
|
||||||
|
|
||||||
nativeBuildInputs = [cmake wrapQtAppsHook];
|
nativeBuildInputs = [cmake wrapQtAppsHook makeShellWrapper];
|
||||||
buildInputs = [qtbase];
|
buildInputs = [qtbase];
|
||||||
|
|
||||||
|
dontWrapQtApps = true;
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
wrapProgramShell $out/bin/hyprland-share-picker \
|
||||||
|
"''${qtWrapperArgs[@]}" \
|
||||||
|
--prefix PATH ":" ${lib.makeBinPath [grim slurp]}
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|
1
protocols/hyprland-protocols
Submodule
1
protocols/hyprland-protocols
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4623a404c091e64743ba310199bb380ec52f1936
|
|
@ -14,6 +14,7 @@ client_protocols = [
|
||||||
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
||||||
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||||
'wlr-screencopy-unstable-v1.xml',
|
'wlr-screencopy-unstable-v1.xml',
|
||||||
|
'hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml'
|
||||||
]
|
]
|
||||||
|
|
||||||
wl_proto_files = []
|
wl_proto_files = []
|
||||||
|
|
|
@ -61,12 +61,17 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
|
||||||
|
|
||||||
cast->ctx = ctx;
|
cast->ctx = ctx;
|
||||||
cast->target = out;
|
cast->target = out;
|
||||||
if (ctx->state->config->screencast_conf.max_fps > 0) {
|
if (out.output == NULL) {
|
||||||
cast->max_framerate = ctx->state->config->screencast_conf.max_fps < (uint32_t)out.output->framerate ?
|
cast->max_framerate = 60; // dirty
|
||||||
ctx->state->config->screencast_conf.max_fps : (uint32_t)out.output->framerate;
|
} else {
|
||||||
} else {
|
if (ctx->state->config->screencast_conf.max_fps > 0) {
|
||||||
cast->max_framerate = (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;
|
||||||
|
} else {
|
||||||
|
cast->max_framerate = (uint32_t)out.output->framerate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast->framerate = cast->max_framerate;
|
cast->framerate = cast->max_framerate;
|
||||||
cast->with_cursor = with_cursor;
|
cast->with_cursor = with_cursor;
|
||||||
cast->refcount = 1;
|
cast->refcount = 1;
|
||||||
|
@ -118,8 +123,8 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
|
||||||
|
|
||||||
struct xdpw_share out;
|
struct xdpw_share out;
|
||||||
out = xdpw_wlr_chooser(ctx);
|
out = xdpw_wlr_chooser(ctx);
|
||||||
if (!out.output) {
|
if (!out.output && out.window_handle == -1) {
|
||||||
logprint(ERROR, "wlroots: no output found");
|
logprint(ERROR, "wlroots: no output / window found");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +157,13 @@ bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *ses
|
||||||
xdpw_screencast_instance_init(ctx, sess->screencast_instance,
|
xdpw_screencast_instance_init(ctx, sess->screencast_instance,
|
||||||
out, with_cursor);
|
out, with_cursor);
|
||||||
}
|
}
|
||||||
logprint(INFO, "wlroots: output: %s",
|
if (out.output) {
|
||||||
sess->screencast_instance->target.output->name);
|
logprint(INFO, "wlroots: output: %s",
|
||||||
|
sess->screencast_instance->target.output->name);
|
||||||
|
} else {
|
||||||
|
logprint(INFO, "hyprland: window handle %d", sess->screencast_instance->target.window_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
#include "wlr-screencopy-unstable-v1-client-protocol.h"
|
#include "wlr-screencopy-unstable-v1-client-protocol.h"
|
||||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
#include "xdg-output-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>
|
||||||
|
@ -249,16 +250,187 @@ static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = {
|
||||||
.damage = wlr_frame_damage,
|
.damage = wlr_frame_damage,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: buffer event handler");
|
||||||
|
cast->hyprland_frame = frame;
|
||||||
|
|
||||||
|
cast->screencopy_frame_info[WL_SHM].width = width;
|
||||||
|
cast->screencopy_frame_info[WL_SHM].height = height;
|
||||||
|
cast->screencopy_frame_info[WL_SHM].stride = stride;
|
||||||
|
cast->screencopy_frame_info[WL_SHM].size = stride * height;
|
||||||
|
cast->screencopy_frame_info[WL_SHM].format = xdpw_format_drm_fourcc_from_wl_shm(format);
|
||||||
|
|
||||||
|
// TODO: am I sure this should be here
|
||||||
|
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) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: linux_dmabuf event handler");
|
||||||
|
|
||||||
|
cast->screencopy_frame_info[DMABUF].width = width;
|
||||||
|
cast->screencopy_frame_info[DMABUF].height = height;
|
||||||
|
cast->screencopy_frame_info[DMABUF].format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hyprland_frame_buffer_done(void *data,
|
||||||
|
struct hyprland_toplevel_export_frame_v1 *frame) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: buffer_done event handler");
|
||||||
|
|
||||||
|
if (!cast->initialized) {
|
||||||
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.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");
|
||||||
|
cast->frame_state = XDPW_FRAME_STATE_RENEG;
|
||||||
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cast->current_frame.xdpw_buffer) {
|
||||||
|
xdpw_pwr_dequeue_buffer(cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cast->current_frame.xdpw_buffer) {
|
||||||
|
logprint(WARN, "hyprland: no current buffer");
|
||||||
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) ||
|
||||||
|
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");
|
||||||
|
cast->frame_state = XDPW_FRAME_STATE_FAILED;
|
||||||
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hyprland_toplevel_export_frame_v1_copy(frame, cast->current_frame.xdpw_buffer->buffer, 0);
|
||||||
|
logprint(TRACE, "hyprland: frame copied");
|
||||||
|
|
||||||
|
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) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: flags event handler");
|
||||||
|
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) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: damage event handler");
|
||||||
|
|
||||||
|
cast->current_frame.damage.x = x;
|
||||||
|
cast->current_frame.damage.y = y;
|
||||||
|
cast->current_frame.damage.width = width;
|
||||||
|
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) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: ready event handler");
|
||||||
|
|
||||||
|
cast->current_frame.tv_sec = ((((uint64_t)tv_sec_hi) << 32) | tv_sec_lo);
|
||||||
|
cast->current_frame.tv_nsec = tv_nsec;
|
||||||
|
logprint(TRACE, "hyprland: timestamp %"PRIu64":%"PRIu32, cast->current_frame.tv_sec, cast->current_frame.tv_nsec);
|
||||||
|
|
||||||
|
cast->frame_state = XDPW_FRAME_STATE_SUCCESS;
|
||||||
|
|
||||||
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hyprland_frame_failed(void *data,
|
||||||
|
struct hyprland_toplevel_export_frame_v1 *frame) {
|
||||||
|
struct xdpw_screencast_instance *cast = data;
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "hyprland: failed event handler");
|
||||||
|
|
||||||
|
cast->frame_state = XDPW_FRAME_STATE_FAILED;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
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) {
|
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(
|
||||||
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output, cast->target.x,
|
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output, cast->target.x,
|
||||||
cast->target.y, cast->target.w, cast->target.h);
|
cast->target.y, cast->target.w, cast->target.h);
|
||||||
} else {
|
} else if (cast->target.window_handle == -1) {
|
||||||
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output(
|
cast->frame_callback = zwlr_screencopy_manager_v1_capture_output(
|
||||||
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output);
|
cast->ctx->screencopy_manager, cast->with_cursor, cast->target.output->output);
|
||||||
|
} else {
|
||||||
|
// share window
|
||||||
|
cast->frame_callback_hyprland = hyprland_toplevel_export_manager_v1_capture_toplevel(
|
||||||
|
cast->ctx->hyprland_toplevel_manager, cast->with_cursor, cast->target.window_handle);
|
||||||
|
|
||||||
|
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,
|
zwlr_screencopy_frame_v1_add_listener(cast->frame_callback,
|
||||||
|
@ -343,9 +515,9 @@ static void wlr_init_xdg_outputs(struct xdpw_screencast_context *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
|
struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
|
||||||
char result[1024];
|
char result[1024] = {0};
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[1024];
|
char buf[1024] = {0};
|
||||||
|
|
||||||
fp = popen("bash -c \"hyprland-share-picker\"", "r");
|
fp = popen("bash -c \"hyprland-share-picker\"", "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
|
@ -361,9 +533,8 @@ struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
|
||||||
|
|
||||||
// great, let's parse it.
|
// great, let's parse it.
|
||||||
|
|
||||||
struct xdpw_share res = {NULL, -1, -1, -1, -1};
|
struct xdpw_share res = {NULL, -1, -1, -1, -1, -1};
|
||||||
|
|
||||||
// TODO: window & region
|
|
||||||
if (strncmp(result, "screen:", 7) == 0) {
|
if (strncmp(result, "screen:", 7) == 0) {
|
||||||
// find output
|
// find output
|
||||||
char* display_name = malloc(strlen(result) - 7);
|
char* display_name = malloc(strlen(result) - 7);
|
||||||
|
@ -429,8 +600,17 @@ struct xdpw_share xdpw_wlr_chooser(struct xdpw_screencast_context *ctx) {
|
||||||
|
|
||||||
struct xdpw_share res2 = {out, coords[0], coords[1], coords[2], coords[3]};
|
struct xdpw_share res2 = {out, coords[0], coords[1], coords[2], coords[3]};
|
||||||
return res2;
|
return res2;
|
||||||
|
} else if (strncmp(result, "window:", 7) == 0) {
|
||||||
|
char *display_name = malloc(strlen(result) - 7);
|
||||||
|
strncpy(display_name, result + 7, strlen(result) - 8);
|
||||||
|
display_name[strlen(result) - 8] = 0;
|
||||||
|
|
||||||
|
res.window_handle = strtol(display_name, NULL, 16);
|
||||||
|
|
||||||
|
free(display_name);
|
||||||
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -668,7 +848,15 @@ 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, wl_shm_interface.name) == 0) {
|
if (!strcmp(interface, hyprland_toplevel_export_manager_v1_interface.name)) {
|
||||||
|
uint32_t version = ver;
|
||||||
|
|
||||||
|
logprint(DEBUG, "hyprland: |-- registered to interface %s (Version %u)", interface, version);
|
||||||
|
|
||||||
|
ctx->hyprland_toplevel_manager = wl_registry_bind(reg, id, &hyprland_toplevel_export_manager_v1_interface, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||||
logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, WL_SHM_VERSION);
|
logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, WL_SHM_VERSION);
|
||||||
ctx->shm = wl_registry_bind(reg, id, &wl_shm_interface, WL_SHM_VERSION);
|
ctx->shm = wl_registry_bind(reg, id, &wl_shm_interface, WL_SHM_VERSION);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue