[wpe-webkit] Using WebKitWPE in an existing GMainLoop/Wayland render loop
ryan at testtoast.com
Mon May 6 17:50:12 PDT 2019
On Tue, 7 May 2019, at 1:34 AM, Adrian Perez de Castro wrote:
> Hi Ryan,
> Wow, that would be the first ever application we know about written in Swift
> that uses WPE, which is really cool! :)
No wonder Stack Overflow is no help...
> Side note: I have not been following Swift much, and I am just learning now
> that it has been made to work well on GNU/Linux already a good while ago.
It is actually very good on the server/command-line side, with support from IBM and Apple. It falls over a bit with Linux GUI integration, and though there have been attempts to create wrappers for GTK (most sucessfully https://github.com/rhx/SwiftGtk), they weren't suitable for what I had in mind and not so portable, hence my bright idea to use WebKit to render my UI.
You can imagine a scenario where a macOS app, Linux app (with WPE or GTK WebKit) or Windows app (using the Windows WebKit port and the newly minted official windows Swift port) could all be using a common code base and UI with only minimal platform specific code.
> I wonder how complicated it may have been to use WPE's GLib-based API in
> Swift — is there any particular pain point that you might remember and which
> could have used a better API on the WPE WebKit side?
There were three basic challenges:
1. Create a Wayland window and EGL render target.
Both of these have C APIs which interoperate (generally) well with Swift so this just took time to port the relevant code over to Swift. There were some issues round-tripping pointers to imported C structs through Swift, then into a Wayland object creation function, then back to swift to store, so I had to resort to using a couple of C shim functions after discussing with some of the Linux Swift devs at Apple (they exist!). However this ultimately worked nicely with the majority of the code in swift calling the C Wayland and EGL APIs, and is very performant.
2. Create a WPE Context and WebView
This was actually the easiest part, I essentially lifted the object creation code directly from Cog, and then it was trivial to replace my renderer callback (a whole glClear command) with the code to take an EGLImageKHR from WPE and render it into the appropriate wl_surface. This is done on demand using a wl_surface callback for proper frame timing.
3. Run a GMainLoop event loop from a NSRunLoop.
This was actually the trickiest part and essentially orthogonal to WPE. Given it's origin at Apple, Swift has the best support for an event loop based on either libdispatch for GCD (using dispatchMain()) or a CoreFoundation run loop using CFRunLoopRun() however neither support GIO-based event sources or FDs. The GTK Swift wrappers use a GApplication and GApplicationMain(), but I preferred to be less reliant on GTK and stick with CFRunLoop.
GTK has code to integrate a GMainLoop into a CFRunLoop or vice versa (https://gitlab.gnome.org/GNOME/gtk/blob/master/gdk/quartz/gdkeventloop-quartz.c) however this is intended to allow GTK-based apps to run on macOS. It did seem like a good approach however so I ported the relevant parts to Swift, and this again works well, allowing processing of both libdispatch/CFRunLoop events on the Swift side (allowing a very portable logic layer) and GIO events allowing WPE to run its WebProcess and handle events.
The only issue I found is that the CFRunLoopTimer object which is required to set a timeout to process events is implemented on macOS as a struct with a compatible memory layout to the NSTimer Cocoa object, but on Linux NSTimer is implemented as a wrapper around CFRunLoopTimer in the Swift corelib implementation. I managed to get a patch accepted (https://github.com/apple/swift-corelibs-foundation/pull/2116) but only recently so you would need a fairly recent build of Swift (>5.0 so the Ubuntu nightlies or custom build) to use the run loop code. It does look like it has been tagged for 5.1 however.
> Thanks a lot for commenting on the WebKit bug and sending the PR for Cog, it
> is very appreciated. I think there are good chances of having the support for
> setting the scaling factor merged.
Great, I'll try to get a formal pull request organised for WebKit. Should I aim for the Igalia repo or upstream?
More information about the webkit-wpe