User avatar
sfernandez
Site Admin
Posts: 1915
Joined: 22 Dec 2011, 19:20

Re: Disable keyboard shortscuts when in gui elements

16 Jun 2020, 14:04

The current state is that we are handling half of the shortcuts only after IView::KeyDown() returned explicit "false", outside Noesis. Which is working perfectly fine for actions which are entirely independent from the UI, with no unwanted side effects.
Correct me if I'm wrong, but doing this has the same problem as using the KeyTrigger, because if you have the focus in a TextBox, and press the 'R' key, IView::KeyDown() will return false (TextBox only handles specific keys it needs like backspace or delete, arrow keys...), so if there is a shortcut associated with the 'R' key it will be executed. Then the 'R' key is translated into the corresponding char and sent to the IView::Char(), and TextInput event is generated, so TextBox writes the 'r' letter too.
And maintaining keybindings in two different systems is not desirable either.
Totally agree, that is why we are trying to offer the best approach with the tools we have available in Noesis.
Trying to move the shortcut definitions to Noesis scope has led up to using KeyTrigger (as the only available tool), but with the result of evaluation order of shortcuts and text input getting flipped
As I said before that is not the case, because KeyDown will always occur before TextInput. Which leads me to another possible solution, that could be more in line with what you are explaining. Implement a ShortcutTrigger that listens to TextInput event and fires the action on the KeyUp event, if no TextBox handled the TextInput event, something like this:
void ShortcutTrigger::OnAttached()
{
    ParentClass::OnAttached();

    Noesis::UIElement* source = GetAssociatedObject();
    if (source != 0)
    {
        source->TextInput() += MakeDelegate(this, &ShortcutTrigger::OnTextInput);
        source->KeyUp() += MakeDelegate(this, &ShortcutTrigger::OnKeyUp);
    }
}

void ShortcutTrigger::OnDetaching()
{
    Noesis::UIElement* source = GetAssociatedObject();
    if (source != 0)
    {
        source->TextInput() -= MakeDelegate(this, &ShortcutTrigger::OnTextInput);
        source->KeyUp() -= MakeDelegate(this, &ShortcutTrigger::OnKeyUp);
    }

    ParentClass::OnDetaching();
}

bool ShortcutTrigger::CheckModifiers() const
{
    Noesis::Keyboard* keyboard = GetAssociatedObject()->GetKeyboard();
    return GetModifiers() == keyboard->GetModifiers();
}

void ShortcutTrigger::OnTextInput(Noesis::BaseComponent*, const Noesis::TextCompositionEventArgs&)
{
    mTextInputIgnored = true;
}

void ShortcutTrigger::OnKeyUp(Noesis::BaseComponent*, const Noesis::KeyEventArgs& e)
{
    if (e.key == GetKey() && CheckModifiers() && mTextInputIgnored)
    {
        mTextInputIgnored = false;
        InvokeActions(0);
    }
}
Is this what you are looking for?
 
Ext3h
Posts: 4
Joined: 07 Mar 2020, 10:14

Re: Disable keyboard shortscuts when in gui elements

16 Jun 2020, 20:06

Correct me if I'm wrong, but doing this has the same problem as using the KeyTrigger, because if you have the focus in a TextBox, and press the 'R' key, IView::KeyDown() will return false
You are correct, it wasn't handled by IView::KeyDown(). But we are checking for return values both of IView::KeyDown() or IView::Char() before continuing to process the input, so it did actually do something plausible for us.

The Idea of waiting on TextCompositionEvent in "ShortcutTrigger" is effectively doing the same. Doesn't exactly need to wait for KeyUp, but may already enter half-triggered state in KeyDown and trigger on TextCompositionEvent already.

But it does fall for another trap. Any logic trying to argue over TextCompositionEvents is then incapable of handling dead keys (e.g. ^), as TextCompositionEvent isn't triggered until UTF8 composite is passed to IView::Char(). (Win32Display from NoesisApp has skipped mapping any potentially dead keys (VK_OEM_*), so that doesn't show. And none are dead on US keyboard layout.)

So at least for dead key support, it's back to explicitly ignoring key presses if the source (or in fact anything in the event route) is potentially a handler of a followup TextCompositionEvent. There is no way around probing whether the scene is currently in text input mode or not, prior to deciding how to handle the key down event.
 
User avatar
sfernandez
Site Admin
Posts: 1915
Joined: 22 Dec 2011, 19:20

Re: Disable keyboard shortscuts when in gui elements

19 Jun 2020, 16:26

I understand what you are saying, you're right using TextInput won't work when a shortcut references a dead key.

Taking into account your comments...
it's that the TextBox should (be able to) consume the input it can handle before shortcuts are triggered
I've been doing more tests and I verified that WPF's TextBox only sets Handled to true for KeyDown event on some specific keys, and TextInput event. The KeyUp event simply bubbles up for all keys. So without breaking that behavior, implementing a shortcut trigger that works on all the scenarios you have exposed can't rely on those events being handled by inner controls.

I think it is better to try to solve the specific problem here: don't trigger shortcuts if a TextBox (or PasswordBox) has the focus (as I exposed before).
Do you have any suggestion on how to improve that approach?

Who is online

Users browsing this forum: Google [Bot], Roest and 0 guests