webview / webview

Tiny cross-platform webview library for C/C++. Uses WebKit (GTK/Cocoa) and Edge WebView2 (Windows).

Home Page:https://webview.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Spawning multiple windows on macOS doesn't work

ttytm opened this issue · comments

It's unfortunately not possible to spawn multiple windows on mac like it is on other platforms.

The following code works on Linux and Windows machines but results in a segfault on macOS.

package main

import "github.com/webview/webview"

func main() {
  w := webview.New(false)
  w2 := webview.New(false)
  defer w.Destroy()
  defer w2.Destroy()

  w.SetTitle("Win1")
  w.SetSize(480, 320, webview.HintNone)
  w.SetHtml("Thanks for using webview!")

  w2.SetTitle("Win2")
  w2.SetSize(480, 320, webview.HintNone)
  w2.SetHtml("Thanks for using webview!")

  w.Run()
  w2.Run()
}

This is based on ttytm/webview#16, thanks a lot for leaving a message there already!

I haven't been a maintainer of this library for a long time but I'll try to answer to the best of my ability.

Unfortunately this isn't currently a supported use case on any platform. While it may work on Linux and Windows without noticeable problems, it isn't a guarantee provided by the library.

When an existing window isn't passed to the library then it wants to take responsibility of managing the application's lifecycle. It supports a single window managed by the library this way.

Specifically on macOS, you work with a single shared instance of NSApplication and an associated instance of a custom NSApplicationDelegate that the library sets on the shared NSApplication instance. You can't have multiple delegates set on the same NSApplication instance and you can't get the same notifications multiple times during app startup (we have some workarounds in place).

Unfortunately it looks like this is also a problem when passing an existing window on macOS because it replaces any existing app delegate set on the shared NSApplication instance.

Some of the described behavior was present when #315 was merged (the major library rewrite by zserge), and while I don't know for sure, it was probably the initial work following his proposal in #305 which said the following:

For the sake of simplicity [...] only a single native window per app process is supported. For those, who have [...] the need of multiple windows there are two options: spawn a process per window and let them talk to each other via IPC, or create an external app loop on your own, then create as many native windows as you need and pass them into webview constructor. [...] However, in this the developer is in charge of managing such native windows.

In believe this is still supposed to be the expected behavior except that on macOS it probably never worked since #315 (don't know about v0.1.1).

I hesitate to label this as a bug because of the reasons described above, but with that said my opinion is that we need to improve documentation, and hopefully we could also improve the experience especially on macOS without a complete redesign of the library.

I've submitted a PR (draft) for experimenting with multiple windows:

At time of writing I've added an example for GTK and I'll move on to Windows before macOS.

Feel free to take a look.

I've done a bit of testing on Windows and found that while it technically works to create two instances of the webview class without passing in an existing window, it doesn't work on my system if you try to instantiate the class the same way within a binding handler unless you do it within a callback passed to dispatch(). If you do it directly in the binding handler then the window appears but WebView2 seemingly never completes initialization so the program becomes stuck.

I haven't been a maintainer of this library for a long time but I'll try to answer to the best of my ability.

Thanks a lot lot for keeping things running here @SteffenL!

Personally, I think in over 90 percent it's the better design decision to handle windows within the applications main as JS windows. This is also the most common way that I see with apps that use web-technologies for the GUI. I also don't see myself writing an app with webview that will need multiple native windows for one instance. So the issue report was rather a forwarding without a lot of personal concern.

For the sake of simplicity [...] only a single native window per app process is supported. For those, who have [...] the need of multiple windows there are two options: spawn a process per window and let them talk to each other via IPC, or create an external app loop on your own, then create as many native windows as you need and pass them into webview constructor. [...] However, in this the developer is in charge of managing such native windows.

I didn't found statements on multiple windows, thanks for sharing this! Though it doesn't work for me to spawn a windows from threads. Trying it (on linux) won't show any window.

If it eventually can covered it will be a nice topping and will probably satisfies some users who need it or don't know better. In any case, thanks a lot for the work !

Thanks for the kind words, @ttytm! 😄

I'll have to agree that it would be much nicer if the library could manage windows. I've found various issues with passing in existing windows so if I were to choose between one or the other, I would rather commit to support multiple windows created by the library.

Oh, and if you want to use the library from a thread other than the main/GUI thread then you should:

  • Create the webview instance on the main thread.
  • Call run() on the main thread.
  • Use dispatch() from another thread.

Personally, I think in over 90 percent it's the better design decision to handle windows within the applications main as JS windows.

It would be logical for the library to support this along with custom URI schemes. Unfortunately WebKitGTK has a bug with loading certain types of content (audio and video) over custom URI schemes which makes it unreliable.

Personally, I think in over 90 percent it's the better design decision to handle windows within the applications main as JS windows.

Reflecting on it it probably was an over-statement, as it can really depends on the context of an application if multiple native windows for one application instance is the right decision. So it's very nice for a library to cover all those corners.

It would be logical for the library to support this along with custom URI schemes. Unfortunately WebKitGTK has a bug with loading certain types of content (audio and video) over custom URI schemes which makes it unreliable.

💯 👍