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);