Merge pull request #834 from fwSmit/fallback-x11

Wayland: fallback to X11 output when initialization fails
This commit is contained in:
Nikos Tsipinakis 2021-02-27 14:53:55 +02:00 committed by GitHub
commit 54b665898f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 47 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);
} }
@ -24,7 +24,6 @@ const struct output output_x11 = {
x_win_hide, x_win_hide,
x_display_surface, x_display_surface,
x_win_visible,
x_win_get_context, x_win_get_context,
get_active_screen, get_active_screen,
@ -45,7 +44,6 @@ const struct output output_wl = {
wl_win_hide, wl_win_hide,
wl_display_surface, wl_display_surface,
wl_win_visible,
wl_win_get_context, wl_win_get_context,
wl_get_active_screen, wl_get_active_screen,
@ -55,18 +53,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);
@ -38,7 +38,6 @@ struct output {
void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*); void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*);
bool (*win_visible)(window);
cairo_t* (*win_get_context)(window); cairo_t* (*win_get_context)(window);
const struct screen_info* (*get_active_screen)(void); const struct screen_info* (*get_active_screen)(void);
@ -47,9 +46,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));
@ -605,6 +616,8 @@ void wl_win_destroy(window winptr) {
} }
void wl_win_show(window win) { 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) { void wl_win_hide(window win) {
@ -631,10 +644,6 @@ void wl_display_surface(cairo_surface_t *srf, window winptr, const struct dimens
wl_display_roundtrip(ctx.display); wl_display_roundtrip(ctx.display);
} }
bool wl_win_visible(window win) {
return true;
}
cairo_t* wl_win_get_context(window winptr) { cairo_t* wl_win_get_context(window winptr) {
struct window_wl *win = (struct window_wl*)winptr; struct window_wl *win = (struct window_wl*)winptr;
ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, 500, 500); ctx.current_buffer = get_next_buffer(ctx.shm, ctx.buffers, 500, 500);

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);
@ -17,7 +17,6 @@ void wl_win_show(window);
void wl_win_hide(window); void wl_win_hide(window);
void wl_display_surface(cairo_surface_t *srf, window win, const struct dimensions*); 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); cairo_t* wl_win_get_context(window);
const struct screen_info* wl_get_active_screen(void); const struct screen_info* wl_get_active_screen(void);

View File

@ -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) cairo_t* x_win_get_context(window winptr)
{ {
return ((struct window_x11*)win)->c_ctx; return ((struct window_x11*)win)->c_ctx;
@ -501,14 +496,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 +529,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

@ -42,12 +42,11 @@ void x_win_hide(window);
void x_display_surface(cairo_surface_t *srf, window, const struct dimensions *dim); 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); 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);