Compare commits

...

18 Commits

Author SHA1 Message Date
Rui Matos
b9d798c213 cursor-tracker: Properly handle invisible cursors
We might be asked to not display the cursor ourselves but we should
still emit cursor-changed signals and hand out the correct sprite and
hot point information when asked so that consumers can still draw an
updated cursor themselves.

This fixes the cursor not showing up in gnome-shell's zoom mode.
2014-04-07 19:23:35 +02:00
Rui Matos
5abf41ab5a split cursor_tracker 2014-04-07 19:20:14 +02:00
Jasper St. Pierre
4f609dbf5e xwayland: Don't use glib after forking
glib doesn't have any guarantee about working after forking.
We can get away with it, but we're better off just not using it.
2014-04-02 13:04:31 -04:00
Jasper St. Pierre
2a7d12ba14 xwayland: Make failing to exec a fatal error 2014-04-02 13:03:29 -04:00
Jasper St. Pierre
c4c0b5f0ab xwayland: Detect a fail to fork 2014-04-02 13:03:17 -04:00
Jasper St. Pierre
8373c90cd8 background: Remove load_still_frame
Nothing uses it, and it's incompatible with XWayland anyway.
2014-04-02 12:35:24 -04:00
Jasper St. Pierre
eb5b54dd8b xwayland: Split another part of the initialization sequence out
This will be used from a SIGUSR1 handler.
2014-04-02 11:41:28 -04:00
Jasper St. Pierre
9653b79a35 xwayland: Split a helper out
This will make the next commit, which ports to the new ClientMessage
API, more understandable.
2014-04-02 11:41:28 -04:00
Jasper St. Pierre
e07bd15fc2 xwayland: Make file cosmetically modern
Put a modeline, include "config.h", and shift around the include ordering
2014-04-02 11:41:27 -04:00
Jasper St. Pierre
5cf0740b4e xwayland: Fork the X server ourselves
gspawn just isn't us the fine-grained control we need for starting
processes and leaking file descriptors in.
2014-04-02 11:41:27 -04:00
Jasper St. Pierre
c540ddf59b xwayland: Move display_name into choose_xdisplay 2014-04-02 11:41:27 -04:00
Jasper St. Pierre
a44295599c xwayland: Split out the code that creates the XWayland sockets 2014-04-02 11:41:26 -04:00
Jasper St. Pierre
af272f2685 xwayland: Move global initialization down 2014-04-02 11:41:26 -04:00
Jasper St. Pierre
81d033ec73 xwayland: Use %m instead of manual strerror(errno) 2014-04-02 11:41:26 -04:00
Jasper St. Pierre
e9ee984921 wayland: Rename the wl_surface interface handlers
We usually name the method handlers after the direct name
of the interface methods. Do that for wl_surface as well.
2014-04-02 11:41:26 -04:00
Jasper St. Pierre
3c404c5db3 wayland: Replace make_toplevel / window_unmanaging with set_window
The make_toplevel / window_unmanaging interface has never made
a lot of sense to me. Replace it with set_window, which does
effectively the same thing.

It's still not perfect in the case of XWayland, but I don't think
XWayland will ever make me happy.
2014-04-02 11:41:07 -04:00
Jasper St. Pierre
e4cd000cef wayland: Implement wl_seat v3
The new XWayland DDX flat out requires seat v3.
2014-04-02 11:40:40 -04:00
Jasper St. Pierre
6296fefea6 window-actor: Clean up has_shadow
This has some particularly picky #if 0'd code. Since the history for
it isn't illuminating in the slightest, I'm just going to kill it.
2014-04-02 11:40:04 -04:00
24 changed files with 1205 additions and 976 deletions

View File

@@ -70,12 +70,16 @@ libmutter_wayland_la_SOURCES = \
backends/meta-monitor-manager-dummy.h \ backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \ backends/edid-parse.c \
backends/edid.h \ backends/edid.h \
backends/native/meta-cursor-tracker-native.c \
backends/native/meta-cursor-tracker-native.h \
backends/native/meta-idle-monitor-native.c \ backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \ backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \ backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \ backends/native/meta-monitor-manager-kms.h \
backends/native/meta-weston-launch.c \ backends/native/meta-weston-launch.c \
backends/native/meta-weston-launch.h \ backends/native/meta-weston-launch.h \
backends/x11/meta-cursor-tracker-x11.c \
backends/x11/meta-cursor-tracker-x11.h \
backends/x11/meta-idle-monitor-xsync.c \ backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \ backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \ backends/x11/meta-monitor-manager-xrandr.c \

View File

@@ -27,6 +27,11 @@
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include <gbm.h> #include <gbm.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <wayland-server.h>
typedef struct { typedef struct {
CoglTexture2D *texture; CoglTexture2D *texture;
struct gbm_bo *bo; struct gbm_bo *bo;
@@ -47,4 +52,26 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x, int *hot_x,
int *hot_y); int *hot_y);
void meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t gbm_format);
void meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
struct wl_resource *buffer,
int width,
int height);
MetaCursorReference *meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image);
MetaCursorReference *meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image);
MetaCursorReference *meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif /* META_CURSOR_PRIVATE_H */ #endif /* META_CURSOR_PRIVATE_H */

View File

