We’ve discussed supporting shell specific Wayland extensions in the past (here and here).
My view following those discussions is that we should encourage “broadly useful” Wayland protocol extensions to be submitted as PRs to the Mir repository. As many such protocols will need to interact with Mir internal APIs this will ensure they can access these features.
However, there are also some plausible protocol extensions that will be specific to particular shells. For example, before Unity8 can transition to Wayland they will need something to replace the “Trusted Prompt Sessions” provided by the libmirclient API.
I’ve now started seriously thinking about how to implement a MirAL API to enable this. There are (at least) three aspects of this API to consider:
- Enabling a shell to register and implement a protocol extension;
- Supporting integration with other abstractions exposed by the MirAL API; and,
- Allowing the shell to control which protocols are available to specific clients.
I’ve sketched out what the API for the first of these might look like in a PR (https://github.com/MirServer/wlcs/pull/77). The API parts are the “MirAL 2.5” parts of this:
class WaylandExtensions
{
public:
/// Provide the default extensions supported by Mir
WaylandExtensions();
/// Provide a custom set of default extensions (colon separated list)
/// \note This can only be a subset of supported_extensions().
explicit WaylandExtensions(std::string const& default_value);
...
/// \remark Since MirAL 2.5
using Executor = std::function<void(std::function<void()>&& work)>;
/// A Builder creates and registers an extension protocol.
/// The Builder is provided the wl_display so that the extension can be registered and
/// an executor that allows server initiated code to be executed on the Wayland mainloop.
/// It returns a shared pointer to the implementation. Mir will manage the lifetime.
/// \remark Since MirAL 2.5
using Builder = std::function<std::shared_ptr<void>(wl_display* display, Executor const& run_on_wayland_mainloop)>;
private:
...
};
/// Add a bespoke Wayland extension.
/// \remark Since MirAL 2.5
auto with_extension(
WaylandExtensions const& wayland_extensions,
std::string const& name, WaylandExtensions::Builder const& builder) -> WaylandExtensions;
/// Add multiple bespoke Wayland extensiona.
/// \remark Since MirAL 2.5
template<typename... Extensions>
auto with_extension(WaylandExtensions const& wayland_extensions,
std::string const& name, WaylandExtensions::Builder const& builder,
Extensions... extensions) -> WaylandExtensions
{
return with_extension(with_extension(wayland_extensions, name, builder), extensions...);
}
This bare minimum API provides the extension implementation to access the wl_display
for registering the protocol and provides an executor so that code can be run on the Wayland mainloop.
auto const server_exit_status = runner.run_with({
...
with_extension(miral::WaylandExtensions{"wl_shell:xdg_wm_base:zxdg_shell_v6:zwlr_layer_shell_v1:xdg_decoration_unstable_v1"},
"xdg_decoration_unstable_v1", &xdg_decoration_unstable_v1,
"some_other_extension", &some_other_extension),
I believe this to be enough to implement some protocols. Obviously, I have something like xdg_decoration_unstable_v1
in mind.
As far as I can see, support for items 2 and 3 in my list above can be added in a later iteration.