With commit 0eab73dc2e we introduced an optimization of not doing
allocations for actors which are hidden. This broke the propagation of
absolute origin changes to hidden actors, so if an actor is moved while
its child is hidden, the child will not get
priv->needs_compute_resource_scale set to TRUE, which means the resource
scale won't be updated when the child gets mapped and shown again.
Since we now have priv->absolute_origin_changed, we can simply check
whether that is TRUE for our parent before bailing out of
clutter_actor_allocate() and if it is, notify the whole hidden sub-tree
about the absolute origin change.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
Since clutter_stage_set_viewport() is only used inside clutter-stage.c
anyway, we can make it a static method. Also we can remove the x and y
arguments from it since they're always set to 0 anyway.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
When getting the last allocation using
clutter_actor_get_allocation_box(), Clutter will do an immediate
relayout of the stage in case an actor has an invalid allocation. Since
the allocation is always invalid when the allocate() vfunc is called,
clutter_stage_allocate() always forces another allocation cycle.
To fix that, stop comparing the old allocation to the new one to find
out whether the viewport changed, but instead use the existing check in
_clutter_stage_set_viewport() and implement the behavior of rounding the
viewport to the nearest int using roundf() (which should behave just as
CLUTTER_NEARBYINT()) since we're passing around floats anyway.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
When manipulating the allocation of a ClutterActor from an allocate()
vfunc override, clutter_actor_set_allocation() is used to let Clutter
know about the changes.
If the actors allocation or its absolute origin did not change before
that, this can also affect the actors absolute_origin_changed property
used by the children to detect changes to their absolute position.
So fix this bug (which luckily didn't seem to affect us so far) and set
priv->absolute_origin_changed to TRUE in case the origin changes inside
clutter_actor_set_allocation_internal(). Since this function is always
called when our allocation changes, we no longer need to update
absolute_origin_changed in clutter_actor_allocate() now.
Since a change to the absolute origin always affects the resource scale,
too, we also need to move that check from clutter_actor_allocate() here
to make sure we update the resource scale.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
Since the introduction of the shallow relayout functionality it's
possible to start an allocation cycle at any point in the tree, not only
at the stage. Now when starting an allocation at an actor that's not the
stage, we'd still look at the absolute_origin_changed property of this
actors parent, which might still be set to TRUE from the parents last
allocation.
So avoid using the parents absolute_origin_changed property from the
last allocation in case a shallow relayout is being done and always
reset the absolute_origin_changed property to FALSE after the allocation
cycle.
This broke with the removal of the ABSOLUTE_ORIGIN_CHANGED
ClutterAllocationFlag that was done in commit dc8e5c7f.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
This cannot be made to work reliably. Some factoids:
- Internal devices may be connected via USB.
- The ACPI spec provides the _PLD (Physical location of device) hook to
determine how is an USB device connected, with an anecdotal success
rate. Internal devices may be seen as external and vice-versa, there is
also an "unknown" value that is widely used.
- There may be non-USB keyboards, the old "AT Translated Set 2 Keyboard"
interface does not change on hotplugging.
- Libinput has an internal series of quirks to classify keyboards as
internal of external, also with an "unknown" value.
These heuristics are kinda hopeless to get right by our own hand. Drop
this external keyboard detection in the hope that there will be something
more deterministic to rely on in the future (e.g. the libinput quirks
made available to us directly or indirectly).
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2378
Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2353https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1277
In clutter_text_queue_redraw_or_relayout() we check whether the size
of the layout has changed and queue a relayout if it did, otherwise we
only queue a redraw and save some resources.
The current check for this also queues a redraw if the actor has no
valid allocation. That seems right on the first glance since the actor
will be allocated anyway, but we actually want to call
clutter_actor_queue_relayout() again here because that also invalidates
the size cache of the actor which might have been updated and marked
valid in the meantime.
So make sure the size cache is always properly invalidated after the
size of the layout changed and also call clutter_actor_queue_relayout()
in case the actor has no allocation.
This fixes a bug where getting the preferred width of a non-allocated
ClutterText, then changing the string of the ClutterText, and then
getting the preferred width again would return the old cached width (the
width before we changed the string).
The only place where this bug is currently happening is in the overview,
where we call get_preferred_width() on the unallocated ClutterText of
the window clone title: When the window title changes while the
ClutterText is unallocated the size of the title is going to be wrong
and the text might end up ellipsized or too large.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1150
It's effectively used by mutter by abusing a ClutterTimeline to scedule
updates. Timelines are not really suited in places that is done, as it
is really just about getting a single new update scheduled whenever
suitable, so expose the API so we can use it directly.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1218
We could call clutter_stage_schedule_update() and it wouldn't actually
schedule anything, as the master frame clock only tries to reschedule if
1) there is an active timeline, 2) there are pending relayouts, 3) there
are pending redraws, or 4) there are pending events. Thus, a call to
clutter_stage_schedule_update() didn't have any effect if it was called
at the wrong time.
Fix this by adding a boolean state "needs_update" to the stage, set on
clutter_stage_schedule_update() and cleared on
_clutter_stage_do_update(), that will make the master clock reschedule
an update if it is TRUE.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1218
We need to use the framebuffer of the view instead of the onscreen
framebuffer when painting the damage region, otherwise the redraw clips
on rotated monitors won't be shown correctly.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
Compare, tile by tile, whether actual damage actually changed any
pixels. While this requires mmap():ing DMA buffers and comparing their
content, we should only ever use shadow buffers when we're using the
software renderer, meaning mmap() is cheap as it doesn't involve any
downloading.
This works by making the shadow framebuffer double buffered, while
keeping track of damage history. When we're about to swap the onscreen
buffer, we compare what part of the posted damage actually changed,
records that into a damage history, then given the onscreen buffer age,
collect all actual damage for that age. The intersection of these tiles,
and the actual damage, is then used when blitting the shadow buffer to
the onscreen framebuffer.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1157https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
Move the damage history tracking to a new ClutterDamageHistory helper
type. The aim is to be able to track damage history elsewhere without
reimplementing the data structure and tracking logic.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
This fixes the last "copy everything" paths when clutter doesn't
directly paint onto the onscreen framebuffer. It adds a new hook into
the stage view called before the swap buffer, as at this point, we have
the swap buffer damag regions ready, which corresponds to the regions we
must blit according to the damage reported to clutter.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
The rest didn't change, so only actually paint the part of the offscreen
that was composited as part of the stage painting. In practice, this
means that, unless a shadow buffer is used, we now only paint the
damaged part of the stage, and copy the damage part of the offscreen to
the onscreen.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
We failed to use the buffer age when monitors were rotated, as when they
are, we first composite to an offscreen framebuffer, then later again to
the onscreen. The buffer age checking happened on the offscreen, and an
offscreen being single buffered, they can't possible support buffer
ages.
Instead, move the buffer age check to check the actual onscreen
framebuffer. The offscreen to onscreen painting is still always full
frame, but that will be fixed in a later commit.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
The manual "cleaning" of the viewport and projection state is removed,
and we only ever try to invalidate the state so that it'll be updated
next time. Change the API used to reflect this.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
The stage would fetch the front framebuffer and set the viewport and
projection matrix, but if we are going to more than one front buffer,
that won't work, so let the stage just pass the viewport and projection
matrix to the view and have the view deal with the framebuffer(s).
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
Will be used for logging to identify what view a log entry concerns. For
the native and nested backend this is the name of the output the CRTC is
assigned to drive; for X11 it's just "X11 screen", and for the legacy
"X11 screen" emulation mode of the nested backend it's called "legacy
nested".
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
All existing users of clutter_actor_has_mapped_clones() actually want to
know whether the actor is being cloned by a visible clone, it doesn't
matter to them if that clone is attached to an actor somewhere else in
the tree or to the actor itself.
So make clutter_actor_has_mapped_clones() a bit more convenient to use
and also check the clones of the parent-actors in that function.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1235
The comment in _clutter_actor_get_allocation_clip() explicitely notices
that it doesn't need the behavior of doing an immediate relayout as
clutter_actor_get_allocation_box() does. The comment is also still valid
since the code calling _clutter_actor_get_allocation_clip() checks for
priv->needs_allocation just before.
So let's just use the allocation directly here instead of going through
that function.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1264
ClutterBoxLayout's layout policy of using the generic ClutterActor
align/expand properties for children that are expanded and a custom
meta otherwise is confusing, in particular as the x-fill/y-fill
defaults don't match the default CLUTTER_ACTOR_ALIGN_FILL align.
StBoxLayout's own custom child meta (which was deprecated last
cycle) is probably the only consumer. And luckily, the St meta
uses different x-fill/y-fill default that match the ClutterActor
defaults, so removing it will not affect code that doesn't use
the deprecated properties themselves.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1265
This stuff has been deprecated for a very long time, and given that
ClutterBoxLayout is most commonly used via StBoxLayout, the impact of
removing it should be low. It will however open the door to further
cleanups.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1265
We're going to remove the "allocation-changed" signal from ClutterActor
since it's no longer needed now that ClutterAllocationFlags are gone.
So listen to "notify-allocation" instead, which has been the recommended
thing to do for some time now anyway.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
The ABSOLUTE_ORIGIN_CHANGED allocation flag is only really useful to
propagate the information of the absolute origin of an actor having
changed inside Clutter. It wasn't used anywhere else besides for some
debug messages and it probably shouldn't be used in custom layout
implementations anyway since 1) actors shouldn't have to be aware of
absolute allocation changes and 2) it doesn't factor in changes to the
transformation matrix of a parent.
Also the propagation of absolute origin changes using this flag broke
with commit 0eab73dc2e and now hidden actors are no longer notified
about those changes.
Additionally, this flag gets in the way of a few potential optimizations
since it has to be propagated even if the allocation box of the child
hasn't changed, forcing a reallocation of the child.
So replace this flag with a simple new private property of ClutterActor
absolute_origin_changed, but keep the exact same behavior for now.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
Since we now only layout the children ourselves in case the actor
implementation doesn't override the allocate vfunc, we can remove
clutter_actor_maybe_layout_children() and move the functionality inside
clutter_actor_real_allocate().
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
Now that we no longer have the DELEGATE_LAYOUT we expect all actors
overriding the allocate() vfunc to allocate their children themselves.
Since clutter_actor_set_allocation() is only called from custom
vfunc_allocate() implementations, the condition in
clutter_actor_maybe_layout_children() would always fail, which makes
calling the function useless anyway.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
The CLUTTER_DELEGATE_LAYOUT flag is unintuitive and makes the allocation
process inside Clutter unnecessarily complicated. It's very easy for
actors overriding the allocate() vfunc to layout their children
themselves (in fact most of them do this), and it also never made sense
that clutter_actor_set_allocation() does eventually layout children.
There was no ClutterActor implementation in mutter or gnome-shell which
actually used the DELEGATE_LAYOUT flag, but even without it, it's fairly
easy to archive the same behavior now: In the allocate() override,
adjust the allocation as wanted, then chain up to the parent vfunc
without calling clutter_actor_set_allocation().
So remove the CLUTTER_DELEGATE_LAYOUT flag, which will allow making the
relayout code in Clutter a bit easier to follow.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
We're going to remove allocation flags, so stop depending on the
DELEGATE_LAYOUT flag in ClutterStage and call
clutter_layout_manager_allocate() directly, which is pretty
straightforward.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1245
The public API to get the parent actor, clutter_actor_get_parent() does
a type check whether the actor is actually a ClutterActor. In case of
_clutter_actor_apply_relative_transformation_matrix(), which is called
recursively and very often during the paint process, this type check
shows up with almost twice the amount of hits than the actual matrix
multiplication.
So use the parent pointer directly in some code paths that are executed
very often and avoid the expensive type checking there, we can do that
since both places are not public API.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1259
Reverting the scale and offset applied to the damage history can be done
in one step, using a few less temporary allocations by passing the
offset right away to a new scale_offset_and_clamp_region() function.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
Since the damage history region is tracked per-view, all the regions it
includes should be inside the current view anyway, so don't
unnecessarily intersect that region with the view.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
Since we now check for the buffer age before setting up the
fb_clip_region, that region will be set to the full extents of the view
in case the buffer age is invalid. This in turn means we don't have to
do this again later and can simply fill the damage history with the
fb_clip_region that's already set for us.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
Since a NULL redraw_clip means that a full view redraw should be done
and an empty redraw clip may never be set (see the width/height checks
in clutter_stage_view_add_redraw_clip()), the fb_clip_region should
always be set to a reasonable region that's either the whole view or
individual regions inside the view.
So make sure that's actually the case by warning and that the
fb_clip_region isn't empty, which allows dropping another few lines of
code.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
Right now we're checking for the DISABLE_CLIPPED_REDRAWS debug flag
after creating the fb_clip_region and adjusting the redraw_clip. That
means that if may_use_clipped_redraw was TRUE, the redraw_clip will
still be set to the region and thus cause the stage to only be partially
redrawn. Since we don't push a clip to the framebuffer though
(use_clipped_redraw is now FALSE), parts of the view will get corrupted.
To fix that, disable clipped redraws right away if the debug flag is
set. This also allows removing the may_use_clipped_redraw bool and
replacing it entirely with use_clipped_redraw.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
We already have a better way to paint the redraw clip: Painting the
damage region paints the individual rects of the clip region and not
only the bounding rect.
So stop painting an outline around the redraw clip bounding rect when
CLUTTER_DEBUG_REDRAWS is set.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
While this is meant as an optimzation to only use the scissor clip and
not the stencil buffer if there's only one clip rectangle, it's not
needed since this optimization is going to be applied to region clips
anyway inside _cogl_clip_stack_gl_flush() (see cogl-clip-stack-gl.c).
So remove the unnecessary optimization here and rely on cogl-clip-stack
to do it for us.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
This was introduced with commit 9ab338d7b6 because the clipping of
fractionally scaled redraws caused glitches, it seems like this is no
longer needed nowadays, so let's remove it.
This should make obscured region culling work a bit better for
fractionally scaled framebuffers because because we overdraw a slightly
smaller region than the actually damaged one. We still do overdraw
though since the clipping region is stored using integers and thus
any non-integer values have to be extended to the bounding rect.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
It doesn't make sense to set the redraw clip when painting the stage if
clipped redraws are disabled. That's because when visualizing the redraw
clip and any new redraws are clipped, the old visualiziations would
remain visible, leaving multiple confusing rectangles on the screen.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1113
This removes ClutterAnimation and related tests. ClutterAnimation has
been deprecated for a long time, and replacements exist and are used by
e.g. GNOME Shell since a while back.
This also disables a few relatively unrelated interactive tests, as they
rely on ClutterAnimation to implement some animations they use to
illustrate what they actually test.
As interactive tests currently are more or less untestable due to any
interaction with them crashing, as well as they in practice means
rewriting the tests using non-deprecated animation APIs, they are not
ported right now. To actually port the interactive tests, it needs to be
possible to fist interact with them.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1192
In the past, it was a odd mix of possible different types, all coalesced
into an unsigned integer. Now, hovewer, it's always a
ClutterAnimationType, so lets change the name of getter, setter and
property to what it really is.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1192
The CLUTTER_ACTOR_IN_REPARENT and the CLUTTER_IN_REPARENT flag are never
set and the logic for skipping unmap, unrealize and the emission of the
"parent-set" signal during reparents has been solved differently by
leaving out the CHECK_STATE and EMIT_PARENT_SET flags when calling
add_child_internal() and remove_child_internal().
The only place where those REPARENT flags are theoretically still useful
is in the clutter_actor_verify_map_state() debugging function, but that
is never called during reparent anyway, so simply leave the comment
regarding reparent there.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1228
The redraw clip that's painted together with the damage region has to be
copied earlier than we do right now. That's because if
PAINT_DAMAGE_REGION is enabled, buffer age is disabled and thus
use_clipped_redraw is FALSE. That means the redraw_clip is updated and
set to the full view-rect. If we copy the queued_redraw_clip after that,
it's also going to be set to the full view-rect. So copy the redraw clip
a bit earlier to make sure we're actually passing the real redraw clip
to paint_damage_region().
Also keep the queued_redraw_clip around a bit longer so it can actually
be used by paint_damage_region() and isn't freed before that.
While at it, move paint_damage_region() from swap_framebuffer() into
clutter_stage_cogl_redraw_view() so we don't have to pass things to
swap_framebuffer() only for debugging.
Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1104https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1208
It takes coordinates in stage coordinate space, and will result in
a screen cast stream consisting of that area, but scaled up by the scale
factor of the view that overlaps with the area and has the highest scale
factor.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1207
Will be used by the stage to not paint the overlays. We skip all
overlays since overlays are only ever used for pointer cursors when the
hardware cursors cannot or should not be used.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1207
Either onto a framebuffer, or into a CPU memory buffer. The latter will
use an former API and then copy the result to CPU memory. The former
allocates an offscreen framebuffer, sets up the relevant framebuffer
matrices and paints part of the stage defined by the passed rectangle.
This will be used by a RecordArea screen cast API. The former to paint
directly onto PipeWire handled dma-buf framebuffers, and the latter for
PipeWire handled shared memory buffers.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1207
A paint flag affects a paint operation in ways defined by the flags.
Currently no flags are defined, so no semantical changes are defined
yet. Eventually a flag aiming to avoid painting of cursors is going to
be added, so that screen cast streams can decide whether to include a
cursor or not.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1207
Try to bypass compositing if there is a fullscreen toplevel window with
a buffer compatible with the primary plane of the monitor it is
fullscreen on. Only non-mirrored is currently supported; as well as
fullscreened on a single monitor. It should be possible to extend with
more cases, but this starts small.
It does this by introducing a new MetaCompositor sub type
MetaCompositorNative specific to the native backend, which derives from
MetaCompositorServer, containing functionality only relevant for when
running on top of the native backend.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
Make it possible to cause the next frame to scan out directly from the
passed CoglScannout. This makes it possible to completely bypass
compositing for the following frame.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
Transitions are used for animating actors when e.g. going from/to
fullscreen, and the like. We need to know such things when deciding
whether to avoid compositing a window actor, so make add API visible to
mutter that checks whether there are any transitions active.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
click_action_query_long_press() can potentially schedule more than
one timeout, since it doesn't clear any already-existing timeout.
Make sure to clear the long press timeout before scheduling a new
one.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1188
Like the click action, it makes sense to cancel the ongoing gesture
when the action is disabled. Do so by overriding our new friend,
ClutterActorMeta.set_enabled, and canceling the gesture when disabling
the action.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1188
ClutterClickAction, like other actions, can potentially be disabled
at any time (that is not during painting). When that happens with
ClutterClickAction, it must release all timeouts and disconnect from
the stage's 'capture-event'.
Override ClutterActorMeta.set_enabled and release the click action
when the action is being disabled.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1188
Various subclasses of ClutterActorMeta need to reacto to being
disabled. Right now, however, the only way to do that is by
overriding GObject's 'notify' vfunc, and doing a string comparison
against "enabled".
Add a new vfunc to ClutterActorMeta in order to replace this bad
practice.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1187
In the unlikely case we have multiple rectangles in our selection
(selection spanning several lines, or across LTR/RTL bounds), paint each
of those instead of setting a CoglPath-based clip/fill.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1126
With the introduction of "shallow" relayouts, we are now able to enter
allocation cycles not only at the stage but also deeper down the
hierarchy if we know an actors allocation isn't affected by its children
since the NO_LAYOUT flag is set.
Now that means when queuing relayouts it's possible that
`priv->needs_allocation` gets set to TRUE for some actors down the
hierarchy, but not for actors higher up in the hierarchy. An actor tree
where that happens could look like that:
stage -> container -> container2 (NO_LAYOUT) -> textActor
With that tree, if the "textActor" queues a relayout, "container2" will
be added to the relayout hashtable of the stage and the actors "stage"
and "container" will have `priv->needs_allocation` set to FALSE.
Now if another relayout on the stage actor is queued,
`clutter_stage_queue_actor_relayout()` currently removes all the other
hashtable entries in favour of the stage entry, (wrongly) assuming that
will allocate everything. It doesn't allocate everything because in the
example above "container" has `priv->needs_allocation` set to FALSE,
which makes clutter_actor_allocate() return early before allocating its
children, so in the end "container2" will never get a new allocation.
To fix this, stop flushing the relayout hashtable when queuing a
stage-relayout and still add new entries to the hashtable if a stage
relayout is already queued to make sure we still go through all the
previously queued "shallow" relayouts. That shouldn't hurt performance,
too, because as soon as an actor got allocated once, it doesn't need an
allocation anymore and should bail out in clutter_actor_allocate() as
long as it's absolute position didn't change.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1173
Disabling a click action after a button-press but before a
button-release is captured makes ClutterClickAction connect to
captured-event and never disconnect.
This change fixes it by making sure the captured-event is only
processed if the action is still enabled, otherwise releasing
the action (reset state) and propagating the event.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1170
Nothing should ever disable an actor modifier (e.g. effect) during the
paint sequence, nor should any actor be set or unset on it. If this
would happen, log warnings so that it can be tracked down.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1166
When selecting the pick regions for an actor we were not considering
whether the actor was allocated and that was causing issues where the
preferred width/height of the actor was used when deciding whether
the actor should be considered as a pick target.
Check if the actor has a valid allocation, in addition to being mapped
and being in pick mode, in clutter_actor_should_pick_paint().
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169
The input method can assign a negative value to
clutter_input_method_delete_surrounding() to move the cursor to the left.
But Wayland protocol accepts positive values in delete_surrounding() and
GTK converts the values to the negative ones in
text_input_delete_surrounding_text_apply().
https://gitlab.gnome.org/GNOME/mutter/issues/539
Fix a regression that got introduced with
c483b52d24 where we started passing the
redraw_clip to paint_stage() instead of creating a temporary view_region
for unclipped redraws: In case we detect an invalid buffer age, we fall
back to doing an unclipped redraw after we passed the first check
setting up may_use_clipped_redraw. That means we didn't reset the
redraw_clip to the view_rect, and we're now going to redraw the stage
using the original redraw clip even though we're swapping the full
framebuffer without damage.
To fix that, check for the buffer age before setting up the
fb_clip_region and the redraw_clip and set may_use_clipped_redraw to
FALSE if the buffer age is invalid, too. This ensures the redraw_clip is
always going to be correctly set to the view rect when we want to force
a full redraw.
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/1128
When calculating the resource scale of a clone source, we might end up
in situations where we fail to do so, even though we're in a paint. A
real world example when this may happen if this happens:
* A client creates a toplevel window
* A client creates a modal dialog for said toplevel window
* Said client commits a buffer to the modal before the toplevel
If GNOME Shell is in overview mode, the window group is hidden, and the
toplevel window actor is hidden. When the clone tries to paint, it fails
to calculate the resource scale, as the parent of the parent (window
group) is not currently mapped. It would have succeeded if only the
clone source was unmapped, as it deals with the unmapped actor painting
by setting intermediate state while painting, but this does not work
when the *parent* of the source is unmapped as well.
Fix this by inheriting the unmapped clone paint even when calculating
the resource scale.
This also adds a test case that mimics the sequence of events otherwise
triggered by a client. We can't add a Wayland client to test this, where
we actually crash is in the offscreen redirect effect used by the window
dimming feature in GNOME Shell.
Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/808https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1147
This is so that cogl-trace.h can start using things from cogl-macros.h,
and so that it doesn't leak cogl-config.h into the world, while exposing
it to e.g. gnome-shell so that it can make use of it as well. There is
no practical reason why we shouldn't just include cogl-trace.h via
cogl.h as we do with everything else.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1059
This adds a new frameclock tracing mark for a single cycle of the frame
clock. Doing so allows Sysprof to potentially do more with the information
that happens during the frameclock. For example, we can now find
allocations that happen while the frame clock is advancing.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1088
offset_scale_and_clamp_region() creates a new region resulting in
view_damage which at this point is the only thing left pointing to what
originally was fb_damage getting overwritten and being leaked.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1089
The stage window handled the redraw clip in a global manner; this would
interfere if we want to paint views individually as it'd mean
intersecting views (i.e. mirrored monitors) would loose the redraw clip
once the first view was painted. It also is awkward to have a global
state for something that is built up before redrawing, and only really
valid during paint, due to buffer damage history.
This commits removes all redraw clip management from the stage window,
moving it all into the stage views. When a redraw clip is added to the
stage, every affected view will get the same redraw clip added to it,
and eventually when painted, the stage window (ClutterStageCogl) will
retrieve the redraw clip for each view as it repaints them.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
Instead of users fetching it via `clutter_stage_get_redraw_clip()`, pass
it via the paint context. This is helpful as it is only valid during a
paint, making it more obvious that it needs to be handled differently
when there is no redraw clip (i.e. we're painting off-screen).
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
Add a helper that scales and clamps a region, aimed to be used when
transforming between framebuffer coordinate space and view coordinate
spaces.
This helps readability by moving out the verbose for loops that deals
with the individual rects of a region to the helper, making the logic
where it's used much simpler.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
The 'have_clip' variable has repeatedly confused me to meaning that
there is a clip. What it actually means is that the effective clip
covers the whole view; the 'redraw_clip == NULL' meaning full redraw is
an important implementation detail for the context, and makes the
intention of the variable unclear; especially since we will after a
couple of blocks will *always* have a clip, just that it covers the
whole view.
Rename the variable to 'is_full_redraw' and negate the meaning, aiming
to make things a lot more clear.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
When calculating the fallback framebuffer clip region, which should be
the region in framebuffer coordinates, we didn't scale the view layout
with the view framebuffer scale, meaning for any other scale than 1,
we'd draw a too small region of the view. Fix this by just using the
size of the framebuffer directly, avoiding any scale dependent
calculation all together.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
We'll expect a swap event if any of the view paints resulted in a swap;
make the logic dealing with this clearer by making changing the less
vilible '|| swap_event' postfix with a up front '|=' operator.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
Prior to this commit the stage was drawn separately for each logical
monitor. This allowed to draw different parts of the stage with
different transformations, e.g. with a different viewport to implement
HiDPI support.
Go even further and have one view per CRTC. This causes the stage to
e.g. draw two mirrored monitors twice, instead of using the same
framebuffer on both. This enables us to do two things: one is to support
tiled monitors and monitor mirroring using the EGLStreams backend; the
other is that it'll enable us to tie rendering directly to the CRTC it
will render for. It is also a requirement for rendering being affected
by CRTC state, such as gamma.
It'll be possible to still inhibit re-drawing of the same content
twice, but it should be implemented differently, so that it will still
be possible to implement features requiring the CRTC split.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
This only needs to be initialized once but is in the hot path of creating
new paint nodes (for which we create many). Instead, do this as part of
the clutter_init() workflow to keep it out of the hot path.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1087
When calculating regions, a lot of temporary allocations are created. For
the array of rects (which is often a short number of them) we can use
stack allocations up to 1 page (256 cairo_rectangle_int_t). For building
a region of rectangles, cairo and pixman are much faster if you have all
of the rectangles up front or else it mallocs quite a bit of temporary
memory.
If we re-use the cairo_rectangle_int_t array we've already allocated (and
preferably on the stack), we can delay the creation of regions until after
the tight loop.
Additionally, it requires fewer allocations to union two cairo_region_t
than to incrementally union the rectangles into the region.
Before (percentages are of total number of allocations)
TOTAL FUNCTION
[ 100.00%] [Everything]
[ 100.00%] [gnome-shell --wayland --display-server]
[ 99.67%] _start
[ 99.67%] __libc_start_main
[ 99.67%] main
[ 98.60%] meta_run
[ 96.90%] g_main_loop_run
[ 96.90%] g_main_context_iterate.isra.0
[ 96.90%] g_main_context_dispatch
[ 90.27%] clutter_clock_dispatch
[ 86.54%] _clutter_stage_do_update
[ 85.00%] clutter_stage_cogl_redraw
[ 84.98%] clutter_stage_cogl_redraw_view
[ 81.09%] cairo_region_union_rectangle
After (overhead has much dropped)
TOTAL FUNCTION
[ 100.00%] [Everything]
[ 99.80%] [gnome-shell --wayland --display-server]
[ 99.48%] _start
[ 99.48%] __libc_start_main
[ 99.48%] main
[ 92.37%] meta_run
[ 81.49%] g_main_loop_run
[ 81.49%] g_main_context_iterate.isra.0
[ 81.43%] g_main_context_dispatch
[ 39.40%] clutter_clock_dispatch
[ 26.93%] _clutter_stage_do_update
[ 25.80%] clutter_stage_cogl_redraw
[ 25.60%] clutter_stage_cogl_redraw_view
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1071
g_signal_emit_by_name() is used to emit signals on ClutterContainer when
actors are removed or added. It happens to do various interface lookups
which are a bit unneccessary and can allocate memory.
Simply using emission wrappers makes all of that go away.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1083
Add API to ClutterSeat that allows inhibiting the unsetting of the
pointer focus surface. This can be useful for drawing custom cursor
textures like the magnifier of gnome-shell does.
In the future this API should also control unsetting of Clutters
focus-actor, not just the focus surface, that's not really needed right
now since we never unset the focus-actor anyway.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1077
Which offscreens actor rendering only in cases where it hasn't changed for
2 frames or more. This avoids the performance penalty of offscreening an
actor whose content is trying to animate at full frame rate. It will
switch automatically.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1069
If the transform matrix is an identity, then positioning wont change and
we can avoid creating the transform node altogether. This is based on
a similar find in GTK today while reducing temporary allocations.
This cuts the number of transforms created in clutter_actor_paint() by
about half under light testing of GNOME Shell from 6.8% to 2.4% of
allocations.
Before:
ALLOCATED TOTAL FUNCTION
[ 20.4 MiB] [ 21.20%] clutter_actor_paint
[ 11.0 MiB] [ 11.45%] clutter_paint_node_paint
[ 6.6 MiB] [ 6.84%] clutter_transform_node_new
[ 2.5 MiB] [ 2.61%] clutter_actor_node_new
After:
ALLOCATED TOTAL FUNCTION
[ 33.4 MiB] [ 24.12%] clutter_actor_paint
[ 26.2 MiB] [ 18.91%] clutter_paint_node_paint
[ 3.4 MiB] [ 2.43%] clutter_actor_node_new
[ 3.3 MiB] [ 2.41%] clutter_transform_node_new
Allocation amounts will have differed due to different amounts of running
time, but the % of allocations has now dropped below
clutter_actor_node_new() which should be expected.
https://gitlab.gnome.org/GNOME/mutter/issues/1056
And the corresponding getter. This property returns FALSE by default
and must be overridden by subclasses. This will allow gnome-shell to
hook up specific behavior that should not happen on mouse+keyboard
setups.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1044
If an actor sets flag `CLUTTER_ACTOR_NO_LAYOUT` then that means it
is (or should be) unaffected by `queue_relayout` calls in its children.
So we can avoid propagating `queue_relayout` all the way up to the stage
and avoid a full stage relayout each time.
But those children whose parent has `CLUTTER_ACTOR_NO_LAYOUT` still need
to be allocated at some point. So we do it at the same point where it
happened before. Only we now queue a *shallow* relayout so the `allocate`
run on the next frame doesn't need to descend the whole actor tree anymore.
Only a subtree and hopefully very small.
For free-floating and top-level actors this provides a measurable
performance benefit. According to Google Profiler, calls to
`_clutter_stage_maybe_relayout` are now so cheap that they no longer show
up in performance profiles.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/575
The private function `_clutter_input_device_update()` is not currently
exported.
This function calls `_clutter_input_device_set_actor()` which updates
the `ClutterActor` under the pointer, so making that function available
outside of Clutter will allow to make sure the pointer device actor is
updated prior to do picking.
Also, now that the functions is exported to the upper layers, drop the
underscore suffix from the function name.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1026
Right now the CONTENT_SIZE request mode for a ClutterActor is only
respected by `clutter_actor_get_preferred_size()`, but not by
`get_preferred_width()` and `get_preferred_height()`. Those simply try
to ask the layout manager and will return [0, 0] for actors without
children. So be consistent and also return the content size in those two
functions.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1019
As recommended by the docs for `g_settings_schema_source_get_default`:
> The returned source may actually consist of multiple schema sources
> from different directories, depending on which directories were given
> in XDG_DATA_DIRS and GSETTINGS_SCHEMA_DIR. For this reason, all lookups
> performed against the default source should probably be done recursively.
Now it's actually found and works again, including subpixel font smoothing.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1447https://gitlab.gnome.org/GNOME/mutter/merge_requests/1017
ClutterActors width and height can be reset to automatically use the
preferred (calculated) value by setting the width or height to -1, so
far this only works by setting it using `clutter_actor_set_width()` or
`clutter_actor_set_height()`, make sure it can also be done using the
"width" and "height" GObject properties.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1018
Some ClutterOffscreenEffect subclasses, such as ClutterBrightnessContrastEffect,
early-return FALSE in pre-paint before chaining up. It's an important optimization
that avoids creating or updating the offscreen framebuffer.
However, if an offscreen framebuffer already exists by the time pre-paint fails,
it will be used *without* repaint the actor over it. That causes an old picture
of the actor to be displayed.
Fix that by always clearing the offscreen framebuffer when pre-paint fails.
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/810https://gitlab.gnome.org/GNOME/mutter/merge_requests/992
When changing the 'enabled' property and disabling the offscreen effect,
it doesn't make sense to preserve the offscreen framebuffer. It's not
drawing, after all.
Furthermore, because ClutterOffscreenEffect only checks if the offscreen
framebuffer exists to decide whether or not to redraw, keeping the fbo
alive is a waste of resources.
Clear the offscreen framebuffer when the effect is disabled or enabled.
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/810https://gitlab.gnome.org/GNOME/mutter/merge_requests/992
FLT_MIN is the smallest *positive* number above 0 that can be
represented as floating point number. If this is used to initialize the
maximum x/y coordinates of a rectangle, this will always be used if all
x/y coordinates of the rectangle are negative. This means that picking
at 0,0 will always be a hit for such rectangles.
Since mutter creates such a window for server side decorations on X11,
this window will always be picked at 0,0 preventing clicking/hovering
the activities button in gnome-shell at that coordinate.
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/893
When rendering on-stage, it might be necessary to push offscreen
framebuffers to the paint context by external consumers, such as
GNOME Shell effects.
Expose clutter_paint_context_push|pop_framebuffer().
https://gitlab.gnome.org/GNOME/mutter/merge_requests/955
They have been deprecated for a long time, and all their uses in clutter
and mutter has been removed. This also removes some no longer needed
legacy state tracking, as they were only ever excercised in certain
circumstances when there was sources (pipelines or materials) on the now
removed source stack.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
Stop using API that uses the implicit Cogl framebuffer stack, (e.g.
cogl_push_matrix()) and replace usage by the corresponding API taking an
explicit framebuffer (e.g. cogl_framebuffer_push_matrix()).
For offscreens etc, the offscreen framebuffer is still pushed to and
popped from the Cogl framebuffer stack, so that paint nodes still draw
to the right framebuffer.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
While we still push and pop to the Cogl framebuffer stack, as so is
still needed to render the actors correctly, don't use the API using the
implicit framebuffer stack ourself in the offscreen effect code.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
clutter_paint_node_get_framebuffer() fell back on
cogl_get_draw_framebuffer() when the root node didn't have a custom
get_framebuffer vfunc. As this relies on deprecated implicit Cogl stack
API, it needs to go away, so handle this in the caller that knows more
about the context.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
Instead of using the intermediate stage state "active framebuffer" to
find the framebuffer a paint eventually targets, use the "base
framebuffer" of the paint context, as this more correctly corresponds to
the end point of a paint. It also means we can then later remove this
intermediate state from the stage.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
Instead of pushing and popping the Cogl framebuffer stack, use the
framebuffer passed around using the pick context. This removes usage of
the deprecated framebuffer stack when picking.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
Rendering off stage we never cull, and previously this was checked by
comparing the "active framebuffer" of the stage, to the current
framebuffer in the cogl stack. Replace this by checking whether the
current paint context is currently drawing on stage or not.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
Just as with painting, add a pick context that carries pick related
temporary state when doing actor picking. It is currently unused, and
will at least at first still carry around a framebuffer to deal track
view transforms etc.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
When painting, actors rely on semi global state tracked by the state to
get various things needed for painting, such as the current draw
framebuffer. Having state hidden in such ways can be very deceiving as
it's hard to follow changes spread out, and adding more and more state
that should be tracked during a paint gets annoying as they will not
change in isolation but one by one in their own places. To do this
better, introduce a paint context that is passed along in paint calls
that contains the necessary state needed during painting.
The paint context implements a framebuffer stack just as Cogl works,
which is currently needed for offscreen rendering used by clutter.
The same context is passed around for paint nodes, contents and effects
as well.
In this commit, the context is only introduced, but not used. It aims to
replace the Cogl framebuffer stack, and will allow actors to know what
view it is currently painted on.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
We do check the clip area as an optimization to know which input devices
might need updating state after a relayout (Assuming that if a device is
under a non-painted area, it's actor beneath didn't change).
Use the clip region for this, and drop the last usage of the clip region
bounds.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/867
This commit was split out from `cleanup: Use g_clear_signal_handler()
where possible` as it fixes an actual signal leak and should therefore
get backported to stable releases.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/940
This is inspired by 98892391d7 where the usage of
`g_signal_handler_disconnect()` without resetting the corresponding
handler id later resulted in a bug. Using `g_clear_signal_handler()`
makes sure we avoid similar bugs and is almost always the better
alternative. We use it for new code, let's clean up the old code to
also use it.
A further benefit is that it can get called even if the passed id is
0, allowing us to remove a lot of now unnessecary checks, and the fact
that `g_clear_signal_handler()` checks for the right type size, forcing us
to clean up all places where we used `guint` instead of `gulong`.
No functional changes intended here and all changes should be trivial,
thus bundled in one big commit.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/940