From a8b2058fcf7bcbbdb244f46e242b13e9777a2634 Mon Sep 17 00:00:00 2001 From: fwsmit Date: Mon, 22 Feb 2021 21:20:39 +0100 Subject: [PATCH 1/2] Wayland: fallback to X11 output when initialization fails --- src/draw.c | 1 - src/output.c | 30 ++++++++++++++++++++++---- src/output.h | 9 ++++++-- src/wayland/wl.c | 55 +++++++++++++++++++++++++++++------------------- src/wayland/wl.h | 2 +- src/x11/x.c | 7 ++++-- src/x11/x.h | 2 +- 7 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/draw.c b/src/draw.c index 09c11df..3ee0668 100644 --- a/src/draw.c +++ b/src/draw.c @@ -51,7 +51,6 @@ void draw_setup(void) const struct output *out = output_create(settings.force_xwayland); output = out; - out->init(); win = out->win_create(); pango_fdesc = pango_font_description_from_string(settings.font); diff --git a/src/output.c b/src/output.c index 238e32d..afedcc7 100644 --- a/src/output.c +++ b/src/output.c @@ -8,7 +8,7 @@ #include "wayland/wl.h" #endif -const bool is_running_wayland(void) { +bool is_running_wayland(void) { char* wayland_display = getenv("WAYLAND_DISPLAY"); return !(wayland_display == NULL); } @@ -55,18 +55,40 @@ const struct output output_wl = { }; #endif +const struct output* get_x11_output() { + const struct output* output = &output_x11; + if (output->init()) { + return output; + } else { + LOG_E("Couldn't initialize X11 output. Aborting..."); + } +} + +#ifdef ENABLE_WAYLAND +const struct output* get_wl_output() { + const struct output* output = &output_wl; + if (output->init()) { + return output; + } else { + LOG_W("Couldn't initialize wayland output. Falling back to X11 output."); + output->deinit(); + return get_x11_output(); + } +} +#endif + const struct output* output_create(bool force_xwayland) { #ifdef ENABLE_WAYLAND if (!force_xwayland && is_running_wayland()) { LOG_I("Using Wayland output"); - return &output_wl; + return get_wl_output(); } else { LOG_I("Using X11 output"); - return &output_x11; + return get_x11_output(); } #else - return &output_x11; + return get_x11_output(); #endif } /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/output.h b/src/output.h index 6ebb436..783b0d3 100644 --- a/src/output.h +++ b/src/output.h @@ -27,7 +27,7 @@ struct screen_info { }; struct output { - void (*init)(void); + bool (*init)(void); void (*deinit)(void); window (*win_create)(void); @@ -47,9 +47,14 @@ struct output { bool (*have_fullscreen_window)(void); }; +/** + * return an initialized output, selecting the correct output type from either + * wayland or X11 according to the settings and environment. + * When the wayland output fails to initilize, it falls back to X11 output. + */ const struct output* output_create(bool force_xwayland); -const bool is_running_wayland(void); +bool is_running_wayland(void); #endif /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/wayland/wl.c b/src/wayland/wl.c index 9b3f412..e7e554d 100644 --- a/src/wayland/wl.c +++ b/src/wayland/wl.c @@ -320,14 +320,14 @@ static const struct wl_registry_listener registry_listener = { .global_remove = handle_global_remove, }; -bool init_wayland() { +bool wl_init() { wl_list_init(&ctx.outputs); - //wl_list_init(&ctx.seats); + //wl_list_init(&ctx.seats); // TODO multi-seat support ctx.display = wl_display_connect(NULL); if (ctx.display == NULL) { - LOG_E("failed to create display"); + LOG_W("failed to create display"); return false; } @@ -336,15 +336,15 @@ bool init_wayland() { wl_display_roundtrip(ctx.display); if (ctx.compositor == NULL) { - LOG_E("compositor doesn't support wl_compositor"); + LOG_W("compositor doesn't support wl_compositor"); return false; } if (ctx.shm == NULL) { - LOG_E("compositor doesn't support wl_shm"); + LOG_W("compositor doesn't support wl_shm"); return false; } if (ctx.layer_shell == NULL) { - LOG_E("compositor doesn't support zwlr_layer_shell_v1"); + LOG_W("compositor doesn't support zwlr_layer_shell_v1"); return false; } if (ctx.seat == NULL) { @@ -362,7 +362,10 @@ bool init_wayland() { return true; } -void finish_wayland() { +void wl_deinit() { + // We need to check if any of these are NULL, since the initialization + // could have been aborted half way through, or the compositor doesn't + // support some of these features. if (ctx.layer_surface != NULL) { zwlr_layer_surface_v1_destroy(ctx.layer_surface); } @@ -372,25 +375,40 @@ void finish_wayland() { finish_buffer(&ctx.buffers[0]); finish_buffer(&ctx.buffers[1]); + // The output list is initialized at the start of init, so no need to + // check for NULL struct dunst_output *output, *output_tmp; wl_list_for_each_safe(output, output_tmp, &ctx.outputs, link) { destroy_output(output); } if (ctx.seat) { - wl_pointer_release(ctx.pointer.wl_pointer); + if (ctx.pointer.wl_pointer) + wl_pointer_release(ctx.pointer.wl_pointer); wl_seat_release(ctx.seat); ctx.seat = NULL; } - zwlr_layer_shell_v1_destroy(ctx.layer_shell); - wl_compositor_destroy(ctx.compositor); - wl_shm_destroy(ctx.shm); - wl_registry_destroy(ctx.registry); - wl_display_disconnect(ctx.display); + if (ctx.idle_handler) + org_kde_kwin_idle_destroy(ctx.idle_handler); - org_kde_kwin_idle_destroy(ctx.idle_handler); - org_kde_kwin_idle_timeout_release(ctx.idle_timeout); + if (ctx.idle_timeout) + org_kde_kwin_idle_timeout_release(ctx.idle_timeout); + + if (ctx.layer_shell) + zwlr_layer_shell_v1_destroy(ctx.layer_shell); + + if (ctx.compositor) + wl_compositor_destroy(ctx.compositor); + + if (ctx.shm) + wl_shm_destroy(ctx.shm); + + if (ctx.registry) + wl_registry_destroy(ctx.registry); + + if (ctx.display) + wl_display_disconnect(ctx.display); } static struct dunst_output *get_configured_output() { @@ -582,13 +600,6 @@ void set_dirty() { schedule_frame_and_commit(); } -void wl_init(void) { - init_wayland(); -} - -void wl_deinit(void) { -} - window wl_win_create(void) { struct window_wl *win = g_malloc0(sizeof(struct window_wl)); diff --git a/src/wayland/wl.h b/src/wayland/wl.h index de184ea..915dd01 100644 --- a/src/wayland/wl.h +++ b/src/wayland/wl.h @@ -7,7 +7,7 @@ #include "../output.h" -void wl_init(void); +bool wl_init(void); void wl_deinit(void); window wl_win_create(void); diff --git a/src/x11/x.c b/src/x11/x.c index 31c88d7..0a552f1 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -501,14 +501,16 @@ static void XRM_update_db(void) /* * Setup X11 stuff */ -void x_setup(void) +bool x_setup(void) { /* initialize xctx.dc, font, keyboard, colors */ if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) LOG_W("No locale support"); + if (!(xctx.dpy = XOpenDisplay(NULL))) { - DIE("Cannot open X11 display."); + LOG_W("Cannot open X11 display."); + return false; } x_shortcut_init(&settings.close_ks); @@ -532,6 +534,7 @@ void x_setup(void) init_screens(); x_shortcut_grab(&settings.history_ks); + return true; } struct geometry x_parse_geometry(const char *geom_str) diff --git a/src/x11/x.h b/src/x11/x.h index f43a752..123d06b 100644 --- a/src/x11/x.h +++ b/src/x11/x.h @@ -47,7 +47,7 @@ cairo_t* x_win_get_context(window); /* X misc */ bool x_is_idle(void); -void x_setup(void); +bool x_setup(void); void x_free(void); struct geometry x_parse_geometry(const char *geom_str); From f8a2ff48b3f3fe027863c0d40175504df10cf76a Mon Sep 17 00:00:00 2001 From: fwsmit Date: Wed, 24 Feb 2021 12:52:43 +0100 Subject: [PATCH 2/2] output: remove unused win_visible function This was used nowhere, and not even implemented for the wayland output. --- src/output.c | 2 -- src/output.h | 1 - src/wayland/wl.c | 6 ++---- src/wayland/wl.h | 1 - src/x11/x.c | 5 ----- src/x11/x.h | 1 - 6 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/output.c b/src/output.c index afedcc7..06f1af5 100644 --- a/src/output.c +++ b/src/output.c @@ -24,7 +24,6 @@ const struct output output_x11 = { x_win_hide, x_display_surface, - x_win_visible, x_win_get_context, get_active_screen, @@ -45,7 +44,6 @@ const struct output output_wl = { wl_win_hide, wl_display_surface, - wl_win_visible, wl_win_get_context, wl_get_active_screen, diff --git a/src/output.h b/src/output.h index 783b0d3..a6cf5e7 100644 --- a/src/output.h +++ b/src/output.h @@ -38,7 +38,6 @@ struct output { void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*); - bool (*win_visible)(window); cairo_t* (*win_get_context)(window); const struct screen_info* (*get_active_screen)(void); diff --git a/src/wayland/wl.c b/src/wayland/wl.c index e7e554d..3598f94 100644 --- a/src/wayland/wl.c +++ b/src/wayland/wl.c @@ -616,6 +616,8 @@ void wl_win_destroy(window winptr) { } void wl_win_show(window win) { + // This is here for compatibilty with the X11 output. The window is + // already shown in wl_display_surface. } void wl_win_hide(window win) { @@ -642,10 +644,6 @@ void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimens wl_display_roundtrip(ctx.display); } -bool wl_win_visible(window win) { - return true; -} - cairo_t* wl_win_get_context(window winptr) { struct window_wl *win = (struct window_wl*)winptr; ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, 500, 500); diff --git a/src/wayland/wl.h b/src/wayland/wl.h index 915dd01..fe54e12 100644 --- a/src/wayland/wl.h +++ b/src/wayland/wl.h @@ -17,7 +17,6 @@ void wl_win_show(window); void wl_win_hide(window); void wl_display_surface(cairo_surface_t *srf, window win, const struct dimensions*); -bool wl_win_visible(window); cairo_t* wl_win_get_context(window); const struct screen_info* wl_get_active_screen(void); diff --git a/src/x11/x.c b/src/x11/x.c index 0a552f1..8cdc0ab 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -179,11 +179,6 @@ void x_display_surface(cairo_surface_t *srf, window winptr, const struct dimensi } -bool x_win_visible(window winptr) -{ - return ((struct window_x11*)winptr)->visible; -} - cairo_t* x_win_get_context(window winptr) { return ((struct window_x11*)win)->c_ctx; diff --git a/src/x11/x.h b/src/x11/x.h index 123d06b..28fb32c 100644 --- a/src/x11/x.h +++ b/src/x11/x.h @@ -42,7 +42,6 @@ void x_win_hide(window); void x_display_surface(cairo_surface_t *srf, window, const struct dimensions *dim); -bool x_win_visible(window); cairo_t* x_win_get_context(window); /* X misc */