Commit Graph

29640 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
b3d4dbdbf1 frames/window-tracker: Reinstate dark titlebar support
Merge request !2541 [1] introduced support for integrating Mutter
frames with the dark style. This was lost after moving frames into
a separate client.

Bring that back. Don't depend on gdesktop-enums as it brings GTK3
into the header chain.

[1] https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2541

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2739>
2022-12-05 12:14:54 -03:00
Carlos Garnacho
2fb3c5a4f5 x11: Move Motif WM hints to a separate header
These are now referenced on the frames client side (in order to
track deletable state from the client window) and the mutter side
(pretty much everything else, like figuring out if a window wants
WM decorations).

It makes sense to make this a separate header, so that we don't
need to doubly define these flags/structs.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2735>
2022-12-05 12:40:53 +01:00
Carlos Garnacho
dfaa6fdc14 frames: Fix check of Motif WM hints
We use this for tracking the deletable state of the client window,
but forgot to check that the MWM_HINT_FUNCTIONS hint is set in
hints.flags before checking hints.functions.

This resulted in windows that do not specify this flag (and thus
should go with the defaults) in being mistakenly removed the close
button, as the functions flags would be typically 0 in that case.

Fixes issues with Chromium and Electron applications missing the
close button, since Chromium does this on X11.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2735>
2022-12-05 12:40:53 +01:00
Carlos Garnacho
6c0254bf02 frames: Double check _MUTTER_NEEDS_FRAME property changes
Recalculating window features is a busy thing on the Mutter side, the
different properties being (re)set will overwrite the current state
and cause some side work. Between that is the rewriting of the
_MUTTER_NEEDS_FRAME property on the window being recalculated, which
throws the frames client off, by thinking the window does actually
require a new frame.

It is not sufficient to trust that PropertyNewValue means the property
or the value are new, also double check that the window did not have
in fact a frame, and avoid the busy work if it did.

Besides the busywork that can be easily avoided, this also fixes the
window close button state being stuck if the window changed its
deletable state, since the frame being respawn managed to miss the
property change.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2735>
2022-12-04 12:09:43 +01:00
Georges Basile Stavracas Neto
381de44c5d window-actor: Use logical monitor scale on cursor scale
When using 'scale-monitor-framebuffer', it's important to use the
monitor's scale on top of the cursor texture scale. This matches
what the monitor screencast source does.

Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/1541

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2737>
2022-12-03 15:22:31 -03:00
Georges Basile Stavracas Neto
1f705ee10a window-actor: Apply resource scale to cursor position
meta_screen_cast_window_stream_src_set_cursor_metadata() relies
entirely on meta_screen_cast_window_transform_cursor_position()
to return the correct relative cursor position.

However, this function actually does not return the expected
values, since it does not apply the resource scale to the
transformed position.

Actually apply the cursor scale when calculating the cursor
position.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2737>
2022-12-03 15:21:46 -03:00
Georges Basile Stavracas Neto
4d4e8e5862 screen-cast/src: Ceil cursor buffer size
meta_screen_cast_stream_src_set_cursor_sprite_metadata() receives
the cursor sprite, position, and scale, and with that it downloads
the cursor sprite by drawing it into a separate framebuffer, then
calls cogl_framebuffer_read_pixels() in it - this is the offscren
path that is very common when using screen capturing applications
such as OBS Studio.

There's a sneaky issue in this code path though: the 'scale' value
is a float. The cursor size is then determined by multiplying the
sprite width and height - two integer variables - by scale, and
this relies on standard float-to-int conversions. This is problematic
as sometimes the rounded values disagree with what is expected by
cogl_framebuffer_read_pixels(). If the packing of either the cursor
width or height is off by one, glReadPixels() will try to write into
off bounds, which crashes.

This can be reproduced by enabling fractional scaling, setting a 150%
zoom level, on a 4K screen, and opening any commit with an image diff
in gitlab.gnome.org, all while screencasting. When hovering the new
image, the cursor sprite will be such that it triggers this code path,
and reproduces this issue.

