From 54ff5a32953a52c030c9a88c9c0a5c7fdaf69363 Mon Sep 17 00:00:00 2001 From: AlanIWBFT Date: Wed, 17 Dec 2025 04:30:40 +0800 Subject: [PATCH] [X11] Clean up IME inconsistencies (#20201) * [X11] Clean up IME inconsistencies * Fix where combinations like `GTK_IM_MODULE=none XMODIFIERS=@im=fcitx` can actually enable IME instead of forbid it - this is consistent with `AvaloniaX11Platform.EnableIme()` * XIM should always be used if none of `IM_MODULE` is set (instead of only when they are explicitly set to `xim`) * [X11] Try connecting to IMEs specified in `XMODIFIERS=@im=` through D-Bus before falling back to XIM * [X11] Refine `XMODIFIERS=@im=` parsing * Only the first one specified will be parsed and accepted --- .../DBusIme/X11DBusImeHelper.cs | 11 ++++++ src/Avalonia.X11/X11Platform.cs | 35 +++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.FreeDesktop/DBusIme/X11DBusImeHelper.cs b/src/Avalonia.FreeDesktop/DBusIme/X11DBusImeHelper.cs index a189c2e5da..57cc2cd496 100644 --- a/src/Avalonia.FreeDesktop/DBusIme/X11DBusImeHelper.cs +++ b/src/Avalonia.FreeDesktop/DBusIme/X11DBusImeHelper.cs @@ -31,6 +31,17 @@ namespace Avalonia.FreeDesktop.DBusIme return factory; } + var modifiers = Environment.GetEnvironmentVariable("XMODIFIERS"); + if (modifiers is not null && modifiers.Contains("@im=")) + { + int imNameStart = modifiers.IndexOf("@im=") + "@im=".Length; + int imNameEnd = modifiers.IndexOf("@", imNameStart); + string imName = imNameEnd == -1 ? modifiers.Substring(imNameStart) : modifiers.Substring(imNameStart, imNameEnd - imNameStart); + + if (KnownMethods.TryGetValue(imName, out var factory)) + return factory; + } + return null; } diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index 2de880833a..634864f768 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -166,27 +166,26 @@ namespace Avalonia.X11 private static bool ShouldUseXim() { + // Priority: AVALONIA_IM_MODULE > GTK_IM_MODULE >= QT_IM_MODULE + string? imeOverride = Environment.GetEnvironmentVariable("AVALONIA_IM_MODULE"); + if (string.IsNullOrEmpty(imeOverride)) + imeOverride = Environment.GetEnvironmentVariable("GTK_IM_MODULE"); + if (string.IsNullOrEmpty(imeOverride)) + imeOverride = Environment.GetEnvironmentVariable("QT_IM_MODULE"); + // Check if we are forbidden from using IME - if (Environment.GetEnvironmentVariable("AVALONIA_IM_MODULE") == "none" - || Environment.GetEnvironmentVariable("GTK_IM_MODULE") == "none" - || Environment.GetEnvironmentVariable("QT_IM_MODULE") == "none") - return true; - + if (imeOverride == "none") + return false; + // Check if XIM is configured var modifiers = Environment.GetEnvironmentVariable("XMODIFIERS"); - if (modifiers == null) - return false; - if (modifiers.Contains("@im=none") || modifiers.Contains("@im=null")) - return false; - if (!modifiers.Contains("@im=")) - return false; - - // Check if we are configured to use it - if (Environment.GetEnvironmentVariable("GTK_IM_MODULE") == "xim" - || Environment.GetEnvironmentVariable("QT_IM_MODULE") == "xim" - || Environment.GetEnvironmentVariable("AVALONIA_IM_MODULE") == "xim") - return true; - + if (modifiers is not null && modifiers.Contains("@im=")) + { + // If XIM is explicitly requested, or no IME override is configured + if (imeOverride == "xim" || string.IsNullOrEmpty(imeOverride)) + return true; + } + return false; }