cdahlin at redhat.com
Sat May 7 12:37:19 PDT 2011
Talking with krh on IRC, there's a few cases that have come up where a
compositor might want objects to have different methods available than usual.
Some examples include:
* System compositors, which might want map_fullscreen, but not the other map_*
* Network proxying compositors that might want the other map_* functions but
* A whole array of different potential additions and removals for wl_shell,
depending on the paradigm this compositor is using for window management.
There's a few ways that this can be handled:
We could have different interfaces when the set of functionality is different.
This is the approach that is being taken now. It keeps wayland simple and
somewhat extensible, but the disadvantage is that apps have to know which
version of the object to expect. If more than one version can provide for them
then they have to learn several ways to interact with different compositors.
The library could abstract around this a bit, but it would mean every version
of a given interface had to be known to the library, which makes it more
painful to, say, have new compositors implement their own shell interfaces
independently of wayland.
We could solve a good bit of this with a naming convention. For example, we
could say wl_shell.meego would contain all the methods in a basic wl_shell
plus whatever was added by meego. Apps that don't use the meego functionality
know that they can use the object like a regular wl_shell. This is nice in that
it is very easy to implement the way wayland is written now; the extended
interface just tacks its new methods onto the end of the implementation struct
in the object header. The disadvantage to this method is that its hard to layer
functionality. For example, if one extension might want to allow move but not
resize, and another wanted resize but not move, it isn't possible to specify
the base shell in such a way that either of those components could be dropped.
You could specify the base shell with move and resize as
wl_shell.with_move.with_resize, but since the names (and internal
interfaces)are strict subsets and supersets there's no way to drop with_move
and keep with_resize. There's also the danger of names becoming quite long,
especially if we want people to be able to snip out large chunks of
"basic" functionality from the interfaces.
A more flexible option is to implement modules for interfaces. From an OO
perspective these would behave semantically like modules in ruby, or like what
many other languages call mix-ins. An object may support one or more addon
modules to its interface, in any combination. Each addon module has its own
list of additional methods and events provided. The interface for this would
basically add one more uint32_t argument to wl_proxy_marshal, for module id,
and one more client call, wl_proxy_supports. When not using functionality added
by a module, the extra argument to wl_proxy_marshal is 0, and things continue
as normal. When using functionality within a module, the client first calls
wl_proxy_supports, passing the proxy, a string name for the module, and a
desired version. If the function returns non-zero, then that value should be
used for the module id argument in wl_proxy_marshal when calling methods in
More information about the wayland-devel