Fix this by always ceiling the cursor sprite sizes.

Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/2542

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2736>
2022-12-03 09:25:52 -03:00
Bram Stolk
7a103bbfe9 core: Avoid generating XEvent from uninitialized data
The uninitialized fields in this event causes use of uninitialised
data as seen in valgrind:

==71864== Syscall param writev(vector[0]) points to uninitialised byte(s)
==71864==    at 0x5026EBD: __writev (writev.c:26)
==71864==    by 0x5026EBD: writev (writev.c:24)
==71864==    by 0x6482A3B: UnknownInlinedFun (xcb_conn.c:296)
==71864==    by 0x6482A3B: _xcb_conn_wait.part.0 (xcb_conn.c:551)
==71864==    by 0x6482BAF: UnknownInlinedFun (xcb_out.c:469)
==71864==    by 0x6482BAF: _xcb_out_send (xcb_out.c:470)
==71864==    by 0x6483DD7: UnknownInlinedFun (xcb_out.c:416)
==71864==    by 0x6483DD7: xcb_writev (xcb_out.c:409)
==71864==    by 0x53B79B4: _XSend (xcb_io.c:587)
==71864==    by 0x53BBF38: _XReply (xcb_io.c:679)
==71864==    by 0x53AFFC9: XQueryTree (QuTree.c:47)
==71864==    by 0x4982A5F: query_xserver_stack (stack-tracker.c:508)
==71864==    by 0x4EA1F5F: g_closure_invoke (gclosure.c:832)
==71864==    by 0x4ECFD45: signal_emit_unlocked_R.isra.0 (gsignal.c:3796)
==71864==    by 0x4EC0129: g_signal_emit_valist (gsignal.c:3549)
==71864==    by 0x4EC03B2: g_signal_emit (gsignal.c:3606)
==71864==  Address 0x287d5900 is 32 bytes inside a block of size 16,384 alloc'd
==71864==    at 0x4849444: calloc (vg_replace_malloc.c:1340)
==71864==    by 0x53A5FE8: XOpenDisplay (OpenDis.c:240)
==71864==    by 0x6100E3C: _gdk_x11_display_open (gdkdisplay-x11.c:1565)
==71864==    by 0x60CF675: gdk_display_manager_open_display (gdkdisplaymanager.c:462)
==71864==    by 0x49D59F1: open_gdk_display (meta-x11-display.c:1041)
==71864==    by 0x49D5D64: meta_x11_display_new (meta-x11-display.c:1156)
==71864==    by 0x49564AD: meta_display_init_x11_finish (display.c:743)
==71864==    by 0x495679D: on_x11_initialized (display.c:818)
==71864==    by 0x4D67558: g_task_return_now (gtask.c:1232)
==71864==    by 0x4D67782: UnknownInlinedFun (gtask.c:1301)
==71864==    by 0x4D67782: g_task_return (gtask.c:1258)
==71864==    by 0x495663C: on_xserver_started (display.c:788)
==71864==    by 0x4D67558: g_task_return_now (gtask.c:1232)
==71864==  Uninitialised value was created by a stack allocation
==71864==    at 0x49D4A59: take_manager_selection (meta-x11-display.c:640)
==71864==

To fix this, fully initialize the event struct before sending it.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2535
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2724>
2022-12-01 20:42:36 +00:00
Carlos Garnacho
20bf7f5ceb x11: Delay next resize op after sync resize until frame is painted
Since the frames are now rendered by a separate process, we no longer
can guarantee at this point that all updates were handled. Engaging
in a new synchronous resize operation will again freeze the actor,
so sometimes we are left with a not-quite-current buffer for the
frame+window surface.