@@ -30,10 +30,7 @@
struct _MetaCursorTracker { struct _MetaCursorTracker {
GObject parent_instance; GObject parent_instance;
MetaScreen *screen;
gboolean is_showing; gboolean is_showing;
gboolean has_hw_cursor;
/* The cursor tracker stores the cursor for the current grab /* The cursor tracker stores the cursor for the current grab
* operation, the cursor for the window with pointer focus, and * operation, the cursor for the window with pointer focus, and
@@ -49,6 +46,12 @@ struct _MetaCursorTracker {
*/ */
MetaCursorReference *displayed_cursor; MetaCursorReference *displayed_cursor;
/* This is the cursor that would be displayed if we hadn't been
* asked to hide it. i.e. it's the same as displayed_cursor unless
* is_showing is false.
*/
MetaCursorReference *current_cursor;
MetaCursorReference *grab_cursor; MetaCursorReference *grab_cursor;
/* Wayland clients can set a NULL buffer as their cursor /* Wayland clients can set a NULL buffer as their cursor
@@ -62,23 +65,37 @@ struct _MetaCursorTracker {
MetaCursorReference *root_cursor; MetaCursorReference *root_cursor;
MetaCursorReference *theme_cursors[META_CURSOR_LAST]; MetaCursorReference *theme_cursors[META_CURSOR_LAST];
int current_x, current_y;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
int drm_fd;
struct gbm_device *gbm;
}; };
struct _MetaCursorTrackerClass { struct _MetaCursorTrackerClass {
GObjectClass parent_class; GObjectClass parent_class;
void (*get_pointer) (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods);
void (*sync_cursor) (MetaCursorTracker *tracker);
void (*ensure_cursor) (MetaCursorTracker *tracker);
void (*load_cursor_pixels) (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format);
void (*load_cursor_buffer) (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer);
}; };
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, void _meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
XEvent *xevent); gboolean has_cursor,
MetaCursorReference *cursor);
void _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker, void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor); MetaCursorReference *cursor);
@@ -87,12 +104,13 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker); void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor); MetaCursorReference *cursor);
MetaCursorReference *
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker, meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
int new_x, MetaCursor cursor);
int new_y); MetaCursorReference *
void meta_cursor_tracker_paint (MetaCursorTracker *tracker); meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker); int hot_x,
int hot_y);
#endif #endif

View File

@@ -33,20 +33,11 @@
#include <meta/util.h> #include <meta/util.h>
#include <meta/errors.h> #include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gbm.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "meta-cursor-private.h" #include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "backends/x11/meta-cursor-tracker-x11.h"
#include "screen-private.h" #include "screen-private.h"
#include "meta-monitor-manager.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
@@ -57,11 +48,6 @@ enum {
static guint signals[LAST_SIGNAL]; static guint signals[LAST_SIGNAL];
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has_hw_cursor);
static void sync_cursor (MetaCursorTracker *tracker);
static void static void
meta_cursor_tracker_init (MetaCursorTracker *self) meta_cursor_tracker_init (MetaCursorTracker *self)
{ {
@@ -88,14 +74,32 @@ meta_cursor_tracker_finalize (GObject *object)
if (self->theme_cursors[i]) if (self->theme_cursors[i])
meta_cursor_reference_unref (self->theme_cursors[i]); meta_cursor_reference_unref (self->theme_cursors[i]);
if (self->pipeline)
cogl_object_unref (self->pipeline);
if (self->gbm)
gbm_device_destroy (self->gbm);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object); G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
} }
static void
default_do_nothing (MetaCursorTracker *tracker)
{
}
static void
default_load_cursor_pixels (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format)
{
}
static void
default_load_cursor_buffer (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer)
{
}
static void static void
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass) meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
{ {
@@ -103,6 +107,11 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
object_class->finalize = meta_cursor_tracker_finalize; object_class->finalize = meta_cursor_tracker_finalize;
klass->sync_cursor = default_do_nothing;
klass->ensure_cursor = default_do_nothing;
klass->load_cursor_pixels = default_load_cursor_pixels;
klass->load_cursor_buffer = default_load_cursor_buffer;
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed", signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
@@ -111,81 +120,6 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
} }
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorTracker *tracker)
{
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
if (!tracker->has_hw_cursor)
return;
/* Go through the new list of monitors, find out where the cursor is */
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
/* Need to do it unconditionally here, our tracking is
wrong because we reloaded the CRTCs */
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static MetaCursorTracker *
make_wayland_cursor_tracker (MetaScreen *screen)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaMonitorManager *monitors;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = self;
meta_cursor_tracker_update_position (self,
wl_fixed_to_int (compositor->seat->pointer.x),
wl_fixed_to_int (compositor->seat->pointer.y));
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
self->gbm = gbm_create_device (self->drm_fd);
}
#endif
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), self, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
/** /**
* meta_cursor_tracker_get_for_screen: * meta_cursor_tracker_get_for_screen:
* @screen: the #MetaScreen * @screen: the #MetaScreen
@@ -203,127 +137,14 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
return screen->cursor_tracker; return screen->cursor_tracker;
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
self = make_wayland_cursor_tracker (screen); self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL);
else else
self = make_x11_cursor_tracker (screen); self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL);
screen->cursor_tracker = self; screen->cursor_tracker = self;
return self; return self;
} }
static void
set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->window_cursor = meta_cursor_reference_ref (cursor);
tracker->has_window_cursor = has_cursor;
sync_cursor (tracker);
}
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
set_window_cursor (tracker, FALSE, NULL);
return TRUE;
}
static MetaCursorReference *
meta_cursor_reference_take_texture (CoglTexture2D *texture,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->image.texture = texture;
self->image.hot_x = hot_x;
self->image.hot_y = hot_y;
return self;
}
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
gboolean free_cursor_data;
CoglContext *ctx;
if (tracker->has_window_cursor)
return;
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
* quantities as arrays of long; we need to convert on 64 bit */
if (sizeof(long) == 4)
{
cursor_data = (guint8 *)cursor_image->pixels;
free_cursor_data = FALSE;
}
else
{
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
cursor_data = (guint8 *)cursor_words;
p = cursor_image->pixels;
q = cursor_words;
for (j = 0; j < cursor_image->height; j++)
for (i = 0; i < cursor_image->width; i++)
*(q++) = *(p++);
free_cursor_data = TRUE;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
sprite = cogl_texture_2d_new_from_data (ctx,
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
if (free_cursor_data)
g_free (cursor_data);
if (sprite != NULL)
{
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
cursor_image->xhot,
cursor_image->yhot);
set_window_cursor (tracker, TRUE, cursor);
}
XFree (cursor_image);
}
/** /**
* meta_cursor_tracker_get_sprite: * meta_cursor_tracker_get_sprite:
* *
@@ -334,11 +155,10 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{ {
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL); g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (!meta_is_wayland_compositor ()) META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
ensure_xfixes_cursor (tracker);
if (tracker->displayed_cursor) if (tracker->current_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL); return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL);
else else
return NULL; return NULL;
} }
@@ -357,11 +177,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
{ {
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (!meta_is_wayland_compositor ()) META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
ensure_xfixes_cursor (tracker);
if (tracker->displayed_cursor) if (tracker->current_cursor)
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y); meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y);
else else
{ {
if (x) if (x)
@@ -371,6 +190,32 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
} }
} }
void
_meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->window_cursor = meta_cursor_reference_ref (cursor);
tracker->has_window_cursor = has_cursor;
_meta_cursor_tracker_sync_cursor (tracker);
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
}
void
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
{
_meta_cursor_tracker_set_window_cursor (tracker, FALSE, NULL);
}
void void
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker, meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor) MetaCursorReference *cursor)
@@ -379,20 +224,7 @@ meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
if (cursor) if (cursor)
tracker->grab_cursor = meta_cursor_reference_ref (cursor); tracker->grab_cursor = meta_cursor_reference_ref (cursor);
sync_cursor (tracker); _meta_cursor_tracker_sync_cursor (tracker);
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
set_window_cursor (tracker, TRUE, cursor);
}
void
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
{
set_window_cursor (tracker, FALSE, NULL);
} }
void void
@@ -403,78 +235,12 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
if (cursor) if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (cursor); tracker->root_cursor = meta_cursor_reference_ref (cursor);
sync_cursor (tracker); _meta_cursor_tracker_sync_cursor (tracker);
}
static gboolean
should_have_hw_cursor (MetaCursorTracker *tracker)
{
if (tracker->displayed_cursor)
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
else
return FALSE;
}
static void
update_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
gboolean enabled;
enabled = should_have_hw_cursor (tracker);
tracker->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = enabled && meta_rectangle_overlap (&tracker->current_rect, rect);
if (has || crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static void
move_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
g_assert (tracker->has_hw_cursor);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
if (has != crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
if (has)
drmModeMoveCursor (tracker->drm_fd, crtcs[i].crtc_id,
tracker->current_rect.x - rect->x,
tracker->current_rect.y - rect->y);
}
} }
static MetaCursorReference * static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker) get_current_cursor (MetaCursorTracker *tracker)
{ {
if (!tracker->is_showing)
return NULL;
if (tracker->grab_cursor) if (tracker->grab_cursor)
return tracker->grab_cursor; return tracker->grab_cursor;
@@ -484,208 +250,38 @@ get_displayed_cursor (MetaCursorTracker *tracker)
return tracker->root_cursor; return tracker->root_cursor;
} }
static void static MetaCursorReference *
update_displayed_cursor (MetaCursorTracker *tracker) get_displayed_cursor (MetaCursorTracker *tracker)
{ {
if (meta_is_wayland_compositor ()) if (!tracker->is_showing)
{ return NULL;
if (tracker->displayed_cursor)
{
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, texture);
}
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
update_hw_cursor (tracker); return get_current_cursor (tracker);
}
} }
static void void
sync_displayed_cursor (MetaCursorTracker *tracker) _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker)
{ {
MetaCursorReference *current_cursor = get_current_cursor (tracker);
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker); MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor) if (tracker->displayed_cursor != displayed_cursor)
return; {
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref); g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor) if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor); tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
update_displayed_cursor (tracker); META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker);
}
if (tracker->current_cursor != current_cursor)
{
g_clear_pointer (&tracker->current_cursor, meta_cursor_reference_unref);
if (current_cursor)
tracker->current_cursor = meta_cursor_reference_ref (current_cursor);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
} }
static void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
cairo_rectangle_int_t clip;
g_assert (meta_is_wayland_compositor ());
/* Clear the location the cursor was at before, if we need to. */
if (tracker->previous_is_valid)
{
clip.x = tracker->previous_rect.x;
clip.y = tracker->previous_rect.y;
clip.width = tracker->previous_rect.width;
clip.height = tracker->previous_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
tracker->previous_is_valid = FALSE;
}
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
clip.x = tracker->current_rect.x;
clip.y = tracker->current_rect.y;
clip.width = tracker->current_rect.width;
clip.height = tracker->current_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor;
sync_displayed_cursor (tracker);
displayed_cursor = tracker->displayed_cursor;
if (displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
tracker->current_rect.x = tracker->current_x - hot_x;
tracker->current_rect.y = tracker->current_y - hot_y;
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
tracker->current_rect.x = 0;
tracker->current_rect.y = 0;
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
if (meta_is_wayland_compositor ())
{
if (tracker->has_hw_cursor)
move_hw_cursor (tracker);
else
meta_cursor_tracker_queue_redraw (tracker);
}
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
tracker->current_x = new_x;
tracker->current_y = new_y;
sync_cursor (tracker);
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
static void
meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has)
{
if (has)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
crtc->has_hw_cursor = TRUE;
}
else
{
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->has_hw_cursor = FALSE;
}
}
static void
get_pointer_position_gdk (int *x,
int *y,
int *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
GdkScreen *gscreen;
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gdk_device_get_position (gdevice, &gscreen, x, y);
if (mods)
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
}
static void
get_pointer_position_clutter (int *x,
int *y,
int *mods)
{
ClutterDeviceManager *cmanager;
ClutterInputDevice *cdevice;
ClutterPoint point;
cmanager = clutter_device_manager_get_default ();
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
clutter_input_device_get_coords (cdevice, NULL, &point);
if (x)
*x = point.x;
if (y)
*y = point.y;
if (mods)
*mods = clutter_input_device_get_modifier_state (cdevice);
} }
void void
@@ -694,15 +290,7 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *y, int *y,
ClutterModifierType *mods) ClutterModifierType *mods)
{ {
/* We can't use the clutter interface when not running as a wayland compositor, META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods);
because we need to query the server, rather than using the last cached value.
OTOH, on wayland we can't use GDK, because that only sees the events
we forward to xwayland.
*/
if (meta_is_wayland_compositor ())
get_pointer_position_clutter (x, y, (int*)mods);
else
get_pointer_position_gdk (x, y, (int*)mods);
} }
void void
@@ -713,26 +301,51 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
return; return;
tracker->is_showing = visible; tracker->is_showing = visible;
if (meta_is_wayland_compositor ()) _meta_cursor_tracker_sync_cursor (tracker);
{
sync_cursor (tracker);
}
else
{
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
}
} }
void MetaCursorReference *
meta_cursor_tracker_force_update (MetaCursorTracker *tracker) meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
MetaCursor meta_cursor)
{ {
g_assert (meta_is_wayland_compositor ()); MetaCursorReference *cursor;
XcursorImage *xc_image;
update_hw_cursor (tracker); if (tracker->theme_cursors[meta_cursor])
sync_cursor (tracker); return meta_cursor_reference_ref (tracker->theme_cursors[meta_cursor]);
xc_image = meta_display_load_x_cursor (meta_get_display (), meta_cursor);
if (!xc_image)
return NULL;
cursor = meta_cursor_reference_from_xcursor_image (xc_image);
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_pixels (tracker,
cursor,
(uint8_t *) xc_image->pixels,
xc_image->width,
xc_image->height,
xc_image->width * 4,
GBM_FORMAT_ARGB8888);
XcursorImageDestroy (xc_image);
tracker->theme_cursors[meta_cursor] = cursor;
return meta_cursor_reference_ref (cursor);
}
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *cursor;
cursor = meta_cursor_reference_from_buffer (buffer, hot_x, hot_y);
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_buffer (tracker,
cursor,
buffer);
return cursor;
} }

