Browse Source

[X11] Skip TextInput event if KeyDown event was handled

pull/9452/head
Nikita Tsukanov 4 years ago
parent
commit
a30d8ba768
  1. 50
      src/Avalonia.X11/X11Window.Ime.cs
  2. 10
      src/Avalonia.X11/X11Window.cs

50
src/Avalonia.X11/X11Window.Ime.cs

@ -8,6 +8,7 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Platform.Interop;
using JetBrains.Annotations;
using static Avalonia.X11.XLib;
namespace Avalonia.X11
@ -104,13 +105,18 @@ namespace Avalonia.X11
if (ev.KeyEvent.state.HasAllFlags(XModifierMask.Mod2Mask)
&& key > X11Key.Num_Lock && key <= X11Key.KP_9)
key = (X11Key)XKeycodeToKeysym(_x11.Display, ev.KeyEvent.keycode, index ? 0 : 1).ToInt32();
var filtered = ScheduleKeyInput(new RawKeyEventArgs(_keyboard, (ulong)ev.KeyEvent.time.ToInt64(), _inputRoot,
ev.type == XEventName.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
X11KeyTransform.ConvertKey(key), TranslateModifiers(ev.KeyEvent.state)), ref ev, (int)key, ev.KeyEvent.keycode);
if (ev.type == XEventName.KeyPress && !filtered)
TriggerClassicTextInputEvent(ref ev);
var convertedKey = X11KeyTransform.ConvertKey(key);
var modifiers = TranslateModifiers(ev.KeyEvent.state);
var timestamp = (ulong)ev.KeyEvent.time.ToInt64();
RawKeyEventArgs args =
ev.type == XEventName.KeyPress
? new RawKeyEventArgsWithText(_keyboard, timestamp, _inputRoot, RawKeyEventType.KeyDown,
convertedKey, modifiers, TranslateEventToString(ref ev))
: new RawKeyEventArgs(_keyboard, timestamp, _inputRoot, RawKeyEventType.KeyUp, convertedKey,
modifiers);
ScheduleKeyInput(args, ref ev, (int)key, ev.KeyEvent.keycode);
}
void TriggerClassicTextInputEvent(ref XEvent ev)
@ -156,16 +162,15 @@ namespace Avalonia.X11
}
bool ScheduleKeyInput(RawKeyEventArgs args, ref XEvent xev, int keyval, int keycode)
void ScheduleKeyInput(RawKeyEventArgs args, ref XEvent xev, int keyval, int keycode)
{
_x11.LastActivityTimestamp = xev.ButtonEvent.time;
if (_imeControl != null && _imeControl.IsEnabled)
{
if (FilterIme(args, xev, keyval, keycode))
return true;
}
if (_imeControl is { IsEnabled: true }
&& FilterIme(args, xev, keyval, keycode))
return;
ScheduleInput(args);
return false;
}
bool FilterIme(RawKeyEventArgs args, XEvent xev, int keyval, int keycode)
@ -190,11 +195,7 @@ namespace Avalonia.X11
{
var ev = _imeQueue.Dequeue();
if (_imeControl == null || !await _imeControl.HandleEventAsync(ev.args, ev.keyval, ev.keycode))
{
ScheduleInput(ev.args);
if (ev.args.Type == RawKeyEventType.KeyDown)
TriggerClassicTextInputEvent(ref ev.xev);
}
}
}
finally
@ -202,5 +203,18 @@ namespace Avalonia.X11
_processingIme = false;
}
}
// This class is used to attach the text value of the key to an asynchronously dispatched KeyDown event
class RawKeyEventArgsWithText : RawKeyEventArgs
{
public RawKeyEventArgsWithText([NotNull] IKeyboardDevice device, ulong timestamp, [NotNull] IInputRoot root,
RawKeyEventType type, Key key, RawInputModifiers modifiers, string text) :
base(device, timestamp, root, type, key, modifiers)
{
Text = text;
}
public string Text { get; }
}
}
}

10
src/Avalonia.X11/X11Window.cs

@ -190,7 +190,7 @@ namespace Avalonia.X11
UpdateMotifHints();
UpdateSizeHints(null);
_rawEventGrouper = new RawEventGrouper(e => Input?.Invoke(e));
_rawEventGrouper = new RawEventGrouper(DispatchInput);
_transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals);
_transparencyHelper.SetTransparencyRequest(WindowTransparencyLevel.None);
@ -724,7 +724,13 @@ namespace Avalonia.X11
_x11.LastActivityTimestamp = xev.ButtonEvent.time;
ScheduleInput(args);
}
void DispatchInput(RawInputEventArgs args)
{
Input?.Invoke(args);
if (!args.Handled && args is RawKeyEventArgsWithText text && !string.IsNullOrWhiteSpace(text.Text))
Input?.Invoke(new RawTextInputEventArgs(_keyboard, args.Timestamp, _inputRoot, text.Text));
}
public void ScheduleXI2Input(RawInputEventArgs args)
{

Loading…
Cancel
Save