From 763f5c34556124a7035795bcef5cdd552d8f4da7 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Tue, 29 Sep 2020 19:53:46 +0100 Subject: [PATCH] output: add output_init() and refactor --- include/labwc.h | 5 ++- src/output.c | 97 ++++++++++++++++++++++++++++--------------------- src/server.c | 46 ++++++----------------- 3 files changed, 69 insertions(+), 79 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index b801e246..dedae5c4 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -45,6 +45,7 @@ enum cursor_mode { struct server { struct wl_display *wl_display; struct wlr_renderer *renderer; + struct wlr_backend *backend; struct wlr_xdg_shell *xdg_shell; struct wl_listener new_xdg_surface; @@ -88,6 +89,7 @@ struct output { struct server *server; struct wlr_output *wlr_output; struct wl_listener frame; + struct wl_listener destroy; }; enum view_type { LAB_XDG_SHELL_VIEW, LAB_XWAYLAND_VIEW }; @@ -232,8 +234,7 @@ void cursor_new(struct server *server, struct wlr_input_device *device); void keyboard_new(struct server *server, struct wlr_input_device *device); -void output_frame(struct wl_listener *listener, void *data); -void output_new(struct wl_listener *listener, void *data); +void output_init(struct server *server); struct border deco_thickness(struct view *view); struct wlr_box deco_max_extents(struct view *view); diff --git a/src/output.c b/src/output.c index a2c1df95..7058b01c 100644 --- a/src/output.c +++ b/src/output.c @@ -1,3 +1,4 @@ +#include #include "labwc.h" #include "theme/theme.h" @@ -231,11 +232,13 @@ render_surface(struct wlr_surface *surface, int sx, int sy, void *data) wlr_surface_send_frame_done(surface, rdata->when); } -void -output_frame(struct wl_listener *listener, void *data) +static void +output_frame_notify(struct wl_listener *listener, void *data) { - /* This function is called every time an output is ready to display a - * frame, generally at the output's refresh rate (e.g. 60Hz). */ + /* + * This function is called every time an output is ready to display a + * frame, generally at the output's refresh rate (e.g. 60Hz). + */ struct output *output = wl_container_of(listener, output, frame); struct wlr_renderer *renderer = output->server->renderer; @@ -246,19 +249,17 @@ output_frame(struct wl_listener *listener, void *data) if (!wlr_output_attach_render(output->wlr_output, NULL)) { return; } + /* The "effective" resolution can change if you rotate your outputs. */ int width, height; wlr_output_effective_resolution(output->wlr_output, &width, &height); - /* Begin the renderer (calls glViewport and some other GL sanity checks) - */ + + /* Calls glViewport and some other GL sanity checks */ wlr_renderer_begin(renderer, width, height); float color[4] = { 0.3, 0.3, 0.3, 1.0 }; wlr_renderer_clear(renderer, color); - /* Each subsequent window we render is rendered on top of the last. - * Because our view list is ordered front-to-back, we iterate over it - * backwards. */ struct view *view; wl_list_for_each_reverse (view, &output->server->views, link) { if (!view->mapped) @@ -305,23 +306,23 @@ output_frame(struct wl_listener *listener, void *data) render_surface(s, 0, 0, &rdata); } - /* Hardware cursors are rendered by the GPU on a separate plane, and can - * be moved around without re-rendering what's beneath them - which is - * more efficient. However, not all hardware supports hardware cursors. - * For this reason, wlroots provides a software fallback, which we ask - * it to render here. wlr_cursor handles configuring hardware vs - * software cursors for you, - * and this function is a no-op when hardware cursors are in use. */ + /* Just in case hardware cursors not supported by GPU */ wlr_output_render_software_cursors(output->wlr_output, NULL); - /* Conclude rendering and swap the buffers, showing the final frame - * on-screen. */ wlr_renderer_end(renderer); wlr_output_commit(output->wlr_output); } -void -output_new(struct wl_listener *listener, void *data) +static void +output_destroy_notify(struct wl_listener *listener, void *data) +{ + struct output *output = wl_container_of(listener, output, destroy); + wl_list_remove(&output->link); +} + + +static void +new_output_notify(struct wl_listener *listener, void *data) { /* This event is rasied by the backend when a new output (aka a display * or monitor) becomes available. */ @@ -329,39 +330,51 @@ output_new(struct wl_listener *listener, void *data) struct wlr_output *wlr_output = data; /* - * Some backends don't have modes. DRM+KMS does, and we need to set a - * mode before we can use the output. The mode is a tuple of (width, - * height, refresh rate), and each monitor supports only a specific set - * of modes. We just pick the monitor's preferred mode. + * The mode is a tuple of (width, height, refresh rate). * TODO: support user configuration */ - if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = - wlr_output_preferred_mode(wlr_output); + struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); + if (mode) { wlr_output_set_mode(wlr_output, mode); - wlr_output_enable(wlr_output, true); - if (!wlr_output_commit(wlr_output)) { - return; - } + wlr_output_commit(wlr_output); } - /* Allocates and configures our state for this output */ struct output *output = calloc(1, sizeof(struct output)); output->wlr_output = wlr_output; output->server = server; - /* Sets up a listener for the frame notify event. */ - output->frame.notify = output_frame; + output->frame.notify = output_frame_notify; wl_signal_add(&wlr_output->events.frame, &output->frame); wl_list_insert(&server->outputs, &output->link); + output->destroy.notify = output_destroy_notify; + wl_signal_add(&wlr_output->events.destroy, &output->destroy); - /* Adds this to the output layout. The add_auto function arranges - * outputs from left-to-right in the order they appear. A more - * sophisticated compositor would let the user configure the arrangement - * of outputs in the layout. - * - * The output layout utility automatically adds a wl_output global to - * the display, which Wayland clients can see to find out information - * about the output (such as DPI, scale factor, manufacturer, etc). + /* + * Arrange outputs from left-to-right in the order they appear. + * TODO: support configuration in run-time */ wlr_output_layout_add_auto(server->output_layout, wlr_output); + wlr_output_schedule_frame(wlr_output); +} + +void +output_init(struct server *server) +{ + server->new_output.notify = new_output_notify; + wl_signal_add(&server->backend->events.new_output, &server->new_output); + + /* + * Create an output layout, which is a wlroots utility for working with + * an arrangement of screens in a physical layout. + */ + server->output_layout = wlr_output_layout_create(); + if (!server->output_layout) { + wlr_log(WLR_ERROR, "unable to create output layout"); + exit(EXIT_FAILURE); + } + + /* Enable screen recording with wf-recorder */ + wlr_xdg_output_manager_v1_create(server->wl_display, + server->output_layout); + + wl_list_init(&server->outputs); } diff --git a/src/server.c b/src/server.c index 3164ded8..d3d696c2 100644 --- a/src/server.c +++ b/src/server.c @@ -9,9 +9,7 @@ #include #include #include -#include -static struct wlr_backend *backend; static struct wlr_compositor *compositor; static struct wl_event_source *sighup_source; @@ -117,18 +115,14 @@ server_init(struct server *server) event_loop, SIGHUP, handle_signal, &server->wl_display); /* - * The backend is a wlroots feature which abstracts the underlying - * input and output hardware. the autocreate option will choose the - * most suitable backend based on the current environment, such as - * opening an x11 window if an x11 server is running. the null - * argument here optionally allows you to pass in a custom renderer if - * wlr_renderer doesn't meet your needs. the backend uses the - * renderer, for example, to fall back to software cursors if the - * backend does not support hardware cursors (some older gpus don't). + * The backend is a feature which abstracts the underlying input and + * output hardware. The autocreate option will choose the most suitable + * backend based on the current environment, such as opening an x11 + * window if an x11 server is running. */ - backend = wlr_backend_autocreate(server->wl_display, NULL); - if (!backend) { - wlr_log(WLR_ERROR, "unable to create the wlroots backend"); + server->backend = wlr_backend_autocreate(server->wl_display, NULL); + if (!server->backend) { + wlr_log(WLR_ERROR, "unable to create backend"); exit(EXIT_FAILURE); } @@ -138,22 +132,11 @@ server_init(struct server *server) * formats it supports for shared memory, this configures that for * clients. */ - server->renderer = wlr_backend_get_renderer(backend); + server->renderer = wlr_backend_get_renderer(server->backend); wlr_renderer_init_wl_display(server->renderer, server->wl_display); wl_list_init(&server->views); wl_list_init(&server->unmanaged_surfaces); - wl_list_init(&server->outputs); - - /* - * Create an output layout, which a wlroots utility for working with - * an arrangement of screens in a physical layout. - */ - server->output_layout = wlr_output_layout_create(); - if (!server->output_layout) { - wlr_log(WLR_ERROR, "unable to create output layout"); - exit(EXIT_FAILURE); - } /* * Create some hands-off wlroots interfaces. The compositor is @@ -176,12 +159,7 @@ server_init(struct server *server) exit(EXIT_FAILURE); } - /* - * Configure a listener to be notified when new outputs are available - * on the backend. - */ - server->new_output.notify = output_new; - wl_signal_add(&backend->events.new_output, &server->new_output); + output_init(server); /* * Configures a seat, which is a single "seat" at which a user sits @@ -218,7 +196,7 @@ server_init(struct server *server) wl_list_init(&server->keyboards); server->new_input.notify = server_new_input; - wl_signal_add(&backend->events.new_input, &server->new_input); + wl_signal_add(&server->backend->events.new_input, &server->new_input); server->request_cursor.notify = seat_request_cursor; wl_signal_add(&server->seat->events.request_set_cursor, &server->request_cursor); @@ -263,8 +241,6 @@ server_init(struct server *server) wlr_data_control_manager_v1_create(server->wl_display); wlr_gamma_control_manager_v1_create(server->wl_display); wlr_primary_selection_v1_device_manager_create(server->wl_display); - wlr_xdg_output_manager_v1_create(server->wl_display, - server->output_layout); /* Init xwayland */ server->xwayland = @@ -320,7 +296,7 @@ server_start(struct server *server) * Start the backend. This will enumerate outputs and inputs, become * the DRM master, etc */ - if (!wlr_backend_start(backend)) { + if (!wlr_backend_start(server->backend)) { wlr_log(WLR_ERROR, "unable to start the wlroots backend"); exit(EXIT_FAILURE); }