View File

@@ -27,16 +27,23 @@
#include "display-private.h" #include "display-private.h"
#include "screen-private.h" #include "screen-private.h"
#include "meta-cursor-tracker-private.h" /* for tracker->gbm */ #include "meta-cursor-tracker-private.h"
#include <string.h> #include <string.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <cogl/cogl-wayland-server.h> #include <cogl/cogl-wayland-server.h>
static MetaCursorReference *
meta_cursor_reference_new (void)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
return self;
}
MetaCursorReference * MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self) meta_cursor_reference_ref (MetaCursorReference *self)
{ {
@@ -190,9 +197,16 @@ load_cursor_on_client (MetaDisplay *display,
return image; return image;
} }
static void XcursorImage *
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, meta_display_load_x_cursor (MetaDisplay *display,
MetaCursorImage *image, MetaCursor cursor)
{
return load_cursor_on_client (display, cursor);
}
void
meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
uint8_t *pixels, uint8_t *pixels,
int width, int width,
int height, int height,
@@ -211,144 +225,25 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
uint8_t buf[4 * 64 * 64]; uint8_t buf[4 * 64 * 64];
int i; int i;
image->bo = gbm_bo_create (gbm, 64, 64, cursor->image.bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4); memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (image->bo, buf, 64 * 64 * 4); gbm_bo_write (cursor->image.bo, buf, 64 * 64 * 4);
} }
else else
meta_warning ("HW cursor for format %d not supported\n", gbm_format); meta_warning ("HW cursor for format %d not supported\n", gbm_format);
} }
static void void
meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker, meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
MetaCursorImage *image, struct gbm_device *gbm,
XcursorImage *xc_image)
{
int width, height, rowstride;
CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
width = xc_image->width;
height = xc_image->height;
rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
image->hot_x = xc_image->xhot;
image->hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
image->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
if (tracker->gbm)
meta_cursor_image_load_gbm_buffer (tracker->gbm,
image,
(uint8_t *) xc_image->pixels,
width, height, rowstride,
gbm_format);
}
MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor)
{
MetaCursorReference *self;
XcursorImage *image;
if (tracker->theme_cursors[cursor])
return meta_cursor_reference_ref (tracker->theme_cursors[cursor]);
image = load_cursor_on_client (tracker->screen->display, cursor);
if (!image)
return NULL;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
XcursorImageDestroy (image);
return self;
}
static void
meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
MetaCursorImage *image,
struct wl_resource *buffer, struct wl_resource *buffer,
int hot_x, int width,
int hot_y) int height)
{
ClutterBackend *backend;
CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
int width, height;
image->hot_x = hot_x;
image->hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
if (tracker->gbm)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_image_load_gbm_buffer (tracker->gbm,
image,
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
width, height, rowstride,
gbm_format);
}
}
else
{ {
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the that, so themed cursors must be padded with transparent pixels to fill the
@@ -362,29 +257,122 @@ meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
return; return;
} }
if (tracker->gbm) cursor->image.bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
{
image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64); buffer, GBM_BO_USE_CURSOR_64X64);
if (!image->bo) if (!cursor->image.bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n"); meta_warning ("Importing HW cursor from wl_buffer failed\n");
} }
}
}
MetaCursorReference * MetaCursorReference *
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker, meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image)
struct wl_resource *buffer, {
MetaCursorReference *cursor;
CoglTexture2D *sprite;
CoglContext *ctx;
guint8 *cursor_data;
gboolean free_cursor_data;
cursor = meta_cursor_reference_new ();
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
* quantities as arrays of long; we need to convert on 64 bit */
if (sizeof(long) == 4)
{
cursor_data = (guint8 *)cursor_image->pixels;
free_cursor_data = FALSE;
}
else
{
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
cursor_data = (guint8 *)cursor_words;
p = cursor_image->pixels;
q = cursor_words;
for (j = 0; j < cursor_image->height; j++)
for (i = 0; i < cursor_image->width; i++)
*(q++) = *(p++);
free_cursor_data = TRUE;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
sprite = cogl_texture_2d_new_from_data (ctx,
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
if (free_cursor_data)
g_free (cursor_data);
cursor->image.texture = sprite;
cursor->image.hot_x = cursor_image->xhot;
cursor->image.hot_y = cursor_image->yhot;
return cursor;
}
MetaCursorReference *
meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image)
{
MetaCursorReference *cursor;
int width, height, rowstride;
CoglPixelFormat cogl_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
cursor = meta_cursor_reference_new ();
width = xc_image->width;
height = xc_image->height;
rowstride = width * 4;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
cursor->image.hot_x = xc_image->xhot;
cursor->image.hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
cursor->image.texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
return cursor;
}
MetaCursorReference *
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x, int hot_x,
int hot_y) int hot_y)
{ {
MetaCursorReference *self; MetaCursorReference *cursor;
ClutterBackend *backend;
CoglContext *cogl_context;
self = g_slice_new0 (MetaCursorReference); cursor = meta_cursor_reference_new ();
self->ref_count = 1;
meta_cursor_image_load_from_buffer (tracker, &self->image, buffer, hot_x, hot_y);
return self; cursor->image.hot_x = hot_x;
cursor->image.hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cursor->image.texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
return cursor;
} }
CoglTexture * CoglTexture *

