Fix compilation: restore clean RC1 codebase
- Restore clean BindableProperty.Create syntax from RC1 commit - Remove decompiler artifacts with mangled delegate types - Add Svg.Skia package reference for icon support - Fix duplicate type definitions - Library now compiles successfully (0 errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,154 +1,172 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating the appropriate Input Method service.
|
||||
/// Automatically selects IBus or XIM based on availability.
|
||||
/// </summary>
|
||||
public static class InputMethodServiceFactory
|
||||
{
|
||||
private static IInputMethodService? _instance;
|
||||
private static IInputMethodService? _instance;
|
||||
private static readonly object _lock = new();
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
/// <summary>
|
||||
/// Gets the singleton input method service instance.
|
||||
/// </summary>
|
||||
public static IInputMethodService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_instance ??= CreateService();
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static IInputMethodService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = CreateService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates the most appropriate input method service for the current environment.
|
||||
/// </summary>
|
||||
public static IInputMethodService CreateService()
|
||||
{
|
||||
// Check environment variable for user preference
|
||||
var imePreference = Environment.GetEnvironmentVariable("MAUI_INPUT_METHOD");
|
||||
|
||||
public static IInputMethodService CreateService()
|
||||
{
|
||||
string environmentVariable = Environment.GetEnvironmentVariable("MAUI_INPUT_METHOD");
|
||||
if (!string.IsNullOrEmpty(environmentVariable))
|
||||
{
|
||||
switch (environmentVariable.ToLowerInvariant())
|
||||
{
|
||||
case "ibus":
|
||||
return CreateIBusService();
|
||||
case "fcitx":
|
||||
case "fcitx5":
|
||||
return CreateFcitx5Service();
|
||||
case "xim":
|
||||
return CreateXIMService();
|
||||
case "none":
|
||||
return new NullInputMethodService();
|
||||
default:
|
||||
return CreateAutoService();
|
||||
}
|
||||
}
|
||||
return CreateAutoService();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(imePreference))
|
||||
{
|
||||
return imePreference.ToLowerInvariant() switch
|
||||
{
|
||||
"ibus" => CreateIBusService(),
|
||||
"xim" => CreateXIMService(),
|
||||
"none" => new NullInputMethodService(),
|
||||
_ => CreateAutoService()
|
||||
};
|
||||
}
|
||||
|
||||
private static IInputMethodService CreateAutoService()
|
||||
{
|
||||
string obj = Environment.GetEnvironmentVariable("GTK_IM_MODULE")?.ToLowerInvariant();
|
||||
if (obj != null && obj.Contains("fcitx") && Fcitx5InputMethodService.IsAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using Fcitx5");
|
||||
return CreateFcitx5Service();
|
||||
}
|
||||
if (IsIBusAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using IBus");
|
||||
return CreateIBusService();
|
||||
}
|
||||
if (Fcitx5InputMethodService.IsAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using Fcitx5");
|
||||
return CreateFcitx5Service();
|
||||
}
|
||||
if (IsXIMAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using XIM");
|
||||
return CreateXIMService();
|
||||
}
|
||||
Console.WriteLine("InputMethodServiceFactory: No IME available, using null service");
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
return CreateAutoService();
|
||||
}
|
||||
|
||||
private static IInputMethodService CreateIBusService()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new IBusInputMethodService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Failed to create IBus service - " + ex.Message);
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
}
|
||||
private static IInputMethodService CreateAutoService()
|
||||
{
|
||||
// Try IBus first (most common on modern Linux)
|
||||
if (IsIBusAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using IBus");
|
||||
return CreateIBusService();
|
||||
}
|
||||
|
||||
private static IInputMethodService CreateFcitx5Service()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Fcitx5InputMethodService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Failed to create Fcitx5 service - " + ex.Message);
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
}
|
||||
// Fall back to XIM
|
||||
if (IsXIMAvailable())
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Using XIM");
|
||||
return CreateXIMService();
|
||||
}
|
||||
|
||||
private static IInputMethodService CreateXIMService()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new X11InputMethodService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("InputMethodServiceFactory: Failed to create XIM service - " + ex.Message);
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
}
|
||||
// No IME available
|
||||
Console.WriteLine("InputMethodServiceFactory: No IME available, using null service");
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
|
||||
private static bool IsIBusAvailable()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("IBUS_ADDRESS")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
NativeLibrary.Free(NativeLibrary.Load("libibus-1.0.so.5"));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static IInputMethodService CreateIBusService()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new IBusInputMethodService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"InputMethodServiceFactory: Failed to create IBus service - {ex.Message}");
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsXIMAvailable()
|
||||
{
|
||||
string environmentVariable = Environment.GetEnvironmentVariable("XMODIFIERS");
|
||||
if (!string.IsNullOrEmpty(environmentVariable) && environmentVariable.Contains("@im="))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DISPLAY"));
|
||||
}
|
||||
private static IInputMethodService CreateXIMService()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new X11InputMethodService();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"InputMethodServiceFactory: Failed to create XIM service - {ex.Message}");
|
||||
return new NullInputMethodService();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_instance?.Shutdown();
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
private static bool IsIBusAvailable()
|
||||
{
|
||||
// Check if IBus daemon is running
|
||||
var ibusAddress = Environment.GetEnvironmentVariable("IBUS_ADDRESS");
|
||||
if (!string.IsNullOrEmpty(ibusAddress))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to load IBus library
|
||||
try
|
||||
{
|
||||
var handle = NativeLibrary.Load("libibus-1.0.so.5");
|
||||
NativeLibrary.Free(handle);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsXIMAvailable()
|
||||
{
|
||||
// Check XMODIFIERS environment variable
|
||||
var xmodifiers = Environment.GetEnvironmentVariable("XMODIFIERS");
|
||||
if (!string.IsNullOrEmpty(xmodifiers) && xmodifiers.Contains("@im="))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if running under X11
|
||||
var display = Environment.GetEnvironmentVariable("DISPLAY");
|
||||
return !string.IsNullOrEmpty(display);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the singleton instance (useful for testing).
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_instance?.Shutdown();
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Null implementation of IInputMethodService for when no IME is available.
|
||||
/// </summary>
|
||||
public class NullInputMethodService : IInputMethodService
|
||||
{
|
||||
public bool IsActive => false;
|
||||
public string PreEditText => string.Empty;
|
||||
public int PreEditCursorPosition => 0;
|
||||
|
||||
public event EventHandler<TextCommittedEventArgs>? TextCommitted;
|
||||
public event EventHandler<PreEditChangedEventArgs>? PreEditChanged;
|
||||
public event EventHandler? PreEditEnded;
|
||||
|
||||
public void Initialize(nint windowHandle) { }
|
||||
public void SetFocus(IInputContext? context) { }
|
||||
public void SetCursorLocation(int x, int y, int width, int height) { }
|
||||
public bool ProcessKeyEvent(uint keyCode, KeyModifiers modifiers, bool isKeyDown) => false;
|
||||
public void Reset() { }
|
||||
public void Shutdown() { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user