In order to ensure that the right changes made it onscreen, delay
this next synchronous resize step until the moment the surface was
repainted. This avoids those glitches, while still ensuing the
resize operation ends up in sync with the pointer.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
9feac5ce62 compositor: Opt out compositor shadows from windows with frames
Let the frames client render its own shadow. In order to do that,
avoid double painting a shadow on the compositor side, and extend
the mask area of the frame, so it does unveil the (so far)
hidden frames-client-side shadows.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
84785951fd x11: Remove MetaX11WindowControl
These interfaces are no longer used, in favor of CSD-alike messaging
between the frames client and Mutter.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
92feea3033 ui: Excise old frames UI
This is no longer used, in favor of the standalone frames client.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1077
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
f2237fa0c8 x11: Add frame synchronization to window frames
There's two meanings of "frame" there! Since SSD frames are now
rendered by an external client, and there are no actual mechanism
that ensures the frame did already get painted when the client did
respond to its NET_WM_FRAME_SYNC_REQUEST request, there may be
artifacts when resizing windows.

In order to get always the best visual result, we should actually
synchronize rendering with both the client window and the window
frame window.

This commit adds these mechanisms, so a sync alarm update is
expected on both windows until further resizes are allowed, this
ensures window and frame stay in sync, even after moving rendering
elsewhere.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
782d200d6c x11: Add "source_xwindow" parameter to MetaPropValue
It will become necessary to track properties and changes from frame windows,
and it will be more convenient to have this managed by the common property
tracking mechanisms.

Add this source_xwindow parameter so property handler functions can check
whether the property belonged to the client Window or the frame Window.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
a22c66fa51 x11: Add intermediate helper function to update X11 window after sync
This function will be added some more logic in future commits.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
6a80bc3a54 x11: Decouple sync alarms from window XIDs
Store the alarms in a different hashtable, and look up the MetaSyncCounter
right away. It so far avoids the MetaWindow middle man, but will also be
simpler when each window can possibly have more than one active alarms.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
f5cb8a73d5 x11: Fix size delta calculations
This used to be a comparison between old/new width and height, but
broke long ago.

Fixes: 6e06648f - window: Refactor all move/resize operations to be in frame rect space
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
bbd988cbc5 core: Shuffle function to get description string from a frame
This will remain used (and mildly useful), so move it outside of src/ui.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
3994297429 x11: Integrate frames client into Mutter
Replace the in-process implementation of frames with the external
frames client.

When a client window is created and managed by Mutter, Mutter will
determine whether it is a window that requires decorations and
hint the creation of a frame for it by setting the _MUTTER_NEEDS_FRAME
property on the client window.

After the frames client created a window that has the _MUTTER_FRAME_FOR
property, Mutter will proceed to reparent the client window on the
frame window, and show them as a single unit.

Rendering and event handling on the frame window will be performed by
the external client, Mutter is still responsible for everything else,
namely resizing client and frame window in synchronization, and
managing updates on the MetaWindowActor.

In order to let the frame be managed by the external client, Mutter
needs to change the way some properties are forwarded to the client
and/or frame windows. Some properties are necessary to keep propagating
to the client window only, some others need to happen on the frame
window now, and some others needs to be propagated on both so they
are synchronized about the behavior.

Also, some events that were previously totally unexpected in frame
windows are now susceptible to happen, so must be allowed now.

MetaFrame in src/core/frame.c now acts as the wrapper of foreign
windows created by the frames client, from the Mutter side. Location,
size, and lifetime are still largely in control of Mutter, some
details like visible/invisible borders are obtained from the client
instead (through the _MUTTER_FRAME_EXTENTS and _GTK_FRAME_EXTENTS
properties, respectively).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
3f8e4d515e frames: Add new X11 frames client
This small X11 client takes care of creating frames for client
windows, Mutter will use this client to delegate window frame
rendering and event handling.

The MetaWindowTracker object will keep track of windows created
from other clients, and will await for _MUTTER_NEEDS_FRAME property
updates on those (coming from Mutter), indicating the need for a
frame window.

This process is resilient to restarts of the frames client, existing
windows will be queried during start, and the existence of relevant
properties checked. Mutter will be able to just hide/show
SSD-decorated windows while the frames client restarts.

The frames are created through GTK4 widgets, the MetaWindowContent
widget acts as a replacement prop for the actual client window,
and the MetaFrameHeader wraps GtkHeaderBar so that windows can be
overshrunk, but otherwise a MetaFrame is a 100% true GTK4 GtkWindow.