View File

@@ -27,16 +27,4 @@ typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor); MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor); void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/meta-cursor-tracker.h>
#include <meta/common.h>
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor);
MetaCursorReference * meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif /* META_CURSOR_H */ #endif /* META_CURSOR_H */

View File

@@ -0,0 +1,443 @@
/*
* Copyright 2014 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gbm.h>
#include "display-private.h"
#include "meta-cursor-tracker-native.h"
#include "meta-cursor-tracker-private.h"
#include "meta-monitor-manager.h"
#include "meta-cursor-private.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorTrackerNative
{
MetaCursorTracker parent;
gboolean has_hw_cursor;
int current_x, current_y;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
int drm_fd;
struct gbm_device *gbm;
};
struct _MetaCursorTrackerNativeClass
{
MetaCursorTrackerClass parent_class;
};
G_DEFINE_TYPE (MetaCursorTrackerNative, meta_cursor_tracker_native, META_TYPE_CURSOR_TRACKER);
static void
meta_cursor_tracker_native_load_cursor_pixels (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
if (!self->gbm)
return;
meta_cursor_reference_load_gbm_buffer (cursor,
self->gbm,
pixels,
width, height, rowstride,
format);
}
static void
meta_cursor_tracker_native_load_cursor_buffer (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer)
{
struct wl_shm_buffer *shm_buffer;
int width, height;
width = cogl_texture_get_width (COGL_TEXTURE (cursor->image.texture));
height = cogl_texture_get_height (COGL_TEXTURE (cursor->image.texture));
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
uint32_t gbm_format;
uint8_t *pixels = wl_shm_buffer_get_data (shm_buffer);
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_tracker_native_load_cursor_pixels (tracker,
cursor,
pixels,
width,
height,
rowstride,
gbm_format);
}
else
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
if (!self->gbm)
return;
meta_cursor_reference_import_gbm_buffer (cursor, self->gbm, buffer, width, height);
}
}
static void
set_crtc_has_hw_cursor (MetaCursorTrackerNative *self,
MetaCRTC *crtc,
gboolean has)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (has)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
crtc->has_hw_cursor = TRUE;
}
else
{
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->has_hw_cursor = FALSE;
}
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorTrackerNative *self)
{
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
if (!self->has_hw_cursor)
return;
/* Go through the new list of monitors, find out where the cursor is */
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&self->current_rect, rect);
/* Need to do it unconditionally here, our tracking is
wrong because we reloaded the CRTCs */
set_crtc_has_hw_cursor (self, &crtcs[i], has);
}
}
static gboolean
should_have_hw_cursor (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (tracker->displayed_cursor)
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
else
return FALSE;
}
static void
update_hw_cursor (MetaCursorTrackerNative *self)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
gboolean enabled;
enabled = should_have_hw_cursor (self);
self->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = enabled && meta_rectangle_overlap (&self->current_rect, rect);
if (has || crtcs[i].has_hw_cursor)
set_crtc_has_hw_cursor (self, &crtcs[i], has);
}
}
static void
move_hw_cursor (MetaCursorTrackerNative *self)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
g_assert (self->has_hw_cursor);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&self->current_rect, rect);
if (has != crtcs[i].has_hw_cursor)
set_crtc_has_hw_cursor (self, &crtcs[i], has);
if (has)
drmModeMoveCursor (self->drm_fd, crtcs[i].crtc_id,
self->current_rect.x - rect->x,
self->current_rect.y - rect->y);
}
}
static void
queue_redraw (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
cairo_rectangle_int_t clip;
/* Clear the location the cursor was at before, if we need to. */
if (self->previous_is_valid)
{
clip.x = self->previous_rect.x;
clip.y = self->previous_rect.y;
clip.width = self->previous_rect.width;
clip.height = self->previous_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
self->previous_is_valid = FALSE;
}
if (self->has_hw_cursor || !tracker->displayed_cursor)
return;
clip.x = self->current_rect.x;
clip.y = self->current_rect.y;
clip.width = self->current_rect.width;
clip.height = self->current_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
meta_cursor_tracker_native_sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
MetaCursorReference *displayed_cursor;
displayed_cursor = tracker->displayed_cursor;
if (displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
self->current_rect.x = self->current_x - hot_x;
self->current_rect.y = self->current_y - hot_y;
self->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
self->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
cogl_pipeline_set_layer_texture (self->pipeline, 0, NULL);
self->current_rect.x = 0;
self->current_rect.y = 0;
self->current_rect.width = 0;
self->current_rect.height = 0;
}
update_hw_cursor (self);
if (self->has_hw_cursor)
move_hw_cursor (self);
else
queue_redraw (self);
}
static void
meta_cursor_tracker_native_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
ClutterDeviceManager *cmanager;
ClutterInputDevice *cdevice;
ClutterPoint point;
/* On wayland we can't use GDK, because that only sees the events we
* forward to xwayland.
*/
cmanager = clutter_device_manager_get_default ();
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
clutter_input_device_get_coords (cdevice, NULL, &point);
if (x)
*x = point.x;
if (y)
*y = point.y;
if (mods)
*mods = clutter_input_device_get_modifier_state (cdevice);
}
static void
meta_cursor_tracker_native_finalize (GObject *object)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (object);
if (self->pipeline)
cogl_object_unref (self->pipeline);
if (self->gbm)
gbm_device_destroy (self->gbm);
G_OBJECT_CLASS (meta_cursor_tracker_native_parent_class)->finalize (object);
}
static void
meta_cursor_tracker_native_class_init (MetaCursorTrackerNativeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
object_class->finalize = meta_cursor_tracker_native_finalize;
cursor_tracker_class->get_pointer = meta_cursor_tracker_native_get_pointer;
cursor_tracker_class->sync_cursor = meta_cursor_tracker_native_sync_cursor;
cursor_tracker_class->load_cursor_pixels = meta_cursor_tracker_native_load_cursor_pixels;
cursor_tracker_class->load_cursor_buffer = meta_cursor_tracker_native_load_cursor_buffer;
}
static void
meta_cursor_tracker_native_init (MetaCursorTrackerNative *self)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaMonitorManager *monitors;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = META_CURSOR_TRACKER (self);
meta_cursor_tracker_native_update_position (self,
wl_fixed_to_int (compositor->seat->pointer.x),
wl_fixed_to_int (compositor->seat->pointer.y));
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
self->gbm = gbm_create_device (self->drm_fd);
}
#endif
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), self, 0);
}
void
meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *self,
int new_x,
int new_y)
{
self->current_x = new_x;
self->current_y = new_y;
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
}
void
meta_cursor_tracker_native_paint (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (self->has_hw_cursor || !tracker->displayed_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
self->pipeline,
self->current_rect.x,
self->current_rect.y,
self->current_rect.x +
self->current_rect.width,
self->current_rect.y +
self->current_rect.height);
self->previous_rect = self->current_rect;
self->previous_is_valid = TRUE;
}
void
meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *self)
{
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2014 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CURSOR_TRACKER_NATIVE_H
#define META_CURSOR_TRACKER_NATIVE_H
#include <glib-object.h>
#include <meta/meta-cursor-tracker.h>
#define META_TYPE_CURSOR_TRACKER_NATIVE (meta_cursor_tracker_native_get_type ())
#define META_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNative))
#define META_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
#define META_IS_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_NATIVE))
#define META_IS_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_NATIVE))
#define META_CURSOR_TRACKER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
typedef struct _MetaCursorTrackerNative MetaCursorTrackerNative;
typedef struct _MetaCursorTrackerNativeClass MetaCursorTrackerNativeClass;
GType meta_cursor_tracker_native_get_type (void);
void meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_native_paint (MetaCursorTrackerNative *tracker);
void meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *tracker);
#endif /* META_CURSOR_TRACKER_NATIVE_H */

