With commit 5a565b4258, we changed
clutter_actor_finish_layout() to be not only about updating stage views,
but also take care of updating the visible_paint_volume, for that we
started doing a full tree traversal of all mapped actors.
This can be quite a performance issue, apparently especially on certain
ARM devices, where the simple tree traversal can take as long as 2ms.
This is precious time we need to paint our next frame, so lets do a bit
more work to avoid those useless traversals.
Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/2459
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
We're using clutter_stage_schedule_update() now from ClutterActor to kick
off the stage updating machinery when a redraw needs to happen.
This introduced a bunch of unnecessary calls to
clutter_stage_schedule_update() and thus
clutter_stage_view_schedule_update() when multiple actors request redraws
during the same stage update cycle, which is a very common case.
Cut off all those unnecessary calls by bailing out in
clutter_stage_schedule_update() when updates are already queued.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
Using a list of heap allocated ClutterPaintVolumes adds quite a bit of
unnecessary overhead: It means for every single redraw clip we allocate a
list and a paint volume on the heap.
Let's avoid all those heap allocations by using a GArray with static
ClutterPaintVolumes instead.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
So far our logic for queueing redraws goes like this: Actor notices that it
needs to redraw -> actor tells stage that it needs to redraw via
clutter_stage_queue_actor_redraw() -> stage collects more and more redraws
into a QueueRedrawList before the actual stage update happens -> when
that happens, the stage collects the actual redraw clips from the actors via
clutter_actor_get_redraw_clip().
The logic behind this QueueRedrawList was that by storing a list of
redraw entries on the stage, way we can avoid traversing the whole actor
tree one more time to build the redraw clip before the stage update.
These days we have clutter_actor_finish_layout() though, which is basically
exactly that, a whole actor tree traversal that happens before every stage
update.
Since we have that now, we might as well get rid of the whole dance back and
forth between ClutterStage and ClutterActor, and simply merge the logic to
queue redraws into the finish-layout step.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
If no actors have changed their positions and we're only repainting
because a window needs a repaint, the paint volumes of all actors
remain unchanged. There is no reason to redo those paint volumes on every
stage update.
So introduce caching and invalidation logic for the visible_paint_volume
that allows us to avoid a ton of matrix multiplications that right now
are happening for the whole mapped actor tree on every redraw.
Note that this removes two places where the visible paint volume is set
to an empty paint volume: This is a compromise so that we can keep
around the cached pv when hiding and showing an actor, it does "regress"
one case though: When hiding -> moving -> showing an actor, we'll now
include the old paint volume of the actor in the redraw clip on show (even
though redrawing that old region is not necessary, the actor was hidden
after all). This results in a bit of overpaint in this very specific case,
but for the sake of simplicity let's not care about that.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
When building mutter with -Ddebug=false, a warning appears, that
`ClutterStagePrivate *priv` is unused.
Simply remove this variable and directly use `stage->priv` in
`CLUTTER_NOTE` to get rid of this warning.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3046>
ClutterText paints selected text using the selection_paint()
function. This function has to main branches of execution:
when the position is in the selection bound, or not. In the
former, we are leaking the CoglPipeline created by copying
the default color pipeline.
Unref the copied pipeline after using it.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3007>
For now, it goes the "easy" way of creating the root node and
immediately painting and destroying it. From now on, the main
root node is created only by ClutterStage itself.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3007>
This aims to reduce the amount of pixels that have to be redrawed on the
screen on a clipped actor redraw in case using the union of two
different clips in a surface will substantially increase the redrawn
area.
This should not result in excessive memory consumption as callers of
`clutter_actor_queue_redraw_with_clip` are expected to ensure that the
redraw clip rectangles are adequately deduplicated.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2965>
mutter-clutter is a private library that is only used by the shell and
not meant to be ABI/API compatible in between versions, so there's no
need to add padding to classes.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2903>
This is needed by GNOME Shell to remove itself as a input method
implementation during its shutdown sequence. We can't do it ourself
later because at mutters own shutdowns equence, the GNOME Shell
Javascript context has by that time already been teared down.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2934>
It will be used to schedule Wayland frame events independently from both
update and presentation time, as the former may happen multiple times
frame and the later not at all.
For frame events we want a timing that is just late enough to ensure
that a following commit by a Wayland client will not get included into
the current frame any more.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2823>
This is not yet used, but next commits will need to assign a frame
to the paint context whenever painting onscreens.
Assigning a frame to the paint context is a one-way operation, and
treats multiple assignments strictly as a programming error.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2804>
Both Clutter and Cogl use g_return(_val)_if_fail() to safeguard
introspected API. Release builds were dropping these checks, which could
result in a much more crashy experience, especially when considering
extensions, but also due to bugs in the shell code itself.
This won't affect any major distro, because they all use "plain" builds.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2930>
Stage view users can schedule updates at ease with
clutter_stage_view_schedule_update(), but couldn't schedule update
"now". Make that easy too by adding
clutter_stage_view_schedule_update_now().
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2854>
If we call schedule(), which will schedule an update some time in the
future, and then schedule_now(), we should reschedule the frame clock to
update immediately, and not some time in the future.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2854>
For motion-induced crossing events, this will be the device that generated
the motion. For code-induced crossing events (e.g. grabs or actors disappearing)
this will be none.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2828>
Since the last commit, ClutterStage automatically cancels an implicit
grab (including all its ClutterActions) when a conflicting ClutterGrab
appears.
This means we no longer have to look out for GRAB_NOTIFY crossings in
ClutterGestureAction and can instead depend on the sequence_cancelled()
vfunc for this.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
A ClutterGrab takes precedence over implicit grabs, so when one happens,
let's check which part of the implicit grab tree is inside the new
ClutterGrab. Cancel and remove the parts which aren't, and if nothing
is in there anymore, cancel the whole implicit grab.
Emitting crossing events correctly here is getting quite tricky:
- When the implicit grab didn't get cancelled by the ClutterGrab, we
simply want to emit all GRAB_NOTIFY crossings to the implicit grab, as
we do with all other crossings.
- When the implicit grab did get cancelled and the new ClutterGrab wants
to emit ENTER crossings, we want those to be emitted to the actual
targets, so cancel the implicit grab before emission.
- In the last case where the implicit grab did get cancelled and the new
ClutterGrab wants to emit LEAVE crossings, those should be emitted to
the implicit grab again, so we cancel the grab only after the emission
of those.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
Now that we have two kinds of grabs, the intricacies of event delivery
got slightly more complicated. So this seems like a good point to
introduce a new GRABS debug flag that gives an overview of which grabs
are currently in effect.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
We're almost there, everything is in place to notify ClutterActions
about a sequence getting pulled away under its feet.
The only thing that's missing is the actual notification to actions now,
so let's do that.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
Another baby step just like the last commit: This commit takes care of
the opposite case: An action handling a sequence event stops further
emission of events to actors.
Since sequences remain around for longer than the context of just a
single event, it makes sense to provide a way to "claim" those sequences
even when outside of event handling context, so introduce API for that.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
As soon as any event of a sequence is handles/stopped during emission,
all actors and actions that would have gotten to see it afterwards have
a big problem: If that event was a TOUCH_END event, the actor/action is
forever going to think that this touch is still active.
For ClutterActions, we're going to handle this by introducing a way to
send them a notification when stuff like this happens.
As a baby step towards all that, make event emission exclusive to actors
as soon as any actor stopped an event.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>
We'll soon introduce a new gesture tracking framework which heavily
depends on ClutterActions seeing all events of a sequence. For this to
work, a larger change to event delivery is needed: Implicit grabbing of
all events for button and touch press->motion->release sequences to
ensure ClutterActions continue receiving events for the whole sequence.
This commit takes care of that: At the start of an event sequence we
collect all the event-handling actors and actions to a GArray that lives
in the PointerDeviceEntry, and then deliver all events belonging to
that sequence to the same actors/actions until the sequence ends.
To avoid events getting pulled from under our feet when mutters event
filter returns CLUTTER_EVENT_STOP, this also introduces private API
(maybe_lost_implicit_grab()) on ClutterStage so that we can't end up
with stale sequences.
Note that this also slightly changes behavior when it comes to event
delivery to actions: Because we now store actions separated from their
actors, any action returning CLUTTER_EVENT_STOP now stops event
propagation immediately. That was different before, where we'd emit
events to all actions of the actor and only then stop propagation.
Note that this isn't handling ClutterGrabs correctly right now,
this will be a little tricky, so we'll take care of that in a future
commit.
To handle actors getting destroyed or unmapped during a grab, listen to
notify::grab on the deepmost actor in the implicit grab tree. This gives
us a notification when any actor inside the tree goes unmapped.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2342>