Deconstructing Clutter

it is pretty clear that, if we want to rebase GTK+ on top of Clutter there will be some form of clash between them — mostly in the windowing system part of the API.

GTK+ has its own windowing system abstraction in GDK; it's public API, and it's been ported on various platforms. while the GTK development team is trying to minimize the API footprint of GDK, the API is expected to exist (in various forms) for the entire 3.x and 4.x cycles.

Clutter has a small windowing system abstraction, mostly to deal with creating a top-level window to draw upon, and to handle events.

we cannot keep them both, and there's a sensible use case for GDK already, in terms of installed code base and multi-platform support. so, the Clutter abstraction should just go away.

Backend

the ClutterBackend class is a platform-specific singleton that is in charge of creating and maintaining the windowing system abstraction inside Clutter. a Backend creates the stage implementation, as well as maintaining the Cogl context and rendering pipeline. we will probably need defer the Cogl pipeline set up to the global Clutter context, but once we remove that, the backend code is mostly empty.

Stage

the top-level actor in the Clutter scene graph is the "stage". the reasons why it exists as a separate class from ClutterActor are historical:

  • the Stage has a backing stage implementation, which depends on the windowing system backend;
  • at Clutter's inception, we didn't want to depend on GDK, so we could not just reuse those data structures and code;
  • ClutterActor was not a container, so ClutterStage had to inherit from a container class.

those reasons are not interesting any more: we can break away from the 0.x/1.x history, and we can depend on GDK being available.

ClutterStage should just not exist any more; it should be possible to assign a GdkWindow to a ClutterActor, and have the actor draw its contents and children on top of that window, e.g.:

    void       clutter_actor_set_window (ClutterActor *, GdkWindow *)
    GdkWindow *clutter_actor_get_window (ClutterActor *)

setting the window of a ClutterActor will automatically set the CLUTTER_ACTOR_TOP_LEVEL flag on the actor; all checks inside Clutter will use that flag instead of a type check (most of them already do). the window is set onto every child when adding it to a parent, so retrieving the top-level is a constant time operation.

sub-windows are not going to be possible in GDK 4.x, and are being phased out in GDK 3.x as well, but the set_window() function should do some sanity checks on the type of window being passed: only native GdkWindow instances can be used as backing stores, and no off screen window is supported.

currently, we have a Stage Manager object that keeps track of all the Stage instances; we will need a (private) class that does the same for all the top-level actors instead, so that we can have multiple top-level actors and associate the correct GdkWindow backing store with the underlying Cogl pipeline.

Event handling

at the very beginning of Clutter, the Stage was the only Actor that could receive events; the Actor underneath the pointer was determined at event handling, and application code was expected to deal with the hit detection. after Clutter 0.1, we added event handling on a per-actor basis, with event capturing and bubbling; this was due to the idea of creating toolkits and applications purely based on Clutter, and because the actor/container split (and the implicit scene graph) made it difficult to traverse the scene.

events are proxied from the native windowing system into ClutterEvent structures, a solution modelled on GdkEvent and friends. an initial step would be to make ClutterEvent a GdkEvent, and probably make GdkEvent a better data structure in the process (refcounted, opaque, no "sub-classes", only accessor pairs). the end goal, on the other hand, would be to go back to Clutter's roots, and not have event handling inside the scene graph core.

events should be handled on the GdkWindow that operates as the top-level backing store; it should be possible to perform hit detection on each event, and traverse the scene graph using the ClutterActor API.

Devices

since we removed the event handling, we can also get away with removing the input infrastructure, and just reuse GDK's. this applies to both pointer/touch devices as well as keyboards.

Frame clock

Clutter has a "master clock" already, which implements the sequence of operations necessary to draw a frame. GDK recently gained the same system, so we can reuse that API.

Settings

ClutterSettings is a singleton that proxies state from the windowing system into the scene graph; we can trivially do that using GDK itself and its existing code.

Result

by removing the windowing system abstraction; event handling; input device abstraction; system settings; and everything already provided by GDK; we end up with a leaner API. Clutter would only be in charge of a scene graph, its layout, and its drawing, as well as the animation infrastructure based on top of the frame clock.

this leaner Clutter would be easily embeddable and usable inside GTK+ without requiring deep modifications to GTK+ itself or to the applications using it, and it would open the possibility of using Clutter actors to build user interfaces on top of a GTK+ base without unnecessary bridges/integration libraries like clutter-gtk.

Attic/Clutter/Future (last edited 2024-04-11 15:39:27 by EmmanueleBassi)