After a frame window is created for a client window, the
_MUTTER_FRAME_FOR property will be set on the frame window,
indicating to mutter the correspondence between both Windows.

Additionally, the pixel sizes of the visible left/right/top/bottom
borders of the frame will be set through the _MUTTER_FRAME_EXTENTS
property, set on the frame window.

In order to make the frame window behave as the frame for the
client window, a number of properties will be tracked from the
client window to update the relevant frame behavior (window title,
resizability, availability of actions...), and also some forwarding
of events happening in the frame will be forwarded to the client
window (mainly, WM_DELETE_WINDOW when the close button is clicked).

Other than that, the frames are pretty much CSD GTK4 windows, so
window drags and resizes, and window context menus are forwarded for
the WM to handle.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
ad02ef6f44 x11: Drop unnecessary check to ignore crossing events
This check dates all the way back to commit ac2aa5337d. At the time, the
window switcher was an actual X window, that could generate crossing events
if popped up under the pointer. Checking for this kind of crossing events
made sense back at the time in order not to break focus-follows-mouse as
it's been behaving for long.

But now, this UI is all Clutter widgetry, which in the worst case (X11
sessions, of course) it will update the stage window shape to make these
parts clickable. This happens in other places of code that do already
check for ignoring crossing events.

Underneath, this looked up for a Mutter-local GdkWindow of type
GDK_WINDOW_TEMP, only the main MetaFrames window matches those characteristics
nowadays, notably no window switcher popups. Since the remaining window is
never unmapped (until perhaps shutdown), the paths were functionally dead.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
2af2b5254d ui: Drop undeclared function definition from header
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:53 +00:00
Carlos Garnacho
450be1dc95 x11: Do not fake frame extents if unmanaged window asks for _NET_FRAME_EXTENTS
If the window is not managed, it's weird that it asks for _NET_FRAME_EXTENTS,
it's even weirder that mutter replies with a frame border that would only
apply if the window were managed. Stop doing the latter, and drop the
MetaUI call that calculates borders from the theme settings.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
b891f8a52c compositor: Move frame drawn x11 management to MetaSyncCounter
This is part of the same MetaSyncCounter mechanism, so move it together
on one place.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
740b8e8cce x11: Replace MetaWindow sync request handling with MetaSyncCounter
Put the helper to use, in order to lift MetaWindow itself from this
accounting. As a bonus, the data itself now moved to the MetaWindowX11
private struct, since this may only happen with X11 windows (or its
Xwayland subclass).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
235a86ab41 x11: Add standalone MetaSyncCounter helper struct
This helper struct takes care of the handling of requests and alarms
in order to satisfy NET_WM_SYNC_REQUEST. It will be necessary to
decouple rendering of windows and frames in future commits, so each
window may need its own synchronization and accounting.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
ab06232dbe compositor: Ensure atom existence initializing DnD
These only exist because GTK creates them ahead of us, stop relying
on that.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
dae981cc5c core: Avoid notifying the stack manager of frame reparents during unmanaging
This may result in a view of the stack in MetaStackManager that does not correspond
to reality, since the window is already being unmanaged, there is no point either in
notifying the stack manager about it.

This slight divergence with reality in the MetaStackManager may produce a non-accurate
view if querying its state has to go through the predicted branches. Later synchronization
with the X11 stack may even this out, but the result really depends on when it is asked.
Fixes some intermittent failures in the stacking/closed-transient-only-take-focus-parents
unit test.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
a60863838e core: Synchronize client window mapped state before showing window
The meta_window_show() method internally relies on window->mapped being
up-to-date, or attempting to focus it may fail since the window is not
mapped yet, resulting on the window being mapped, but not focused as
it would be expected.

This is moot so far, since windows with frames are created sort-of
synchronously and showing them will result in the focus attempt happening
when the window is already mapped, but things will break when this
becomes an asynchronous step.

