2

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

Community
  • 1
  • 1
nielsbot
  • 15,922
  • 4
  • 48
  • 73
  • What exactly do you mean by "system context menu"? Do you mean you want to disable the monaco context menu (including the options therein) completely or do you want it to "render" differently? Probably some screenshots (current vs. desired) could help. – MSeifert Mar 27 '18 at 07:38
  • Sorry, I mean the menu that appears when I right click on the text (“Go To Definition...”, “Format Text”) etc. In VS Code the menu appears as a native Mac menu. In Monaco I get a “menu” rendered inside the web view. – nielsbot Mar 28 '18 at 16:29
  • Yes. Screen shot is a great idea. – nielsbot Mar 28 '18 at 16:30
  • Did you forget to actually include the screenshot of actual vs. desired in the question? It seemed like you liked the idea. – MSeifert Mar 29 '18 at 23:43
  • yes.. I did. I've attached them. – nielsbot Mar 30 '18 at 11:15
  • Does this help ? https://stackoverflow.com/questions/44750658/how-to-disable-monaco-context-menu – Tarun Lalwani Apr 01 '18 at 10:01
  • Just to be clear: You just want it to **look** like the native contextmenu, or do you want it to **contain** the commands of the native contextmenu? – MSeifert Apr 02 '18 at 14:43
  • @MSeifert I want it to render using the a system context menu... I am not trying to change the contents. Thanks. – nielsbot Apr 02 '18 at 20:12
  • @TarunLalwani There's nothing in there about changing the rendering of the context menu, just how to disable it.. That doesn't help. – nielsbot Apr 02 '18 at 20:13
  • The menu your see in vscode is not native, it's CSS look and feel is native. So you can get a native look and feel only I believe – Tarun Lalwani Apr 02 '18 at 21:26
  • No, it's actually a native menu. I updated my question. – nielsbot Apr 03 '18 at 06:23
  • @nielsbot, thats the way it works in chrome, a electron browser as well. Checking what VScode does to get it working – Tarun Lalwani Apr 08 '18 at 09:16
  • @TarunLalwani VSCode source is not available anywhere, correct? – nielsbot Apr 09 '18 at 06:52

1 Answers1

4

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

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265