2015-12-15 04:51:24 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2012-2013 Intel Corporation
|
|
|
|
* Copyright (C) 2013-2015 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* 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
|
2023-08-07 09:50:23 +00:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2015-12-15 04:51:24 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "wayland/meta-wayland-xdg-shell.h"
|
|
|
|
|
2016-12-13 02:37:11 +00:00
|
|
|
#include "backends/meta-logical-monitor.h"
|
2022-10-21 10:56:24 +00:00
|
|
|
#include "compositor/compositor-private.h"
|
2019-07-26 13:03:36 +00:00
|
|
|
#include "core/boxes-private.h"
|
2015-12-15 04:51:24 +00:00
|
|
|
#include "core/window-private.h"
|
2016-11-02 16:55:01 +00:00
|
|
|
#include "wayland/meta-wayland-outputs.h"
|
2015-12-15 04:51:24 +00:00
|
|
|
#include "wayland/meta-wayland-popup.h"
|
|
|
|
#include "wayland/meta-wayland-private.h"
|
|
|
|
#include "wayland/meta-wayland-seat.h"
|
2017-12-22 06:28:28 +00:00
|
|
|
#include "wayland/meta-wayland-shell-surface.h"
|
2023-10-23 21:59:19 +00:00
|
|
|
#include "wayland/meta-wayland-surface-private.h"
|
2022-11-01 15:52:41 +00:00
|
|
|
#include "wayland/meta-wayland-transaction.h"
|
2015-12-15 04:51:24 +00:00
|
|
|
#include "wayland/meta-wayland-versions.h"
|
2019-07-05 16:10:14 +00:00
|
|
|
#include "wayland/meta-wayland-window-configuration.h"
|
2018-07-10 08:36:24 +00:00
|
|
|
#include "wayland/meta-wayland.h"
|
2015-12-15 04:51:24 +00:00
|
|
|
#include "wayland/meta-window-wayland.h"
|
2017-12-22 08:37:44 +00:00
|
|
|
|
|
|
|
#include "xdg-shell-server-protocol.h"
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
enum
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
XDG_SURFACE_PROP_0,
|
2016-01-14 09:49:57 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
XDG_SURFACE_PROP_SHELL_CLIENT,
|
|
|
|
XDG_SURFACE_PROP_RESOURCE,
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _MetaWaylandXdgShellClient
|
|
|
|
{
|
2022-05-30 21:48:44 +00:00
|
|
|
MetaWaylandCompositor *compositor;
|
2016-07-01 08:30:14 +00:00
|
|
|
struct wl_resource *resource;
|
|
|
|
GList *surfaces;
|
|
|
|
GList *surface_constructors;
|
|
|
|
} MetaWaylandXdgShellClient;
|
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
struct _MetaWaylandXdgPositioner
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle anchor_rect;
|
2016-07-01 08:30:14 +00:00
|
|
|
int32_t width;
|
|
|
|
int32_t height;
|
|
|
|
uint32_t gravity;
|
|
|
|
uint32_t anchor;
|
|
|
|
uint32_t constraint_adjustment;
|
|
|
|
int32_t offset_x;
|
|
|
|
int32_t offset_y;
|
2020-02-14 10:11:10 +00:00
|
|
|
|
|
|
|
gboolean is_reactive;
|
2020-02-14 10:13:24 +00:00
|
|
|
|
|
|
|
gboolean has_parent_size;
|
|
|
|
int32_t parent_width;
|
|
|
|
int32_t parent_height;
|
|
|
|
|
|
|
|
gboolean acked_parent_configure;
|
|
|
|
uint32_t parent_configure_serial;
|
2022-11-01 16:30:00 +00:00
|
|
|
};
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
typedef struct _MetaWaylandXdgSurfaceConstructor
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface;
|
|
|
|
struct wl_resource *resource;
|
|
|
|
MetaWaylandXdgShellClient *shell_client;
|
|
|
|
} MetaWaylandXdgSurfaceConstructor;
|
|
|
|
|
|
|
|
typedef struct _MetaWaylandXdgSurfacePrivate
|
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
struct wl_resource *resource;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgShellClient *shell_client;
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle geometry;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
guint configure_sent : 1;
|
|
|
|
guint first_buffer_attached : 1;
|
|
|
|
guint has_set_geometry : 1;
|
|
|
|
} MetaWaylandXdgSurfacePrivate;
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandXdgSurface,
|
|
|
|
meta_wayland_xdg_surface,
|
2017-12-13 04:37:23 +00:00
|
|
|
META_TYPE_WAYLAND_SHELL_SURFACE);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
struct _MetaWaylandXdgToplevel
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface parent;
|
|
|
|
|
|
|
|
struct wl_resource *resource;
|
2015-12-15 04:51:24 +00:00
|
|
|
};
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
G_DEFINE_TYPE (MetaWaylandXdgToplevel,
|
|
|
|
meta_wayland_xdg_toplevel,
|
|
|
|
META_TYPE_WAYLAND_XDG_SURFACE);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-01-14 04:49:14 +00:00
|
|
|
struct _MetaWaylandXdgPopup
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface parent;
|
2016-01-22 06:22:40 +00:00
|
|
|
|
|
|
|
struct wl_resource *resource;
|
|
|
|
|
|
|
|
MetaWaylandSurface *parent_surface;
|
2017-12-22 08:37:44 +00:00
|
|
|
gulong parent_surface_unmapped_handler_id;
|
2016-01-22 06:22:40 +00:00
|
|
|
|
2020-02-14 10:13:24 +00:00
|
|
|
uint32_t pending_reposition_token;
|
|
|
|
gboolean pending_repositioned;
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
MetaWaylandPopup *popup;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
gboolean dismissed_by_client;
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
struct {
|
|
|
|
MetaWaylandSurface *parent_surface;
|
2016-10-13 05:56:00 +00:00
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
MetaWaylandXdgPositioner xdg_positioner;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
MetaWaylandSeat *grab_seat;
|
|
|
|
uint32_t grab_serial;
|
|
|
|
} setup;
|
2015-12-15 04:51:24 +00:00
|
|
|
};
|
|
|
|
|
2016-01-21 09:01:08 +00:00
|
|
|
static void
|
|
|
|
popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface);
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (MetaWaylandXdgPopup,
|
|
|
|
meta_wayland_xdg_popup,
|
2016-07-01 08:30:14 +00:00
|
|
|
META_TYPE_WAYLAND_XDG_SURFACE,
|
2016-01-21 09:01:08 +00:00
|
|
|
G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE,
|
|
|
|
popup_surface_iface_init));
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static MetaPlacementRule
|
2020-02-14 09:41:38 +00:00
|
|
|
meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner,
|
|
|
|
MetaWindow *parent_window);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
static struct wl_resource *
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2023-07-19 23:46:15 +00:00
|
|
|
static MtkRectangle
|
2016-07-01 08:30:14 +00:00
|
|
|
meta_wayland_xdg_surface_get_window_geometry (MetaWaylandXdgSurface *xdg_surface);
|
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface,
|
|
|
|
MetaWaylandWindowConfiguration *configuration);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2020-02-14 10:13:24 +00:00
|
|
|
static void
|
|
|
|
scale_placement_rule (MetaPlacementRule *placement_rule,
|
|
|
|
MetaWaylandSurface *surface);
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
static MetaWaylandSurface *
|
|
|
|
surface_from_xdg_surface_resource (struct wl_resource *resource)
|
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurfaceRole *surface_role = wl_resource_get_user_data (resource);
|
2020-08-26 20:55:40 +00:00
|
|
|
|
|
|
|
if (!META_IS_WAYLAND_SURFACE_ROLE (surface_role))
|
|
|
|
return NULL;
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
return meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaWaylandSurface *
|
2016-07-01 08:30:14 +00:00
|
|
|
surface_from_xdg_toplevel_resource (struct wl_resource *resource)
|
2016-01-22 06:22:40 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
return surface_from_xdg_surface_resource (resource);
|
2016-01-22 06:22:40 +00:00
|
|
|
}
|
|
|
|
|
2022-05-30 21:48:44 +00:00
|
|
|
static MetaDisplay *
|
|
|
|
display_from_surface (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaContext *context =
|
|
|
|
meta_wayland_compositor_get_context (surface->compositor);
|
|
|
|
|
|
|
|
return meta_context_get_display (context);
|
|
|
|
}
|
|
|
|
|
2022-09-28 20:52:54 +00:00
|
|
|
static MetaWaylandXdgPopup *
|
|
|
|
meta_wayland_xdg_popup_from_surface (MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
return META_WAYLAND_XDG_POPUP (surface->role);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_reset (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
META_WAYLAND_XDG_SURFACE_GET_CLASS (xdg_surface)->reset (xdg_surface);
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_destructor (struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel = wl_resource_get_user_data (resource);
|
2019-09-04 16:35:08 +00:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (xdg_toplevel);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-09-04 16:35:08 +00:00
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel->resource = NULL;
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_parent (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *parent_resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2015-12-15 04:51:24 +00:00
|
|
|
MetaWindow *transient_for = NULL;
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
|
|
|
if (parent_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *parent_surface =
|
2016-01-22 06:22:40 +00:00
|
|
|
surface_from_xdg_surface_resource (parent_resource);
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
transient_for = meta_wayland_surface_get_window (parent_surface);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_set_transient_for (window, transient_for);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_title (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
const char *title)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-06-07 14:17:28 +00:00
|
|
|
if (!g_utf8_validate (title, -1, NULL))
|
|
|
|
title = "";
|
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_set_title (window, title);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_app_id (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
const char *app_id)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-06-07 14:17:28 +00:00
|
|
|
if (!g_utf8_validate (app_id, -1, NULL))
|
|
|
|
app_id = "";
|
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_set_wm_class (window, app_id, app_id);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_show_window_menu (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
2016-12-30 12:51:06 +00:00
|
|
|
int monitor_scale;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
2022-10-21 17:36:59 +00:00
|
|
|
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE,
|
|
|
|
NULL, NULL, NULL, NULL))
|
2015-12-15 04:51:24 +00:00
|
|
|
return;
|
|
|
|
|
2019-03-26 21:24:44 +00:00
|
|
|
monitor_scale = meta_window_wayland_get_geometry_scale (window);
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_show_menu (window, META_WINDOW_MENU_WM,
|
|
|
|
window->buffer_rect.x + (x * monitor_scale),
|
|
|
|
window->buffer_rect.y + (y * monitor_scale));
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_move (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
2022-10-21 17:52:35 +00:00
|
|
|
ClutterInputDevice *device;
|
|
|
|
ClutterEventSequence *sequence;
|
2017-12-13 04:55:57 +00:00
|
|
|
float x, y;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
2022-10-21 17:36:59 +00:00
|
|
|
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE,
|
2022-10-21 17:52:35 +00:00
|
|
|
&device, &sequence, &x, &y))
|
2015-12-15 04:51:24 +00:00
|
|
|
return;
|
|
|
|
|
2022-10-21 17:52:35 +00:00
|
|
|
meta_wayland_surface_begin_grab_op (surface, seat, META_GRAB_OP_MOVING,
|
|
|
|
device, sequence, x, y);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaGrabOp
|
2016-07-01 08:30:14 +00:00
|
|
|
grab_op_for_xdg_toplevel_resize_edge (int edge)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
MetaGrabOp op = META_GRAB_OP_WINDOW_BASE;
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
if (edge & XDG_TOPLEVEL_RESIZE_EDGE_TOP)
|
2015-12-15 04:51:24 +00:00
|
|
|
op |= META_GRAB_OP_WINDOW_DIR_NORTH;
|
2017-12-22 08:37:44 +00:00
|
|
|
if (edge & XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM)
|
2015-12-15 04:51:24 +00:00
|
|
|
op |= META_GRAB_OP_WINDOW_DIR_SOUTH;
|
2017-12-22 08:37:44 +00:00
|
|
|
if (edge & XDG_TOPLEVEL_RESIZE_EDGE_LEFT)
|
2015-12-15 04:51:24 +00:00
|
|
|
op |= META_GRAB_OP_WINDOW_DIR_WEST;
|
2017-12-22 08:37:44 +00:00
|
|
|
if (edge & XDG_TOPLEVEL_RESIZE_EDGE_RIGHT)
|
2015-12-15 04:51:24 +00:00
|
|
|
op |= META_GRAB_OP_WINDOW_DIR_EAST;
|
|
|
|
|
|
|
|
if (op == META_GRAB_OP_WINDOW_BASE)
|
|
|
|
{
|
|
|
|
g_warning ("invalid edge: %d", edge);
|
|
|
|
return META_GRAB_OP_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_resize (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial,
|
|
|
|
uint32_t edges)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
2015-12-15 04:51:24 +00:00
|
|
|
gfloat x, y;
|
|
|
|
MetaGrabOp grab_op;
|
2022-10-21 17:52:35 +00:00
|
|
|
ClutterInputDevice *device;
|
|
|
|
ClutterEventSequence *sequence;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
2020-07-12 00:04:38 +00:00
|
|
|
if (!window->has_resize_func)
|
|
|
|
return;
|
|
|
|
|
2022-10-21 17:36:59 +00:00
|
|
|
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE,
|
2022-10-21 17:52:35 +00:00
|
|
|
&device, &sequence, &x, &y))
|
2015-12-15 04:51:24 +00:00
|
|
|
return;
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
grab_op = grab_op_for_xdg_toplevel_resize_edge (edges);
|
2022-10-21 17:52:35 +00:00
|
|
|
meta_wayland_surface_begin_grab_op (surface, seat, grab_op,
|
|
|
|
device, sequence, x, y);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_max_size (struct wl_client *client,
|
2015-12-15 04:51:24 +00:00
|
|
|
struct wl_resource *resource,
|
2016-07-01 08:30:14 +00:00
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-04-06 12:07:08 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2019-03-13 12:27:25 +00:00
|
|
|
MetaWaylandSurfaceState *pending;
|
2016-04-06 12:07:08 +00:00
|
|
|
|
|
|
|
if (width < 0 || height < 0)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
2016-04-06 12:07:08 +00:00
|
|
|
"invalid negative max size requested %i x %i",
|
|
|
|
width, height);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
|
|
|
|
pending = meta_wayland_surface_get_pending_state (surface);
|
2021-07-29 16:14:20 +00:00
|
|
|
if (!pending)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"underlying wl_surface already destroyed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
pending->has_new_max_size = TRUE;
|
|
|
|
pending->new_max_width = width;
|
|
|
|
pending->new_max_height = height;
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_min_size (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-04-06 12:07:08 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2019-03-13 12:27:25 +00:00
|
|
|
MetaWaylandSurfaceState *pending;
|
2016-04-06 12:07:08 +00:00
|
|
|
|
|
|
|
if (width < 0 || height < 0)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
2016-04-06 12:07:08 +00:00
|
|
|
"invalid negative min size requested %i x %i",
|
|
|
|
width, height);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
|
|
|
|
pending = meta_wayland_surface_get_pending_state (surface);
|
2021-07-29 16:14:20 +00:00
|
|
|
if (!pending)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"underlying wl_surface already destroyed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
pending->has_new_min_size = TRUE;
|
|
|
|
pending->new_min_width = width;
|
|
|
|
pending->new_min_height = height;
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_maximized (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-06-21 11:30:22 +00:00
|
|
|
meta_window_force_placement (window, TRUE);
|
|
|
|
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_unset_maximized (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
|
|
|
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_fullscreen (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *output_resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-11-02 16:55:01 +00:00
|
|
|
if (output_resource)
|
|
|
|
{
|
2021-02-05 15:46:43 +00:00
|
|
|
MetaWaylandOutput *wayland_output;
|
2017-12-22 08:37:44 +00:00
|
|
|
|
2021-02-05 15:46:43 +00:00
|
|
|
wayland_output = wl_resource_get_user_data (output_resource);
|
|
|
|
if (wayland_output)
|
2017-12-22 08:37:44 +00:00
|
|
|
{
|
2021-02-05 15:46:43 +00:00
|
|
|
MetaLogicalMonitor *logical_monitor;
|
|
|
|
|
|
|
|
logical_monitor =
|
|
|
|
meta_wayland_output_get_logical_monitor (wayland_output);
|
|
|
|
meta_window_move_to_monitor (window, logical_monitor->number);
|
2017-12-22 08:37:44 +00:00
|
|
|
}
|
2016-11-02 16:55:01 +00:00
|
|
|
}
|
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_make_fullscreen (window);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_unset_fullscreen (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_unmake_fullscreen (window);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_set_minimized (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
2018-07-25 09:56:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-07-25 09:56:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2018-07-25 09:56:14 +00:00
|
|
|
meta_window_minimize (window);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_toplevel_interface meta_wayland_xdg_toplevel_interface = {
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel_destroy,
|
|
|
|
xdg_toplevel_set_parent,
|
|
|
|
xdg_toplevel_set_title,
|
|
|
|
xdg_toplevel_set_app_id,
|
|
|
|
xdg_toplevel_show_window_menu,
|
|
|
|
xdg_toplevel_move,
|
|
|
|
xdg_toplevel_resize,
|
|
|
|
xdg_toplevel_set_max_size,
|
|
|
|
xdg_toplevel_set_min_size,
|
|
|
|
xdg_toplevel_set_maximized,
|
|
|
|
xdg_toplevel_unset_maximized,
|
|
|
|
xdg_toplevel_set_fullscreen,
|
|
|
|
xdg_toplevel_unset_fullscreen,
|
|
|
|
xdg_toplevel_set_minimized,
|
2015-12-15 04:51:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_xdg_popup_unmap (MetaWaylandXdgPopup *xdg_popup)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2019-09-04 16:35:08 +00:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (xdg_popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
|
|
|
|
g_assert (!xdg_popup->popup);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
if (xdg_popup->parent_surface)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2019-11-16 00:25:52 +00:00
|
|
|
g_clear_signal_handler (&xdg_popup->parent_surface_unmapped_handler_id,
|
|
|
|
xdg_popup->parent_surface);
|
2016-01-22 06:22:40 +00:00
|
|
|
xdg_popup->parent_surface = NULL;
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2019-09-04 16:35:08 +00:00
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
2017-12-22 08:37:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-07-26 13:03:36 +00:00
|
|
|
dismiss_popup (MetaWaylandXdgPopup *xdg_popup)
|
2017-12-22 08:37:44 +00:00
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
if (xdg_popup->popup)
|
|
|
|
meta_wayland_popup_dismiss (xdg_popup->popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
else
|
|
|
|
meta_wayland_xdg_popup_unmap (xdg_popup);
|
2019-07-26 13:03:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_popup_destructor (struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup =
|
|
|
|
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
|
wayland: Unset keyboard focus if surface is destroyed
Depending on the ordering of the surface-associated resources
being destroyed, we may fall into the following situation:
- wl_surface is destroyed
- destruction notifications for the surface runs
- The MetaWaylandKeyboard attempts to synchronize the window
focus
- The MetaWindow is not destroyed yet, so the focused window
remains the same, and the MetaWaylandKeyboard keeps the same
focus MetaWaylandSurface.
- wl_surface finalizes destruction, MetaWaylandSurface now has
a NULL resource
- xdg_toplevel destructor kicks in, it unmanages the window
- The current focus window is again looked up, forced to look
a different window
- The MetaWaylandKeyboard focus now changes, tries to leave the
old surface, but it has a NULL resource already, and raises
a protocol error.
If the order is inverted, the window being unmanaged triggers a
focus change into a different window, the MetaWaylandKeyboard
triggers a focus change while the MetaWaylandSurface is still
intact, it succeeds, and the window gets properly destroyed.
In order to make this independent of the order, it makes sense
to make MetaWaylandKeyboard do like the other objects tracking
focus surfaces, and have it care of its own little parcel. The
surface destructor changed to simply unsetting the keyboard focus
to NULL (guaranteeing that the old focus is left while the surface
resource is still up), and leaving potential focus changes to
the xdg_toplevel_destructor->unmanage->update_focus paths.
Doing that alone is basically a revert of commit 228d681b, thus
is still subject to keyboard focus being lost after a popup is
destroyed. Change the approach to trigger the focus sync (and
new focus surface lookup) so it happens from xdg_popup_destructor
specifically to popups and alike xdg_toplevel.
Fixes: 228d681b ("wayland: Trigger full focus sync after keyboard focus surface is destroyed")
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2853
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3077>
2023-06-14 19:15:36 +00:00
|
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
|
|
META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2019-07-26 13:03:36 +00:00
|
|
|
|
|
|
|
dismiss_popup (xdg_popup);
|
2016-01-22 06:22:40 +00:00
|
|
|
xdg_popup->resource = NULL;
|
wayland: Unset keyboard focus if surface is destroyed
Depending on the ordering of the surface-associated resources
being destroyed, we may fall into the following situation:
- wl_surface is destroyed
- destruction notifications for the surface runs
- The MetaWaylandKeyboard attempts to synchronize the window
focus
- The MetaWindow is not destroyed yet, so the focused window
remains the same, and the MetaWaylandKeyboard keeps the same
focus MetaWaylandSurface.
- wl_surface finalizes destruction, MetaWaylandSurface now has
a NULL resource
- xdg_toplevel destructor kicks in, it unmanages the window
- The current focus window is again looked up, forced to look
a different window
- The MetaWaylandKeyboard focus now changes, tries to leave the
old surface, but it has a NULL resource already, and raises
a protocol error.
If the order is inverted, the window being unmanaged triggers a
focus change into a different window, the MetaWaylandKeyboard
triggers a focus change while the MetaWaylandSurface is still
intact, it succeeds, and the window gets properly destroyed.
In order to make this independent of the order, it makes sense
to make MetaWaylandKeyboard do like the other objects tracking
focus surfaces, and have it care of its own little parcel. The
surface destructor changed to simply unsetting the keyboard focus
to NULL (guaranteeing that the old focus is left while the surface
resource is still up), and leaving potential focus changes to
the xdg_toplevel_destructor->unmanage->update_focus paths.
Doing that alone is basically a revert of commit 228d681b, thus
is still subject to keyboard focus being lost after a popup is
destroyed. Change the approach to trigger the focus sync (and
new focus surface lookup) so it happens from xdg_popup_destructor
specifically to popups and alike xdg_toplevel.
Fixes: 228d681b ("wayland: Trigger full focus sync after keyboard focus surface is destroyed")
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2853
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3077>
2023-06-14 19:15:36 +00:00
|
|
|
|
|
|
|
meta_display_sync_wayland_input_focus (display_from_surface (surface));
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_popup_destroy (struct wl_client *client,
|
2015-12-15 04:51:24 +00:00
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
|
|
|
xdg_popup_grab (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup =
|
|
|
|
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
|
|
|
|
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
|
|
|
MetaWaylandSurface *parent_surface;
|
|
|
|
|
|
|
|
parent_surface = xdg_popup->setup.parent_surface;
|
|
|
|
if (!parent_surface)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_POPUP_ERROR_INVALID_GRAB,
|
2016-07-01 08:30:14 +00:00
|
|
|
"tried to grab after popup was mapped");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xdg_popup->setup.grab_seat = seat;
|
|
|
|
xdg_popup->setup.grab_serial = serial;
|
|
|
|
}
|
|
|
|
|
2020-02-14 10:13:24 +00:00
|
|
|
static void
|
|
|
|
xdg_popup_reposition (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
struct wl_resource *positioner_resource,
|
|
|
|
uint32_t token)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup =
|
|
|
|
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
|
|
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
|
|
META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
MetaWaylandXdgPositioner *xdg_positioner;
|
2022-11-01 16:30:00 +00:00
|
|
|
MetaWaylandTransaction *transaction;
|
2020-02-14 10:13:24 +00:00
|
|
|
|
2023-03-27 19:36:19 +00:00
|
|
|
if (!meta_wayland_surface_get_window (surface))
|
|
|
|
return;
|
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
xdg_positioner = g_memdup2 (wl_resource_get_user_data (positioner_resource),
|
|
|
|
sizeof (MetaWaylandXdgPositioner));
|
2020-02-14 10:13:24 +00:00
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
transaction = meta_wayland_transaction_new (surface->compositor);
|
|
|
|
meta_wayland_transaction_add_xdg_popup_reposition (transaction, surface,
|
|
|
|
xdg_positioner, token);
|
|
|
|
meta_wayland_transaction_ensure_entry (transaction, xdg_popup->parent_surface);
|
|
|
|
meta_wayland_transaction_commit (transaction);
|
2020-02-14 10:13:24 +00:00
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
|
2015-12-15 04:51:24 +00:00
|
|
|
xdg_popup_destroy,
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_popup_grab,
|
2020-02-14 10:13:24 +00:00
|
|
|
xdg_popup_reposition,
|
2015-12-15 04:51:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
on_parent_surface_unmapped (MetaWaylandSurface *parent_surface,
|
|
|
|
MetaWaylandXdgPopup *xdg_popup)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2019-09-04 16:35:08 +00:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (xdg_popup);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
|
2015-12-15 04:51:24 +00:00
|
|
|
"destroyed popup not top most popup");
|
2016-01-22 06:22:40 +00:00
|
|
|
xdg_popup->parent_surface = NULL;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-09-04 16:35:08 +00:00
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-10-24 11:20:59 +00:00
|
|
|
add_state_value (struct wl_array *states,
|
|
|
|
enum xdg_toplevel_state state)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
uint32_t *s;
|
|
|
|
|
2018-10-24 11:20:59 +00:00
|
|
|
s = wl_array_add (states, sizeof *s);
|
|
|
|
*s = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-05-24 12:40:55 +00:00
|
|
|
fill_states (MetaWaylandXdgToplevel *xdg_toplevel,
|
|
|
|
MetaWaylandWindowConfiguration *configuration,
|
|
|
|
struct wl_array *states)
|
2018-10-24 11:20:59 +00:00
|
|
|
{
|
2018-10-24 12:45:11 +00:00
|
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
|
|
META_WAYLAND_SURFACE_ROLE (xdg_toplevel);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2019-10-09 07:37:04 +00:00
|
|
|
MetaWindow *window = meta_wayland_surface_get_window (surface);
|
2022-10-21 10:56:24 +00:00
|
|
|
MetaWindowDrag *window_drag;
|
|
|
|
|
|
|
|
window_drag =
|
|
|
|
meta_compositor_get_current_window_drag (window->display->compositor);
|
2018-10-24 12:45:11 +00:00
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
if (META_WINDOW_MAXIMIZED (window))
|
2018-10-24 11:20:59 +00:00
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_MAXIMIZED);
|
2015-12-15 04:51:24 +00:00
|
|
|
if (meta_window_is_fullscreen (window))
|
2018-10-24 11:20:59 +00:00
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_FULLSCREEN);
|
2022-10-21 10:56:24 +00:00
|
|
|
if (window_drag &&
|
|
|
|
meta_grab_op_is_resizing (meta_window_drag_get_grab_op (window_drag)))
|
2018-10-24 11:20:59 +00:00
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_RESIZING);
|
2015-12-15 04:51:24 +00:00
|
|
|
if (meta_window_appears_focused (window))
|
2018-10-24 11:20:59 +00:00
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_ACTIVATED);
|
2023-05-24 12:40:55 +00:00
|
|
|
if (configuration->is_suspended &&
|
|
|
|
wl_resource_get_version (xdg_toplevel->resource) >=
|
|
|
|
XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION)
|
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_SUSPENDED);
|
2018-10-24 12:45:11 +00:00
|
|
|
|
|
|
|
if (wl_resource_get_version (xdg_toplevel->resource) >=
|
|
|
|
XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION)
|
|
|
|
{
|
|
|
|
if (window->edge_constraints.top != META_EDGE_CONSTRAINT_NONE)
|
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_TILED_TOP);
|
|
|
|
if (window->edge_constraints.right != META_EDGE_CONSTRAINT_NONE)
|
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_TILED_RIGHT);
|
|
|
|
if (window->edge_constraints.bottom != META_EDGE_CONSTRAINT_NONE)
|
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_TILED_BOTTOM);
|
|
|
|
if (window->edge_constraints.left != META_EDGE_CONSTRAINT_NONE)
|
|
|
|
add_state_value (states, XDG_TOPLEVEL_STATE_TILED_LEFT);
|
|
|
|
}
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2023-08-24 16:20:33 +00:00
|
|
|
static void
|
|
|
|
add_wm_capability_value (struct wl_array *states,
|
|
|
|
enum xdg_toplevel_wm_capabilities wm_capability)
|
|
|
|
{
|
|
|
|
*((uint32_t *) wl_array_add (states, sizeof (uint32_t))) = wm_capability;
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_toplevel,
|
|
|
|
MetaWaylandWindowConfiguration *configuration)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
|
2023-08-24 16:20:33 +00:00
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
struct wl_array states;
|
|
|
|
|
|
|
|
wl_array_init (&states);
|
2023-05-24 12:40:55 +00:00
|
|
|
fill_states (xdg_toplevel, configuration, &states);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2021-12-17 23:15:56 +00:00
|
|
|
if (wl_resource_get_version (xdg_toplevel->resource) >=
|
|
|
|
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION &&
|
|
|
|
configuration->bounds_width > 0 &&
|
|
|
|
configuration->bounds_height > 0)
|
|
|
|
{
|
|
|
|
xdg_toplevel_send_configure_bounds (xdg_toplevel->resource,
|
|
|
|
(configuration->bounds_width /
|
|
|
|
configuration->scale),
|
|
|
|
(configuration->bounds_height /
|
|
|
|
configuration->scale));
|
|
|
|
}
|
|
|
|
|
2023-08-24 16:20:33 +00:00
|
|
|
if (!xdg_surface_priv->configure_sent &&
|
|
|
|
wl_resource_get_version (xdg_toplevel->resource) >=
|
|
|
|
XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
|
|
|
{
|
|
|
|
struct wl_array wm_capabilities;
|
|
|
|
|
|
|
|
wl_array_init (&wm_capabilities);
|
|
|
|
add_wm_capability_value (&wm_capabilities,
|
|
|
|
XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU);
|
|
|
|
add_wm_capability_value (&wm_capabilities,
|
|
|
|
XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE);
|
|
|
|
add_wm_capability_value (&wm_capabilities,
|
|
|
|
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
|
|
|
add_wm_capability_value (&wm_capabilities,
|
|
|
|
XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE);
|
|
|
|
xdg_toplevel_send_wm_capabilities (xdg_toplevel->resource, &wm_capabilities);
|
|
|
|
wl_array_release (&wm_capabilities);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_toplevel_send_configure (xdg_toplevel->resource,
|
wayland/window: Don't lose precision in MetaWaylandWindowConfiguration
Commit 8bdd2aa7 would offset the window position by the difference
between the configured window size and the committed size from the
client to prevent the window from drifting while resizing.
This, however, did not take into account the actual geometry scale, so
when using any scale greater than 1, the window would rapidly drift away
due to that offset.
In order to solve this, we need to make sure we store away the pending
window configuration in the stage coordinate space, in order to not
loose precision. When we then calculate the offset given the result from
the client, it'll use the right scalars, while before, one scalar was in
surface coordinates, while the other in stage coordinates.
https://gitlab.gnome.org/GNOME/mutter/-/issues/1490
2020-10-29 09:11:15 +00:00
|
|
|
configuration->width / configuration->scale,
|
|
|
|
configuration->height / configuration->scale,
|
2017-12-22 08:37:44 +00:00
|
|
|
&states);
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_array_release (&states);
|
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_surface_send_configure (xdg_surface, configuration);
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 12:07:08 +00:00
|
|
|
static gboolean
|
|
|
|
is_new_size_hints_valid (MetaWindow *window,
|
2019-03-13 12:27:25 +00:00
|
|
|
MetaWaylandSurfaceState *pending)
|
2016-04-06 12:07:08 +00:00
|
|
|
{
|
|
|
|
int new_min_width, new_min_height;
|
|
|
|
int new_max_width, new_max_height;
|
|
|
|
|
|
|
|
if (pending->has_new_min_size)
|
|
|
|
{
|
|
|
|
new_min_width = pending->new_min_width;
|
|
|
|
new_min_height = pending->new_min_height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_window_wayland_get_min_size (window, &new_min_width, &new_min_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending->has_new_max_size)
|
|
|
|
{
|
|
|
|
new_max_width = pending->new_max_width;
|
|
|
|
new_max_height = pending->new_max_height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_window_wayland_get_max_size (window, &new_max_width, &new_max_height);
|
|
|
|
}
|
|
|
|
/* Zero means unlimited */
|
|
|
|
return ((new_max_width == 0 || new_min_width <= new_max_width) &&
|
|
|
|
(new_max_height == 0 || new_min_height <= new_max_height));
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
2019-07-11 09:20:44 +00:00
|
|
|
meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (surface_role);
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
|
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2020-04-27 13:43:19 +00:00
|
|
|
MetaWaylandActorSurface *actor_surface =
|
|
|
|
META_WAYLAND_ACTOR_SURFACE (xdg_toplevel);
|
2015-12-15 04:51:24 +00:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2017-12-22 08:37:44 +00:00
|
|
|
MetaWindow *window;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2018-08-27 10:30:07 +00:00
|
|
|
if (!window)
|
|
|
|
{
|
2020-04-27 13:43:19 +00:00
|
|
|
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
|
2018-08-27 10:30:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (!surface->buffer && xdg_surface_priv->first_buffer_attached)
|
2017-12-22 08:37:44 +00:00
|
|
|
{
|
|
|
|
meta_wayland_xdg_surface_reset (xdg_surface);
|
2018-07-25 09:49:36 +00:00
|
|
|
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface,
|
|
|
|
pending);
|
2017-12-22 08:37:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
surface_role_class =
|
2016-07-01 08:30:14 +00:00
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state (surface_role, pending);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (!xdg_surface_priv->configure_sent)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2019-07-05 16:10:14 +00:00
|
|
|
MetaWaylandWindowConfiguration *configuration;
|
2021-12-17 23:15:56 +00:00
|
|
|
int bounds_width;
|
|
|
|
int bounds_height;
|
|
|
|
|
|
|
|
if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height))
|
|
|
|
{
|
|
|
|
bounds_width = 0;
|
|
|
|
bounds_height = 0;
|
|
|
|
}
|
2019-07-05 16:10:14 +00:00
|
|
|
|
2021-12-17 23:15:56 +00:00
|
|
|
configuration =
|
|
|
|
meta_wayland_window_configuration_new_empty (bounds_width,
|
|
|
|
bounds_height);
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration);
|
|
|
|
meta_wayland_window_configuration_free (configuration);
|
2015-12-15 04:51:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-08 07:13:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_toplevel_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
|
|
MetaWindow *window;
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle old_geometry;
|
|
|
|
MtkRectangle window_geometry;
|
2020-06-08 08:06:44 +00:00
|
|
|
|
2020-06-08 07:13:44 +00:00
|
|
|
gboolean geometry_changed;
|
|
|
|
|
|
|
|
window = meta_wayland_surface_get_window (surface);
|
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
|
|
|
old_geometry = xdg_surface_priv->geometry;
|
|
|
|
|
|
|
|
surface_role_class =
|
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
|
|
|
surface_role_class->post_apply_state (surface_role, pending);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2020-06-08 08:06:44 +00:00
|
|
|
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
|
2023-07-19 15:14:13 +00:00
|
|
|
geometry_changed = !mtk_rectangle_equal (&old_geometry, &window_geometry);
|
2018-05-17 20:46:05 +00:00
|
|
|
|
2022-09-28 15:01:50 +00:00
|
|
|
if (geometry_changed ||
|
|
|
|
pending->derived.surface_size_changed ||
|
|
|
|
pending->has_acked_configure_serial)
|
2016-01-14 09:49:57 +00:00
|
|
|
{
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_window_wayland_finish_move_resize (window, window_geometry, pending);
|
2017-05-10 06:59:53 +00:00
|
|
|
}
|
2019-01-20 16:43:31 +00:00
|
|
|
else if (pending->dx != 0 || pending->dy != 0)
|
2017-05-10 06:59:53 +00:00
|
|
|
{
|
2017-12-13 04:55:57 +00:00
|
|
|
g_warning ("XXX: Attach-initiated move without a new geometry. "
|
|
|
|
"This is unimplemented right now.");
|
2016-01-14 09:49:57 +00:00
|
|
|
}
|
2016-10-11 13:20:30 +00:00
|
|
|
|
2016-04-06 12:07:08 +00:00
|
|
|
/* When we get to this point, we ought to have valid size hints */
|
|
|
|
if (pending->has_new_min_size || pending->has_new_max_size)
|
|
|
|
{
|
|
|
|
if (is_new_size_hints_valid (window, pending))
|
|
|
|
{
|
|
|
|
if (pending->has_new_min_size)
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_window_wayland_set_min_size (window,
|
|
|
|
pending->new_min_width,
|
|
|
|
pending->new_min_height);
|
2016-04-06 12:07:08 +00:00
|
|
|
|
|
|
|
if (pending->has_new_max_size)
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_window_wayland_set_max_size (window,
|
|
|
|
pending->new_max_width,
|
|
|
|
pending->new_max_height);
|
2016-04-06 12:07:08 +00:00
|
|
|
|
|
|
|
meta_window_recalc_features (window);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-07-29 16:14:20 +00:00
|
|
|
if (surface->resource)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (surface->resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"Invalid min/max size");
|
|
|
|
}
|
2016-04-06 12:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 09:43:47 +00:00
|
|
|
static MetaWaylandSurface *
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_get_toplevel (MetaWaylandSurfaceRole *surface_role)
|
2016-01-14 09:43:47 +00:00
|
|
|
{
|
|
|
|
return meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_toplevel_reset (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
|
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
|
|
META_WAYLAND_SURFACE_ROLE (xdg_surface);
|
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class =
|
|
|
|
META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
|
|
|
MetaWaylandSurface *surface;
|
|
|
|
MetaWindow *window;
|
|
|
|
|
|
|
|
surface = meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
|
2019-09-04 16:35:08 +00:00
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
2017-12-22 08:37:44 +00:00
|
|
|
|
2018-04-06 11:27:52 +00:00
|
|
|
meta_wayland_actor_surface_reset_actor (META_WAYLAND_ACTOR_SURFACE (surface_role));
|
2022-05-30 21:48:44 +00:00
|
|
|
window = meta_window_wayland_new (display_from_surface (surface), surface);
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_shell_surface_set_window (shell_surface, window);
|
|
|
|
|
|
|
|
xdg_surface_class->reset (xdg_surface);
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_configure (MetaWaylandShellSurface *shell_surface,
|
|
|
|
MetaWaylandWindowConfiguration *configuration)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel =
|
2017-12-13 04:37:23 +00:00
|
|
|
META_WAYLAND_XDG_TOPLEVEL (shell_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
|
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (!xdg_surface_priv->resource)
|
2015-12-15 04:51:24 +00:00
|
|
|
return;
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (!xdg_toplevel->resource)
|
|
|
|
return;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:09:20 +00:00
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_managed (MetaWaylandShellSurface *shell_surface,
|
|
|
|
MetaWindow *window)
|
2015-12-15 14:09:20 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_close (MetaWaylandShellSurface *shell_surface)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel =
|
2017-12-13 04:37:23 +00:00
|
|
|
META_WAYLAND_XDG_TOPLEVEL (shell_surface);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_toplevel_send_close (xdg_toplevel->resource);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel =
|
|
|
|
META_WAYLAND_XDG_TOPLEVEL (xdg_surface);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class =
|
|
|
|
META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
|
|
|
|
|
|
|
xdg_surface_class->shell_client_destroyed (xdg_surface);
|
|
|
|
|
|
|
|
if (xdg_toplevel->resource)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
|
|
|
|
"xdg_wm_base of xdg_toplevel@%d was destroyed",
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_id (xdg_toplevel->resource));
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_destroy (xdg_toplevel->resource);
|
|
|
|
}
|
2016-01-22 06:22:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_finalize (GObject *object)
|
2016-01-22 06:22:40 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (object);
|
2016-01-22 06:22:40 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
g_clear_pointer (&xdg_toplevel->resource, wl_resource_destroy);
|
2016-01-22 06:22:40 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
G_OBJECT_CLASS (meta_wayland_xdg_toplevel_parent_class)->finalize (object);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_init (MetaWaylandXdgToplevel *role)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
meta_wayland_xdg_toplevel_class_init (MetaWaylandXdgToplevelClass *klass)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
GObjectClass *object_class;
|
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
2017-12-13 04:37:23 +00:00
|
|
|
MetaWaylandShellSurfaceClass *shell_surface_class;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
object_class->finalize = meta_wayland_xdg_toplevel_finalize;
|
2016-01-22 06:22:40 +00:00
|
|
|
|
|
|
|
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state = meta_wayland_xdg_toplevel_apply_state;
|
2020-06-08 07:13:44 +00:00
|
|
|
surface_role_class->post_apply_state = meta_wayland_xdg_toplevel_post_apply_state;
|
2017-12-13 04:43:41 +00:00
|
|
|
surface_role_class->get_toplevel = meta_wayland_xdg_toplevel_get_toplevel;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-12-13 04:37:23 +00:00
|
|
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
shell_surface_class->configure = meta_wayland_xdg_toplevel_configure;
|
|
|
|
shell_surface_class->managed = meta_wayland_xdg_toplevel_managed;
|
|
|
|
shell_surface_class->close = meta_wayland_xdg_toplevel_close;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
xdg_surface_class = META_WAYLAND_XDG_SURFACE_CLASS (klass);
|
|
|
|
xdg_surface_class->shell_client_destroyed =
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_toplevel_shell_client_destroyed;
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_surface_class->reset = meta_wayland_xdg_toplevel_reset;
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
2016-10-13 05:56:00 +00:00
|
|
|
static void
|
|
|
|
scale_placement_rule (MetaPlacementRule *placement_rule,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
2019-10-09 07:37:04 +00:00
|
|
|
MetaWindow *window = meta_wayland_surface_get_window (surface);
|
2017-02-24 09:05:01 +00:00
|
|
|
int geometry_scale;
|
2016-10-13 05:56:00 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
geometry_scale = meta_window_wayland_get_geometry_scale (window);
|
2017-02-24 09:05:01 +00:00
|
|
|
|
|
|
|
placement_rule->anchor_rect.x *= geometry_scale;
|
|
|
|
placement_rule->anchor_rect.y *= geometry_scale;
|
|
|
|
placement_rule->anchor_rect.width *= geometry_scale;
|
|
|
|
placement_rule->anchor_rect.height *= geometry_scale;
|
|
|
|
placement_rule->offset_x *= geometry_scale;
|
|
|
|
placement_rule->offset_y *= geometry_scale;
|
|
|
|
placement_rule->width *= geometry_scale;
|
|
|
|
placement_rule->height *= geometry_scale;
|
2016-10-13 05:56:00 +00:00
|
|
|
}
|
|
|
|
|
2018-10-24 13:02:42 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_popup_place (MetaWaylandXdgPopup *xdg_popup,
|
|
|
|
MetaPlacementRule *placement_rule)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
MetaPlacementRule scaled_placement_rule;
|
2019-10-09 07:37:04 +00:00
|
|
|
MetaWindow *window;
|
2018-10-24 13:02:42 +00:00
|
|
|
|
|
|
|
scaled_placement_rule = *placement_rule;
|
|
|
|
scale_placement_rule (&scaled_placement_rule, surface);
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
|
|
|
meta_window_place_with_placement_rule (window, &scaled_placement_rule);
|
2018-10-24 13:02:42 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
|
|
|
finish_popup_setup (MetaWaylandXdgPopup *xdg_popup)
|
|
|
|
{
|
2017-11-15 08:02:03 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
|
2017-12-22 08:26:24 +00:00
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
MetaWaylandSurface *parent_surface;
|
|
|
|
MetaWaylandSeat *seat;
|
|
|
|
uint32_t serial;
|
2022-05-30 21:48:44 +00:00
|
|
|
MetaDisplay *display = display_from_surface (surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWindow *window;
|
2022-11-01 16:30:00 +00:00
|
|
|
MetaWindow *parent_window;
|
|
|
|
MetaPlacementRule placement_rule;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
parent_surface = xdg_popup->setup.parent_surface;
|
|
|
|
seat = xdg_popup->setup.grab_seat;
|
|
|
|
serial = xdg_popup->setup.grab_serial;
|
|
|
|
|
|
|
|
xdg_popup->setup.parent_surface = NULL;
|
|
|
|
xdg_popup->setup.grab_seat = NULL;
|
2021-09-07 08:57:53 +00:00
|
|
|
xdg_popup->dismissed_by_client = FALSE;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
if (!meta_wayland_surface_get_window (parent_surface))
|
2017-11-15 08:04:33 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup_send_popup_done (xdg_popup->resource);
|
2017-11-15 08:04:33 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (seat)
|
|
|
|
{
|
2017-11-15 08:02:03 +00:00
|
|
|
MetaWaylandSurface *top_popup;
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (!meta_wayland_seat_can_popup (seat, serial))
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup_send_popup_done (xdg_popup->resource);
|
2016-07-01 08:30:14 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-11-15 08:02:03 +00:00
|
|
|
|
|
|
|
top_popup = meta_wayland_pointer_get_top_popup (seat->pointer);
|
|
|
|
if (top_popup && parent_surface != top_popup)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
|
2017-11-15 08:02:03 +00:00
|
|
|
"parent not top most surface");
|
|
|
|
return;
|
|
|
|
}
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
xdg_popup->parent_surface = parent_surface;
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup->parent_surface_unmapped_handler_id =
|
|
|
|
g_signal_connect (parent_surface, "unmapped",
|
|
|
|
G_CALLBACK (on_parent_surface_unmapped),
|
|
|
|
xdg_popup);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
window = meta_window_wayland_new (display, surface);
|
2017-12-22 08:26:24 +00:00
|
|
|
meta_wayland_shell_surface_set_window (shell_surface, window);
|
2016-10-13 05:56:00 +00:00
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
parent_window = meta_wayland_surface_get_window (parent_surface);
|
|
|
|
placement_rule =
|
|
|
|
meta_wayland_xdg_positioner_to_placement (&xdg_popup->setup.xdg_positioner,
|
|
|
|
parent_window);
|
|
|
|
meta_wayland_xdg_popup_place (xdg_popup, &placement_rule);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
if (seat)
|
|
|
|
{
|
|
|
|
MetaWaylandPopupSurface *popup_surface;
|
|
|
|
MetaWaylandPopup *popup;
|
|
|
|
|
|
|
|
meta_window_focus (window, meta_display_get_current_time (display));
|
|
|
|
popup_surface = META_WAYLAND_POPUP_SURFACE (surface->role);
|
2016-04-01 08:39:30 +00:00
|
|
|
popup = meta_wayland_pointer_start_popup_grab (seat->pointer,
|
2016-07-01 08:30:14 +00:00
|
|
|
popup_surface);
|
|
|
|
if (popup == NULL)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup_send_popup_done (xdg_popup->resource);
|
2019-09-04 16:35:08 +00:00
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xdg_popup->popup = popup;
|
|
|
|
}
|
2016-12-12 18:30:36 +00:00
|
|
|
else
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
/* The keyboard focus semantics for non-grabbing xdg_wm_base popups
|
2016-12-12 18:30:36 +00:00
|
|
|
* is pretty undefined. Same applies for subsurfaces, but in practice,
|
|
|
|
* subsurfaces never receive keyboard focus, so it makes sense to
|
|
|
|
* do the same for non-grabbing popups.
|
|
|
|
*
|
|
|
|
* See https://bugzilla.gnome.org/show_bug.cgi?id=771694#c24
|
|
|
|
*/
|
|
|
|
window->input = FALSE;
|
|
|
|
}
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 20:52:54 +00:00
|
|
|
static void
|
|
|
|
dismiss_invalid_popup (MetaWaylandXdgPopup *xdg_popup)
|
|
|
|
{
|
|
|
|
if (xdg_popup->popup)
|
|
|
|
{
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *top_popup_surface;
|
|
|
|
MetaWaylandXdgPopup *top_xdg_popup;
|
|
|
|
|
|
|
|
top_popup_surface =
|
|
|
|
meta_wayland_popup_get_top_popup (xdg_popup->popup);
|
|
|
|
if (!top_popup_surface)
|
|
|
|
break;
|
|
|
|
|
|
|
|
top_xdg_popup = meta_wayland_xdg_popup_from_surface (top_popup_surface);
|
|
|
|
|
|
|
|
xdg_popup_send_popup_done (top_xdg_popup->resource);
|
2023-03-27 19:43:33 +00:00
|
|
|
meta_wayland_popup_dismiss (top_xdg_popup->popup);
|
2022-09-28 20:52:54 +00:00
|
|
|
|
|
|
|
if (top_xdg_popup == xdg_popup)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xdg_popup_send_popup_done (xdg_popup->resource);
|
|
|
|
meta_wayland_xdg_popup_unmap (xdg_popup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 15:52:41 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_popup_commit_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandTransaction *transaction,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
|
|
|
|
|
|
|
|
if (xdg_popup->setup.parent_surface)
|
|
|
|
{
|
|
|
|
meta_wayland_transaction_ensure_entry (transaction,
|
|
|
|
xdg_popup->setup.parent_surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2019-07-11 09:20:44 +00:00
|
|
|
meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
2017-12-22 08:37:44 +00:00
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2020-04-27 13:43:19 +00:00
|
|
|
MetaWaylandActorSurface *actor_surface =
|
|
|
|
META_WAYLAND_ACTOR_SURFACE (xdg_popup);
|
2015-12-15 04:51:24 +00:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
if (xdg_popup->setup.parent_surface)
|
|
|
|
finish_popup_setup (xdg_popup);
|
|
|
|
|
xdg-shell: Early out of apply if dismissed
We might end up trying to apply a pending state late if it was delayed
by DMA buffers not being ready. Trying to discard the pending state from
the transaction when dismissing is hard, because we might be applying a
chain of transactions that would disqualify subsequent transactions if a
former one dismisses the popup, so lets just drop what the apply would
otherwise do, if we're not going to use it anyway.
This fixes the following crash:
0) meta_wayland_surface_get_window (surface=0x0)
1) meta_wayland_xdg_popup_apply_state (surface_role=0xf5ee80, pending=0xf662a0)
2) meta_wayland_surface_role_apply_state (surface_role=0xf5ee80, pending=0xf662a0)
3) meta_wayland_surface_apply_state (surface=0xf5e640, state=0xf662a0)
4) meta_wayland_transaction_apply (transaction=0xf56170, first_candidate=0x7fffffffcee8)
5) meta_wayland_transaction_maybe_apply_one (transaction=0xf56170, first_candidate=0x7fffffffcee8)
6) meta_wayland_transaction_maybe_apply (transaction=0xf56170)
7) meta_wayland_transaction_dma_buf_dispatch (buffer=0xf448a0, user_data=0xf56200)
8) meta_wayland_dma_buf_source_dispatch (base=0xf5f140, callback=0x0, user_data=0x0)
9) g_main_dispatch (context=0x41baa0)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2940>
2023-03-28 21:07:54 +00:00
|
|
|
if (!meta_wayland_surface_get_window (surface))
|
2023-04-16 09:21:49 +00:00
|
|
|
{
|
|
|
|
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
|
|
|
|
return;
|
|
|
|
}
|
xdg-shell: Early out of apply if dismissed
We might end up trying to apply a pending state late if it was delayed
by DMA buffers not being ready. Trying to discard the pending state from
the transaction when dismissing is hard, because we might be applying a
chain of transactions that would disqualify subsequent transactions if a
former one dismisses the popup, so lets just drop what the apply would
otherwise do, if we're not going to use it anyway.
This fixes the following crash:
0) meta_wayland_surface_get_window (surface=0x0)
1) meta_wayland_xdg_popup_apply_state (surface_role=0xf5ee80, pending=0xf662a0)
2) meta_wayland_surface_role_apply_state (surface_role=0xf5ee80, pending=0xf662a0)
3) meta_wayland_surface_apply_state (surface=0xf5e640, state=0xf662a0)
4) meta_wayland_transaction_apply (transaction=0xf56170, first_candidate=0x7fffffffcee8)
5) meta_wayland_transaction_maybe_apply_one (transaction=0xf56170, first_candidate=0x7fffffffcee8)
6) meta_wayland_transaction_maybe_apply (transaction=0xf56170)
7) meta_wayland_transaction_dma_buf_dispatch (buffer=0xf448a0, user_data=0xf56200)
8) meta_wayland_dma_buf_source_dispatch (base=0xf5f140, callback=0x0, user_data=0x0)
9) g_main_dispatch (context=0x41baa0)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2940>
2023-03-28 21:07:54 +00:00
|
|
|
|
2022-11-01 16:30:00 +00:00
|
|
|
if (pending->xdg_positioner)
|
|
|
|
{
|
|
|
|
MetaWindow *window, *parent_window;
|
|
|
|
MetaPlacementRule placement_rule;
|
|
|
|
|
|
|
|
parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface);
|
|
|
|
placement_rule =
|
|
|
|
meta_wayland_xdg_positioner_to_placement (pending->xdg_positioner,
|
|
|
|
parent_window);
|
|
|
|
|
|
|
|
xdg_popup->pending_reposition_token = pending->xdg_popup_reposition_token;
|
|
|
|
xdg_popup->pending_repositioned = TRUE;
|
|
|
|
|
|
|
|
scale_placement_rule (&placement_rule, surface);
|
|
|
|
|
|
|
|
window = meta_wayland_surface_get_window (surface);
|
|
|
|
meta_window_update_placement_rule (window, &placement_rule);
|
|
|
|
}
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (!surface->buffer && xdg_surface_priv->first_buffer_attached)
|
2017-12-22 08:37:44 +00:00
|
|
|
{
|
|
|
|
meta_wayland_xdg_surface_reset (xdg_surface);
|
2020-04-27 13:43:19 +00:00
|
|
|
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
|
2017-12-22 08:37:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
surface_role_class =
|
2016-01-14 04:49:14 +00:00
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class);
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state (surface_role, pending);
|
2015-12-15 04:51:24 +00: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 16:43:11 +00:00
|
|
|
if (xdg_popup->dismissed_by_client && surface->buffer)
|
2017-12-22 08:37:44 +00:00
|
|
|
{
|
|
|
|
wl_resource_post_error (xdg_popup->resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"Can't commit buffer to dismissed popup");
|
|
|
|
return;
|
|
|
|
}
|
2020-06-08 07:13:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_popup_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2022-09-28 15:01:50 +00:00
|
|
|
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2020-06-08 07:13:44 +00:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class =
|
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class);
|
|
|
|
MetaWindow *window;
|
|
|
|
MetaWindow *parent_window;
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle old_geometry;
|
|
|
|
MtkRectangle window_geometry;
|
|
|
|
MtkRectangle buffer_rect;
|
|
|
|
MtkRectangle parent_buffer_rect;
|
2017-12-22 08:37:44 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
window = meta_wayland_surface_get_window (surface);
|
2019-07-05 16:10:14 +00:00
|
|
|
if (!window)
|
2016-07-15 09:44:21 +00:00
|
|
|
return;
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (!surface->buffer)
|
2016-01-14 09:49:57 +00:00
|
|
|
return;
|
|
|
|
|
2020-06-08 07:13:44 +00:00
|
|
|
surface_role_class->post_apply_state (surface_role, pending);
|
|
|
|
|
2022-09-28 15:01:50 +00:00
|
|
|
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
|
|
|
|
old_geometry = xdg_surface_priv->geometry;
|
2023-07-19 15:14:13 +00:00
|
|
|
if (!mtk_rectangle_equal (&old_geometry, &window_geometry) ||
|
2022-09-28 15:01:50 +00:00
|
|
|
pending->derived.surface_size_changed ||
|
|
|
|
pending->has_acked_configure_serial)
|
|
|
|
meta_window_wayland_finish_move_resize (window, window_geometry, pending);
|
2019-07-26 13:03:36 +00:00
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface);
|
2019-07-26 13:03:36 +00:00
|
|
|
meta_window_get_buffer_rect (window, &buffer_rect);
|
|
|
|
meta_window_get_buffer_rect (parent_window, &parent_buffer_rect);
|
2023-07-19 22:55:37 +00:00
|
|
|
if (!mtk_rectangle_overlap (&buffer_rect, &parent_buffer_rect) &&
|
2019-07-26 13:03:36 +00:00
|
|
|
!meta_rectangle_is_adjacent_to (&buffer_rect, &parent_buffer_rect))
|
|
|
|
{
|
|
|
|
g_warning ("Buggy client caused popup to be placed outside of "
|
|
|
|
"parent window");
|
2022-09-28 20:52:54 +00:00
|
|
|
dismiss_invalid_popup (xdg_popup);
|
2019-07-26 13:03:36 +00:00
|
|
|
}
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 09:43:47 +00:00
|
|
|
static MetaWaylandSurface *
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_popup_get_toplevel (MetaWaylandSurfaceRole *surface_role)
|
2016-01-14 09:43:47 +00:00
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
|
2016-01-14 09:43:47 +00:00
|
|
|
|
2016-09-16 07:07:22 +00:00
|
|
|
if (xdg_popup->parent_surface)
|
|
|
|
return meta_wayland_surface_get_toplevel (xdg_popup->parent_surface);
|
|
|
|
else
|
|
|
|
return NULL;
|
2016-01-14 09:43:47 +00:00
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_popup_reset (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (xdg_surface);
|
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class =
|
|
|
|
META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_popup_parent_class);
|
|
|
|
|
2019-07-26 13:03:36 +00:00
|
|
|
dismiss_popup (xdg_popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
|
|
|
|
xdg_popup->dismissed_by_client = TRUE;
|
|
|
|
|
|
|
|
xdg_surface_class->reset (xdg_surface);
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2019-07-05 16:10:14 +00:00
|
|
|
meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface,
|
|
|
|
MetaWaylandWindowConfiguration *configuration)
|
2017-12-13 04:37:23 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
|
2019-10-09 07:37:04 +00:00
|
|
|
MetaWindow *parent_window =
|
|
|
|
meta_wayland_surface_get_window (xdg_popup->parent_surface);
|
2017-02-24 09:05:01 +00:00
|
|
|
int geometry_scale;
|
2016-07-01 08:30:14 +00:00
|
|
|
int x, y;
|
|
|
|
|
2023-04-17 16:35:09 +00:00
|
|
|
if (!xdg_popup->resource)
|
|
|
|
return;
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
/* If the parent surface was destroyed, its window will be destroyed
|
|
|
|
* before the popup receives the parent-destroy signal. This means that
|
|
|
|
* the popup may potentially get temporary focus until itself is destroyed.
|
|
|
|
* If this happen, don't try to configure the xdg_popup surface.
|
|
|
|
*
|
|
|
|
* FIXME: Could maybe add a signal that is emitted before the window is
|
|
|
|
* created so that we can avoid incorrect intermediate foci.
|
|
|
|
*/
|
|
|
|
if (!parent_window)
|
|
|
|
return;
|
|
|
|
|
2017-02-24 09:05:01 +00:00
|
|
|
geometry_scale = meta_window_wayland_get_geometry_scale (parent_window);
|
2020-02-13 21:20:15 +00:00
|
|
|
x = configuration->rel_x / geometry_scale;
|
|
|
|
y = configuration->rel_y / geometry_scale;
|
2020-02-14 10:13:24 +00:00
|
|
|
if (xdg_popup->pending_repositioned)
|
|
|
|
{
|
|
|
|
xdg_popup_send_repositioned (xdg_popup->resource,
|
|
|
|
xdg_popup->pending_reposition_token);
|
|
|
|
xdg_popup->pending_repositioned = FALSE;
|
|
|
|
}
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup_send_configure (xdg_popup->resource,
|
2019-07-05 16:10:14 +00:00
|
|
|
x, y,
|
wayland/window: Don't lose precision in MetaWaylandWindowConfiguration
Commit 8bdd2aa7 would offset the window position by the difference
between the configured window size and the committed size from the
client to prevent the window from drifting while resizing.
This, however, did not take into account the actual geometry scale, so
when using any scale greater than 1, the window would rapidly drift away
due to that offset.
In order to solve this, we need to make sure we store away the pending
window configuration in the stage coordinate space, in order to not
loose precision. When we then calculate the offset given the result from
the client, it'll use the right scalars, while before, one scalar was in
surface coordinates, while the other in stage coordinates.
https://gitlab.gnome.org/GNOME/mutter/-/issues/1490
2020-10-29 09:11:15 +00:00
|
|
|
configuration->width / configuration->scale,
|
|
|
|
configuration->height / configuration->scale);
|
2019-07-05 16:10:14 +00:00
|
|
|
|
|
|
|
meta_wayland_xdg_surface_send_configure (xdg_surface, configuration);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:09:20 +00:00
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_popup_managed (MetaWaylandShellSurface *shell_surface,
|
|
|
|
MetaWindow *window)
|
2015-12-15 14:09:20 +00:00
|
|
|
{
|
2017-12-13 04:37:23 +00:00
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface);
|
2016-01-22 06:22:40 +00:00
|
|
|
MetaWaylandSurface *parent = xdg_popup->parent_surface;
|
2015-12-15 14:09:20 +00:00
|
|
|
|
|
|
|
g_assert (parent);
|
|
|
|
|
2019-10-09 07:37:04 +00:00
|
|
|
meta_window_set_transient_for (window,
|
|
|
|
meta_wayland_surface_get_window (parent));
|
2015-12-15 14:09:20 +00:00
|
|
|
meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_popup_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (xdg_surface);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class =
|
|
|
|
META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_popup_parent_class);
|
|
|
|
|
|
|
|
xdg_surface_class->shell_client_destroyed (xdg_surface);
|
|
|
|
|
|
|
|
if (xdg_popup->resource)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
|
|
|
|
"xdg_wm_base of xdg_popup@%d was destroyed",
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_id (xdg_popup->resource));
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_destroy (xdg_popup->resource);
|
|
|
|
}
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-01-21 09:01:08 +00:00
|
|
|
meta_wayland_xdg_popup_done (MetaWaylandPopupSurface *popup_surface)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface);
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_popup_send_popup_done (xdg_popup->resource);
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2016-01-21 09:01:08 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_popup_dismiss (MetaWaylandPopupSurface *popup_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-01-21 09:01:08 +00:00
|
|
|
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
MetaWaylandSurface *top_popup;
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
top_popup = meta_wayland_popup_get_top_popup (xdg_popup->popup);
|
2016-01-21 09:01:08 +00:00
|
|
|
if (surface != top_popup)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
|
2016-01-21 09:01:08 +00:00
|
|
|
"destroyed popup not top most popup");
|
|
|
|
}
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
xdg_popup->popup = NULL;
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_xdg_popup_unmap (xdg_popup);
|
2016-01-21 09:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaWaylandSurface *
|
|
|
|
meta_wayland_xdg_popup_get_surface (MetaWaylandPopupSurface *popup_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
|
|
META_WAYLAND_SURFACE_ROLE (popup_surface);
|
|
|
|
|
|
|
|
return meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface)
|
|
|
|
{
|
|
|
|
iface->done = meta_wayland_xdg_popup_done;
|
|
|
|
iface->dismiss = meta_wayland_xdg_popup_dismiss;
|
|
|
|
iface->get_surface = meta_wayland_xdg_popup_get_surface;
|
|
|
|
}
|
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_popup_finalize (GObject *object)
|
2016-01-22 06:22:40 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (object);
|
|
|
|
|
|
|
|
g_clear_pointer (&xdg_popup->resource, wl_resource_destroy);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_wayland_xdg_popup_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
static void
|
2016-01-14 04:49:14 +00:00
|
|
|
meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-01-14 04:49:14 +00:00
|
|
|
meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass)
|
2015-12-15 04:51:24 +00:00
|
|
|
{
|
2016-01-22 06:22:40 +00:00
|
|
|
GObjectClass *object_class;
|
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
2017-12-13 04:37:23 +00:00
|
|
|
MetaWaylandShellSurfaceClass *shell_surface_class;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class;
|
2016-01-22 06:22:40 +00:00
|
|
|
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
object_class->finalize = meta_wayland_xdg_popup_finalize;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2016-01-22 06:22:40 +00:00
|
|
|
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
2022-11-01 15:52:41 +00:00
|
|
|
surface_role_class->commit_state = meta_wayland_xdg_popup_commit_state;
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state = meta_wayland_xdg_popup_apply_state;
|
2020-06-08 07:13:44 +00:00
|
|
|
surface_role_class->post_apply_state = meta_wayland_xdg_popup_post_apply_state;
|
2017-12-13 04:43:41 +00:00
|
|
|
surface_role_class->get_toplevel = meta_wayland_xdg_popup_get_toplevel;
|
2015-12-15 04:51:24 +00:00
|
|
|
|
2017-12-13 04:37:23 +00:00
|
|
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
shell_surface_class->configure = meta_wayland_xdg_popup_configure;
|
|
|
|
shell_surface_class->managed = meta_wayland_xdg_popup_managed;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
xdg_surface_class = META_WAYLAND_XDG_SURFACE_CLASS (klass);
|
|
|
|
xdg_surface_class->shell_client_destroyed =
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_popup_shell_client_destroyed;
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_surface_class->reset = meta_wayland_xdg_popup_reset;
|
2015-12-15 04:51:24 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static struct wl_resource *
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surface)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
return priv->shell_client->resource;
|
|
|
|
}
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2023-07-19 23:46:15 +00:00
|
|
|
static MtkRectangle
|
2016-07-01 08:30:14 +00:00
|
|
|
meta_wayland_xdg_surface_get_window_geometry (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
return priv->geometry;
|
|
|
|
}
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static gboolean
|
|
|
|
meta_wayland_xdg_surface_is_assigned (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
return priv->resource != NULL;
|
|
|
|
}
|
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface,
|
|
|
|
MetaWaylandWindowConfiguration *configuration)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
xdg_surface_send_configure (priv->resource, configuration->serial);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
priv->configure_sent = TRUE;
|
2016-01-22 08:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_surface_destructor (struct wl_resource *resource)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces,
|
|
|
|
xdg_surface);
|
|
|
|
|
|
|
|
priv->resource = NULL;
|
|
|
|
priv->first_buffer_attached = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_get_toplevel (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource, XDG_WM_BASE_ERROR_ROLE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a role assigned",
|
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_get_popup (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *parent_resource,
|
|
|
|
struct wl_resource *positioner_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
|
|
|
|
|
|
|
|
wl_resource_post_error (priv->shell_client->resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_ROLE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a role assigned",
|
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_set_window_geometry (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
|
2019-03-13 12:27:25 +00:00
|
|
|
MetaWaylandSurfaceState *pending;
|
2019-03-13 11:47:48 +00:00
|
|
|
|
2020-11-11 09:49:25 +00:00
|
|
|
if (width == 0 || height == 0)
|
|
|
|
{
|
|
|
|
g_warning ("Invalid geometry %dx%d+%d+%d set on xdg_surface@%d. Ignoring for "
|
|
|
|
"now, but this will result in client termination in the future.",
|
|
|
|
width, height, x, y,
|
|
|
|
wl_resource_get_id (resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
pending = meta_wayland_surface_get_pending_state (surface);
|
2021-07-29 16:14:20 +00:00
|
|
|
if (!pending)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"underlying wl_surface already destroyed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-13 11:47:48 +00:00
|
|
|
pending->has_new_geometry = TRUE;
|
|
|
|
pending->new_geometry.x = x;
|
|
|
|
pending->new_geometry.y = y;
|
|
|
|
pending->new_geometry.width = width;
|
|
|
|
pending->new_geometry.height = height;
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_ack_configure (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
2019-07-05 16:10:14 +00:00
|
|
|
MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource);
|
|
|
|
MetaWaylandSurfaceState *pending;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
pending = meta_wayland_surface_get_pending_state (surface);
|
2021-07-29 16:14:20 +00:00
|
|
|
if (!pending)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
|
|
|
"underlying wl_surface already destroyed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-07-05 16:10:14 +00:00
|
|
|
pending->has_acked_configure_serial = TRUE;
|
|
|
|
pending->acked_configure_serial = serial;
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_surface_destroy,
|
|
|
|
xdg_surface_get_toplevel,
|
|
|
|
xdg_surface_get_popup,
|
|
|
|
xdg_surface_set_window_geometry,
|
|
|
|
xdg_surface_ack_configure,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_surface_finalize (GObject *object)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->resource, wl_resource_destroy);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_wayland_xdg_surface_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_real_reset (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
priv->first_buffer_attached = FALSE;
|
|
|
|
priv->configure_sent = FALSE;
|
2023-07-19 23:46:15 +00:00
|
|
|
priv->geometry = (MtkRectangle) { 0 };
|
2017-12-22 08:37:44 +00:00
|
|
|
priv->has_set_geometry = FALSE;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
2019-07-11 09:20:44 +00:00
|
|
|
meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2019-10-09 07:37:04 +00:00
|
|
|
MetaWindow *window = meta_wayland_surface_get_window (surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
|
|
|
|
|
|
surface_role_class =
|
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_surface_parent_class);
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state (surface_role, pending);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
/* Ignore commits when unassigned. */
|
|
|
|
if (!priv->resource)
|
|
|
|
return;
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (!window)
|
|
|
|
return;
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (surface->buffer)
|
2016-07-01 08:30:14 +00:00
|
|
|
priv->first_buffer_attached = TRUE;
|
2020-06-08 07:13:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
|
|
MetaWaylandSurfaceState *pending)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
MetaWaylandShellSurface *shell_surface =
|
|
|
|
META_WAYLAND_SHELL_SURFACE (surface_role);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
if (pending->has_new_geometry)
|
|
|
|
{
|
2018-08-18 17:41:15 +00:00
|
|
|
meta_wayland_shell_surface_determine_geometry (shell_surface,
|
|
|
|
&pending->new_geometry,
|
|
|
|
&priv->geometry);
|
2020-11-13 07:50:57 +00:00
|
|
|
if (priv->geometry.width == 0 || priv->geometry.height == 0)
|
|
|
|
{
|
|
|
|
g_warning ("Invalid window geometry for xdg_surface@%d. Ignoring "
|
|
|
|
"for now, but this will result in client termination "
|
|
|
|
"in the future.",
|
|
|
|
wl_resource_get_id (priv->resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
priv->has_set_geometry = TRUE;
|
|
|
|
}
|
|
|
|
else if (!priv->has_set_geometry)
|
|
|
|
{
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle new_geometry = { 0 };
|
2017-05-05 11:55:51 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
/* If the surface has never set any geometry, calculate
|
|
|
|
* a default one unioning the surface and all subsurfaces together. */
|
2017-05-05 11:55:51 +00:00
|
|
|
|
2017-12-22 06:28:28 +00:00
|
|
|
meta_wayland_shell_surface_calculate_geometry (shell_surface,
|
|
|
|
&new_geometry);
|
2023-07-19 15:14:13 +00:00
|
|
|
if (!mtk_rectangle_equal (&new_geometry, &priv->geometry))
|
2017-05-05 11:55:51 +00:00
|
|
|
{
|
|
|
|
pending->has_new_geometry = TRUE;
|
|
|
|
priv->geometry = new_geometry;
|
|
|
|
}
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_surface_assigned (MetaWaylandSurfaceRole *surface_role)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
MetaWaylandSurface *surface =
|
|
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource =
|
|
|
|
meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
|
|
|
|
|
|
priv->configure_sent = FALSE;
|
|
|
|
priv->first_buffer_attached = FALSE;
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (surface->buffer)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a buffer committed",
|
2016-01-22 08:44:59 +00:00
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
surface_role_class =
|
|
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_surface_parent_class);
|
|
|
|
surface_role_class->assigned (surface_role);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_surface_ping (MetaWaylandShellSurface *shell_surface,
|
|
|
|
uint32_t serial)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
2017-12-13 04:37:23 +00:00
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (shell_surface);
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_send_ping (priv->shell_client->resource, serial);
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:43:41 +00:00
|
|
|
meta_wayland_xdg_surface_real_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
if (priv->resource)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_post_error (priv->shell_client->resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
|
|
|
|
"xdg_wm_base of xdg_surface@%d was destroyed",
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_id (priv->resource));
|
|
|
|
|
|
|
|
wl_resource_destroy (priv->resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case XDG_SURFACE_PROP_SHELL_CLIENT:
|
|
|
|
priv->shell_client = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XDG_SURFACE_PROP_RESOURCE:
|
|
|
|
priv->resource = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:55:57 +00:00
|
|
|
meta_wayland_xdg_surface_get_property (GObject *object,
|
2016-07-01 08:30:14 +00:00
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object);
|
|
|
|
MetaWaylandXdgSurfacePrivate *priv =
|
|
|
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case XDG_SURFACE_PROP_SHELL_CLIENT:
|
|
|
|
g_value_set_pointer (value, priv->shell_client);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XDG_SURFACE_PROP_RESOURCE:
|
|
|
|
g_value_set_pointer (value, priv->resource);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_init (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class;
|
|
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
2017-12-13 04:37:23 +00:00
|
|
|
MetaWaylandShellSurfaceClass *shell_surface_class;
|
2016-07-01 08:30:14 +00:00
|
|
|
GParamSpec *pspec;
|
|
|
|
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
object_class->finalize = meta_wayland_xdg_surface_finalize;
|
2016-07-01 08:30:14 +00:00
|
|
|
object_class->set_property = meta_wayland_xdg_surface_set_property;
|
|
|
|
object_class->get_property = meta_wayland_xdg_surface_get_property;
|
|
|
|
|
|
|
|
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
2019-07-11 09:20:44 +00:00
|
|
|
surface_role_class->apply_state = meta_wayland_xdg_surface_apply_state;
|
2020-06-08 07:13:44 +00:00
|
|
|
surface_role_class->post_apply_state = meta_wayland_xdg_surface_post_apply_state;
|
2017-12-13 04:43:41 +00:00
|
|
|
surface_role_class->assigned = meta_wayland_xdg_surface_assigned;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2017-12-13 04:37:23 +00:00
|
|
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
2017-12-13 04:43:41 +00:00
|
|
|
shell_surface_class->ping = meta_wayland_xdg_surface_ping;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2017-12-13 04:43:41 +00:00
|
|
|
klass->shell_client_destroyed =
|
|
|
|
meta_wayland_xdg_surface_real_shell_client_destroyed;
|
2017-12-22 08:37:44 +00:00
|
|
|
klass->reset = meta_wayland_xdg_surface_real_reset;
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2023-06-28 12:02:43 +00:00
|
|
|
pspec = g_param_spec_pointer ("shell-client", NULL, NULL,
|
2016-07-01 08:30:14 +00:00
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
XDG_SURFACE_PROP_SHELL_CLIENT,
|
|
|
|
pspec);
|
2023-06-28 12:02:43 +00:00
|
|
|
pspec = g_param_spec_pointer ("xdg-surface-resource", NULL, NULL,
|
2016-07-01 08:30:14 +00:00
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
XDG_SURFACE_PROP_RESOURCE,
|
|
|
|
pspec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfaceClass *xdg_surface_class =
|
|
|
|
META_WAYLAND_XDG_SURFACE_GET_CLASS (xdg_surface);
|
|
|
|
|
|
|
|
xdg_surface_class->shell_client_destroyed (xdg_surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_xdg_surface_constructor_finalize (MetaWaylandXdgSurfaceConstructor *constructor,
|
|
|
|
MetaWaylandXdgSurface *xdg_surface)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgShellClient *shell_client = constructor->shell_client;
|
|
|
|
|
|
|
|
shell_client->surface_constructors =
|
|
|
|
g_list_remove (shell_client->surface_constructors, constructor);
|
|
|
|
shell_client->surfaces = g_list_append (shell_client->surfaces, xdg_surface);
|
|
|
|
|
|
|
|
wl_resource_set_implementation (constructor->resource,
|
|
|
|
&meta_wayland_xdg_surface_interface,
|
|
|
|
xdg_surface,
|
|
|
|
xdg_surface_destructor);
|
|
|
|
|
|
|
|
g_free (constructor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
|
2016-07-01 08:30:14 +00:00
|
|
|
"xdg_surface destroyed before constructed");
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_get_toplevel (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfaceConstructor *constructor =
|
|
|
|
wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandXdgShellClient *shell_client = constructor->shell_client;
|
|
|
|
struct wl_resource *xdg_surface_resource = constructor->resource;
|
|
|
|
MetaWaylandSurface *surface = constructor->surface;
|
|
|
|
MetaWaylandXdgToplevel *xdg_toplevel;
|
|
|
|
MetaWaylandXdgSurface *xdg_surface;
|
2017-12-22 08:26:24 +00:00
|
|
|
MetaWaylandShellSurface *shell_surface;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWindow *window;
|
|
|
|
|
|
|
|
if (!meta_wayland_surface_assign_role (surface,
|
|
|
|
META_TYPE_WAYLAND_XDG_TOPLEVEL,
|
|
|
|
"shell-client", shell_client,
|
|
|
|
"xdg-surface-resource", xdg_surface_resource,
|
|
|
|
NULL))
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_WM_BASE_ERROR_ROLE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a different role",
|
|
|
|
wl_resource_get_id (surface->resource));
|
2016-01-22 08:44:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (surface->role);
|
|
|
|
xdg_toplevel->resource = wl_resource_create (client,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_toplevel_interface,
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_version (resource),
|
|
|
|
id);
|
|
|
|
wl_resource_set_implementation (xdg_toplevel->resource,
|
|
|
|
&meta_wayland_xdg_toplevel_interface,
|
|
|
|
xdg_toplevel,
|
|
|
|
xdg_toplevel_destructor);
|
|
|
|
|
|
|
|
xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel);
|
|
|
|
meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface);
|
|
|
|
|
2022-05-30 21:48:44 +00:00
|
|
|
window = meta_window_wayland_new (display_from_surface (surface), surface);
|
2017-12-22 08:26:24 +00:00
|
|
|
shell_surface = META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
|
|
|
meta_wayland_shell_surface_set_window (shell_surface, window);
|
2016-07-01 08:30:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_get_popup (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *parent_resource,
|
|
|
|
struct wl_resource *positioner_resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfaceConstructor *constructor =
|
|
|
|
wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandXdgShellClient *shell_client = constructor->shell_client;
|
|
|
|
MetaWaylandSurface *surface = constructor->surface;
|
2017-12-22 08:37:44 +00:00
|
|
|
struct wl_resource *xdg_wm_base_resource = constructor->shell_client->resource;
|
2016-07-01 08:30:14 +00:00
|
|
|
struct wl_resource *xdg_surface_resource = constructor->resource;
|
2020-08-26 18:51:13 +00:00
|
|
|
MetaWaylandSurface *parent_surface;
|
2020-02-14 09:41:38 +00:00
|
|
|
MetaWindow *parent_window;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgPositioner *xdg_positioner;
|
|
|
|
MetaWaylandXdgPopup *xdg_popup;
|
|
|
|
MetaWaylandXdgSurface *xdg_surface;
|
|
|
|
|
2020-08-26 18:51:13 +00:00
|
|
|
if (!parent_resource)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT,
|
|
|
|
"Parent surface is null but Mutter does not yet "
|
|
|
|
"support specifying parent surfaces via other "
|
|
|
|
"protocols");
|
2020-08-26 20:55:40 +00:00
|
|
|
return;
|
2020-08-26 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
parent_surface = surface_from_xdg_surface_resource (parent_resource);
|
2020-08-26 20:55:40 +00:00
|
|
|
if (!parent_surface || !META_IS_WAYLAND_XDG_SURFACE (parent_surface->role))
|
2017-11-15 08:03:36 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT,
|
2017-11-15 08:03:36 +00:00
|
|
|
"Invalid popup parent role");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-16 20:54:23 +00:00
|
|
|
parent_window = meta_wayland_surface_get_window (parent_surface);
|
|
|
|
if (!parent_window)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (xdg_wm_base_resource,
|
|
|
|
XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT,
|
|
|
|
"Invalid popup parent window");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-26 20:55:40 +00:00
|
|
|
if (!meta_wayland_surface_assign_role (surface,
|
|
|
|
META_TYPE_WAYLAND_XDG_POPUP,
|
|
|
|
"shell-client", shell_client,
|
|
|
|
"xdg-surface-resource", xdg_surface_resource,
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
wl_resource_post_error (xdg_wm_base_resource, XDG_WM_BASE_ERROR_ROLE,
|
|
|
|
"wl_surface@%d already has a different role",
|
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-22 08:44:59 +00:00
|
|
|
xdg_popup = META_WAYLAND_XDG_POPUP (surface->role);
|
2017-12-22 08:37:44 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_popup->resource = wl_resource_create (client,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_popup_interface,
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_version (resource),
|
|
|
|
id);
|
2016-01-22 08:44:59 +00:00
|
|
|
wl_resource_set_implementation (xdg_popup->resource,
|
|
|
|
&meta_wayland_xdg_popup_interface,
|
|
|
|
xdg_popup,
|
|
|
|
xdg_popup_destructor);
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
|
|
|
|
meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface);
|
|
|
|
|
|
|
|
xdg_positioner = wl_resource_get_user_data (positioner_resource);
|
2022-11-01 16:30:00 +00:00
|
|
|
xdg_popup->setup.xdg_positioner = *xdg_positioner;
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_popup->setup.parent_surface = parent_surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_set_window_geometry (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
|
2016-07-01 08:30:14 +00:00
|
|
|
"xdg_surface::set_window_geometry called before constructed");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_ack_configure (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
|
2016-07-01 08:30:14 +00:00
|
|
|
"xdg_surface::ack_configure called before constructed");
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_surface_interface meta_wayland_xdg_surface_constructor_interface = {
|
2016-07-01 08:30:14 +00:00
|
|
|
xdg_surface_constructor_destroy,
|
|
|
|
xdg_surface_constructor_get_toplevel,
|
|
|
|
xdg_surface_constructor_get_popup,
|
|
|
|
xdg_surface_constructor_set_window_geometry,
|
|
|
|
xdg_surface_constructor_ack_configure,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_surface_constructor_destructor (struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfaceConstructor *constructor =
|
|
|
|
wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
constructor->shell_client->surface_constructors =
|
|
|
|
g_list_remove (constructor->shell_client->surface_constructors,
|
|
|
|
constructor);
|
|
|
|
|
|
|
|
g_free (constructor);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static MetaPlacementAnchor
|
|
|
|
positioner_anchor_to_placement_anchor (uint32_t anchor)
|
|
|
|
{
|
|
|
|
switch (anchor)
|
|
|
|
{
|
|
|
|
case XDG_POSITIONER_ANCHOR_NONE:
|
|
|
|
return META_PLACEMENT_ANCHOR_NONE;
|
|
|
|
case XDG_POSITIONER_ANCHOR_TOP:
|
|
|
|
return META_PLACEMENT_ANCHOR_TOP;
|
|
|
|
case XDG_POSITIONER_ANCHOR_BOTTOM:
|
|
|
|
return META_PLACEMENT_ANCHOR_BOTTOM;
|
|
|
|
case XDG_POSITIONER_ANCHOR_LEFT:
|
|
|
|
return META_PLACEMENT_ANCHOR_LEFT;
|
|
|
|
case XDG_POSITIONER_ANCHOR_RIGHT:
|
|
|
|
return META_PLACEMENT_ANCHOR_RIGHT;
|
|
|
|
case XDG_POSITIONER_ANCHOR_TOP_LEFT:
|
|
|
|
return (META_PLACEMENT_ANCHOR_TOP | META_PLACEMENT_ANCHOR_LEFT);
|
|
|
|
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT:
|
|
|
|
return (META_PLACEMENT_ANCHOR_BOTTOM | META_PLACEMENT_ANCHOR_LEFT);
|
|
|
|
case XDG_POSITIONER_ANCHOR_TOP_RIGHT:
|
|
|
|
return (META_PLACEMENT_ANCHOR_TOP | META_PLACEMENT_ANCHOR_RIGHT);
|
|
|
|
case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT:
|
|
|
|
return (META_PLACEMENT_ANCHOR_BOTTOM | META_PLACEMENT_ANCHOR_RIGHT);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2019-01-24 23:47:44 +00:00
|
|
|
return META_PLACEMENT_ANCHOR_NONE;
|
2017-12-22 08:37:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaPlacementGravity
|
|
|
|
positioner_gravity_to_placement_gravity (uint32_t gravity)
|
|
|
|
{
|
|
|
|
switch (gravity)
|
|
|
|
{
|
|
|
|
case XDG_POSITIONER_GRAVITY_NONE:
|
|
|
|
return META_PLACEMENT_GRAVITY_NONE;
|
|
|
|
case XDG_POSITIONER_GRAVITY_TOP:
|
|
|
|
return META_PLACEMENT_GRAVITY_TOP;
|
|
|
|
case XDG_POSITIONER_GRAVITY_BOTTOM:
|
|
|
|
return META_PLACEMENT_GRAVITY_BOTTOM;
|
|
|
|
case XDG_POSITIONER_GRAVITY_LEFT:
|
|
|
|
return META_PLACEMENT_GRAVITY_LEFT;
|
|
|
|
case XDG_POSITIONER_GRAVITY_RIGHT:
|
|
|
|
return META_PLACEMENT_GRAVITY_RIGHT;
|
|
|
|
case XDG_POSITIONER_GRAVITY_TOP_LEFT:
|
|
|
|
return (META_PLACEMENT_GRAVITY_TOP | META_PLACEMENT_GRAVITY_LEFT);
|
|
|
|
case XDG_POSITIONER_GRAVITY_BOTTOM_LEFT:
|
|
|
|
return (META_PLACEMENT_GRAVITY_BOTTOM | META_PLACEMENT_GRAVITY_LEFT);
|
|
|
|
case XDG_POSITIONER_GRAVITY_TOP_RIGHT:
|
|
|
|
return (META_PLACEMENT_GRAVITY_TOP | META_PLACEMENT_GRAVITY_RIGHT);
|
|
|
|
case XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT:
|
|
|
|
return (META_PLACEMENT_GRAVITY_BOTTOM | META_PLACEMENT_GRAVITY_RIGHT);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2019-01-24 23:47:44 +00:00
|
|
|
return META_PLACEMENT_GRAVITY_NONE;
|
2017-12-22 08:37:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static MetaPlacementRule
|
2020-02-14 09:41:38 +00:00
|
|
|
meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner,
|
|
|
|
MetaWindow *parent_window)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
2023-07-19 23:46:15 +00:00
|
|
|
MtkRectangle parent_rect;
|
2020-02-14 09:41:38 +00:00
|
|
|
|
|
|
|
meta_window_get_frame_rect (parent_window, &parent_rect);
|
|
|
|
|
2020-02-14 10:13:24 +00:00
|
|
|
if (xdg_positioner->acked_parent_configure)
|
|
|
|
{
|
|
|
|
MetaWindowWayland *parent_wl_window = META_WINDOW_WAYLAND (parent_window);
|
|
|
|
uint32_t serial;
|
|
|
|
MetaWaylandWindowConfiguration *configuration;
|
|
|
|
|
|
|
|
serial = xdg_positioner->parent_configure_serial;
|
|
|
|
configuration = meta_window_wayland_peek_configuration (parent_wl_window,
|
|
|
|
serial);
|
|
|
|
|
|
|
|
if (configuration)
|
|
|
|
{
|
|
|
|
if (configuration->flags & META_MOVE_RESIZE_STATE_CHANGED)
|
|
|
|
{
|
|
|
|
if (configuration->has_position)
|
|
|
|
{
|
|
|
|
parent_rect.x = configuration->x;
|
|
|
|
parent_rect.y = configuration->y;
|
|
|
|
}
|
|
|
|
if (configuration->has_size)
|
|
|
|
{
|
wayland/window: Don't lose precision in MetaWaylandWindowConfiguration
Commit 8bdd2aa7 would offset the window position by the difference
between the configured window size and the committed size from the
client to prevent the window from drifting while resizing.
This, however, did not take into account the actual geometry scale, so
when using any scale greater than 1, the window would rapidly drift away
due to that offset.
In order to solve this, we need to make sure we store away the pending
window configuration in the stage coordinate space, in order to not
loose precision. When we then calculate the offset given the result from
the client, it'll use the right scalars, while before, one scalar was in
surface coordinates, while the other in stage coordinates.
https://gitlab.gnome.org/GNOME/mutter/-/issues/1490
2020-10-29 09:11:15 +00:00
|
|
|
parent_rect.width =
|
|
|
|
configuration->width / configuration->scale;
|
|
|
|
parent_rect.height =
|
|
|
|
configuration->height / configuration->scale;
|
2020-02-14 10:13:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (xdg_positioner->has_parent_size)
|
|
|
|
{
|
|
|
|
meta_rectangle_resize_with_gravity (&parent_rect,
|
|
|
|
&parent_rect,
|
|
|
|
configuration->gravity,
|
|
|
|
xdg_positioner->parent_width,
|
|
|
|
xdg_positioner->parent_height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (xdg_positioner->has_parent_size)
|
|
|
|
{
|
|
|
|
meta_rectangle_resize_with_gravity (&parent_rect,
|
|
|
|
&parent_rect,
|
|
|
|
META_GRAVITY_SOUTH_EAST,
|
|
|
|
xdg_positioner->parent_width,
|
|
|
|
xdg_positioner->parent_height);
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
return (MetaPlacementRule) {
|
|
|
|
.anchor_rect = xdg_positioner->anchor_rect,
|
2017-12-22 08:37:44 +00:00
|
|
|
.gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity),
|
|
|
|
.anchor = positioner_anchor_to_placement_anchor (xdg_positioner->anchor),
|
2016-07-01 08:30:14 +00:00
|
|
|
.constraint_adjustment = xdg_positioner->constraint_adjustment,
|
|
|
|
.offset_x = xdg_positioner->offset_x,
|
|
|
|
.offset_y = xdg_positioner->offset_y,
|
|
|
|
.width = xdg_positioner->width,
|
|
|
|
.height = xdg_positioner->height,
|
2020-02-14 09:41:38 +00:00
|
|
|
|
2020-02-14 10:11:10 +00:00
|
|
|
.is_reactive = xdg_positioner->is_reactive,
|
|
|
|
|
2020-02-14 09:41:38 +00:00
|
|
|
.parent_rect = parent_rect,
|
2016-07-01 08:30:14 +00:00
|
|
|
};
|
|
|
|
}
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_size (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
if (width <= 0 || height <= 0)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT,
|
2016-07-01 08:30:14 +00:00
|
|
|
"Invalid size");
|
2016-01-22 08:44:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
positioner->width = width;
|
|
|
|
positioner->height = height;
|
|
|
|
}
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_anchor_rect (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y,
|
|
|
|
int32_t width,
|
|
|
|
int32_t height)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
if (width <= 0 || height <= 0)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT,
|
2016-07-01 08:30:14 +00:00
|
|
|
"Invalid anchor rectangle size");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-19 23:46:15 +00:00
|
|
|
positioner->anchor_rect = (MtkRectangle) {
|
2016-07-01 08:30:14 +00:00
|
|
|
.x = x,
|
|
|
|
.y = y,
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_anchor (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t anchor)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
if (anchor > XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT,
|
2016-07-01 08:30:14 +00:00
|
|
|
"Invalid anchor");
|
2016-01-22 08:44:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
positioner->anchor = anchor;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_gravity (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t gravity)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
if (gravity > XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT,
|
2016-07-01 08:30:14 +00:00
|
|
|
"Invalid gravity");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
positioner->gravity = gravity;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_constraint_adjustment (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t constraint_adjustment)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
2017-12-22 08:37:44 +00:00
|
|
|
uint32_t all_adjustments = (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
|
|
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X |
|
|
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y |
|
|
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
|
|
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X |
|
|
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y);
|
2016-07-01 08:30:14 +00:00
|
|
|
|
|
|
|
if ((constraint_adjustment & ~all_adjustments) != 0)
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT,
|
2016-07-01 08:30:14 +00:00
|
|
|
"Invalid constraint action");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
positioner->constraint_adjustment = constraint_adjustment;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_set_offset (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t x,
|
|
|
|
int32_t y)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
positioner->offset_x = x;
|
|
|
|
positioner->offset_y = y;
|
|
|
|
}
|
|
|
|
|
2020-02-14 10:11:10 +00:00
|
|
|
static void
|
|
|
|
xdg_positioner_set_reactive (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
positioner->is_reactive = TRUE;
|
|
|
|
}
|
|
|
|
|
2020-02-14 10:13:24 +00:00
|
|
|
static void
|
|
|
|
xdg_positioner_set_parent_size (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
int32_t parent_width,
|
|
|
|
int32_t parent_height)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
positioner->has_parent_size = TRUE;
|
|
|
|
positioner->parent_width = parent_width;
|
|
|
|
positioner->parent_height = parent_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_positioner_set_parent_configure (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
positioner->acked_parent_configure = TRUE;
|
|
|
|
positioner->parent_configure_serial = serial;
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interface = {
|
2017-12-13 04:49:08 +00:00
|
|
|
xdg_positioner_destroy,
|
|
|
|
xdg_positioner_set_size,
|
|
|
|
xdg_positioner_set_anchor_rect,
|
|
|
|
xdg_positioner_set_anchor,
|
|
|
|
xdg_positioner_set_gravity,
|
|
|
|
xdg_positioner_set_constraint_adjustment,
|
|
|
|
xdg_positioner_set_offset,
|
2020-02-14 10:11:10 +00:00
|
|
|
xdg_positioner_set_reactive,
|
2020-02-14 10:13:24 +00:00
|
|
|
xdg_positioner_set_parent_size,
|
|
|
|
xdg_positioner_set_parent_configure,
|
2016-07-01 08:30:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
xdg_positioner_destructor (struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
g_free (positioner);
|
2016-01-22 08:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_destroy (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgShellClient *shell_client = wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
if (shell_client->surfaces || shell_client->surface_constructors)
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
|
|
|
|
"xdg_wm_base destroyed before its surfaces");
|
2016-07-01 08:30:14 +00:00
|
|
|
|
2016-01-22 08:44:59 +00:00
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_create_positioner (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgPositioner *positioner;
|
|
|
|
struct wl_resource *positioner_resource;
|
|
|
|
|
|
|
|
positioner = g_new0 (MetaWaylandXdgPositioner, 1);
|
|
|
|
positioner_resource = wl_resource_create (client,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_positioner_interface,
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_version (resource),
|
|
|
|
id);
|
|
|
|
wl_resource_set_implementation (positioner_resource,
|
|
|
|
&meta_wayland_xdg_positioner_interface,
|
|
|
|
positioner,
|
|
|
|
xdg_positioner_destructor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_get_xdg_surface (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t id,
|
|
|
|
struct wl_resource *surface_resource)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
MetaWaylandXdgShellClient *shell_client = wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
|
|
|
MetaWaylandXdgSurfaceConstructor *constructor;
|
|
|
|
|
|
|
|
if (surface->role && !META_IS_WAYLAND_XDG_SURFACE (surface->role))
|
|
|
|
{
|
2017-12-22 08:37:44 +00:00
|
|
|
wl_resource_post_error (resource, XDG_WM_BASE_ERROR_ROLE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a different role",
|
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (surface->role && META_IS_WAYLAND_XDG_SURFACE (surface->role) &&
|
|
|
|
meta_wayland_xdg_surface_is_assigned (META_WAYLAND_XDG_SURFACE (surface->role)))
|
|
|
|
{
|
|
|
|
wl_resource_post_error (surface_resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_ROLE,
|
|
|
|
"xdg_wm_base::get_xdg_surface already requested");
|
2016-07-01 08:30:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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 16:43:11 +00:00
|
|
|
if (surface->buffer)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
wl_resource_post_error (resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
2016-07-01 08:30:14 +00:00
|
|
|
"wl_surface@%d already has a buffer committed",
|
|
|
|
wl_resource_get_id (surface->resource));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor = g_new0 (MetaWaylandXdgSurfaceConstructor, 1);
|
|
|
|
constructor->surface = surface;
|
|
|
|
constructor->shell_client = shell_client;
|
|
|
|
constructor->resource = wl_resource_create (client,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_surface_interface,
|
2016-07-01 08:30:14 +00:00
|
|
|
wl_resource_get_version (resource),
|
|
|
|
id);
|
|
|
|
wl_resource_set_implementation (constructor->resource,
|
|
|
|
&meta_wayland_xdg_surface_constructor_interface,
|
|
|
|
constructor,
|
|
|
|
xdg_surface_constructor_destructor);
|
|
|
|
|
|
|
|
shell_client->surface_constructors =
|
|
|
|
g_list_append (shell_client->surface_constructors, constructor);
|
2016-01-22 08:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_pong (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2022-05-30 21:48:44 +00:00
|
|
|
MetaWaylandXdgShellClient *shell_client =
|
|
|
|
wl_resource_get_user_data (resource);
|
|
|
|
MetaContext *context =
|
|
|
|
meta_wayland_compositor_get_context (shell_client->compositor);
|
|
|
|
MetaDisplay *display = meta_context_get_display (context);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
|
|
|
meta_display_pong_for_serial (display, serial);
|
|
|
|
}
|
|
|
|
|
2017-12-22 08:37:44 +00:00
|
|
|
static const struct xdg_wm_base_interface meta_wayland_xdg_wm_base_interface = {
|
|
|
|
xdg_wm_base_destroy,
|
|
|
|
xdg_wm_base_create_positioner,
|
|
|
|
xdg_wm_base_get_xdg_surface,
|
|
|
|
xdg_wm_base_pong,
|
2016-01-22 08:44:59 +00:00
|
|
|
};
|
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
meta_wayland_xdg_shell_client_destroy (MetaWaylandXdgShellClient *shell_client)
|
2016-07-01 08:30:14 +00:00
|
|
|
{
|
|
|
|
while (shell_client->surface_constructors)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurfaceConstructor *constructor =
|
|
|
|
g_list_first (shell_client->surface_constructors)->data;
|
|
|
|
|
|
|
|
wl_resource_destroy (constructor->resource);
|
|
|
|
}
|
|
|
|
g_list_free (shell_client->surface_constructors);
|
|
|
|
|
|
|
|
while (shell_client->surfaces)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgSurface *xdg_surface =
|
|
|
|
g_list_first (shell_client->surfaces)->data;
|
|
|
|
|
|
|
|
meta_wayland_xdg_surface_shell_client_destroyed (xdg_surface);
|
|
|
|
}
|
|
|
|
g_list_free (shell_client->surfaces);
|
|
|
|
|
|
|
|
g_free (shell_client);
|
|
|
|
}
|
|
|
|
|
2016-01-22 08:44:59 +00:00
|
|
|
static void
|
2017-12-22 08:37:44 +00:00
|
|
|
xdg_wm_base_destructor (struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
MetaWaylandXdgShellClient *shell_client =
|
|
|
|
wl_resource_get_user_data (resource);
|
|
|
|
|
|
|
|
meta_wayland_xdg_shell_client_destroy (shell_client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bind_xdg_wm_base (struct wl_client *client,
|
|
|
|
void *data,
|
|
|
|
uint32_t version,
|
|
|
|
uint32_t id)
|
2016-01-22 08:44:59 +00:00
|
|
|
{
|
2022-05-30 21:48:44 +00:00
|
|
|
MetaWaylandCompositor *compositor = data;
|
2016-07-01 08:30:14 +00:00
|
|
|
MetaWaylandXdgShellClient *shell_client;
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2016-07-01 08:30:14 +00:00
|
|
|
shell_client = g_new0 (MetaWaylandXdgShellClient, 1);
|
2016-01-22 08:44:59 +00:00
|
|
|
|
2022-05-30 21:48:44 +00:00
|
|
|
shell_client->compositor = compositor;
|
2016-07-01 08:30:14 +00:00
|
|
|
shell_client->resource = wl_resource_create (client,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_wm_base_interface,
|
2016-07-01 08:30:14 +00:00
|
|
|
version, id);
|
|
|
|
wl_resource_set_implementation (shell_client->resource,
|
2017-12-22 08:37:44 +00:00
|
|
|
&meta_wayland_xdg_wm_base_interface,
|
|
|
|
shell_client, xdg_wm_base_destructor);
|
2016-01-22 08:44:59 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 04:51:24 +00:00
|
|
|
void
|
|
|
|
meta_wayland_xdg_shell_init (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
if (wl_global_create (compositor->wayland_display,
|
2017-12-22 08:37:44 +00:00
|
|
|
&xdg_wm_base_interface,
|
|
|
|
META_XDG_WM_BASE_VERSION,
|
|
|
|
compositor, bind_xdg_wm_base) == NULL)
|
2015-12-15 04:51:24 +00:00
|
|
|
g_error ("Failed to register a global xdg-shell object");
|
|
|
|
}
|