View File

@@ -44,6 +44,7 @@
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "meta-cursor-tracker-native.h"
#include "meta-weston-launch.h" #include "meta-weston-launch.h"
struct _MetaLauncher struct _MetaLauncher
@@ -219,7 +220,7 @@ meta_launcher_enter (MetaLauncher *launcher)
* update. */ * update. */
clutter_actor_queue_redraw (compositor->stage); clutter_actor_queue_redraw (compositor->stage);
meta_cursor_tracker_force_update (compositor->seat->cursor_tracker); meta_cursor_tracker_native_force_update (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
} }
} }

View File

@@ -0,0 +1,138 @@
/*
* Copyright 2014 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdkx.h>
#include <meta/errors.h>
#include "display-private.h"
#include "meta-cursor-tracker-x11.h"
#include "meta-cursor-tracker-private.h"
#include "meta-cursor-private.h"
struct _MetaCursorTrackerX11
{
MetaCursorTracker parent;
};
struct _MetaCursorTrackerX11Class
{
MetaCursorTrackerClass parent_class;
};
G_DEFINE_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, META_TYPE_CURSOR_TRACKER);
static void
meta_cursor_tracker_x11_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
GdkScreen *gscreen;
/* We can't use the clutter interface when not running as a wayland
* compositor, because we need to query the server, rather than
* using the last cached value.
*/
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gdk_device_get_position (gdevice, &gscreen, x, y);
if (mods)
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
}
static void
meta_cursor_tracker_x11_sync_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
meta_error_trap_push (display);
if (tracker->is_showing)
XFixesShowCursor (display->xdisplay,
DefaultRootWindow (display->xdisplay));
else
XFixesHideCursor (display->xdisplay,
DefaultRootWindow (display->xdisplay));
meta_error_trap_pop (display);
}
static void
meta_cursor_tracker_x11_ensure_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
MetaCursorReference *cursor;
if (tracker->has_window_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
if (!cursor_image)
return;
cursor = meta_cursor_reference_from_xfixes_cursor_image (cursor_image);
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
XFree (cursor_image);
}
static void
meta_cursor_tracker_x11_class_init (MetaCursorTrackerX11Class *klass)
{
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
cursor_tracker_class->get_pointer = meta_cursor_tracker_x11_get_pointer;
cursor_tracker_class->sync_cursor = meta_cursor_tracker_x11_sync_cursor;
cursor_tracker_class->ensure_cursor = meta_cursor_tracker_x11_ensure_cursor;
}
static void
meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *self)
{
MetaDisplay *display = meta_get_display ();
XFixesSelectCursorInput (display->xdisplay,
DefaultRootWindow (display->xdisplay),
XFixesDisplayCursorNotifyMask);
}
gboolean
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
_meta_cursor_tracker_set_window_cursor (META_CURSOR_TRACKER (tracker), FALSE, NULL);
return TRUE;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2014 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CURSOR_TRACKER_X11_H
#define META_CURSOR_TRACKER_X11_H
#include <glib-object.h>
#include <meta/meta-cursor-tracker.h>
#define META_TYPE_CURSOR_TRACKER_X11 (meta_cursor_tracker_x11_get_type ())
#define META_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11))
#define META_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
#define META_IS_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_X11))
#define META_IS_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_X11))
#define META_CURSOR_TRACKER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
typedef struct _MetaCursorTrackerX11 MetaCursorTrackerX11;
typedef struct _MetaCursorTrackerX11Class MetaCursorTrackerX11Class;
GType meta_cursor_tracker_x11_get_type (void);
gboolean
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
XEvent *xevent);
#endif /* META_CURSOR_TRACKER_X11_H */

View File

