Verso: initial multi-window support
The multi-window has landed! We are fortunate that refactoring worked as planned. Although it opened some follow-up issues to triage, I'm glad we got the initial support to open more windows instead of just only one in the very beginning. This is one of the most difficult challenge when it comes to develop GUI tools and frameworks. This opens more opportunities to implement further features such as prompt dialog and directory selector, etc. This post is actually the third part of previous series, but I think it worths an unique title for it. In this post, I'll explain what are the key changes to enable multiple windows.
Multiple surfaces
To achieve multi-window, we need, of course, multiple windows (Duh). Winit can already open and manage more than one window.
What we need to do next is create individual surfaces for each window. A surface is a collection of pixel buffers that
are rendered via GPU and displayed in the final target. The target could be either a window or a texture that can be
saved in the file or offscreen. In our case, we only need the window surface for now. We will explore offscreen rendering
in the future. We extended the capability of RenderingContext
to be able to create and destroy additional surfaces in
Servo#32933. And then we try to swap the surface whenever we need the Compositor to deal with different windows.
This change is easier said then done. Although it essentially just needs to add the method of swapping surfaces to the Compositor, updating the window fields to a hashmap of windows requires a lot of fields to be updated as well. I'm also surprised that many changes in the PR are actually updating the parts related to windows instead of dealing with surface.
Multiple display lists
Let the Compositor manage multiple surfaces is the first half. The other half is telling WebRender to render the correct display list. A display list is used to supply a new frame to the WebRender. When building the display list, we could decide which webviews are in such window and push to the list. Finally, we will see the Compositor displays the different surface when we swap the window. It will call the method that can update the display list when the surface is changed.
And that's how Verso gets its initial support of multi-window. There are some follow-up issues we need to triage further. For example, it seems to have some trouble when we try to close the window on macOS and X11. On Wayland, it still displays in the same window. We will have to spend some more time to fix these issues and polish the multi-window feature. Nevertheless, I'm still happy with what Verso achieved. Because even Firefox is still creating multiple contexts to deal with multi-window. We managed to do it with a single context with multiple surfaces.
What's next?
After we polish the multi-window feature. We will explore the multi-process mode, which is already a configuration option in Servo, but it only supports Linux and macOS for now. I want to even improve it via sandboxing on all platforms. Then, we plan to figure out the set-up of Gstreamer with the best DX experience and enable the media feature back. We should also revision the IPC mechanism again since we can communicate with the Constellation directly now. If I still have some free time, I would like to implement ReadableStream in the script crate again. So we can remove the heavy patch from mozjs.
There are many challenging tasks ahead, but I'm excited to see what Verso will become. I'm also looking for new sponsors since this work is probably the final grant from NLNet. If you are also interested in supporting Verso, a new web browser written in Rust, please don't hesitate to donate or contact me.