Ensure to synchronize client state before showing, so any attempts to
focus the window are able to succeed despite the initial state when
calling meta_window_update_visibility().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
9135931385 tests: Ensure that restore-size resizes the client before maximize/unmaximize
The test does simply "wait" which apparently is not enough to ensure the
client window did resize to the expected dimensions. Use "wait_reconfigure"
and assert that the size after resize is the expected, before going further
at testing its behavior after maximize/unmaximize; it might end up with the
unexpected size after the whole operation.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Carlos Garnacho
62d91bb5fd tests: Wait for windows being mapped after show
Since having a window shown is becoming a more asynchronous process,
we should wait for the window actor being mapped after requesting
the window to be shown.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-12-01 20:10:52 +00:00
Michel Dänzer
05efcb4b21 wayland/surface: Overhaul handling of buffer use count
Move the use count from a separate MetaWaylandBufferRef struct to the
MetaWaylandBuffer class, and remove the former.

The buffer use count is now incremented already in
meta_wayland_surface_commit, since the Wayland protocol defines the
buffer to be in use by the compositor at that point. If the buffer
attachment ends up being dropped again before it is applied to the
surface state (e.g. because another buffer is committed to a
synchronized sub-surface before the parent surface is committed),
the use count is now decremented, and a buffer release event is sent if
the use count drops to 0.

Buffer release events were previously incorrectly not sent under these
circumstances. Test case: Run the weston-subsurfaces demo with the -r1
and/or -t1 command line parameter. Resize the window. Before this
change, weston-subsurfaces would freeze or abort after a few resize
operations, because mutter failed to send release events and the
client ran out of usable buffers.

v2:
* Handle NULL priv->buffer_ref in
  meta_wayland_cursor_surface_apply_state.
v3:
* Remove MetaWaylandBufferRef altogether, move the use count tracking
  to MetaWaylandBuffer itself. Much simpler, and doesn't run into
  lifetime issues when mutter shuts down.
v4:
* Warn if use count isn't 0 in meta_wayland_buffer_finalize.
* Keep pending_buffer_resource_destroyed for attached but not yet
  committed buffers. If the client attaches a buffer and then destroys
  it before commit, we ignore the buffer attachement, same as before
  this MR.
v5:
* Rebase on top of new commit which splits up surface->texture.
* MetaWaylandSurfaceState::buffer can only be non-NULL if
  ::newly_attached is TRUE, simplify accordingly.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 17:23:34 +01:00
Michel Dänzer
6e6a38342e wayland/surface: Defer meta_wayland_transaction_apply for dma-bufs
Until all dma-buf file descriptors for all buffers in the transaction
are readable, which corresponds to when the client drawing to the
buffers has finished.

This fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1162 if the
GPU & drivers support high priority contexts which can preempt lower
priority contexts.

v2:
* Also remove dma-buf fds from transaction and try applying it from
  pending_buffer_resource_destroyed. Avoids freeze due to leaving a
  GSource based on a closed fd attached if a client destroys a wl_buffer
  which is part of a transaction which was committed but not applied
  yet. (Robert Mader)
* Tweak transaction cleanup logic in wl_surface_destructor.
v3:
* Adapt to meta_wayland_dma_buf_get_source.
v4:
* Adapt to new commits using transactions for (sub-)surface destruction,
  drop code to remove destroyed surfaces from pending transactions.
v5:
* Use g_clear_pointer in meta_wayland_transaction_destroy.
  (Georges Basile Stavracas Neto)
* Add spaces between type casts and values. (Carlos Garnacho)
* Use (gpointer *) instead of (void**). (Carlos Garnacho)
* Use gpointer instead of void * in
  meta_wayland_transaction_dma_buf_dispatch.
v6:
* Use g_hash_table_remove in meta_wayland_transaction_dma_buf_dispatch.
  (Carlos Garnacho)
v7: (Jonas Ådahl)
* Move include of glib-unix.h below that of meta-wayland-transaction.h.
* Split up g_hash_table_iter_next call to multiple lines in
  meta_wayland_transaction_commit.
* Call g_source_destroy as well as g_source_unref when freeing a
  committed but not yet applied transaction (during mutter shutdown).
