Compare commits
	
		
			2 Commits
		
	
	
		
			wip/fmuell
			...
			wip/split-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b9d798c213 | ||
|   | 5abf41ab5a | 
| @@ -70,12 +70,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	\ | ||||
|   | ||||
| @@ -27,6 +27,11 @@ | ||||
| #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; | ||||
| @@ -47,4 +52,26 @@ 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 */ | ||||
|   | ||||
| @@ -30,10 +30,7 @@ | ||||
| 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 | ||||
| @@ -49,9 +46,15 @@ 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. | ||||
| @@ -62,23 +65,37 @@ 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); | ||||
| }; | ||||
|  | ||||
| gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
| 					    XEvent            *xevent); | ||||
| void    _meta_cursor_tracker_set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                                                 gboolean             has_cursor, | ||||
|                                                 MetaCursorReference *cursor); | ||||
| void    _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker); | ||||
|  | ||||
| void     meta_cursor_tracker_set_grab_cursor     (MetaCursorTracker   *tracker, | ||||
|                                                   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_set_root_cursor     (MetaCursorTracker   *tracker, | ||||
|                                                   MetaCursorReference *cursor); | ||||
|  | ||||
| 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); | ||||
| 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); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -33,20 +33,11 @@ | ||||
| #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); | ||||
|  | ||||
| @@ -57,11 +48,6 @@ 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) | ||||
| { | ||||
| @@ -88,14 +74,32 @@ 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) | ||||
| { | ||||
| @@ -103,6 +107,11 @@ 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, | ||||
| @@ -111,81 +120,6 @@ 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 | ||||
| @@ -203,127 +137,14 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen) | ||||
|     return screen->cursor_tracker; | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     self = make_wayland_cursor_tracker (screen); | ||||
|     self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL); | ||||
|   else | ||||
|     self = make_x11_cursor_tracker (screen); | ||||
|     self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL); | ||||
|  | ||||
|   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: | ||||
|  * | ||||
| @@ -334,11 +155,10 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) | ||||
| { | ||||
|   g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL); | ||||
|  | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     ensure_xfixes_cursor (tracker); | ||||
|   META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker); | ||||
|  | ||||
|   if (tracker->displayed_cursor) | ||||
|     return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL); | ||||
|   if (tracker->current_cursor) | ||||
|     return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
| @@ -357,11 +177,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, | ||||
| { | ||||
|   g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); | ||||
|  | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     ensure_xfixes_cursor (tracker); | ||||
|   META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker); | ||||
|  | ||||
|   if (tracker->displayed_cursor) | ||||
|     meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y); | ||||
|   if (tracker->current_cursor) | ||||
|     meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y); | ||||
|   else | ||||
|     { | ||||
|       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 | ||||
| meta_cursor_tracker_set_grab_cursor (MetaCursorTracker   *tracker, | ||||
|                                      MetaCursorReference *cursor) | ||||
| @@ -379,20 +224,7 @@ meta_cursor_tracker_set_grab_cursor (MetaCursorTracker   *tracker, | ||||
|   if (cursor) | ||||
|     tracker->grab_cursor = meta_cursor_reference_ref (cursor); | ||||
|  | ||||
|   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); | ||||
|   _meta_cursor_tracker_sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -403,78 +235,12 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker, | ||||
|   if (cursor) | ||||
|     tracker->root_cursor = meta_cursor_reference_ref (cursor); | ||||
|  | ||||
|   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); | ||||
|     } | ||||
|   _meta_cursor_tracker_sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| static MetaCursorReference * | ||||
| get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| get_current_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   if (!tracker->is_showing) | ||||
|     return NULL; | ||||
|  | ||||
|   if (tracker->grab_cursor) | ||||
|     return tracker->grab_cursor; | ||||
|  | ||||
| @@ -484,208 +250,38 @@ get_displayed_cursor (MetaCursorTracker *tracker) | ||||
|   return tracker->root_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_displayed_cursor (MetaCursorTracker *tracker) | ||||
| static MetaCursorReference * | ||||
| get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   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); | ||||
|   if (!tracker->is_showing) | ||||
|     return NULL; | ||||
|  | ||||
|       update_hw_cursor (tracker); | ||||
|     } | ||||
|   return get_current_cursor (tracker); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_displayed_cursor (MetaCursorTracker *tracker) | ||||
| void | ||||
| _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *current_cursor = get_current_cursor (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) | ||||
|   if (tracker->displayed_cursor != displayed_cursor) | ||||
|     { | ||||
|       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; | ||||
|       g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref); | ||||
|       if (displayed_cursor) | ||||
|         tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor); | ||||
|  | ||||
|       META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker); | ||||
|     } | ||||
|  | ||||
|   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) | ||||
|   if (tracker->current_cursor != current_cursor) | ||||
|     { | ||||
|       CoglTexture *texture; | ||||
|       int hot_x, hot_y; | ||||
|       g_clear_pointer (&tracker->current_cursor, meta_cursor_reference_unref); | ||||
|       if (current_cursor) | ||||
|         tracker->current_cursor = meta_cursor_reference_ref (current_cursor); | ||||
|  | ||||
|       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)); | ||||
|       g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
|     } | ||||
|   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 | ||||
| @@ -694,15 +290,7 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker   *tracker, | ||||
|                                  int                 *y, | ||||
|                                  ClutterModifierType *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); | ||||
|   META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -713,26 +301,51 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, | ||||
|     return; | ||||
|   tracker->is_showing = visible; | ||||
|  | ||||
|   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); | ||||
|     } | ||||
|   _meta_cursor_tracker_sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_force_update (MetaCursorTracker *tracker) | ||||
| MetaCursorReference * | ||||
| 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); | ||||
|   sync_cursor (tracker); | ||||
|   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; | ||||
| } | ||||
|   | ||||
| @@ -27,16 +27,23 @@ | ||||
|  | ||||
| #include "display-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 <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) | ||||
| { | ||||
| @@ -190,14 +197,21 @@ load_cursor_on_client (MetaDisplay *display, | ||||
|   return image; | ||||
| } | ||||
|  | ||||
| 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) | ||||
| 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) | ||||
| { | ||||
|   if (width > 64 || height > 64) | ||||
|     { | ||||
| @@ -211,180 +225,154 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, | ||||
|       uint8_t buf[4 * 64 * 64]; | ||||
|       int i; | ||||
|  | ||||
|       image->bo = gbm_bo_create (gbm, 64, 64, | ||||
|                                  gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); | ||||
|       cursor->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 (image->bo, buf, 64 * 64 * 4); | ||||
|       gbm_bo_write (cursor->image.bo, buf, 64 * 64 * 4); | ||||
|     } | ||||
|   else | ||||
|     meta_warning ("HW cursor for format %d not supported\n", gbm_format); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker, | ||||
|                                            MetaCursorImage   *image, | ||||
|                                            XcursorImage      *xc_image) | ||||
| void | ||||
| meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor, | ||||
|                                          struct gbm_device   *gbm, | ||||
|                                          struct wl_resource  *buffer, | ||||
|                                          int                  width, | ||||
|                                          int                  height) | ||||
| { | ||||
|   /* 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 | ||||
|  | ||||
|   image->hot_x = xc_image->xhot; | ||||
|   image->hot_y = xc_image->yhot; | ||||
|   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); | ||||
|   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); | ||||
|   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_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) | ||||
| meta_cursor_reference_from_buffer (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; | ||||
|  | ||||
|   image->hot_x = hot_x; | ||||
|   image->hot_y = hot_y; | ||||
|   cursor = meta_cursor_reference_new (); | ||||
|  | ||||
|   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); | ||||
|  | ||||
|   image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL); | ||||
|   cursor->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 | ||||
|          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; | ||||
|   return cursor; | ||||
| } | ||||
|  | ||||
| CoglTexture * | ||||
|   | ||||
| @@ -27,16 +27,4 @@ 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 */ | ||||
|   | ||||
							
								
								
									
										443
									
								
								src/backends/native/meta-cursor-tracker-native.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								src/backends/native/meta-cursor-tracker-native.c
									
									
									
									
									
										Normal 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)); | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/backends/native/meta-cursor-tracker-native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/backends/native/meta-cursor-tracker-native.h
									
									
									
									
									
										Normal 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 */ | ||||
