feat: support capture window in obs

This commit is contained in:
DreamMaoMao 2025-08-01 16:49:02 +08:00
parent cf36b8c5ba
commit 0f65d3caa6

View file

@ -33,6 +33,7 @@
#include <wlr/types/wlr_drm.h> #include <wlr/types/wlr_drm.h>
#include <wlr/types/wlr_export_dmabuf_v1.h> #include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_ext_data_control_v1.h> #include <wlr/types/wlr_ext_data_control_v1.h>
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
#include <wlr/types/wlr_ext_image_capture_source_v1.h> #include <wlr/types/wlr_ext_image_capture_source_v1.h>
#include <wlr/types/wlr_ext_image_copy_capture_v1.h> #include <wlr/types/wlr_ext_image_copy_capture_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h> #include <wlr/types/wlr_fractional_scale_v1.h>
@ -229,6 +230,11 @@ struct Client {
struct wlr_scene_tree *scene; struct wlr_scene_tree *scene;
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
struct wlr_scene_tree *scene_surface; struct wlr_scene_tree *scene_surface;
struct wlr_scene_tree *image_capture_tree;
struct wlr_scene *image_capture_scene;
struct wlr_ext_image_capture_source_v1 *image_capture_source;
struct wl_list link; struct wl_list link;
struct wl_list flink; struct wl_list flink;
struct wl_list fadeout_link; struct wl_list fadeout_link;
@ -245,6 +251,8 @@ struct Client {
struct wl_listener set_title; struct wl_listener set_title;
struct wl_listener fullscreen; struct wl_listener fullscreen;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wlr_scene_surface *image_capture_scene_surface;
struct wl_listener activate; struct wl_listener activate;
struct wl_listener associate; struct wl_listener associate;
struct wl_listener dissociate; struct wl_listener dissociate;
@ -303,6 +311,7 @@ struct Client {
float unfocused_opacity; float unfocused_opacity;
char oldmonname[128]; char oldmonname[128];
int scratchpad_width, scratchpad_height; int scratchpad_width, scratchpad_height;
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
}; };
typedef struct { typedef struct {
@ -720,6 +729,11 @@ static unsigned int cursor_mode;
static Client *grabc; static Client *grabc;
static int grabcx, grabcy; /* client-relative */ static int grabcx, grabcy; /* client-relative */
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1
*ext_foreign_toplevel_image_capture_source_manager_v1;
static struct wl_listener new_foreign_toplevel_capture_request;
static struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
static struct wlr_output_layout *output_layout; static struct wlr_output_layout *output_layout;
static struct wlr_box sgeom; static struct wlr_box sgeom;
static struct wl_list mons; static struct wl_list mons;
@ -1882,6 +1896,7 @@ void cleanuplisteners(void) {
wl_list_remove(&request_start_drag.link); wl_list_remove(&request_start_drag.link);
wl_list_remove(&start_drag.link); wl_list_remove(&start_drag.link);
wl_list_remove(&new_session_lock.link); wl_list_remove(&new_session_lock.link);
wl_list_remove(&new_foreign_toplevel_capture_request.link);
#ifdef XWAYLAND #ifdef XWAYLAND
wl_list_remove(&new_xwayland_surface.link); wl_list_remove(&new_xwayland_surface.link);
wl_list_remove(&xwayland_ready.link); wl_list_remove(&xwayland_ready.link);
@ -3184,6 +3199,22 @@ mapnotify(struct wl_listener *listener, void *data) {
c->geom.width += 2 * c->bw; c->geom.width += 2 * c->bw;
c->geom.height += 2 * c->bw; c->geom.height += 2 * c->bw;
c->image_capture_scene = wlr_scene_create();
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
.app_id = client_get_appid(c),
.title = client_get_title(c),
};
c->image_capture_scene = wlr_scene_create();
c->ext_foreign_toplevel = wlr_ext_foreign_toplevel_handle_v1_create(
foreign_toplevel_list, &foreign_toplevel_state);
c->ext_foreign_toplevel->data = c;
#ifdef XWAYLAND
c->image_capture_scene_surface = wlr_scene_surface_create(
&c->image_capture_scene->tree, client_surface(c));
#endif
/* Handle unmanaged clients first so we can return prior create borders */ /* Handle unmanaged clients first so we can return prior create borders */
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
/* Unmanaged clients always are floating */ /* Unmanaged clients always are floating */
@ -3473,6 +3504,26 @@ void outputmgrapply(struct wl_listener *listener, void *data) {
outputmgrapplyortest(config, 0); outputmgrapplyortest(config, 0);
} }
static void
handle_new_foreign_toplevel_capture_request(struct wl_listener *listener,
void *data) {
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request
*request = data;
Client *c = request->toplevel_handle->data;
if (c->image_capture_source == NULL) {
c->image_capture_source =
wlr_ext_image_capture_source_v1_create_with_scene_node(
&c->image_capture_scene->tree.node, event_loop, alloc, drw);
if (c->image_capture_source == NULL) {
return;
}
}
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
request, c->image_capture_source);
}
void // 0.7 custom void // 0.7 custom
outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) { outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) {
/* /*
@ -4297,6 +4348,15 @@ void setup(void) {
power_mgr = wlr_output_power_manager_v1_create(dpy); power_mgr = wlr_output_power_manager_v1_create(dpy);
wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode); wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode);
foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(dpy, 1);
ext_foreign_toplevel_image_capture_source_manager_v1 =
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(dpy, 1);
new_foreign_toplevel_capture_request.notify =
handle_new_foreign_toplevel_capture_request;
wl_signal_add(&ext_foreign_toplevel_image_capture_source_manager_v1->events
.new_request,
&new_foreign_toplevel_capture_request);
/* Creates an output layout, which a wlroots utility for working with an /* Creates an output layout, which a wlroots utility for working with an
* arrangement of screens in a physical layout. */ * arrangement of screens in a physical layout. */
output_layout = wlr_output_layout_create(dpy); output_layout = wlr_output_layout_create(dpy);
@ -4742,6 +4802,11 @@ void unmapnotify(struct wl_listener *listener, void *data) {
c->foreign_toplevel = NULL; c->foreign_toplevel = NULL;
} }
if (c->ext_foreign_toplevel) {
wlr_ext_foreign_toplevel_handle_v1_destroy(c->ext_foreign_toplevel);
c->ext_foreign_toplevel = NULL;
}
if (c->swallowedby) { if (c->swallowedby) {
setfullscreen(c->swallowedby, c->isfullscreen); setfullscreen(c->swallowedby, c->isfullscreen);
setmaxmizescreen(c->swallowedby, c->ismaxmizescreen); setmaxmizescreen(c->swallowedby, c->ismaxmizescreen);
@ -4754,6 +4819,13 @@ void unmapnotify(struct wl_listener *listener, void *data) {
c->swallowing = NULL; c->swallowing = NULL;
} }
#ifdef XWAYLAND
if (client_is_x11(c)) {
wlr_scene_node_destroy(&c->image_capture_scene_surface->buffer->node);
c->image_capture_scene_surface = NULL;
}
#endif
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
wlr_scene_node_destroy(&c->scene->node); wlr_scene_node_destroy(&c->scene->node);
printstatus(); printstatus();
motionnotify(0, NULL, 0, 0, 0, 0); motionnotify(0, NULL, 0, 0, 0, 0);