v8:
* Drop dma_buf_source_destroy, can use g_source_destroy directly.
  (Jonas Ådahl)

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 16:35:19 +01:00
Michel Dänzer
b7599fb766 wayland/xdg-shell: Defer meta_wayland_xdg_positioner_to_placement call
From xdg_surface_constructor_get_popup / xdg_popup_reposition (called
during Wayland protocol processing) to finish_popup_setup /
meta_wayland_xdg_popup_apply_state (called when the popup state is
applied).

This makes sure that the parent window frame rectangle is up to date in
meta_wayland_xdg_positioner_to_placement.

v2:
* Use meta_wayland_surface_state_new () in
  meta_wayland_transaction_add_xdg_popup_reposition.
v3:
* Move xdg_popup_repositioned handling to
  meta_wayland_xdg_popup_apply_state.
v4:
* Do not steal pending->xdg_positioner in
  meta_wayland_xdg_popup_apply_state, fixes leaking the corresponding
  memory.
* Drop MetaWaylandSurfaceState::xdg_popup_repositioned, just use
  ::xdg_positioner.
v5:
* Reformat meta_wayland_xdg_positioner_to_placement calls to stay within
  80 columns. (Jonas Ådahl)

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
6c3879766d wayland/xdg-shell: Add parent surface entry to popup setup transaction
This makes sure that finish_popup_setup is called after any previous
transactions for the parent surface have been applied, so the parent
window geometry is up to date.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
26346a06ee wayland/surface: Make meta_wayland_transaction_ensure_entry non-static
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
9ed6a3dffb wayland/surface: Add role commit_state callback
Which gets called when pending state is committed for the surface.

This callback may amend the pending transaction or surface state as
needed.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
79dc41499d wayland/surface: Call meta_wayland_buffer_attach from surface commit
Preparation for potentially calling meta_wayland_transaction_apply some
time after surface commit, in which case doing it in the former would be
too late: The client may legally destroy the attached wl_buffer
immediately after commit, in which case meta_wayland_buffer_attach would
spuriously fail and disconnect the client (or possibly even crash mutter
due to NULL error).

Requires splitting up the surface texture between protocol and output
state, and propagating from the former to the latter via
MetaWaylandSurfaceState.

v2: (Jonas Ådahl)
* Move meta_wayland_surface_get_texture call to separate line.
* Use g_autoptr for GError.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
80c6b7d82b wayland/surface: Use transactions for all sub-surface hierarchy changes
And keep track of the hierarchy separately for the Wayland protocol and
for output. Protocol state is updated immediately as protocol requests
are processed, output state only when the corresponding transaction is
applied (which may be deferred until the next commit of the parent
surface).

v2:
* Directly add placement ops to a transaction, instead of going via
  pending_state.
* Use transaction entry for the sub-surface instead of that for its
  parent surface.
v3:
* Use transaction entry for the parent surface again, to ensure proper
  ordering of placement ops, and call
  meta_wayland_surface_notify_subsurface_state_changed only once per
  parent surface.
* Drop all use of wl_resource_add_destroy_listener, transactions are
  keeping surfaces alive as long as needed.
v4:
* Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501
* Drop ClutterActor code from meta_wayland_surface_apply_placement_ops.
  (Robert Mader)
v5:
* Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since
  the next commit adds not sub-surface specific state to it.
v6:
* Move include of meta-wayland-subsurface.h from
  meta-wayland-transaction.c to .h, since the latter references
  MetaWaylandSubsurfacePlacementOp.
v7:
* Drop superfluous !entry check from meta_wayland_transaction_apply.
v8:
* Rename output/protocol fields to output/protocol_state. (Jonas Ådahl)
v9:
* Use meta_wayland_surface_state_new in
  meta_wayland_transaction_add_placement_op.
v10:
* Fix a few style issues per check-style.py.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
4eef08c5c3 wayland/surface: Two phase surface destruction
Destroy Wayland protocol related state immediately when the Wayland
resource is destroyed, but keep the rest alive by any transaction which
references the surface.

This makes it easier and cleaner to deal with a surface getting
destroyed while it's still referenced by transactions.

