Compare commits

..

3 Commits

Author SHA1 Message Date
e947d2f544 Bump version to 3.12.1
Update NEWS.
2014-04-15 22:46:38 +02:00
12e8d04c16 po: Update POTFILES after file got renamed 2014-04-15 22:46:37 +02:00
783dbf9390 build: Complete rename of header file
Fallout from commit d5552cc372.
2014-04-15 22:31:11 +02:00
27 changed files with 987 additions and 1209 deletions

7
NEWS
View File

@ -1,3 +1,10 @@
3.12.1
======
* Fix crash when running as X11 compositor [Adel; #727115]
Contributors:
Matthias Clasen, Adel Gadllah, Florian Müllner, Jasper St. Pierre
3.12.0
======
* Fix grab issue with SSD xwayland windows [Rui; #726123]

View File

@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [12])
m4_define([mutter_micro_version], [0])
m4_define([mutter_micro_version], [1])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])

View File

@ -3,6 +3,7 @@
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
src/core/bell.c
@ -12,7 +13,6 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c

View File

@ -58,6 +58,7 @@ libmutter_wayland_la_SOURCES = \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-display-config-shared.h \
backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
@ -70,21 +71,16 @@ libmutter_wayland_la_SOURCES = \
backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \
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.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-weston-launch.c \
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.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
backends/x11/meta-xrandr-shared.h \
core/above-tab-keycode.c \
core/barrier.c \
meta/barrier.h \

View File