@@ -26,8 +26,6 @@
#include <config.h> #include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include "cogl-utils.h" #include "cogl-utils.h"
@@ -755,88 +753,6 @@ set_filename (MetaBackground *self,
priv->filename = g_strdup (filename); priv->filename = g_strdup (filename);
} }
static Pixmap
get_still_frame_for_monitor (MetaScreen *screen,
int monitor)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
Pixmap pixmap;
GC gc;
XGCValues values;
MetaRectangle geometry;
int depth;
meta_screen_get_monitor_geometry (screen, monitor, &geometry);
depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen));
pixmap = XCreatePixmap (xdisplay,
xroot,
geometry.width, geometry.height, depth);
values.function = GXcopy;
values.plane_mask = AllPlanes;
values.fill_style = FillSolid;
values.subwindow_mode = IncludeInferiors;
gc = XCreateGC (xdisplay,
xroot,
GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode,
&values);
XCopyArea (xdisplay,
xroot, pixmap, gc,
geometry.x, geometry.y,
geometry.width, geometry.height,
0, 0);
XFreeGC (xdisplay, gc);
return pixmap;
}
/**
* meta_background_load_still_frame:
* @self: the #MetaBackground
*
* Takes a screenshot of the desktop and uses it as the background
* source.
*/
void
meta_background_load_still_frame (MetaBackground *self)
{
MetaBackgroundPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Pixmap still_frame;
CoglTexture *texture;
CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
GError *error = NULL;
ensure_pipeline (self);
unset_texture (self);
set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED);
still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor);
XSync (meta_display_get_xdisplay (display), False);
meta_error_trap_push (display);
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error));
meta_error_trap_pop (display);
if (error != NULL)
{
g_warning ("Failed to create background texture from pixmap: %s",
error->message);
g_error_free (error);
return;
}
set_texture (self, texture);
}
/** /**
* meta_background_load_gradient: * meta_background_load_gradient:
* @self: the #MetaBackground * @self: the #MetaBackground

View File

@@ -702,7 +702,6 @@ static gboolean
meta_window_actor_has_shadow (MetaWindowActor *self) meta_window_actor_has_shadow (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaWindowType window_type = meta_window_get_window_type (priv->window);
if (priv->no_shadow) if (priv->no_shadow)
return FALSE; return FALSE;
@@ -741,25 +740,6 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
if (priv->window->override_redirect) if (priv->window->override_redirect)
return TRUE; return TRUE;
/*
* Don't put shadow around DND icon windows
*/
if (window_type == META_WINDOW_DND ||
window_type == META_WINDOW_DESKTOP)
return FALSE;
if (window_type == META_WINDOW_MENU
#if 0
|| window_type == META_WINDOW_DROPDOWN_MENU
#endif
)
return TRUE;
#if 0
if (window_type == META_WINDOW_TOOLTIP)
return TRUE;
#endif
return FALSE; return FALSE;
} }

View File

@@ -31,6 +31,7 @@
#include <glib.h> #include <glib.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
#include <meta/common.h> #include <meta/common.h>
#include <meta/boxes.h> #include <meta/boxes.h>
#include <meta/display.h> #include <meta/display.h>
@@ -397,6 +398,8 @@ MetaDisplay* meta_get_display (void);
Cursor meta_display_create_x_cursor (MetaDisplay *display, Cursor meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor); MetaCursor cursor);
XcursorImage *meta_display_load_x_cursor (MetaDisplay *display,
MetaCursor cursor);
void meta_display_set_grab_op_cursor (MetaDisplay *display, void meta_display_set_grab_op_cursor (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,

View File

@@ -1873,7 +1873,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
meta_error_trap_pop (display); meta_error_trap_pop (display);
cursor_ref = meta_cursor_reference_from_theme (screen->cursor_tracker, cursor); cursor_ref = meta_cursor_tracker_get_cursor_from_theme (screen->cursor_tracker, cursor);
meta_cursor_tracker_set_grab_cursor (screen->cursor_tracker, cursor_ref); meta_cursor_tracker_set_grab_cursor (screen->cursor_tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref); meta_cursor_reference_unref (cursor_ref);
} }

View File

@@ -43,6 +43,7 @@
#include "mutter-enum-types.h" #include "mutter-enum-types.h"
#include "core.h" #include "core.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "backends/x11/meta-cursor-tracker-x11.h"
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
@@ -1389,7 +1390,7 @@ meta_screen_update_cursor (MetaScreen *screen)
Cursor xcursor; Cursor xcursor;
MetaCursorReference *cursor_ref; MetaCursorReference *cursor_ref;
cursor_ref = meta_cursor_reference_from_theme (screen->cursor_tracker, cursor); cursor_ref = meta_cursor_tracker_get_cursor_from_theme (screen->cursor_tracker, cursor);
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor_ref); meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref); meta_cursor_reference_unref (cursor_ref);
@@ -3305,7 +3306,10 @@ gboolean
meta_screen_handle_xevent (MetaScreen *screen, meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent) XEvent *xevent)
{ {
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent)) if (meta_is_wayland_compositor ())
return FALSE;
if (meta_cursor_tracker_x11_handle_xevent (META_CURSOR_TRACKER_X11 (screen->cursor_tracker), xevent))
return TRUE; return TRUE;
return FALSE; return FALSE;

View File

