@@ -66,13 +66,11 @@ static AvaloniaGtk()
6666 public static bool HasSoup3 { get ; }
6767
6868 /// <summary>
69- /// Ensures GDK_BACKEND=x11 is in effect for the duration of the bridge call that
70- /// initializes GTK in Avalonia.X11.NativeDialogs.Gtk. The X11 GTK adapters in this
71- /// package use X11/GDK-X11-only entry points and require the X11 GDK backend; under
72- /// a Wayland session GDK_BACKEND is typically pre-set to "wayland" by the desktop,
73- /// which would otherwise cause `gtk_init` to fail with "Unable to initialize GTK".
69+ /// Checks that GTK can initialize with the x11 GDK backend, which the GTK adapters require.
70+ /// GDK_BACKEND replaces the backend list, while Avalonia only filters it with
71+ /// gdk_set_allowed_backends("x11"), so any other explicit value makes gtk_init fail.
7472 /// </summary>
75- public static IDisposable EnsureX11GdkBackendForGtkInit ( )
73+ public static IDisposable PrepareGdkBackendForGtkInit ( bool forceX11 )
7674 {
7775 if ( ! OperatingSystem . IsLinux ( ) )
7876 return EmptyScope . Instance ;
@@ -81,11 +79,16 @@ public static IDisposable EnsureX11GdkBackendForGtkInit()
8179 {
8280 if ( s_overrideCount == 0 )
8381 {
82+ // Unset is fine: GDK then falls back to the backends Avalonia allowed, i.e. x11 only.
8483 var current = Environment . GetEnvironmentVariable ( "GDK_BACKEND" ) ;
85- if ( string . Equals ( current , "x11" , StringComparison . Ordinal ) )
84+ if ( current is not { Length : > 0 } || string . Equals ( current , "x11" , StringComparison . Ordinal ) )
8685 return EmptyScope . Instance ;
87- if ( current is { Length : > 0 } && ! string . Equals ( current , "wayland" , StringComparison . Ordinal ) )
86+
87+ if ( ! forceX11 )
88+ {
89+ ReportUnsupportedBackend ( current ) ;
8890 return EmptyScope . Instance ;
91+ }
8992
9093 int rc ;
9194 try { rc = LibC . setenv ( "GDK_BACKEND" , "x11" , 1 ) ; }
@@ -94,9 +97,10 @@ public static IDisposable EnsureX11GdkBackendForGtkInit()
9497 if ( rc != 0 )
9598 {
9699 Logger . TryGet ( LogEventLevel . Warning , "WebView" ) ? . Log ( null ,
97- "libc setenv(GDK_BACKEND, x11) returned {Rc}; gtk_init may still pick Wayland " , rc ) ;
100+ "libc setenv(GDK_BACKEND, x11) returned {Rc}; gtk_init may still fail " , rc ) ;
98101 return EmptyScope . Instance ;
99102 }
103+ // Keep the managed cache in step, it doesn't share storage with libc's environ.
100104 Environment . SetEnvironmentVariable ( "GDK_BACKEND" , "x11" ) ;
101105 s_savedBackend = current ;
102106 }
@@ -105,9 +109,22 @@ public static IDisposable EnsureX11GdkBackendForGtkInit()
105109 return new RestoreGdkBackendScope ( ) ;
106110 }
107111
112+ private static void ReportUnsupportedBackend ( string current )
113+ {
114+ if ( s_reportedUnsupportedBackend )
115+ return ;
116+ s_reportedUnsupportedBackend = true ;
117+
118+ Logger . TryGet ( LogEventLevel . Error , "WebView" ) ? . Log ( null ,
119+ "GDK_BACKEND is set to {Backend}, but the GTK web view requires the x11 GDK backend, " +
120+ "so GTK initialization is expected to fail. Either run with GDK_BACKEND=x11, or set " +
121+ "ForceX11GdkBackend on GtkWebViewEnvironmentRequestedEventArgs." , current ) ;
122+ }
123+
108124 private static readonly object s_overrideLock = new ( ) ;
109125 private static int s_overrideCount ;
110126 private static string ? s_savedBackend ;
127+ private static bool s_reportedUnsupportedBackend ;
111128
112129 private sealed class EmptyScope : IDisposable
113130 {
@@ -126,15 +143,13 @@ public void Dispose()
126143 {
127144 if ( -- s_overrideCount > 0 )
128145 return ;
146+ // Only ever set when GDK_BACKEND already had a value, so there is nothing to unset.
129147 var previous = s_savedBackend ;
130148 s_savedBackend = null ;
131- try
132- {
133- if ( previous is null )
134- LibC . unsetenv ( "GDK_BACKEND" ) ;
135- else
136- LibC . setenv ( "GDK_BACKEND" , previous , 1 ) ;
137- }
149+ if ( previous is null )
150+ return ;
151+
152+ try { LibC . setenv ( "GDK_BACKEND" , previous , 1 ) ; }
138153 catch ( DllNotFoundException ) { }
139154 catch ( EntryPointNotFoundException ) { }
140155 Environment . SetEnvironmentVariable ( "GDK_BACKEND" , previous ) ;
0 commit comments