Commit Graph

7664 Commits

Author SHA1 Message Date
Daniel van Vugt
da3ff9f6d0 clutter/frame-clock: Correct indentation
To resolve CI warnings.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1972>
2021-08-24 16:43:49 +08:00
Jonas Ådahl
18c414cca4 clutter/stage-view: Initialize view as damaged and awaiting frame
Make sure that when we've recreated views that we'll actually paint a
new frame for it. This was very rarely a problem, as views tend to
result in getting damage etc being queued as side effects of various
things, like layout, but e.g. when running certain tests, this might not
happen. There is no situation where we want to create a new view that
should remain unpainted, so just make sure we initialize it to become up
to date.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1947>
2021-08-22 17:06:53 +00:00
Ivan Molodetskikh
13a2a33257 clutter: Add clutter_stage_paint_to_content ()
Used in the new screenshot UI.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1899>
2021-08-22 12:44:38 +00:00
Florian Müllner
9252b7c6b4 clutter/text: Don't query preferred size without allocation
The size request functions query the resource scale, which hits
an assert if headless. The returned sizes are already only used
when clutter_actor_has_allocation() is true, so this doesn't
change the condition for calling either redraw or relayout.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4522

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1956>
2021-08-05 13:20:54 +02:00
Carlos Garnacho
a4c50ad123 clutter: Add COGL_HAS_TRACING checks around tracing code
This code sneaked unconditionally, even though we can disable
tracing code with -Dprofiler=false. Add some COGL_HAS_TRACING
checks so that this code is also optionally built.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1951>
2021-08-02 17:15:10 +02:00
Jonas Ådahl
6b1f49c153 clutter/actor: Optionally trace allocations
If 'detailed-trace' is enabled, trace the allocation of every actor every
frame, and pass along the type and name of the actor to sysprof.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1700>
2021-07-29 15:37:48 +02:00
Jonas Ådahl
5c7795dfa9 clutter/actor: Optionally trace painting
If 'detailed-trace' is enabled, trace the painting of every actor every
frame, and pass along the type and name of the actor to sysprof.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1700>
2021-07-29 15:37:29 +02:00
Jonas Ådahl
9d22e7153c clutter/actor: Sneakily remove the g from the debug names gchar
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1700>
2021-07-29 15:37:12 +02:00
Jonas Ådahl
6a0dd2a0fa clutter/actor: Always generate the same debug name
It's useful also for non-debug builds to have a more proper name for
actors, e.g. when tracing.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1700>
2021-07-29 15:37:12 +02:00
Jonas Ådahl
796eb005bc clutter/main: Add 'detailed-trace' debug flag
Will be used to trace a lot more, and with more details, and thus may
have a larger impact on what is actually measured. This potential impact
is the reason for enabling only when needed.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1700>
2021-07-29 15:37:12 +02:00
Jonas Ådahl
96b1ebb2fd clutter/layer-paint-node: Handle failure to allocate offscreen
The failure to allocate was not properly handled, causing crashes later
on due to the offscreen being NULL.

 #0  cogl_gl_framebuffer_bind (target=36160, gl_framebuffer=0x0)
 #1  _cogl_driver_gl_flush_framebuffer_state (...)
 #2  cogl_context_flush_framebuffer_state (read_buffer=0x55f48f386780, draw_buffer=0x55f48f386780, ...)
 #3  cogl_framebuffer_clear4f (framebuffer=0x55f48f386780, ...)
 #4  clutter_layer_node_pre_draw (...)
 #5  clutter_paint_node_paint (...)

...

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1942>
2021-07-29 11:16:21 +00:00
Jonas Ådahl
5e5c7fe1af clutter/layer-paint-node: Fix variable naming
It's elsewhere in the file referred to as lnode. No idea what "res"
means.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1942>
2021-07-29 11:16:21 +00:00
Carlos Garnacho
c80ef12c79 clutter: Remove unused EGL header
This just pulled cogl headers, so not very useful.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
1f67e4650c clutter: Remove leftovers from backend code in build system
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
229b52872e clutter: Drop generation of x11 pkgconfig file
This is no longer needed, at least from the Clutter API perspective.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
dc6d3cead2 backends: Shuffle ClutterBackendX11 code into MetaClutterBackendX11
We have a Clutter implementation of the X11, just to subclass it in
our backends. Move the implementation entirely to src/backends/x11.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
1e84c00d86 clutter: Drop dead X11 code
We don't use the ClutterBackendX11 direct constructor.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
7fcc7a6edb clutter: Drop Xsettings client code
We only listen to it for 2 settings (drag threshold, double click
time), and we already have the stock ClutterSettings object tracking
the source of these. This code is redundant.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
8f839b2f9c clutter: Move ClutterStageCogl[View] code to src/backends
This is now MetaStageImpl in backend code.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
7712b58170 clutter: Export private function to get debug flags
We're shuffling some code into src/backends, that needs knowing
about these flags to minimize immediate refactors.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
dd9d40aedb clutter: Make ClutterStageView API public to mutter
All subclasses and stage implementations will come from src/backends,
so this internal API must be accessible there.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
5beba8b99b clutter: Make ClutterDamageHistory API public to mutter
We are moving things to src/backends, make this helper object able
to be used there. This is a temporary measure as ClutterDamageHistory
itself should be moved too.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Carlos Garnacho
c58909dc0f clutter: Demote CLUTTER_NOTE to g_debug in clutter-stage-cogl.c
This code is being shuffled out of Clutter code, so cut the ties with
it before doing that.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1862>
2021-07-16 19:08:06 +02:00
Jonas Ådahl
07384e18c5 clutter: Remove clutter_init_with_args()
Not used anymore.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 11:25:21 +02:00
Daniel van Vugt
0555a5bbc1 clutter/frame-clock: Apply error diffusion (dithering) to dispatch times
But only the dispatch times used when `last_presentation_time_us == 0`
(Nvidia + Xorg).