@@ -1468,7 +1468,7 @@ meta_window_unmanage (MetaWindow *window,
/* This needs to happen for both Wayland and XWayland clients, /* This needs to happen for both Wayland and XWayland clients,
* so it can't be in MetaWindowWayland. */ * so it can't be in MetaWindowWayland. */
if (window->surface) if (window->surface)
meta_wayland_surface_window_unmanaged (window->surface); meta_wayland_surface_set_window (window->surface, NULL);
if (window->visible_to_compositor) if (window->visible_to_compositor)
{ {

View File

@@ -91,7 +91,6 @@ void meta_background_load_gradient (MetaBackground *self,
ClutterColor *second_color); ClutterColor *second_color);
void meta_background_load_color (MetaBackground *self, void meta_background_load_color (MetaBackground *self,
ClutterColor *color); ClutterColor *color);
void meta_background_load_still_frame (MetaBackground *self);
void meta_background_load_file_async (MetaBackground *self, void meta_background_load_file_async (MetaBackground *self,
const char *filename, const char *filename,
GDesktopBackgroundStyle style, GDesktopBackgroundStyle style,

View File

@@ -38,6 +38,7 @@
#include "meta-shaped-texture-private.h" #include "meta-shaped-texture-private.h"
#include "meta-wayland-stage.h" #include "meta-wayland-stage.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "meta-surface-actor-wayland.h" #include "meta-surface-actor-wayland.h"
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10) #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
@@ -76,7 +77,7 @@ meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
if (seat->cursor_surface && seat->cursor_surface->buffer) if (seat->cursor_surface && seat->cursor_surface->buffer)
{ {
struct wl_resource *buffer = seat->cursor_surface->buffer->resource; struct wl_resource *buffer = seat->cursor_surface->buffer->resource;
cursor = meta_cursor_reference_from_buffer (seat->cursor_tracker, cursor = meta_cursor_tracker_get_cursor_from_buffer (seat->cursor_tracker,
buffer, buffer,
seat->hotspot_x, seat->hotspot_x,
seat->hotspot_y); seat->hotspot_y);
@@ -115,8 +116,16 @@ pointer_set_cursor (struct wl_client *client,
meta_wayland_seat_update_cursor_surface (seat); meta_wayland_seat_update_cursor_surface (seat);
} }
static void
pointer_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_pointer_interface pointer_interface = { static const struct wl_pointer_interface pointer_interface = {
pointer_set_cursor pointer_set_cursor,
pointer_release,
}; };
static void static void
@@ -137,6 +146,17 @@ seat_get_pointer (struct wl_client *client,
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface); meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
} }
static void
keyboard_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_keyboard_interface keyboard_interface = {
keyboard_release,
};
static void static void
seat_get_keyboard (struct wl_client *client, seat_get_keyboard (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
@@ -367,7 +387,7 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
if (seat->cursor_tracker) if (seat->cursor_tracker)
{ {
meta_cursor_tracker_update_position (seat->cursor_tracker, meta_cursor_tracker_native_update_position (META_CURSOR_TRACKER_NATIVE (seat->cursor_tracker),
wl_fixed_to_int (seat->pointer.x), wl_fixed_to_int (seat->pointer.x),
wl_fixed_to_int (seat->pointer.y)); wl_fixed_to_int (seat->pointer.y));

View File

@@ -30,6 +30,7 @@
#include "meta/meta-window-actor.h" #include "meta/meta-window-actor.h"
#include "meta/meta-shaped-texture.h" #include "meta/meta-shaped-texture.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
G_DEFINE_TYPE (MetaWaylandStage, meta_wayland_stage, CLUTTER_TYPE_STAGE); G_DEFINE_TYPE (MetaWaylandStage, meta_wayland_stage, CLUTTER_TYPE_STAGE);
@@ -42,7 +43,7 @@ meta_wayland_stage_paint (ClutterActor *actor)
compositor = meta_wayland_compositor_get_default (); compositor = meta_wayland_compositor_get_default ();
if (compositor->seat->cursor_tracker) if (compositor->seat->cursor_tracker)
meta_cursor_tracker_paint (compositor->seat->cursor_tracker); meta_cursor_tracker_native_paint (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
} }
static void static void

View File

@@ -118,14 +118,14 @@ surface_process_damage (MetaWaylandSurface *surface,
} }
static void static void
meta_wayland_surface_destroy (struct wl_client *client, wl_surface_destroy (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
wl_resource_destroy (resource); wl_resource_destroy (resource);
} }
static void static void
meta_wayland_surface_attach (struct wl_client *client, wl_surface_attach (struct wl_client *client,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
struct wl_resource *buffer_resource, struct wl_resource *buffer_resource,
gint32 dx, gint32 dy) gint32 dx, gint32 dy)
@@ -158,7 +158,7 @@ meta_wayland_surface_attach (struct wl_client *client,
} }
static void static void
meta_wayland_surface_damage (struct wl_client *client, wl_surface_damage (struct wl_client *client,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
gint32 x, gint32 x,
gint32 y, gint32 y,
@@ -186,7 +186,7 @@ destroy_frame_callback (struct wl_resource *callback_resource)
} }
static void static void
meta_wayland_surface_frame (struct wl_client *client, wl_surface_frame (struct wl_client *client,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
guint32 callback_id) guint32 callback_id)
{ {
@@ -206,7 +206,7 @@ meta_wayland_surface_frame (struct wl_client *client,
} }
static void static void
meta_wayland_surface_set_opaque_region (struct wl_client *client, wl_surface_set_opaque_region (struct wl_client *client,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
struct wl_resource *region_resource) struct wl_resource *region_resource)
{ {
@@ -225,7 +225,7 @@ meta_wayland_surface_set_opaque_region (struct wl_client *client,
} }
static void static void
meta_wayland_surface_set_input_region (struct wl_client *client, wl_surface_set_input_region (struct wl_client *client,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
struct wl_resource *region_resource) struct wl_resource *region_resource)
{ {
@@ -507,7 +507,7 @@ commit_double_buffered_state (MetaWaylandSurface *surface,
} }
static void static void
meta_wayland_surface_commit (struct wl_client *client, wl_surface_commit (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -520,7 +520,7 @@ meta_wayland_surface_commit (struct wl_client *client,
} }
static void static void
meta_wayland_surface_set_buffer_transform (struct wl_client *client, wl_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
int32_t transform) int32_t transform)
{ {
@@ -528,7 +528,7 @@ meta_wayland_surface_set_buffer_transform (struct wl_client *client,
} }
static void static void
meta_wayland_surface_set_buffer_scale (struct wl_client *client, wl_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
int scale) int scale)
{ {
@@ -536,29 +536,26 @@ meta_wayland_surface_set_buffer_scale (struct wl_client *client,
g_warning ("TODO: support set_buffer_scale request"); g_warning ("TODO: support set_buffer_scale request");
} }
const struct wl_surface_interface meta_wayland_surface_interface = { const struct wl_surface_interface meta_wayland_wl_surface_interface = {
meta_wayland_surface_destroy, wl_surface_destroy,
meta_wayland_surface_attach, wl_surface_attach,
meta_wayland_surface_damage, wl_surface_damage,
meta_wayland_surface_frame, wl_surface_frame,
meta_wayland_surface_set_opaque_region, wl_surface_set_opaque_region,
meta_wayland_surface_set_input_region, wl_surface_set_input_region,
meta_wayland_surface_commit, wl_surface_commit,
meta_wayland_surface_set_buffer_transform, wl_surface_set_buffer_transform,
meta_wayland_surface_set_buffer_scale wl_surface_set_buffer_scale
}; };
void void
meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface) meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{ {
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE); gboolean has_window = (window != NULL);
}
void clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), has_window);
meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface) surface->window = window;
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
surface->window = NULL;
} }
static void static void
@@ -612,7 +609,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->compositor = compositor; surface->compositor = compositor;
surface->resource = wl_resource_create (client, &wl_surface_interface, version, id); surface->resource = wl_resource_create (client, &wl_surface_interface, version, id);
wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor); wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy; surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface)); surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
@@ -909,6 +906,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->xdg_surface, if (!create_surface_extension (&surface->xdg_surface,
META_XDG_SURFACE_VERSION, META_XDG_SURFACE_VERSION,
@@ -923,8 +921,8 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return; return;
} }
meta_wayland_surface_make_toplevel (surface); window = meta_window_wayland_new (meta_get_display (), surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface); meta_wayland_surface_set_window (surface, window);
} }
static void static void
@@ -962,6 +960,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWindow *window;
if (parent_surf == NULL || parent_surf->window == NULL) if (parent_surf == NULL || parent_surf->window == NULL)
return; return;
@@ -979,15 +978,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return; return;
} }
meta_wayland_surface_make_toplevel (surface); window = meta_window_wayland_new (meta_get_display (), surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface); window->rect.x = parent_surf->window->rect.x + x;
surface->window->rect.x = parent_surf->window->rect.x + x; window->rect.y = parent_surf->window->rect.y + y;
surface->window->rect.y = parent_surf->window->rect.y + y; window->showing_for_first_time = FALSE;
surface->window->showing_for_first_time = FALSE; window->placed = TRUE;
surface->window->placed = TRUE; meta_window_set_transient_for (window, parent_surf->window);
meta_window_set_transient_for (surface->window, parent_surf->window); meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU); meta_wayland_surface_set_window (surface, window);
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface); meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
} }
@@ -1270,6 +1269,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->wl_shell_surface, if (!create_surface_extension (&surface->wl_shell_surface,
META_WL_SHELL_SURFACE_VERSION, META_WL_SHELL_SURFACE_VERSION,
@@ -1284,8 +1284,8 @@ wl_shell_get_shell_surface (struct wl_client *client,
return; return;
} }
meta_wayland_surface_make_toplevel (surface); window = meta_window_wayland_new (meta_get_display (), surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface); meta_wayland_surface_set_window (surface, window);
} }
static const struct wl_shell_interface meta_wayland_wl_shell_interface = { static const struct wl_shell_interface meta_wayland_wl_shell_interface = {

View File

@@ -111,8 +111,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
guint32 id, guint32 id,
guint32 version); guint32 version);
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface); void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface); MetaWindow *window);
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width, int width,

