wayland: Add an actor for the cursor
When running Mutter under Cogl's KMS backend no cursor will be provided so instead this makes it so the cursor will be painted as a CoglTexture that gets moved in response to mouse motion events. The painting is done in a subclass of ClutterStage so that we can guarantee that the cursor will be painted on top of everything else. This patch adds support for the set_cursor method on the pointer interface so that clients can change the cursor image. The set_pointer method sets a surface and a hotspot position to use for the cursor image. The surface's buffer is converted to a CoglTexture and attached to a pipeline to paint directly via Cogl. If a new buffer is attached to the surface the image will be updated. The cursor reverts back to the default image whenever to the pointer focus is moved off of any surface. The image for the pointer is taken from X. It gets installed into a fixed data location for mutter.
This commit is contained in:
parent
268ebb1b18
commit
a5585327dc
@ -1,5 +1,5 @@
|
||||
|
||||
SUBDIRS=src protocol po doc
|
||||
SUBDIRS=src protocol data po doc
|
||||
|
||||
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||
|
||||
|
@ -495,6 +495,7 @@ src/mutter-plugins.pc
|
||||
src/tools/Makefile
|
||||
src/compositor/plugins/Makefile
|
||||
protocol/Makefile
|
||||
data/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
7
data/Makefile.am
Normal file
7
data/Makefile.am
Normal file
@ -0,0 +1,7 @@
|
||||
defaultcursordir = $(datadir)/mutter/cursors
|
||||
|
||||
dist_defaultcursor_DATA =
|
||||
|
||||
if HAVE_WAYLAND
|
||||
dist_defaultcursor_DATA += left_ptr.png
|
||||
endif
|
BIN
data/left_ptr.png
Normal file
BIN
data/left_ptr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 736 B |
@ -187,7 +187,9 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-pointer.c \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-stage.h \
|
||||
wayland/meta-wayland-stage.c
|
||||
endif
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/wayland/clutter-wayland-compositor.h>
|
||||
#include <clutter/wayland/clutter-wayland-surface.h>
|
||||
@ -34,6 +35,7 @@
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta/meta-shaped-texture.h"
|
||||
#include "meta-wayland-stage.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
||||
|
||||
@ -71,23 +73,40 @@ transform_stage_point_fixed (MetaWaylandSurface *surface,
|
||||
static void
|
||||
pointer_unmap_sprite (MetaWaylandSeat *seat)
|
||||
{
|
||||
if (seat->current_stage)
|
||||
{
|
||||
MetaWaylandStage *stage = META_WAYLAND_STAGE (seat->current_stage);
|
||||
meta_wayland_stage_set_invisible_cursor (stage);
|
||||
}
|
||||
|
||||
if (seat->sprite)
|
||||
{
|
||||
if (seat->sprite->window)
|
||||
{
|
||||
GObject *window_actor_object =
|
||||
meta_window_get_compositor_private (seat->sprite->window);
|
||||
ClutterActor *window_actor = CLUTTER_ACTOR (window_actor_object);
|
||||
|
||||
if (window_actor)
|
||||
clutter_actor_hide (window_actor);
|
||||
}
|
||||
|
||||
wl_list_remove (&seat->sprite_destroy_listener.link);
|
||||
seat->sprite = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_seat_update_sprite (MetaWaylandSeat *seat)
|
||||
{
|
||||
if (seat->current_stage)
|
||||
{
|
||||
MetaWaylandStage *stage = META_WAYLAND_STAGE (seat->current_stage);
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *context = clutter_backend_get_cogl_context (backend);
|
||||
struct wl_resource *buffer = seat->sprite->buffer_ref.buffer->resource;
|
||||
CoglTexture2D *texture =
|
||||
cogl_wayland_texture_2d_new_from_buffer (context, buffer, NULL);
|
||||
|
||||
meta_wayland_stage_set_cursor_from_texture (stage,
|
||||
COGL_TEXTURE (texture),
|
||||
seat->hotspot_x,
|
||||
seat->hotspot_y);
|
||||
|
||||
cogl_object_unref (texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_set_cursor (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -109,17 +128,24 @@ pointer_set_cursor (struct wl_client *client,
|
||||
if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2)
|
||||
return;
|
||||
|
||||
pointer_unmap_sprite (seat);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
wl_resource_add_destroy_listener (surface->resource,
|
||||
&seat->sprite_destroy_listener);
|
||||
|
||||
seat->sprite = surface;
|
||||
seat->hotspot_x = x;
|
||||
seat->hotspot_y = y;
|
||||
|
||||
if (seat->sprite != surface)
|
||||
{
|
||||
pointer_unmap_sprite (seat);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
wl_resource_add_destroy_listener (surface->resource,
|
||||
&seat->sprite_destroy_listener);
|
||||
|
||||
seat->sprite = surface;
|
||||
|
||||
if (seat->sprite->buffer_ref.buffer)
|
||||
meta_wayland_seat_update_sprite (seat);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_pointer_interface
|
||||
@ -228,7 +254,7 @@ pointer_handle_sprite_destroy (struct wl_listener *listener, void *data)
|
||||
MetaWaylandSeat *seat =
|
||||
wl_container_of (listener, seat, sprite_destroy_listener);
|
||||
|
||||
seat->sprite = NULL;
|
||||
pointer_unmap_sprite (seat);
|
||||
}
|
||||
|
||||
MetaWaylandSeat *
|
||||
|
@ -41,6 +41,9 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
uint32_t time,
|
||||
ClutterActor *actor);
|
||||
|
||||
void
|
||||
meta_wayland_seat_update_sprite (MetaWaylandSeat *seat);
|
||||
|
||||
void
|
||||
meta_wayland_seat_free (MetaWaylandSeat *seat);
|
||||
|
||||
|
243
src/wayland/meta-wayland-stage.c
Normal file
243
src/wayland/meta-wayland-stage.c
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
|
||||
#include "meta-wayland-stage.h"
|
||||
#include "meta/meta-window-actor.h"
|
||||
#include "meta/meta-shaped-texture.h"
|
||||
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandStage, meta_wayland_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
meta_wayland_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandStage *self = (MetaWaylandStage *) object;
|
||||
|
||||
cogl_object_unref (self->default_cursor_pipeline);
|
||||
cogl_object_unref (self->texture_cursor_pipeline);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_stage_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
get_cursor_draw_position (MetaWaylandStage *self,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
rect->x = self->cursor_x - self->cursor_hotspot_x;
|
||||
rect->y = self->cursor_y - self->cursor_hotspot_y;
|
||||
rect->width = self->cursor_width;
|
||||
rect->height = self->cursor_height;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_cursor_pipeline (MetaWaylandStage *self,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
get_cursor_draw_position (self, &rect);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
pipeline,
|
||||
rect.x, rect.y,
|
||||
rect.x + rect.width,
|
||||
rect.y + rect.height);
|
||||
|
||||
self->has_last_cursor_position = TRUE;
|
||||
self->last_cursor_position = rect;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaWaylandStage *self = META_WAYLAND_STAGE (actor);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_wayland_stage_parent_class)->paint (actor);
|
||||
|
||||
/* Make sure the cursor is always painted on top of all of the other
|
||||
actors */
|
||||
|
||||
switch (self->cursor_type)
|
||||
{
|
||||
case META_WAYLAND_STAGE_CURSOR_INVISIBLE:
|
||||
break;
|
||||
|
||||
case META_WAYLAND_STAGE_CURSOR_DEFAULT:
|
||||
draw_cursor_pipeline (self, self->default_cursor_pipeline);
|
||||
break;
|
||||
|
||||
case META_WAYLAND_STAGE_CURSOR_TEXTURE:
|
||||
draw_cursor_pipeline (self, self->texture_cursor_pipeline);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor_position (MetaWaylandStage *self)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (self->has_last_cursor_position)
|
||||
{
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self),
|
||||
&self->last_cursor_position);
|
||||
self->has_last_cursor_position = FALSE;
|
||||
}
|
||||
|
||||
get_cursor_draw_position (self, &rect);
|
||||
if (rect.width != 0 && rect.height != 0)
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self), &rect);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_stage_class_init (MetaWaylandStageClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
gobject_class->finalize = meta_wayland_stage_finalize;
|
||||
|
||||
actor_class->paint = meta_wayland_stage_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
load_default_cursor_pipeline (MetaWaylandStage *self)
|
||||
{
|
||||
CoglContext *context =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglTexture *texture;
|
||||
CoglError *error = NULL;
|
||||
char *filename;
|
||||
|
||||
filename = g_build_filename (MUTTER_DATADIR,
|
||||
"mutter/cursors/left_ptr.png",
|
||||
NULL);
|
||||
|
||||
texture = cogl_texture_new_from_file (filename,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&error);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
self->default_cursor_pipeline = cogl_pipeline_new (context);
|
||||
cogl_pipeline_set_layer_filters (self->default_cursor_pipeline,
|
||||
0, /* layer */
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
g_warning ("Failed to load default cursor: %s",
|
||||
error->message);
|
||||
cogl_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->default_cursor_width = cogl_texture_get_width (texture);
|
||||
self->default_cursor_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->default_cursor_pipeline,
|
||||
0, /* layer */
|
||||
texture);
|
||||
cogl_object_unref (texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_stage_init (MetaWaylandStage *self)
|
||||
{
|
||||
load_default_cursor_pipeline (self);
|
||||
|
||||
self->texture_cursor_pipeline =
|
||||
cogl_pipeline_copy (self->default_cursor_pipeline);
|
||||
|
||||
meta_wayland_stage_set_default_cursor (self);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_wayland_stage_new (void)
|
||||
{
|
||||
return g_object_new (META_WAYLAND_TYPE_STAGE,
|
||||
"cursor-visible", FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_stage_set_cursor_position (MetaWaylandStage *self,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
self->cursor_x = x;
|
||||
self->cursor_y = y;
|
||||
update_cursor_position (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_stage_set_cursor_from_texture (MetaWaylandStage *self,
|
||||
CoglTexture *texture,
|
||||
int hotspot_x,
|
||||
int hotspot_y)
|
||||
{
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
self->cursor_hotspot_x = hotspot_x;
|
||||
self->cursor_hotspot_y = hotspot_y;
|
||||
self->cursor_type = META_WAYLAND_STAGE_CURSOR_TEXTURE;
|
||||
|
||||
pipeline = cogl_pipeline_copy (self->texture_cursor_pipeline);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, texture);
|
||||
cogl_object_unref (self->texture_cursor_pipeline);
|
||||
self->texture_cursor_pipeline = pipeline;
|
||||
|
||||
self->cursor_width = cogl_texture_get_width (texture);
|
||||
self->cursor_height = cogl_texture_get_height (texture);
|
||||
|
||||
update_cursor_position (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_stage_set_invisible_cursor (MetaWaylandStage *self)
|
||||
{
|
||||
self->cursor_type = META_WAYLAND_STAGE_CURSOR_INVISIBLE;
|
||||
self->cursor_width = 0;
|
||||
self->cursor_height = 0;
|
||||
update_cursor_position (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_stage_set_default_cursor (MetaWaylandStage *self)
|
||||
{
|
||||
self->cursor_type = META_WAYLAND_STAGE_CURSOR_DEFAULT;
|
||||
self->cursor_hotspot_x = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X;
|
||||
self->cursor_hotspot_y = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y;
|
||||
self->cursor_width = self->default_cursor_width;
|
||||
self->cursor_height = self->default_cursor_height;
|
||||
update_cursor_position (self);
|
||||
}
|
111
src/wayland/meta-wayland-stage.h
Normal file
111
src/wayland/meta-wayland-stage.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_STAGE_H
|
||||
#define META_WAYLAND_STAGE_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "window-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_WAYLAND_TYPE_STAGE \
|
||||
(meta_wayland_stage_get_type())
|
||||
#define META_WAYLAND_STAGE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
META_WAYLAND_TYPE_STAGE, \
|
||||
MetaWaylandStage))
|
||||
#define META_WAYLAND_STAGE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
META_WAYLAND_TYPE_STAGE, \
|
||||
MetaWaylandStageClass))
|
||||
#define META_WAYLAND_IS_STAGE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
META_WAYLAND_TYPE_STAGE))
|
||||
#define META_WAYLAND_IS_STAGE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
META_WAYLAND_TYPE_STAGE))
|
||||
#define META_WAYLAND_STAGE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
META_WAYLAND_STAGE, \
|
||||
MetaWaylandStageClass))
|
||||
|
||||
typedef struct _MetaWaylandStage MetaWaylandStage;
|
||||
typedef struct _MetaWaylandStageClass MetaWaylandStageClass;
|
||||
|
||||
struct _MetaWaylandStageClass
|
||||
{
|
||||
ClutterStageClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaWaylandStage
|
||||
{
|
||||
ClutterStage parent;
|
||||
|
||||
/* A pipeline containing the cursor texture that will be used when
|
||||
the cursor is not over a surface */
|
||||
CoglPipeline *default_cursor_pipeline;
|
||||
int default_cursor_width;
|
||||
int default_cursor_height;
|
||||
|
||||
CoglPipeline *texture_cursor_pipeline;
|
||||
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int cursor_width;
|
||||
int cursor_height;
|
||||
int cursor_hotspot_x;
|
||||
int cursor_hotspot_y;
|
||||
|
||||
enum
|
||||
{
|
||||
/* No cursor will be drawn */
|
||||
META_WAYLAND_STAGE_CURSOR_INVISIBLE,
|
||||
/* The cursor will be drawn from our default cursor image */
|
||||
META_WAYLAND_STAGE_CURSOR_DEFAULT,
|
||||
/* The cursor will be drawn using a custom texture */
|
||||
META_WAYLAND_STAGE_CURSOR_TEXTURE
|
||||
} cursor_type;
|
||||
|
||||
gboolean has_last_cursor_position;
|
||||
cairo_rectangle_int_t last_cursor_position;
|
||||
};
|
||||
|
||||
GType meta_wayland_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_wayland_stage_new (void);
|
||||
|
||||
void meta_wayland_stage_set_cursor_position (MetaWaylandStage *stage,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_wayland_stage_set_default_cursor (MetaWaylandStage *self);
|
||||
|
||||
void meta_wayland_stage_set_cursor_from_texture (MetaWaylandStage *self,
|
||||
CoglTexture *texture,
|
||||
int hotspot_x,
|
||||
int hotspot_y);
|
||||
|
||||
void meta_wayland_stage_set_invisible_cursor (MetaWaylandStage *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_WAYLAND_STAGE_H */
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-wayland-stage.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
@ -368,6 +369,8 @@ meta_wayland_surface_commit (struct wl_client *client,
|
||||
(buffer->width != rect.width || buffer->height != rect.height))
|
||||
meta_window_resize (surface->window, FALSE, buffer->width, buffer->height);
|
||||
}
|
||||
else if (surface == compositor->seat->sprite)
|
||||
meta_wayland_seat_update_sprite (compositor->seat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,6 +1203,13 @@ event_cb (ClutterActor *stage,
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_stage_set_cursor_position (META_WAYLAND_STAGE (stage),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
|
||||
if (pointer->current == NULL)
|
||||
meta_wayland_stage_set_default_cursor (META_WAYLAND_STAGE (stage));
|
||||
|
||||
display = meta_get_display ();
|
||||
if (!display)
|
||||
return FALSE;
|
||||
@ -1326,7 +1336,7 @@ meta_wayland_init (void)
|
||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||
g_error ("Failed to initialize Clutter");
|
||||
|
||||
compositor->stage = clutter_stage_new ();
|
||||
compositor->stage = meta_wayland_stage_new ();
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (compositor->stage), FALSE);
|
||||
g_signal_connect_after (compositor->stage, "paint",
|
||||
G_CALLBACK (paint_finished_cb), compositor);
|
||||
|
Loading…
Reference in New Issue
Block a user