diff --git a/meson.build b/meson.build index 8212ff6b0..ac6f18def 100644 --- a/meson.build +++ b/meson.build @@ -188,9 +188,18 @@ if get_option('notifications').enabled() endif # GTK (for icons and clipboard) +x11_extra_dep = [] if get_option('icons-and-clipboard').enabled() gtk_dep = dependency('gtk+-3.0', version: '>= 3.24.0', required: true) conf_data.set('HAVE_GTK', 1) + + x11_dep = dependency('x11', required: false) + if x11_dep.found() + if cc.has_function('XSetIOErrorExitHandler', dependencies: x11_dep) + conf_data.set('HAVE_XEXITHANDLER', 1) + x11_extra_dep = [x11_dep] + endif + endif endif # XScreenSaver @@ -330,6 +339,10 @@ if xscrnsaver_dep.length() > 0 profanity_deps += xscrnsaver_dep endif +if x11_extra_dep.length() > 0 + profanity_deps += x11_extra_dep +endif + if python_dep.found() profanity_deps += python_dep endif diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 870407361..4d7a821bf 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -6477,6 +6477,10 @@ gboolean cmd_tray(ProfWin* window, const char* const command, gchar** args) { #ifdef HAVE_GTK + if (!tray_gtk_ready()) { + log_warning("GTK is not ready. Tray functionality is disabled."); + return TRUE; + } if (g_strcmp0(args[0], "timer") == 0) { if (args[1] == NULL) { cons_bad_cmd_usage(command); @@ -8975,6 +8979,10 @@ gboolean cmd_paste(ProfWin* window, const char* const command, gchar** args) { #ifdef HAVE_GTK + if (!tray_gtk_ready()) { + log_warning("GTK is not ready. Paste from clipboard is disabled."); + return TRUE; + } auto_char char* clipboard_buffer = clipboard_get(); if (clipboard_buffer) { diff --git a/src/tools/clipboard.c b/src/tools/clipboard.c index 1df4a9a1f..acaca4069 100644 --- a/src/tools/clipboard.c +++ b/src/tools/clipboard.c @@ -15,6 +15,7 @@ #include #include "log.h" +#include "ui/tray.h" /* For now we rely on tray_init(void) @@ -27,6 +28,9 @@ void clipboard_init(int argc, char **argv) { char* clipboard_get(void) { + if (!tray_gtk_ready()) { + return NULL; + } gchar* clip; GtkClipboard* cl = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); diff --git a/src/ui/notifier.c b/src/ui/notifier.c index 8ba934cca..9b4c676f6 100644 --- a/src/ui/notifier.c +++ b/src/ui/notifier.c @@ -26,6 +26,9 @@ #include "config/preferences.h" #include "ui/ui.h" #include "ui/window_list.h" +#ifdef HAVE_GTK +#include "ui/tray.h" +#endif #include "xmpp/xmpp.h" #include "xmpp/muc.h" @@ -54,6 +57,11 @@ _notifier_uninit(void) static void _notify(const char* const message, int timeout, const char* const category) { +#ifdef HAVE_GTK + if (!tray_gtk_ready()) { + return; + } +#endif log_debug("Attempting notification: %s", message); if (notify_is_initted()) { log_debug("Reinitialising libnotify"); diff --git a/src/ui/tray.c b/src/ui/tray.c index 7e367a677..b1a97b7e9 100644 --- a/src/ui/tray.c +++ b/src/ui/tray.c @@ -21,6 +21,11 @@ #include "ui/tray.h" #include "ui/window_list.h" +#if defined(GDK_WINDOWING_X11) && defined(HAVE_XEXITHANDLER) +#include +#include +#endif + static gboolean gtk_ready = FALSE; static GtkStatusIcon* prof_tray = NULL; static GString* icon_filename = NULL; @@ -29,6 +34,21 @@ static gint unread_messages; static gboolean shutting_down; static guint timer; +#if defined(GDK_WINDOWING_X11) && defined(HAVE_XEXITHANDLER) +static void +_x_io_error_handler(Display* display, void* user_data) +{ + log_warning("Error: X Server connection lost."); + gtk_ready = FALSE; +} + +static int +_x_io_handler(Display* display) +{ + return 0; +} +#endif + /* * Get icons from installation share folder or (if defined) .locale user's folder * @@ -98,7 +118,7 @@ _get_icons(void) gboolean _tray_change_icon(gpointer data) { - if (shutting_down) { + if (shutting_down || !gtk_ready) { return FALSE; } @@ -151,6 +171,14 @@ tray_init(void) return; } +#if defined(GDK_WINDOWING_X11) && defined(HAVE_XEXITHANDLER) + GdkDisplay* display = gdk_display_get_default(); + if (GDK_IS_X11_DISPLAY(display)) { + XSetIOErrorExitHandler(GDK_DISPLAY_XDISPLAY(display), _x_io_error_handler, NULL); + XSetIOErrorHandler(_x_io_handler); + } +#endif + if (prefs_get_boolean(PREF_TRAY)) { log_debug("Building GTK icon"); tray_enable(); @@ -167,9 +195,18 @@ tray_update(void) } } +gboolean +tray_gtk_ready(void) +{ + return gtk_ready; +} + void tray_set_timer(int interval) { + if (!gtk_ready) { + return; + } if (timer) { g_source_remove(timer); } @@ -186,6 +223,9 @@ tray_set_timer(int interval) void tray_enable(void) { + if (!gtk_ready) { + return; + } prof_tray = gtk_status_icon_new_from_file(icon_filename->str); shutting_down = FALSE; _tray_change_icon(NULL); diff --git a/src/ui/tray.h b/src/ui/tray.h index 8c9419b42..0e047a175 100644 --- a/src/ui/tray.h +++ b/src/ui/tray.h @@ -11,8 +11,10 @@ #define UI_TRAY_H #ifdef HAVE_GTK +#include void tray_init(void); void tray_update(void); +gboolean tray_gtk_ready(void); void tray_enable(void); void tray_disable(void);