Blob Blame History Raw
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 */