-
Notifications
You must be signed in to change notification settings - Fork 921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
App lifecycle separation #1005
App lifecycle separation #1005
Conversation
Don't create an NSApplicationDelegate and set it on the shared NSApplication instance unless the library takes responsibility of the application lifecycle.
Only perform COM initialization and enable DPI awareness when an existing window isn't provided.
Looks interesting. I'll take a look over the weekend. Thank you for the work! |
* Create a message-only window for internal messaging. * Remove responsibility of handling WM_APP from run().
On Windows the event loop ends when a single window is closed. |
A problem causes the run loop to exit.
I've managed to avoid the crashes on macOS but a remaining problem is how the first This is turning into a bit of a mess in my opinion. |
This looks awesome already. I gave it a shot with the V binding without stopovers. On mac I'm still running into a seg fault as soon as opening the second window. Works on Linux and Windows. I will try better tomorrow and in the other officially supported langs! import webview { EventId, JSArgs }
const doc = '<button id="new-window">New window</button>
<script>
const newWindowButton = document.querySelector("#new-window");
document.addEventListener("DOMContentLoaded", () => {
newWindowButton.addEventListener("click", () => {
window.new_window();
});
});
</script>'
fn main() {
w := webview.create()
w.set_title('Primary Window')
w.set_size(480, 320, .@none)
w.set_html(doc)
w.bind('new_window', fn [w] (_ EventId, _ JSArgs, _ voidptr) {
w.dispatch(fn (_ &webview.Webview, _ voidptr) {
w2 := webview.create()
w2.set_title('Secondary Window')
w2.set_size(480, 320, .@none)
w2.set_html('Secondary Window')
}, 0)
}, 0)
w.run()
}
|
Not sure but to me it looks like maybe somewhere in |
Make sure that |
Unfortunately no change. |
Okay works when disabling garbage collection, should have tried that earlier... Thanks for the assistance! |
It seems like I was incorrect regarding the current behavior on macOS when closing windows. When testing it again, it appears that the run loop does stop, and the app does exit. It just takes a few seconds sometimes. |
The window closing behavior is now aligned on all platforms: It relies on a static variable to track the number of windows. |
Regarding creating multiple windows on macOS: Go works well with the PR 🙂:+1:. I tried several approaches so that V users would only require |
Sorry, can you please clarify this bit? I read this as Go working well except when you disable GC on macOS. Is there any chance the webview library is being compiled with ARC enabled on macOS? If so then you currently need to disable it just for the webview core library. |
Yes sure, what I mean is that Go is working well with the PR, just regularly compiled. Using the git head it crashes on macOS. I never fiddled with the garbage collector in go so this is all with the defaults. I'm working on the V wrapper, so I also added the experience made with it. With V it is already possible to create multiple windows on macOS the git head, as long as not using garbage collection. Of course there are still the life cycle issues you fix here, but it won't crash. With the PR it's still required to use manual memory management in V to not segfault. IDK if and if yes how it's possible to help the GC better understand. |
By "git head", I guess you mean the Frankly I'm not really a Go developer and have never worked with V before, but I would just assume that there's a sensible way to avoid your objects from being destroyed by the GC. For example this snippet that you shared before:
To me this looks like it'll for sure be GC at some point because I assume you made changes to this example so what does it look like now? |
Yes, exactly - latest master, fix not yet merged.
Yes it changed. I'm at my phone currently on the way to do some light work. When I get the chance I add one or two of the approaches here during the day. Else this night. Thanks already 🙏 |
To share a very short insight at first: The segfault happens as soon as calling E.g. // windows.v - (just the file name, it's run on mac 😅)
import webview
fn main() {
w := webview.create()
w2 := webview.create()
}
An example using dispatch and adding the window into the applications scope: import webview
const doc = '<button id="new-window">New window</button>
<script>
const newWindowButton = document.querySelector("#new-window");
document.addEventListener("DOMContentLoaded", () => {
newWindowButton.addEventListener("click", () => {
window.new_window();
});
});
</script>'
[heap]
struct App {
mut:
w &webview.Webview
w2 &webview.Webview
}
fn main() {
mut app := App{
w: webview.create()
w2: unsafe { nil }
}
app.w.set_title('Primary Window')
app.w.set_size(480, 320, .@none)
app.w.set_html(doc)
app.w.bind_ctx('new_window', fn (e &webview.Event, mut ctx App) {
e.dispatch_ctx(fn (mut ctx App) {
ctx.w2 = webview.create()
ctx.w2.set_title('Secondary Window')
ctx.w2.set_size(480, 320, .@none)
ctx.w2.set_html('Secondary Window')
}, ctx)
}, app)
app.w.run()
} The example above run with the current version of the V library on Linux and Windows. Some other attempts included modifying the wrapper functions in the library to force it into a working version. They didn't work either on mac so I won't go further into them. In the end the only way was to disable garbage collection entirely. |
I hate to ask something that may seem so obvious but did you see proof that I guess you could just put an If that doesn't help then it would be interesting to figure out what's causing the segfault inside |
That's good steps to come closer to the problem, thank you! @SteffenL I'll walk the dog and come back to this. |
I made sure of this. In fact I just manually copied the
Adding But! Adding the So @SteffenL it works. You're the man 💪 👍 ! |
The If we're going to fully support this then we also need examples that cover passing an existing window, and that isn't something that worked well across all platforms even before this PR. The library is missing features that are important for managing windows so that shouldn't be the main focus of this PR. The initial post has been rewritten and describes the changes in more detail. |
This work more clearly separates application lifecycle from windowing by taking responsibility of managing the app lifecycle only when an existing window isn't passed to the library, and leaves it up to the user when an existing window is passed.
Note that this isn't to say that using an existing window with the library is now fully usable across all platforms, but was it ever?
This is also not about making multiple windows created by the library a key feature but we can remove hinders, align some behaviors across platforms, and perhaps facilitate future work on multi-window support.
The key differences in this work are described below.
Linux:
gtk_init_check()
before the library creates the window.macOS:
webview
class that creates a window will register classes.
NSApplication
instance.Windows:
run()
by using a message-only window. Allows internal messaging when users use their own message loop instead of callingrun()
.