2012-01-07 17:21:32 -05:00
|
|
|
/*
|
|
|
|
* Wayland Support
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012,2013 Intel Corporation
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2014-10-07 23:05:57 -04:00
|
|
|
#include "config.h"
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland.h"
|
2012-01-07 17:21:32 -05:00
|
|
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <wayland-server.h>
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "clutter/clutter.h"
|
2021-05-06 06:12:34 -04:00
|
|
|
#include "cogl/cogl-egl.h"
|
2020-10-22 17:16:28 -04:00
|
|
|
#include "compositor/meta-surface-actor-wayland.h"
|
2021-03-02 04:21:20 -05:00
|
|
|
#include "core/meta-context-private.h"
|
2020-10-09 10:23:32 -04:00
|
|
|
#include "wayland/meta-wayland-activation.h"
|
2019-09-18 10:18:58 -04:00
|
|
|
#include "wayland/meta-wayland-buffer.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-data-device.h"
|
|
|
|
#include "wayland/meta-wayland-dma-buf.h"
|
|
|
|
#include "wayland/meta-wayland-egl-stream.h"
|
|
|
|
#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h"
|
|
|
|
#include "wayland/meta-wayland-inhibit-shortcuts.h"
|
|
|
|
#include "wayland/meta-wayland-outputs.h"
|
2020-10-07 05:02:41 -04:00
|
|
|
#include "wayland/meta-wayland-presentation-time-private.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "wayland/meta-wayland-private.h"
|
|
|
|
#include "wayland/meta-wayland-region.h"
|
|
|
|
#include "wayland/meta-wayland-seat.h"
|
|
|
|
#include "wayland/meta-wayland-subsurface.h"
|
|
|
|
#include "wayland/meta-wayland-tablet-manager.h"
|
|
|
|
#include "wayland/meta-wayland-xdg-foreign.h"
|
|
|
|
#include "wayland/meta-xwayland-grab-keyboard.h"
|
|
|
|
#include "wayland/meta-xwayland-private.h"
|
|
|
|
#include "wayland/meta-xwayland.h"
|
2017-08-27 14:44:58 -04:00
|
|
|
|
2021-10-14 12:36:43 -04:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
#include "backends/native/meta-renderer-native.h"
|
|
|
|
#endif
|
|
|
|
|
2016-12-05 08:23:46 -05:00
|
|
|
static char *_display_name_override;
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2018-08-23 09:49:17 -04:00
|
|
|
G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT)
|
|
|
|
|
2012-01-07 17:21:32 -05:00
|
|
|
MetaWaylandCompositor *
|
|
|
|
meta_wayland_compositor_get_default (void)
|
|
|
|
{
|
2020-04-27 07:30:26 -04:00
|
|
|
MetaBackend *backend;
|
2021-03-03 16:00:05 -05:00
|
|
|
MetaContext *context;
|
2020-04-27 07:30:26 -04:00
|
|
|
MetaWaylandCompositor *wayland_compositor;
|
2018-08-23 09:49:17 -04:00
|
|
|
|
2020-04-27 07:30:26 -04:00
|
|
|
backend = meta_get_backend ();
|
2021-03-03 16:00:05 -05:00
|
|
|
context = meta_backend_get_context (backend);
|
|
|
|
wayland_compositor = meta_context_get_wayland_compositor (context);
|
2020-04-27 07:30:26 -04:00
|
|
|
g_assert (wayland_compositor);
|
|
|
|
|
|
|
|
return wayland_compositor;
|
2012-01-07 17:21:32 -05:00
|
|
|
}
|
|
|
|
|
2014-10-07 23:50:57 -04:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GSource source;
|
|
|
|
struct wl_display *display;
|
|
|
|
} WaylandEventSource;
|
|
|
|
|
2012-01-07 17:21:32 -05:00
|
|
|
static gboolean
|
2017-06-05 08:09:01 -04:00
|
|
|
wayland_event_source_prepare (GSource *base,
|
|
|
|
int *timeout)
|
2012-01-07 17:21:32 -05:00
|
|
|
{
|
|
|
|
WaylandEventSource *source = (WaylandEventSource *)base;
|
|
|
|
|
|
|
|
*timeout = -1;
|
|
|
|
|
|
|
|
wl_display_flush_clients (source->display);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2017-06-05 08:09:01 -04:00
|
|
|
wayland_event_source_dispatch (GSource *base,
|
2012-01-07 17:21:32 -05:00
|
|
|
GSourceFunc callback,
|
2017-06-05 08:09:01 -04:00
|
|
|
void *data)
|
2012-01-07 17:21:32 -05:00
|
|
|
{
|
|
|
|
WaylandEventSource *source = (WaylandEventSource *)base;
|
|
|
|
struct wl_event_loop *loop = wl_display_get_event_loop (source->display);
|
|
|
|
|
|
|
|
wl_event_loop_dispatch (loop, 0);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GSourceFuncs wayland_event_source_funcs =
|
|
|
|
{
|
|
|
|
wayland_event_source_prepare,
|
2014-12-15 17:42:33 -05:00
|
|
|
NULL,
|
2012-01-07 17:21:32 -05:00
|
|
|
wayland_event_source_dispatch,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static GSource *
|
|
|
|
wayland_event_source_new (struct wl_display *display)
|
|
|
|
{
|
|
|
|
WaylandEventSource *source;
|
|
|
|
struct wl_event_loop *loop = wl_display_get_event_loop (display);
|
|
|
|
|
|
|
|
source = (WaylandEventSource *) g_source_new (&wayland_event_source_funcs,
|
|
|
|
sizeof (WaylandEventSource));
|
|
|
|
source->display = display;
|
2014-12-15 17:42:33 -05:00
|
|
|
g_source_add_unix_fd (&source->source,
|
|
|
|
wl_event_loop_get_fd (loop),
|
|
|
|
G_IO_IN | G_IO_ERR);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
|
|
|
return &source->source;
|
|
|
|
}
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
void
|
|
|
|
meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
MetaWaylandSurface *surface = window ? window->surface : NULL;
|
|
|
|
|
2014-07-10 10:13:54 -04:00
|
|
|
meta_wayland_seat_set_input_focus (compositor->seat, surface);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2014-10-07 23:08:31 -04:00
|
|
|
static void
|
2017-06-05 08:09:01 -04:00
|
|
|
wl_compositor_create_surface (struct wl_client *client,
|
2014-10-07 23:08:31 -04:00
|
|
|
struct wl_resource *resource,
|
2017-06-05 08:09:01 -04:00
|
|
|
uint32_t id)
|
2014-10-07 23:08:31 -04:00
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
|
2017-06-05 08:09:01 -04:00
|
|
|
|
2014-10-07 23:08:31 -04:00
|
|
|
meta_wayland_surface_create (compositor, client, resource, id);
|
|
|
|
}
|
|
|
|
|
2012-01-07 17:21:32 -05:00
|
|
|
static void
|
2017-06-05 08:09:01 -04:00
|
|
|
wl_compositor_create_region (struct wl_client *client,
|
2014-10-07 23:12:36 -04:00
|
|
|
struct wl_resource *resource,
|
2017-06-05 08:09:01 -04:00
|
|
|
uint32_t id)
|
2012-01-07 17:21:32 -05:00
|
|
|
{
|
2014-10-07 23:12:36 -04:00
|
|
|
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
|
2017-06-05 08:09:01 -04:00
|
|
|
|
2014-10-07 23:12:36 -04:00
|
|
|
meta_wayland_region_create (compositor, client, resource, id);
|
2012-01-07 17:21:32 -05:00
|
|
|
}
|
|
|
|
|
2015-09-23 19:20:33 -04:00
|
|
|
static const struct wl_compositor_interface meta_wayland_wl_compositor_interface = {
|
2014-08-04 10:26:55 -04:00
|
|
|
wl_compositor_create_surface,
|
|
|
|
wl_compositor_create_region
|
2012-01-07 17:21:32 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
compositor_bind (struct wl_client *client,
|
2017-06-05 08:09:01 -04:00
|
|
|
void *data,
|
|
|
|
uint32_t version,
|
|
|
|
uint32_t id)
|
2012-01-07 17:21:32 -05:00
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = data;
|
|
|
|
struct wl_resource *resource;
|
|
|
|
|
2014-08-04 10:24:59 -04:00
|
|
|
resource = wl_resource_create (client, &wl_compositor_interface, version, id);
|
2017-06-05 08:09:01 -04:00
|
|
|
wl_resource_set_implementation (resource,
|
|
|
|
&meta_wayland_wl_compositor_interface,
|
|
|
|
compositor, NULL);
|
2012-01-07 17:21:32 -05:00
|
|
|
}
|
|
|
|
|
2014-03-18 13:00:48 -04:00
|
|
|
/**
|
|
|
|
* meta_wayland_compositor_update:
|
|
|
|
* @compositor: the #MetaWaylandCompositor instance
|
|
|
|
* @event: the #ClutterEvent used to update @seat's state
|
|
|
|
*
|
|
|
|
* This is used to update display server state like updating cursor
|
|
|
|
* position and keeping track of buttons and keys pressed. It must be
|
|
|
|
* called for all input events coming from the underlying devices.
|
|
|
|
*/
|
2013-11-13 15:41:29 -05:00
|
|
|
void
|
|
|
|
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
|
|
|
const ClutterEvent *event)
|
2013-08-23 09:07:57 -04:00
|
|
|
{
|
2015-01-09 11:29:06 -05:00
|
|
|
if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
|
|
|
|
meta_wayland_tablet_manager_update (compositor->tablet_manager, event);
|
|
|
|
else
|
|
|
|
meta_wayland_seat_update (compositor->seat, event);
|
2013-08-23 09:07:57 -04:00
|
|
|
}
|
|
|
|
|
2020-06-03 05:38:32 -04:00
|
|
|
static void
|
|
|
|
on_after_update (ClutterStage *stage,
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
ClutterStageView *stage_view,
|
2020-06-03 05:38:32 -04:00
|
|
|
MetaWaylandCompositor *compositor)
|
2014-10-07 23:08:31 -04:00
|
|
|
{
|
2020-04-27 09:43:19 -04:00
|
|
|
GList *l;
|
|
|
|
int64_t now_us;
|
2017-04-30 14:49:26 -04:00
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
now_us = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
l = compositor->frame_callback_surfaces;
|
|
|
|
while (l)
|
2014-10-07 23:08:31 -04:00
|
|
|
{
|
2020-04-27 09:43:19 -04:00
|
|
|
GList *l_cur = l;
|
|
|
|
MetaWaylandSurface *surface = l->data;
|
|
|
|
MetaSurfaceActor *actor;
|
|
|
|
MetaWaylandActorSurface *actor_surface;
|
2020-10-22 17:16:28 -04:00
|
|
|
ClutterStageView *surface_primary_view;
|
2020-04-27 09:43:19 -04:00
|
|
|
|
|
|
|
l = l->next;
|
|
|
|
|
|
|
|
actor = meta_wayland_surface_get_actor (surface);
|
|
|
|
if (!actor)
|
|
|
|
continue;
|
2014-10-07 23:08:31 -04:00
|
|
|
|
2020-10-22 17:16:28 -04:00
|
|
|
surface_primary_view =
|
|
|
|
meta_surface_actor_wayland_get_current_primary_view (actor, stage);
|
|
|
|
if (stage_view != surface_primary_view)
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
continue;
|
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role);
|
|
|
|
meta_wayland_actor_surface_emit_frame_callbacks (actor_surface,
|
|
|
|
now_us / 1000);
|
|
|
|
|
|
|
|
compositor->frame_callback_surfaces =
|
|
|
|
g_list_delete_link (compositor->frame_callback_surfaces, l_cur);
|
2014-10-07 23:08:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-08 08:34:28 -04:00
|
|
|
static MetaWaylandOutput *
|
|
|
|
get_output_for_stage_view (MetaWaylandCompositor *compositor,
|
|
|
|
ClutterStageView *stage_view)
|
|
|
|
{
|
|
|
|
MetaCrtc *crtc;
|
|
|
|
MetaOutput *output;
|
|
|
|
MetaMonitor *monitor;
|
|
|
|
|
|
|
|
crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* All outputs occupy the same region of the screen, as their contents are
|
|
|
|
* the same, so pick the first one.
|
|
|
|
*/
|
|
|
|
output = meta_crtc_get_outputs (crtc)->data;
|
|
|
|
|
|
|
|
monitor = meta_output_get_monitor (output);
|
2021-02-05 11:22:30 -05:00
|
|
|
return g_hash_table_lookup (compositor->outputs,
|
|
|
|
meta_monitor_get_spec (monitor));
|
2020-10-08 08:34:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_presented (ClutterStage *stage,
|
|
|
|
ClutterStageView *stage_view,
|
|
|
|
ClutterFrameInfo *frame_info,
|
|
|
|
MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaWaylandPresentationFeedback *feedback, *next;
|
|
|
|
struct wl_list *feedbacks;
|
|
|
|
MetaWaylandOutput *output;
|
|
|
|
|
|
|
|
feedbacks =
|
|
|
|
meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
|
|
|
|
stage_view);
|
|
|
|
|
|
|
|
output = get_output_for_stage_view (compositor, stage_view);
|
|
|
|
|
|
|
|
wl_list_for_each_safe (feedback, next, feedbacks, link)
|
|
|
|
{
|
|
|
|
meta_wayland_presentation_feedback_present (feedback,
|
|
|
|
frame_info,
|
|
|
|
output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 13:00:48 -04:00
|
|
|
/**
|
|
|
|
* meta_wayland_compositor_handle_event:
|
|
|
|
* @compositor: the #MetaWaylandCompositor instance
|
|
|
|
* @event: the #ClutterEvent to be sent
|
|
|
|
*
|
|
|
|
* This method sends events to the focused wayland client, if any.
|
|
|
|
*
|
|
|
|
* Return value: whether @event was sent to a wayland client.
|
|
|
|
*/
|
2013-10-04 02:29:43 -04:00
|
|
|
gboolean
|
|
|
|
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
|
|
|
const ClutterEvent *event)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2015-01-09 11:29:06 -05:00
|
|
|
if (meta_wayland_tablet_manager_handle_event (compositor->tablet_manager,
|
|
|
|
event))
|
|
|
|
return TRUE;
|
|
|
|
|
2013-10-04 02:33:10 -04:00
|
|
|
return meta_wayland_seat_handle_event (compositor->seat, event);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2015-08-21 16:25:53 -04:00
|
|
|
/* meta_wayland_compositor_update_key_state:
|
|
|
|
* @compositor: the #MetaWaylandCompositor
|
|
|
|
* @key_vector: bit vector of key states
|
|
|
|
* @key_vector_len: length of @key_vector
|
|
|
|
* @offset: the key for the first evdev keycode is found at this offset in @key_vector
|
|
|
|
*
|
|
|
|
* This function is used to resynchronize the key state that Mutter
|
|
|
|
* is tracking with the actual keyboard state. This is useful, for example,
|
|
|
|
* to handle changes in key state when a nested compositor doesn't
|
|
|
|
* have focus. We need to fix up the XKB modifier tracking and deliver
|
|
|
|
* any modifier changes to clients.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor,
|
|
|
|
char *key_vector,
|
|
|
|
int key_vector_len,
|
|
|
|
int offset)
|
|
|
|
{
|
2016-04-01 04:39:30 -04:00
|
|
|
meta_wayland_keyboard_update_key_state (compositor->seat->keyboard,
|
2015-08-21 16:25:53 -04:00
|
|
|
key_vector, key_vector_len, offset);
|
|
|
|
}
|
|
|
|
|
2015-02-25 10:26:01 -05:00
|
|
|
void
|
2020-04-27 09:43:19 -04:00
|
|
|
meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWaylandSurface *surface)
|
2015-02-25 10:26:01 -05:00
|
|
|
{
|
2020-04-27 09:43:19 -04:00
|
|
|
if (g_list_find (compositor->frame_callback_surfaces, surface))
|
|
|
|
return;
|
2015-02-25 10:26:01 -05:00
|
|
|
|
2020-04-27 09:43:19 -04:00
|
|
|
compositor->frame_callback_surfaces =
|
|
|
|
g_list_prepend (compositor->frame_callback_surfaces, surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
compositor->frame_callback_surfaces =
|
|
|
|
g_list_remove (compositor->frame_callback_surfaces, surface);
|
2015-02-25 10:26:01 -05:00
|
|
|
}
|
|
|
|
|
2020-10-08 08:41:31 -04:00
|
|
|
void
|
|
|
|
meta_wayland_compositor_add_presentation_feedback_surface (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (g_list_find (compositor->presentation_time.feedback_surfaces, surface))
|
|
|
|
return;
|
|
|
|
|
|
|
|
compositor->presentation_time.feedback_surfaces =
|
|
|
|
g_list_prepend (compositor->presentation_time.feedback_surfaces, surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_remove_presentation_feedback_surface (MetaWaylandCompositor *compositor,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
compositor->presentation_time.feedback_surfaces =
|
|
|
|
g_list_remove (compositor->presentation_time.feedback_surfaces, surface);
|
|
|
|
}
|
|
|
|
|
2013-08-20 12:03:26 -04:00
|
|
|
static void
|
|
|
|
set_gnome_env (const char *name,
|
|
|
|
const char *value)
|
|
|
|
{
|
|
|
|
GDBusConnection *session_bus;
|
2014-03-26 12:02:08 -04:00
|
|
|
GError *error = NULL;
|
2020-01-24 12:47:43 -05:00
|
|
|
g_autoptr (GVariant) result = NULL;
|
2013-08-20 12:03:26 -04:00
|
|
|
|
|
|
|
setenv (name, value, TRUE);
|
|
|
|
|
|
|
|
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
|
|
|
g_assert (session_bus);
|
|
|
|
|
2020-01-24 12:47:43 -05:00
|
|
|
result = g_dbus_connection_call_sync (session_bus,
|
2013-08-20 12:03:26 -04:00
|
|
|
"org.gnome.SessionManager",
|
|
|
|
"/org/gnome/SessionManager",
|
|
|
|
"org.gnome.SessionManager",
|
|
|
|
"Setenv",
|
|
|
|
g_variant_new ("(ss)", name, value),
|
|
|
|
NULL,
|
2014-05-15 14:16:20 -04:00
|
|
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
2013-08-20 12:03:26 -04:00
|
|
|
-1, NULL, &error);
|
|
|
|
if (error)
|
|
|
|
{
|
2017-11-06 14:37:34 -05:00
|
|
|
char *remote_error;
|
|
|
|
|
|
|
|
remote_error = g_dbus_error_get_remote_error (error);
|
|
|
|
if (g_strcmp0 (remote_error, "org.gnome.SessionManager.NotInInitialization") != 0)
|
2020-10-02 11:47:22 -04:00
|
|
|
{
|
|
|
|
meta_warning ("Failed to set environment variable %s for gnome-session: %s",
|
|
|
|
name, error->message);
|
|
|
|
}
|
2014-03-26 12:02:08 -04:00
|
|
|
|
2017-11-06 14:37:34 -05:00
|
|
|
g_free (remote_error);
|
2014-03-26 12:02:08 -04:00
|
|
|
g_error_free (error);
|
2013-08-20 12:03:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-23 19:18:15 -04:00
|
|
|
static void meta_wayland_log_func (const char *, va_list) G_GNUC_PRINTF (1, 0);
|
|
|
|
|
2013-11-19 20:04:49 -05:00
|
|
|
static void
|
|
|
|
meta_wayland_log_func (const char *fmt,
|
|
|
|
va_list arg)
|
|
|
|
{
|
|
|
|
char *str = g_strdup_vprintf (fmt, arg);
|
|
|
|
g_warning ("WL: %s", str);
|
|
|
|
g_free (str);
|
|
|
|
}
|
|
|
|
|
2021-03-03 16:00:05 -05:00
|
|
|
void
|
|
|
|
meta_wayland_compositor_prepare_shutdown (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
meta_xwayland_shutdown (&compositor->xwayland_manager);
|
|
|
|
|
|
|
|
if (compositor->wayland_display)
|
|
|
|
wl_display_destroy_clients (compositor->wayland_display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_compositor_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = META_WAYLAND_COMPOSITOR (object);
|
|
|
|
|
|
|
|
g_clear_pointer (&compositor->seat, meta_wayland_seat_free);
|
|
|
|
|
|
|
|
g_clear_pointer (&compositor->display_name, g_free);
|
|
|
|
g_clear_pointer (&compositor->wayland_display, wl_display_destroy);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_wayland_compositor_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2014-08-18 16:54:15 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
2018-04-06 09:47:50 -04:00
|
|
|
compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL);
|
2014-08-18 16:54:15 -04:00
|
|
|
|
|
|
|
wl_log_set_handler_server (meta_wayland_log_func);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
|
|
|
compositor->wayland_display = wl_display_create ();
|
|
|
|
if (compositor->wayland_display == NULL)
|
2014-08-18 16:54:15 -04:00
|
|
|
g_error ("Failed to create the global wl_display");
|
2018-08-23 09:49:17 -04:00
|
|
|
}
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2018-08-23 09:49:17 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_compositor_class_init (MetaWaylandCompositorClass *klass)
|
|
|
|
{
|
2021-03-03 16:00:05 -05:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_wayland_compositor_finalize;
|
2018-08-23 09:49:17 -04:00
|
|
|
}
|
|
|
|
|
2016-08-30 03:20:49 -04:00
|
|
|
static bool
|
|
|
|
meta_xwayland_global_filter (const struct wl_client *client,
|
|
|
|
const struct wl_global *global,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = (MetaWaylandCompositor *) data;
|
|
|
|
MetaXWaylandManager *xwayland_manager = &compositor->xwayland_manager;
|
|
|
|
|
|
|
|
/* Keyboard grabbing protocol is for Xwayland only */
|
|
|
|
if (client != xwayland_manager->client)
|
|
|
|
return (wl_global_get_interface (global) !=
|
|
|
|
&zwp_xwayland_keyboard_grab_manager_v1_interface);
|
|
|
|
|
|
|
|
/* All others are visible to all clients */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-12-05 08:23:46 -05:00
|
|
|
void
|
2019-01-20 05:46:46 -05:00
|
|
|
meta_wayland_override_display_name (const char *display_name)
|
2016-12-05 08:23:46 -05:00
|
|
|
{
|
2017-08-18 02:18:14 -04:00
|
|
|
g_clear_pointer (&_display_name_override, g_free);
|
2016-12-05 08:23:46 -05:00
|
|
|
_display_name_override = g_strdup (display_name);
|
|
|
|
}
|
|
|
|
|
2019-06-18 10:12:46 -04:00
|
|
|
static const char *
|
|
|
|
meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
return compositor->xwayland_manager.auth_file;
|
|
|
|
}
|
|
|
|
|
2021-05-06 06:12:34 -04:00
|
|
|
static void
|
|
|
|
meta_wayland_init_egl (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaBackend *backend = meta_get_backend ();
|
|
|
|
MetaEgl *egl = meta_backend_get_egl (backend);
|
|
|
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
|
|
CoglContext *cogl_context =
|
|
|
|
clutter_backend_get_cogl_context (clutter_backend);
|
|
|
|
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
if (!meta_egl_has_extensions (egl, egl_display, NULL,
|
|
|
|
"EGL_WL_bind_wayland_display",
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_WAYLAND,
|
|
|
|
"Not binding Wayland display, missing extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_WAYLAND,
|
|
|
|
"Binding Wayland EGL display");
|
|
|
|
|
|
|
|
if (!meta_egl_bind_wayland_display (egl,
|
|
|
|
egl_display,
|
|
|
|
compositor->wayland_display,
|
|
|
|
&error))
|
|
|
|
g_warning ("Failed to bind Wayland display: %s", error->message);
|
|
|
|
}
|
|
|
|
|
2021-05-06 10:02:34 -04:00
|
|
|
MetaWaylandCompositor *
|
|
|
|
meta_wayland_compositor_new (MetaContext *context)
|
2014-08-18 16:54:15 -04:00
|
|
|
{
|
2021-05-06 10:02:34 -04:00
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2021-03-03 16:00:05 -05:00
|
|
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
2021-05-06 10:02:34 -04:00
|
|
|
MetaWaylandCompositor *compositor;
|
2014-08-18 16:54:15 -04:00
|
|
|
GSource *wayland_event_source;
|
2021-04-16 14:34:29 -04:00
|
|
|
MetaX11DisplayPolicy x11_display_policy;
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2021-05-06 10:02:34 -04:00
|
|
|
compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL);
|
|
|
|
compositor->context = context;
|
|
|
|
|
2014-07-10 11:05:59 -04:00
|
|
|
wayland_event_source = wayland_event_source_new (compositor->wayland_display);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
|
|
|
/* XXX: Here we are setting the wayland event source to have a
|
|
|
|
* slightly lower priority than the X event source, because we are
|
|
|
|
* much more likely to get confused being told about surface changes
|
|
|
|
* relating to X clients when we don't know what's happened to them
|
|
|
|
* according to the X protocol.
|
2014-10-07 23:51:28 -04:00
|
|
|
*/
|
2014-07-10 11:05:59 -04:00
|
|
|
g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1);
|
|
|
|
g_source_attach (wayland_event_source, NULL);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2020-06-03 05:38:32 -04:00
|
|
|
g_signal_connect (stage, "after-update",
|
|
|
|
G_CALLBACK (on_after_update), compositor);
|
2020-10-08 08:34:28 -04:00
|
|
|
g_signal_connect (stage, "presented",
|
|
|
|
G_CALLBACK (on_presented), compositor);
|
2020-06-03 05:38:32 -04:00
|
|
|
|
2014-10-07 23:54:28 -04:00
|
|
|
if (!wl_global_create (compositor->wayland_display,
|
|
|
|
&wl_compositor_interface,
|
|
|
|
META_WL_COMPOSITOR_VERSION,
|
|
|
|
compositor, compositor_bind))
|
|
|
|
g_error ("Failed to register the global wl_compositor");
|
|
|
|
|
2021-05-06 06:12:34 -04:00
|
|
|
meta_wayland_init_egl (compositor);
|
2019-09-18 10:18:58 -04:00
|
|
|
meta_wayland_init_shm (compositor);
|
2014-08-19 18:27:21 -04:00
|
|
|
|
2014-04-22 18:05:44 -04:00
|
|
|
meta_wayland_outputs_init (compositor);
|
|
|
|
meta_wayland_data_device_manager_init (compositor);
|
2020-05-13 12:07:27 -04:00
|
|
|
meta_wayland_data_device_primary_manager_init (compositor);
|
2020-05-13 12:04:04 -04:00
|
|
|
meta_wayland_data_device_primary_legacy_manager_init (compositor);
|
2017-12-20 04:40:22 -05:00
|
|
|
meta_wayland_subsurfaces_init (compositor);
|
2014-04-22 18:05:44 -04:00
|
|
|
meta_wayland_shell_init (compositor);
|
2015-07-22 10:50:20 -04:00
|
|
|
meta_wayland_pointer_gestures_init (compositor);
|
2015-01-09 11:28:42 -05:00
|
|
|
meta_wayland_tablet_manager_init (compositor);
|
2014-04-22 18:05:44 -04:00
|
|
|
meta_wayland_seat_init (compositor);
|
2015-06-02 04:26:34 -04:00
|
|
|
meta_wayland_relative_pointer_init (compositor);
|
2015-06-17 00:10:52 -04:00
|
|
|
meta_wayland_pointer_constraints_init (compositor);
|
2015-09-23 20:05:25 -04:00
|
|
|
meta_wayland_xdg_foreign_init (compositor);
|
2017-07-11 11:03:26 -04:00
|
|
|
meta_wayland_dma_buf_init (compositor);
|
2017-03-21 06:47:16 -04:00
|
|
|
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
|
2017-06-14 05:27:14 -04:00
|
|
|
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
|
2018-08-13 12:59:02 -04:00
|
|
|
meta_wayland_text_input_init (compositor);
|
2018-08-13 12:03:49 -04:00
|
|
|
meta_wayland_gtk_text_input_init (compositor);
|
2020-10-07 05:02:41 -04:00
|
|
|
meta_wayland_init_presentation_time (compositor);
|
2020-10-09 10:23:32 -04:00
|
|
|
meta_wayland_activation_init (compositor);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2016-08-30 03:20:49 -04:00
|
|
|
/* Xwayland specific protocol, needs to be filtered out for all other clients */
|
|
|
|
if (meta_xwayland_grab_keyboard_init (compositor))
|
|
|
|
wl_display_set_global_filter (compositor->wayland_display,
|
|
|
|
meta_xwayland_global_filter,
|
|
|
|
compositor);
|
|
|
|
|
2018-11-06 11:09:03 -05:00
|
|
|
#ifdef HAVE_WAYLAND_EGLSTREAM
|
2021-10-14 12:36:43 -04:00
|
|
|
{
|
|
|
|
gboolean should_enable_eglstream_controller = TRUE;
|
|
|
|
#if defined(HAVE_EGL_DEVICE) && defined(HAVE_NATIVE_BACKEND)
|
|
|
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
|
|
|
|
|
|
if (META_IS_RENDERER_NATIVE (renderer))
|
|
|
|
{
|
|
|
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
|
|
|
|
|
|
|
if (meta_renderer_native_get_mode (renderer_native) ==
|
|
|
|
META_RENDERER_NATIVE_MODE_GBM)
|
|
|
|
should_enable_eglstream_controller = FALSE;
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_EGL_DEVICE) && defined(HAVE_NATIVE_BACKEND) */
|
|
|
|
|
|
|
|
if (should_enable_eglstream_controller)
|
|
|
|
meta_wayland_eglstream_controller_init (compositor);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_WAYLAND_EGLSTREAM */
|
2017-06-27 19:37:30 -04:00
|
|
|
|
2021-04-16 14:34:29 -04:00
|
|
|
x11_display_policy =
|
|
|
|
meta_context_get_x11_display_policy (compositor->context);
|
|
|
|
if (x11_display_policy != META_X11_DISPLAY_POLICY_DISABLED)
|
2017-08-27 14:44:58 -04:00
|
|
|
{
|
2020-12-08 11:42:05 -05:00
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
if (!meta_xwayland_init (&compositor->xwayland_manager,
|
2021-05-06 12:49:25 -04:00
|
|
|
compositor,
|
2020-12-08 11:42:05 -05:00
|
|
|
compositor->wayland_display,
|
|
|
|
&error))
|
|
|
|
g_error ("Failed to start X Wayland: %s", error->message);
|
2017-08-27 14:44:58 -04:00
|
|
|
}
|
2015-07-02 04:41:37 -04:00
|
|
|
|
2016-12-05 08:23:46 -05:00
|
|
|
if (_display_name_override)
|
|
|
|
{
|
2017-08-18 02:18:14 -04:00
|
|
|
compositor->display_name = g_steal_pointer (&_display_name_override);
|
2016-12-05 08:23:46 -05:00
|
|
|
|
|
|
|
if (wl_display_add_socket (compositor->wayland_display,
|
2017-08-18 02:18:14 -04:00
|
|
|
compositor->display_name) != 0)
|
2016-12-05 08:23:46 -05:00
|
|
|
g_error ("Failed to create_socket");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-04 00:32:53 -04:00
|
|
|
const char *display_name;
|
|
|
|
|
|
|
|
display_name = wl_display_add_socket_auto (compositor->wayland_display);
|
|
|
|
if (!display_name)
|
2016-12-05 08:23:46 -05:00
|
|
|
g_error ("Failed to create socket");
|
2017-09-04 00:32:53 -04:00
|
|
|
|
|
|
|
compositor->display_name = g_strdup (display_name);
|
2016-12-05 08:23:46 -05:00
|
|
|
}
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2020-10-20 15:38:05 -04:00
|
|
|
g_message ("Using Wayland display name '%s'", compositor->display_name);
|
|
|
|
|
2021-04-16 14:34:29 -04:00
|
|
|
if (x11_display_policy != META_X11_DISPLAY_POLICY_DISABLED)
|
2019-06-18 10:12:46 -04:00
|
|
|
{
|
2019-11-14 17:51:45 -05:00
|
|
|
set_gnome_env ("GNOME_SETUP_DISPLAY", compositor->xwayland_manager.private_connection.name);
|
2019-07-19 16:50:31 -04:00
|
|
|
set_gnome_env ("DISPLAY", compositor->xwayland_manager.public_connection.name);
|
2019-06-18 10:12:46 -04:00
|
|
|
set_gnome_env ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor));
|
|
|
|
}
|
2017-08-27 14:44:58 -04:00
|
|
|
|
2014-09-11 10:07:34 -04:00
|
|
|
set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor));
|
2021-05-06 10:02:34 -04:00
|
|
|
|
|
|
|
return compositor;
|
2014-09-11 10:07:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
return compositor->display_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2021-01-21 12:56:18 -05:00
|
|
|
meta_wayland_get_public_xwayland_display_name (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
return compositor->xwayland_manager.public_connection.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
meta_wayland_get_private_xwayland_display_name (MetaWaylandCompositor *compositor)
|
2014-09-11 10:07:34 -04:00
|
|
|
{
|
2019-07-19 16:50:31 -04:00
|
|
|
return compositor->xwayland_manager.private_connection.name;
|
2012-01-07 17:21:32 -05:00
|
|
|
}
|
|
|
|
|
2017-03-17 08:34:52 -04:00
|
|
|
void
|
|
|
|
meta_wayland_compositor_restore_shortcuts (MetaWaylandCompositor *compositor,
|
|
|
|
ClutterInputDevice *source)
|
|
|
|
{
|
|
|
|
MetaWaylandKeyboard *keyboard;
|
|
|
|
|
|
|
|
/* Clutter is not multi-seat aware yet, use the default seat instead */
|
|
|
|
keyboard = compositor->seat->keyboard;
|
|
|
|
if (!keyboard || !keyboard->focus_surface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface,
|
|
|
|
compositor->seat))
|
|
|
|
return;
|
|
|
|
|
|
|
|
meta_wayland_surface_restore_shortcuts (keyboard->focus_surface,
|
|
|
|
compositor->seat);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_compositor_is_shortcuts_inhibited (MetaWaylandCompositor *compositor,
|
|
|
|
ClutterInputDevice *source)
|
|
|
|
{
|
|
|
|
MetaWaylandKeyboard *keyboard;
|
|
|
|
|
|
|
|
/* Clutter is not multi-seat aware yet, use the default seat instead */
|
|
|
|
keyboard = compositor->seat->keyboard;
|
|
|
|
if (keyboard && keyboard->focus_surface != NULL)
|
|
|
|
return meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface,
|
|
|
|
compositor->seat);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-08-18 02:16:22 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor)
|
|
|
|
{
|
|
|
|
wl_display_flush_clients (compositor->wayland_display);
|
|
|
|
}
|
2018-04-06 09:47:50 -04:00
|
|
|
|
|
|
|
static void on_scheduled_association_unmanaged (MetaWindow *window,
|
|
|
|
gpointer user_data);
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_wayland_compositor_remove_surface_association (MetaWaylandCompositor *compositor,
|
|
|
|
int id)
|
|
|
|
{
|
|
|
|
MetaWindow *window;
|
|
|
|
|
|
|
|
window = g_hash_table_lookup (compositor->scheduled_surface_associations,
|
|
|
|
GINT_TO_POINTER (id));
|
|
|
|
if (window)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_func (window,
|
|
|
|
on_scheduled_association_unmanaged,
|
|
|
|
GINT_TO_POINTER (id));
|
|
|
|
g_hash_table_remove (compositor->scheduled_surface_associations,
|
|
|
|
GINT_TO_POINTER (id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_scheduled_association_unmanaged (MetaWindow *window,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
|
|
|
|
|
|
meta_wayland_compositor_remove_surface_association (compositor,
|
|
|
|
GPOINTER_TO_INT (user_data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_schedule_surface_association (MetaWaylandCompositor *compositor,
|
|
|
|
int id,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
g_signal_connect (window, "unmanaged",
|
|
|
|
G_CALLBACK (on_scheduled_association_unmanaged),
|
|
|
|
GINT_TO_POINTER (id));
|
|
|
|
g_hash_table_insert (compositor->scheduled_surface_associations,
|
|
|
|
GINT_TO_POINTER (id), window);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_compositor_notify_surface_id (MetaWaylandCompositor *compositor,
|
|
|
|
int id,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWindow *window;
|
|
|
|
|
|
|
|
window = g_hash_table_lookup (compositor->scheduled_surface_associations,
|
|
|
|
GINT_TO_POINTER (id));
|
|
|
|
if (window)
|
|
|
|
{
|
|
|
|
meta_xwayland_associate_window_with_surface (window, surface);
|
|
|
|
meta_wayland_compositor_remove_surface_association (compositor, id);
|
|
|
|
}
|
|
|
|
}
|