| @@ -44,6 +44,7 @@ | ||||
|  | ||||
| #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 | ||||
| @@ -219,7 +220,7 @@ meta_launcher_enter (MetaLauncher *launcher) | ||||
|      * update. */ | ||||
|  | ||||
|     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)); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										138
									
								
								src/backends/x11/meta-cursor-tracker-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/backends/x11/meta-cursor-tracker-x11.c
									
									
									
									
									
										Normal 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; | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/backends/x11/meta-cursor-tracker-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/backends/x11/meta-cursor-tracker-x11.h
									
									
									
									
									
										Normal 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 */ | ||||
| @@ -31,6 +31,7 @@ | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xcursor/Xcursor.h> | ||||
| #include <meta/common.h> | ||||
| #include <meta/boxes.h> | ||||
| #include <meta/display.h> | ||||
| @@ -397,6 +398,8 @@ 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, | ||||
|   | ||||
| @@ -1873,7 +1873,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *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_reference_unref (cursor_ref); | ||||
| } | ||||
|   | ||||
| @@ -43,6 +43,7 @@ | ||||
| #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> | ||||
|  | ||||
| @@ -1389,7 +1390,7 @@ meta_screen_update_cursor (MetaScreen *screen) | ||||
|   Cursor xcursor; | ||||
|   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_reference_unref (cursor_ref); | ||||
|  | ||||
| @@ -3305,7 +3306,10 @@ gboolean | ||||
| meta_screen_handle_xevent (MetaScreen *screen, | ||||
|                            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 FALSE; | ||||
|   | ||||
| @@ -38,6 +38,7 @@ | ||||
| #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) | ||||
| @@ -76,10 +77,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_reference_from_buffer (seat->cursor_tracker, | ||||
|                                                   buffer, | ||||
|                                                   seat->hotspot_x, | ||||
|                                                   seat->hotspot_y); | ||||
|       cursor = meta_cursor_tracker_get_cursor_from_buffer (seat->cursor_tracker, | ||||
|                                                            buffer, | ||||
|                                                            seat->hotspot_x, | ||||
|                                                            seat->hotspot_y); | ||||
|     } | ||||
|   else | ||||
|     cursor = NULL; | ||||
| @@ -386,9 +387,9 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat    *seat, | ||||
|  | ||||
|   if (seat->cursor_tracker) | ||||
|     { | ||||
|       meta_cursor_tracker_update_position (seat->cursor_tracker, | ||||
| 					   wl_fixed_to_int (seat->pointer.x), | ||||
| 					   wl_fixed_to_int (seat->pointer.y)); | ||||
|       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)); | ||||
|  | ||||
|       if (seat->pointer.current == NULL) | ||||
| 	meta_cursor_tracker_unset_window_cursor (seat->cursor_tracker); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
| #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); | ||||
|  | ||||
| @@ -42,7 +43,7 @@ meta_wayland_stage_paint (ClutterActor *actor) | ||||
|  | ||||
|   compositor = meta_wayland_compositor_get_default (); | ||||
|   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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user