From 09095a7d9261676871a881aff7df4b39bd2802b4 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 15 Jul 2023 21:05:41 +0100 Subject: [PATCH] Avoid treating non-X GDK display names as X ones When running on Wayland, gdk_display_get_name() can return things like "wayland-0" rather than valid X display names. PuTTY nonetheless treated them as X display names, meaning that when running under Wayland, pterm would set DISPLAY to "wayland-0" in subprocesses, and PuTTY's X forwarding wouldn't work properly. To fix this, places that call gdk_display_get_name() now only do so on displays for which GDK_IS_X_DISPLAY() is true. As with GDK_IS_X_WINDOW(), this requires some backward-compatibility for GDK versions where everything is implicitly running on X. To make this work usefully, pterm now also won't unset DISPLAY if it can't get an X display name and instead will pass through whatever value of DISPLAY it received. I think that's better behaviour anyway. There are two separate parts of PuTTY that call gdk_display_get_name(). platform_get_x_display() in unix/putty.c is used for X forwarding, while gtk_seat_get_x_display() in unix/window.c is used used for setting DISPLAY and recording in utmp. I've updated both of them. --- unix/gtkcompat.h | 1 + unix/pty.c | 2 -- unix/putty.c | 9 ++++++++- unix/window.c | 11 +++++++---- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/unix/gtkcompat.h b/unix/gtkcompat.h index 2e8e8b88..02768323 100644 --- a/unix/gtkcompat.h +++ b/unix/gtkcompat.h @@ -187,6 +187,7 @@ #endif /* 2.24 */ #if !GTK_CHECK_VERSION(3,0,0) +#define GDK_IS_X11_DISPLAY(display) (1) #define GDK_IS_X11_WINDOW(window) (1) #endif diff --git a/unix/pty.c b/unix/pty.c index c03328f7..2e3ca749 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -1138,8 +1138,6 @@ Backend *pty_backend_create( char *x_display_env_var = dupprintf("DISPLAY=%s", x_display); putenv(x_display_env_var); /* As above, we don't free this. */ - } else { - unsetenv("DISPLAY"); } } #endif diff --git a/unix/putty.c b/unix/putty.c index a96217e3..1ccc10b6 100644 --- a/unix/putty.c +++ b/unix/putty.c @@ -18,6 +18,10 @@ #include "gtkcompat.h" +#ifndef NOT_X_WINDOWS +#include +#endif + /* * Stubs to avoid pty.c needing to be linked in. */ @@ -62,8 +66,11 @@ const bool dup_check_launchable = true; char *platform_get_x_display(void) { const char *display; +#ifndef NOT_X_WINDOWS /* Try to take account of --display and what have you. */ - if (!(display = gdk_get_display())) + if (!GDK_IS_X11_DISPLAY(gdk_display_get_default()) || + !(display = gdk_get_display())) +#endif /* fall back to traditional method */ display = getenv("DISPLAY"); return dupstr(display); diff --git a/unix/window.c b/unix/window.c index 4a8968d6..97977c3c 100644 --- a/unix/window.c +++ b/unix/window.c @@ -411,8 +411,8 @@ StripCtrlChars *gtk_seat_stripctrl_new( static void gtk_seat_notify_remote_exit(Seat *seat); static void gtk_seat_update_specials_menu(Seat *seat); static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status); -static const char *gtk_seat_get_x_display(Seat *seat); #ifndef NOT_X_WINDOWS +static const char *gtk_seat_get_x_display(Seat *seat); static bool gtk_seat_get_windowid(Seat *seat, long *id); #endif static void gtk_seat_set_trust_status(Seat *seat, bool trusted); @@ -439,10 +439,11 @@ static const SeatVtable gtk_seat_vt = { .prompt_descriptions = gtk_seat_prompt_descriptions, .is_utf8 = gtk_seat_is_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = gtk_seat_get_x_display, #ifdef NOT_X_WINDOWS + .get_x_display = nullseat_get_x_display, .get_windowid = nullseat_get_windowid, #else + .get_x_display = gtk_seat_get_x_display, .get_windowid = gtk_seat_get_windowid, #endif .get_window_pixel_size = gtk_seat_get_window_pixel_size, @@ -4348,12 +4349,14 @@ void modalfatalbox(const char *p, ...) exit(1); } +#ifndef NOT_X_WINDOWS static const char *gtk_seat_get_x_display(Seat *seat) { - return gdk_get_display(); + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return gdk_get_display(); + return NULL; } -#ifndef NOT_X_WINDOWS static bool gtk_seat_get_windowid(Seat *seat, long *id) { GtkFrontend *inst = container_of(seat, GtkFrontend, seat);