Skip to content

Commit

Permalink
Use SDL3 text editing events on windows
Browse files Browse the repository at this point in the history
`StartTextInput()` and `ResetIme()` are kept as they improve
and can co-exist with SDL3 logic.
  • Loading branch information
Susko3 committed Nov 11, 2024
1 parent 109df77 commit d9603f7
Showing 1 changed file with 0 additions and 111 deletions.
111 changes: 0 additions & 111 deletions osu.Framework/Platform/Windows/SDL3WindowsWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using osu.Framework.Allocation;
using osu.Framework.Input.Handlers.Mouse;
using osu.Framework.Platform.SDL3;
using osu.Framework.Platform.Windows.Native;
Expand Down Expand Up @@ -62,36 +59,6 @@ public override void Create()
Native.Input.SetWindowFeedbackSetting(WindowHandle, feedbackType, false);
}

public override unsafe void Run()
{
SDL_SetWindowsMessageHook(&messageHook, ObjectHandle.Handle);
base.Run();
}

[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe SDLBool messageHook(IntPtr userdata, MSG* msg)
{
var handle = new ObjectHandle<SDL3WindowsWindow>(userdata);
if (handle.GetTarget(out SDL3WindowsWindow window))
return window.handleEventFromHook(*msg);

return true;
}

private SDLBool handleEventFromHook(MSG msg)
{
switch (msg.message)
{
case Imm.WM_IME_STARTCOMPOSITION:
case Imm.WM_IME_COMPOSITION:
case Imm.WM_IME_ENDCOMPOSITION:
handleImeMessage(msg.hwnd, msg.message, msg.lParam);
break;
}

return true;
}

protected override void HandleEventFromFilter(SDL_Event evt)
{
switch (evt.Type)
Expand Down Expand Up @@ -125,8 +92,6 @@ private void warpCursorFromFocusLoss()
}
}

#region IME handling

public override void StartTextInput(bool allowIme)
{
base.StartTextInput(allowIme);
Expand All @@ -135,82 +100,6 @@ public override void StartTextInput(bool allowIme)

public override void ResetIme() => ScheduleCommand(() => Imm.CancelComposition(WindowHandle));

protected override void HandleTextInputEvent(SDL_TextInputEvent evtText)
{
string? sdlResult = evtText.GetText();
Debug.Assert(sdlResult != null);

// Block SDL text input if it was already handled by `handleImeMessage()`.
// SDL truncates text over 32 bytes and sends it as multiple events.
// We assume these events will be handled in the same `pollSDLEvents()` call.
if (lastImeResult?.Contains(sdlResult) == true)
{
// clear the result after this SDL event loop finishes so normal text input isn't blocked.
EventScheduler.AddOnce(() => lastImeResult = null);
return;
}

// also block if there is an ongoing composition (unlikely to occur).
if (imeCompositionActive) return;

base.HandleTextInputEvent(evtText);
}

protected override void HandleTextEditingEvent(SDL_TextEditingEvent evtEdit)
{
// handled by custom logic below
}

/// <summary>
/// Whether IME composition is active.
/// </summary>
/// <remarks>Used for blocking SDL IME results since we handle those ourselves.</remarks>
private bool imeCompositionActive;

/// <summary>
/// The last IME result.
/// </summary>
/// <remarks>
/// Used for blocking SDL IME results since we handle those ourselves.
/// Cleared when the SDL events are blocked.
/// </remarks>
private string? lastImeResult;

private void handleImeMessage(IntPtr hWnd, uint uMsg, long lParam)
{
switch (uMsg)
{
case Imm.WM_IME_STARTCOMPOSITION:
imeCompositionActive = true;
ScheduleEvent(() => TriggerTextEditing(string.Empty, 0, 0));
break;

case Imm.WM_IME_COMPOSITION:
using (var inputContext = new Imm.InputContext(hWnd, lParam))
{
if (inputContext.TryGetImeResult(out string? resultText))
{
lastImeResult = resultText;
ScheduleEvent(() => TriggerTextInput(resultText));
}

if (inputContext.TryGetImeComposition(out string? compositionText, out int start, out int length))
{
ScheduleEvent(() => TriggerTextEditing(compositionText, start, length));
}
}

break;

case Imm.WM_IME_ENDCOMPOSITION:
imeCompositionActive = false;
ScheduleEvent(() => TriggerTextEditing(string.Empty, 0, 0));
break;
}
}

#endregion

protected override void HandleTouchFingerEvent(SDL_TouchFingerEvent evtTfinger)
{
if (evtTfinger.TryGetTouchName(out string? name) && name == "pen")
Expand Down

0 comments on commit d9603f7

Please sign in to comment.