Depending on the ordering of the surface-associated resources
being destroyed, we may fall into the following situation:
- wl_surface is destroyed
- destruction notifications for the surface runs
- The MetaWaylandKeyboard attempts to synchronize the window
focus
- The MetaWindow is not destroyed yet, so the focused window
remains the same, and the MetaWaylandKeyboard keeps the same
focus MetaWaylandSurface.
- wl_surface finalizes destruction, MetaWaylandSurface now has
a NULL resource
- xdg_toplevel destructor kicks in, it unmanages the window
- The current focus window is again looked up, forced to look
a different window
- The MetaWaylandKeyboard focus now changes, tries to leave the
old surface, but it has a NULL resource already, and raises
a protocol error.
If the order is inverted, the window being unmanaged triggers a
focus change into a different window, the MetaWaylandKeyboard
triggers a focus change while the MetaWaylandSurface is still
intact, it succeeds, and the window gets properly destroyed.
In order to make this independent of the order, it makes sense
to make MetaWaylandKeyboard do like the other objects tracking
focus surfaces, and have it care of its own little parcel. The
surface destructor changed to simply unsetting the keyboard focus
to NULL (guaranteeing that the old focus is left while the surface
resource is still up), and leaving potential focus changes to
the xdg_toplevel_destructor->unmanage->update_focus paths.
Doing that alone is basically a revert of commit 228d681b, thus
is still subject to keyboard focus being lost after a popup is
destroyed. Change the approach to trigger the focus sync (and
new focus surface lookup) so it happens from xdg_popup_destructor
specifically to popups and alike xdg_toplevel.
Fixes: 228d681b ("wayland: Trigger full focus sync after keyboard focus surface is destroyed")
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2853
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3077>
Current behavior pushes a window which receives focus to the start of
the MRU list on every workspace it is on. By focusing a sticky window
the default focus on all other workspaces changes as well. This is fine
for sticky windows explicitly marked as sticky by the user but if a
window is on a secondary output and workspaces are only on the primary
output the behavior is unexpected. Instead we want the window to be the
default focus only on the current workspace but also keep those windows
in a relative MRU order to each other on all workspaces.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2681
Fixes: 058981dc1 ("workspace: Focus the default window only if no window is focused")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2909>
This avoids use-after-free when handle_start() is called following
handle_stop() during the lifetime of the MetaProfiler. This happens
on repeated profiling sessions using Sysprof.
Fixes: e16d68372 ("profiler: Add API to register profiler threads")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3076>
We need to juggle with some things here to keep key event ordering
and accounting consistent.
The keyboard internal state changes (and maybe modifier event emission)
happening through meta_wayland_seat_update() should ideally happen
from the same key events that reach the client through wl_keyboard.key,
so that wl_keyboard.modifier events are emitted in the right relative
order to other key events.
In order to fix this, we need to decide at an earlier point whether
the event will get processed through IM (and maybe be reinjected),
thus ignored in wait of IM-postprocessed events.
This means we pay less attention to whether events are first-hand
hardware events for some things and go with the event that does
eventually reach to us (hardware or IM).
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5890
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3044>
Given the presence of IMs and the different paths in event handling to reach
one of them, we cannot make guesses about whether should stick to the original
hardware-triggered event, or wait/prefer a second hand IM event that might or
might not arrive. We also have no say for other IM foci unrelated to wayland
(e.g. ClutterText) triggering the double event emission.
So go with it and maintain our own internal state for keys, we already kinda
do, but mainly for warning purposes, at the time of updating the
MetaWaylandKeyboard state.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3044>
Currently, we let the same function handle key event filtering as they
are passed to the IM, and the IM events resulting in actions like text
commit or preedit changes.
Split these two aspects into filter/process functions, and port
ClutterText to it. MetaWaylandTextInput still handles everything in
a single place, but that will be split in later commits.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3044>
This means initializing the pointer position in MetaSeatImpl
synchronously too, otherwise it's not guaranteed querying the seat state
will result in the expected position.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3071>
I have a monitor which can report two preferred modes: 5120x1440@240
and 3840x1080@60. Since they are enumerated in this order by KMS,
init_output_modes would end up using 3840x1080@60 (and it was impossible
to select any 5120x1440 mode in the GNOME display settings).
Fix this by using meta_kms_connector_get_preferred_mode, which returns
the first KMS mode with DRM_MODE_TYPE_PREFERRED.
v2:
* Use meta_kms_connector_get_preferred_mode. (Jonas Ådahl)
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3055>
This will consist of device-added events, meaning before init finishes,
we can derive some state that depends on the set of input devices
available on startup, such as cursor visibility.
This avoids cursor visibility switching between hidden and visibility
during startup.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3070>
This opens up for a possibility to handle initial events (devices
discovered on startup) during initialization, meaning we can figure out
a more correct initial state that depends on available input devices.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3070>
This is different from "warping" as it doesn't necessarily result in a
pointer motion event. This can be helpful during initializing so we can
avoid faked pointer events that would otherwise need to be special cased
to not appear as actual pointer movements.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3070>
glGetIntegerv() with GL_RED_BITS/GL_GREEN_BITS/GL_BLUE_BITS/etc. is not
supported with the GL core context, so there is no point in falling back
to that without supporting COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS,
as this will cause an GL error.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3047>
The function ensure_bits_initialized() in cogl-gl-framebuffer-fbo.c
checks for COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS whereas the same
in cogl-gl-framebuffer-back.c simply checks for the driver being
COGL_DRIVER_GL3.
Change the later to use the COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS
flag as well.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3047>
Cogl's feature COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS is required
to use the GL_FRAMEBUFFER_ATTACHMENT_* queries.
Unfortunately, the test for the availability of the private feature is
actually inverted in ensure_bits_initialized() which causes that whole
portion of code to be ignored, falling back to the glGetIntegerv()
method which isn't supported in core profiles.
As Mesa has recently started to be more strict about these, this causes
the CI tests to fail in mutter.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3047>
The stage already maintains its own list of stage-views via
clutter_stage_peek_stage_views(), it's a bit superfluous to copy that list
around all the time into priv->stage_views of ClutterActor. Let's deal with
that by returning clutter_stage_peek_stage_views() when
clutter_actor_peek_stage_views() gets called for the stage.
In order to make sure ClutterActor::stage-views-changed still gets emitted
correctly for the stage, always emit that signal on the ClutterStage when
the stage views get invalidated. This now depends on the backend only
actually invalidating the views and calling
clutter_stage_clear_stage_views() when things have actually changed, but
that should be the case.
This needs a change in one of the stage-views tests, namely the one which
tests stage-view-changed emission on the stage: Here we now see an emission
of stage-views-changed, but that signal emission actually seems correct.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
While we're now doing a fairly good job at not needing those matrices
all the time anymore, we still need it multiple times during every paint
cycle, so it definitely makes sense to introduce some caching here.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
With commit 5a565b4258, we changed
clutter_actor_finish_layout() to be not only about updating stage views,
but also take care of updating the visible_paint_volume, for that we
started doing a full tree traversal of all mapped actors.
This can be quite a performance issue, apparently especially on certain
ARM devices, where the simple tree traversal can take as long as 2ms.
This is precious time we need to paint our next frame, so lets do a bit
more work to avoid those useless traversals.
Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/2459
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
We're using clutter_stage_schedule_update() now from ClutterActor to kick
off the stage updating machinery when a redraw needs to happen.
This introduced a bunch of unnecessary calls to
clutter_stage_schedule_update() and thus
clutter_stage_view_schedule_update() when multiple actors request redraws
during the same stage update cycle, which is a very common case.
Cut off all those unnecessary calls by bailing out in
clutter_stage_schedule_update() when updates are already queued.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
Using a list of heap allocated ClutterPaintVolumes adds quite a bit of
unnecessary overhead: It means for every single redraw clip we allocate a
list and a paint volume on the heap.
Let's avoid all those heap allocations by using a GArray with static
ClutterPaintVolumes instead.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
So far our logic for queueing redraws goes like this: Actor notices that it
needs to redraw -> actor tells stage that it needs to redraw via
clutter_stage_queue_actor_redraw() -> stage collects more and more redraws
into a QueueRedrawList before the actual stage update happens -> when
that happens, the stage collects the actual redraw clips from the actors via
clutter_actor_get_redraw_clip().
The logic behind this QueueRedrawList was that by storing a list of
redraw entries on the stage, way we can avoid traversing the whole actor
tree one more time to build the redraw clip before the stage update.
These days we have clutter_actor_finish_layout() though, which is basically
exactly that, a whole actor tree traversal that happens before every stage
update.
Since we have that now, we might as well get rid of the whole dance back and
forth between ClutterStage and ClutterActor, and simply merge the logic to
queue redraws into the finish-layout step.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
If no actors have changed their positions and we're only repainting
because a window needs a repaint, the paint volumes of all actors
remain unchanged. There is no reason to redo those paint volumes on every
stage update.
So introduce caching and invalidation logic for the visible_paint_volume
that allows us to avoid a ton of matrix multiplications that right now
are happening for the whole mapped actor tree on every redraw.
Note that this removes two places where the visible paint volume is set
to an empty paint volume: This is a compromise so that we can keep
around the cached pv when hiding and showing an actor, it does "regress"
one case though: When hiding -> moving -> showing an actor, we'll now
include the old paint volume of the actor in the redraw clip on show (even
though redrawing that old region is not necessary, the actor was hidden
after all). This results in a bit of overpaint in this very specific case,
but for the sake of simplicity let's not care about that.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2679>
There were two issues with using the shape region to derive an input
region.
Firstly, the shape region is against the client rectangle, while the
surface actor needs it to be against the buffer rectangle. Fix this by
offsetting the shape region before passing it along.
Secondly, we can't just intersect the shape and input region, since that
leaves out the window decorations. Fix this by only intersecting the
input region covering the client part, and the shape region, and then
union that with the input region covering the rest.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3045>
When building mutter with -Ddebug=false, a warning appears, that
`ClutterStagePrivate *priv` is unused.
Simply remove this variable and directly use `stage->priv` in
`CLUTTER_NOTE` to get rid of this warning.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3046>
Don't try to handle things by threads enabling/disabling the main trace
context on-demand, just have a clear start/stop API. For the D-Bus API,
it becomes more straight forward, and for the persistent variant too, as
it avoids having to pass garbage input when it's known that arguments
will be discarded.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2998>