From c5800b2223400a7f078d1c967af44e4a38bffa47 Mon Sep 17 00:00:00 2001 From: project-repo Date: Wed, 26 Jan 2022 19:36:10 +0100 Subject: [PATCH] Switch to wlr_scene api --- cagebreak.c | 73 ++++++-- input_manager.h | 2 +- keybinding.c | 31 ++-- meson.build | 7 +- message.c | 102 +++++++++-- message.h | 5 +- output.c | 476 ++++++++++-------------------------------------- output.h | 26 +-- render.c | 277 ---------------------------- render.h | 9 - seat.c | 88 ++------- seat.h | 1 + server.c | 2 +- server.h | 7 +- util.c | 3 +- view.c | 197 ++------------------ view.h | 53 +----- workspace.c | 9 + workspace.h | 5 +- xdg_shell.c | 249 +++++++++---------------- xdg_shell.h | 12 -- xwayland.c | 59 +----- xwayland.h | 1 - 23 files changed, 404 insertions(+), 1290 deletions(-) delete mode 100644 render.c delete mode 100644 render.h diff --git a/cagebreak.c b/cagebreak.c index 3aea339..3c144da 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -17,9 +17,13 @@ #include #include #include +#include #include #include +#include #include +#include +#include #include #include #include @@ -28,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -133,9 +139,6 @@ usage(FILE *file, const char *const cage) { "\n" " -r\t Rotate the output 90 degrees clockwise, specify up to three " "times\n" -#ifdef DEBUG - " -D\t Turn on damage tracking debugging\n" -#endif " -h\t Display this help message\n" " -v\t Show the version number and exit\n" " -s\t Show information about the current setup and exit\n", @@ -145,11 +148,7 @@ usage(FILE *file, const char *const cage) { static bool parse_args(struct cg_server *server, int argc, char *argv[]) { int c; -#ifdef DEBUG - while((c = getopt(argc, argv, "rDhvs")) != -1) { -#else while((c = getopt(argc, argv, "rhvs")) != -1) { -#endif switch(c) { case 'r': server->output_transform++; @@ -157,11 +156,6 @@ parse_args(struct cg_server *server, int argc, char *argv[]) { server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; } break; -#ifdef DEBUG - case 'D': - server->debug_damage_tracking = true; - break; -#endif case 'h': usage(stdout, argv[0]); return false; @@ -245,7 +239,6 @@ main(int argc, char *argv[]) { struct wl_event_source *sigterm_source = NULL; struct wl_event_source *sigalrm_source = NULL; struct wlr_backend *backend = NULL; - struct wlr_renderer *renderer = NULL; struct wlr_compositor *compositor = NULL; struct wlr_data_device_manager *data_device_manager = NULL; struct wlr_server_decoration_manager *server_decoration_manager = NULL; @@ -253,6 +246,8 @@ main(int argc, char *argv[]) { struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL; struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; struct wlr_data_control_manager_v1 *data_control_manager = NULL; + struct wlr_viewporter *viewporter = NULL; + struct wlr_presentation *presentation = NULL; struct wlr_xdg_output_manager_v1 *output_manager = NULL; struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; struct wlr_xdg_shell *xdg_shell = NULL; @@ -353,10 +348,23 @@ main(int argc, char *argv[]) { goto end; } - renderer = wlr_backend_get_renderer(backend); - wlr_renderer_init_wl_display(renderer, server.wl_display); + server.renderer = wlr_renderer_autocreate(backend); + if (!server.renderer) { + wlr_log(WLR_ERROR, "Unable to create the wlroots renderer"); + ret = 1; + goto end; + } - server.bg_color = (float[4]){0, 0, 0, 1}; + server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); + if (!server.allocator) { + wlr_log(WLR_ERROR, "Unable to create the wlroots allocator"); + ret = 1; + goto end; + } + + wlr_renderer_init_wl_display(server.renderer, server.wl_display); + + server.bg_color = (float[4]){0, 0, 1, 1}; wl_list_init(&server.outputs); wl_list_init(&server.disabled_outputs); @@ -373,7 +381,15 @@ main(int argc, char *argv[]) { goto end; } - compositor = wlr_compositor_create(server.wl_display, renderer); + server.scene = wlr_scene_create(); + if (!server.scene) { + wlr_log(WLR_ERROR, "Unable to create scene"); + ret = 1; + goto end; + } + wlr_scene_attach_output_layout(server.scene, server.output_layout); + + compositor = wlr_compositor_create(server.wl_display, server.renderer); if(!compositor) { wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); ret = 1; @@ -467,6 +483,29 @@ main(int argc, char *argv[]) { goto end; } + viewporter = wlr_viewporter_create(server.wl_display); + if (!viewporter) { + wlr_log(WLR_ERROR, "Unable to create the viewporter interface"); + ret = 1; + goto end; + } + + presentation = wlr_presentation_create(server.wl_display, server.backend); + if (!presentation) { + wlr_log(WLR_ERROR, "Unable to create the presentation interface"); + ret = 1; + goto end; + } + wlr_scene_set_presentation(server.scene, presentation); + + export_dmabuf_manager = wlr_export_dmabuf_manager_v1_create(server.wl_display); + if (!export_dmabuf_manager) { + wlr_log(WLR_ERROR, "Unable to create the export DMABUF manager"); + ret = 1; + goto end; + } + + screencopy_manager = wlr_screencopy_manager_v1_create(server.wl_display); if(!screencopy_manager) { wlr_log(WLR_ERROR, "Unable to create the screencopy manager"); diff --git a/input_manager.h b/input_manager.h index 6a2cdc3..35318f6 100644 --- a/input_manager.h +++ b/input_manager.h @@ -4,7 +4,7 @@ #include "seat.h" #include "server.h" #include -#include +#include struct cg_input_manager * input_manager_create(struct cg_server *server); diff --git a/keybinding.c b/keybinding.c index b5b6380..7314b09 100644 --- a/keybinding.c +++ b/keybinding.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "input.h" @@ -196,21 +197,13 @@ swap_tile(struct cg_tile *tile, swap_tile->view = tmp_view; if(tile->view != NULL) { view_maximize(tile->view, tile); - view_damage_whole(tile->view); - } else { - wlr_output_damage_add_box(tile->workspace->output->damage, &tile->tile); } workspace_focus_tile( server->curr_output->workspaces[server->curr_output->curr_workspace], swap_tile); if(swap_tile->view != NULL) { view_maximize(swap_tile->view, swap_tile); - view_damage_whole(swap_tile->view); - } else { - wlr_output_damage_add_box(tile->workspace->output->damage, - &swap_tile->tile); } - seat_set_focus(server->seat, swap_tile->view); ipc_send_event( tile->workspace->output->server, @@ -363,12 +356,7 @@ resize(struct cg_tile *tile, const struct cg_tile *parent, int coord_offset, old_height = tile->tile.height, old_width = tile->tile.width; *get_coord(tile) += coord_offset; *get_dim(tile) += dim_offset; - struct wlr_box damage_box = { - .x = old_x, - .y = old_y, - .width = tile->tile.x - old_x == 0 ? tile->tile.width : coord_offset, - .height = tile->tile.y == 0 ? tile->tile.height : coord_offset}; - wlr_output_damage_add_box(tile->workspace->output->damage, &damage_box); + if(tile->view != NULL) { view_maximize(tile->view, tile); } @@ -699,8 +687,6 @@ keybinding_cycle_views(struct cg_server *server, bool reverse) { return; } - wlr_output_damage_add_box(curr_workspace->output->damage, - &curr_workspace->focused_tile->tile); /* Prevent seat_set_focus from reordering the views */ curr_workspace->focused_tile->view = wl_container_of( next_view->link.prev, curr_workspace->focused_tile->view, link); @@ -743,10 +729,9 @@ keybinding_switch_ws(struct cg_server *server, uint32_t ws) { } struct cg_output *output = server->curr_output; uint32_t old_ws = server->curr_output->curr_workspace; - output->curr_workspace = ws; + workspace_focus(output,ws); seat_set_focus(server->seat, server->curr_output->workspaces[ws]->focused_tile->view); - wlr_output_damage_add_whole(output->damage); message_printf(server->curr_output, "Workspace %d", ws + 1); ipc_send_event(output->server, "switch_ws(old_workspace:%d,new_workspace:%d,output:%s)", @@ -794,7 +779,6 @@ keybinding_move_view_to_cycle_output(struct cg_server *server, bool reverse) { server->curr_output->workspaces[server->curr_output->curr_workspace] ->focused_tile->view = NULL; keybinding_cycle_views(server, false); - view_damage_whole(view); if(server->curr_output->workspaces[server->curr_output->curr_workspace] ->focused_tile->view == NULL) { seat_set_focus(server->seat, NULL); @@ -864,7 +848,7 @@ keybinding_set_nws(struct cg_server *server, int nws) { } if(output->curr_workspace >= nws) { - output->curr_workspace = nws - 1; + workspace_focus(output,nws-1); } } server->nws = nws; @@ -908,6 +892,13 @@ keybinding_set_background(struct cg_server *server, float *bg) { server->bg_color[0] = bg[0]; server->bg_color[1] = bg[1]; server->bg_color[2] = bg[2]; + struct cg_output *it=NULL; + wl_list_for_each(it,&server->outputs,link) { + wlr_scene_rect_set_color(it->bg, server->bg_color); + } + wl_list_for_each(it,&server->disabled_outputs,link) { + wlr_scene_rect_set_color(it->bg, server->bg_color); + } } void diff --git a/meson.build b/meson.build index b81b261..6574753 100644 --- a/meson.build +++ b/meson.build @@ -53,12 +53,11 @@ if is_freebsd ) endif -wlroots = dependency('wlroots', version: ['>=0.14.1', '< 0.15.0']) +wlroots = dependency('wlroots', version: ['>=0.14.1', '< 0.16.0']) wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') wayland_cursor = dependency('wayland-cursor') wayland_client = dependency('wayland-client') -pixman = dependency('pixman-1') xkbcommon = dependency('xkbcommon') cairo = dependency('cairo') pango = dependency('pango') @@ -132,7 +131,6 @@ cagebreak_source_strings = [ 'workspace.c', 'output.c', 'parse.c', - 'render.c', 'seat.c', 'util.c', 'view.c', @@ -150,7 +148,6 @@ cagebreak_header_strings = [ 'workspace.h', 'output.h', 'parse.h', - 'render.h', 'seat.h', 'server.h', 'util.h', @@ -194,7 +191,6 @@ cagebreak_dependencies_dict = { 'libinput': [libinput,true], 'libevdev': [libevdev,true], 'libudev': [libudev,true], - 'pixman': [pixman,true], 'pango': [pango,true], 'cairo': [cairo,true], 'pangocairo': [pangocairo,true], @@ -212,7 +208,6 @@ reproducible_build_versions = { 'libinput': '1.19.2', 'libevdev': '1.12.0', 'libudev': '249', - 'pixman': '0.40.0', 'pango': '1.50.0', 'cairo': '1.17.4', 'pangocairo': '1.50.0', diff --git a/message.c b/message.c index 7786a07..8e8e0d1 100644 --- a/message.c +++ b/message.c @@ -2,11 +2,16 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include #include "message.h" #include "output.h" @@ -14,6 +19,62 @@ #include "server.h" #include "util.h" +struct msg_buffer { + struct wlr_buffer base; + void *data; + uint32_t format; + size_t stride; +}; + +static void msg_buffer_destroy(struct wlr_buffer *wlr_buffer) { + struct msg_buffer *buffer = wl_container_of(wlr_buffer, buffer, base); + free(buffer->data); + free(buffer); +} + +static bool msg_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, + uint32_t flags, void **data, uint32_t *format, size_t *stride) { + struct msg_buffer *buffer = wl_container_of(wlr_buffer, buffer, base); + if(data != NULL) { + *data = (void *)buffer->data; + } + if(format != NULL) { + *format = buffer->format; + } + if(stride != NULL) { + *stride = buffer->stride; + } + return true; +} + +static void msg_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { + // This space is intentionally left blank +} + +static const struct wlr_buffer_impl msg_buffer_impl = { + .destroy = msg_buffer_destroy, + .begin_data_ptr_access = msg_buffer_begin_data_ptr_access, + .end_data_ptr_access = msg_buffer_end_data_ptr_access, +}; + +static struct msg_buffer *msg_buffer_create(uint32_t width, uint32_t height, uint32_t stride) { + struct msg_buffer *buffer = calloc(1, sizeof(*buffer)); + if (buffer == NULL) { + return NULL; + } + + wlr_buffer_init(&buffer->base, &msg_buffer_impl, width, height); + buffer->format = DRM_FORMAT_ARGB8888; + buffer->stride = stride; + + buffer->data = malloc(buffer->stride * height); + if (buffer->data == NULL) { + free(buffer); + return NULL; + } + + return buffer; +} cairo_subpixel_order_t to_cairo_subpixel_order(const enum wl_output_subpixel subpixel) { switch(subpixel) { @@ -31,12 +92,11 @@ to_cairo_subpixel_order(const enum wl_output_subpixel subpixel) { return CAIRO_SUBPIXEL_ORDER_DEFAULT; } -struct wlr_texture * +struct msg_buffer * create_message_texture(const char *string, const struct cg_output *output) { const int WIDTH_PADDING = 8; const int HEIGHT_PADDING = 2; - struct wlr_texture *texture; double scale = output->wlr_output->scale; int width = 0; int height = 0; @@ -89,14 +149,21 @@ create_message_texture(const char *string, const struct cg_output *output) { cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); - struct wlr_renderer *renderer = - wlr_backend_get_renderer(output->wlr_output->backend); - texture = wlr_texture_from_pixels(renderer, DRM_FORMAT_ARGB8888, stride, - width, height, data); + + struct msg_buffer *buf=msg_buffer_create(width, height,stride); + void *data_ptr; + + if(!wlr_buffer_begin_data_ptr_access(&buf->base, WLR_BUFFER_DATA_PTR_ACCESS_WRITE,&data_ptr,NULL,NULL)) { + wlr_log(WLR_ERROR, "Failed to get pointer access to message buffer"); + return NULL; + } + memcpy(data_ptr,data,stride*height); + wlr_buffer_end_data_ptr_access(&buf->base); + cairo_surface_destroy(surface); g_object_unref(pango); cairo_destroy(cairo); - return texture; + return buf; } #if CG_HAS_FANALYZE @@ -112,8 +179,8 @@ message_set_output(struct cg_output *output, const char *string, free(box); return; } - message->message = create_message_texture(string, output); - if(!message->message) { + struct msg_buffer *buf = create_message_texture(string, output); + if(!buf) { wlr_log(WLR_ERROR, "Could not create message texture"); free(box); free(message); @@ -122,8 +189,8 @@ message_set_output(struct cg_output *output, const char *string, message->position = box; wl_list_insert(&output->messages, &message->link); - int width = message->message->width; - int height = message->message->height; + int width = buf->base.width; + int height = buf->base.height; message->position->width = width; message->position->height = height; switch(align) { @@ -149,7 +216,13 @@ message_set_output(struct cg_output *output, const char *string, default: break; } - wlr_output_damage_add_box(output->damage, message->position); + + message->message=wlr_scene_buffer_create(&output->scene_output->scene->node,&buf->base); + wlr_scene_node_raise_to_top(&message->message->node); + wlr_scene_node_set_enabled(&message->message->node,true); + struct wlr_box *outp_box = wlr_output_layout_get_box( + output->server->output_layout, output->wlr_output); + wlr_scene_node_set_position(&message->message->node, message->position->x+outp_box->x, message->position->y+outp_box->y); } void @@ -206,9 +279,10 @@ message_clear(struct cg_output *output) { struct cg_message *message, *tmp; wl_list_for_each_safe(message, tmp, &output->messages, link) { wl_list_remove(&message->link); - wlr_output_damage_add_box(output->damage, message->position); - wlr_texture_destroy(message->message); + struct wlr_buffer *buf=message->message->buffer; + wlr_scene_node_destroy(&message->message->node); free(message->position); + buf->impl->destroy(buf); free(message); } } diff --git a/message.h b/message.h index b1081ab..e672f5d 100644 --- a/message.h +++ b/message.h @@ -6,7 +6,7 @@ struct cg_output; struct wlr_box; -struct wlr_texture; +struct wlr_buffer; enum cg_message_align { CG_MESSAGE_TOP_LEFT, @@ -25,7 +25,8 @@ struct cg_message_config { struct cg_message { struct wlr_box *position; - struct wlr_texture *message; + struct wlr_scene_buffer *message; + struct wl_surface *surface; struct wl_list link; }; diff --git a/output.c b/output.c index cf034c3..a31e575 100644 --- a/output.c +++ b/output.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include "keybinding.h" #include "message.h" #include "output.h" -#include "render.h" #include "seat.h" #include "server.h" #include "util.h" @@ -44,367 +44,6 @@ #include "xwayland.h" #endif -static void -output_for_each_surface(struct cg_output *output, - cg_surface_iterator_func_t iterator, void *user_data); - -struct surface_iterator_data { - cg_surface_iterator_func_t user_iterator; - void *user_data; - - struct cg_output *output; - - /* Output-local coordinates. */ - double ox, oy; -}; - -static bool -intersects_with_output(struct cg_output *output, - const struct wlr_output_layout *output_layout, - const struct wlr_box *surface_box) { - /* Since the surface_box's x- and y-coordinates are already output local, - * the x- and y-coordinates of this box need to be 0 for this function to - * work correctly. */ - struct wlr_box output_box = {0}; - wlr_output_effective_resolution(output->wlr_output, &output_box.width, - &output_box.height); - - struct wlr_box intersection; - return wlr_box_intersection(&intersection, &output_box, surface_box); -} - -static void -output_for_each_surface_iterator(struct wlr_surface *surface, int sx, int sy, - void *user_data) { - struct surface_iterator_data *data = user_data; - struct cg_output *output = data->output; - - if(!wlr_surface_has_buffer(surface)) { - return; - } - - struct wlr_box surface_box = { - .x = data->ox + sx + surface->sx, - .y = data->oy + sy + surface->sy, - .width = surface->current.width, - .height = surface->current.height, - }; - - if(!intersects_with_output(output, output->server->output_layout, - &surface_box)) { - return; - } - - data->user_iterator(data->output, surface, &surface_box, data->user_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) { - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .ox = ox, - .oy = oy, - }; - - 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->ox, - .oy = view->oy, - }; - - view_for_each_surface(view, output_for_each_surface_iterator, &data); -} - -void -output_view_for_each_popup(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->ox, - .oy = view->oy, - }; - - view_for_each_popup(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->workspaces[output->curr_workspace]->views, link) { - output_view_for_each_surface(output, view, iterator, user_data); - } - - wl_list_for_each_reverse( - view, &output->workspaces[output->curr_workspace]->unmanaged_views, - link) { - output_view_for_each_surface(output, view, iterator, user_data); - } - - output_drag_icons_for_each_surface( - output, &output->server->seat->drag_icons, iterator, user_data); -} - -struct send_frame_done_data { - struct timespec when; -}; - -static void -send_frame_done_iterator(struct cg_output *output, struct wlr_surface *surface, - struct wlr_box *box, void *user_data) { - struct send_frame_done_data *data = user_data; - wlr_surface_send_frame_done(surface, &data->when); -} - -static void -send_frame_done(struct cg_output *output, struct send_frame_done_data *data) { - output_for_each_surface(output, send_frame_done_iterator, data); -} - -struct damage_data { - bool whole; -}; - -static void -count_surface_iterator(struct cg_output *output, struct wlr_surface *surface, - struct wlr_box *_box, void *data) { - size_t *n = data; - (*n)++; -} - -static bool -scan_out_primary_view(struct cg_output *output) { - struct cg_server *server = output->server; - struct wlr_output *wlr_output = output->wlr_output; - - if(!wl_list_empty(&output->messages)) { - return false; - } - - struct cg_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &server->seat->drag_icons, link) { - if(drag_icon->wlr_drag_icon->mapped) { - return false; - } - } - - struct cg_workspace *ws = output->workspaces[output->curr_workspace]; - if(ws->focused_tile->next != ws->focused_tile) { - return false; - } - - struct cg_view *view = ws->focused_tile->view; - if(view == NULL || view->wlr_surface == NULL) { - return false; - } - - size_t n_surfaces = 0; - output_view_for_each_surface(output, view, count_surface_iterator, - &n_surfaces); - if(n_surfaces > 1) { - return false; - } - -#if CG_HAS_XWAYLAND - if(view->type == CG_XWAYLAND_VIEW) { - struct cg_xwayland_view *xwayland_view = xwayland_view_from_view(view); - if(!wl_list_empty(&xwayland_view->xwayland_surface->children) || - !wl_list_empty(&view->workspace->unmanaged_views)) { - return false; - } - } -#endif - - struct wlr_surface *surface = view->wlr_surface; - - if(!surface->buffer) { - return false; - } - - if((float)surface->current.scale != wlr_output->scale || - surface->current.transform != wlr_output->transform) { - return false; - } - - wlr_output_attach_buffer(wlr_output, &surface->buffer->base); - if(!wlr_output_test(wlr_output)) { - return false; - } - return wlr_output_commit(wlr_output); -} - -static void -damage_surface_iterator(struct cg_output *output, struct wlr_surface *surface, - struct wlr_box *box, void *user_data) { - struct wlr_output *wlr_output = output->wlr_output; - struct damage_data *data = (struct damage_data *)user_data; - bool whole = data->whole; - - scale_box(box, output->wlr_output->scale); - - if(whole) { - wlr_output_damage_add_box(output->damage, box); - } else if(pixman_region32_not_empty(&surface->buffer_damage)) { - pixman_region32_t damage; - pixman_region32_init(&damage); - wlr_surface_get_effective_damage(surface, &damage); - - if(ceil(wlr_output->scale) > surface->current.scale) { - /* When scaling up a surface it'll become - blurry, so we need to expand the damage - region. */ - wlr_region_expand(&damage, &damage, - ceil(wlr_output->scale) - surface->current.scale); - } - pixman_region32_translate(&damage, box->x, box->y); - wlr_output_damage_add(output->damage, &damage); - pixman_region32_fini(&damage); - } -} - -void -output_damage_surface(struct cg_output *output, struct wlr_surface *surface, - double ox, double oy, bool whole) { - struct damage_data data = { - .whole = whole, - }; - - output_surface_for_each_surface(output, surface, ox, oy, - damage_surface_iterator, &data); -} - -static void -handle_output_damage_frame(struct wl_listener *listener, void *data) { - struct cg_output *output = wl_container_of(listener, output, damage_frame); - struct send_frame_done_data frame_data = {0}; - - if(!output->wlr_output->enabled) { - return; - } - - bool scanned_out = scan_out_primary_view(output); - - if(scanned_out && !output->last_scanned_out_view) { - wlr_log(WLR_DEBUG, "Scanning out primary view"); - } - if(output->last_scanned_out_view && !scanned_out) { - wlr_log(WLR_DEBUG, "Stopping primary view scan out"); - wlr_output_damage_add_whole(output->damage); - output->last_scanned_out_view = NULL; - } - if(output->last_scanned_out_view && - output->last_scanned_out_view != seat_get_focus(output->server->seat)) { - wlr_output_damage_add_whole(output->damage); - } - if(scanned_out) { - output->last_scanned_out_view = - output->workspaces[output->curr_workspace]->focused_tile->view; - } - - if(scanned_out) { - goto frame_done; - } - - bool needs_frame; - pixman_region32_t damage; - pixman_region32_init(&damage); - if(!wlr_output_damage_attach_render(output->damage, &needs_frame, - &damage)) { - wlr_log(WLR_ERROR, "Cannot make damage output current"); - goto damage_finish; - } - - if(!needs_frame) { - wlr_output_rollback(output->wlr_output); - goto damage_finish; - } - - output_render(output, &damage); - -damage_finish: - pixman_region32_fini(&damage); - -frame_done: - clock_gettime(CLOCK_MONOTONIC, &frame_data.when); - send_frame_done(output, &frame_data); -} - -static void -handle_output_commit(struct wl_listener *listener, void *data) { - struct cg_output *output = wl_container_of(listener, output, commit); - struct wlr_output_event_commit *event = data; - - if(!output->wlr_output->enabled || output->workspaces == NULL) { - return; - } - - if(event->committed & - (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { - struct cg_view *view; - wl_list_for_each( - view, &output->workspaces[output->curr_workspace]->views, link) { - if(view_is_visible(view)) { - view_maximize(view, view->tile); - } - } - } -} - -static void -handle_output_mode(struct wl_listener *listener, void *data) { - struct cg_output *output = wl_container_of(listener, output, mode); - - if(!output->wlr_output->enabled || output->workspaces == NULL) { - return; - } - - struct cg_view *view; - wl_list_for_each(view, &output->workspaces[output->curr_workspace]->views, - link) { - if(view_is_visible(view)) { - view_maximize(view, view->tile); - } - } -} - void output_clear(struct cg_output *output) { struct cg_server *server = output->server; @@ -485,8 +124,7 @@ output_destroy(struct cg_output *output) { wl_list_remove(&output->destroy.link); wl_list_remove(&output->mode.link); wl_list_remove(&output->commit.link); - wl_list_remove(&output->damage_frame.link); - wl_list_remove(&output->damage_destroy.link); + wl_list_remove(&output->frame.link); output_clear(output); @@ -513,17 +151,22 @@ output_destroy(struct cg_output *output) { } static void -handle_output_damage_destroy(struct wl_listener *listener, void *data) { - struct cg_output *output = - wl_container_of(listener, output, damage_destroy); +handle_output_destroy(struct wl_listener *listener, void *data) { + struct cg_output *output = wl_container_of(listener, output, destroy); output_destroy(output); } static void -handle_output_destroy(struct wl_listener *listener, void *data) { - struct cg_output *output = wl_container_of(listener, output, destroy); - wlr_output_damage_destroy(output->damage); - output_destroy(output); +handle_output_frame(struct wl_listener *listener, void *data) { + struct cg_output *output=wl_container_of(listener, output, frame); + if(!output->wlr_output->enabled) { + return; + } + wlr_scene_output_commit(output->scene_output); + + struct timespec now={0}; + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(output->scene_output, &now); } struct cg_output_config * @@ -570,6 +213,19 @@ output_set_mode(struct wlr_output *output, int width, int height, wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); } wlr_output_set_mode(output, best); + if(!wlr_output_test(output)) { + wlr_log(WLR_ERROR, "Unable to assign configured mode to %s, picking arbitrary available mode",output->name); + struct wlr_output_mode *mode; + wl_list_for_each(mode, &output->modes, link) { + if(mode == best) { + continue; + } + wlr_output_set_mode(output, mode); + if(wlr_output_test(output)) { + break; + } + } + } } void @@ -642,6 +298,59 @@ output_configure(struct cg_server *server, struct cg_output *output) { wlr_output_commit(wlr_output); } } + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output,&output->server->scene->outputs,link) { + if(scene_output->output == wlr_output) { + output->scene_output=scene_output; + break; + } + } + if(output->bg!=NULL) { + wlr_scene_node_destroy(&output->bg->node); + } + output->bg=wlr_scene_rect_create(&output->scene_output->scene->node, output->wlr_output->width,output->wlr_output->height, server->bg_color); + struct wlr_box *box = wlr_output_layout_get_box( + server->output_layout, output->wlr_output); + wlr_scene_node_set_position(&output->bg->node, box->x, box->y); + wlr_scene_node_lower_to_bottom(&output->bg->node); +} + +static void +handle_output_commit(struct wl_listener *listener, void *data) { + struct cg_output *output = wl_container_of(listener, output, commit); + struct wlr_output_event_commit *event = data; + + if(!output->wlr_output->enabled || output->workspaces == NULL) { + return; + } + + if(event->committed & + (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { + struct cg_view *view; + wl_list_for_each( + view, &output->workspaces[output->curr_workspace]->views, link) { + if(view_is_visible(view)) { + view_maximize(view, view->tile); + } + } + } +} + +static void +handle_output_mode(struct wl_listener *listener, void *data) { + struct cg_output *output = wl_container_of(listener, output, mode); + + if(!output->wlr_output->enabled || output->workspaces == NULL) { + return; + } + + struct cg_view *view; + wl_list_for_each(view, &output->workspaces[output->curr_workspace]->views, + link) { + if(view_is_visible(view)) { + view_maximize(view, view->tile); + } + } } #if CG_HAS_FANALYZE @@ -653,6 +362,11 @@ handle_new_output(struct wl_listener *listener, void *data) { struct cg_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; + if(!wlr_output_init_render(wlr_output,server->allocator,server->renderer)) { + wlr_log(WLR_ERROR, "Failed to initialize output rendering"); + return; + } + struct cg_output *output = calloc(1, sizeof(struct cg_output)); if(!output) { wlr_log(WLR_ERROR, "Failed to allocate output"); @@ -661,7 +375,6 @@ handle_new_output(struct wl_listener *listener, void *data) { output->wlr_output = wlr_output; output->server = server; - output->damage = wlr_output_damage_create(wlr_output); output->last_scanned_out_view = NULL; struct cg_output_priorities *it; @@ -675,7 +388,6 @@ handle_new_output(struct wl_listener *listener, void *data) { wlr_output_set_transform(wlr_output, server->output_transform); output->workspaces = NULL; - output->curr_workspace = 0; wl_list_init(&output->messages); if(!wlr_xcursor_manager_load(server->seat->xcursor_manager, @@ -687,7 +399,6 @@ handle_new_output(struct wl_listener *listener, void *data) { output_insert(server, output); output_configure(server, output); - wlr_output_damage_add_whole(output->damage); output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *)); for(unsigned int i = 0; i < server->nws; ++i) { @@ -701,6 +412,9 @@ handle_new_output(struct wl_listener *listener, void *data) { wl_list_init(&output->workspaces[i]->unmanaged_views); } + wlr_scene_node_raise_to_top(&output->workspaces[0]->scene->node); + workspace_focus(output,0); + /* We are the first output. Set the current output to this one. */ if(server->curr_output == NULL) { server->curr_output = output; @@ -709,16 +423,14 @@ handle_new_output(struct wl_listener *listener, void *data) { DEFAULT_XCURSOR, server->seat->cursor); wlr_cursor_warp(server->seat->cursor, NULL, 0, 0); - output->mode.notify = handle_output_mode; - wl_signal_add(&wlr_output->events.mode, &output->mode); - output->commit.notify = handle_output_commit; - wl_signal_add(&wlr_output->events.commit, &output->commit); output->destroy.notify = handle_output_destroy; wl_signal_add(&wlr_output->events.destroy, &output->destroy); - output->damage_frame.notify = handle_output_damage_frame; - wl_signal_add(&output->damage->events.frame, &output->damage_frame); - output->damage_destroy.notify = handle_output_damage_destroy; - wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); + output->frame.notify = handle_output_frame; + wl_signal_add(&wlr_output->events.frame, &output->frame); + output->commit.notify = handle_output_commit; + wl_signal_add(&wlr_output->events.commit, &output->commit); + output->mode.notify = handle_output_mode; + wl_signal_add(&wlr_output->events.mode, &output->mode); ipc_send_event(server, "new_output(output:%s,priority:%d)", output->wlr_output->name, output->priority); } diff --git a/output.h b/output.h index 796d0f4..787efdd 100644 --- a/output.h +++ b/output.h @@ -2,24 +2,23 @@ #define CG_OUTPUT_H #include -#include +#include struct cg_server; struct cg_view; struct wlr_output; -struct wlr_output_damage; struct wlr_surface; struct cg_output { struct cg_server *server; struct wlr_output *wlr_output; - struct wlr_output_damage *damage; + struct wlr_scene_output *scene_output; + struct wlr_scene_rect *bg; struct wl_listener mode; struct wl_listener commit; struct wl_listener destroy; - struct wl_listener damage_frame; - struct wl_listener damage_destroy; + struct wl_listener frame; struct cg_workspace **workspaces; struct wl_list messages; int curr_workspace; @@ -56,23 +55,6 @@ handle_new_output(struct wl_listener *listener, void *data); void output_configure(struct cg_server *server, struct cg_output *output); 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(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 ox, double oy, bool whole); -void output_set_window_title(struct cg_output *output, const char *title); #endif diff --git a/render.c b/render.c deleted file mode 100644 index ca4a2d2..0000000 --- a/render.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Cagebreak: A Wayland tiling compositor. - * - * Copyright (C) 2020-2022 The Cagebreak Authors - * Copyright (C) 2018-2020 Jente Hidskes - * Copyright (C) 2019 The Sway authors - * - * See the LICENSE file accompanying this file. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "message.h" -#include "output.h" -#include "seat.h" -#include "server.h" -#include "util.h" -#include "view.h" -#include "workspace.h" - -static void -scissor_output(struct wlr_output *output, pixman_box32_t *rect) { - struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); - - struct wlr_box box = { - .x = rect->x1, - .y = rect->y1, - .width = rect->x2 - rect->x1, - .height = rect->y2 - rect->y1, - }; - - int output_width, output_height; - wlr_output_transformed_resolution(output, &output_width, &output_height); - enum wl_output_transform transform = - wlr_output_transform_invert(output->transform); - wlr_box_transform(&box, &box, transform, output_width, output_height); - - wlr_renderer_scissor(renderer, &box); -} - -struct render_data { - pixman_region32_t *damage; - int tile_width, tile_height; -}; - -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); - - if(data->tile_width != 0) { - box->width = - box->width > data->tile_width ? data->tile_width : box->width; - } - if(data->tile_height != 0) { - box->height = - box->height > data->tile_height ? data->tile_height : box->height; - } - 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, - .tile_width = 0, - .tile_height = 0, - }; - 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, - .tile_width = 0, - .tile_height = 0, - }; - struct cg_tile *view_tile = view_get_tile(view); - if(view_tile != NULL) { - if(view_tile->tile.width != view->wlr_surface->current.width || - view_tile->tile.height != view->wlr_surface->current.height) { - view_damage_whole(view); - } - data.tile_width = view_tile->tile.width; - data.tile_height = view_tile->tile.height; - } - - double ox, oy; - ox = view->ox; - oy = view->oy; - output_surface_for_each_surface(output, view->wlr_surface, ox, oy, - render_surface_iterator, &data); -} - -static void -render_popup_iterator(struct cg_output *output, struct wlr_surface *surface, - struct wlr_box *box, void *data) { - /* Render this popup's surface. */ - render_surface_iterator(output, surface, box, data); - - /* Render this popup's child toplevels. */ - output_surface_for_each_surface(output, surface, box->x, box->y, - 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, - .tile_width = 0, - .tile_height = 0, - }; - output_view_for_each_popup(output, view, render_popup_iterator, &data); -} - -void -output_render(struct cg_output *output, pixman_region32_t *damage) { - struct cg_server *server = output->server; - struct wlr_output *wlr_output = output->wlr_output; - - struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); - if(!renderer) { - wlr_log(WLR_DEBUG, "Expected the output backend to have a renderer"); - return; - } - - wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); - - if(!pixman_region32_not_empty(damage)) { - wlr_log(WLR_DEBUG, "Output isn't damaged but needs a buffer swap"); - goto renderer_end; - } - -#ifdef DEBUG - if(server->debug_damage_tracking) { - wlr_renderer_clear(renderer, (float[]){1.0F, 0.0F, 0.0F, 1.0F}); - } -#endif - - 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_renderer_clear(renderer, server->bg_color); - } - - bool first = true; - for(struct cg_tile *tile = - output->workspaces[output->curr_workspace]->focused_tile; - first || - tile != output->workspaces[output->curr_workspace]->focused_tile; - tile = tile->next) { - first = false; - /* Only render visible views */ - if(tile->view != NULL) { - render_view_toplevels(tile->view, output, damage); - } - } - - struct cg_view *view; - wl_list_for_each_reverse( - view, &output->workspaces[output->curr_workspace]->unmanaged_views, - link) { - render_view_toplevels(view, output, damage); - } - - struct cg_view *focused_view = seat_get_focus(server->seat); - if(focused_view != NULL) { - render_view_popups(focused_view, output, damage); - } - - struct cg_message *message; - wl_list_for_each_reverse(message, &output->messages, link) { - float matrix[9]; - wlr_matrix_project_box(matrix, message->position, - WL_OUTPUT_TRANSFORM_NORMAL, 0.0F, - wlr_output->transform_matrix); - render_texture(output->wlr_output, damage, message->message, - message->position, matrix); - } - render_drag_icons(output, damage, &server->seat->drag_icons); - -renderer_end: - /* Draw software cursor in case hardware cursors aren't - available. This is a no-op when they are. */ - wlr_output_render_software_cursors(wlr_output, damage); - wlr_renderer_scissor(renderer, NULL); - wlr_renderer_end(renderer); - - int output_width, output_height; - wlr_output_transformed_resolution(wlr_output, &output_width, - &output_height); - - pixman_region32_t frame_damage; - pixman_region32_init(&frame_damage); - - enum wl_output_transform transform = - wlr_output_transform_invert(wlr_output->transform); - wlr_region_transform(&frame_damage, &output->damage->current, transform, - output_width, output_height); - -#ifdef DEBUG - if(server->debug_damage_tracking) { - pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0, - output_width, output_height); - } -#endif - - wlr_output_set_damage(wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); - - if(!wlr_output_commit(wlr_output)) { - wlr_log(WLR_ERROR, "Could not commit output"); - } -} diff --git a/render.h b/render.h deleted file mode 100644 index 0a883bd..0000000 --- a/render.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CG_RENDER_H -#define CG_RENDER_H - -struct cg_output; - -void -output_render(struct cg_output *output, pixman_region32_t *damage); - -#endif diff --git a/seat.c b/seat.c index 280b3ea..e1ed24f 100644 --- a/seat.c +++ b/seat.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -46,67 +47,22 @@ static void drag_icon_update_position(struct cg_drag_icon *drag_icon); -/* XDG toplevels may have nested surfaces, such as popup windows for context - * menus or tooltips. This function tests if any of those are underneath the - * coordinates lx and ly (in output Layout Coordinates). If so, it sets the - * surface pointer to that wlr_surface and the sx and sy coordinates to the - * coordinates relative to that surface's top-left corner. */ -static bool -view_at(const struct cg_view *view, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - struct wlr_box *output_layout_box = wlr_output_layout_get_box( - view->server->output_layout, view->workspace->output->wlr_output); - if(output_layout_box == NULL) { - return false; - } - - double view_sx = lx - view->ox - output_layout_box->x; - double view_sy = ly - view->oy - output_layout_box->y; - - double _sx, _sy; - struct wlr_surface *_surface = - view_wlr_surface_at(view, view_sx, view_sy, &_sx, &_sy); - if(_surface != NULL) { - *sx = _sx; - *sy = _sy; - *surface = _surface; - return true; - } - - return false; -} - /* If desktop_view_at returns a view, there is also a * surface. There cannot be a surface without a view, either. It's * both or nothing. */ static struct cg_view * desktop_view_at(const struct cg_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - struct cg_view *view; - wl_list_for_each( - view, - &server->curr_output->workspaces[server->curr_output->curr_workspace] - ->unmanaged_views, - link) { - if(view_at(view, lx, ly, surface, sx, sy)) { - return view; - } + struct wlr_scene_node *node=wlr_scene_node_at(&server->scene->node, lx,ly,sx,sy); + if(node == NULL || node->type != WLR_SCENE_NODE_SURFACE) { + return NULL; } + *surface = wlr_scene_surface_from_node(node)->surface; - bool first = true; - for(struct cg_tile *tile = - server->curr_output->workspaces[server->curr_output->curr_workspace] - ->focused_tile; - first || - server->curr_output->workspaces[server->curr_output->curr_workspace] - ->focused_tile != tile; - tile = tile->next) { - first = false; - if(tile->view != NULL && view_at(tile->view, lx, ly, surface, sx, sy)) { - return tile->view; - } + while(node != NULL && node->data == NULL) { + node=node->parent; } - return NULL; + return node->data; } static void @@ -720,26 +676,12 @@ handle_cursor_motion(struct wl_listener *listener, void *data) { wlr_idle_notify_activity(seat->server->idle, seat->seat); } -static void -drag_icon_damage(struct cg_drag_icon *drag_icon) { - struct cg_output *output; - wl_list_for_each(output, &drag_icon->seat->server->outputs, link) { - struct wlr_box *output_layout_box = wlr_output_layout_get_box( - output->server->output_layout, output->wlr_output); - output_damage_surface(output, drag_icon->wlr_drag_icon->surface, - drag_icon->lx - output_layout_box->x, - drag_icon->ly - output_layout_box->y, true); - } -} - static void drag_icon_update_position(struct cg_drag_icon *drag_icon) { struct wlr_drag_icon *wlr_icon = drag_icon->wlr_drag_icon; struct cg_seat *seat = drag_icon->seat; struct wlr_touch_point *point; - drag_icon_damage(drag_icon); - switch(wlr_icon->drag->grab_type) { case WLR_DRAG_GRAB_KEYBOARD: return; @@ -756,8 +698,7 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon) { drag_icon->ly = seat->touch_ly; break; } - - drag_icon_damage(drag_icon); + wlr_scene_node_set_position(drag_icon->scene_node, drag_icon->lx, drag_icon->ly); } static void @@ -765,9 +706,9 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *_data) { struct cg_drag_icon *drag_icon = wl_container_of(listener, drag_icon, destroy); - 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_node); free(drag_icon); } @@ -813,6 +754,11 @@ handle_start_drag(struct wl_listener *listener, void *data) { } drag_icon->seat = seat; drag_icon->wlr_drag_icon = wlr_drag_icon; + drag_icon->scene_node = wlr_scene_subsurface_tree_create(&seat->server->scene->node, wlr_drag_icon->surface); + if(!drag_icon->scene_node) { + free(drag_icon); + return; + } drag_icon->destroy.notify = handle_drag_icon_destroy; wl_signal_add(&wlr_drag_icon->events.destroy, &drag_icon->destroy); @@ -1038,5 +984,9 @@ seat_set_focus(struct cg_seat *seat, struct cg_view *view) { NULL); } + wlr_scene_node_raise_to_top(view->scene_node); process_cursor_motion(seat, -1); + struct wlr_box *box = wlr_output_layout_get_box( + server->output_layout, view->workspace->output->wlr_output); + wlr_scene_node_set_position(&view->workspace->output->bg->node, box->x, box->y); } diff --git a/seat.h b/seat.h index 9331042..c581de3 100644 --- a/seat.h +++ b/seat.h @@ -85,6 +85,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_node *scene_node; /* The drag icon has a position in layout coordinates. */ double lx, ly; diff --git a/server.c b/server.c index e5b6137..242fd30 100644 --- a/server.c +++ b/server.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "input_manager.h" diff --git a/server.h b/server.h index 610210d..fbaab40 100644 --- a/server.h +++ b/server.h @@ -35,6 +35,10 @@ struct cg_server { struct wl_listener new_output; struct wl_list output_priorities; + struct wlr_renderer *renderer; + struct wlr_allocator *allocator; + struct wlr_scene *scene; + struct wl_listener xdg_toplevel_decoration; struct wl_listener new_xdg_shell_surface; #if CG_HAS_XWAYLAND @@ -56,9 +60,6 @@ struct cg_server { float *bg_color; uint32_t views_curr_id; uint32_t tiles_curr_id; -#ifdef DEBUG - bool debug_damage_tracking; -#endif }; void diff --git a/util.c b/util.c index 1e7fa7c..4ed180b 100644 --- a/util.c +++ b/util.c @@ -7,10 +7,11 @@ * See the LICENSE file accompanying this file. */ -#include +#include #include "util.h" #include +#include int scale_length(int length, int offset, double scale) { diff --git a/view.c b/view.c index cdb90df..da5aac5 100644 --- a/view.c +++ b/view.c @@ -12,11 +12,13 @@ #include #include #include -#include +#include #include #include #include #include +#include +#include #include "ipc_server.h" #include "output.h" @@ -50,118 +52,6 @@ view_get_prev_view(struct cg_view *view) { return prev; } -void -view_damage_child(struct cg_view_child *child, bool whole) { - if(child->view != NULL) { - view_damage_part(child->view); - } -} - -static void -view_child_handle_commit(struct wl_listener *listener, void *_data) { - struct cg_view_child *child = wl_container_of(listener, child, commit); - view_damage_child(child, false); -} - -static void -subsurface_create(struct cg_view_child *parent, struct cg_view *view, - struct wlr_subsurface *wlr_subsurface); - -static void -view_child_handle_new_subsurface(struct wl_listener *listener, void *data) { - struct cg_view_child *child = - wl_container_of(listener, child, new_subsurface); - struct wlr_subsurface *wlr_subsurface = data; - subsurface_create(child, child->view, wlr_subsurface); -} - -void -view_child_finish(struct cg_view_child *child) { - if(!child) { - return; - } - - if(child->view != NULL) { - view_damage_child(child, true); - } - - struct cg_view_child *subchild, *tmpchild; - wl_list_for_each_safe(subchild, tmpchild, &child->children, parent_link) { - subchild->parent = NULL; - wl_list_remove(&subchild->parent_link); - } - - wl_list_remove(&child->link); - if(child->parent != NULL) { - wl_list_remove(&child->parent_link); - } - wl_list_remove(&child->commit.link); - wl_list_remove(&child->new_subsurface.link); -} - -void -view_child_init(struct cg_view_child *child, struct cg_view_child *parent, - struct cg_view *view, struct wlr_surface *wlr_surface) { - child->view = view; - child->parent = parent; - if(parent != NULL) { - wl_list_insert(&parent->children, &child->parent_link); - } - child->wlr_surface = wlr_surface; - wl_list_init(&child->children); - - child->commit.notify = view_child_handle_commit; - wl_signal_add(&wlr_surface->events.commit, &child->commit); - child->new_subsurface.notify = view_child_handle_new_subsurface; - wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface); - - wl_list_insert(&view->children, &child->link); -} - -static void -subsurface_destroy(struct cg_view_child *child) { - if(!child) { - return; - } - - struct cg_subsurface *subsurface = (struct cg_subsurface *)child; - wl_list_remove(&subsurface->destroy.link); - view_child_finish(&subsurface->view_child); - free(subsurface); -} - -static void -subsurface_handle_destroy(struct wl_listener *listener, void *_data) { - struct cg_subsurface *subsurface = - wl_container_of(listener, subsurface, destroy); - struct cg_view_child *view_child = (struct cg_view_child *)subsurface; - subsurface_destroy(view_child); -} - -static void -subsurface_create(struct cg_view_child *parent, struct cg_view *view, - struct wlr_subsurface *wlr_subsurface) { - struct cg_subsurface *subsurface = calloc(1, sizeof(struct cg_subsurface)); - if(!subsurface) { - return; - } - - view_child_init(&subsurface->view_child, parent, view, - wlr_subsurface->surface); - subsurface->view_child.destroy = subsurface_destroy; - subsurface->wlr_subsurface = wlr_subsurface; - - subsurface->destroy.notify = subsurface_handle_destroy; - wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); -} - -static void -handle_new_subsurface(struct wl_listener *listener, void *data) { - struct cg_view *view = wl_container_of(listener, view, new_subsurface); - struct wlr_subsurface *wlr_subsurface = data; - subsurface_create(NULL, view, wlr_subsurface); -} - char * view_get_title(const struct cg_view *view) { const char *title = view->impl->get_title(view); @@ -196,28 +86,6 @@ view_is_visible(const struct cg_view *view) { return view_get_tile(view) != NULL; } -void -view_damage(struct cg_view *view, bool whole) { - struct cg_tile *view_tile = view_get_tile(view); - if(view_tile != NULL && - (view->wlr_surface->current.width != view_tile->tile.width || - view->wlr_surface->current.height != view_tile->tile.height)) { - view_maximize(view, view_tile); - } - output_damage_surface(view->workspace->output, view->wlr_surface, view->ox, - view->oy, whole); -} - -void -view_damage_part(struct cg_view *view) { - view_damage(view, false); -} - -void -view_damage_whole(struct cg_view *view) { - view_damage(view, true); -} - void view_activate(struct cg_view *view, bool activate) { if(view != NULL) { @@ -229,25 +97,13 @@ void view_maximize(struct cg_view *view, struct cg_tile *tile) { view->ox = tile->tile.x; view->oy = tile->tile.y; + struct wlr_box *box = wlr_output_layout_get_box( + view->server->output_layout, view->workspace->output->wlr_output); + wlr_scene_node_set_position(view->scene_node, view->ox+box->x, view->oy+box->y); view->impl->maximize(view, tile->tile.width, tile->tile.height); view->tile = tile; } -void -view_for_each_surface(struct cg_view *view, - wlr_surface_iterator_func_t iterator, void *data) { - view->impl->for_each_surface(view, iterator, data); -} - -void -view_for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, - void *data) { - if(!view->impl->for_each_popup) { - return; - } - view->impl->for_each_popup(view, iterator, data); -} - void view_unmap(struct cg_view *view) { @@ -261,19 +117,13 @@ view_unmap(struct cg_view *view) { return; } - struct cg_view_child *child, *tmp; - wl_list_for_each_safe(child, tmp, &view->children, link) { - child->destroy(child); - } + wlr_scene_node_destroy(view->scene_node); + #if CG_HAS_XWAYLAND if((view->type != CG_XWAYLAND_VIEW || xwayland_view_should_manage(view))) #endif { struct cg_tile *view_tile = view_get_tile(view); - if(view_tile != NULL) { - wlr_output_damage_add_box(view_tile->workspace->output->damage, - &view_tile->tile); - } struct cg_view *prev = view_get_prev_view(view); if(view == view->server->seat->focused_view) { seat_set_focus(view->server->seat, prev); @@ -285,8 +135,6 @@ view_unmap(struct cg_view *view) { } view_tile = view_get_tile(view); if(view_tile != NULL) { - wlr_output_damage_add_box(view_tile->workspace->output->damage, - &view_tile->tile); view_tile->view = prev; if(prev != NULL) { view_maximize(prev, view_tile); @@ -295,7 +143,6 @@ view_unmap(struct cg_view *view) { } #if CG_HAS_XWAYLAND else { - view_damage_whole(view); if(view->server->seat->seat->keyboard_state.focused_surface == NULL || view->server->seat->seat->keyboard_state.focused_surface == view->wlr_surface) { @@ -307,7 +154,6 @@ view_unmap(struct cg_view *view) { wl_list_remove(&view->link); - wl_list_remove(&view->new_subsurface.link); view->wlr_surface = NULL; ipc_send_event(view->workspace->server, "view_unmap(view_id:%d,tile_id:%d,workspace:%d,output:%s," @@ -321,21 +167,12 @@ view_map(struct cg_view *view, struct wlr_surface *surface, struct cg_output *output = ws->output; view->wlr_surface = surface; - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &view->wlr_surface->subsurfaces_above, - parent_link) { - subsurface_create(NULL, view, subsurface); + view->scene_node=wlr_scene_subsurface_tree_create(&ws->scene->node, surface); + if(!view->scene_node) { + wl_resource_post_no_memory(surface->resource); + return; } - - wl_list_for_each(subsurface, &view->wlr_surface->subsurfaces_below, - parent_link) { - subsurface_create(NULL, view, subsurface); - } - - view->new_subsurface.notify = handle_new_subsurface; - wl_signal_add(&view->wlr_surface->events.new_subsurface, - &view->new_subsurface); - + view->scene_node->data=view; view->workspace = ws; #if CG_HAS_XWAYLAND @@ -381,12 +218,4 @@ view_init(struct cg_view *view, enum cg_view_type type, view->impl = impl; view->id = server->views_curr_id; ++server->views_curr_id; - - wl_list_init(&view->children); -} - -struct wlr_surface * -view_wlr_surface_at(const struct cg_view *view, double sx, double sy, - double *sub_x, double *sub_y) { - return view->impl->wlr_surface_at(view, sx, sy, sub_x, sub_y); } diff --git a/view.h b/view.h index 772728d..9484d58 100644 --- a/view.h +++ b/view.h @@ -21,9 +21,9 @@ struct cg_view { struct cg_workspace *workspace; struct cg_server *server; struct wl_list link; // server::views - struct wl_list children; // cg_view_child::link struct wlr_surface *wlr_surface; struct cg_tile *tile; + struct wlr_scene_node *scene_node; /* The view has a position in output coordinates. */ int ox, oy; @@ -31,7 +31,6 @@ struct cg_view { enum cg_view_type type; const struct cg_view_impl *impl; - struct wl_listener new_subsurface; uint32_t id; }; @@ -42,34 +41,6 @@ struct cg_view_impl { void (*close)(struct cg_view *view); void (*maximize)(struct cg_view *view, int width, int height); void (*destroy)(struct cg_view *view); - void (*for_each_surface)(struct cg_view *view, - wlr_surface_iterator_func_t iterator, void *data); - void (*for_each_popup)(struct cg_view *view, - wlr_surface_iterator_func_t iterator, void *data); - struct wlr_surface *(*wlr_surface_at)(const struct cg_view *view, double sx, - double sy, double *sub_x, - double *sub_y); -}; - -struct cg_view_child { - struct cg_view *view; - struct cg_view_child *parent; - struct wl_list children; - struct wlr_surface *wlr_surface; - struct wl_list link; - struct wl_list parent_link; - - struct wl_listener commit; - struct wl_listener new_subsurface; - - void (*destroy)(struct cg_view_child *child); -}; - -struct cg_subsurface { - struct cg_view_child view_child; - struct wlr_subsurface *wlr_subsurface; - - struct wl_listener destroy; }; char * @@ -81,20 +52,8 @@ view_is_primary(const struct cg_view *view); bool view_is_visible(const struct cg_view *view); void -view_damage_part(struct cg_view *view); -void -view_damage_whole(struct cg_view *view); -void -view_damage_child(struct cg_view_child *view, bool whole); -void view_activate(struct cg_view *view, bool activate); void -view_for_each_surface(struct cg_view *view, - wlr_surface_iterator_func_t iterator, void *data); -void -view_for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, - void *data); -void view_unmap(struct cg_view *view); void view_maximize(struct cg_view *view, struct cg_tile *tile); @@ -106,16 +65,6 @@ view_destroy(struct cg_view *view); void view_init(struct cg_view *view, enum cg_view_type type, const struct cg_view_impl *impl, struct cg_server *server); - -struct wlr_surface * -view_wlr_surface_at(const struct cg_view *view, double sx, double sy, - double *sub_x, double *sub_y); - -void -view_child_finish(struct cg_view_child *child); -void -view_child_init(struct cg_view_child *child, struct cg_view_child *parent, - struct cg_view *view, struct wlr_surface *wlr_surface); struct cg_view * view_get_prev_view(struct cg_view *view); diff --git a/workspace.c b/workspace.c index e7da406..4000545 100644 --- a/workspace.c +++ b/workspace.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "message.h" #include "output.h" @@ -57,6 +58,7 @@ full_screen_workspace(struct cg_output *output) { } workspace->server = output->server; workspace->num = -1; + workspace->scene = wlr_scene_tree_create(&output->scene_output->scene->node); if(full_screen_workspace_tiles(output->server->output_layout, output->wlr_output, workspace, &output->server->tiles_curr_id) != 0) { @@ -95,3 +97,10 @@ workspace_free(struct cg_workspace *workspace) { workspace_free_tiles(workspace); free(workspace); } + +void +workspace_focus(struct cg_output *outp, int ws) { + wlr_scene_node_place_above(&outp->bg->node,&outp->workspaces[outp->curr_workspace]->scene->node); + wlr_scene_node_place_above(&outp->workspaces[ws]->scene->node,&outp->bg->node); + outp->curr_workspace=ws; +} diff --git a/workspace.h b/workspace.h index 43eb250..77a9b00 100644 --- a/workspace.h +++ b/workspace.h @@ -1,7 +1,7 @@ #ifndef CG_WORKSPACE_H #define CG_WORKSPACE_H -#include +#include struct cg_output; struct cg_server; @@ -20,6 +20,7 @@ struct cg_workspace { struct wl_list views; struct wl_list unmanaged_views; struct cg_output *output; + struct wlr_scene_tree *scene; struct cg_tile *focused_tile; uint32_t num; @@ -38,5 +39,7 @@ void workspace_free(struct cg_workspace *workspace); void workspace_focus_tile(struct cg_workspace *ws, struct cg_tile *tile); +void +workspace_focus(struct cg_output *outp, int ws); #endif diff --git a/xdg_shell.c b/xdg_shell.c index 7972b5f..b5bc24b 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -10,13 +10,15 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include -#include +#include #include #include #include #include #include +#include #include "output.h" #include "server.h" @@ -24,10 +26,29 @@ #include "workspace.h" #include "xdg_shell.h" +static struct cg_view * +popup_get_view(struct wlr_xdg_popup *popup) { + while(true) { + if(popup->parent == NULL || !wlr_surface_is_xdg_surface(popup->parent)) { + return NULL; + } + struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(popup->parent); + switch(xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + return xdg_surface->data; + case WLR_XDG_SURFACE_ROLE_POPUP: + popup=xdg_surface->popup; + break; + case WLR_XDG_SURFACE_ROLE_NONE: + return NULL; + } + } +} + static void -xdg_decoration_handle_destroy(struct wl_listener *listener, void *_data) { - struct cg_xdg_decoration *xdg_decoration = - wl_container_of(listener, xdg_decoration, destroy); +xdg_decoration_handle_destroy(struct wl_listener *listener, void *data) +{ + struct cg_xdg_decoration *xdg_decoration = wl_container_of(listener, xdg_decoration, destroy); wl_list_remove(&xdg_decoration->destroy.link); wl_list_remove(&xdg_decoration->request_mode.link); @@ -53,54 +74,8 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { #endif static void -xdg_popup_destroy(struct cg_view_child *child) { - if(!child) { - return; - } - - view_damage_child(child, true); - struct cg_xdg_popup *popup = (struct cg_xdg_popup *)child; - wl_list_remove(&popup->destroy.link); - wl_list_remove(&popup->map.link); - wl_list_remove(&popup->unmap.link); - wl_list_remove(&popup->new_popup.link); - view_child_finish(&popup->view_child); - free(popup); -} - -static void -handle_xdg_popup_map(struct wl_listener *listener, void *_data) { - struct cg_xdg_popup *popup = wl_container_of(listener, popup, map); - view_damage_whole(popup->view_child.view); -} - -static void -handle_xdg_popup_unmap(struct wl_listener *listener, void *_data) { - struct cg_xdg_popup *popup = wl_container_of(listener, popup, unmap); - view_damage_whole(popup->view_child.view); -} - -static void -handle_xdg_popup_destroy(struct wl_listener *listener, void *_data) { - struct cg_xdg_popup *popup = wl_container_of(listener, popup, destroy); - struct cg_view_child *view_child = (struct cg_view_child *)popup; - xdg_popup_destroy(view_child); -} - -static void -xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup); - -static void -popup_handle_new_xdg_popup(struct wl_listener *listener, void *data) { - struct cg_xdg_popup *popup = wl_container_of(listener, popup, new_popup); - struct wlr_xdg_popup *wlr_popup = data; - xdg_popup_create(popup->view_child.view, wlr_popup); -} - -static void -popup_unconstrain(struct cg_xdg_popup *popup) { - struct cg_view *view = popup->view_child.view; - struct wlr_box *popup_box = &popup->wlr_popup->geometry; +popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup) { + struct wlr_box *popup_box = &popup->geometry; struct wlr_output_layout *output_layout = view->server->output_layout; struct wlr_box *view_output_box = wlr_output_layout_get_box( @@ -116,37 +91,7 @@ popup_unconstrain(struct cg_xdg_popup *popup) { .width = output_box->width, .height = output_box->height}; - wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box); -} - -static void -xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup) { - struct cg_xdg_popup *popup = calloc(1, sizeof(struct cg_xdg_popup)); - if(!popup) { - return; - } - - popup->wlr_popup = wlr_popup; - view_child_init(&popup->view_child, NULL, view, wlr_popup->base->surface); - popup->view_child.destroy = xdg_popup_destroy; - popup->destroy.notify = handle_xdg_popup_destroy; - wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); - popup->map.notify = handle_xdg_popup_map; - wl_signal_add(&wlr_popup->base->events.map, &popup->map); - popup->unmap.notify = handle_xdg_popup_unmap; - wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap); - popup->new_popup.notify = popup_handle_new_xdg_popup; - wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); - - popup_unconstrain(popup); -} - -static void -handle_new_xdg_popup(struct wl_listener *listener, void *data) { - struct cg_xdg_shell_view *xdg_shell_view = - wl_container_of(listener, xdg_shell_view, new_popup); - struct wlr_xdg_popup *wlr_popup = data; - xdg_popup_create(&xdg_shell_view->view, wlr_popup); + wlr_xdg_popup_unconstrain_from_box(popup, &output_toplevel_box); } static struct cg_xdg_shell_view * @@ -206,31 +151,6 @@ destroy(struct cg_view *view) { free(xdg_shell_view); } -static void -for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, - void *data) { - struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_surface_for_each_surface(xdg_shell_view->xdg_surface, iterator, - data); -} - -static void -for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, - void *data) { - struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_surface_for_each_popup_surface(xdg_shell_view->xdg_surface, - iterator, data); -} - -static struct wlr_surface * -wlr_surface_at(const struct cg_view *view, double sx, double sy, double *sub_x, - double *sub_y) { - const struct cg_xdg_shell_view *xdg_shell_view = - xdg_shell_view_from_const_view(view); - return wlr_xdg_surface_surface_at(xdg_shell_view->xdg_surface, sx, sy, - sub_x, sub_y); -} - static void handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, void *data) { @@ -241,23 +161,12 @@ handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, event->fullscreen); } -static void -handle_xdg_shell_surface_commit(struct wl_listener *listener, void *_data) { - struct cg_xdg_shell_view *xdg_shell_view = - wl_container_of(listener, xdg_shell_view, commit); - struct cg_view *view = &xdg_shell_view->view; - view_damage_part(view); -} - static void handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *_data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, unmap); struct cg_view *view = &xdg_shell_view->view; - wl_list_remove(&xdg_shell_view->new_popup.link); - wl_list_remove(&xdg_shell_view->commit.link); - view_unmap(view); } @@ -267,17 +176,9 @@ handle_xdg_shell_surface_map(struct wl_listener *listener, void *_data) { wl_container_of(listener, xdg_shell_view, map); struct cg_view *view = &xdg_shell_view->view; - xdg_shell_view->commit.notify = handle_xdg_shell_surface_commit; - wl_signal_add(&xdg_shell_view->xdg_surface->surface->events.commit, - &xdg_shell_view->commit); - xdg_shell_view->new_popup.notify = handle_new_xdg_popup; - wl_signal_add(&xdg_shell_view->xdg_surface->events.new_popup, - &xdg_shell_view->new_popup); - view_map(view, xdg_shell_view->xdg_surface->surface, view->server->curr_output ->workspaces[view->server->curr_output->curr_workspace]); - view_damage_whole(view); } static void @@ -301,43 +202,75 @@ static const struct cg_view_impl xdg_shell_view_impl = { .activate = activate, .close = close, .maximize = maximize, - .destroy = destroy, - .for_each_surface = for_each_surface, - .for_each_popup = for_each_popup, - .wlr_surface_at = wlr_surface_at, + .destroy = destroy }; + void -handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) { - struct cg_server *server = - wl_container_of(listener, server, new_xdg_shell_surface); +handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, new_xdg_shell_surface); struct wlr_xdg_surface *xdg_surface = data; - if(xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) { - return; + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; + struct cg_xdg_shell_view *xdg_shell_view = calloc(1, sizeof(struct cg_xdg_shell_view)); + if (!xdg_shell_view) { + wlr_log(WLR_ERROR, "Failed to allocate XDG Shell view"); + return; + } + + view_init(&xdg_shell_view->view, CG_XDG_SHELL_VIEW, &xdg_shell_view_impl,server); + + xdg_shell_view->xdg_surface = xdg_surface; + + xdg_shell_view->map.notify = handle_xdg_shell_surface_map; + wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); + xdg_shell_view->unmap.notify = handle_xdg_shell_surface_unmap; + wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); + xdg_shell_view->destroy.notify = handle_xdg_shell_surface_destroy; + wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); + xdg_shell_view->request_fullscreen.notify = handle_xdg_shell_surface_request_fullscreen; + wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &xdg_shell_view->request_fullscreen); + + xdg_surface->data = xdg_shell_view; + break; + case WLR_XDG_SURFACE_ROLE_POPUP:; + struct wlr_xdg_popup *popup = xdg_surface->popup; + struct cg_view *view = popup_get_view(popup); + if (view == NULL) { + return; + } + + struct wlr_scene_node *parent_scene_node = NULL; + struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface(popup->parent); + switch (parent->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; + parent_scene_node = view->scene_node; + break; + case WLR_XDG_SURFACE_ROLE_POPUP: + parent_scene_node = parent->data; + break; + case WLR_XDG_SURFACE_ROLE_NONE: + break; + } + if (parent_scene_node == NULL) { + return; + } + + struct wlr_scene_node *popup_scene_node = wlr_scene_xdg_surface_create(parent_scene_node, xdg_surface); + if (popup_scene_node == NULL) { + wlr_log(WLR_ERROR, "Failed to allocate scene-graph node for XDG popup"); + return; + } + + popup_unconstrain(view, popup); + + xdg_surface->data = popup_scene_node; + break; + case WLR_XDG_SURFACE_ROLE_NONE: + assert(false); // unreachable } - - struct cg_xdg_shell_view *xdg_shell_view = - calloc(1, sizeof(struct cg_xdg_shell_view)); - if(!xdg_shell_view) { - wlr_log(WLR_ERROR, "Failed to allocate XDG Shell view"); - return; - } - view_init(&xdg_shell_view->view, CG_XDG_SHELL_VIEW, &xdg_shell_view_impl, - server); - - xdg_shell_view->xdg_surface = xdg_surface; - - xdg_shell_view->map.notify = handle_xdg_shell_surface_map; - wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); - xdg_shell_view->unmap.notify = handle_xdg_shell_surface_unmap; - wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); - xdg_shell_view->destroy.notify = handle_xdg_shell_surface_destroy; - wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); - xdg_shell_view->request_fullscreen.notify = - handle_xdg_shell_surface_request_fullscreen; - wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, - &xdg_shell_view->request_fullscreen); } void diff --git a/xdg_shell.h b/xdg_shell.h index 601134b..cb92b5a 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -10,19 +10,7 @@ struct cg_xdg_shell_view { struct wl_listener destroy; struct wl_listener unmap; struct wl_listener map; - struct wl_listener commit; struct wl_listener request_fullscreen; - struct wl_listener new_popup; -}; - -struct cg_xdg_popup { - struct cg_view_child view_child; - struct wlr_xdg_popup *wlr_popup; - - struct wl_listener destroy; - struct wl_listener map; - struct wl_listener unmap; - struct wl_listener new_popup; }; struct cg_xdg_decoration { diff --git a/xwayland.c b/xwayland.c index daf3658..500a1ce 100644 --- a/xwayland.c +++ b/xwayland.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -72,29 +72,15 @@ close(struct cg_view *view) { static void maximize(struct cg_view *view, int width, int height) { struct cg_xwayland_view *xwayland_view = xwayland_view_from_view(view); - struct cg_output *output = view->workspace->output; - - struct wlr_box *box = wlr_output_layout_get_box( - view->server->output_layout, view->workspace->output->wlr_output); struct wlr_xwayland_surface_size_hints *hints = xwayland_view->xwayland_surface->size_hints; if(hints != NULL && hints->flags & PMaxSize) { if(width > hints->max_width) { - wlr_output_damage_add_box(output->damage, - &(struct wlr_box){.x = view->ox + box->x, - .y = view->oy + box->y, - .width = width, - .height = height}); width = hints->max_width; } if(height > hints->max_height) { - wlr_output_damage_add_box(output->damage, - &(struct wlr_box){.x = view->ox + box->x, - .y = view->oy + box->y, - .width = width, - .height = height}); height = hints->max_height; } } @@ -110,18 +96,6 @@ destroy(struct cg_view *view) { free(xwayland_view); } -static void -for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, - void *data) { - wlr_surface_for_each_surface(view->wlr_surface, iterator, data); -} - -static struct wlr_surface * -wlr_surface_at(const struct cg_view *view, double sx, double sy, double *sub_x, - double *sub_y) { - return wlr_surface_surface_at(view->wlr_surface, sx, sy, sub_x, sub_y); -} - static void handle_xwayland_surface_request_fullscreen(struct wl_listener *listener, void *data) { @@ -133,33 +107,12 @@ handle_xwayland_surface_request_fullscreen(struct wl_listener *listener, xwayland_surface->fullscreen); } -static void -handle_xwayland_surface_commit(struct wl_listener *listener, void *_data) { - struct cg_xwayland_view *xwayland_view = - wl_container_of(listener, xwayland_view, commit); - struct cg_view *view = &xwayland_view->view; - /* xwayland surface has moved */ - if(xwayland_view->xwayland_surface->x != view->ox || - xwayland_view->xwayland_surface->y != view->oy) { - output_damage_surface(view->workspace->output, view->wlr_surface, - view->ox, view->oy, true); - view->ox = xwayland_view->xwayland_surface->x; - view->oy = xwayland_view->xwayland_surface->y; - output_damage_surface(view->workspace->output, view->wlr_surface, - view->ox, view->oy, true); - } else { - view_damage_part(view); - } -} - static void handle_xwayland_surface_unmap(struct wl_listener *listener, void *_data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, unmap); struct cg_view *view = &xwayland_view->view; - wl_list_remove(&xwayland_view->commit.link); - view_unmap(view); } @@ -174,15 +127,9 @@ handle_xwayland_surface_map(struct wl_listener *listener, void *_data) { view->oy = xwayland_view->xwayland_surface->y; } - xwayland_view->commit.notify = handle_xwayland_surface_commit; - wl_signal_add(&xwayland_view->xwayland_surface->surface->events.commit, - &xwayland_view->commit); - view_map(view, xwayland_view->xwayland_surface->surface, view->server->curr_output ->workspaces[view->server->curr_output->curr_workspace]); - - view_damage_whole(view); } static void @@ -207,10 +154,6 @@ static const struct cg_view_impl xwayland_view_impl = { .close = close, .maximize = maximize, .destroy = destroy, - .for_each_surface = for_each_surface, - /* XWayland doesn't have a separate popup iterator. */ - .for_each_popup = NULL, - .wlr_surface_at = wlr_surface_at, }; void diff --git a/xwayland.h b/xwayland.h index 4dfaac4..71db92f 100644 --- a/xwayland.h +++ b/xwayland.h @@ -10,7 +10,6 @@ struct cg_xwayland_view { struct wl_listener destroy; struct wl_listener unmap; struct wl_listener map; - struct wl_listener commit; struct wl_listener request_fullscreen; };