2013-08-30 12:26:18 -04:00
|
|
|
/*
|
|
|
|
* Wayland Support
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012,2013 Intel Corporation
|
2017-12-20 04:40:22 -05:00
|
|
|
* Copyright (C) 2013-2017 Red Hat, Inc.
|
2013-08-30 12:26:18 -04:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2014-10-07 22:59:01 -04:00
|
|
|
#include "config.h"
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-surface.h"
|
2013-08-30 12:26:18 -04:00
|
|
|
|
2016-01-28 04:14:06 -05:00
|
|
|
#include <gobject/gvaluecollector.h>
|
2013-08-30 12:26:18 -04:00
|
|
|
#include <wayland-server.h>
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "backends/meta-cursor-tracker-private.h"
|
|
|
|
#include "clutter/clutter.h"
|
2020-02-17 12:32:35 -05:00
|
|
|
#include "cogl/cogl.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "compositor/meta-surface-actor-wayland.h"
|
|
|
|
#include "compositor/meta-surface-actor.h"
|
2018-04-04 04:15:25 -04:00
|
|
|
#include "compositor/meta-window-actor-private.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "compositor/region-utils.h"
|
|
|
|
#include "core/display-private.h"
|
|
|
|
#include "core/window-private.h"
|
2018-11-30 14:35:15 -05:00
|
|
|
#include "wayland/meta-wayland-actor-surface.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-buffer.h"
|
|
|
|
#include "wayland/meta-wayland-data-device.h"
|
|
|
|
#include "wayland/meta-wayland-gtk-shell.h"
|
|
|
|
#include "wayland/meta-wayland-keyboard.h"
|
|
|
|
#include "wayland/meta-wayland-outputs.h"
|
|
|
|
#include "wayland/meta-wayland-pointer.h"
|
2020-10-07 05:02:41 -04:00
|
|
|
#include "wayland/meta-wayland-presentation-time-private.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-private.h"
|
|
|
|
#include "wayland/meta-wayland-region.h"
|
|
|
|
#include "wayland/meta-wayland-seat.h"
|
|
|
|
#include "wayland/meta-wayland-subsurface.h"
|
2021-05-28 06:39:48 -04:00
|
|
|
#include "wayland/meta-wayland-transaction.h"
|
2018-11-24 14:25:38 -05:00
|
|
|
#include "wayland/meta-wayland-viewporter.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-xdg-shell.h"
|
|
|
|
#include "wayland/meta-window-wayland.h"
|
|
|
|
#include "wayland/meta-xwayland-private.h"
|
|
|
|
#include "wayland/meta-xwayland-private.h"
|
window-actor: Split into two subclasses of MetaSurfaceActor
The rendering logic before was somewhat complex. We had three independent
cases to take into account when doing rendering:
* X11 compositor. In this case, we're a traditional X11 compositor,
not a Wayland compositor. We use XCompositeNameWindowPixmap to get
the backing pixmap for the window, and deal with the COMPOSITE
extension messiness.
In this case, meta_is_wayland_compositor() is FALSE.
* Wayland clients. In this case, we're a Wayland compositor managing
Wayland surfaces. The rendering for this is fairly straightforward,
as Cogl handles most of the complexity with EGL and SHM buffers...
Wayland clients give us the input and opaque regions through
wl_surface.
In this case, meta_is_wayland_compositor() is TRUE and
priv->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND.
* XWayland clients. In this case, we're a Wayland compositor, like
above, and XWayland hands us Wayland surfaces. XWayland handles
the COMPOSITE extension messiness for us, and hands us a buffer
like any other Wayland client. We have to fetch the input and
opaque regions from the X11 window ourselves.
In this case, meta_is_wayland_compositor() is TRUE and
priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11.
We now split the rendering logic into two subclasses, which are:
* MetaSurfaceActorX11, which handles the X11 compositor case, in that
it uses XCompositeNameWindowPixmap to get the backing pixmap, and
deal with all the COMPOSITE extension messiness.
* MetaSurfaceActorWayland, which handles the Wayland compositor case
for both native Wayland clients and XWayland clients. XWayland handles
COMPOSITE for us, and handles pushing a surface over through the
xf86-video-wayland DDX.
Frame sync is still in MetaWindowActor, as it needs to work for both the
X11 compositor and XWayland client cases. When Wayland's video display
protocol lands, this will need to be significantly overhauled, as it would
have to work for any wl_surface, including subsurfaces, so we would need
surface-level discretion.
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-01 17:21:11 -05:00
|
|
|
|
2018-12-19 03:04:25 -05:00
|
|
|
enum
|
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
SURFACE_STATE_SIGNAL_APPLIED,
|
2015-06-17 00:10:52 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
SURFACE_STATE_SIGNAL_N_SIGNALS
|
2015-06-17 00:10:52 -04:00
|
|
|
};
|
|
|
|
|
2016-01-28 03:55:42 -05:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
SURFACE_ROLE_PROP_0,
|
|
|
|
|
|
|
|
SURFACE_ROLE_PROP_SURFACE,
|
|
|
|
};
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
static guint surface_state_signals[SURFACE_STATE_SIGNAL_N_SIGNALS];
|
2015-06-17 00:10:52 -04:00
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
typedef struct _MetaWaylandSurfaceRolePrivate
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface;
|
|
|
|
} MetaWaylandSurfaceRolePrivate;
|
|
|
|
|
2021-08-06 11:00:19 -04:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
PROP_SCANOUT_CANDIDATE,
|
|
|
|
|
|
|
|
N_PROPS
|
|
|
|
};
|
|
|
|
|
|
|
|
static GParamSpec *obj_props[N_PROPS];
|
|
|
|
|
2015-07-07 23:21:23 -04:00
|
|
|
G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
|
|
|
|
|
2018-02-23 06:05:05 -05:00
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
|
|
|
|
meta_wayland_surface_role,
|
|
|
|
G_TYPE_OBJECT)
|
2015-07-08 04:14:00 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
G_DEFINE_TYPE (MetaWaylandSurfaceState,
|
|
|
|
meta_wayland_surface_state,
|
|
|
|
G_TYPE_OBJECT)
|
2015-12-14 04:13:35 -05:00
|
|
|
|
2018-12-19 03:04:25 -05:00
|
|
|
enum
|
|
|
|
{
|
2015-10-22 08:07:52 -04:00
|
|
|
SURFACE_DESTROY,
|
2016-08-18 00:57:17 -04:00
|
|
|
SURFACE_UNMAPPED,
|
2016-06-28 02:56:20 -04:00
|
|
|
SURFACE_CONFIGURE,
|
2017-03-17 08:34:52 -04:00
|
|
|
SURFACE_SHORTCUTS_INHIBITED,
|
|
|
|
SURFACE_SHORTCUTS_RESTORED,
|
2018-04-06 06:35:34 -04:00
|
|
|
SURFACE_GEOMETRY_CHANGED,
|
2018-10-24 05:34:18 -04:00
|
|
|
SURFACE_PRE_STATE_APPLIED,
|
2015-10-22 08:07:52 -04:00
|
|
|
N_SURFACE_SIGNALS
|
|
|
|
};
|
|
|
|
|
|
|
|
guint surface_signals[N_SURFACE_SIGNALS] = { 0 };
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role);
|
|
|
|
|
2022-11-01 11:43:03 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_commit_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandTransaction *transaction,
|
|
|
|
MetaWaylandSurfaceState *pending);
|
|
|
|
|
2016-03-16 02:55:51 -04:00
|
|
|
static void
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending);
|
2016-03-16 02:55:51 -04:00
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
static void
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending);
|
2015-07-08 04:14:00 -04:00
|
|
|
|
2020-06-08 03:13:44 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending);
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
static gboolean
|
2016-11-25 01:38:28 -05:00
|
|
|
meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaLogicalMonitor *logical_monitor);
|
2015-07-08 04:14:00 -04:00
|
|
|
|
2016-01-14 04:43:47 -05:00
|
|
|
static MetaWaylandSurface *
|
|
|
|
meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role);
|
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
static void
|
|
|
|
set_surface_is_on_output (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandOutput *wayland_output,
|
|
|
|
gboolean is_on_output);
|
|
|
|
|
2016-01-28 04:14:06 -05:00
|
|
|
static void
|
2017-12-12 23:57:08 -05:00
|
|
|
role_assignment_valist_to_properties (GType role_type,
|
|
|
|
const char *first_property_name,
|
|
|
|
va_list var_args,
|
|
|
|
GArray *names,
|
|
|
|
GArray *values)
|
2016-01-28 04:14:06 -05:00
|
|
|
{
|
|
|
|
GObjectClass *object_class;
|
|
|
|
const char *property_name = first_property_name;
|
|
|
|
|
|
|
|
object_class = g_type_class_ref (role_type);
|
|
|
|
|
|
|
|
while (property_name)
|
|
|
|
{
|
2017-12-12 23:57:08 -05:00
|
|
|
GValue value = G_VALUE_INIT;
|
2016-01-28 04:14:06 -05:00
|
|
|
GParamSpec *pspec;
|
|
|
|
GType ptype;
|
|
|
|
gchar *error = NULL;
|
|
|
|
|
|
|
|
pspec = g_object_class_find_property (object_class,
|
|
|
|
property_name);
|
|
|
|
g_assert (pspec);
|
|
|
|
|
|
|
|
ptype = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
2017-12-12 23:57:08 -05:00
|
|
|
G_VALUE_COLLECT_INIT (&value, ptype, var_args, 0, &error);
|
2016-01-28 04:14:06 -05:00
|
|
|
g_assert (!error);
|
|
|
|
|
2017-12-12 23:57:08 -05:00
|
|
|
g_array_append_val (names, property_name);
|
|
|
|
g_array_append_val (values, value);
|
2016-01-28 04:14:06 -05:00
|
|
|
|
|
|
|
property_name = va_arg (var_args, const char *);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_type_class_unref (object_class);
|
|
|
|
}
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
gboolean
|
|
|
|
meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
|
2016-01-28 04:14:06 -05:00
|
|
|
GType role_type,
|
|
|
|
const char *first_property_name,
|
|
|
|
...)
|
2015-07-08 04:14:00 -04:00
|
|
|
{
|
2016-01-28 04:14:06 -05:00
|
|
|
va_list var_args;
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
if (!surface->role)
|
2015-02-06 03:12:21 -05:00
|
|
|
{
|
2016-01-28 04:14:06 -05:00
|
|
|
if (first_property_name)
|
|
|
|
{
|
2017-12-12 23:57:08 -05:00
|
|
|
GArray *names;
|
|
|
|
GArray *values;
|
|
|
|
const char *surface_prop_name;
|
|
|
|
GValue surface_value = G_VALUE_INIT;
|
|
|
|
GObject *role_object;
|
|
|
|
|
|
|
|
names = g_array_new (FALSE, FALSE, sizeof (const char *));
|
|
|
|
values = g_array_new (FALSE, FALSE, sizeof (GValue));
|
|
|
|
g_array_set_clear_func (values, (GDestroyNotify) g_value_unset);
|
2016-01-28 04:14:06 -05:00
|
|
|
|
|
|
|
va_start (var_args, first_property_name);
|
2017-12-12 23:57:08 -05:00
|
|
|
role_assignment_valist_to_properties (role_type,
|
|
|
|
first_property_name,
|
|
|
|
var_args,
|
|
|
|
names,
|
|
|
|
values);
|
2016-01-28 04:14:06 -05:00
|
|
|
va_end (var_args);
|
|
|
|
|
2017-12-12 23:57:08 -05:00
|
|
|
surface_prop_name = "surface";
|
|
|
|
g_value_init (&surface_value, META_TYPE_WAYLAND_SURFACE);
|
|
|
|
g_value_set_object (&surface_value, surface);
|
|
|
|
g_array_append_val (names, surface_prop_name);
|
|
|
|
g_array_append_val (values, surface_value);
|
|
|
|
|
|
|
|
role_object =
|
|
|
|
g_object_new_with_properties (role_type,
|
|
|
|
values->len,
|
|
|
|
(const char **) names->data,
|
|
|
|
(const GValue *) values->data);
|
|
|
|
surface->role = META_WAYLAND_SURFACE_ROLE (role_object);
|
|
|
|
|
2020-01-24 07:53:08 -05:00
|
|
|
g_array_free (names, TRUE);
|
2017-12-12 23:57:08 -05:00
|
|
|
g_array_free (values, TRUE);
|
2016-01-28 04:14:06 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
surface->role = g_object_new (role_type, "surface", surface, NULL);
|
|
|
|
}
|
2015-07-08 04:14:00 -04:00
|
|
|
|
|
|
|
meta_wayland_surface_role_assigned (surface->role);
|
2015-08-18 23:06:46 -04:00
|
|
|
|
2016-03-16 02:55:51 -04:00
|
|
|
/* Release the use count held on behalf of the just assigned role. */
|
|
|
|
if (surface->unassigned.buffer)
|
|
|
|
{
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (surface->unassigned.buffer);
|
2016-03-16 02:55:51 -04:00
|
|
|
g_clear_object (&surface->unassigned.buffer);
|
|
|
|
}
|
|
|
|
|
2015-08-28 00:15:21 -04:00
|
|
|
return TRUE;
|
2015-02-06 03:12:21 -05:00
|
|
|
}
|
2015-07-08 04:14:00 -04:00
|
|
|
else if (G_OBJECT_TYPE (surface->role) != role_type)
|
2015-02-06 03:12:21 -05:00
|
|
|
{
|
2015-08-28 00:15:21 -04:00
|
|
|
return FALSE;
|
2015-02-06 03:12:21 -05:00
|
|
|
}
|
2015-07-08 04:14:00 -04:00
|
|
|
else
|
|
|
|
{
|
2016-01-28 04:14:06 -05:00
|
|
|
va_start (var_args, first_property_name);
|
|
|
|
g_object_set_valist (G_OBJECT (surface->role),
|
|
|
|
first_property_name, var_args);
|
|
|
|
va_end (var_args);
|
|
|
|
|
2016-07-01 03:30:21 -04:00
|
|
|
meta_wayland_surface_role_assigned (surface->role);
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
2015-02-06 03:12:21 -05:00
|
|
|
}
|
|
|
|
|
2018-11-26 13:40:57 -05:00
|
|
|
static int
|
|
|
|
get_buffer_width (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
|
|
|
|
|
|
|
if (buffer)
|
2022-07-13 11:10:05 -04:00
|
|
|
return cogl_texture_get_width (surface->output_state.texture);
|
2018-11-26 13:40:57 -05:00
|
|
|
else
|
wayland: Move surface texture ownership to MetaWaylandSurface
Prior to this commit, MetaWaylandSurface held a reference to
MetaWaylandBuffer, who owned the texture drawn by the surface. When
switching buffer, the texture change with it.
This is problematic when dealing with SHM buffer damage management, as
when having one texture per buffer, damaged regions uploaded to one,
will not follow along to the next one attached. It also wasted GPU
memory as there would be one texture per buffer, instead of one one
texture per surface.
Instead, move the texture ownership to MetaWaylandSurface, and have the
SHM buffer damage management update the surface texture. This ensures
damage is processed properly, and that we won't end up with stale
texture content when doing partial texture uploads. If the same SHM
buffer is attached to multiple surfaces, each surface will get their own
copy, and damage is tracked and uploaded separately.
Non-SHM types of buffers still has their own texture reference, as the
texture is just a representation of the GPU memory associated with the
buffer. When such a buffer is attached to a surface, instead the surface
just gets a reference to that texture, instead of a separately allocated
one.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-08 05:46:48 -05:00
|
|
|
return 0;
|
2018-11-26 13:40:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
get_buffer_height (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
|
|
|
|
|
|
|
if (buffer)
|
2022-07-13 11:10:05 -04:00
|
|
|
return cogl_texture_get_height (surface->output_state.texture);
|
2018-11-26 13:40:57 -05:00
|
|
|
else
|
wayland: Move surface texture ownership to MetaWaylandSurface
Prior to this commit, MetaWaylandSurface held a reference to
MetaWaylandBuffer, who owned the texture drawn by the surface. When
switching buffer, the texture change with it.
This is problematic when dealing with SHM buffer damage management, as
when having one texture per buffer, damaged regions uploaded to one,
will not follow along to the next one attached. It also wasted GPU
memory as there would be one texture per buffer, instead of one one
texture per surface.
Instead, move the texture ownership to MetaWaylandSurface, and have the
SHM buffer damage management update the surface texture. This ensures
damage is processed properly, and that we won't end up with stale
texture content when doing partial texture uploads. If the same SHM
buffer is attached to multiple surfaces, each surface will get their own
copy, and damage is tracked and uploaded separately.
Non-SHM types of buffers still has their own texture reference, as the
texture is just a representation of the GPU memory associated with the
buffer. When such a buffer is attached to a surface, instead the surface
just gets a reference to that texture, instead of a separately allocated
one.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-08 05:46:48 -05:00
|
|
|
return 0;
|
2018-11-26 13:40:57 -05:00
|
|
|
}
|
|
|
|
|
2013-08-30 12:26:18 -04:00
|
|
|
static void
|
|
|
|
surface_process_damage (MetaWaylandSurface *surface,
|
2017-06-05 08:08:04 -04:00
|
|
|
cairo_region_t *surface_region,
|
|
|
|
cairo_region_t *buffer_region)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2018-11-26 13:40:57 -05:00
|
|
|
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
2018-12-03 11:02:30 -05:00
|
|
|
cairo_rectangle_int_t buffer_rect;
|
2019-02-08 13:42:06 -05:00
|
|
|
MetaSurfaceActor *actor;
|
2014-04-23 16:14:31 -04:00
|
|
|
|
2016-03-16 02:47:53 -04:00
|
|
|
/* If the client destroyed the buffer it attached before committing, but
|
|
|
|
* still posted damage, or posted damage without any buffer, don't try to
|
|
|
|
* process it on the non-existing buffer.
|
|
|
|
*/
|
|
|
|
if (!buffer)
|
2014-04-27 10:18:09 -04:00
|
|
|
return;
|
|
|
|
|
2018-12-03 11:02:30 -05:00
|
|
|
buffer_rect = (cairo_rectangle_int_t) {
|
|
|
|
.width = get_buffer_width (surface),
|
|
|
|
.height = get_buffer_height (surface),
|
|
|
|
};
|
|
|
|
|
2021-12-18 16:00:41 -05:00
|
|
|
if (!cairo_region_is_empty (surface_region))
|
2018-11-24 14:25:38 -05:00
|
|
|
{
|
2021-12-18 16:00:41 -05:00
|
|
|
cairo_rectangle_int_t surface_rect;
|
|
|
|
cairo_region_t *scaled_region;
|
|
|
|
cairo_region_t *transformed_region;
|
|
|
|
cairo_region_t *viewport_region;
|
|
|
|
graphene_rect_t src_rect;
|
|
|
|
|
|
|
|
/* Intersect the damage region with the surface region before scaling in
|
|
|
|
* order to avoid integer overflow when scaling a damage region is too
|
|
|
|
* large (for example INT32_MAX which mesa passes). */
|
|
|
|
surface_rect = (cairo_rectangle_int_t) {
|
|
|
|
.width = meta_wayland_surface_get_width (surface),
|
|
|
|
.height = meta_wayland_surface_get_height (surface),
|
2018-11-24 14:25:38 -05:00
|
|
|
};
|
2021-12-18 16:00:41 -05:00
|
|
|
cairo_region_intersect_rectangle (surface_region, &surface_rect);
|
2021-12-18 15:45:52 -05:00
|
|
|
|
2021-12-18 16:00:41 -05:00
|
|
|
/* The damage region must be in the same coordinate space as the buffer,
|
|
|
|
* i.e. scaled with surface->scale. */
|
|
|
|
if (surface->viewport.has_src_rect)
|
2021-12-18 15:45:52 -05:00
|
|
|
{
|
2021-12-18 16:00:41 -05:00
|
|
|
src_rect = (graphene_rect_t) {
|
|
|
|
.origin.x = surface->viewport.src_rect.origin.x,
|
|
|
|
.origin.y = surface->viewport.src_rect.origin.y,
|
|
|
|
.size.width = surface->viewport.src_rect.size.width,
|
|
|
|
.size.height = surface->viewport.src_rect.size.height
|
|
|
|
};
|
2021-12-18 15:45:52 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-18 16:00:41 -05:00
|
|
|
int width, height;
|
|
|
|
|
|
|
|
if (meta_monitor_transform_is_rotated (surface->buffer_transform))
|
|
|
|
{
|
|
|
|
width = get_buffer_height (surface);
|
|
|
|
height = get_buffer_width (surface);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width = get_buffer_width (surface);
|
|
|
|
height = get_buffer_height (surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
src_rect = (graphene_rect_t) {
|
|
|
|
.size.width = width / surface->scale,
|
|
|
|
.size.height = height / surface->scale
|
|
|
|
};
|
2021-12-18 15:45:52 -05:00
|
|
|
}
|
2021-12-18 16:00:41 -05:00
|
|
|
viewport_region = meta_region_crop_and_scale (surface_region,
|
|
|
|
&src_rect,
|
|
|
|
surface_rect.width,
|
|
|
|
surface_rect.height);
|
|
|
|
scaled_region = meta_region_scale (viewport_region, surface->scale);
|
|
|
|
transformed_region = meta_region_transform (scaled_region,
|
|
|
|
surface->buffer_transform,
|
|
|
|
buffer_rect.width,
|
|
|
|
buffer_rect.height);
|
|
|
|
|
|
|
|
/* Now add the scaled, cropped and transformed damage region to the
|
|
|
|
* buffer damage. Buffer damage is already in the correct coordinate
|
|
|
|
* space. */
|
|
|
|
cairo_region_union (buffer_region, transformed_region);
|
|
|
|
|
|
|
|
cairo_region_destroy (viewport_region);
|
|
|
|
cairo_region_destroy (scaled_region);
|
|
|
|
cairo_region_destroy (transformed_region);
|
2018-11-24 14:25:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
cairo_region_intersect_rectangle (buffer_region, &buffer_rect);
|
2015-03-02 22:07:36 -05:00
|
|
|
|
2022-07-13 11:10:05 -04:00
|
|
|
meta_wayland_buffer_process_damage (buffer, surface->output_state.texture,
|
|
|
|
buffer_region);
|
2014-08-21 16:19:23 -04:00
|
|
|
|
2019-02-08 13:42:06 -05:00
|
|
|
actor = meta_wayland_surface_get_actor (surface);
|
|
|
|
if (actor)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2019-02-08 13:42:06 -05:00
|
|
|
int i, n_rectangles;
|
2014-08-21 16:19:23 -04:00
|
|
|
|
2019-02-08 13:42:06 -05:00
|
|
|
n_rectangles = cairo_region_num_rectangles (buffer_region);
|
|
|
|
for (i = 0; i < n_rectangles; i++)
|
|
|
|
{
|
|
|
|
cairo_rectangle_int_t rect;
|
|
|
|
cairo_region_get_rectangle (buffer_region, i, &rect);
|
|
|
|
|
|
|
|
meta_surface_actor_process_damage (actor,
|
|
|
|
rect.x, rect.y,
|
|
|
|
rect.width, rect.height);
|
|
|
|
}
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 02:47:53 -04:00
|
|
|
MetaWaylandBuffer *
|
|
|
|
meta_wayland_surface_get_buffer (MetaWaylandSurface *surface)
|
|
|
|
{
|
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-06-22 12:43:11 -04:00
|
|
|
return surface->buffer;
|
2016-03-16 02:47:53 -04:00
|
|
|
}
|
|
|
|
|
2014-01-13 17:31:25 -05:00
|
|
|
static void
|
2016-03-15 00:46:06 -04:00
|
|
|
pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer,
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending)
|
2014-01-13 17:31:25 -05:00
|
|
|
{
|
2019-10-20 15:32:29 -04:00
|
|
|
g_clear_signal_handler (&pending->buffer_destroy_handler_id, buffer);
|
2016-03-15 00:46:06 -04:00
|
|
|
pending->buffer = NULL;
|
2014-01-13 17:31:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state)
|
2014-01-13 17:31:25 -05:00
|
|
|
{
|
|
|
|
state->newly_attached = FALSE;
|
|
|
|
state->buffer = NULL;
|
2022-07-13 11:10:05 -04:00
|
|
|
state->texture = NULL;
|
2018-04-06 11:50:31 -04:00
|
|
|
state->buffer_destroy_handler_id = 0;
|
2014-01-13 17:31:25 -05:00
|
|
|
state->dx = 0;
|
|
|
|
state->dy = 0;
|
2014-04-26 04:27:34 -04:00
|
|
|
state->scale = 0;
|
2014-01-13 17:31:25 -05:00
|
|
|
|
2014-04-18 18:19:02 -04:00
|
|
|
state->input_region = NULL;
|
2015-08-04 02:58:26 -04:00
|
|
|
state->input_region_set = FALSE;
|
2014-04-18 18:19:02 -04:00
|
|
|
state->opaque_region = NULL;
|
2015-08-04 02:58:26 -04:00
|
|
|
state->opaque_region_set = FALSE;
|
2014-04-18 18:19:02 -04:00
|
|
|
|
2017-06-05 08:08:04 -04:00
|
|
|
state->surface_damage = cairo_region_create ();
|
|
|
|
state->buffer_damage = cairo_region_create ();
|
2014-01-13 17:31:25 -05:00
|
|
|
wl_list_init (&state->frame_callback_list);
|
2014-02-09 18:23:07 -05:00
|
|
|
|
2014-07-17 14:07:38 -04:00
|
|
|
state->has_new_geometry = FALSE;
|
2019-07-05 12:10:14 -04:00
|
|
|
state->has_acked_configure_serial = FALSE;
|
2016-04-06 08:07:08 -04:00
|
|
|
state->has_new_min_size = FALSE;
|
|
|
|
state->has_new_max_size = FALSE;
|
2018-11-26 13:40:57 -05:00
|
|
|
|
|
|
|
state->has_new_buffer_transform = FALSE;
|
2018-11-24 14:25:38 -05:00
|
|
|
state->has_new_viewport_src_rect = FALSE;
|
|
|
|
state->has_new_viewport_dst_size = FALSE;
|
2020-10-07 05:02:41 -04:00
|
|
|
|
2021-03-09 16:24:13 -05:00
|
|
|
state->subsurface_placement_ops = NULL;
|
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
wl_list_init (&state->presentation_feedback_list);
|
2022-11-01 12:30:00 -04:00
|
|
|
|
|
|
|
state->xdg_popup_reposition_token = 0;
|
2020-10-07 05:02:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_surface_state_discard_presentation_feedback (MetaWaylandSurfaceState *state)
|
|
|
|
{
|
|
|
|
while (!wl_list_empty (&state->presentation_feedback_list))
|
|
|
|
{
|
|
|
|
MetaWaylandPresentationFeedback *feedback =
|
|
|
|
wl_container_of (state->presentation_feedback_list.next, feedback, link);
|
|
|
|
|
|
|
|
meta_wayland_presentation_feedback_discard (feedback);
|
|
|
|
}
|
2014-01-13 17:31:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state)
|
2014-01-13 17:31:25 -05:00
|
|
|
{
|
|
|
|
MetaWaylandFrameCallback *cb, *next;
|
|
|
|
|
2022-07-13 11:10:05 -04:00
|
|
|
cogl_clear_object (&state->texture);
|
|
|
|
|
2017-06-05 08:08:04 -04:00
|
|
|
g_clear_pointer (&state->surface_damage, cairo_region_destroy);
|
|
|
|
g_clear_pointer (&state->buffer_damage, cairo_region_destroy);
|
2014-01-13 17:31:25 -05:00
|
|
|
g_clear_pointer (&state->input_region, cairo_region_destroy);
|
|
|
|
g_clear_pointer (&state->opaque_region, cairo_region_destroy);
|
2022-11-01 12:30:00 -04:00
|
|
|
g_clear_pointer (&state->xdg_positioner, g_free);
|
2014-01-13 17:31:25 -05:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
if (state->buffer_destroy_handler_id)
|
|
|
|
{
|
|
|
|
g_clear_signal_handler (&state->buffer_destroy_handler_id, state->buffer);
|
|
|
|
state->buffer = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_clear_object (&state->buffer);
|
|
|
|
}
|
2019-11-15 19:25:52 -05:00
|
|
|
|
2014-01-13 17:31:25 -05:00
|
|
|
wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
|
|
|
|
wl_resource_destroy (cb->resource);
|
2020-10-07 05:02:41 -04:00
|
|
|
|
2021-03-09 16:24:13 -05:00
|
|
|
if (state->subsurface_placement_ops)
|
2021-07-23 10:01:37 -04:00
|
|
|
g_slist_free_full (state->subsurface_placement_ops, g_free);
|
2021-03-09 16:24:13 -05:00
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
meta_wayland_surface_state_discard_presentation_feedback (state);
|
2014-01-13 17:31:25 -05:00
|
|
|
}
|
|
|
|
|
2021-06-07 09:19:47 -04:00
|
|
|
void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_reset (MetaWaylandSurfaceState *state)
|
2014-01-13 17:31:25 -05:00
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_clear (state);
|
|
|
|
meta_wayland_surface_state_set_default (state);
|
2014-01-13 17:31:25 -05:00
|
|
|
}
|
|
|
|
|
2021-06-07 09:19:47 -04:00
|
|
|
void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from,
|
|
|
|
MetaWaylandSurfaceState *to)
|
2014-01-13 17:31:25 -05:00
|
|
|
{
|
2018-04-06 11:50:31 -04:00
|
|
|
if (from->newly_attached)
|
|
|
|
{
|
|
|
|
if (to->buffer)
|
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-06-22 12:43:11 -04:00
|
|
|
{
|
|
|
|
g_warn_if_fail (to->buffer_destroy_handler_id == 0);
|
|
|
|
meta_wayland_buffer_dec_use_count (to->buffer);
|
|
|
|
g_object_unref (to->buffer);
|
|
|
|
}
|
2018-04-06 11:50:31 -04:00
|
|
|
|
|
|
|
to->newly_attached = TRUE;
|
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-06-22 12:43:11 -04:00
|
|
|
to->buffer = g_steal_pointer (&from->buffer);
|
2022-07-13 11:10:05 -04:00
|
|
|
|
|
|
|
cogl_clear_object (&to->texture);
|
|
|
|
to->texture = g_steal_pointer (&from->texture);
|
2018-04-06 11:50:31 -04:00
|
|
|
}
|
2014-01-13 17:31:25 -05:00
|
|
|
|
2021-03-22 06:49:11 -04:00
|
|
|
to->dx += from->dx;
|
|
|
|
to->dy += from->dy;
|
|
|
|
|
2015-01-29 02:43:01 -05:00
|
|
|
wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list);
|
2020-05-04 13:55:56 -04:00
|
|
|
wl_list_init (&from->frame_callback_list);
|
2015-01-29 02:43:01 -05:00
|
|
|
|
2018-04-06 11:50:31 -04:00
|
|
|
cairo_region_union (to->surface_damage, from->surface_damage);
|
|
|
|
cairo_region_union (to->buffer_damage, from->buffer_damage);
|
|
|
|
|
|
|
|
if (from->input_region_set)
|
|
|
|
{
|
|
|
|
if (to->input_region)
|
|
|
|
cairo_region_union (to->input_region, from->input_region);
|
|
|
|
else
|
|
|
|
to->input_region = cairo_region_reference (from->input_region);
|
|
|
|
|
|
|
|
to->input_region_set = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from->opaque_region_set)
|
|
|
|
{
|
|
|
|
if (to->opaque_region)
|
|
|
|
cairo_region_union (to->opaque_region, from->opaque_region);
|
|
|
|
else
|
|
|
|
to->opaque_region = cairo_region_reference (from->opaque_region);
|
|
|
|
|
|
|
|
to->opaque_region_set = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from->has_new_geometry)
|
|
|
|
{
|
|
|
|
to->new_geometry = from->new_geometry;
|
|
|
|
to->has_new_geometry = TRUE;
|
|
|
|
}
|
|
|
|
|
2019-07-05 12:10:14 -04:00
|
|
|
if (from->has_acked_configure_serial)
|
|
|
|
{
|
|
|
|
to->acked_configure_serial = from->acked_configure_serial;
|
|
|
|
to->has_acked_configure_serial = TRUE;
|
|
|
|
}
|
|
|
|
|
2018-04-06 11:50:31 -04:00
|
|
|
if (from->has_new_min_size)
|
|
|
|
{
|
|
|
|
to->new_min_width = from->new_min_width;
|
|
|
|
to->new_min_height = from->new_min_height;
|
|
|
|
to->has_new_min_size = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from->has_new_max_size)
|
|
|
|
{
|
|
|
|
to->new_max_width = from->new_max_width;
|
|
|
|
to->new_max_height = from->new_max_height;
|
|
|
|
to->has_new_max_size = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from->scale > 0)
|
|
|
|
to->scale = from->scale;
|
|
|
|
|
2018-11-26 13:40:57 -05:00
|
|
|
if (from->has_new_buffer_transform)
|
|
|
|
{
|
|
|
|
to->buffer_transform = from->buffer_transform;
|
|
|
|
to->has_new_buffer_transform = TRUE;
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:25:38 -05:00
|
|
|
if (from->has_new_viewport_src_rect)
|
|
|
|
{
|
|
|
|
to->viewport_src_rect.origin.x = from->viewport_src_rect.origin.x;
|
|
|
|
to->viewport_src_rect.origin.y = from->viewport_src_rect.origin.y;
|
|
|
|
to->viewport_src_rect.size.width = from->viewport_src_rect.size.width;
|
|
|
|
to->viewport_src_rect.size.height = from->viewport_src_rect.size.height;
|
|
|
|
to->has_new_viewport_src_rect = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from->has_new_viewport_dst_size)
|
|
|
|
{
|
|
|
|
to->viewport_dst_width = from->viewport_dst_width;
|
|
|
|
to->viewport_dst_height = from->viewport_dst_height;
|
|
|
|
to->has_new_viewport_dst_size = TRUE;
|
|
|
|
}
|
|
|
|
|
2021-03-09 16:24:13 -05:00
|
|
|
if (from->subsurface_placement_ops != NULL)
|
|
|
|
{
|
|
|
|
if (to->subsurface_placement_ops != NULL)
|
|
|
|
{
|
|
|
|
to->subsurface_placement_ops =
|
|
|
|
g_slist_concat (to->subsurface_placement_ops,
|
|
|
|
from->subsurface_placement_ops);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
to->subsurface_placement_ops = from->subsurface_placement_ops;
|
|
|
|
}
|
2021-03-13 20:08:03 -05:00
|
|
|
|
|
|
|
from->subsurface_placement_ops = NULL;
|
2021-03-09 16:24:13 -05:00
|
|
|
}
|
|
|
|
|
2021-05-25 09:51:52 -04:00
|
|
|
/*
|
|
|
|
* A new commit indicates a new content update, so any previous
|
|
|
|
* content update did not go on screen and needs to be discarded.
|
|
|
|
*/
|
|
|
|
meta_wayland_surface_state_discard_presentation_feedback (to);
|
2020-10-07 05:02:41 -04:00
|
|
|
wl_list_insert_list (&to->presentation_feedback_list,
|
|
|
|
&from->presentation_feedback_list);
|
|
|
|
wl_list_init (&from->presentation_feedback_list);
|
2022-11-01 12:30:00 -04:00
|
|
|
|
|
|
|
if (from->xdg_positioner)
|
|
|
|
{
|
|
|
|
g_clear_pointer (&to->xdg_positioner, g_free);
|
|
|
|
to->xdg_positioner = g_steal_pointer (&from->xdg_positioner);
|
|
|
|
to->xdg_popup_reposition_token = from->xdg_popup_reposition_token;
|
|
|
|
}
|
2014-01-13 17:31:25 -05:00
|
|
|
}
|
|
|
|
|
2015-12-14 04:13:35 -05:00
|
|
|
static void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_finalize (GObject *object)
|
2015-12-14 04:13:35 -05:00
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *state = META_WAYLAND_SURFACE_STATE (object);
|
2015-12-14 04:13:35 -05:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_clear (state);
|
2015-12-14 04:13:35 -05:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
G_OBJECT_CLASS (meta_wayland_surface_state_parent_class)->finalize (object);
|
2015-12-14 04:13:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_init (MetaWaylandSurfaceState *state)
|
2015-12-14 04:13:35 -05:00
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_set_default (state);
|
2015-12-14 04:13:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_state_class_init (MetaWaylandSurfaceStateClass *klass)
|
2015-12-14 04:13:35 -05:00
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
object_class->finalize = meta_wayland_surface_state_finalize;
|
2015-06-17 00:10:52 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED] =
|
2015-06-17 00:10:52 -04:00
|
|
|
g_signal_new ("applied",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
G_TYPE_NONE, 0);
|
2015-12-14 04:13:35 -05:00
|
|
|
}
|
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_discard_presentation_feedback (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
while (!wl_list_empty (&surface->presentation_time.feedback_list))
|
|
|
|
{
|
|
|
|
MetaWaylandPresentationFeedback *feedback =
|
|
|
|
wl_container_of (surface->presentation_time.feedback_list.next,
|
|
|
|
feedback, link);
|
|
|
|
|
|
|
|
meta_wayland_presentation_feedback_discard (feedback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 10:01:37 -04:00
|
|
|
void
|
|
|
|
meta_wayland_surface_apply_placement_ops (MetaWaylandSurface *parent,
|
|
|
|
MetaWaylandSurfaceState *state)
|
|
|
|
{
|
|
|
|
GSList *l;
|
|
|
|
|
|
|
|
for (l = state->subsurface_placement_ops; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaWaylandSubsurfacePlacementOp *op = l->data;
|
|
|
|
MetaWaylandSurface *surface = op->surface;
|
|
|
|
GNode *sibling_node;
|
|
|
|
|
|
|
|
g_node_unlink (surface->output_state.subsurface_branch_node);
|
|
|
|
|
|
|
|
if (!op->sibling)
|
|
|
|
{
|
|
|
|
surface->output_state.parent = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
surface->output_state.parent = parent;
|
|
|
|
|
|
|
|
if (op->sibling == parent)
|
|
|
|
sibling_node = parent->output_state.subsurface_leaf_node;
|
|
|
|
else
|
|
|
|
sibling_node = op->sibling->output_state.subsurface_branch_node;
|
|
|
|
|
|
|
|
switch (op->placement)
|
|
|
|
{
|
|
|
|
case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
|
|
|
|
g_node_insert_after (parent->output_state.subsurface_branch_node,
|
|
|
|
sibling_node,
|
|
|
|
surface->output_state.subsurface_branch_node);
|
|
|
|
break;
|
|
|
|
case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
|
|
|
|
g_node_insert_before (parent->output_state.subsurface_branch_node,
|
|
|
|
sibling_node,
|
|
|
|
surface->output_state.subsurface_branch_node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 11:23:08 -04:00
|
|
|
void
|
2019-03-13 08:27:25 -04:00
|
|
|
meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandSurfaceState *state)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2019-08-26 09:09:53 -04:00
|
|
|
gboolean had_damage = FALSE;
|
2022-09-28 11:01:50 -04:00
|
|
|
int old_width, old_height;
|
|
|
|
|
|
|
|
old_width = meta_wayland_surface_get_width (surface);
|
|
|
|
old_height = meta_wayland_surface_get_height (surface);
|
2019-08-26 09:09:53 -04:00
|
|
|
|
2018-10-24 05:34:18 -04:00
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_PRE_STATE_APPLIED], 0);
|
|
|
|
|
2016-03-16 02:55:51 -04:00
|
|
|
if (surface->role)
|
|
|
|
{
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_pre_apply_state (surface->role, state);
|
2016-03-16 02:55:51 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->newly_attached && surface->unassigned.buffer)
|
2016-03-16 02:55:51 -04:00
|
|
|
{
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (surface->unassigned.buffer);
|
2016-03-16 02:55:51 -04:00
|
|
|
g_clear_object (&surface->unassigned.buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->newly_attached)
|
2014-04-18 15:41:48 -04:00
|
|
|
{
|
2016-03-16 02:47:53 -04:00
|
|
|
/* Always release any previously held buffer. If the buffer held is same
|
|
|
|
* as the newly attached buffer, we still need to release it here, because
|
|
|
|
* wl_surface.attach+commit and wl_buffer.release on the attached buffer
|
|
|
|
* is symmetric.
|
|
|
|
*/
|
|
|
|
if (surface->buffer_held)
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (surface->buffer);
|
2016-02-08 16:07:34 -05:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
g_set_object (&surface->buffer, state->buffer);
|
2022-07-13 11:10:05 -04:00
|
|
|
cogl_clear_object (&surface->output_state.texture);
|
|
|
|
surface->output_state.texture = g_steal_pointer (&state->texture);
|
2016-03-16 02:47:53 -04:00
|
|
|
|
|
|
|
/* If the newly attached buffer is going to be accessed directly without
|
|
|
|
* making a copy, such as an EGL buffer, mark it as in-use don't release
|
|
|
|
* it until is replaced by a subsequent wl_surface.commit or when the
|
|
|
|
* wl_surface is destroyed.
|
|
|
|
*/
|
2022-01-19 05:49:32 -05:00
|
|
|
surface->buffer_held =
|
|
|
|
(state->buffer &&
|
|
|
|
(state->buffer->type != META_WAYLAND_BUFFER_TYPE_SHM &&
|
|
|
|
state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL));
|
2014-04-18 15:41:48 -04:00
|
|
|
}
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->scale > 0)
|
|
|
|
surface->scale = state->scale;
|
2014-04-26 04:27:34 -04:00
|
|
|
|
2021-12-29 21:41:07 -05:00
|
|
|
if ((get_buffer_width (surface) % surface->scale != 0) ||
|
|
|
|
(get_buffer_height (surface) % surface->scale != 0))
|
|
|
|
{
|
2022-03-09 18:19:21 -05:00
|
|
|
struct wl_resource *resource = surface->resource;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
wl_client_get_credentials (wl_resource_get_client (resource), &pid, NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_warning ("Bug in client with pid %ld: Buffer size (%dx%d) is not an"
|
|
|
|
"integer multiple of the buffer_scale (%d).", (long) pid,
|
|
|
|
get_buffer_width (surface), get_buffer_height (surface),
|
|
|
|
surface->scale);
|
2021-12-29 21:41:07 -05:00
|
|
|
}
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->has_new_buffer_transform)
|
|
|
|
surface->buffer_transform = state->buffer_transform;
|
2018-11-26 13:40:57 -05:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->has_new_viewport_src_rect)
|
2018-11-24 14:25:38 -05:00
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
surface->viewport.src_rect.origin.x = state->viewport_src_rect.origin.x;
|
|
|
|
surface->viewport.src_rect.origin.y = state->viewport_src_rect.origin.y;
|
|
|
|
surface->viewport.src_rect.size.width = state->viewport_src_rect.size.width;
|
|
|
|
surface->viewport.src_rect.size.height = state->viewport_src_rect.size.height;
|
2018-11-24 14:25:38 -05:00
|
|
|
surface->viewport.has_src_rect = surface->viewport.src_rect.size.width > 0;
|
|
|
|
}
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->has_new_viewport_dst_size)
|
2018-11-24 14:25:38 -05:00
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
surface->viewport.dst_width = state->viewport_dst_width;
|
|
|
|
surface->viewport.dst_height = state->viewport_dst_height;
|
2018-11-24 14:25:38 -05:00
|
|
|
surface->viewport.has_dst_size = surface->viewport.dst_width > 0;
|
|
|
|
}
|
|
|
|
|
2022-09-28 11:01:50 -04:00
|
|
|
state->derived.surface_size_changed =
|
|
|
|
meta_wayland_surface_get_width (surface) != old_width ||
|
|
|
|
meta_wayland_surface_get_height (surface) != old_height;
|
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (!cairo_region_is_empty (state->surface_damage) ||
|
|
|
|
!cairo_region_is_empty (state->buffer_damage))
|
2019-08-26 09:09:53 -04:00
|
|
|
{
|
|
|
|
surface_process_damage (surface,
|
2019-03-13 08:27:25 -04:00
|
|
|
state->surface_damage,
|
|
|
|
state->buffer_damage);
|
2019-08-26 09:09:53 -04:00
|
|
|
had_damage = TRUE;
|
|
|
|
}
|
2014-04-12 02:29:05 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
surface->offset_x += state->dx;
|
|
|
|
surface->offset_y += state->dy;
|
2014-08-21 17:46:36 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->opaque_region_set)
|
2014-04-26 04:27:34 -04:00
|
|
|
{
|
2015-03-02 09:56:35 -05:00
|
|
|
if (surface->opaque_region)
|
|
|
|
cairo_region_destroy (surface->opaque_region);
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->opaque_region)
|
|
|
|
surface->opaque_region = cairo_region_reference (state->opaque_region);
|
2015-08-04 02:58:26 -04:00
|
|
|
else
|
|
|
|
surface->opaque_region = NULL;
|
2014-04-26 04:27:34 -04:00
|
|
|
}
|
2015-03-02 09:56:35 -05:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->input_region_set)
|
2014-04-26 04:27:34 -04:00
|
|
|
{
|
2015-03-02 09:56:35 -05:00
|
|
|
if (surface->input_region)
|
|
|
|
cairo_region_destroy (surface->input_region);
|
2019-03-13 08:27:25 -04:00
|
|
|
if (state->input_region)
|
|
|
|
surface->input_region = cairo_region_reference (state->input_region);
|
2015-08-04 02:58:26 -04:00
|
|
|
else
|
|
|
|
surface->input_region = NULL;
|
2014-04-26 04:27:34 -04:00
|
|
|
}
|
2014-04-12 02:42:40 -04:00
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
/*
|
|
|
|
* A new commit indicates a new content update, so any previous
|
|
|
|
* content update did not go on screen and needs to be discarded.
|
|
|
|
*/
|
|
|
|
meta_wayland_surface_discard_presentation_feedback (surface);
|
|
|
|
|
|
|
|
wl_list_insert_list (&surface->presentation_time.feedback_list,
|
|
|
|
&state->presentation_feedback_list);
|
|
|
|
wl_list_init (&state->presentation_feedback_list);
|
|
|
|
|
2020-10-08 08:34:28 -04:00
|
|
|
if (!wl_list_empty (&surface->presentation_time.feedback_list))
|
|
|
|
meta_wayland_compositor_add_presentation_feedback_surface (surface->compositor,
|
|
|
|
surface);
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
if (surface->role)
|
|
|
|
{
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_apply_state (surface->role, state);
|
2019-03-13 08:27:25 -04:00
|
|
|
g_assert (wl_list_empty (&state->frame_callback_list));
|
2015-07-08 04:14:00 -04:00
|
|
|
}
|
|
|
|
else
|
2015-08-09 06:54:00 -04:00
|
|
|
{
|
2020-04-27 09:43:19 -04:00
|
|
|
wl_list_insert_list (surface->unassigned.pending_frame_callback_list.prev,
|
|
|
|
&state->frame_callback_list);
|
|
|
|
wl_list_init (&state->frame_callback_list);
|
2016-03-16 02:55:51 -04:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
if (state->buffer)
|
2016-03-16 02:55:51 -04:00
|
|
|
{
|
|
|
|
/* The need to keep the wl_buffer from being released depends on what
|
|
|
|
* role the surface is given. That means we need to also keep a use
|
|
|
|
* count for wl_buffer's that are used by unassigned wl_surface's.
|
|
|
|
*/
|
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-06-22 12:43:11 -04:00
|
|
|
surface->unassigned.buffer = g_object_ref (state->buffer);
|
|
|
|
meta_wayland_buffer_inc_use_count (surface->unassigned.buffer);
|
2016-03-16 02:55:51 -04:00
|
|
|
}
|
2015-02-05 05:50:27 -05:00
|
|
|
}
|
2013-08-30 12:26:18 -04:00
|
|
|
|
2021-03-09 16:24:13 -05:00
|
|
|
if (state->subsurface_placement_ops)
|
2021-07-23 10:01:37 -04:00
|
|
|
meta_wayland_surface_notify_subsurface_state_changed (surface);
|
2021-03-09 16:24:13 -05:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
/* If we need to hold the newly attached buffer, drop its reference from the
|
|
|
|
* state, to prevent meta_wayland_transaction_entry_destroy from decreasing
|
|
|
|
* the use count.
|
2016-03-16 02:55:51 -04:00
|
|
|
*/
|
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-06-22 12:43:11 -04:00
|
|
|
if (state->newly_attached && surface->buffer_held)
|
|
|
|
g_clear_object (&state->buffer);
|
2016-03-16 02:55:51 -04:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
g_signal_emit (state,
|
|
|
|
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED],
|
2015-06-17 00:10:52 -04:00
|
|
|
0);
|
|
|
|
|
2019-08-26 09:09:53 -04:00
|
|
|
if (had_damage)
|
|
|
|
{
|
|
|
|
MetaWindow *toplevel_window;
|
|
|
|
|
|
|
|
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
|
|
|
|
if (toplevel_window)
|
|
|
|
{
|
|
|
|
MetaWindowActor *toplevel_window_actor;
|
|
|
|
|
|
|
|
toplevel_window_actor =
|
|
|
|
meta_window_actor_from_window (toplevel_window);
|
|
|
|
if (toplevel_window_actor)
|
|
|
|
meta_window_actor_notify_damaged (toplevel_window_actor);
|
|
|
|
}
|
|
|
|
}
|
2020-06-08 03:13:44 -04:00
|
|
|
|
|
|
|
if (surface->role)
|
|
|
|
meta_wayland_surface_role_post_apply_state (surface->role, state);
|
2014-02-01 16:24:43 -05:00
|
|
|
}
|
2014-01-13 17:31:25 -05:00
|
|
|
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *
|
2019-03-13 07:47:48 -04:00
|
|
|
meta_wayland_surface_get_pending_state (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
return surface->pending_state;
|
|
|
|
}
|
|
|
|
|
2021-06-07 09:19:47 -04:00
|
|
|
MetaWaylandTransaction *
|
|
|
|
meta_wayland_surface_ensure_transaction (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (!surface->sub.transaction)
|
|
|
|
surface->sub.transaction = meta_wayland_transaction_new (surface->compositor);
|
|
|
|
|
|
|
|
return surface->sub.transaction;
|
|
|
|
}
|
|
|
|
|
2014-04-12 02:45:38 -04:00
|
|
|
static void
|
2014-04-02 11:12:58 -04:00
|
|
|
meta_wayland_surface_commit (MetaWaylandSurface *surface)
|
|
|
|
{
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2022-07-13 11:10:05 -04:00
|
|
|
MetaWaylandBuffer *buffer = pending->buffer;
|
2021-06-07 09:19:47 -04:00
|
|
|
MetaWaylandTransaction *transaction;
|
|
|
|
MetaWaylandSurface *subsurface_surface;
|
2019-03-13 07:47:48 -04:00
|
|
|
|
2019-08-29 13:34:41 -04:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit,
|
2019-09-12 13:30:44 -04:00
|
|
|
"WaylandSurface (commit)");
|
2019-08-29 13:34:41 -04:00
|
|
|
|
2022-07-13 11:10:05 -04:00
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
g_clear_signal_handler (&pending->buffer_destroy_handler_id,
|
|
|
|
buffer);
|
|
|
|
|
2022-07-13 11:10:05 -04:00
|
|
|
if (!meta_wayland_buffer_is_realized (buffer))
|
|
|
|
meta_wayland_buffer_realize (buffer);
|
|
|
|
|
|
|
|
if (!meta_wayland_buffer_attach (buffer,
|
|
|
|
&surface->protocol_state.texture,
|
|
|
|
&error))
|
|
|
|
{
|
|
|
|
g_warning ("Could not import pending buffer: %s", error->message);
|
|
|
|
|
|
|
|
wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY,
|
|
|
|
"Failed to attach buffer to surface %i: %s",
|
|
|
|
wl_resource_get_id (surface->resource),
|
|
|
|
error->message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pending->texture = cogl_object_ref (surface->protocol_state.texture);
|
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-06-22 12:43:11 -04:00
|
|
|
|
|
|
|
g_object_ref (buffer);
|
|
|
|
meta_wayland_buffer_inc_use_count (buffer);
|
2022-07-13 11:10:05 -04:00
|
|
|
}
|
|
|
|
else if (pending->newly_attached)
|
|
|
|
{
|
|
|
|
cogl_clear_object (&surface->protocol_state.texture);
|
|
|
|
}
|
2017-05-05 21:41:51 -04:00
|
|
|
|
2021-06-07 09:19:47 -04:00
|
|
|
if (meta_wayland_surface_is_synchronized (surface))
|
|
|
|
transaction = meta_wayland_surface_ensure_transaction (surface);
|
|
|
|
else
|
|
|
|
transaction = meta_wayland_transaction_new (surface->compositor);
|
|
|
|
|
2022-11-01 11:43:03 -04:00
|
|
|
if (surface->role)
|
|
|
|
meta_wayland_surface_role_commit_state (surface->role, transaction, pending);
|
|
|
|
|
2021-06-07 09:19:47 -04:00
|
|
|
meta_wayland_transaction_merge_pending_state (transaction, surface);
|
|
|
|
|
2021-07-23 10:01:37 -04:00
|
|
|
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->protocol_state,
|
|
|
|
subsurface_surface)
|
2021-06-07 09:19:47 -04:00
|
|
|
{
|
|
|
|
if (!subsurface_surface->sub.transaction)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
meta_wayland_transaction_merge_into (subsurface_surface->sub.transaction,
|
|
|
|
transaction);
|
|
|
|
subsurface_surface->sub.transaction = NULL;
|
|
|
|
}
|
|
|
|
|
2015-01-26 03:46:20 -05:00
|
|
|
/*
|
|
|
|
* If this is a sub-surface and it is in effective synchronous mode, only
|
|
|
|
* cache the pending surface state until either one of the following two
|
|
|
|
* scenarios happens:
|
|
|
|
* 1) Its parent surface gets its state applied.
|
|
|
|
* 2) Its mode changes from synchronized to desynchronized and its parent
|
|
|
|
* surface is in effective desynchronized mode.
|
|
|
|
*/
|
2021-06-07 09:19:47 -04:00
|
|
|
if (!meta_wayland_surface_is_synchronized (surface))
|
|
|
|
meta_wayland_transaction_commit (transaction);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wl_surface_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-01-03 13:28:09 -05:00
|
|
|
wl_surface_attach (struct wl_client *client,
|
2014-04-02 11:12:58 -04:00
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
struct wl_resource *buffer_resource,
|
2022-01-03 13:28:09 -05:00
|
|
|
int32_t dx,
|
|
|
|
int32_t dy)
|
2014-04-02 11:12:58 -04:00
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
wl_resource_get_user_data (surface_resource);
|
2022-05-13 15:51:53 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2014-04-02 11:12:58 -04:00
|
|
|
MetaWaylandBuffer *buffer;
|
|
|
|
|
|
|
|
if (buffer_resource)
|
2022-05-13 15:51:53 -04:00
|
|
|
buffer = meta_wayland_buffer_from_resource (compositor, buffer_resource);
|
2014-04-02 11:12:58 -04:00
|
|
|
else
|
|
|
|
buffer = NULL;
|
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
if (surface->pending_state->buffer)
|
2016-03-15 00:46:06 -04:00
|
|
|
{
|
2019-03-13 07:47:48 -04:00
|
|
|
g_clear_signal_handler (&pending->buffer_destroy_handler_id,
|
|
|
|
pending->buffer);
|
2016-03-15 00:46:06 -04:00
|
|
|
}
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2021-03-22 06:49:11 -04:00
|
|
|
if (wl_resource_get_version (surface_resource) >=
|
|
|
|
WL_SURFACE_OFFSET_SINCE_VERSION &&
|
|
|
|
(dx != 0 || dy != 0))
|
|
|
|
{
|
|
|
|
wl_resource_post_error (surface_resource,
|
|
|
|
WL_SURFACE_ERROR_INVALID_OFFSET,
|
|
|
|
"Attaching with an offset is no longer allowed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->newly_attached = TRUE;
|
|
|
|
pending->buffer = buffer;
|
|
|
|
pending->dx = dx;
|
|
|
|
pending->dy = dy;
|
2014-04-02 11:12:58 -04:00
|
|
|
|
|
|
|
if (buffer)
|
2016-03-15 00:46:06 -04:00
|
|
|
{
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->buffer_destroy_handler_id =
|
2016-03-15 00:46:06 -04:00
|
|
|
g_signal_connect (buffer, "resource-destroyed",
|
|
|
|
G_CALLBACK (pending_buffer_resource_destroyed),
|
2019-03-13 07:47:48 -04:00
|
|
|
pending);
|
2016-03-15 00:46:06 -04:00
|
|
|
}
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-06-05 08:08:04 -04:00
|
|
|
wl_surface_damage (struct wl_client *client,
|
2014-04-02 11:12:58 -04:00
|
|
|
struct wl_resource *surface_resource,
|
2017-06-05 08:08:04 -04:00
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
2014-04-02 11:12:58 -04:00
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2017-06-05 08:08:04 -04:00
|
|
|
cairo_rectangle_int_t rectangle;
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2017-06-05 08:08:04 -04:00
|
|
|
rectangle = (cairo_rectangle_int_t) {
|
|
|
|
.x = x,
|
|
|
|
.y = y,
|
|
|
|
.width = width,
|
|
|
|
.height = height
|
|
|
|
};
|
2019-03-13 07:47:48 -04:00
|
|
|
cairo_region_union_rectangle (pending->surface_damage, &rectangle);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
destroy_frame_callback (struct wl_resource *callback_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandFrameCallback *callback =
|
|
|
|
wl_resource_get_user_data (callback_resource);
|
|
|
|
|
|
|
|
wl_list_remove (&callback->link);
|
2020-10-19 13:57:57 -04:00
|
|
|
g_free (callback);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-01-03 13:28:09 -05:00
|
|
|
wl_surface_frame (struct wl_client *client,
|
2014-04-02 11:12:58 -04:00
|
|
|
struct wl_resource *surface_resource,
|
2022-01-03 13:28:09 -05:00
|
|
|
uint32_t callback_id)
|
2014-04-02 11:12:58 -04:00
|
|
|
{
|
|
|
|
MetaWaylandFrameCallback *callback;
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2020-10-19 13:57:57 -04:00
|
|
|
callback = g_new0 (MetaWaylandFrameCallback, 1);
|
2015-02-25 10:26:01 -05:00
|
|
|
callback->surface = surface;
|
2019-10-09 15:27:11 -04:00
|
|
|
callback->resource = wl_resource_create (client,
|
|
|
|
&wl_callback_interface,
|
|
|
|
META_WL_CALLBACK_VERSION,
|
|
|
|
callback_id);
|
|
|
|
wl_resource_set_implementation (callback->resource, NULL, callback,
|
|
|
|
destroy_frame_callback);
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
wl_list_insert (pending->frame_callback_list.prev, &callback->link);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-01-03 13:28:09 -05:00
|
|
|
wl_surface_set_opaque_region (struct wl_client *client,
|
2014-04-02 11:12:58 -04:00
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
struct wl_resource *region_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
g_clear_pointer (&pending->opaque_region, cairo_region_destroy);
|
2014-04-02 11:12:58 -04:00
|
|
|
if (region_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
2014-10-07 23:23:55 -04:00
|
|
|
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->opaque_region = cairo_region_copy (cr_region);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->opaque_region_set = TRUE;
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-01-03 13:28:09 -05:00
|
|
|
wl_surface_set_input_region (struct wl_client *client,
|
2014-04-02 11:12:58 -04:00
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
struct wl_resource *region_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2014-04-02 11:12:58 -04:00
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
g_clear_pointer (&pending->input_region, cairo_region_destroy);
|
2014-04-02 11:12:58 -04:00
|
|
|
if (region_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
2014-10-07 23:23:55 -04:00
|
|
|
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->input_region = cairo_region_copy (cr_region);
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->input_region_set = TRUE;
|
2014-04-02 11:12:58 -04:00
|
|
|
}
|
|
|
|
|
2014-02-01 16:24:43 -05:00
|
|
|
static void
|
2022-01-03 13:28:09 -05:00
|
|
|
wl_surface_commit (struct wl_client *client,
|
2014-04-02 11:10:20 -04:00
|
|
|
struct wl_resource *resource)
|
2014-02-01 16:24:43 -05:00
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
|
|
|
|
2014-04-02 11:12:58 -04:00
|
|
|
meta_wayland_surface_commit (surface);
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
|
2018-11-26 13:40:57 -05:00
|
|
|
static MetaMonitorTransform
|
|
|
|
transform_from_wl_output_transform (int32_t transform_value)
|
|
|
|
{
|
|
|
|
enum wl_output_transform transform = transform_value;
|
|
|
|
|
|
|
|
switch (transform)
|
|
|
|
{
|
|
|
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
|
|
|
return META_MONITOR_TRANSFORM_NORMAL;
|
|
|
|
case WL_OUTPUT_TRANSFORM_90:
|
2022-06-14 13:02:03 -04:00
|
|
|
return META_MONITOR_TRANSFORM_90;
|
2018-11-26 13:40:57 -05:00
|
|
|
case WL_OUTPUT_TRANSFORM_180:
|
|
|
|
return META_MONITOR_TRANSFORM_180;
|
|
|
|
case WL_OUTPUT_TRANSFORM_270:
|
2022-06-14 13:02:03 -04:00
|
|
|
return META_MONITOR_TRANSFORM_270;
|
2018-11-26 13:40:57 -05:00
|
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
|
|
|
return META_MONITOR_TRANSFORM_FLIPPED;
|
|
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
2022-06-14 13:02:03 -04:00
|
|
|
return META_MONITOR_TRANSFORM_FLIPPED_90;
|
2018-11-26 13:40:57 -05:00
|
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
|
|
|
return META_MONITOR_TRANSFORM_FLIPPED_180;
|
|
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
2022-06-14 13:02:03 -04:00
|
|
|
return META_MONITOR_TRANSFORM_FLIPPED_270;
|
2018-11-26 13:40:57 -05:00
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 12:26:18 -04:00
|
|
|
static void
|
2018-11-26 13:40:57 -05:00
|
|
|
wl_surface_set_buffer_transform (struct wl_client *client,
|
2014-04-02 11:10:20 -04:00
|
|
|
struct wl_resource *resource,
|
2018-11-26 13:40:57 -05:00
|
|
|
int32_t transform)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2018-11-26 13:40:57 -05:00
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2018-11-26 13:40:57 -05:00
|
|
|
MetaMonitorTransform buffer_transform;
|
|
|
|
|
|
|
|
buffer_transform = transform_from_wl_output_transform (transform);
|
|
|
|
|
|
|
|
if (buffer_transform == -1)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
WL_SURFACE_ERROR_INVALID_TRANSFORM,
|
2020-10-02 11:52:37 -04:00
|
|
|
"Trying to set invalid buffer_transform of %d",
|
2018-11-26 13:40:57 -05:00
|
|
|
transform);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->buffer_transform = buffer_transform;
|
|
|
|
pending->has_new_buffer_transform = TRUE;
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-04-02 11:10:20 -04:00
|
|
|
wl_surface_set_buffer_scale (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int scale)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2014-04-26 04:27:34 -04:00
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2019-03-11 09:33:38 -04:00
|
|
|
|
|
|
|
if (scale <= 0)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
WL_SURFACE_ERROR_INVALID_SCALE,
|
2020-10-02 11:52:37 -04:00
|
|
|
"Trying to set invalid buffer_scale of %d",
|
2019-03-11 09:33:38 -04:00
|
|
|
scale);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 07:47:48 -04:00
|
|
|
pending->scale = scale;
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
|
2017-06-05 08:08:04 -04:00
|
|
|
static void
|
|
|
|
wl_surface_damage_buffer (struct wl_client *client,
|
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
2019-03-13 08:27:25 -04:00
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
2017-06-05 08:08:04 -04:00
|
|
|
cairo_rectangle_int_t rectangle;
|
|
|
|
|
|
|
|
rectangle = (cairo_rectangle_int_t) {
|
|
|
|
.x = x,
|
|
|
|
.y = y,
|
|
|
|
.width = width,
|
|
|
|
.height = height
|
|
|
|
};
|
2019-03-13 07:47:48 -04:00
|
|
|
cairo_region_union_rectangle (pending->buffer_damage, &rectangle);
|
2017-06-05 08:08:04 -04:00
|
|
|
}
|
|
|
|
|
2021-03-22 06:49:11 -04:00
|
|
|
static void
|
|
|
|
wl_surface_offset (struct wl_client *client,
|
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
int32_t dx,
|
|
|
|
int32_t dy)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
|
|
|
MetaWaylandSurfaceState *pending = surface->pending_state;
|
|
|
|
|
|
|
|
pending->dx = dx;
|
|
|
|
pending->dy = dy;
|
|
|
|
}
|
|
|
|
|
2014-08-04 10:28:44 -04:00
|
|
|
static const struct wl_surface_interface meta_wayland_wl_surface_interface = {
|
2014-04-02 11:10:20 -04:00
|
|
|
wl_surface_destroy,
|
|
|
|
wl_surface_attach,
|
|
|
|
wl_surface_damage,
|
|
|
|
wl_surface_frame,
|
|
|
|
wl_surface_set_opaque_region,
|
|
|
|
wl_surface_set_input_region,
|
|
|
|
wl_surface_commit,
|
|
|
|
wl_surface_set_buffer_transform,
|
2017-06-05 08:08:04 -04:00
|
|
|
wl_surface_set_buffer_scale,
|
|
|
|
wl_surface_damage_buffer,
|
2021-03-22 06:49:11 -04:00
|
|
|
wl_surface_offset,
|
2013-08-30 12:26:18 -04:00
|
|
|
};
|
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
static void
|
|
|
|
handle_output_destroyed (MetaWaylandOutput *wayland_output,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
set_surface_is_on_output (surface, wayland_output, FALSE);
|
|
|
|
}
|
|
|
|
|
2020-03-09 07:33:17 -04:00
|
|
|
static void
|
|
|
|
handle_output_bound (MetaWaylandOutput *wayland_output,
|
|
|
|
struct wl_resource *output_resource,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (wl_resource_get_client (output_resource) ==
|
|
|
|
wl_resource_get_client (surface->resource))
|
|
|
|
wl_surface_send_enter (surface->resource, output_resource);
|
|
|
|
}
|
|
|
|
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
static void
|
|
|
|
surface_entered_output (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandOutput *wayland_output)
|
|
|
|
{
|
2020-05-07 10:44:04 -04:00
|
|
|
g_signal_connect (wayland_output, "output-destroyed",
|
|
|
|
G_CALLBACK (handle_output_destroyed),
|
|
|
|
surface);
|
|
|
|
|
2021-07-29 12:14:20 -04:00
|
|
|
if (surface->resource)
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
{
|
2021-07-29 12:14:20 -04:00
|
|
|
const GList *l;
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2021-07-29 12:14:20 -04:00
|
|
|
for (l = meta_wayland_output_get_resources (wayland_output); l; l = l->next)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource = l->data;
|
|
|
|
|
|
|
|
if (wl_resource_get_client (resource) !=
|
|
|
|
wl_resource_get_client (surface->resource))
|
|
|
|
continue;
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2021-07-29 12:14:20 -04:00
|
|
|
wl_surface_send_enter (surface->resource, resource);
|
|
|
|
}
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
}
|
2020-03-09 07:33:17 -04:00
|
|
|
|
|
|
|
g_signal_connect (wayland_output, "output-bound",
|
|
|
|
G_CALLBACK (handle_output_bound),
|
|
|
|
surface);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
surface_left_output (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandOutput *wayland_output)
|
|
|
|
{
|
2021-02-05 10:38:31 -05:00
|
|
|
const GList *l;
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
g_signal_handlers_disconnect_by_func (wayland_output,
|
|
|
|
G_CALLBACK (handle_output_destroyed),
|
|
|
|
surface);
|
|
|
|
|
2020-03-09 07:33:17 -04:00
|
|
|
g_signal_handlers_disconnect_by_func (wayland_output,
|
|
|
|
G_CALLBACK (handle_output_bound),
|
|
|
|
surface);
|
|
|
|
|
2021-07-29 12:14:20 -04:00
|
|
|
if (!surface->resource)
|
|
|
|
return;
|
|
|
|
|
2021-02-05 10:38:31 -05:00
|
|
|
for (l = meta_wayland_output_get_resources (wayland_output); l; l = l->next)
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
{
|
2021-02-05 10:38:31 -05:00
|
|
|
struct wl_resource *resource = l->data;
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
|
|
|
if (wl_resource_get_client (resource) !=
|
|
|
|
wl_resource_get_client (surface->resource))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
wl_surface_send_leave (surface->resource, resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_surface_is_on_output (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandOutput *wayland_output,
|
|
|
|
gboolean is_on_output)
|
|
|
|
{
|
2020-05-07 10:44:04 -04:00
|
|
|
gboolean was_on_output;
|
|
|
|
|
|
|
|
was_on_output = g_hash_table_contains (surface->outputs, wayland_output);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
|
|
|
if (!was_on_output && is_on_output)
|
|
|
|
{
|
2020-05-07 10:44:04 -04:00
|
|
|
g_hash_table_add (surface->outputs, wayland_output);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
surface_entered_output (surface, wayland_output);
|
|
|
|
}
|
|
|
|
else if (was_on_output && !is_on_output)
|
|
|
|
{
|
2020-05-07 10:44:04 -04:00
|
|
|
g_hash_table_remove (surface->outputs, wayland_output);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
surface_left_output (surface, wayland_output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaWaylandOutput *wayland_output = value;
|
|
|
|
MetaWaylandSurface *surface = user_data;
|
2016-11-25 01:31:38 -05:00
|
|
|
MetaLogicalMonitor *logical_monitor;
|
2016-11-25 01:38:28 -05:00
|
|
|
gboolean is_on_logical_monitor;
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
g_assert (surface->role);
|
|
|
|
|
2021-02-05 10:46:43 -05:00
|
|
|
logical_monitor = meta_wayland_output_get_logical_monitor (wayland_output);
|
2016-11-25 01:31:38 -05:00
|
|
|
if (!logical_monitor)
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
{
|
|
|
|
set_surface_is_on_output (surface, wayland_output, FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-25 01:38:28 -05:00
|
|
|
is_on_logical_monitor =
|
|
|
|
meta_wayland_surface_role_is_on_logical_monitor (surface->role,
|
|
|
|
logical_monitor);
|
|
|
|
set_surface_is_on_output (surface, wayland_output, is_on_logical_monitor);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
}
|
|
|
|
|
2015-10-14 00:33:15 -04:00
|
|
|
static void
|
2020-03-09 07:33:17 -04:00
|
|
|
surface_output_disconnect_signals (gpointer key,
|
|
|
|
gpointer value,
|
|
|
|
gpointer user_data)
|
2015-10-14 00:33:15 -04:00
|
|
|
{
|
2020-03-09 07:33:17 -04:00
|
|
|
MetaWaylandOutput *wayland_output = key;
|
|
|
|
MetaWaylandSurface *surface = user_data;
|
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
g_signal_handlers_disconnect_by_func (wayland_output,
|
|
|
|
G_CALLBACK (handle_output_destroyed),
|
|
|
|
surface);
|
|
|
|
|
2020-03-09 07:33:17 -04:00
|
|
|
g_signal_handlers_disconnect_by_func (wayland_output,
|
|
|
|
G_CALLBACK (handle_output_bound),
|
|
|
|
surface);
|
2015-10-14 00:33:15 -04:00
|
|
|
}
|
|
|
|
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
void
|
|
|
|
meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (!surface->compositor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_hash_table_foreach (surface->compositor->outputs,
|
|
|
|
update_surface_output_state,
|
|
|
|
surface);
|
|
|
|
}
|
|
|
|
|
2014-02-24 13:32:17 -05:00
|
|
|
void
|
wayland: Move MetaWindow ownership to window owning roles
There are two surface roles owning a MetaWindow: MetaWaylandShellSurface
(basis of MetaWaylandXdgToplevel, MetaWaylandXdgPopup,
MetaWaylandWlShellSurface, etc), and MetaXwaylandSurface.
With these two role types, the MetaWindow has two different types of
life times. With MetaWaylandShellSurface, the window is owned and
managed by the role itself, while with MetaXwaylandSurface, the
MetaWindow is tied to the X11 window, while the Wayland surface and its
role plays more the role of the backing rendering surface.
Before, for historical reasons, MetaWindow was part of
MetaWaylandSurface, even though just some roles used it, and before
'wayland: Untie MetaWindowXwayland lifetime from the wl_surface' had
equivalent life times as well. But since that commit, the management
changed. To not have the same fied in MetaWaylandSurface being managed
in such drastically different ways, rearrange it so that the roles that
has a MetaWindow themself manages it in the way it is meant to; meaning
MetaWaylandShellSurface practically owns it, while with Xwayland, the
existance of a MetaWindow is tracked via X11.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/835
2019-10-09 03:57:40 -04:00
|
|
|
meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface)
|
2013-11-26 13:04:37 -05:00
|
|
|
{
|
wayland: Move MetaWindow ownership to window owning roles
There are two surface roles owning a MetaWindow: MetaWaylandShellSurface
(basis of MetaWaylandXdgToplevel, MetaWaylandXdgPopup,
MetaWaylandWlShellSurface, etc), and MetaXwaylandSurface.
With these two role types, the MetaWindow has two different types of
life times. With MetaWaylandShellSurface, the window is owned and
managed by the role itself, while with MetaXwaylandSurface, the
MetaWindow is tied to the X11 window, while the Wayland surface and its
role plays more the role of the backing rendering surface.
Before, for historical reasons, MetaWindow was part of
MetaWaylandSurface, even though just some roles used it, and before
'wayland: Untie MetaWindowXwayland lifetime from the wl_surface' had
equivalent life times as well. But since that commit, the management
changed. To not have the same fied in MetaWaylandSurface being managed
in such drastically different ways, rearrange it so that the roles that
has a MetaWindow themself manages it in the way it is meant to; meaning
MetaWaylandShellSurface practically owns it, while with Xwayland, the
existance of a MetaWindow is tracked via X11.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/835
2019-10-09 03:57:40 -04:00
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_UNMAPPED], 0);
|
2014-02-18 16:39:23 -05:00
|
|
|
}
|
|
|
|
|
2013-08-30 12:26:18 -04:00
|
|
|
static void
|
2021-07-23 12:33:39 -04:00
|
|
|
meta_wayland_surface_finalize (GObject *object)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2021-07-23 12:33:39 -04:00
|
|
|
MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
|
2014-02-18 16:39:23 -05:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-08-18 23:06:46 -04:00
|
|
|
MetaWaylandFrameCallback *cb, *next;
|
2013-08-30 12:26:18 -04:00
|
|
|
|
2021-08-06 11:00:19 -04:00
|
|
|
g_clear_object (&surface->scanout_candidate);
|
2015-07-08 04:14:00 -04:00
|
|
|
g_clear_object (&surface->role);
|
|
|
|
|
2016-03-16 02:55:51 -04:00
|
|
|
if (surface->unassigned.buffer)
|
|
|
|
{
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (surface->unassigned.buffer);
|
2016-03-16 02:55:51 -04:00
|
|
|
g_clear_object (&surface->unassigned.buffer);
|
|
|
|
}
|
|
|
|
|
2016-03-16 02:47:53 -04:00
|
|
|
if (surface->buffer_held)
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (surface->buffer);
|
2022-07-13 11:10:05 -04:00
|
|
|
g_clear_pointer (&surface->output_state.texture, cogl_object_unref);
|
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-06-22 12:43:11 -04:00
|
|
|
g_clear_object (&surface->buffer);
|
2016-03-16 02:47:53 -04:00
|
|
|
|
2015-03-02 09:56:35 -05:00
|
|
|
if (surface->opaque_region)
|
|
|
|
cairo_region_destroy (surface->opaque_region);
|
|
|
|
if (surface->input_region)
|
|
|
|
cairo_region_destroy (surface->input_region);
|
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
meta_wayland_compositor_remove_frame_callback_surface (compositor, surface);
|
2020-10-08 08:34:28 -04:00
|
|
|
meta_wayland_compositor_remove_presentation_feedback_surface (compositor,
|
|
|
|
surface);
|
2015-02-25 10:26:01 -05:00
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
g_hash_table_foreach (surface->outputs,
|
2020-03-09 07:33:17 -04:00
|
|
|
surface_output_disconnect_signals,
|
2019-10-09 15:27:11 -04:00
|
|
|
surface);
|
2020-05-07 10:44:04 -04:00
|
|
|
g_hash_table_destroy (surface->outputs);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
wl_list_for_each_safe (cb, next,
|
|
|
|
&surface->unassigned.pending_frame_callback_list,
|
|
|
|
link)
|
2015-08-18 23:06:46 -04:00
|
|
|
wl_resource_destroy (cb->resource);
|
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
meta_wayland_surface_discard_presentation_feedback (surface);
|
|
|
|
|
2021-07-23 10:01:37 -04:00
|
|
|
g_clear_pointer (&surface->output_state.subsurface_branch_node, g_node_destroy);
|
2019-06-30 09:18:46 -04:00
|
|
|
|
2017-03-17 08:34:52 -04:00
|
|
|
g_hash_table_destroy (surface->shortcut_inhibited_seats);
|
|
|
|
|
2021-07-23 12:33:39 -04:00
|
|
|
G_OBJECT_CLASS (meta_wayland_surface_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wl_surface_destructor (struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
2021-07-23 10:01:37 -04:00
|
|
|
MetaWaylandSurface *subsurface_surface;
|
2021-07-23 12:33:39 -04:00
|
|
|
|
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0);
|
|
|
|
|
|
|
|
g_clear_object (&surface->pending_state);
|
|
|
|
g_clear_pointer (&surface->sub.transaction, meta_wayland_transaction_free);
|
|
|
|
|
|
|
|
if (surface->resource)
|
|
|
|
wl_resource_set_user_data (g_steal_pointer (&surface->resource), NULL);
|
|
|
|
|
2021-07-23 10:01:37 -04:00
|
|
|
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->protocol_state,
|
|
|
|
subsurface_surface)
|
|
|
|
meta_wayland_subsurface_parent_destroyed (subsurface_surface);
|
|
|
|
|
2021-07-23 12:33:39 -04:00
|
|
|
g_clear_pointer (&surface->wl_subsurface, wl_resource_destroy);
|
2021-07-23 10:01:37 -04:00
|
|
|
g_clear_pointer (&surface->protocol_state.subsurface_branch_node, g_node_destroy);
|
2021-07-23 12:33:39 -04:00
|
|
|
|
2022-07-13 11:10:05 -04:00
|
|
|
cogl_clear_object (&surface->protocol_state.texture);
|
|
|
|
|
2021-07-23 12:33:39 -04:00
|
|
|
/*
|
|
|
|
* Any transactions referencing this surface will keep it alive until they get
|
|
|
|
* applied/destroyed. The last reference will be dropped in
|
|
|
|
* meta_wayland_transaction_free.
|
|
|
|
*/
|
2015-07-07 23:21:23 -04:00
|
|
|
g_object_unref (surface);
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MetaWaylandSurface *
|
|
|
|
meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
2014-04-22 18:22:13 -04:00
|
|
|
struct wl_client *client,
|
|
|
|
struct wl_resource *compositor_resource,
|
|
|
|
guint32 id)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2015-07-07 23:21:23 -04:00
|
|
|
MetaWaylandSurface *surface = g_object_new (META_TYPE_WAYLAND_SURFACE, NULL);
|
2019-10-09 15:27:11 -04:00
|
|
|
int surface_version;
|
2013-08-30 12:26:18 -04:00
|
|
|
|
|
|
|
surface->compositor = compositor;
|
2014-04-26 04:27:34 -04:00
|
|
|
surface->scale = 1;
|
2013-08-30 12:26:18 -04:00
|
|
|
|
2019-10-09 15:27:11 -04:00
|
|
|
surface_version = wl_resource_get_version (compositor_resource);
|
|
|
|
surface->resource = wl_resource_create (client,
|
|
|
|
&wl_surface_interface,
|
|
|
|
surface_version,
|
|
|
|
id);
|
|
|
|
wl_resource_set_implementation (surface->resource,
|
|
|
|
&meta_wayland_wl_surface_interface,
|
|
|
|
surface,
|
|
|
|
wl_surface_destructor);
|
2013-08-30 12:26:18 -04:00
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
wl_list_init (&surface->unassigned.pending_frame_callback_list);
|
2015-08-18 23:06:46 -04:00
|
|
|
|
2020-05-07 10:44:04 -04:00
|
|
|
surface->outputs = g_hash_table_new (NULL, NULL);
|
2017-03-17 08:34:52 -04:00
|
|
|
surface->shortcut_inhibited_seats = g_hash_table_new (NULL, NULL);
|
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
2015-02-03 02:49:52 -05:00
|
|
|
|
2020-10-07 05:02:41 -04:00
|
|
|
wl_list_init (&surface->presentation_time.feedback_list);
|
|
|
|
|
2018-04-06 09:47:50 -04:00
|
|
|
meta_wayland_compositor_notify_surface_id (compositor, id, surface);
|
|
|
|
|
2013-08-30 12:26:18 -04:00
|
|
|
return surface;
|
|
|
|
}
|
|
|
|
|
2015-12-14 23:51:24 -05:00
|
|
|
gboolean
|
|
|
|
meta_wayland_surface_begin_grab_op (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandSeat *seat,
|
|
|
|
MetaGrabOp grab_op,
|
|
|
|
gfloat x,
|
|
|
|
gfloat y)
|
2013-11-14 21:45:34 -05:00
|
|
|
{
|
2019-10-09 03:37:04 -04:00
|
|
|
MetaWindow *window = meta_wayland_surface_get_window (surface);
|
2013-11-14 21:45:34 -05:00
|
|
|
|
|
|
|
if (grab_op == META_GRAB_OP_NONE)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-03-23 13:45:45 -04:00
|
|
|
/* This is an input driven operation so we set frame_action to
|
|
|
|
constrain it in the same way as it would be if the window was
|
|
|
|
being moved/resized via a SSD event. */
|
2013-11-14 21:45:34 -05:00
|
|
|
return meta_display_begin_grab_op (window->display,
|
|
|
|
window,
|
|
|
|
grab_op,
|
|
|
|
TRUE, /* pointer_already_grabbed */
|
2016-03-23 13:45:45 -04:00
|
|
|
TRUE, /* frame_action */
|
2013-11-14 21:45:34 -05:00
|
|
|
1, /* button. XXX? */
|
|
|
|
0, /* modmask */
|
|
|
|
meta_display_get_current_time_roundtrip (window->display),
|
2014-07-21 19:28:39 -04:00
|
|
|
x, y);
|
2013-11-14 21:45:34 -05:00
|
|
|
}
|
|
|
|
|
2019-10-21 07:31:25 -04:00
|
|
|
/**
|
|
|
|
* meta_wayland_shell_init:
|
|
|
|
* @compositor: The #MetaWaylandCompositor object
|
|
|
|
*
|
|
|
|
* Initializes the Wayland interfaces providing features that deal with
|
2021-09-16 16:23:18 -04:00
|
|
|
* desktop-specific conundrums, like XDG shell, etc.
|
2019-10-21 07:31:25 -04:00
|
|
|
*/
|
2013-08-30 12:26:18 -04:00
|
|
|
void
|
2014-04-22 18:05:44 -04:00
|
|
|
meta_wayland_shell_init (MetaWaylandCompositor *compositor)
|
2013-08-30 12:26:18 -04:00
|
|
|
{
|
2015-12-14 23:51:24 -05:00
|
|
|
meta_wayland_xdg_shell_init (compositor);
|
2018-08-23 09:53:55 -04:00
|
|
|
meta_wayland_init_gtk_shell (compositor);
|
2018-11-24 14:25:38 -05:00
|
|
|
meta_wayland_init_viewporter (compositor);
|
2013-08-30 12:26:18 -04:00
|
|
|
}
|
|
|
|
|
2014-02-09 11:45:09 -05:00
|
|
|
void
|
2019-07-05 12:10:14 -04:00
|
|
|
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandWindowConfiguration *configuration)
|
2014-05-05 19:09:07 -04:00
|
|
|
{
|
2017-12-12 23:37:23 -05:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (surface->role);
|
2014-05-05 19:09:07 -04:00
|
|
|
|
2016-06-28 02:56:20 -04:00
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_CONFIGURE], 0);
|
|
|
|
|
2019-07-05 12:10:14 -04:00
|
|
|
meta_wayland_shell_surface_configure (shell_surface, configuration);
|
2013-11-12 15:52:03 -05:00
|
|
|
}
|
2013-11-21 14:20:52 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
2014-02-15 10:26:43 -05:00
|
|
|
guint32 serial)
|
2013-11-21 14:20:52 -05:00
|
|
|
{
|
2017-12-12 23:37:23 -05:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (surface->role);
|
2015-12-14 23:51:24 -05:00
|
|
|
|
2017-12-12 23:37:23 -05:00
|
|
|
meta_wayland_shell_surface_ping (shell_surface, serial);
|
2013-11-21 14:20:52 -05:00
|
|
|
}
|
2014-02-07 17:28:33 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_delete (MetaWaylandSurface *surface)
|
|
|
|
{
|
2017-12-12 23:37:23 -05:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (surface->role);
|
2015-12-14 23:51:24 -05:00
|
|
|
|
2017-12-12 23:37:23 -05:00
|
|
|
meta_wayland_shell_surface_close (shell_surface);
|
2014-02-07 17:28:33 -05:00
|
|
|
}
|
2014-02-28 00:18:42 -05:00
|
|
|
|
2015-12-15 09:09:20 -05:00
|
|
|
void
|
|
|
|
meta_wayland_surface_window_managed (MetaWaylandSurface *surface,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
2017-12-12 23:37:23 -05:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (surface->role);
|
2015-12-15 09:09:20 -05:00
|
|
|
|
2017-12-12 23:37:23 -05:00
|
|
|
meta_wayland_shell_surface_managed (shell_surface, window);
|
2015-12-15 09:09:20 -05:00
|
|
|
}
|
|
|
|
|
2015-05-18 07:24:27 -04:00
|
|
|
void
|
|
|
|
meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandDataOffer *offer)
|
|
|
|
{
|
2022-05-30 17:48:44 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-05-18 07:24:27 -04:00
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
|
|
|
|
surface->dnd.funcs->focus_in (data_device, surface, offer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
2022-05-30 17:48:44 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-05-18 07:24:27 -04:00
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
|
|
|
|
surface->dnd.funcs->motion (data_device, surface, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface)
|
|
|
|
{
|
2022-05-30 17:48:44 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-05-18 07:24:27 -04:00
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
|
|
|
|
surface->dnd.funcs->focus_out (data_device, surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface)
|
|
|
|
{
|
2022-05-30 17:48:44 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-05-18 07:24:27 -04:00
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
|
|
|
|
surface->dnd.funcs->drop (data_device, surface);
|
2015-09-28 08:16:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface)
|
|
|
|
{
|
2022-05-30 17:48:44 -04:00
|
|
|
MetaWaylandCompositor *compositor = surface->compositor;
|
2015-09-28 08:16:20 -04:00
|
|
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
|
|
|
|
|
|
|
surface->dnd.funcs->update (data_device, surface);
|
2015-05-18 07:24:27 -04:00
|
|
|
}
|
2015-03-23 09:10:20 -04:00
|
|
|
|
2016-01-14 04:43:47 -05:00
|
|
|
MetaWaylandSurface *
|
|
|
|
meta_wayland_surface_get_toplevel (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (surface->role)
|
|
|
|
return meta_wayland_surface_role_get_toplevel (surface->role);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-23 09:10:20 -04:00
|
|
|
MetaWindow *
|
|
|
|
meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
|
|
|
|
{
|
2016-01-14 04:43:47 -05:00
|
|
|
MetaWaylandSurface *toplevel;
|
2015-03-23 09:10:20 -04:00
|
|
|
|
2016-01-14 04:43:47 -05:00
|
|
|
toplevel = meta_wayland_surface_get_toplevel (surface);
|
|
|
|
if (toplevel)
|
2019-10-09 03:37:04 -04:00
|
|
|
return meta_wayland_surface_get_window (toplevel);
|
2016-01-14 04:43:47 -05:00
|
|
|
else
|
|
|
|
return NULL;
|
2015-03-23 09:10:20 -04:00
|
|
|
}
|
2015-07-07 23:21:23 -04:00
|
|
|
|
2015-06-16 22:16:02 -04:00
|
|
|
void
|
|
|
|
meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
|
|
|
float abs_x,
|
|
|
|
float abs_y,
|
|
|
|
float *sx,
|
|
|
|
float *sy)
|
|
|
|
{
|
2019-10-09 03:47:23 -04:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class =
|
|
|
|
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role);
|
2016-07-14 08:39:26 -04:00
|
|
|
|
2019-10-09 03:47:23 -04:00
|
|
|
surface_role_class->get_relative_coordinates (surface->role,
|
|
|
|
abs_x, abs_y,
|
|
|
|
sx, sy);
|
2015-06-16 22:16:02 -04:00
|
|
|
}
|
|
|
|
|
2015-06-17 00:10:52 -04:00
|
|
|
void
|
|
|
|
meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
|
|
|
float sx,
|
|
|
|
float sy,
|
|
|
|
float *x,
|
|
|
|
float *y)
|
|
|
|
{
|
|
|
|
ClutterActor *actor =
|
2018-12-26 10:41:26 -05:00
|
|
|
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
2019-02-20 08:18:48 -05:00
|
|
|
graphene_point3d_t sv = {
|
2019-11-02 15:05:57 -04:00
|
|
|
.x = sx,
|
|
|
|
.y = sy,
|
2015-06-17 00:10:52 -04:00
|
|
|
};
|
2019-02-20 08:18:48 -05:00
|
|
|
graphene_point3d_t v = { 0 };
|
2015-06-17 00:10:52 -04:00
|
|
|
|
|
|
|
clutter_actor_apply_relative_transform_to_point (actor, NULL, &sv, &v);
|
|
|
|
|
|
|
|
*x = v.x;
|
|
|
|
*y = v.y;
|
|
|
|
}
|
|
|
|
|
2015-07-07 23:21:23 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_init (MetaWaylandSurface *surface)
|
|
|
|
{
|
2021-05-28 06:39:48 -04:00
|
|
|
surface->pending_state = meta_wayland_surface_state_new ();
|
2019-08-13 12:46:36 -04:00
|
|
|
|
2021-07-23 10:01:37 -04:00
|
|
|
surface->output_state.subsurface_branch_node = g_node_new (surface);
|
|
|
|
surface->output_state.subsurface_leaf_node =
|
|
|
|
g_node_prepend_data (surface->output_state.subsurface_branch_node, surface);
|
|
|
|
|
|
|
|
surface->protocol_state.subsurface_branch_node = g_node_new (surface);
|
|
|
|
surface->protocol_state.subsurface_leaf_node =
|
|
|
|
g_node_prepend_data (surface->protocol_state.subsurface_branch_node, surface);
|
2015-07-07 23:21:23 -04:00
|
|
|
}
|
|
|
|
|
2021-08-06 11:00:19 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_SCANOUT_CANDIDATE:
|
|
|
|
g_value_set_object (value, surface->scanout_candidate);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-07 23:21:23 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
|
|
|
|
{
|
2015-10-22 08:07:52 -04:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2021-07-23 12:33:39 -04:00
|
|
|
object_class->finalize = meta_wayland_surface_finalize;
|
2021-08-06 11:00:19 -04:00
|
|
|
object_class->get_property = meta_wayland_surface_get_property;
|
|
|
|
|
|
|
|
obj_props[PROP_SCANOUT_CANDIDATE] =
|
|
|
|
g_param_spec_object ("scanout-candidate",
|
|
|
|
"scanout-candidate",
|
|
|
|
"Scanout candidate for given CRTC",
|
|
|
|
META_TYPE_CRTC,
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
|
|
|
|
2015-10-22 08:07:52 -04:00
|
|
|
surface_signals[SURFACE_DESTROY] =
|
|
|
|
g_signal_new ("destroy",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2016-08-18 00:57:17 -04:00
|
|
|
|
|
|
|
surface_signals[SURFACE_UNMAPPED] =
|
|
|
|
g_signal_new ("unmapped",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2016-06-28 02:56:20 -04:00
|
|
|
|
|
|
|
surface_signals[SURFACE_CONFIGURE] =
|
|
|
|
g_signal_new ("configure",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2017-03-17 08:34:52 -04:00
|
|
|
|
|
|
|
surface_signals[SURFACE_SHORTCUTS_INHIBITED] =
|
|
|
|
g_signal_new ("shortcuts-inhibited",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
|
|
|
|
surface_signals[SURFACE_SHORTCUTS_RESTORED] =
|
|
|
|
g_signal_new ("shortcuts-restored",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2018-04-06 06:35:34 -04:00
|
|
|
surface_signals[SURFACE_GEOMETRY_CHANGED] =
|
|
|
|
g_signal_new ("geometry-changed",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2018-10-24 05:34:18 -04:00
|
|
|
surface_signals[SURFACE_PRE_STATE_APPLIED] =
|
|
|
|
g_signal_new ("pre-state-applied",
|
|
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2015-07-07 23:21:23 -04:00
|
|
|
}
|
2015-07-08 04:14:00 -04:00
|
|
|
|
2016-01-28 03:55:42 -05:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (object);
|
|
|
|
MetaWaylandSurfaceRolePrivate *priv =
|
|
|
|
meta_wayland_surface_role_get_instance_private (surface_role);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case SURFACE_ROLE_PROP_SURFACE:
|
|
|
|
priv->surface = g_value_get_object (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (object);
|
|
|
|
MetaWaylandSurfaceRolePrivate *priv =
|
|
|
|
meta_wayland_surface_role_get_instance_private (surface_role);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case SURFACE_ROLE_PROP_SURFACE:
|
|
|
|
g_value_set_object (value, priv->surface);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_init (MetaWaylandSurfaceRole *role)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_class_init (MetaWaylandSurfaceRoleClass *klass)
|
|
|
|
{
|
2016-01-28 03:55:42 -05:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->set_property = meta_wayland_surface_role_set_property;
|
|
|
|
object_class->get_property = meta_wayland_surface_role_get_property;
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
SURFACE_ROLE_PROP_SURFACE,
|
|
|
|
g_param_spec_object ("surface",
|
|
|
|
"MetaWaylandSurface",
|
|
|
|
"The MetaWaylandSurface instance",
|
|
|
|
META_TYPE_WAYLAND_SURFACE,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
2015-07-08 04:14:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
|
|
|
{
|
|
|
|
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->assigned (surface_role);
|
|
|
|
}
|
|
|
|
|
2022-11-01 11:43:03 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_commit_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandTransaction *transaction,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
|
|
|
if (klass->commit_state)
|
|
|
|
klass->commit_state (surface_role, transaction, pending);
|
|
|
|
}
|
|
|
|
|
2016-03-16 02:55:51 -04:00
|
|
|
static void
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
2016-03-16 02:55:51 -04:00
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
2019-07-11 05:20:44 -04:00
|
|
|
if (klass->pre_apply_state)
|
|
|
|
klass->pre_apply_state (surface_role, pending);
|
2016-03-16 02:55:51 -04:00
|
|
|
}
|
|
|
|
|
2020-06-08 03:13:44 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
|
|
|
if (klass->post_apply_state)
|
|
|
|
klass->post_apply_state (surface_role, pending);
|
|
|
|
}
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
static void
|
2019-07-11 05:20:44 -04:00
|
|
|
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
2015-07-08 04:14:00 -04:00
|
|
|
{
|
2019-07-11 05:20:44 -04:00
|
|
|
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->apply_state (surface_role,
|
|
|
|
pending);
|
2015-07-08 04:14:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2016-11-25 01:38:28 -05:00
|
|
|
meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaLogicalMonitor *logical_monitor)
|
2015-07-08 04:14:00 -04:00
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
2016-11-25 01:38:28 -05:00
|
|
|
if (klass->is_on_logical_monitor)
|
|
|
|
return klass->is_on_logical_monitor (surface_role, logical_monitor);
|
2015-07-08 04:14:00 -04:00
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-01-14 04:43:47 -05:00
|
|
|
static MetaWaylandSurface *
|
|
|
|
meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
|
|
|
if (klass->get_toplevel)
|
|
|
|
return klass->get_toplevel (surface_role);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
wayland: Move MetaWindow ownership to window owning roles
There are two surface roles owning a MetaWindow: MetaWaylandShellSurface
(basis of MetaWaylandXdgToplevel, MetaWaylandXdgPopup,
MetaWaylandWlShellSurface, etc), and MetaXwaylandSurface.
With these two role types, the MetaWindow has two different types of
life times. With MetaWaylandShellSurface, the window is owned and
managed by the role itself, while with MetaXwaylandSurface, the
MetaWindow is tied to the X11 window, while the Wayland surface and its
role plays more the role of the backing rendering surface.
Before, for historical reasons, MetaWindow was part of
MetaWaylandSurface, even though just some roles used it, and before
'wayland: Untie MetaWindowXwayland lifetime from the wl_surface' had
equivalent life times as well. But since that commit, the management
changed. To not have the same fied in MetaWaylandSurface being managed
in such drastically different ways, rearrange it so that the roles that
has a MetaWindow themself manages it in the way it is meant to; meaning
MetaWaylandShellSurface practically owns it, while with Xwayland, the
existance of a MetaWindow is tracked via X11.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/835
2019-10-09 03:57:40 -04:00
|
|
|
static MetaWindow *
|
|
|
|
meta_wayland_surface_role_get_window (MetaWaylandSurfaceRole *surface_role)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
|
|
|
|
|
|
|
if (klass->get_window)
|
|
|
|
return klass->get_window (surface_role);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-09 03:37:04 -04:00
|
|
|
MetaWindow *
|
|
|
|
meta_wayland_surface_get_window (MetaWaylandSurface *surface)
|
|
|
|
{
|
2020-03-30 09:53:29 -04:00
|
|
|
if (!surface->role)
|
|
|
|
return NULL;
|
|
|
|
|
wayland: Move MetaWindow ownership to window owning roles
There are two surface roles owning a MetaWindow: MetaWaylandShellSurface
(basis of MetaWaylandXdgToplevel, MetaWaylandXdgPopup,
MetaWaylandWlShellSurface, etc), and MetaXwaylandSurface.
With these two role types, the MetaWindow has two different types of
life times. With MetaWaylandShellSurface, the window is owned and
managed by the role itself, while with MetaXwaylandSurface, the
MetaWindow is tied to the X11 window, while the Wayland surface and its
role plays more the role of the backing rendering surface.
Before, for historical reasons, MetaWindow was part of
MetaWaylandSurface, even though just some roles used it, and before
'wayland: Untie MetaWindowXwayland lifetime from the wl_surface' had
equivalent life times as well. But since that commit, the management
changed. To not have the same fied in MetaWaylandSurface being managed
in such drastically different ways, rearrange it so that the roles that
has a MetaWindow themself manages it in the way it is meant to; meaning
MetaWaylandShellSurface practically owns it, while with Xwayland, the
existance of a MetaWindow is tracked via X11.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/835
2019-10-09 03:57:40 -04:00
|
|
|
return meta_wayland_surface_role_get_window (surface->role);
|
2019-10-09 03:37:04 -04:00
|
|
|
}
|
|
|
|
|
2019-03-13 07:26:22 -04:00
|
|
|
static gboolean
|
2021-06-05 10:46:56 -04:00
|
|
|
meta_wayland_surface_role_is_synchronized (MetaWaylandSurfaceRole *surface_role)
|
2019-03-13 07:26:22 -04:00
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
2021-06-05 10:46:56 -04:00
|
|
|
if (klass->is_synchronized)
|
|
|
|
return klass->is_synchronized (surface_role);
|
2019-03-13 07:26:22 -04:00
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2021-06-05 10:46:56 -04:00
|
|
|
meta_wayland_surface_is_synchronized (MetaWaylandSurface *surface)
|
2019-03-13 07:26:22 -04:00
|
|
|
{
|
|
|
|
if (!surface->role)
|
|
|
|
return FALSE;
|
|
|
|
|
2021-06-05 10:46:56 -04:00
|
|
|
return meta_wayland_surface_role_is_synchronized (surface->role);
|
2019-03-13 07:26:22 -04:00
|
|
|
}
|
|
|
|
|
2019-10-08 17:32:37 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_surface_role_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRoleClass *klass;
|
|
|
|
|
|
|
|
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
|
|
|
g_return_if_fail (klass->notify_subsurface_state_changed);
|
|
|
|
|
|
|
|
klass->notify_subsurface_state_changed (surface_role);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_notify_subsurface_state_changed (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (surface->role)
|
|
|
|
meta_wayland_surface_role_notify_subsurface_state_changed (surface->role);
|
|
|
|
}
|
|
|
|
|
2015-07-08 04:14:00 -04:00
|
|
|
MetaWaylandSurface *
|
|
|
|
meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRolePrivate *priv =
|
|
|
|
meta_wayland_surface_role_get_instance_private (role);
|
|
|
|
|
|
|
|
return priv->surface;
|
|
|
|
}
|
|
|
|
|
2016-02-23 08:26:52 -05:00
|
|
|
cairo_region_t *
|
|
|
|
meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
cairo_region_t *region;
|
|
|
|
cairo_rectangle_int_t buffer_rect;
|
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
if (!surface->buffer)
|
2016-02-23 08:26:52 -05:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
buffer_rect = (cairo_rectangle_int_t) {
|
2018-06-29 11:53:21 -04:00
|
|
|
.width = meta_wayland_surface_get_width (surface),
|
|
|
|
.height = meta_wayland_surface_get_height (surface),
|
2016-02-23 08:26:52 -05:00
|
|
|
};
|
|
|
|
region = cairo_region_create_rectangle (&buffer_rect);
|
|
|
|
|
|
|
|
if (surface->input_region)
|
|
|
|
cairo_region_intersect (region, surface->input_region);
|
|
|
|
|
|
|
|
return region;
|
|
|
|
}
|
2017-03-17 08:34:52 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_inhibit_shortcuts (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandSeat *seat)
|
|
|
|
{
|
|
|
|
g_hash_table_add (surface->shortcut_inhibited_seats, seat);
|
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_INHIBITED], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandSeat *seat)
|
|
|
|
{
|
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_RESTORED], 0);
|
|
|
|
g_hash_table_remove (surface->shortcut_inhibited_seats, seat);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
|
|
|
|
MetaWaylandSeat *seat)
|
|
|
|
{
|
|
|
|
if (surface->shortcut_inhibited_seats == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return g_hash_table_contains (surface->shortcut_inhibited_seats, seat);
|
|
|
|
}
|
2018-04-06 06:29:37 -04:00
|
|
|
|
wayland: Move surface texture ownership to MetaWaylandSurface
Prior to this commit, MetaWaylandSurface held a reference to
MetaWaylandBuffer, who owned the texture drawn by the surface. When
switching buffer, the texture change with it.
This is problematic when dealing with SHM buffer damage management, as
when having one texture per buffer, damaged regions uploaded to one,
will not follow along to the next one attached. It also wasted GPU
memory as there would be one texture per buffer, instead of one one
texture per surface.
Instead, move the texture ownership to MetaWaylandSurface, and have the
SHM buffer damage management update the surface texture. This ensures
damage is processed properly, and that we won't end up with stale
texture content when doing partial texture uploads. If the same SHM
buffer is attached to multiple surfaces, each surface will get their own
copy, and damage is tracked and uploaded separately.
Non-SHM types of buffers still has their own texture reference, as the
texture is just a representation of the GPU memory associated with the
buffer. When such a buffer is attached to a surface, instead the surface
just gets a reference to that texture, instead of a separately allocated
one.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-08 05:46:48 -05:00
|
|
|
CoglTexture *
|
|
|
|
meta_wayland_surface_get_texture (MetaWaylandSurface *surface)
|
|
|
|
{
|
2022-07-13 11:10:05 -04:00
|
|
|
return surface->output_state.texture;
|
wayland: Move surface texture ownership to MetaWaylandSurface
Prior to this commit, MetaWaylandSurface held a reference to
MetaWaylandBuffer, who owned the texture drawn by the surface. When
switching buffer, the texture change with it.
This is problematic when dealing with SHM buffer damage management, as
when having one texture per buffer, damaged regions uploaded to one,
will not follow along to the next one attached. It also wasted GPU
memory as there would be one texture per buffer, instead of one one
texture per surface.
Instead, move the texture ownership to MetaWaylandSurface, and have the
SHM buffer damage management update the surface texture. This ensures
damage is processed properly, and that we won't end up with stale
texture content when doing partial texture uploads. If the same SHM
buffer is attached to multiple surfaces, each surface will get their own
copy, and damage is tracked and uploaded separately.
Non-SHM types of buffers still has their own texture reference, as the
texture is just a representation of the GPU memory associated with the
buffer. When such a buffer is attached to a surface, instead the surface
just gets a reference to that texture, instead of a separately allocated
one.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-08 05:46:48 -05:00
|
|
|
}
|
|
|
|
|
2018-04-06 06:29:37 -04:00
|
|
|
MetaSurfaceActor *
|
|
|
|
meta_wayland_surface_get_actor (MetaWaylandSurface *surface)
|
|
|
|
{
|
2018-04-06 07:27:52 -04:00
|
|
|
if (!surface->role || !META_IS_WAYLAND_ACTOR_SURFACE (surface->role))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return meta_wayland_actor_surface_get_actor (META_WAYLAND_ACTOR_SURFACE (surface->role));
|
2018-04-06 06:29:37 -04:00
|
|
|
}
|
2018-04-06 06:35:34 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_notify_geometry_changed (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
g_signal_emit (surface, surface_signals[SURFACE_GEOMETRY_CHANGED], 0);
|
|
|
|
}
|
2018-06-29 11:45:28 -04:00
|
|
|
|
|
|
|
int
|
|
|
|
meta_wayland_surface_get_width (MetaWaylandSurface *surface)
|
|
|
|
{
|
2018-11-24 14:25:38 -05:00
|
|
|
if (surface->viewport.has_dst_size)
|
|
|
|
{
|
|
|
|
return surface->viewport.dst_width;
|
|
|
|
}
|
|
|
|
else if (surface->viewport.has_src_rect)
|
|
|
|
{
|
|
|
|
return ceilf (surface->viewport.src_rect.size.width);
|
|
|
|
}
|
2018-06-29 11:45:28 -04:00
|
|
|
else
|
2018-11-24 14:25:38 -05:00
|
|
|
{
|
|
|
|
int width;
|
2018-11-26 13:40:57 -05:00
|
|
|
|
2018-11-24 14:25:38 -05:00
|
|
|
if (meta_monitor_transform_is_rotated (surface->buffer_transform))
|
|
|
|
width = get_buffer_height (surface);
|
|
|
|
else
|
|
|
|
width = get_buffer_width (surface);
|
|
|
|
|
|
|
|
return width / surface->scale;
|
|
|
|
}
|
2018-06-29 11:45:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
meta_wayland_surface_get_height (MetaWaylandSurface *surface)
|
|
|
|
{
|
2018-11-24 14:25:38 -05:00
|
|
|
if (surface->viewport.has_dst_size)
|
|
|
|
{
|
|
|
|
return surface->viewport.dst_height;
|
|
|
|
}
|
|
|
|
else if (surface->viewport.has_src_rect)
|
|
|
|
{
|
|
|
|
return ceilf (surface->viewport.src_rect.size.height);
|
|
|
|
}
|
2018-06-29 11:45:28 -04:00
|
|
|
else
|
2018-11-24 14:25:38 -05:00
|
|
|
{
|
|
|
|
int height;
|
|
|
|
|
|
|
|
if (meta_monitor_transform_is_rotated (surface->buffer_transform))
|
|
|
|
height = get_buffer_width (surface);
|
|
|
|
else
|
|
|
|
height = get_buffer_height (surface);
|
2018-11-26 13:40:57 -05:00
|
|
|
|
2018-11-24 14:25:38 -05:00
|
|
|
return height / surface->scale;
|
|
|
|
}
|
2018-06-29 11:45:28 -04:00
|
|
|
}
|
2019-09-12 05:44:59 -04:00
|
|
|
|
|
|
|
static void
|
|
|
|
scanout_destroyed (gpointer data,
|
|
|
|
GObject *where_the_object_was)
|
|
|
|
{
|
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-06-22 12:43:11 -04:00
|
|
|
MetaWaylandBuffer *buffer = data;
|
2019-09-12 05:44:59 -04:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
meta_wayland_buffer_dec_use_count (buffer);
|
|
|
|
g_object_unref (buffer);
|
2019-09-12 05:44:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
CoglScanout *
|
|
|
|
meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
|
|
|
|
CoglOnscreen *onscreen)
|
|
|
|
{
|
|
|
|
CoglScanout *scanout;
|
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-06-22 12:43:11 -04:00
|
|
|
MetaWaylandBuffer *buffer;
|
2019-09-12 05:44:59 -04:00
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
if (!surface->buffer)
|
2019-09-12 05:44:59 -04:00
|
|
|
return NULL;
|
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
if (surface->buffer->use_count == 0)
|
2019-09-12 05:44:59 -04:00
|
|
|
return NULL;
|
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
scanout = meta_wayland_buffer_try_acquire_scanout (surface->buffer,
|
2019-09-12 05:44:59 -04:00
|
|
|
onscreen);
|
|
|
|
if (!scanout)
|
|
|
|
return NULL;
|
|
|
|
|
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-06-22 12:43:11 -04:00
|
|
|
buffer = g_object_ref (surface->buffer);
|
|
|
|
meta_wayland_buffer_inc_use_count (buffer);
|
|
|
|
g_object_weak_ref (G_OBJECT (scanout), scanout_destroyed, buffer);
|
2019-09-12 05:44:59 -04:00
|
|
|
|
|
|
|
return scanout;
|
|
|
|
}
|
2021-08-06 11:00:19 -04:00
|
|
|
|
|
|
|
MetaCrtc *
|
|
|
|
meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
return surface->scanout_candidate;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
|
|
|
|
MetaCrtc *crtc)
|
|
|
|
{
|
|
|
|
if (surface->scanout_candidate == crtc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_set_object (&surface->scanout_candidate, crtc);
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (surface),
|
|
|
|
obj_props[PROP_SCANOUT_CANDIDATE]);
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_surface_can_scanout_untransformed (MetaWaylandSurface *surface,
|
|
|
|
MetaRendererView *view,
|
|
|
|
int geometry_scale)
|
|
|
|
{
|
|
|
|
if (meta_renderer_view_get_transform (view) != surface->buffer_transform)
|
2022-10-28 16:41:35 -04:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_RENDER,
|
|
|
|
"Surface can not be scanned out untransformed: buffer "
|
|
|
|
"transform does not match renderer-view transform");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
|
|
|
|
if (surface->viewport.has_dst_size)
|
|
|
|
{
|
|
|
|
MetaRectangle view_layout;
|
|
|
|
float view_scale;
|
|
|
|
|
|
|
|
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
|
|
|
|
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
|
|
|
|
|
|
|
|
if (!G_APPROX_VALUE (view_layout.width, surface->viewport.dst_width,
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (view_layout.height, surface->viewport.dst_height,
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (view_layout.width * view_scale,
|
|
|
|
get_buffer_width (surface),
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (view_layout.height * view_scale,
|
|
|
|
get_buffer_height (surface),
|
|
|
|
FLT_EPSILON))
|
2022-10-28 16:41:35 -04:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_RENDER,
|
|
|
|
"Surface can not be scanned out untransformed: viewport "
|
|
|
|
"destination size does not match stage-view layout");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-05-27 14:30:37 -04:00
|
|
|
MetaContext *context =
|
|
|
|
meta_wayland_compositor_get_context (surface->compositor);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
|
|
|
|
|
|
|
if (meta_backend_is_stage_views_scaled (backend))
|
2022-02-08 14:23:27 -05:00
|
|
|
{
|
|
|
|
float view_scale;
|
|
|
|
|
|
|
|
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
|
|
|
|
if (!G_APPROX_VALUE (view_scale, surface->scale, FLT_EPSILON))
|
2022-10-28 16:41:35 -04:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_RENDER,
|
|
|
|
"Surface can not be scanned out untransformed: "
|
|
|
|
"buffer scale does not match stage-view scale");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (geometry_scale != surface->scale)
|
2022-10-28 16:41:35 -04:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_RENDER,
|
|
|
|
"Surface can not be scanned out untransformed: "
|
|
|
|
"buffer scale does not match actor geometry scale");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (surface->viewport.has_src_rect)
|
|
|
|
{
|
|
|
|
if (!G_APPROX_VALUE (surface->viewport.src_rect.origin.x, 0.0,
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (surface->viewport.src_rect.origin.y, 0.0,
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (surface->viewport.src_rect.size.width *
|
|
|
|
surface->scale,
|
|
|
|
get_buffer_width (surface),
|
|
|
|
FLT_EPSILON) ||
|
|
|
|
!G_APPROX_VALUE (surface->viewport.src_rect.size.height *
|
|
|
|
surface->scale,
|
|
|
|
get_buffer_height (surface),
|
|
|
|
FLT_EPSILON))
|
2022-10-28 16:41:35 -04:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_RENDER,
|
|
|
|
"Surface can not be scanned out untransformed: viewport "
|
|
|
|
"source rect does not cover the whole buffer");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2022-02-08 14:23:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2022-06-13 04:25:02 -04:00
|
|
|
|
|
|
|
int
|
|
|
|
meta_wayland_surface_get_geometry_scale (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandActorSurface *actor_surface;
|
|
|
|
|
|
|
|
g_return_val_if_fail (META_IS_WAYLAND_ACTOR_SURFACE (surface->role), 1);
|
|
|
|
|
|
|
|
actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role);
|
|
|
|
return meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
|
|
|
}
|