mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 12:00:44 -05:00
a64dba4d7a
Just because of implementation details, this is only relevant to Wayland, and is done via ::effects-completed handlers there. Ideally, Clutter should notice by itself about effects starting, finishing, and affecting picking. Doing this in generic code seems slightly cleaner in the interim. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1654>
381 lines
12 KiB
C
381 lines
12 KiB
C
/*
|
|
* Copyright (C) 2012,2013 Intel Corporation
|
|
* Copyright (C) 2013-2017 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
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "wayland/meta-wayland-shell-surface.h"
|
|
|
|
#include "compositor/meta-surface-actor-wayland.h"
|
|
#include "compositor/meta-window-actor-private.h"
|
|
#include "compositor/meta-window-actor-wayland.h"
|
|
#include "wayland/meta-wayland-actor-surface.h"
|
|
#include "wayland/meta-wayland-buffer.h"
|
|
#include "wayland/meta-wayland-subsurface.h"
|
|
#include "wayland/meta-wayland-surface.h"
|
|
#include "wayland/meta-window-wayland.h"
|
|
|
|
typedef struct _MetaWaylandShellSurfacePrivate
|
|
{
|
|
MetaWindow *window;
|
|
|
|
gulong unmanaging_handler_id;
|
|
} MetaWaylandShellSurfacePrivate;
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandShellSurface,
|
|
meta_wayland_shell_surface,
|
|
META_TYPE_WAYLAND_ACTOR_SURFACE)
|
|
|
|
void
|
|
meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
|
|
MetaRectangle *out_geometry)
|
|
{
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
META_WAYLAND_SURFACE_ROLE (shell_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaRectangle geometry;
|
|
MetaWaylandSurface *subsurface_surface;
|
|
|
|
geometry = (MetaRectangle) {
|
|
.width = meta_wayland_surface_get_width (surface),
|
|
.height = meta_wayland_surface_get_height (surface),
|
|
};
|
|
|
|
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
|
{
|
|
MetaWaylandSubsurface *subsurface;
|
|
|
|
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
|
meta_wayland_subsurface_union_geometry (subsurface,
|
|
0, 0,
|
|
&geometry);
|
|
}
|
|
|
|
*out_geometry = geometry;
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_determine_geometry (MetaWaylandShellSurface *shell_surface,
|
|
MetaRectangle *set_geometry,
|
|
MetaRectangle *out_geometry)
|
|
{
|
|
MetaRectangle bounding_geometry = { 0 };
|
|
MetaRectangle intersected_geometry = { 0 };
|
|
|
|
meta_wayland_shell_surface_calculate_geometry (shell_surface,
|
|
&bounding_geometry);
|
|
|
|
meta_rectangle_intersect (set_geometry, &bounding_geometry,
|
|
&intersected_geometry);
|
|
|
|
*out_geometry = intersected_geometry;
|
|
}
|
|
|
|
static void
|
|
clear_window (MetaWaylandShellSurface *shell_surface)
|
|
{
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
META_WAYLAND_SURFACE_ROLE (shell_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaSurfaceActor *surface_actor;
|
|
|
|
if (!priv->window)
|
|
return;
|
|
|
|
g_clear_signal_handler (&priv->unmanaging_handler_id,
|
|
priv->window);
|
|
priv->window = NULL;
|
|
|
|
surface_actor = meta_wayland_surface_get_actor (surface);
|
|
if (surface_actor)
|
|
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE);
|
|
|
|
meta_wayland_surface_notify_unmapped (surface);
|
|
}
|
|
|
|
static void
|
|
window_unmanaging (MetaWindow *window,
|
|
MetaWaylandShellSurface *shell_surface)
|
|
{
|
|
clear_window (shell_surface);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface,
|
|
MetaWindow *window)
|
|
{
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
META_WAYLAND_SURFACE_ROLE (shell_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaSurfaceActor *surface_actor;
|
|
|
|
g_assert (!priv->window);
|
|
|
|
priv->window = window;
|
|
|
|
surface_actor = meta_wayland_surface_get_actor (surface);
|
|
if (surface_actor)
|
|
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
|
|
|
|
priv->unmanaging_handler_id =
|
|
g_signal_connect (window,
|
|
"unmanaging",
|
|
G_CALLBACK (window_unmanaging),
|
|
shell_surface);
|
|
|
|
meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface,
|
|
MetaWaylandWindowConfiguration *configuration)
|
|
{
|
|
MetaWaylandShellSurfaceClass *shell_surface_class =
|
|
META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
|
|
|
|
shell_surface_class->configure (shell_surface, configuration);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_ping (MetaWaylandShellSurface *shell_surface,
|
|
uint32_t serial)
|
|
{
|
|
MetaWaylandShellSurfaceClass *shell_surface_class =
|
|
META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
|
|
|
|
shell_surface_class->ping (shell_surface, serial);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface)
|
|
{
|
|
MetaWaylandShellSurfaceClass *shell_surface_class =
|
|
META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
|
|
|
|
shell_surface_class->close (shell_surface);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface,
|
|
MetaWindow *window)
|
|
{
|
|
MetaWaylandShellSurfaceClass *shell_surface_class =
|
|
META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
|
|
|
|
shell_surface_class->managed (shell_surface, window);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_assigned (MetaWaylandSurfaceRole *surface_role)
|
|
{
|
|
MetaWaylandSurfaceRoleClass *surface_role_class =
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs ();
|
|
|
|
surface_role_class->assigned (surface_role);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
MetaWaylandSurfaceState *pending)
|
|
{
|
|
MetaWaylandShellSurface *shell_surface =
|
|
META_WAYLAND_SHELL_SURFACE (surface_role);
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
|
|
if (pending->newly_attached &&
|
|
!surface->buffer_ref->buffer &&
|
|
priv->window)
|
|
meta_window_queue (priv->window, META_QUEUE_CALC_SHOWING);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|
MetaWaylandSurfaceState *pending)
|
|
{
|
|
MetaWaylandShellSurface *shell_surface =
|
|
META_WAYLAND_SHELL_SURFACE (surface_role);
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWaylandActorSurface *actor_surface =
|
|
META_WAYLAND_ACTOR_SURFACE (surface_role);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
|
MetaWindow *window;
|
|
MetaWaylandBuffer *buffer;
|
|
double geometry_scale;
|
|
|
|
surface_role_class =
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class);
|
|
surface_role_class->apply_state (surface_role, pending);
|
|
|
|
buffer = surface->buffer_ref->buffer;
|
|
if (!buffer)
|
|
return;
|
|
|
|
window = priv->window;
|
|
if (!window)
|
|
return;
|
|
|
|
geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
|
|
|
window->buffer_rect.width =
|
|
meta_wayland_surface_get_width (surface) * geometry_scale;
|
|
window->buffer_rect.height =
|
|
meta_wayland_surface_get_height (surface) * geometry_scale;
|
|
}
|
|
|
|
static MetaWindow *
|
|
meta_wayland_shell_surface_get_window (MetaWaylandSurfaceRole *surface_role)
|
|
{
|
|
MetaWaylandShellSurface *shell_surface =
|
|
META_WAYLAND_SHELL_SURFACE (surface_role);
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
|
|
return priv->window;
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role)
|
|
{
|
|
MetaWaylandShellSurface *shell_surface =
|
|
META_WAYLAND_SHELL_SURFACE (surface_role);
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWindow *window;
|
|
MetaWindowActor *window_actor;
|
|
|
|
window = priv->window;
|
|
if (!window)
|
|
return;
|
|
|
|
window_actor = meta_window_actor_from_window (window);
|
|
meta_window_actor_wayland_rebuild_surface_tree (window_actor);
|
|
}
|
|
|
|
static double
|
|
meta_wayland_shell_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface)
|
|
{
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
META_WAYLAND_SURFACE_ROLE (actor_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaWindow *toplevel_window;
|
|
|
|
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
|
|
if (meta_is_stage_views_scaled () || !toplevel_window)
|
|
return 1;
|
|
else
|
|
return meta_window_wayland_get_geometry_scale (toplevel_window);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
|
|
{
|
|
MetaWaylandSurfaceRole *surface_role =
|
|
META_WAYLAND_SURFACE_ROLE (actor_surface);
|
|
MetaWaylandSurface *surface =
|
|
meta_wayland_surface_role_get_surface (surface_role);
|
|
MetaWaylandActorSurfaceClass *actor_surface_class =
|
|
META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_shell_surface_parent_class);
|
|
MetaWindow *toplevel_window;
|
|
|
|
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
|
|
if (!toplevel_window)
|
|
return;
|
|
|
|
actor_surface_class->sync_actor_state (actor_surface);
|
|
}
|
|
|
|
void
|
|
meta_wayland_shell_surface_destroy_window (MetaWaylandShellSurface *shell_surface)
|
|
{
|
|
MetaWaylandShellSurfacePrivate *priv =
|
|
meta_wayland_shell_surface_get_instance_private (shell_surface);
|
|
MetaWindow *window;
|
|
MetaDisplay *display;
|
|
uint32_t timestamp;
|
|
|
|
window = priv->window;
|
|
if (!window)
|
|
return;
|
|
|
|
display = meta_window_get_display (window);
|
|
timestamp = meta_display_get_current_time_roundtrip (display);
|
|
meta_window_unmanage (window, timestamp);
|
|
g_assert (!priv->window);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_finalize (GObject *object)
|
|
{
|
|
MetaWaylandShellSurface *shell_surface = META_WAYLAND_SHELL_SURFACE (object);
|
|
|
|
meta_wayland_shell_surface_destroy_window (shell_surface);
|
|
|
|
G_OBJECT_CLASS (meta_wayland_shell_surface_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_init (MetaWaylandShellSurface *role)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_wayland_shell_surface_class_init (MetaWaylandShellSurfaceClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
MetaWaylandSurfaceRoleClass *surface_role_class =
|
|
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
|
MetaWaylandActorSurfaceClass *actor_surface_class =
|
|
META_WAYLAND_ACTOR_SURFACE_CLASS (klass);
|
|
|
|
object_class->finalize = meta_wayland_shell_surface_finalize;
|
|
|
|
surface_role_class->assigned = meta_wayland_shell_surface_assigned;
|
|
surface_role_class->pre_apply_state =
|
|
meta_wayland_shell_surface_surface_pre_apply_state;
|
|
surface_role_class->apply_state =
|
|
meta_wayland_shell_surface_surface_apply_state;
|
|
surface_role_class->notify_subsurface_state_changed =
|
|
meta_wayland_shell_surface_notify_subsurface_state_changed;
|
|
surface_role_class->get_window = meta_wayland_shell_surface_get_window;
|
|
|
|
actor_surface_class->get_geometry_scale =
|
|
meta_wayland_shell_surface_get_geometry_scale;
|
|
actor_surface_class->sync_actor_state =
|
|
meta_wayland_shell_surface_sync_actor_state;
|
|
}
|