KeyDown/KeyUP from an Eto Panel

,

Hello,

I want to be able to detect keyboard input from an Eto Panel control.
I’m running my plugin on macOS (haven’t checked if the following applies for Win as well, but it’s not the point).

I tried subscribing KeyDown or KeyUp events directly on the Panel, but none of them are triggered when any key is pressed.
Of course I can subscribe the RhinoApp.KeyboardEvent (and it works), but there is no way to mark the keyboard input as handled, once it is processed by the attached delegate function.

So - for example - if I want my panel to respond to an F1 key to show some custom help, RhinoApp.KeyboarEvent makes it work, but the F1 key continues to “bubble up” to application level, so the Rhino Application also responds to the key input, showing the default Rhino Help panel.

Is there any other way to intercept keyboard input from a panel and mark it as handled, so that the application does not process the input a second time?

Thanks

With this sample I see the same. I would expect this to work.

// #! csharp
using System;

using Eto.Forms;
using Eto;

using Rhino;

void HandleKeyDown(object sender, KeyEventArgs e)

    RhinoApp.WriteLine("Down!");
}

void HandleKeyUp(object sender, KeyEventArgs e)
{
    RhinoApp.WriteLine("Up!");
}

Panel panel = new() { Width = 200, Height = 200 };
panel.KeyDown += HandleKeyDown;
panel.KeyUp += HandleKeyUp;

Form form = new()
{
    Topmost = true,
    Content = panel
};

form.Show();

Similar thread - Eto OnKeyDown issue

Hey @p.stragliotto,

You need to make sure that a control within your panel has focus in order for the KeyDown or KeyUp to fire. If you don’t have any, you could use a Drawable with CanFocus = true, then call Focus() on that control when your panel shows (or is clicked).

Hope this helps!

Hello @curtisw

thanks for the advice. I tried to implement my control as Drawable and setting a focused state whenever it is clicked.
To make sure the control has focus when I press any key, I did the following:

class MyControl : Drawable {
  // ...

  public MyControl() {
    CanFocus = true;

    RhinoApp.KeyboardEvent += key => {
      // Just to check if this control has focus.
      if (this.HasFocus) {
        RhinoApp.WriteLine("I have focus");
      }
    };

    // Does this control intercept keyup event?
    this.KeyUp += (sender, args) => {
      // Do something...
    };
  }

  // ...
}

I have the confirmation that my control has focus, because the message is written on the command history.
But it behaves in a strange way, and after testing it a bit, I think the way in which the keyboard input is processed is the following:

  1. If the pressed keys are related to a Rhino App shortcut (e.g. F2 –> Command History) or alpha keystrokes that can be interpreted as a command line string, the Rhino App deals with them straight away (I guess with its own listener) and none of those reach the current focused control
  2. If the pressed keys are something else (e.g ESC, ⇧+F2, …) the Rhino App “ignores” them and they reach the focused control, triggering the KeyUp event.

Don’t know if this is specifically happens for Eto.Mac, I’ll try to investigate a bit more, but if no other solution can be applied, I will instruct macOS users to use ⇧+F2 shortcut rather than F2.

This looks like you have a typo in there:

    RhinoApp.KeyboardEvent += key => {
      // Just to check if this control has focus.
      if (this.HasFocus) {
        RhinoApp.WriteLine("I have focus");
      }
    };

should probably be:

    this.KeyDown += (sender, args) => {
      // Just to check if this control has focus.
      if (this.HasFocus) {
        RhinoApp.WriteLine("I should always have focus");
        e.Handled = true;
      }
    };

Hope this helps!