Compare commits
	
		
			18 Commits
		
	
	
		
			3.14.3
			...
			wip/dnd-su
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 410b37bc53 | ||
|   | 6dfdc6d6ec | ||
|   | 869d12c36d | ||
|   | 827e0c23c5 | ||
|   | 9efd96be7b | ||
|   | 102d1e62a2 | ||
|   | aba81603b9 | ||
|   | 10c6056ce0 | ||
|   | 79fdbbfe1a | ||
|   | 572727e6e8 | ||
|   | 1dbc9e868f | ||
|   | a181ea3cde | ||
|   | 78477dd56a | ||
|   | 30cc4e1d0a | ||
|   | 4b83b031bc | ||
|   | 40a85e0e99 | ||
|   | dfde1ff327 | ||
|   | 92b7daab61 | 
| @@ -35,13 +35,21 @@ | ||||
|  | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   CoglTexture *texture; | ||||
|   MetaRectangle current_rect; | ||||
|   int current_x, current_y; | ||||
| } MetaCursorLayer; | ||||
|  | ||||
| struct _MetaCursorRendererPrivate | ||||
| { | ||||
|   int current_x, current_y; | ||||
|   MetaRectangle current_rect; | ||||
|   MetaCursorLayer core_layer; | ||||
|   MetaCursorLayer dnd_layer; | ||||
|  | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|   gboolean handled_by_backend; | ||||
|   int dnd_surface_offset_x, dnd_surface_offset_y; | ||||
|   gboolean cursor_handled_by_backend; | ||||
| }; | ||||
| typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; | ||||
|  | ||||
| @@ -59,12 +67,19 @@ queue_redraw (MetaCursorRenderer *renderer) | ||||
|   if (!stage) | ||||
|     return; | ||||
|  | ||||
|   if (priv->displayed_cursor && !priv->handled_by_backend) | ||||
|     texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL); | ||||
|   /* Pointer cursor */ | ||||
|   if (!priv->cursor_handled_by_backend) | ||||
|     texture = priv->core_layer.texture; | ||||
|   else | ||||
|     texture = NULL; | ||||
|  | ||||
|   meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect); | ||||
|   meta_stage_set_cursor (META_STAGE (stage), texture, | ||||
|                          &priv->core_layer.current_rect); | ||||
|  | ||||
|   /* DnD surface */ | ||||
|   meta_stage_set_dnd_surface (META_STAGE (stage), | ||||
|                               priv->dnd_layer.texture, | ||||
|                               &priv->dnd_layer.current_rect); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -85,46 +100,76 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer) | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_cursor (MetaCursorRenderer *renderer) | ||||
| update_layer (MetaCursorRenderer *renderer, | ||||
|               MetaCursorLayer    *layer, | ||||
|               CoglTexture        *texture, | ||||
|               int                 offset_x, | ||||
|               int                 offset_y) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   gboolean handled_by_backend; | ||||
|   gboolean should_redraw = FALSE; | ||||
|   layer->texture = texture; | ||||
|  | ||||
|   if (priv->displayed_cursor) | ||||
|   if (layer->texture) | ||||
|     { | ||||
|       CoglTexture *texture; | ||||
|       int hot_x, hot_y; | ||||
|  | ||||
|       texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y); | ||||
|  | ||||
|       priv->current_rect.x = priv->current_x - hot_x; | ||||
|       priv->current_rect.y = priv->current_y - hot_y; | ||||
|       priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture)); | ||||
|       priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture)); | ||||
|       layer->current_rect.x = layer->current_x + offset_x; | ||||
|       layer->current_rect.y = layer->current_y + offset_y; | ||||
|       layer->current_rect.width = cogl_texture_get_width (layer->texture); | ||||
|       layer->current_rect.height = cogl_texture_get_height (layer->texture); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       priv->current_rect.x = 0; | ||||
|       priv->current_rect.y = 0; | ||||
|       priv->current_rect.width = 0; | ||||
|       priv->current_rect.height = 0; | ||||
|       layer->current_rect.x = 0; | ||||
|       layer->current_rect.y = 0; | ||||
|       layer->current_rect.width = 0; | ||||
|       layer->current_rect.height = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_update_cursor (MetaCursorRenderer *renderer, | ||||
|                     gboolean            force) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   gboolean handled_by_backend, should_redraw = FALSE; | ||||
|  | ||||
|   handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer); | ||||
|   if (handled_by_backend != priv->handled_by_backend) | ||||
|  | ||||
|   if (handled_by_backend != priv->cursor_handled_by_backend) | ||||
|     { | ||||
|       priv->handled_by_backend = handled_by_backend; | ||||
|       priv->cursor_handled_by_backend = handled_by_backend; | ||||
|       should_redraw = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (!handled_by_backend) | ||||
|   if (force || !handled_by_backend || priv->dnd_layer.texture) | ||||
|     should_redraw = TRUE; | ||||
|  | ||||
|   if (should_redraw) | ||||
|     queue_redraw (renderer); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   CoglTexture *texture; | ||||
|   int hot_x, hot_y; | ||||
|  | ||||
|   /* Cursor layer */ | ||||
|   if (priv->displayed_cursor) | ||||
|     { | ||||
|       texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, | ||||
|                                                         &hot_x, &hot_y); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       texture = NULL; | ||||
|       hot_x = 0; | ||||
|       hot_y = 0; | ||||
|     } | ||||
|  | ||||
|   update_layer (renderer, &priv->core_layer, texture, -hot_x, -hot_y); | ||||
|   emit_update_cursor (renderer, FALSE); | ||||
| } | ||||
|  | ||||
| MetaCursorRenderer * | ||||
| meta_cursor_renderer_new (void) | ||||
| { | ||||
| @@ -144,6 +189,23 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer, | ||||
|   update_cursor (renderer); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer, | ||||
|                                       CoglTexture        *texture, | ||||
|                                       int                 offset_x, | ||||
|                                       int                 offset_y) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->dnd_surface_offset_x = offset_x; | ||||
|   priv->dnd_surface_offset_y = offset_y; | ||||
|  | ||||
|   update_layer (renderer, &priv->dnd_layer, texture, offset_x, offset_y); | ||||
|   emit_update_cursor (renderer, TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|                                    int x, int y) | ||||
| @@ -152,12 +214,46 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->current_x = x; | ||||
|   priv->current_y = y; | ||||
|   priv->core_layer.current_x = x; | ||||
|   priv->core_layer.current_y = y; | ||||
|  | ||||
|   update_cursor (renderer); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer, | ||||
|                                                int                 x, | ||||
|                                                int                 y) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->dnd_layer.current_x = x; | ||||
|   priv->dnd_layer.current_y = y; | ||||
|  | ||||
|   update_layer (renderer, &priv->dnd_layer, priv->dnd_layer.texture, | ||||
|                 priv->dnd_surface_offset_x, priv->dnd_surface_offset_y); | ||||
|   emit_update_cursor (renderer, FALSE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer, | ||||
|                                  int                 dest_x, | ||||
|                                  int                 dest_y) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   ClutterActor *stage = meta_backend_get_stage (backend); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   if (priv->dnd_layer.texture) | ||||
|     meta_stage_dnd_failed (META_STAGE (stage), | ||||
|                            dest_x + priv->dnd_surface_offset_x, | ||||
|                            dest_y + priv->dnd_surface_offset_y); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
| @@ -171,5 +267,5 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   return &priv->current_rect; | ||||
|   return &priv->core_layer.current_rect; | ||||
| } | ||||
|   | ||||
| @@ -67,4 +67,14 @@ void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
| MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); | ||||
| const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer); | ||||
|  | ||||
| void meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer, | ||||
|                                            CoglTexture        *texture, | ||||
|                                            int                 offset_x, | ||||
|                                            int                 offset_y); | ||||
| void meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer, | ||||
|                                                     int x, int y); | ||||
|  | ||||
| void meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer, | ||||
|                                       int dest_x, int dest_y); | ||||
|  | ||||
| #endif /* META_CURSOR_RENDERER_H */ | ||||
|   | ||||
| @@ -62,10 +62,20 @@ 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_set_dnd_surface     (MetaCursorTracker   *tracker, | ||||
|                                                   CoglTexture         *texture, | ||||
|                                                   int                  offset_x, | ||||
|                                                   int                  offset_y); | ||||
|  | ||||
| void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
| 					      int                new_x, | ||||
| 					      int                new_y); | ||||
| void     meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker, | ||||
|                                                           int                new_x, | ||||
|                                                           int                new_y); | ||||
| void     meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker, | ||||
|                                          int                dest_x, | ||||
|                                          int                dest_y); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); | ||||
|  | ||||
|   | ||||
| @@ -358,6 +358,28 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker, | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_dnd_surface (MetaCursorTracker   *tracker, | ||||
|                                      CoglTexture         *texture, | ||||
|                                      int                  offset_x, | ||||
|                                      int                  offset_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   meta_cursor_renderer_set_dnd_surface (tracker->renderer, texture, | ||||
|                                         offset_x, offset_y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker, | ||||
|                                 int                dest_x, | ||||
|                                 int                dest_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   meta_cursor_renderer_dnd_failed (tracker->renderer, dest_x, dest_y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
|                                      int                new_x, | ||||
| @@ -368,6 +390,17 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
|   meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker, | ||||
|                                                  int                new_x, | ||||
|                                                  int                new_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   meta_cursor_renderer_set_dnd_surface_position (tracker->renderer, | ||||
|                                                  new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_pointer_position_gdk (int         *x, | ||||
|                           int         *y, | ||||
|   | ||||
| @@ -28,6 +28,8 @@ | ||||
| #include <meta/meta-backend.h> | ||||
| #include <meta/util.h> | ||||
|  | ||||
| #define DRAG_FAILED_MSECS 500 | ||||
|  | ||||
| typedef struct { | ||||
|   gboolean enabled; | ||||
|  | ||||
| @@ -39,8 +41,20 @@ typedef struct { | ||||
|   gboolean previous_is_valid; | ||||
| } MetaOverlay; | ||||
|  | ||||
| typedef struct { | ||||
|   MetaStage *stage; | ||||
|   MetaOverlay overlay; | ||||
|   ClutterTimeline *timeline; | ||||
|   int orig_x; | ||||
|   int orig_y; | ||||
|   int dest_x; | ||||
|   int dest_y; | ||||
| } MetaDragFailedAnimation; | ||||
|  | ||||
| struct _MetaStagePrivate { | ||||
|   MetaOverlay dnd_overlay; | ||||
|   MetaOverlay cursor_overlay; | ||||
|   GList *drag_failed_animations; | ||||
| }; | ||||
| typedef struct _MetaStagePrivate MetaStagePrivate; | ||||
|  | ||||
| @@ -54,6 +68,15 @@ meta_overlay_init (MetaOverlay *overlay) | ||||
|   overlay->pipeline = cogl_pipeline_new (ctx); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_overlay_copy (MetaOverlay *src, | ||||
|                    MetaOverlay *dst) | ||||
| { | ||||
|   *dst = *src; | ||||
|   dst->pipeline = cogl_pipeline_copy (src->pipeline); | ||||
|   dst->texture = src->texture; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_overlay_free (MetaOverlay *overlay) | ||||
| { | ||||
| @@ -112,6 +135,7 @@ meta_stage_finalize (GObject *object) | ||||
|   MetaStage *stage = META_STAGE (object); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   meta_overlay_free (&priv->dnd_overlay); | ||||
|   meta_overlay_free (&priv->cursor_overlay); | ||||
| } | ||||
|  | ||||
| @@ -120,9 +144,18 @@ meta_stage_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (actor); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   MetaDragFailedAnimation *animation; | ||||
|   GList *l; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor); | ||||
|  | ||||
|   for (l = priv->drag_failed_animations; l; l = l->next) | ||||
|     { | ||||
|       animation = l->data; | ||||
|       meta_overlay_paint (&animation->overlay); | ||||
|     } | ||||
|  | ||||
|   meta_overlay_paint (&priv->dnd_overlay); | ||||
|   meta_overlay_paint (&priv->cursor_overlay); | ||||
| } | ||||
|  | ||||
| @@ -142,6 +175,7 @@ meta_stage_init (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   meta_overlay_init (&priv->dnd_overlay); | ||||
|   meta_overlay_init (&priv->cursor_overlay); | ||||
|  | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE); | ||||
| @@ -183,6 +217,19 @@ queue_redraw_for_overlay (MetaStage   *stage, | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_set_dnd_surface (MetaStage     *stage, | ||||
|                             CoglTexture   *texture, | ||||
|                             MetaRectangle *rect) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   meta_overlay_set (&priv->dnd_overlay, texture, rect); | ||||
|   queue_redraw_for_overlay (stage, &priv->dnd_overlay); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_set_cursor (MetaStage     *stage, | ||||
|                        CoglTexture   *texture, | ||||
| @@ -195,3 +242,84 @@ meta_stage_set_cursor (MetaStage     *stage, | ||||
|   meta_overlay_set (&priv->cursor_overlay, texture, rect); | ||||
|   queue_redraw_for_overlay (stage, &priv->cursor_overlay); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drag_failed_animation_frame_cb (ClutterTimeline *timeline, | ||||
|                                 guint            pos, | ||||
|                                 gpointer         user_data) | ||||
| { | ||||
|   MetaDragFailedAnimation *data = user_data; | ||||
|   gdouble progress = clutter_timeline_get_progress (timeline); | ||||
|   CoglColor color; | ||||
|  | ||||
|   cogl_color_init_from_4f (&color, 0, 0, 0, 1 - progress); | ||||
|   cogl_pipeline_set_layer_combine_constant (data->overlay.pipeline, 0, &color); | ||||
|  | ||||
|   data->overlay.current_rect.x = data->orig_x + ((data->dest_x - data->orig_x) * progress); | ||||
|   data->overlay.current_rect.y = data->orig_y + ((data->dest_y - data->orig_y) * progress); | ||||
|   queue_redraw_for_overlay (data->stage, &data->overlay); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_drag_failed_animation_free (MetaDragFailedAnimation *data) | ||||
| { | ||||
|   MetaStage *stage = data->stage; | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   priv->drag_failed_animations = | ||||
|     g_list_remove (priv->drag_failed_animations, data); | ||||
|  | ||||
|   g_object_unref (data->timeline); | ||||
|   meta_overlay_free (&data->overlay); | ||||
|   g_slice_free (MetaDragFailedAnimation, data); | ||||
| } | ||||
|  | ||||
| static MetaDragFailedAnimation * | ||||
| meta_drag_failed_animation_new (MetaStage *stage, | ||||
|                                 int        dest_x, | ||||
|                                 int        dest_y) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   MetaDragFailedAnimation *data; | ||||
|  | ||||
|   data = g_slice_new0 (MetaDragFailedAnimation); | ||||
|   data->stage = stage; | ||||
|   data->orig_x = priv->dnd_overlay.current_rect.x; | ||||
|   data->orig_y = priv->dnd_overlay.current_rect.y; | ||||
|   data->dest_x = dest_x; | ||||
|   data->dest_y = dest_y; | ||||
|  | ||||
|   meta_overlay_copy (&priv->dnd_overlay, &data->overlay); | ||||
|  | ||||
|   data->timeline = clutter_timeline_new (DRAG_FAILED_MSECS); | ||||
|   clutter_timeline_set_progress_mode (data->timeline, CLUTTER_EASE_OUT_CUBIC); | ||||
|   g_signal_connect (data->timeline, "new-frame", | ||||
|                     G_CALLBACK (drag_failed_animation_frame_cb), data); | ||||
|   g_signal_connect_swapped (data->timeline, "completed", | ||||
|                             G_CALLBACK (meta_drag_failed_animation_free), data); | ||||
|  | ||||
|   priv->drag_failed_animations = | ||||
|     g_list_prepend (priv->drag_failed_animations, data); | ||||
|  | ||||
|   cogl_pipeline_set_layer_combine (data->overlay.pipeline, 0, | ||||
|                                    "RGBA = MODULATE (TEXTURE, CONSTANT[A])", | ||||
|                                    NULL); | ||||
|   return data; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_dnd_failed (MetaStage *stage, | ||||
|                        int        dest_x, | ||||
|                        int        dest_y) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   MetaDragFailedAnimation *data; | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   if (!priv->dnd_overlay.enabled) | ||||
|     return; | ||||
|  | ||||
|   data = meta_drag_failed_animation_new (stage, dest_x, dest_y); | ||||
|   clutter_timeline_start (data->timeline); | ||||
| } | ||||
|   | ||||
| @@ -51,9 +51,18 @@ GType             meta_stage_get_type                (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterActor     *meta_stage_new                     (void); | ||||
|  | ||||
| void meta_stage_set_dnd_surface (MetaStage     *stage, | ||||
|                                  CoglTexture   *texture, | ||||
|                                  MetaRectangle *rect); | ||||
|  | ||||
| void meta_stage_set_cursor (MetaStage     *stage, | ||||
|                             CoglTexture   *texture, | ||||
|                             MetaRectangle *rect); | ||||
|  | ||||
| void meta_stage_dnd_failed (MetaStage *stage, | ||||
|                             int        dest_x, | ||||
|                             int        dest_y); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_STAGE_H */ | ||||
|   | ||||
| @@ -34,6 +34,7 @@ | ||||
| #include "meta-wayland-seat.h" | ||||
| #include "meta-wayland-pointer.h" | ||||
| #include "meta-wayland-private.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
| @@ -46,6 +47,7 @@ struct _MetaWaylandDataSource | ||||
| { | ||||
|   struct wl_resource *resource; | ||||
|   struct wl_array mime_types; | ||||
|   gboolean has_target; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| @@ -67,7 +69,10 @@ data_offer_accept (struct wl_client *client, | ||||
|    * this be a wl_data_device request? */ | ||||
|  | ||||
|   if (offer->source) | ||||
|     wl_data_source_send_target (offer->source->resource, mime_type); | ||||
|     { | ||||
|       wl_data_source_send_target (offer->source->resource, mime_type); | ||||
|       offer->source->has_target = mime_type != NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -162,7 +167,7 @@ static struct wl_data_source_interface data_source_interface = { | ||||
|   data_source_destroy | ||||
| }; | ||||
|  | ||||
| typedef struct { | ||||
| struct _MetaWaylandDragGrab { | ||||
|   MetaWaylandPointerGrab  generic; | ||||
|  | ||||
|   MetaWaylandSeat        *seat; | ||||
| @@ -177,7 +182,12 @@ typedef struct { | ||||
|  | ||||
|   MetaWaylandDataSource  *drag_data_source; | ||||
|   struct wl_listener      drag_data_source_listener; | ||||
| } MetaWaylandDragGrab; | ||||
|  | ||||
|   MetaWaylandSurface     *drag_origin; | ||||
|   struct wl_listener      drag_origin_listener; | ||||
|  | ||||
|   int                     drag_start_x, drag_start_y; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| destroy_drag_focus (struct wl_listener *listener, void *data) | ||||
| @@ -202,6 +212,8 @@ drag_grab_focus (MetaWaylandPointerGrab *grab, | ||||
|   if (drag_grab->drag_focus == surface) | ||||
|     return; | ||||
|  | ||||
|   meta_wayland_pointer_set_focus (&seat->pointer, surface, FALSE); | ||||
|  | ||||
|   if (drag_grab->drag_focus_data_device) | ||||
|     { | ||||
|       wl_data_device_send_leave (drag_grab->drag_focus_data_device); | ||||
| @@ -241,6 +253,40 @@ drag_grab_focus (MetaWaylandPointerGrab *grab, | ||||
|   wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drag_grab_update_dnd_surface_position (MetaWaylandDragGrab *drag_grab) | ||||
| { | ||||
|   MetaWaylandSeat *seat = drag_grab->seat; | ||||
|   ClutterPoint pos; | ||||
|  | ||||
|   clutter_input_device_get_coords (seat->pointer.device, NULL, &pos); | ||||
|   meta_cursor_tracker_update_dnd_surface_position (seat->pointer.cursor_tracker, | ||||
|                                                    (int) pos.x, (int) pos.y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drag_grab_update_dnd_surface (MetaWaylandDragGrab *drag_grab) | ||||
| { | ||||
|   MetaWaylandSurface *surface = drag_grab->drag_surface; | ||||
|   MetaWaylandSeat *seat = drag_grab->seat; | ||||
|   CoglTexture *texture = NULL; | ||||
|   int offset_x, offset_y; | ||||
|  | ||||
|   if (surface) | ||||
|     { | ||||
|       if (surface->buffer) | ||||
|         texture = surface->buffer->texture; | ||||
|  | ||||
|       offset_x = surface->offset_x; | ||||
|       offset_y = surface->offset_y; | ||||
|     } | ||||
|   else | ||||
|     offset_x = offset_y = 0; | ||||
|  | ||||
|   meta_cursor_tracker_set_dnd_surface (seat->pointer.cursor_tracker, | ||||
|                                        texture, offset_x, offset_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drag_grab_motion (MetaWaylandPointerGrab *grab, | ||||
| 		  const ClutterEvent     *event) | ||||
| @@ -248,6 +294,8 @@ drag_grab_motion (MetaWaylandPointerGrab *grab, | ||||
|   MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; | ||||
|   wl_fixed_t sx, sy; | ||||
|  | ||||
|   drag_grab_update_dnd_surface_position (drag_grab); | ||||
|  | ||||
|   if (drag_grab->drag_focus_data_device) | ||||
|     { | ||||
|       meta_wayland_pointer_get_relative_coordinates (grab->pointer, | ||||
| @@ -259,9 +307,38 @@ drag_grab_motion (MetaWaylandPointerGrab *grab, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| data_device_dnd_failed (MetaWaylandDragGrab *drag_grab) | ||||
| { | ||||
|   MetaWaylandSurface *surface = drag_grab->drag_origin; | ||||
|   MetaWaylandSeat *seat = drag_grab->seat; | ||||
|   ClutterPoint dest; | ||||
|  | ||||
|   if (drag_grab->drag_origin && | ||||
|       !meta_window_is_hidden (surface->window)) | ||||
|     { | ||||
|       /* Find out the snap back position */ | ||||
|       clutter_actor_get_transformed_position (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)), | ||||
|                                               &dest.x, &dest.y); | ||||
|       dest.x += drag_grab->drag_start_x; | ||||
|       dest.y += drag_grab->drag_start_y; | ||||
|     } | ||||
|   else | ||||
|     clutter_input_device_get_coords (seat->pointer.device, NULL, &dest); | ||||
|  | ||||
|   meta_cursor_tracker_dnd_failed (seat->pointer.cursor_tracker, | ||||
|                                   dest.x, dest.y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) | ||||
| { | ||||
|   if (drag_grab->drag_origin) | ||||
|     { | ||||
|       drag_grab->drag_origin = NULL; | ||||
|       wl_list_remove (&drag_grab->drag_origin_listener.link); | ||||
|     } | ||||
|  | ||||
|   if (drag_grab->drag_surface) | ||||
|     { | ||||
|       drag_grab->drag_surface = NULL; | ||||
| @@ -269,9 +346,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) | ||||
|     } | ||||
|  | ||||
|   if (drag_grab->drag_data_source) | ||||
|     wl_list_remove (&drag_grab->drag_data_source_listener.link); | ||||
|     { | ||||
|       drag_grab->drag_data_source->has_target = FALSE; | ||||
|       wl_list_remove (&drag_grab->drag_data_source_listener.link); | ||||
|     } | ||||
|  | ||||
|   drag_grab->seat->data_device.current_grab = NULL; | ||||
|  | ||||
|   drag_grab_focus (&drag_grab->generic, NULL); | ||||
|   drag_grab_update_dnd_surface (drag_grab); | ||||
|  | ||||
|   meta_wayland_pointer_end_grab (drag_grab->generic.pointer); | ||||
|   g_slice_free (MetaWaylandDragGrab, drag_grab); | ||||
| @@ -285,10 +368,15 @@ drag_grab_button (MetaWaylandPointerGrab *grab, | ||||
|   MetaWaylandSeat *seat = drag_grab->seat; | ||||
|   ClutterEventType event_type = clutter_event_type (event); | ||||
|  | ||||
|   if (drag_grab->drag_focus_data_device && | ||||
|       drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) && | ||||
|   if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) && | ||||
|       event_type == CLUTTER_BUTTON_RELEASE) | ||||
|     wl_data_device_send_drop (drag_grab->drag_focus_data_device); | ||||
|     { | ||||
|       if (drag_grab->drag_focus_data_device && | ||||
|           drag_grab->drag_data_source->has_target) | ||||
|         wl_data_device_send_drop (drag_grab->drag_focus_data_device); | ||||
|       else | ||||
|         data_device_dnd_failed (drag_grab); | ||||
|     } | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 && | ||||
|       event_type == CLUTTER_BUTTON_RELEASE) | ||||
| @@ -301,6 +389,16 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = { | ||||
|   drag_grab_button, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| destroy_data_device_origin (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaWaylandDragGrab *drag_grab = | ||||
|     wl_container_of (listener, drag_grab, drag_origin_listener); | ||||
|  | ||||
|   drag_grab->drag_origin = NULL; | ||||
|   data_device_end_drag_grab (drag_grab); | ||||
| } | ||||
|  | ||||
| static void | ||||
| destroy_data_device_source (struct wl_listener *listener, void *data) | ||||
| { | ||||
| @@ -318,6 +416,7 @@ destroy_data_device_icon (struct wl_listener *listener, void *data) | ||||
|     wl_container_of (listener, drag_grab, drag_data_source_listener); | ||||
|  | ||||
|   drag_grab->drag_surface = NULL; | ||||
|   drag_grab_update_dnd_surface (drag_grab); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -329,20 +428,29 @@ data_device_start_drag (struct wl_client *client, | ||||
| { | ||||
|   MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); | ||||
|   MetaWaylandSurface *surface = NULL; | ||||
|   MetaWaylandDragGrab *drag_grab; | ||||
|   ClutterPoint pos; | ||||
|  | ||||
|   if ((seat->pointer.button_count == 0 || | ||||
|        seat->pointer.grab_serial != serial || | ||||
|        !seat->pointer.focus_surface || | ||||
|        seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource))) | ||||
|   if (origin_resource) | ||||
|     surface = wl_resource_get_user_data (origin_resource); | ||||
|  | ||||
|   if (!surface) | ||||
|     return; | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 || | ||||
|       seat->pointer.grab_serial != serial || | ||||
|       !seat->pointer.focus_surface || | ||||
|       seat->pointer.focus_surface != surface) | ||||
|     return; | ||||
|  | ||||
|   /* FIXME: Check that the data source type array isn't empty. */ | ||||
|  | ||||
|   if (seat->pointer.grab != &seat->pointer.default_grab) | ||||
|   if (data_device->current_grab || | ||||
|       seat->pointer.grab != &seat->pointer.default_grab) | ||||
|     return; | ||||
|  | ||||
|   drag_grab = g_slice_new0 (MetaWaylandDragGrab); | ||||
|   data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab); | ||||
|  | ||||
|   drag_grab->generic.interface = &drag_grab_interface; | ||||
|   drag_grab->generic.pointer = &seat->pointer; | ||||
| @@ -350,6 +458,17 @@ data_device_start_drag (struct wl_client *client, | ||||
|   drag_grab->drag_client = client; | ||||
|   drag_grab->seat = seat; | ||||
|  | ||||
|   drag_grab->drag_origin = surface; | ||||
|   drag_grab->drag_origin_listener.notify = destroy_data_device_origin; | ||||
|   wl_resource_add_destroy_listener (origin_resource, | ||||
|                                     &drag_grab->drag_origin_listener); | ||||
|  | ||||
|   clutter_input_device_get_coords (seat->pointer.device, NULL, &pos); | ||||
|   clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)), | ||||
|                                        pos.x, pos.y, &pos.x, &pos.y); | ||||
|   drag_grab->drag_start_x = pos.x; | ||||
|   drag_grab->drag_start_y = pos.y; | ||||
|  | ||||
|   if (source_resource) | ||||
|     { | ||||
|       drag_grab->drag_data_source = wl_resource_get_user_data (source_resource); | ||||
| @@ -366,8 +485,10 @@ data_device_start_drag (struct wl_client *client, | ||||
|                                         &drag_grab->drag_icon_listener); | ||||
|     } | ||||
|  | ||||
|   meta_wayland_pointer_set_focus (&seat->pointer, NULL); | ||||
|   meta_wayland_pointer_set_focus (&seat->pointer, NULL, TRUE); | ||||
|   meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab); | ||||
|   drag_grab_update_dnd_surface_position (drag_grab); | ||||
|   drag_grab_update_dnd_surface (drag_grab); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -551,3 +672,18 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device) | ||||
|       wl_data_device_send_selection (data_device_resource, offer); | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device, | ||||
|                                          MetaWaylandSurface    *surface) | ||||
| { | ||||
|   return data_device->current_grab && | ||||
|     data_device->current_grab->drag_surface == surface; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device) | ||||
| { | ||||
|   if (data_device->current_grab) | ||||
|     drag_grab_update_dnd_surface (data_device->current_grab); | ||||
| } | ||||
|   | ||||
| @@ -27,12 +27,15 @@ | ||||
|  | ||||
| #include "meta-wayland-types.h" | ||||
|  | ||||
| typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab; | ||||
|  | ||||
| struct _MetaWaylandDataDevice | ||||
| { | ||||
|   uint32_t selection_serial; | ||||
|   MetaWaylandDataSource *selection_data_source; | ||||
|   struct wl_listener selection_data_source_listener; | ||||
|   struct wl_list resource_list; | ||||
|   MetaWaylandDragGrab *current_grab; | ||||
| }; | ||||
|  | ||||
| void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor); | ||||
| @@ -41,4 +44,8 @@ void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device); | ||||
|  | ||||
| void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device); | ||||
|  | ||||
| gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device, | ||||
|                                                   MetaWaylandSurface    *surface); | ||||
| void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device); | ||||
|  | ||||
| #endif /* META_WAYLAND_DATA_DEVICE_H */ | ||||
|   | ||||
| @@ -95,7 +95,7 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener); | ||||
|  | ||||
|   meta_wayland_pointer_set_focus (pointer, NULL); | ||||
|   meta_wayland_pointer_set_focus (pointer, NULL, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -107,7 +107,7 @@ default_grab_focus (MetaWaylandPointerGrab *grab, | ||||
|   if (pointer->button_count > 0) | ||||
|     return; | ||||
|  | ||||
|   meta_wayland_pointer_set_focus (pointer, surface); | ||||
|   meta_wayland_pointer_set_focus (pointer, surface, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -178,7 +178,7 @@ default_grab_button (MetaWaylandPointerGrab *grab, | ||||
|     } | ||||
|  | ||||
|   if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE) | ||||
|     meta_wayland_pointer_set_focus (pointer, pointer->current); | ||||
|     meta_wayland_pointer_set_focus (pointer, pointer->current, TRUE); | ||||
| } | ||||
|  | ||||
| static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = { | ||||
| @@ -218,7 +218,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer, | ||||
| void | ||||
| meta_wayland_pointer_release (MetaWaylandPointer *pointer) | ||||
| { | ||||
|   meta_wayland_pointer_set_focus (pointer, NULL); | ||||
|   meta_wayland_pointer_set_focus (pointer, NULL, TRUE); | ||||
|   set_cursor_surface (pointer, NULL); | ||||
|  | ||||
|   pointer->display = NULL; | ||||
| @@ -480,7 +480,8 @@ broadcast_focus (MetaWaylandPointer *pointer, | ||||
|  | ||||
| void | ||||
| meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, | ||||
|                                 MetaWaylandSurface *surface) | ||||
|                                 MetaWaylandSurface *surface, | ||||
|                                 gboolean            emit_crossing) | ||||
| { | ||||
|   if (pointer->display == NULL) | ||||
|     return; | ||||
| @@ -500,9 +501,12 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, | ||||
|           struct wl_display *display = wl_client_get_display (client); | ||||
|           uint32_t serial = wl_display_next_serial (display); | ||||
|  | ||||
|           wl_resource_for_each (resource, l) | ||||
|           if (emit_crossing) | ||||
|             { | ||||
|               wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource); | ||||
|               wl_resource_for_each (resource, l) | ||||
|                 { | ||||
|                   wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           move_resources (&pointer->resource_list, &pointer->focus_resource_list); | ||||
| @@ -533,7 +537,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, | ||||
|                                  wl_resource_get_client (pointer->focus_surface->resource)); | ||||
|  | ||||
|       l = &pointer->focus_resource_list; | ||||
|       if (!wl_list_empty (l)) | ||||
|       if (emit_crossing && !wl_list_empty (l)) | ||||
|         { | ||||
|           struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource); | ||||
|           struct wl_display *display = wl_client_get_display (client); | ||||
| @@ -595,9 +599,9 @@ popup_grab_focus (MetaWaylandPointerGrab *grab, | ||||
|   /* Popup grabs are in owner-events mode (ie, events for the same client | ||||
|      are reported as normal) */ | ||||
|   if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client) | ||||
|     meta_wayland_pointer_set_focus (grab->pointer, surface); | ||||
|     meta_wayland_pointer_set_focus (grab->pointer, surface, TRUE); | ||||
|   else | ||||
|     meta_wayland_pointer_set_focus (grab->pointer, NULL); | ||||
|     meta_wayland_pointer_set_focus (grab->pointer, NULL, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -86,7 +86,8 @@ gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer, | ||||
|                                             const ClutterEvent *event); | ||||
|  | ||||
| void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, | ||||
|                                      MetaWaylandSurface *surface); | ||||
|                                      MetaWaylandSurface *surface, | ||||
|                                      gboolean            emit_crossing); | ||||
|  | ||||
| void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer, | ||||
|                                       MetaWaylandPointerGrab *grab); | ||||
|   | ||||
| @@ -175,6 +175,13 @@ cursor_surface_commit (MetaWaylandSurface      *surface, | ||||
|     meta_wayland_seat_update_cursor_surface (surface->compositor->seat); | ||||
| } | ||||
|  | ||||
| static void | ||||
| dnd_surface_commit (MetaWaylandSurface      *surface, | ||||
|                     MetaWaylandPendingState *pending) | ||||
| { | ||||
|   meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| calculate_surface_window_geometry (MetaWaylandSurface *surface, | ||||
|                                    MetaRectangle      *total_geometry, | ||||
| @@ -429,6 +436,9 @@ commit_pending_state (MetaWaylandSurface      *surface, | ||||
|   if (!cairo_region_is_empty (pending->damage)) | ||||
|     surface_process_damage (surface, pending->damage); | ||||
|  | ||||
|   surface->offset_x += pending->dx; | ||||
|   surface->offset_y += pending->dy; | ||||
|  | ||||
|   if (pending->opaque_region) | ||||
|     { | ||||
|       pending->opaque_region = scale_region (pending->opaque_region, surface->scale); | ||||
| @@ -442,6 +452,8 @@ commit_pending_state (MetaWaylandSurface      *surface, | ||||
|  | ||||
|   if (surface == compositor->seat->pointer.cursor_surface) | ||||
|     cursor_surface_commit (surface, pending); | ||||
|   else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface)) | ||||
|     dnd_surface_commit (surface, pending); | ||||
|   else if (surface->window) | ||||
|     toplevel_surface_commit (surface, pending); | ||||
|   else if (surface->subsurface.resource) | ||||
|   | ||||
| @@ -115,6 +115,8 @@ struct _MetaWaylandSurface | ||||
|     GSList *pending_placement_ops; | ||||
|   } sub; | ||||
|  | ||||
|   int32_t offset_x, offset_y; | ||||
|  | ||||
|   gboolean has_set_geometry; | ||||
|  | ||||
|   /* All the pending state that wl_surface.commit will apply. */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user