v2:
* No more need to keep references for surfaces in the entries hash
  table.
v3:
* Do not use surface->sub.transaction in wl_surface_destructor, just
  destroy it.
v4:
* No need for wl_surface_destructor to use its own transaction.
v5:
* Use g_steal_pointer & (more) g_clear_pointer in wl_surface_destructor.
v6:
* Leave SURFACE_DESTROY signal emission in wl_surface_destructor.
v7:
* Use finalize instead of dispose callback.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
ff707a6de6 wayland/surface: Store pointers to next transaction with same surface
This saves traversing all committed transactions to find the next one
which references the same surface.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
e26df6ac14 wayland/surface: Keep transaction entries for all referenced surfaces
This keeps all surfaces referenced by a transaction alive until the
transaction is destroyed, and makes sure transactions are applied in
the same order as they were committed with respect to all surfaces
they reference.

v2:
* Guard against NULL entry in meta_wayland_transaction_apply.
v3:
* Keep single entries hash table.
v4:
* Unref the surface in the meta_wayland_transaction_merge_into while
  loop only if the "to" transaction didn't already have an entry for it,
  to prevent premature finalization of the surface (likely followed by a
  crash).
v5:
* Unref the surface (implicitly via g_hash_table_iter_remove) in the
  meta_wayland_transaction_merge_into while loop even if the "to"
  transaction already had an entry for it, or we leak a reference.
* Use g_clear_object & g_steal_pointer to not leave behind a dangling
  from->state pointer in meta_wayland_transaction_entry_merge_into.
v6:
* Add curly braces around
  meta_wayland_transaction_add_placement_surfaces calls. (Jonas Ådahl)

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
5fa4ce6fa8 wayland/surface: Use transactions for synchronized sub-surface state
Instead of cached_state.

surface_commit for a synchronized sub-surface either commits the
transaction or merges it into the parent surface's transaction (if
the parent is a synchronized sub-surface itself).

This should fix or at least improve the behaviour of nested synchronized
sub-surfaces.

Also change wl_subsurface_set_desync:

* Commit sub-surface transactions separately. This may allow some of
  them to be applied earlier in some cases.
* Commit transaction only for descendant sub-surfaces which become
  newly de-synchronized themselves.

v2:
* Drop unused function prototypes
v3:
* Use g_clear_pointer for surface->sub.transaction.
v4:
* Use g_steal_pointer instead of g_clear_pointer. (Sebastian Wick, Jonas
  Ådahl)
v5: (Carlos Garnacho)
* Add spaces between type casts and values.
* Use (gpointer *) instead of (void**).
v6: (Jonas Ådahl)
* Use g_clear_object in meta_wayland_transaction_entry_merge_into.
* Use meta_wayland_transaction_entry_free in
  meta_wayland_transaction_merge_into.
* Fix alignment of meta_wayland_transaction_merge_pending_state
  parameters.
* Remove unused meta_wayland_transaction_add_state declaration.
v7:
* Use meta_wayland_surface_state_new in
  meta_wayland_transaction_merge_pending_state.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
0bae4ece19 wayland/surface: Use transactions for applying committed states
A transaction contains the committed state for a surface, plus any
cached state for synchronized subsurfaces.

v2:
* Handle sub-surface positions separately from surface states.
v3:
* Sync child states only for surfaces with state in the transaction.
v4: (Jonas Ådahl)
* Drop unnecessary g_object_new call from wl_subsurface_set_desync. (me)
* Fix indentation & formatting in meta_wayland_surface_commit.
* Add meta_wayland_surface_state_new helper function.
* Fix alignment of meta_wayland_transaction_apply_subsurface_position
  parameters.
* Add curly braces around meta_wayland_transaction_sync_child_states
  call in meta_wayland_transaction_apply.
v5:
* Make meta_wayland_surface_state_new an inline function.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
56260e3e07 wayland/surface: Make sure transactions are applied in consistent order
If multiple transactions have entries for the same surface, they are
applied in the same order as they were committed. Otherwise, they can
be applied in any order.

