Wayland: fallback to X11 output when initialization fails

This commit is contained in:
fwsmit 2021-02-22 21:20:39 +01:00
parent ceca7cfcc7
commit a8b2058fcf
7 changed files with 73 additions and 33 deletions

View File

@ -51,7 +51,6 @@ void draw_setup(void)
const struct output *out = output_create(settings.force_xwayland); const struct output *out = output_create(settings.force_xwayland);
output = out; output = out;
out->init();
win = out->win_create(); win = out->win_create();
pango_fdesc = pango_font_description_from_string(settings.font); pango_fdesc = pango_font_description_from_string(settings.font);

View File

@ -8,7 +8,7 @@
#include "wayland/wl.h" #include "wayland/wl.h"
#endif #endif
const bool is_running_wayland(void) { bool is_running_wayland(void) {
char* wayland_display = getenv("WAYLAND_DISPLAY"); char* wayland_display = getenv("WAYLAND_DISPLAY");
return !(wayland_display == NULL); return !(wayland_display == NULL);
} }
@ -55,18 +55,40 @@ const struct output output_wl = {
}; };
#endif #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) const struct output* output_create(bool force_xwayland)
{ {
#ifdef ENABLE_WAYLAND #ifdef ENABLE_WAYLAND
if (!force_xwayland && is_running_wayland()) { if (!force_xwayland && is_running_wayland()) {
LOG_I("Using Wayland output"); LOG_I("Using Wayland output");
return &output_wl; return get_wl_output();
} else { } else {
LOG_I("Using X11 output"); LOG_I("Using X11 output");
return &output_x11; return get_x11_output();
} }
#else #else
return &output_x11; return get_x11_output();
#endif #endif
} }
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -27,7 +27,7 @@ struct screen_info {
}; };
struct output { struct output {
void (*init)(void); bool (*init)(void);
void (*deinit)(void); void (*deinit)(void);
window (*win_create)(void); window (*win_create)(void);
@ -47,9 +47,14 @@ struct output {
bool (*have_fullscreen_window)(void); 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 struct output* output_create(bool force_xwayland);
const bool is_running_wayland(void); bool is_running_wayland(void);
#endif #endif
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -320,14 +320,14 @@ static const struct wl_registry_listener registry_listener = {
.global_remove = handle_global_remove, .global_remove = handle_global_remove,
}; };
bool init_wayland() { bool wl_init() {
wl_list_init(&ctx.outputs); 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); ctx.display = wl_display_connect(NULL);
if (ctx.display == NULL) { if (ctx.display == NULL) {
LOG_E("failed to create display"); LOG_W("failed to create display");
return false; return false;
} }
@ -336,15 +336,15 @@ bool init_wayland() {
wl_display_roundtrip(ctx.display); wl_display_roundtrip(ctx.display);
if (ctx.compositor == NULL) { if (ctx.compositor == NULL) {
LOG_E("compositor doesn't support wl_compositor"); LOG_W("compositor doesn't support wl_compositor");
return false; return false;
} }
if (ctx.shm == NULL) { if (ctx.shm == NULL) {
LOG_E("compositor doesn't support wl_shm"); LOG_W("compositor doesn't support wl_shm");
return false; return false;
} }
if (ctx.layer_shell == NULL) { 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; return false;
} }
if (ctx.seat == NULL) { if (ctx.seat == NULL) {
@ -362,7 +362,10 @@ bool init_wayland() {
return true; 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) { if (ctx.layer_surface != NULL) {
zwlr_layer_surface_v1_destroy(ctx.layer_surface); zwlr_layer_surface_v1_destroy(ctx.layer_surface);
} }
@ -372,25 +375,40 @@ void finish_wayland() {
finish_buffer(&ctx.buffers[0]); finish_buffer(&ctx.buffers[0]);
finish_buffer(&ctx.buffers[1]); 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; struct dunst_output *output, *output_tmp;
wl_list_for_each_safe(output, output_tmp, &ctx.outputs, link) { wl_list_for_each_safe(output, output_tmp, &ctx.outputs, link) {
destroy_output(output); destroy_output(output);
} }
if (ctx.seat) { if (ctx.seat) {
if (ctx.pointer.wl_pointer)
wl_pointer_release(ctx.pointer.wl_pointer); wl_pointer_release(ctx.pointer.wl_pointer);
wl_seat_release(ctx.seat); wl_seat_release(ctx.seat);
ctx.seat = NULL; ctx.seat = NULL;
} }
zwlr_layer_shell_v1_destroy(ctx.layer_shell); if (ctx.idle_handler)
wl_compositor_destroy(ctx.compositor);
wl_shm_destroy(ctx.shm);
wl_registry_destroy(ctx.registry);
wl_display_disconnect(ctx.display);
org_kde_kwin_idle_destroy(ctx.idle_handler); org_kde_kwin_idle_destroy(ctx.idle_handler);
if (ctx.idle_timeout)
org_kde_kwin_idle_timeout_release(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() { static struct dunst_output *get_configured_output() {
@ -582,13 +600,6 @@ void set_dirty() {
schedule_frame_and_commit(); schedule_frame_and_commit();
} }
void wl_init(void) {
init_wayland();
}
void wl_deinit(void) {
}
window wl_win_create(void) { window wl_win_create(void) {
struct window_wl *win = g_malloc0(sizeof(struct window_wl)); struct window_wl *win = g_malloc0(sizeof(struct window_wl));

View File

@ -7,7 +7,7 @@
#include "../output.h" #include "../output.h"
void wl_init(void); bool wl_init(void);
void wl_deinit(void); void wl_deinit(void);
window wl_win_create(void); window wl_win_create(void);

View File

@ -501,14 +501,16 @@ static void XRM_update_db(void)
/* /*
* Setup X11 stuff * Setup X11 stuff
*/ */
void x_setup(void) bool x_setup(void)
{ {
/* initialize xctx.dc, font, keyboard, colors */ /* initialize xctx.dc, font, keyboard, colors */
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
LOG_W("No locale support"); LOG_W("No locale support");
if (!(xctx.dpy = XOpenDisplay(NULL))) { if (!(xctx.dpy = XOpenDisplay(NULL))) {
DIE("Cannot open X11 display."); LOG_W("Cannot open X11 display.");
return false;
} }
x_shortcut_init(&settings.close_ks); x_shortcut_init(&settings.close_ks);
@ -532,6 +534,7 @@ void x_setup(void)
init_screens(); init_screens();
x_shortcut_grab(&settings.history_ks); x_shortcut_grab(&settings.history_ks);
return true;
} }
struct geometry x_parse_geometry(const char *geom_str) struct geometry x_parse_geometry(const char *geom_str)

View File

@ -47,7 +47,7 @@ cairo_t* x_win_get_context(window);
/* X misc */ /* X misc */
bool x_is_idle(void); bool x_is_idle(void);
void x_setup(void); bool x_setup(void);
void x_free(void); void x_free(void);
struct geometry x_parse_geometry(const char *geom_str); struct geometry x_parse_geometry(const char *geom_str);