visual-studio-codevscode-extensionsmonaco-editorvisual-studio-monaco

Monaco editor: Use native (system) context menu


Is there a way to get Monaco to use a system menu for the context menu?

I have embedded Monaco in a WKWebView on macOS. The contextual (right-click) menu is rendered inside the web view, not as a native system menu. (But VSCode does show a native context menu.)

How can I make this work?


This is what I want: (What I see in VS Code)

enter image description here

But I get this: (What I get in my embedded WKWebView)

enter image description here


edit 2:

You can see this is actually a system menu by the way it renders outside the containing window. A screenshot:

enter image description here


Solution

  • So after digging into all of this. This answer will give your pointer to how to achieve this. If you look at ContextMenu rendered by MonaEditor in any browser, it is always clipped by viewport.

    Electron Browser

    Chrome Browser

    Now this is because the contextmenu is a HTML based on, which is bound by the limits of the viewport.

    So why is VSCode able to show a menu out of ViewPort?

    VSCode context menu

    This is because electron has capabilities to show native menus. VSCode disables Monaco's own menu and creates a native menu on right click. You can see below npm module which shows how

    https://github.com/mixmaxhq/electron-editor-context-menu

    Now when you are using WKWebView, you can't use electron features, so this means you will need to natively implement a Context handler in your Swift Code. Below are some SO threads which will point you in the right direction

    How can the context menu in WKWebView on the Mac be modified or overridden?

    Catch Javascript Event in iOS WKWebview with Swift

    I created a Cocoa app with below code to just make sure the approach would work

    //
    //  ViewController.swift
    //  WebViewTEst
    //
    //  Created by Tarun Lalwani on 4/8/18.
    //  Copyright © 2018 Tarun Lalwani. All rights reserved.
    //
    
    import Cocoa
    import WebKit
    
    class ViewController: NSViewController {
    
        @IBOutlet weak var webView: WKWebView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
            let url = "https://microsoft.github.io/monaco-editor/"
    
            let prefs = self.webView.configuration.preferences
            prefs.javaScriptEnabled = true
            prefs.plugInsEnabled = true
            self.webView.customUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5"
            self.webView.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
            self.webView.load(URLRequest(url: URL(string: url)!))
    
    
            // Do any additional setup after loading the view.
        }
    
        override var representedObject: Any? {
            didSet {
            // Update the view, if already loaded.
            }
        }
    
    
    }
    

    And then disabled the monaco default context menu by running editor.updateOptions({contextmenu: false}) and after that the context menu shown on the editor was native. Now this is what you need to now customize from your native code

    Context menu native