d42f1873fc introduced a semi circular
reference between the CoglFramebuffer, and CoglJournal, where
CoglJournal would keep a reference on the CoglFramebuffer when there
were any entries in the journal log.
To avoid risking leaking these objects indefinitely, when freeing
objects without doing anything that triggered a flush, CoglFramebuffer
had a "filter" on cogl_object_unref() calls, which knew
about under what conditions CoglJournal had a reference to it. When it
could detect that there were only the journal itself holding such a
reference, it'd flush the journal, effectively releasing the reference
the journal held, thus freeing itself, as well as the journal.
When CoglFramebuffer was ported to be implemented using GObject instead
of CoglObject, this "filter" was missed, causing not only awkward but
infrequent leaks, but also situations where we'd flush journals when
only the journal itself held the last reference to the framebuffer,
meaning the journal would free the framebuffer, thus itself, in the
middle of flushing, causing memory corruption and crashes.
A way to detect this, by asserting on CoglObject reference count during
flush, is by adding the `g_assert()` as described below, which will
assert instead cause memory corruption.
void
_cogl_journal_flush (CoglJournal *journal
{
...
_cogl_journal_discard (journal);
+ g_assert (journal->_parent.ref_count > 0);
...
}
Fix this by making CoglFramebuffer the owner of the journal, which it
already was, and remove any circle referencing that was there before, as
it is not needed given that the CoglFramebuffer pointer is guaranteed to
be valid for the lifetime of CoglJournal as the framebuffer is the owner
of the journal.
However, to not miss flushing before tearing down, which is important as
this flushes painting calls to the driver that is important for e.g.
using the result of those journal entries, flush the journal the first
time cogl_framebuffer_dispose() is called, before doing anything else.
This also adds a test case. Without having broken the circular
reference, the test would fail on g_assert_null (offscreen), as it would
have been "leaked" at this point, but the actual memory corruption would
be a result of the `cogl_texture_get_data()` call, which flushes the
framebuffer, and causes the 'mid-flush' destruction of the journal
described above. Note that the texture keeps track of dependent
framebuffers, but it does not hold any references to them.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1474
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1735>
Currently, the documentation for NotifyPointerAxis() just mentions that
a smooth scroll event is emitted.
However, this is not entirely correct. For each NotifyPointerAxis(),
mutter emits an emulated discrete scrolling event based on the
submitted accumulated smooth scrolling deltas.
Additionally, it doesn't mention how the motion deltas need to be
interpreted.
So, document the NotifyPointerAxis() notification better by mentioning
the emulation of discrete scroll events, how these discrete scroll
events are calculated and how the motion deltas need to be interpreted.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1727>
When a remote desktop user emits a virtual smooth scrolling event, a
smooth scroll event, that is not emulated, is emitted and on occasion
a discrete scroll event, that is emulated, is emitted.
As base for the discrete scrolling event, the smooth scrolling steps
are accumulated.
When the accumulated smooth scrolling steps surpass the
DISCRETE_SCROLL_STEP, the discrete scrolling event is emitted.
Currently, mutter uses for DISCRETE_SCROLL_STEP the value 10, which is
a terrible value to work with, especially for high resolution mouse
wheels.
When a triple resolution mouse wheel is used, each scrolling step will
have the value 3 1/3.
Three of such events won't however surpass the DISCRETE_SCROLL_STEP.
To fix this situation, add DBL_EPSILON to the calculation step, when
checking for the discrete scroll event to ensure that 3 smooth scroll
events, with each having the value 3 1/3, emit a discrete scrolling
event.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1727>
MetaVirtualInputDeviceX11 currently doesn't handle smooth scroll events
at all.
So, if a user of the remote desktop API uses smooth scroll events, then
only the wayland backend handles these events.
The user of the remote desktop API however, might not know which
backend is being used and actually the user should not even have to
care about it.
Actual smooth events cannot be emulated in the X11 events.
What can be done however is accumulating smooth events and then when
the accumulated steps surpass the DISCRETE_SCROLL_STEP value, emit a
discrete scroll event.
So, do exactly that, to make smooth scroll events work when the remote
desktop API is used with the x11 backend.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1727>
With 734a185915 an optimization was
introduced to only pick on events which can actually cause the pointer
to move. In case of touch events, the first event (TOUCH_BEGIN) will
already move the touchpoint though, and we'll send our crossing
CLUTTER_ENTER event to the actor this TOUCH_BEGIN happened on.
So fix this embarrassing bug that caused touch input to break by also
picking to find an event-actor on TOUCH_BEGIN events.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1733>
Aside from ENTER/LEAVE, there are only two kinds of events that can move
the pointer, motion events and touch update events. Everything else
keeps the pointer at it's current position.
The reason we pick inside _clutter_process_event_details() is that we
want to set the event actor. Now if an event can't move the pointer, it
also can't change the event actor (well, it can subsequently by
triggering changes to the scenegraph, but that's handled elsewhere), so
there's no need to pick a new event actor when we get those events.
Instead, simply reuse the actor that's already associated with the
current input device as the event actor for non MOTION/TOUCH_UPDATE
events.
Events where a device or a touchpoint goes away (like DEVICE_REMOVED or
TOUCH_END/CANCEL) also affect picking, they don't need a repick, but
instead the actor associated with the device/touchpoint needs to be
unassociated. This is ensured by invoking remove_device_for_event() on
those events and will not be affected by this change.
This should improve performance while scrolling quite a bit, since
scroll events come in unthrottled and we now no longer do a repick on
each one of those.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1729>
Given X11 nature, the pointer "leaves" the stage anytime it wanders into
a client window, or any other areas that are not deemed part of the
stage input region.
Yet we want to stay correct in those situations, e.g. have the clutter
side reasonably in sync, picking and highlighting to work properly, etc.
In order to achieve that, emulate motion events on XI_RawMotion. These
are as much throttled as our pointer tracking for a11y, in order to avoid
too many XIQueryPointer sync calls. This emulation only kicks in anytime
that X11 notifies us that we are not "on" the stage.
This replaces some sync_pointer() calls in GNOME Shell code that are
there just to compensate for this trait of X11, e.g. in the message tray
code.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1659>
Ensure we issue a motion event for the current pointer position,
as there might be situations where compositor modals get X grabs
from other clients stacked on top, or missed events in between
otherwise.
Ensure the Clutter state is still up-to-date afterwards here. This
replaces some sync_pointer() calls done in GNOME Shell code, always
done after modality changes.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1659>
Do these Wayland operations (that apply on both native and nested backends)
in the MetaCompositorServer subclass. We want to add more backend specific
behavior here in the future.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1659>
In the case that DnD is performed and succeeds, we want to release
the grab early, and let the transfer IPC happen in the back. For
that to happen without a hitch, drag source and offer must be left
related to each other after undoing the grab, even though the default
ungrabbing code does that automatically (indirectly, by unsetting the
drag focus).
In these cases, we used to manually unset the current source, so
this decoupling was skipped. Notably, one missed case is X11 DnD,
so we might end up with the situation there that DnD did succeed,
transfer is ongoing, but the source and offer are already decoupled,
this confused the machinery and missed the finishing XdndFinished
to be emitted to the X11 drag source.
The prior commits prepared for this source/offer decoupling being
a manual operation, this commit avoids doing this automatically
when ungrabbing.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1720>
This object is just being detached, with no code unref'ing it. Do
this whenever the XDnD selection goes unowned, usually a good
indication that the drag source no longer is one.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1720>
g_set_error_literal() asserts that the provided message is not NULL.
If it is NULL, the function is entirely no-op.
This resulted in a NULL dereference of the GError, which remained
NULL in this case, when trying to print a warning in
clutter_stage_cogl_redraw_view().
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1715>
We might have a stage view listener attached to the stage itself if the
actor didn't have a suitable frame clock when the actor was associated
with the timeline. We'd then listen to stage-views-changed signals on
the stage itself to be able to attach to a frame clock when one
appeared.
What went wrong is that if an actor that didn't have a frameclock was
associated with a timeline, but then destroyed, the timeline would
disassociate itself from the actor, but it'd still listen on the
stage-views-changed signal on the stage. This would be in itself
harmless, until the timeline itself is destroyed, as at this point, it
wouldn't clean up the stage-views-changed listener on the stage, as it's
assumed to only be valid when there is an actor attached.
Fix this issue by cleaning up the stage's stage-views-changed listener
when the actor is destroyed, as we wouldn't be able to make use of it by
then anyway.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3323
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1719>
PipeWire recently introduced busy buffers, which actually fixes the last remaining
issue that blocked us from downgrading these cogl_framebuffer_finish() calls into
cogl_framebuffer_flush() ones.
Switch to cogl_framebuffer_flush() in all three stream sources.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1701>
The 0.3.21 release includes busy buffers, which are a requirement
for us to switch to cogl_framebuffer_flush() in the next commit.
Bump pipewire dependency to 0.3.21, and adjust CI to build it from
the corresponding tag.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1701>
Before this commit, next presentation time could end up behind now_us or
ahead of now_us depending on how presentation times happened to be
aligned relative to integer multiples of refresh_interval_us. It's not
clear whether this was originally intended because even if it the next
presentation time ends up behind now_us, it is moved ahead by a while
loop down below in this function.
Even though this difference in behavior didn't really matter, it made
reasoning about the subsequent branches more complex. It would also
potentially introduce bugs if the logic was to be modified. So this
commit makes it so next presentation time is always ahead of now_us.
It also adds a comment with a graph detailing the computations, and
adjusts the variable names to drop unfortunate terminology mistakes.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1707>
Last presentation time is mainly used to make sure predicted
presentation time is aligned with display refreshes. Even if it went
back in time, there will be no issue as next presentation time takes
current time into account. Synthetic presentation time is not exactly
aligned with display refreshes, so using it would only result in
inconsistent animations.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1707>