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