Eto WebView inactive keyboard

Hello @dale !

Yes, I have a simple startup template in vs2017 without command (just the plugin file)

using System;
using System.IO;
using System.Reflection;
using Rhino.PlugIns;

namespace RhWebView
{
    public class RhWebViewPlugIn : Rhino.PlugIns.PlugIn
    {
        public static RhWebViewPlugIn Instance { get; private set; }

        public RhWebViewPlugIn()
        {
            Instance = this;
        }

        protected override LoadReturnCode OnLoad(ref string errorMessage)
        {
            Rhino.UI.Panels.RegisterPanel(this, typeof(Panel), "RhWebView", null);
            return base.OnLoad(ref errorMessage);
        }
    }
    
    [System.Runtime.InteropServices.Guid("244B0C87-BD56-4DB7-AB2C-F7CC170775B1")]
    public class Panel : Eto.Forms.Panel
    {
        public MyWebView browser;
        
        private bool isInEvent = false;

        public Panel()
        {
            browser = new MyWebView ();

            Content = new Eto.Forms.DynamicLayout
            {
                Rows = { new Eto.Forms.DynamicRow(browser) }
            };
        }
        
        protected override void OnLoadComplete(EventArgs e)
        {
            var fpath = (Directory.GetParent(Assembly.GetExecutingAssembly().Location) + "/app/index.html").Replace("\\", "/");
            browser.Url = new System.Uri(fpath);
            base.OnLoadComplete(e);
        }

        protected override void OnGotFocus(EventArgs e) // just shoot the first time, immediately followed by OnLostFocus
        {
            //isInEvent = true;
            Rhino.RhinoApp.WriteLine("+ WarpKeyboardEvent");
            Rhino.RhinoApp.KeyboardEvent += WarpKeyboardEvent;
        }

        protected override void OnLostFocus(EventArgs e) // so OnGotFocus & OnLostFocus is not useful here
        {
            //if ( isInEvent ) { isInEvent = false; return; }
            Rhino.RhinoApp.WriteLine("- WarpKeyboardEvent");
            //Rhino.RhinoApp.KeyboardEvent -= WarpKeyboardEvent;
        }

        protected void WarpKeyboardEvent(int key)
        {
            Rhino.RhinoApp.WriteLine("WarpKeyboardEvent");
            if (isInEvent) { isInEvent = false; return; } // the event is repeated several times, so multiple events can pass
            isInEvent = true;                             // these lines do not solve it
            var loffset = "";                             // (I guess this event is triggered every time like RhinoApp.Idle)
            var coffset = "";
            switch (key)
            {
                case 37: coffset = "- 1"; break;
                case 38: loffset = "- 1"; break;
                case 39: coffset = "+ 1"; break;
                case 40: loffset = "+ 1"; break;
            }
            browser.ExecuteScript(
                $"var pos = editor.getPosition(); editor.setPosition(new monaco.Position (pos.lineNumber {loffset}, pos.column {coffset}))"
            );
        }

        //protected override void OnMouseLeave(MouseEventArgs e) // no effect
        //protected override void OnMouseEnter(MouseEventArgs e) // no effect
        //protected override void OnTextInput(TextInputEventArgs e) // no effect
        //protected override void OnKeyDown(KeyEventArgs e) // no effect
        //protected override void OnKeyUp(KeyEventArgs e) // no effect
    }

    public class MyWebView : Eto.Forms.WebView
    {
        //protected override void OnKeyDown(KeyEventArgs e) // no effect
        //protected override void OnKeyUp(KeyEventArgs e) // no effect
        //protected override void OnMouseEnter(MouseEventArgs e) // no effect
        //protected override void OnMouseLeave(MouseEventArgs e) // no effect

        protected override void OnGotFocus(EventArgs e) // just shoot the first time, immediately followed by OnLostFocus
        { Rhino.RhinoApp.WriteLine("OnGotFocus"); }

        protected override void OnLostFocus(EventArgs e) // just the first time then nothing
        { Rhino.RhinoApp.WriteLine("OnLostFocus"); }

    }
}

and the content of the app/ directory

app.zip (530.1 KB)

And i have change: HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION\rhino_fr-fr_6.7.18183.14071.exe to 11000

note for WarpKeyboardEvent listener that work with up, down, left, right key. But I think it’s not the right method because I do not know how to replace Ctl+C Ctrl+V Ctrl+X


My goal is to have a custom multilingual editor to attach scripts to objects or the document.
it could be:

  • A C# script to run directly in Rhino
  • A Markdown file to document part of 3D
  • A special js/glsl for writing in the webgl export

So I chose monaco editor (the editor of Visual Code) and the content of the editor must listen to the current selection. If the control is in a Modal dialog this project loses all its simplicity.

I tested several approaches:

  • With CefSharp, the editor is fully functional but I have an incompatibility with another library.
    For example: with the C# code i don’t use the same way of your Rhino Inside (because there is too much call between Rhino and the script), i use the Roslyn Script but Roslyn Script needs net46 and CefSharp has no target for this version.
    And CefSharp is very complex to just have a WebView control and to have a control for multi platforms.

  • I tested the editor in a non-modal external window (Electron) and simulate a dockable panel by positioning this window over Rhino.
    But here too I have a problems with Rhino listeners: RhinoEtoApp.MainWindow.SizeChanged has no effect!
    And here too it’s very complex for just have a WebView control.

I would be disappointed if this problem of event listeners forces me to use modal box.
because there would be no interest. Rhino has a script dialog and adding a document to the file can be done with a text file in the Rhino file directory.

Thank you.
jmv