@ -27,11 +27,6 @@
#include <cogl/cogl.h>
#include <gbm.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <wayland-server.h>
typedef struct {
CoglTexture2D *texture;
struct gbm_bo *bo;
@ -52,26 +47,4 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
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 */

View File

@ -30,7 +30,10 @@
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
gboolean is_showing;
gboolean has_hw_cursor;
/* The cursor tracker stores the cursor for the current grab
* operation, the cursor for the window with pointer focus, and
@ -46,15 +49,9 @@ struct _MetaCursorTracker {
*/
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;
/* Wayland clients can set a NULL buffer as their cursor
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean.
@ -65,37 +62,23 @@ struct _MetaCursorTracker {
MetaCursorReference *root_cursor;
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 {
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);
};
void _meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor);
void _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker);
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
@ -104,13 +87,12 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor);
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
#endif

View File

@ -33,11 +33,20 @@
#include <meta/util.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-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "backends/x11/meta-cursor-tracker-x11.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);
@ -48,6 +57,11 @@ enum {
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
meta_cursor_tracker_init (MetaCursorTracker *self)
{
@ -74,32 +88,14 @@ meta_cursor_tracker_finalize (GObject *object)
if (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);
}
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
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
{
@ -107,11 +103,6 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
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",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
@ -120,6 +111,81 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
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:
* @screen: the #MetaScreen
@ -137,14 +203,127 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
return screen->cursor_tracker;
if (meta_is_wayland_compositor ())
self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL);
self = make_wayland_cursor_tracker (screen);
else
self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL);
self = make_x11_cursor_tracker (screen);
screen->cursor_tracker = 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:
*
@ -155,10 +334,11 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (tracker->current_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL);
if (tracker->displayed_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
else
return NULL;
}
@ -177,10 +357,11 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
{
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (tracker->current_cursor)
meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y);
if (tracker->displayed_cursor)
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
else
{
if (x)
@ -190,32 +371,6 @@ 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
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
@ -224,7 +379,20 @@ meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
if (cursor)
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
_meta_cursor_tracker_sync_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
@ -235,12 +403,78 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (cursor);
_meta_cursor_tracker_sync_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 *
get_current_cursor (MetaCursorTracker *tracker)
get_displayed_cursor (MetaCursorTracker *tracker)
{
if (!tracker->is_showing)
return NULL;
if (tracker->grab_cursor)
return tracker->grab_cursor;
@ -250,47 +484,225 @@ get_current_cursor (MetaCursorTracker *tracker)
return tracker->root_cursor;
}
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
static void
update_displayed_cursor (MetaCursorTracker *tracker)
{
if (!tracker->is_showing)
return NULL;
if (meta_is_wayland_compositor ())
{
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);
return get_current_cursor (tracker);
update_hw_cursor (tracker);
}
}
static void
sync_displayed_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
update_displayed_cursor (tracker);
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_sync_cursor (MetaCursorTracker *tracker)
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
MetaCursorReference *current_cursor = get_current_cursor (tracker);
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
g_assert (meta_is_wayland_compositor ());
if (tracker->displayed_cursor != displayed_cursor)
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)
{
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker);
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;
}
if (tracker->current_cursor != current_cursor)
else
{
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);
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
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods);
/* 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.
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
@ -301,51 +713,26 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
return;
tracker->is_showing = visible;
_meta_cursor_tracker_sync_cursor (tracker);
if (meta_is_wayland_compositor ())
{
sync_cursor (tracker);
}
else
{
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
}
}
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
MetaCursor meta_cursor)
void
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
{
MetaCursorReference *cursor;
XcursorImage *xc_image;
g_assert (meta_is_wayland_compositor ());
if (tracker->theme_cursors[meta_cursor])
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;
update_hw_cursor (tracker);
sync_cursor (tracker);
}

View File

@ -27,23 +27,16 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-cursor-tracker-private.h"
#include "meta-cursor-tracker-private.h" /* for tracker->gbm */
#include <string.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.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 *
meta_cursor_reference_ref (MetaCursorReference *self)
{
@ -197,21 +190,14 @@ load_cursor_on_client (MetaDisplay *display,
return image;
}
XcursorImage *
meta_display_load_x_cursor (MetaDisplay *display,
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,
int width,
int height,
int rowstride,
uint32_t gbm_format)
static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t gbm_format)
{
if (width > 64 || height > 64)
{
@ -225,154 +211,180 @@ meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
uint8_t buf[4 * 64 * 64];
int i;
cursor->image.bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
image->bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (cursor->image.bo, buf, 64 * 64 * 4);
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
void
meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
struct wl_resource *buffer,
int width,
int height)
static void
meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker,
MetaCursorImage *image,
XcursorImage *xc_image)
{
/* 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
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
cursor->image.bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!cursor->image.bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
MetaCursorReference *
meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image)
{
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;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
cursor = meta_cursor_reference_new ();
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
cursor->image.hot_x = xc_image->xhot;
cursor->image.hot_y = xc_image->yhot;
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);
cursor->image.texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
return cursor;
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_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y)
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,
int hot_x,
int hot_y)
{
MetaCursorReference *cursor;
ClutterBackend *backend;
CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
int width, height;
cursor = meta_cursor_reference_new ();
cursor->image.hot_x = hot_x;
cursor->image.hot_y = hot_y;
image->hot_x = hot_x;
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);
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
return cursor;
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
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
if (tracker->gbm)
{
image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
}
}
MetaCursorReference *
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_buffer (tracker, &self->image, buffer, hot_x, hot_y);
return self;
}
CoglTexture *

View File

@ -27,4 +27,16 @@ typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (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 */

View File

@ -1,443 +0,0 @@
/*
* 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

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

View File

@ -1,138 +0,0 @@
/*
* 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

@ -1,40 +0,0 @@
/*
* 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,6 +26,8 @@
#include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h>
#include "cogl-utils.h"
@ -753,6 +755,88 @@ set_filename (MetaBackground *self,
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:
* @self: the #MetaBackground

View File

@ -702,6 +702,7 @@ static gboolean
meta_window_actor_has_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindowType window_type = meta_window_get_window_type (priv->window);
if (priv->no_shadow)
return FALSE;
@ -740,6 +741,25 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
if (priv->window->override_redirect)
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,7 +38,6 @@
#include "meta-shaped-texture-private.h"
#include "meta-wayland-stage.h"
#include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "meta-surface-actor-wayland.h"
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
@ -77,10 +76,10 @@ meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
if (seat->cursor_surface && seat->cursor_surface->buffer)
{
struct wl_resource *buffer = seat->cursor_surface->buffer->resource;
cursor = meta_cursor_tracker_get_cursor_from_buffer (seat->cursor_tracker,
buffer,
seat->hotspot_x,
seat->hotspot_y);
cursor = meta_cursor_reference_from_buffer (seat->cursor_tracker,
buffer,
seat->hotspot_x,
seat->hotspot_y);
}
else
cursor = NULL;
@ -116,16 +115,8 @@ pointer_set_cursor (struct wl_client *client,
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 = {
pointer_set_cursor,
pointer_release,
pointer_set_cursor
};
static void
@ -146,17 +137,6 @@ seat_get_pointer (struct wl_client *client,
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
seat_get_keyboard (struct wl_client *client,
struct wl_resource *resource,
@ -387,9 +367,9 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
if (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.y));
meta_cursor_tracker_update_position (seat->cursor_tracker,
wl_fixed_to_int (seat->pointer.x),
wl_fixed_to_int (seat->pointer.y));
if (seat->pointer.current == NULL)
meta_cursor_tracker_unset_window_cursor (seat->cursor_tracker);

View File

@ -30,7 +30,6 @@
#include "meta/meta-window-actor.h"
#include "meta/meta-shaped-texture.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);
@ -43,7 +42,7 @@ meta_wayland_stage_paint (ClutterActor *actor)
compositor = meta_wayland_compositor_get_default ();
if (compositor->seat->cursor_tracker)
meta_cursor_tracker_native_paint (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
meta_cursor_tracker_paint (compositor->seat->cursor_tracker);
}
static void

View File

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

View File

@ -38,7 +38,7 @@
#define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 3
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_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_DEVICE_VERSION 1 /* from wl_data_device_manager */
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_POINTER_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */

View File

@ -1,5 +1,3 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* X Wayland Support
*
@ -21,11 +19,8 @@
* 02111-1307, USA.
*/
#include "config.h"
#include "meta-xwayland-private.h"
#include <glib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
@ -34,31 +29,10 @@
#include <sys/wait.h>
#include <stdlib.h>
#include "meta-xwayland-private.h"
#include "meta-window-actor-private.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
xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource,
@ -73,7 +47,19 @@ xserver_set_window_id (struct wl_client *client,
if (!window)
return;
associate_window_with_surface (window, surface);
/* 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_make_toplevel (surface);
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
}
static const struct xserver_interface xserver_implementation = {
@ -107,7 +93,12 @@ bind_xserver (struct wl_client *client,
* manager. */
wl_client_flush (client);
xserver_finished_init (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);
}
static char *
@ -215,7 +206,8 @@ bind_to_abstract_socket (int display)
size = offsetof (struct sockaddr_un, sun_path) + name_size;
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
g_warning ("failed to bind to @%s: %s\n",
addr.sun_path + 1, strerror (errno));
close (fd);
return -1;
}
@ -247,7 +239,8 @@ bind_to_unix_socket (int display)
unlink (addr.sun_path);
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
g_warning ("failed to bind to %s: %m\n", addr.sun_path);
char *msg = strerror (errno);
g_warning ("failed to bind to %s (%s)\n", addr.sun_path, msg);
close (fd);
return -1;
}
@ -262,6 +255,18 @@ bind_to_unix_socket (int display)
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
xserver_died (GPid pid,
gint status,
@ -287,11 +292,20 @@ x_io_error (Display *display)
return 0;
}
static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
int display = 0;
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
{
@ -329,85 +343,68 @@ choose_xdisplay (MetaXWaylandManager *manager)
while (1);
manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
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
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0)
{
g_warning ("socketpair failed\n");
unlink (manager->lockfile);
unlink (lockfile);
return 1;
}
manager->pid = fork ();
if (manager->pid == 0)
{
char socket_fd[8];
env = g_get_environ ();
fd_string = g_strdup_printf ("%d", sp[1]);
env = g_environ_setenv (env, "WAYLAND_SOCKET", fd_string, TRUE);
g_free (fd_string);
/* We passed SOCK_CLOEXEC, so dup the FD so it isn't
* closed on exec.. */
fd = dup (sp[1]);
snprintf (socket_fd, sizeof (socket_fd), "%d", fd);
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
manager->display_name = g_strdup_printf (":%d", manager->display_index);
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
int dev_null;
dev_null = open ("/dev/null", O_WRONLY);
{
GError *error = NULL;
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
int flags = 0;
dup2 (dev_null, STDOUT_FILENO);
dup2 (dev_null, STDERR_FILENO);
}
flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten", "all",
NULL) < 0)
{
g_error ("Failed to spawn XWayland: %m");
}
}
else if (manager->pid == -1)
{
g_error ("Failed to fork: %m");
}
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
}
g_child_watch_add (manager->pid, xserver_died, NULL);
manager->client = wl_client_create (wl_display, sp[0]);
if (g_spawn_async (NULL, /* cwd */
args,
env,
flags,
uncloexec,
GINT_TO_POINTER (sp[1]),
&pid,
&error))
{
close (sp[1]);
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
* for our xserver interface at which point we can assume it's