fix: handle X11 connection loss gracefully
Use XSetIOErrorExitHandler on X11 to detect connection loss and disable GTK features (tray, clipboard, notifications). Signed-off-by: Michael Vetter <jubalh@iodoru.org> Signed-off-by: Paul Fertser <fercerpav@gmail.com> Co-authored-by: Paul Fertser <fercerpav@gmail.com>
This commit is contained in:
13
meson.build
13
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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
#include "ui/tray.h"
|
||||
#include "ui/window_list.h"
|
||||
|
||||
#if defined(GDK_WINDOWING_X11) && defined(HAVE_XEXITHANDLER)
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/Xlib.h>
|
||||
#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);
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
#define UI_TRAY_H
|
||||
|
||||
#ifdef HAVE_GTK
|
||||
#include <glib.h>
|
||||
void tray_init(void);
|
||||
void tray_update(void);
|
||||
gboolean tray_gtk_ready(void);
|
||||
|
||||
void tray_enable(void);
|
||||
void tray_disable(void);
|
||||
|
||||
Reference in New Issue
Block a user