This ensures the average dispatch interval is always precisely equal
to the refresh interval, regardless of any jitter in the mainloop.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1751,
       https://gitlab.gnome.org/GNOME/mutter/-/issues/1758,
       https://gitlab.gnome.org/GNOME/mutter/-/issues/1870

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1826>
2021-07-13 17:18:17 +08:00
Daniel van Vugt
ba1490ec9c clutter/frame-clock: Remember the refresh interval
Instead of recalculating it every time we need it. The performance
gain is not important; this is more because it will be needed in
multiple functions soon.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1826>
2021-07-13 17:18:14 +08:00
Ivan Molodetskikh
a5d1d48bf1 clutter: Add a max render time debug HUD
Not sure how to update the damage or redraw clip or something; at least
this works properly when under a constantly-redrawing window, which is
ok for debugging purposes.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
f55c9af618 clutter: Add an lg command to set max render time constant
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
565e34b4d2 clutter: Add a flag to disable heuristic max render time
Debugging purposes: allows to check if frame drops are caused by
heuristic max render time or if they are there even with the old
behavior.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
592fbee065 clutter: Compute max render time heuristically
Max render time shows how early the frame clock needs to be dispatched
to make it to the predicted next presentation time. Before this commit
it was set to refresh interval minus 2 ms. This means Mutter would
always start compositing 14.7 ms before a display refresh on a 60 Hz
screen or 4.9 ms before a display refresh on a 144 Hz screen. However,
Mutter frequently does not need as much time to finish compositing and
submit buffer to KMS:

      max render time
      /------------\
---|---------------|---------------|---> presentations
      D----S          D--S

      D - frame clock dispatch
      S - buffer submission

This commit aims to automatically compute a shorter max render time to
make Mutter start compositing as late as possible (but still making it
in time for the presentation):

         max render time
             /-----\
---|---------------|---------------|---> presentations
             D----S          D--S

Why is this better? First of all, Mutter gets application contents to
draw at the time when compositing starts. If new application buffer
arrives after the compositing has started, but before the next
presentation, it won't make it on screen:

---|---------------|---------------|---> presentations
      D----S          D--S
        A-------------X----------->

                   ^ doesn't make it for this presentation

        A - application buffer commit
        X - application buffer sampled by Mutter

Here the application committed just a few ms too late and didn't make on
screen until the next presentation. If compositing starts later in the
frame cycle, applications can commit buffers closer to the presentation.
These buffers will be more up-to-date thereby reducing input latency.

---|---------------|---------------|---> presentations
             D----S          D--S
        A----X---->

                   ^ made it!

Moreover, applications are recommended to render their frames on frame
callbacks, which Mutter sends right after compositing is done. Since
this commit delays the compositing, it also reduces the latency for
applications drawing on frame callbacks. Compare:

---|---------------|---------------|---> presentations
      D----S          D--S
           F--A-------X----------->
              \____________________/
                     latency

---|---------------|---------------|---> presentations
             D----S          D--S
                  F--A-------X---->
                     \_____________/
                      less latency

           F - frame callback received, application starts rendering

So how do we actually estimate max render time? We want it to be as low
as possible, but still large enough so as not to miss any frames by
accident:

         max render time
             /-----\
---|---------------|---------------|---> presentations
             D------S------------->
                   oops, took a little too long

For a successful presentation, the frame needs to be submitted to KMS
and the GPU work must be completed before the vblank. This deadline can
be computed by subtracting the vblank duration (calculated from display
mode) from the predicted next presentation time.

We don't know how long compositing will take, and we also don't know how
long the GPU work will take, since clients can submit buffers with
unfinished GPU work. So we measure and estimate these values.