View File

@@ -38,7 +38,7 @@
#define META_WL_COMPOSITOR_VERSION 3 #define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1 #define META_WL_DATA_DEVICE_MANAGER_VERSION 1
#define META_WL_SHELL_VERSION 1 #define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */ #define META_WL_SEAT_VERSION 3
#define META_WL_OUTPUT_VERSION 2 #define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1 #define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 1 #define META_GTK_SHELL_VERSION 1
@@ -49,8 +49,8 @@
#define META_WL_DATA_SOURCE_VERSION 1 /* from wl_data_device */ #define META_WL_DATA_SOURCE_VERSION 1 /* from wl_data_device */
#define META_WL_DATA_DEVICE_VERSION 1 /* from wl_data_device_manager */ #define META_WL_DATA_DEVICE_VERSION 1 /* from wl_data_device_manager */
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */ #define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 2 /* from wl_seat; 3 not implemented yet */ #define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */ #define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */ #define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */ #define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */ #define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */

View File

@@ -1,3 +1,5 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* /*
* X Wayland Support * X Wayland Support
* *
@@ -19,8 +21,11 @@
* 02111-1307, USA. * 02111-1307, USA.
*/ */
#include <glib.h> #include "config.h"
#include "meta-xwayland-private.h"
#include <glib.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@@ -29,10 +34,31 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <stdlib.h> #include <stdlib.h>
#include "meta-xwayland-private.h"
#include "meta-window-actor-private.h" #include "meta-window-actor-private.h"
#include "xserver-server-protocol.h" #include "xserver-server-protocol.h"
static void
xserver_finished_init (MetaXWaylandManager *manager);
static void
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
{
MetaDisplay *display = window->display;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_set_window (surface, window);
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
}
static void static void
xserver_set_window_id (struct wl_client *client, xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource, struct wl_resource *compositor_resource,
@@ -47,19 +73,7 @@ xserver_set_window_id (struct wl_client *client,
if (!window) if (!window)
return; return;
/* If the window has an existing surface, like if we're associate_window_with_surface (window, surface);
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_make_toplevel (surface);
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
} }
static const struct xserver_interface xserver_implementation = { static const struct xserver_interface xserver_implementation = {
@@ -93,12 +107,7 @@ bind_xserver (struct wl_client *client,
* manager. */ * manager. */
wl_client_flush (client); wl_client_flush (client);
/* At this point xwayland is all setup to start accepting xserver_finished_init (manager);
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
} }
static char * static char *
@@ -206,8 +215,7 @@ bind_to_abstract_socket (int display)
size = offsetof (struct sockaddr_un, sun_path) + name_size; size = offsetof (struct sockaddr_un, sun_path) + name_size;
if (bind (fd, (struct sockaddr *) &addr, size) < 0) if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{ {
g_warning ("failed to bind to @%s: %s\n", g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
addr.sun_path + 1, strerror (errno));
close (fd); close (fd);
return -1; return -1;
} }
@@ -239,8 +247,7 @@ bind_to_unix_socket (int display)
unlink (addr.sun_path); unlink (addr.sun_path);
if (bind (fd, (struct sockaddr *) &addr, size) < 0) if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{ {
char *msg = strerror (errno); g_warning ("failed to bind to %s: %m\n", addr.sun_path);
g_warning ("failed to bind to %s (%s)\n", addr.sun_path, msg);
close (fd); close (fd);
return -1; return -1;
} }
@@ -255,18 +262,6 @@ bind_to_unix_socket (int display)
return fd; return fd;
} }
static void
uncloexec (gpointer user_data)
{
int fd = GPOINTER_TO_INT (user_data);
/* Make sure the client end of the socket pair doesn't get closed
* when we exec xwayland. */
int flags = fcntl (fd, F_GETFD);
if (flags != -1)
fcntl (fd, F_SETFD, flags & ~FD_CLOEXEC);
}
static void static void
xserver_died (GPid pid, xserver_died (GPid pid,
gint status, gint status,
@@ -292,20 +287,11 @@ x_io_error (Display *display)
return 0; return 0;
} }
gboolean static gboolean
meta_xwayland_start (MetaXWaylandManager *manager, choose_xdisplay (MetaXWaylandManager *manager)
struct wl_display *wl_display)
{ {
int display = 0; int display = 0;
char *lockfile = NULL; char *lockfile = NULL;
int sp[2];
pid_t pid;
char **env;
char *fd_string;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
do do
{ {
@@ -343,69 +329,86 @@ meta_xwayland_start (MetaXWaylandManager *manager,
while (1); while (1);
manager->display_index = display; manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
manager->lockfile = lockfile; manager->lockfile = lockfile;
return TRUE;
}
static void
xserver_finished_init (MetaXWaylandManager *manager)
{
/* At this point xwayland is all setup to start accepting
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
int sp[2];
int fd;
if (!choose_xdisplay (manager))
return FALSE;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
/* We want xwayland to be a wayland client so we make a socketpair to setup a /* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */ * wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0) if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0)
{ {
g_warning ("socketpair failed\n"); g_warning ("socketpair failed\n");
unlink (lockfile); unlink (manager->lockfile);
return 1; return 1;
} }
env = g_get_environ (); manager->pid = fork ();
fd_string = g_strdup_printf ("%d", sp[1]); if (manager->pid == 0)
env = g_environ_setenv (env, "WAYLAND_SOCKET", fd_string, TRUE);
g_free (fd_string);
manager->display_name = g_strdup_printf (":%d", manager->display_index);
{ {
GError *error = NULL; char socket_fd[8];
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
int flags = 0;
flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN; /* We passed SOCK_CLOEXEC, so dup the FD so it isn't
flags |= G_SPAWN_DO_NOT_REAP_CHILD; * closed on exec.. */
fd = dup (sp[1]);
snprintf (socket_fd, sizeof (socket_fd), "%d", fd);
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
/* xwayland, please. */ /* xwayland, please. */
if (getenv ("XWAYLAND_STFU")) if (getenv ("XWAYLAND_STFU"))
{ {
flags |= G_SPAWN_STDOUT_TO_DEV_NULL; int dev_null;
flags |= G_SPAWN_STDERR_TO_DEV_NULL; dev_null = open ("/dev/null", O_WRONLY);
dup2 (dev_null, STDOUT_FILENO);
dup2 (dev_null, STDERR_FILENO);
} }
if (g_spawn_async (NULL, /* cwd */ if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
args, manager->display_name,
env, "-wayland",
flags, "-rootless",
uncloexec, "-noreset",
GINT_TO_POINTER (sp[1]), "-nolisten", "all",
&pid, NULL) < 0)
&error))
{ {
close (sp[1]); g_error ("Failed to spawn XWayland: %m");
}
}
else if (manager->pid == -1)
{
g_error ("Failed to fork: %m");
}
g_child_watch_add (manager->pid, xserver_died, NULL);
manager->client = wl_client_create (wl_display, sp[0]); manager->client = wl_client_create (wl_display, sp[0]);
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
}
g_strfreev (env);
/* We need to run a mainloop until we know xwayland has a binding /* We need to run a mainloop until we know xwayland has a binding
* for our xserver interface at which point we can assume it's * for our xserver interface at which point we can assume it's
* ready to start accepting connections. */ * ready to start accepting connections. */