This is preparation for following changes, transactions are still
applied as soon as they're committed.

v2:
* Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl)
v3
* Say "entry for" instead of "state for", since there can be transaction
  entries with no state (for surfaces which are getting destroyed).
v4:
* Use a hash table to keep track of all candidate transactions which
  might be newly ready to be applied.
* Use clearer function / variable names.
v5:
* Use custom single-linked list instead of hash table for candidate
  transactions, ordered by the transaction commit sequence number, so
  that they're attempted to be applied in the same order as they were
  committed.
* Rename transaction->queue to transaction->committed_queue, and
  simplify its handling.
v6: (Carlos Garnacho)
* Add spaces between type casts and values.
* Use (gpointer *) instead of (void**).
v7: (Jonas Ådahl)
* Use G_MAXSIZE instead of ULONG_MAX.
* Fix indentation of meta_wayland_transaction_apply &
  meta_wayland_transaction_maybe_apply_one parameters.
* Refactor find_next_transaction_for_surface & ensure_next_candidate
  helper functions out of meta_wayland_transaction_apply.
* Refactor has_unapplied_dependencies helper function out of
  meta_wayland_transaction_maybe_apply_one.
* Make while (TRUE) loop in meta_wayland_transaction_maybe_apply
  consistent with general usage.
* Drop unused value local from meta_wayland_transaction_commit.
* Store pointer to compositor object in transactions, instead of
  pointer to the queue of committed transactions.
* Drop tautological g_assert from meta_wayland_transaction_apply. (me)

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
207847e8cf wayland: Add transaction skeleton
v2:
* Use single hash table with struct which will contain all kinds of
  state handled by a transaction.
v3:
* Add meta_wayland_transaction_destroy.
v4 (Georges Basile Stavracas Neto)
* Fix struct _MetaWaylandTransaction(Entry) formatting.
* Explicitly test against NULL.
* Use gpointer insteadof void * for
  meta_wayland_transaction_entry_destroy.
v5: (Robert Mader)
* Use for loop in is_ancestor.
* Include meta-wayland-transaction.h first in
  meta-wayland-transaction.c.
v6:
* Use g_autofree & g_clear_object.
v7: (Jonas Ådahl)
* Rename meta_wayland_transaction_entry_destroy to
  meta_wayland_transaction_entry_free.
* Drop g_autofree use from meta_wayland_transaction_entry_free again.
* Make meta_wayland_transaction_entry_free take a
  MetaWaylandTransactionEntry pointer.
* Rename meta_wayland_transaction_destroy to
  meta_wayland_transaction_free.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
6379e54847 wayland/surface: Prepare for decoupled surface & resource lifetimes
Need to deal with surface->resource == NULL and
surface->pending_state == NULL in some places.

v2:
* Avoid expanding conditions to multiple lines.
  (Georges Basile Stavracas Neto)
v3:
* Use a single bailout condition in meta_wayland_client_owns_window as
  well.
v4:
* Remove spare empty line in meta_wayland_surface_apply_state.
  (Robert Mader)
* Add wl_resource_post_error calls in xdg-shell request handlers.
  (Robert Mader)
* Drop checks in functions which can only be called if there's a valid
  resource.
* Drop more checks which are unnecessary due to leaving the
  SURFACE_DESTROY signal emission in wl_surface_destructor later.
v5:
* Move resource = surface->resource assignments to if (!resource) tests.
  (Jonas Ådahl)
v6:
* Fix style issue per check-style.py.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
a99198de83 wayland/surface: Rename "should_cache_state" to "is_synchronized"
Also remove the stale meta_wayland_surface_is_effectively_synchronized
prototype.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
e7d589d45b wayland/surface: Move out meta_wayland_surface_state_reset calls
From meta_wayland_surface_apply_state / _state_merge_into to their
callers.

Preparation for changing behaviour in the callers, no functional
change intended.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00
Michel Dänzer
854c02651f wayland/surface: Discard presentation feedback in _state_merge_into
Newly merged state is always from a different surface commit than the
existing state.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-12-01 12:41:32 +01:00