The frame clock dispatch can be split into two phases:
1. From start of the dispatch to all GPU commands being submitted (but
   not finished)—until the call to eglSwapBuffers().
2. From eglSwapBuffers() to submitting the buffer to KMS and to GPU
   work completing. These happen in parallel, and we want the latest of
   the two to be done before the vblank.

We measure these three durations and store them for the last 16 frames.
The estimate for each duration is a maximum of these last 16 durations.
Usually even taking just the last frame's durations as the estimates
works well enough, but I found that screen-capturing with OBS Studio
increases duration variability enough to cause frequent missed frames
when using that method. Taking a maximum of the last 16 frames smoothes
out this variability.

The durations are naturally quite variable and the estimates aren't
perfect. To take this into account, an additional constant 2 ms is added
to the max render time.

How does it perform in practice? On my desktop with 144 Hz monitors I
get a max render time of 4–5 ms instead of the default 4.9 ms (I had
1 ms manually configured in sway) and on my laptop with a 60 Hz screen I
get a max render time of 4.8–5.5 ms instead of the default 14.7 ms (I
had 5–6 ms manually configured in sway). Weston [1] went with a 7 ms
default.

The main downside is that if there's a sudden heavy batch of work in the
compositing, which would've made it in default 14.7 ms, but doesn't make
it in reduced 6 ms, there is a delayed frame which would otherwise not
be there. Arguably, this happens rarely enough to be a good trade-off
for reduced latency. One possible solution is a "next frame is expected
to be heavy" function which manually increases max render time for the
next frame. This would avoid this single dropped frame at the start of
complex animations.

[1]: https://www.collabora.com/about-us/blog/2015/02/12/weston-repaint-scheduling/

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
4a4e61c1f1 clutter: Add FRAME_TIMINGS debug key
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
8d51c5ac55 clutter/frame-clock: Store dispatch timings
Will be used to adjust max render time dynamically.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
8c4a91ddd6 clutter: Add swap time and GPU rendering duration to FrameInfo
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
8c258d1de1 cogl: Add CPU swap time and GPU rendering query to CoglFrameInfo
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
3aa0e3074f clutter: Store vblank duration in ClutterFrameClock
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
d10567ea3e clutter: Add vblank duration to ClutterStageView
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
63b9ac2724 clutter: Record flip time
Will be used for intelligent max render time computation (aka repaint
scheduling).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Jonas Ådahl
8afae2ebaf clutter/xsettings-client: Zero-initialize stack struct
This fixes a warning/error:

In function 'parse_settings',
    inlined from 'read_settings' at ../clutter/clutter/x11/xsettings/xsettings-client.c:398:25:
../clutter/clutter/x11/xsettings/xsettings-client.c:202:13: error: 'buffer.byte_order' may be used uninitialized [-Werror=maybe-uninitialized]
  202 |   if (buffer.byte_order != MSBFirst &&
      |       ~~~~~~^~~~~~~~~~~

This is needed to bump the CI image from F33 to F34, which includes a
upgraded compiler.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1865>
2021-07-08 13:15:18 +00:00
Jonas Ådahl
f6f9c093ba clutter/seat: Remove backend pointer
It was unused, and having a pointer to the MetaBackend in subtypes is
more useful, so remove it.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
2021-07-07 21:03:25 +02:00
Zander Brown
4ab331e60f clutter: Drop declarations for dead functions
It seems these methods haven't existed for some time

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1916>
2021-07-05 23:01:26 +01:00
Robert Mader
8da65d7dcd clutter: Add new ClutterContent type ClutterTextureContent
A simply wrapper around `CoglTexture`, making it easy to reuse
content without roundtrip from GPU to CPU memory and back.

It optionally takes a clip rectangle which is implemented by
creating a `CoglSubTexture`. A limitation here is that floating
point clips are not supported.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1888>
2021-06-29 21:36:43 +00:00
Daniel van Vugt
97c6a68b0d clutter/stage-cogl: Ensure queued_redraw_clip is not empty
When using `CLUTTER_PAINT=damage-region` highlighting was conspicuously
absent during fullscreen animations like entering or leaving the
overview. That was because `queued_redraw_clip` was empty, because it
had been initialized from `redraw_clip == NULL` (full stage redraw).

Now we paint the damage region as the full view (which it is) instead
of nothing at all.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1890>
2021-06-09 13:56:52 +08:00
Florian Müllner
dce3aa5c01 clutter/actor: Don't emit focus signals during destruction
We rightfully unset the stage focus when the focus actor is destroyed,
which in turns results in the ClutterActor::-key-focus-out signal being
emitted on an actor that is no longer fully valid.

Avoid that emission, so consumers don't have to deal with half-disposed
actors in their handler.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4324

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1884>
2021-06-02 16:47:49 +02:00
Jonas Ådahl
b578a534a3 clutter: Remove Wayland server helper
It's a wrapper around a similar Cogl API we don't use anymore.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1863>
2021-05-18 14:03:22 +00:00
kirbykevinson
64c9c9c5b0 clutter: Make stage capture support fractional scaling
This commit adds scaling support to clutter_stage_capture_into, which
is currently used when screencasting monitors. This is supposed to
fix graphical issues that arise when using fractional scaling.

Fixes #1131

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1855>
2021-05-08 22:27:52 +07:00
Carlos Garnacho
7ba1448e5b clutter: Move pointer a11y settings management from MetaInputSettings
All pointer a11y is a fabrication of Clutter backend-independent
code, with the help of a ClutterVirtualInputDevice and with some
UI on top.

On the other hand, MetaInputSettings is a backend implementation
detail, this has 2 gotchas:
- In the native backend, the MetaInputSettings (and pointer a11y
  with it) are initialized early, before the ClutterSeat core
  pointer is set up.
- Doing this from the MetaInputSettings also means another dubious
  access from the input thread into main thread territory.

Move the pointer a11y into ClutterSettings, making this effectively
backend-independent business, invariably done from the main thread
and ensured to happen after seat initialization.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1765
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1849>
2021-05-05 19:07:26 +00:00
Jonas Dreßler
cc912614c7 clutter/paint-volume: Union paint volumes correctly using Graphene
Since commit d2f8a30625 we use Graphene to union paint volumes, it
turns out a quite severe issue snuck in during review of that MR though:
Unioned paint volumes (so paint volumes of any actors with children) now
have negative heights. Once projected to 2d coordinates they luckily are
correct again, which is why everything is still working.

The problem is that obvious once looking closer: For the y coordinates
of the unioned paint volume we confused the maximum and the minimum
points and simply used the wrong coordinates to create the unioned paint
volume.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1827>
2021-05-04 15:10:23 +00:00
Sebastian Keller
a7c4e8cefa clutter/pick-stack: Use exclusive bottom/right box borders when picking
The graphene functions used by clutter for picking assume that boxes are
inclusive in both there start and end coordinates, so picking at y
coordinate 32 for an actor with the height 32 placed at y coordinate 0
would still be considered a hit. This however is wrong as 32 is the
first position that is not in the actor anymore.

Usually this would not be much of a problem, because motion events are
rarely ever at exactly these borders and even if they are there will be
another motion event soon after. But since actors in gnome-shell usually
are aligned with the pixel grid and on X11 enter/leave events are
generated by the X server at integer coordinates, this case is much
more likely for those.

This can cause issues with Firefox which when using client side
decorations, still requests MWM_DECOR_BORDER via _MOTIF_WM_HINTS to have
mutter draw a border + shadow. This means that the Firefox window even
when using CSD is still reparented. For such windows we receive among
others XI_RawMotion and XI_Enter events, but no XI_Motion events. And
the raw motion events are discarded after an enter event, because that
sets has_pointer_focus to TRUE in MetaSeatX11. So when moving the cursor
from the panel to a maximized Firefox window the last event clutter
receives is the enter event at exactly integer coordinates. Since the
panel is 32px tall and the generated enter event is at y position 32,
the picking code will pick a panel actor and the focus will remain on it
as long as the cursor does not leave the Firefox window.

Fix this by excluding the bottom and right border of a box when picking.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4041

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1842>
2021-05-04 14:47:43 +00:00
Jonas Dreßler
2be30a3482 clutter/actor: Invalidate paint volumes of clones when ours changes
Turns out ClutterClones need a bit of extra handling as always, there's
currently nothing that invalidates a clones paint volume when the source
actors paint volume changes.

Since ClutterClones get_paint_volume() implementation simply takes the
source actors paint volume and returns that, we should make sure they
are kept in sync and invalidate the clones paint volume as soon as the
source actor gets its PV invalidated.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1829>
2021-04-19 17:56:08 +00:00
Jonas Dreßler
5a565b4258 clutter/actor: Update all last_paint_volumes before painting
Updating the last_paint_volume while painting has proven itself to be
quite prone to issues: First we had to make sure actors painted by
offscreen effects get their last_paint_volumes updated correctly (see
0320649a1c), and now a new issue turned up
where we don't update the paint volumes while a fullscreen unredirect is
happening.

To stop those issues from happening and to lay the foundation for using
the last_paint_volume for other things, update the last_paint_volume in
a separate step before painting instead of doing it in
clutter_actor_paint().

To save some resources, avoid introducing another traversal of the
scenegraph and add that step into the existing step of updating the
stage_views lists of actors. To properly update the paint volumes, we
need to do that after finishing the queued redraws, which is why we move
clutter_stage_maybe_finish_queue_redraws() to happen before the new
clutter_stage_finish_layout().

Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1699

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1773>
2021-04-12 15:18:31 +00:00