diff --git a/cage.c b/cage.c index 5392535..9d604d3 100644 --- a/cage.c +++ b/cage.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #if CAGE_HAS_XWAYLAND @@ -329,6 +330,13 @@ main(int argc, char *argv[]) goto end; } + server.scene = wlr_scene_create(); + if (!server.scene) { + wlr_log(WLR_ERROR, "Unable to create scene"); + ret = 1; + goto end; + } + compositor = wlr_compositor_create(server.wl_display, renderer); if (!compositor) { wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); diff --git a/meson.build b/meson.build index 6b5bce6..dba7599 100644 --- a/meson.build +++ b/meson.build @@ -34,7 +34,7 @@ if is_freebsd ) endif -wlroots = dependency('wlroots', version: '>= 0.14.0', fallback: ['wlroots', 'wlroots']) +wlroots = dependency('wlroots', version: '>= 0.15.0', fallback: ['wlroots', 'wlroots']) wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') pixman = dependency('pixman-1') diff --git a/output.c b/output.c index d8da3b9..3888ec2 100644 --- a/output.c +++ b/output.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -105,63 +106,19 @@ output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *su wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data); } -static void -output_view_for_each_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator, - void *user_data) -{ - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .ox = view->lx, - .oy = view->ly, - }; - - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - view_for_each_surface(view, output_for_each_surface_iterator, &data); -} - -void -output_view_for_each_popup_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator, - void *user_data) -{ - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .ox = view->lx, - .oy = view->ly, - }; - - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); -} - -void -output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, - cg_surface_iterator_func_t iterator, void *user_data) -{ - struct cg_drag_icon *drag_icon; - wl_list_for_each (drag_icon, drag_icons, link) { - if (drag_icon->wlr_drag_icon->mapped) { - double ox = drag_icon->lx; - double oy = drag_icon->ly; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy); - output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface, ox, oy, iterator, - user_data); - } - } -} - static void output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data) { - struct cg_view *view; - wl_list_for_each_reverse (view, &output->server->views, link) { - output_view_for_each_surface(output, view, iterator, user_data); - } + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = 0, + .oy = 0, + }; + wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - output_drag_icons_for_each_surface(output, &output->server->seat->drag_icons, iterator, user_data); + wlr_scene_node_for_each_surface(&output->server->scene->node, output_for_each_surface_iterator, &data); } struct send_frame_done_data { @@ -182,7 +139,7 @@ send_frame_done(struct cg_output *output, struct send_frame_done_data *data) } static void -count_surface_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *_box, void *data) +count_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *data) { size_t *n = data; n++; @@ -207,7 +164,7 @@ scan_out_primary_view(struct cg_output *output) } size_t n_surfaces = 0; - output_view_for_each_surface(output, view, count_surface_iterator, &n_surfaces); + wlr_scene_node_for_each_surface(&view->scene_surface->node, count_surface_iterator, &n_surfaces); if (n_surfaces > 1) { return false; } diff --git a/output.h b/output.h index b3fd3b4..8c5799f 100644 --- a/output.h +++ b/output.h @@ -28,10 +28,6 @@ typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_ void handle_new_output(struct wl_listener *listener, void *data); void output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface, double ox, double oy, cg_surface_iterator_func_t iterator, void *user_data); -void output_view_for_each_popup_surface(struct cg_output *output, struct cg_view *view, - cg_surface_iterator_func_t iterator, void *user_data); -void output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, - cg_surface_iterator_func_t iterator, void *user_data); void output_damage_surface(struct cg_output *output, struct wlr_surface *surface, double lx, double ly, bool whole); void output_set_window_title(struct cg_output *output, const char *title); diff --git a/render.c b/render.c index 166a088..e3ee038 100644 --- a/render.c +++ b/render.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -48,86 +49,6 @@ struct render_data { pixman_region32_t *damage; }; -static void -render_texture(struct wlr_output *wlr_output, pixman_region32_t *output_damage, struct wlr_texture *texture, - const struct wlr_box *box, const float matrix[static 9]) -{ - struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); - - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box->x, box->y, box->width, box->height); - pixman_region32_intersect(&damage, &damage, output_damage); - if (!pixman_region32_not_empty(&damage)) { - goto damage_finish; - } - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; i++) { - scissor_output(wlr_output, &rects[i]); - wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f); - } - -damage_finish: - pixman_region32_fini(&damage); -} - -static void -render_surface_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data) -{ - struct render_data *data = user_data; - struct wlr_output *wlr_output = output->wlr_output; - pixman_region32_t *output_damage = data->damage; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - wlr_log(WLR_DEBUG, "Cannot obtain surface texture"); - return; - } - - scale_box(box, wlr_output->scale); - - float matrix[9]; - enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, box, transform, 0.0f, wlr_output->transform_matrix); - - render_texture(wlr_output, output_damage, texture, box, matrix); -} - -static void -render_drag_icons(struct cg_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) -{ - struct render_data data = { - .damage = damage, - }; - output_drag_icons_for_each_surface(output, drag_icons, render_surface_iterator, &data); -} - -/** - * Render all toplevels without descending into popups. - */ -static void -render_view_toplevels(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage) -{ - struct render_data data = { - .damage = damage, - }; - double ox = view->lx; - double oy = view->ly; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy); - output_surface_for_each_surface(output, view->wlr_surface, ox, oy, render_surface_iterator, &data); -} - -static void -render_view_popups(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage) -{ - struct render_data data = { - .damage = damage, - }; - output_view_for_each_popup_surface(output, view, render_surface_iterator, &data); -} - void output_render(struct cg_output *output, pixman_region32_t *damage) { @@ -161,18 +82,9 @@ output_render(struct cg_output *output, pixman_region32_t *damage) wlr_renderer_clear(renderer, color); } - // TODO: render only top view, possibly use focused view for this, see #35. - struct cg_view *view; - wl_list_for_each_reverse (view, &server->views, link) { - render_view_toplevels(view, output, damage); - } - - struct cg_view *focused_view = seat_get_focus(server->seat); - if (focused_view) { - render_view_popups(focused_view, output, damage); - } - - render_drag_icons(output, damage, &server->seat->drag_icons); + double lx = 0, ly = 0; + wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &lx, &ly); + wlr_scene_render_output(server->scene, wlr_output, lx, ly, damage); renderer_end: /* Draw software cursor in case hardware cursors aren't diff --git a/seat.c b/seat.c index e8f0d92..426c6ba 100644 --- a/seat.c +++ b/seat.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -635,6 +636,8 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon) } drag_icon_damage(drag_icon); + + wlr_scene_node_set_position(&drag_icon->scene_surface->node, drag_icon->lx, drag_icon->ly); } static void @@ -645,6 +648,7 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data) drag_icon_damage(drag_icon); wl_list_remove(&drag_icon->link); wl_list_remove(&drag_icon->destroy.link); + wlr_scene_node_destroy(&drag_icon->scene_surface->node); free(drag_icon); } @@ -687,6 +691,10 @@ handle_start_drag(struct wl_listener *listener, void *data) } drag_icon->seat = seat; drag_icon->wlr_drag_icon = wlr_drag_icon; + drag_icon->scene_surface = wlr_scene_surface_create(&seat->server->scene->node, wlr_drag_icon->surface); + if (!drag_icon->scene_surface) { + return; + } drag_icon->destroy.notify = handle_drag_icon_destroy; wl_signal_add(&wlr_drag_icon->events.destroy, &drag_icon->destroy); diff --git a/seat.h b/seat.h index 188543d..75f1cc6 100644 --- a/seat.h +++ b/seat.h @@ -77,6 +77,7 @@ struct cg_drag_icon { struct wl_list link; // seat::drag_icons struct cg_seat *seat; struct wlr_drag_icon *wlr_drag_icon; + struct wlr_scene_surface *scene_surface; /* The drag icon has a position in layout coordinates. */ double lx, ly; diff --git a/server.h b/server.h index 817637b..835c444 100644 --- a/server.h +++ b/server.h @@ -34,6 +34,7 @@ struct cg_server { enum cg_multi_output_mode output_mode; struct wlr_output_layout *output_layout; + struct wlr_scene *scene; /* Includes disabled outputs; depending on the output_mode * some outputs may be disabled. */ struct wl_list outputs; // cg_output::link diff --git a/view.c b/view.c index 3f3b0ed..93ae95d 100644 --- a/view.c +++ b/view.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "output.h" #include "seat.h" @@ -174,6 +175,9 @@ view_maximize(struct cg_view *view, struct wlr_box *layout_box) { view->lx = layout_box->x; view->ly = layout_box->y; + + wlr_scene_node_set_position(&view->scene_surface->node, view->lx, view->ly); + view->impl->maximize(view, layout_box->width, layout_box->height); } @@ -185,6 +189,8 @@ view_center(struct cg_view *view, struct wlr_box *layout_box) view->lx = (layout_box->width - width) / 2; view->ly = (layout_box->height - height) / 2; + + wlr_scene_node_set_position(&view->scene_surface->node, view->lx, view->ly); } void @@ -226,6 +232,8 @@ view_unmap(struct cg_view *view) child->destroy(child); } + wlr_scene_node_destroy(&view->scene_surface->node); + view->wlr_surface = NULL; } @@ -234,6 +242,11 @@ view_map(struct cg_view *view, struct wlr_surface *surface) { view->wlr_surface = surface; + view->scene_surface = wlr_scene_surface_create(&view->server->scene->node, surface); + if (!view->scene_surface) { + return; + } + struct wlr_subsurface *subsurface; wl_list_for_each (subsurface, &view->wlr_surface->subsurfaces_below, parent_link) { subsurface_create(view, subsurface); diff --git a/view.h b/view.h index cd16e42..82b2943 100644 --- a/view.h +++ b/view.h @@ -26,6 +26,7 @@ struct cg_view { struct wl_list link; // server::views struct wl_list children; // cg_view_child::link struct wlr_surface *wlr_surface; + struct wlr_scene_surface *scene_surface; /* The view has a position in layout coordinates. */ int lx, ly; diff --git a/xdg_shell.c b/xdg_shell.c index 2e42347..5a35b1c 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,14 @@ static void handle_xdg_popup_map(struct wl_listener *listener, void *data) { struct cg_xdg_popup *popup = wl_container_of(listener, popup, map); + struct wlr_scene_node *parent_node = &popup->view_child.view->scene_surface->node; + popup->scene_surface = wlr_scene_surface_create(parent_node, popup->view_child.wlr_surface); + if (!popup->scene_surface) { + return; + } + double sx, sy; + wlr_xdg_popup_get_position(popup->wlr_popup, &sx, &sy); + wlr_scene_node_set_position(&popup->scene_surface->node, sx, sy); view_damage_whole(popup->view_child.view); } @@ -68,6 +77,7 @@ static void handle_xdg_popup_unmap(struct wl_listener *listener, void *data) { struct cg_xdg_popup *popup = wl_container_of(listener, popup, unmap); + wlr_scene_node_destroy(&popup->scene_surface->node); view_damage_whole(popup->view_child.view); } diff --git a/xdg_shell.h b/xdg_shell.h index 45d87db..5ee0bba 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -22,6 +22,7 @@ struct cg_xdg_shell_view { struct cg_xdg_popup { struct cg_view_child view_child; struct wlr_xdg_popup *wlr_popup; + struct wlr_scene_surface *scene_surface; struct wl_listener destroy; struct wl_listener map;