From a8b2058fcf7bcbbdb244f46e242b13e9777a2634 Mon Sep 17 00:00:00 2001
From: fwsmit <fw.smit01@gmail.com>
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 09c11dfc..3ee0668a 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 238e32d3..afedcc7e 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 6ebb4363..783b0d35 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 9b3f412a..e7e554db 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);
+
+ 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);
- org_kde_kwin_idle_destroy(ctx.idle_handler);
- org_kde_kwin_idle_timeout_release(ctx.idle_timeout);
+ 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 de184ead..915dd010 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 31c88d77..0a552f14 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 f43a752e..123d06b4 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 <fw.smit01@gmail.com>
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 afedcc7e..06f1af50 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 783b0d35..a6cf5e7a 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 e7e554db..3598f949 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 915dd010..fe54e12d 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 0a552f14..8cdc0ab7 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 123d06b4..28fb32cc 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 */