diff --git a/src/mango.c b/src/mango.c index 529417fe..111adf3a 100644 --- a/src/mango.c +++ b/src/mango.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -316,6 +317,12 @@ struct Client { struct wlr_scene_rect *border; /* top, bottom, left, right */ struct wlr_scene_shadow *shadow; 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 wlr_scene_surface *image_capture_scene_surface; + struct wl_list link; struct wl_list flink; struct wl_list fadeout_link; @@ -407,6 +414,7 @@ struct Client { float focused_opacity; float unfocused_opacity; char oldmonname[128]; + struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel; int32_t noblur; double master_mfact_per, master_inner_per, stack_inner_per; double old_master_mfact_per, old_master_inner_per, old_stack_inner_per; @@ -873,6 +881,11 @@ static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */ static bool start_drag_window = false; static int32_t last_apply_drap_time = 0; +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_box sgeom; static struct wl_list mons; @@ -2252,6 +2265,7 @@ void cleanuplisteners(void) { wl_list_remove(&request_start_drag.link); wl_list_remove(&start_drag.link); wl_list_remove(&new_session_lock.link); + wl_list_remove(&new_foreign_toplevel_capture_request.link); wl_list_remove(&tearing_new_object.link); wl_list_remove(&keyboard_shortcuts_inhibit_new_inhibitor.link); if (drm_lease_manager) { @@ -4130,8 +4144,21 @@ mapnotify(struct wl_listener *listener, void *data) { c->geom.width += 2 * c->bw; c->geom.height += 2 * c->bw; + 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; + c->image_capture_scene_surface = wlr_scene_surface_create( + &c->image_capture_scene->tree, client_surface(c)); + /* Handle unmanaged clients first so we can return prior create borders */ + if (client_is_unmanaged(c)) { /* Unmanaged clients always are floating */ #ifdef XWAYLAND @@ -4476,6 +4503,26 @@ void outputmgrapply(struct wl_listener *listener, void *data) { 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 outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int32_t test) { /* @@ -5608,6 +5655,14 @@ void setup(void) { power_mgr = wlr_output_power_manager_v1_create(dpy); 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); tearing_control = wlr_tearing_control_manager_v1_create(dpy, 1); tearing_new_object.notify = handle_tearing_new_object; wl_signal_add(&tearing_control->events.new_object, &tearing_new_object); @@ -6096,6 +6151,11 @@ void unmapnotify(struct wl_listener *listener, void *data) { 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) { setmaximizescreen(c->swallowedby, c->ismaximizescreen); setfullscreen(c->swallowedby, c->isfullscreen); @@ -6108,6 +6168,8 @@ void unmapnotify(struct wl_listener *listener, void *data) { c->swallowing = NULL; } + wlr_scene_node_destroy(&c->image_capture_scene_surface->buffer->node); + wlr_scene_node_destroy(&c->image_capture_scene->tree.node); c->stack_proportion = 0.0f; c->next_in_stack = NULL; c->prev_in_stack = NULL; @@ -6265,6 +6327,14 @@ void updatetitle(struct wl_listener *listener, void *data) { title = client_get_title(c); if (title && c->foreign_toplevel) wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); + if (title && c->ext_foreign_toplevel) { + wlr_ext_foreign_toplevel_handle_v1_update_state( + c->ext_foreign_toplevel, + &(struct wlr_ext_foreign_toplevel_handle_v1_state){ + .title = title, + .app_id = c->ext_foreign_toplevel->app_id, + }); + } if (c == focustop(c->mon)) printstatus(); }