Compare commits
5 Commits
wip/garnac
...
wip/dnd-ac
Author | SHA1 | Date | |
---|---|---|---|
![]() |
319d0bb679 | ||
![]() |
ce78db31b7 | ||
![]() |
15513adcc3 | ||
![]() |
832c710c81 | ||
![]() |
682c13723b |
@@ -42,12 +42,18 @@ struct _MetaWaylandDataOffer
|
|||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
MetaWaylandDataSource *source;
|
MetaWaylandDataSource *source;
|
||||||
struct wl_listener source_destroy_listener;
|
struct wl_listener source_destroy_listener;
|
||||||
|
uint32_t dnd_actions;
|
||||||
|
uint32_t preferred_dnd_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _MetaWaylandDataSourcePrivate
|
typedef struct _MetaWaylandDataSourcePrivate
|
||||||
{
|
{
|
||||||
|
MetaWaylandDataOffer *offer;
|
||||||
struct wl_array mime_types;
|
struct wl_array mime_types;
|
||||||
gboolean has_target;
|
gboolean has_target;
|
||||||
|
uint32_t dnd_actions;
|
||||||
|
uint32_t user_dnd_action;
|
||||||
|
uint32_t current_dnd_action;
|
||||||
} MetaWaylandDataSourcePrivate;
|
} MetaWaylandDataSourcePrivate;
|
||||||
|
|
||||||
typedef struct _MetaWaylandDataSourceWayland
|
typedef struct _MetaWaylandDataSourceWayland
|
||||||
@@ -74,6 +80,50 @@ unbind_resource (struct wl_resource *resource)
|
|||||||
wl_list_remove (wl_resource_get_link (resource));
|
wl_list_remove (wl_resource_get_link (resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
data_offer_choose_action (MetaWaylandDataOffer *offer)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSource *source = offer->source;
|
||||||
|
uint32_t actions, user_action, available_actions;
|
||||||
|
|
||||||
|
actions = meta_wayland_data_source_get_actions (source);
|
||||||
|
user_action = meta_wayland_data_source_get_user_action (source);
|
||||||
|
|
||||||
|
available_actions = actions & offer->dnd_actions;
|
||||||
|
|
||||||
|
if (!available_actions)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* If the user is forcing an action, go for it */
|
||||||
|
if ((user_action & available_actions) != 0)
|
||||||
|
return user_action;
|
||||||
|
|
||||||
|
/* If the dest side has a preferred DnD action, use it */
|
||||||
|
if ((offer->preferred_dnd_action & available_actions) != 0)
|
||||||
|
return offer->preferred_dnd_action;
|
||||||
|
|
||||||
|
/* Use the first found action, in bit order */
|
||||||
|
return 1 << (ffs (available_actions) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
data_offer_update_action (MetaWaylandDataOffer *offer)
|
||||||
|
{
|
||||||
|
uint32_t current_action, action;
|
||||||
|
|
||||||
|
if (!offer->source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
current_action = meta_wayland_data_source_get_current_action (offer->source);
|
||||||
|
action = data_offer_choose_action (offer);
|
||||||
|
|
||||||
|
if (current_action == action)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_wayland_data_source_set_current_action (offer->source, action);
|
||||||
|
wl_data_offer_send_action (offer->resource, action);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||||
const char *mime_type)
|
const char *mime_type)
|
||||||
@@ -123,6 +173,106 @@ meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
|
|||||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
|
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
meta_wayland_data_source_get_actions (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
return priv->dnd_actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
return priv->user_dnd_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
return priv->current_dnd_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source,
|
||||||
|
MetaWaylandDataOffer *offer)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
priv->offer = offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandDataOffer *
|
||||||
|
meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
return priv->offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
|
if (priv->current_dnd_action == action)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->current_dnd_action = action;
|
||||||
|
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||||
|
uint32_t dnd_actions)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
MetaWaylandDataOffer *offer;
|
||||||
|
|
||||||
|
if (priv->dnd_actions == dnd_actions)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->dnd_actions = dnd_actions;
|
||||||
|
offer = meta_wayland_data_source_get_current_offer (source);
|
||||||
|
|
||||||
|
if (offer)
|
||||||
|
{
|
||||||
|
wl_data_offer_send_source_actions (offer->resource,
|
||||||
|
priv->dnd_actions);
|
||||||
|
data_offer_update_action (offer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourcePrivate *priv =
|
||||||
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
MetaWaylandDataOffer *offer;
|
||||||
|
|
||||||
|
if (priv->user_dnd_action == action)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->user_dnd_action = action;
|
||||||
|
offer = meta_wayland_data_source_get_current_offer (source);
|
||||||
|
|
||||||
|
if (offer)
|
||||||
|
data_offer_update_action (offer);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
data_offer_accept (struct wl_client *client,
|
data_offer_accept (struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
@@ -161,21 +311,59 @@ data_offer_destroy (struct wl_client *client, struct wl_resource *resource)
|
|||||||
wl_resource_destroy (resource);
|
wl_resource_destroy (resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
data_offer_set_actions (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t dnd_actions,
|
||||||
|
uint32_t preferred_action)
|
||||||
|
{
|
||||||
|
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
if (offer->dnd_actions == dnd_actions &&
|
||||||
|
offer->preferred_dnd_action == preferred_action)
|
||||||
|
return;
|
||||||
|
|
||||||
|
offer->dnd_actions = dnd_actions;
|
||||||
|
offer->preferred_dnd_action = preferred_action;
|
||||||
|
|
||||||
|
data_offer_update_action (offer);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wl_data_offer_interface data_offer_interface = {
|
static const struct wl_data_offer_interface data_offer_interface = {
|
||||||
data_offer_accept,
|
data_offer_accept,
|
||||||
data_offer_receive,
|
data_offer_receive,
|
||||||
data_offer_destroy,
|
data_offer_destroy,
|
||||||
|
data_offer_set_actions
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_data_offer (struct wl_resource *resource)
|
destroy_data_offer (struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
if (offer->source)
|
if (offer->source)
|
||||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
{
|
||||||
(gpointer *)&offer->source);
|
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||||
|
meta_wayland_data_source_notify_finish (offer->source);
|
||||||
|
|
||||||
|
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||||
|
(gpointer *)&offer->source);
|
||||||
|
offer->source = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||||
g_slice_free (MetaWaylandDataOffer, offer);
|
g_slice_free (MetaWaylandDataOffer, offer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,6 +391,9 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
|
|||||||
wl_array_for_each (p, &priv->mime_types)
|
wl_array_for_each (p, &priv->mime_types)
|
||||||
wl_data_offer_send_offer (offer->resource, *p);
|
wl_data_offer_send_offer (offer->resource, *p);
|
||||||
|
|
||||||
|
data_offer_update_action (offer);
|
||||||
|
meta_wayland_data_source_set_current_offer (source, offer);
|
||||||
|
|
||||||
return offer->resource;
|
return offer->resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,14 +413,27 @@ data_source_destroy (struct wl_client *client, struct wl_resource *resource)
|
|||||||
wl_resource_destroy (resource);
|
wl_resource_destroy (resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
data_source_set_actions (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t dnd_actions)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
meta_wayland_data_source_set_actions (source, dnd_actions);
|
||||||
|
}
|
||||||
|
|
||||||
static struct wl_data_source_interface data_source_interface = {
|
static struct wl_data_source_interface data_source_interface = {
|
||||||
data_source_offer,
|
data_source_offer,
|
||||||
data_source_destroy
|
data_source_destroy,
|
||||||
|
data_source_set_actions
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWaylandDragGrab {
|
struct _MetaWaylandDragGrab {
|
||||||
MetaWaylandPointerGrab generic;
|
MetaWaylandPointerGrab generic;
|
||||||
|
|
||||||
|
MetaWaylandKeyboardGrab keyboard_grab;
|
||||||
|
|
||||||
MetaWaylandSeat *seat;
|
MetaWaylandSeat *seat;
|
||||||
struct wl_client *drag_client;
|
struct wl_client *drag_client;
|
||||||
|
|
||||||
@@ -248,6 +452,7 @@ struct _MetaWaylandDragGrab {
|
|||||||
struct wl_listener drag_origin_listener;
|
struct wl_listener drag_origin_listener;
|
||||||
|
|
||||||
int drag_start_x, drag_start_y;
|
int drag_start_x, drag_start_y;
|
||||||
|
ClutterModifierType buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -256,6 +461,7 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
|
|||||||
MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener);
|
MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener);
|
||||||
|
|
||||||
grab->drag_focus_data_device = NULL;
|
grab->drag_focus_data_device = NULL;
|
||||||
|
grab->drag_focus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -285,6 +491,7 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
|
|||||||
client = wl_resource_get_client (surface->resource);
|
client = wl_resource_get_client (surface->resource);
|
||||||
|
|
||||||
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
||||||
|
meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL);
|
||||||
|
|
||||||
if (drag_grab->drag_data_source && data_device_resource)
|
if (drag_grab->drag_data_source && data_device_resource)
|
||||||
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
|
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
|
||||||
@@ -312,6 +519,22 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
|||||||
meta_wayland_drag_grab_set_focus (drag_grab, surface);
|
meta_wayland_drag_grab_set_focus (drag_grab, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
data_source_update_user_dnd_action (MetaWaylandDataSource *source,
|
||||||
|
ClutterModifierType modifiers)
|
||||||
|
{
|
||||||
|
uint32_t user_dnd_action = 0;
|
||||||
|
|
||||||
|
if (modifiers & CLUTTER_SHIFT_MASK)
|
||||||
|
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||||
|
else if (modifiers & CLUTTER_CONTROL_MASK)
|
||||||
|
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||||
|
else if (modifiers & (CLUTTER_MOD1_MASK | CLUTTER_BUTTON2_MASK))
|
||||||
|
user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||||
|
|
||||||
|
meta_wayland_data_source_set_user_action (source, user_dnd_action);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drag_grab_motion (MetaWaylandPointerGrab *grab,
|
drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||||
const ClutterEvent *event)
|
const ClutterEvent *event)
|
||||||
@@ -356,7 +579,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
|||||||
|
|
||||||
drag_grab->seat->data_device.current_grab = NULL;
|
drag_grab->seat->data_device.current_grab = NULL;
|
||||||
|
|
||||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
/* There might be other grabs created in result to DnD actions like popups
|
||||||
|
* on "ask" actions, we must not reset those, only our own.
|
||||||
|
*/
|
||||||
|
if (drag_grab->generic.pointer->grab == (MetaWaylandPointerGrab *) drag_grab)
|
||||||
|
{
|
||||||
|
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
||||||
|
meta_wayland_keyboard_end_grab (drag_grab->keyboard_grab.keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,13 +602,23 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
|||||||
if (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)
|
event_type == CLUTTER_BUTTON_RELEASE)
|
||||||
{
|
{
|
||||||
|
MetaWaylandDataSource *data_source = drag_grab->drag_data_source;
|
||||||
gboolean success = FALSE;
|
gboolean success = FALSE;
|
||||||
|
|
||||||
if (meta_wayland_data_source_has_target (drag_grab->drag_data_source))
|
if (drag_grab->drag_focus &&
|
||||||
|
meta_wayland_data_source_get_current_action (drag_grab->drag_data_source) &&
|
||||||
|
meta_wayland_data_source_has_target (drag_grab->drag_data_source))
|
||||||
{
|
{
|
||||||
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
|
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
|
||||||
|
meta_wayland_data_source_notify_drop_performed (data_source);
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_wayland_data_source_cancel (data_source);
|
||||||
|
meta_wayland_data_source_set_current_offer (data_source, NULL);
|
||||||
|
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Finish drag and let actor self-destruct */
|
/* Finish drag and let actor self-destruct */
|
||||||
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
|
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
|
||||||
@@ -396,6 +637,40 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
|
|||||||
drag_grab_button,
|
drag_grab_button,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_drag_grab_modifiers (MetaWaylandKeyboardGrab *grab,
|
||||||
|
ClutterModifierType modifiers)
|
||||||
|
{
|
||||||
|
MetaWaylandDragGrab *drag_grab;
|
||||||
|
|
||||||
|
drag_grab = wl_container_of (grab, drag_grab, keyboard_grab);
|
||||||
|
|
||||||
|
/* The modifiers here just contain keyboard modifiers, mix it with the
|
||||||
|
* mouse button modifiers we got when starting the drag operation.
|
||||||
|
*/
|
||||||
|
modifiers |= drag_grab->buttons;
|
||||||
|
|
||||||
|
if (drag_grab->drag_data_source)
|
||||||
|
{
|
||||||
|
data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers);
|
||||||
|
|
||||||
|
if (drag_grab->drag_focus)
|
||||||
|
meta_wayland_surface_drag_dest_update (drag_grab->drag_focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MetaWaylandKeyboardGrabInterface keyboard_drag_grab_interface = {
|
||||||
|
keyboard_drag_grab_key,
|
||||||
|
keyboard_drag_grab_modifiers
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_data_device_origin (struct wl_listener *listener, void *data)
|
destroy_data_device_origin (struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -440,12 +715,16 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
|
|||||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||||
MetaWaylandDragGrab *drag_grab;
|
MetaWaylandDragGrab *drag_grab;
|
||||||
ClutterPoint pos, stage_pos;
|
ClutterPoint pos, stage_pos;
|
||||||
|
ClutterModifierType modifiers;
|
||||||
|
|
||||||
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||||
|
|
||||||
drag_grab->generic.interface = funcs;
|
drag_grab->generic.interface = funcs;
|
||||||
drag_grab->generic.pointer = &seat->pointer;
|
drag_grab->generic.pointer = &seat->pointer;
|
||||||
|
|
||||||
|
drag_grab->keyboard_grab.interface = &keyboard_drag_grab_interface;
|
||||||
|
drag_grab->keyboard_grab.keyboard = &seat->keyboard;
|
||||||
|
|
||||||
drag_grab->drag_client = client;
|
drag_grab->drag_client = client;
|
||||||
drag_grab->seat = seat;
|
drag_grab->seat = seat;
|
||||||
|
|
||||||
@@ -460,6 +739,11 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
|
|||||||
drag_grab->drag_start_x = stage_pos.x;
|
drag_grab->drag_start_x = stage_pos.x;
|
||||||
drag_grab->drag_start_y = stage_pos.y;
|
drag_grab->drag_start_y = stage_pos.y;
|
||||||
|
|
||||||
|
modifiers = clutter_input_device_get_modifier_state (seat->pointer.device);
|
||||||
|
drag_grab->buttons = modifiers &
|
||||||
|
(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK |
|
||||||
|
CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK);
|
||||||
|
|
||||||
g_object_weak_ref (G_OBJECT (source),
|
g_object_weak_ref (G_OBJECT (source),
|
||||||
drag_grab_data_source_destroyed,
|
drag_grab_data_source_destroyed,
|
||||||
drag_grab);
|
drag_grab);
|
||||||
@@ -467,6 +751,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
|
|||||||
drag_grab->drag_data_source = source;
|
drag_grab->drag_data_source = source;
|
||||||
meta_wayland_data_device_set_dnd_source (data_device,
|
meta_wayland_data_device_set_dnd_source (data_device,
|
||||||
drag_grab->drag_data_source);
|
drag_grab->drag_data_source);
|
||||||
|
data_source_update_user_dnd_action (source, modifiers);
|
||||||
|
|
||||||
if (icon_surface)
|
if (icon_surface)
|
||||||
{
|
{
|
||||||
@@ -548,6 +833,10 @@ data_device_start_drag (struct wl_client *client,
|
|||||||
meta_wayland_data_device_start_drag (data_device, client,
|
meta_wayland_data_device_start_drag (data_device, client,
|
||||||
&drag_grab_interface,
|
&drag_grab_interface,
|
||||||
surface, drag_source, icon_surface);
|
surface, drag_source, icon_surface);
|
||||||
|
|
||||||
|
meta_wayland_keyboard_set_focus (&seat->keyboard, NULL);
|
||||||
|
meta_wayland_keyboard_start_grab (&seat->keyboard,
|
||||||
|
&seat->data_device.current_grab->keyboard_grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -600,6 +889,34 @@ meta_wayland_source_cancel (MetaWaylandDataSource *source)
|
|||||||
wl_data_source_send_cancelled (source_wayland->resource);
|
wl_data_source_send_cancelled (source_wayland->resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_source_action (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourceWayland *source_wayland =
|
||||||
|
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||||
|
|
||||||
|
wl_data_source_send_action (source_wayland->resource, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourceWayland *source_wayland =
|
||||||
|
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||||
|
|
||||||
|
wl_data_source_send_drop_performed (source_wayland->resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourceWayland *source_wayland =
|
||||||
|
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||||
|
|
||||||
|
wl_data_source_send_drag_finished (source_wayland->resource);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_source_finalize (GObject *object)
|
meta_wayland_source_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -623,6 +940,9 @@ meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *
|
|||||||
data_source_class->send = meta_wayland_source_send;
|
data_source_class->send = meta_wayland_source_send;
|
||||||
data_source_class->target = meta_wayland_source_target;
|
data_source_class->target = meta_wayland_source_target;
|
||||||
data_source_class->cancel = meta_wayland_source_cancel;
|
data_source_class->cancel = meta_wayland_source_cancel;
|
||||||
|
data_source_class->action = meta_wayland_source_action;
|
||||||
|
data_source_class->drop_performed = meta_wayland_source_drop_performed;
|
||||||
|
data_source_class->drag_finished = meta_wayland_source_drag_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -647,6 +967,7 @@ meta_wayland_data_source_init (MetaWaylandDataSource *source)
|
|||||||
meta_wayland_data_source_get_instance_private (source);
|
meta_wayland_data_source_get_instance_private (source);
|
||||||
|
|
||||||
wl_array_init (&priv->mime_types);
|
wl_array_init (&priv->mime_types);
|
||||||
|
priv->current_dnd_action = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -722,11 +1043,18 @@ meta_wayland_drag_dest_drop (MetaWaylandDataDevice *data_device,
|
|||||||
wl_data_device_send_drop (grab->drag_focus_data_device);
|
wl_data_device_send_drop (grab->drag_focus_data_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_drag_dest_update (MetaWaylandDataDevice *data_device,
|
||||||
|
MetaWaylandSurface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = {
|
static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = {
|
||||||
meta_wayland_drag_dest_focus_in,
|
meta_wayland_drag_dest_focus_in,
|
||||||
meta_wayland_drag_dest_focus_out,
|
meta_wayland_drag_dest_focus_out,
|
||||||
meta_wayland_drag_dest_motion,
|
meta_wayland_drag_dest_motion,
|
||||||
meta_wayland_drag_dest_drop
|
meta_wayland_drag_dest_drop,
|
||||||
|
meta_wayland_drag_dest_update
|
||||||
};
|
};
|
||||||
|
|
||||||
const MetaWaylandDragDestFuncs *
|
const MetaWaylandDragDestFuncs *
|
||||||
@@ -912,6 +1240,12 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
|||||||
MetaWaylandDataSource *source;
|
MetaWaylandDataSource *source;
|
||||||
|
|
||||||
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
|
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
|
||||||
|
|
||||||
|
if (focus_client == data_device->focus_client)
|
||||||
|
return;
|
||||||
|
|
||||||
|
data_device->focus_client = focus_client;
|
||||||
|
|
||||||
if (!focus_client)
|
if (!focus_client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -45,6 +45,11 @@ struct _MetaWaylandDataSourceClass
|
|||||||
void (* target) (MetaWaylandDataSource *source,
|
void (* target) (MetaWaylandDataSource *source,
|
||||||
const gchar *mime_type);
|
const gchar *mime_type);
|
||||||
void (* cancel) (MetaWaylandDataSource *source);
|
void (* cancel) (MetaWaylandDataSource *source);
|
||||||
|
|
||||||
|
void (* action) (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action);
|
||||||
|
void (* drop_performed) (MetaWaylandDataSource *source);
|
||||||
|
void (* drag_finished) (MetaWaylandDataSource *source);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWaylandDataDevice
|
struct _MetaWaylandDataDevice
|
||||||
@@ -55,6 +60,7 @@ struct _MetaWaylandDataDevice
|
|||||||
struct wl_listener selection_data_source_listener;
|
struct wl_listener selection_data_source_listener;
|
||||||
struct wl_list resource_list;
|
struct wl_list resource_list;
|
||||||
MetaWaylandDragGrab *current_grab;
|
MetaWaylandDragGrab *current_grab;
|
||||||
|
struct wl_client *focus_client;
|
||||||
|
|
||||||
struct wl_signal selection_ownership_signal;
|
struct wl_signal selection_ownership_signal;
|
||||||
struct wl_signal dnd_ownership_signal;
|
struct wl_signal dnd_ownership_signal;
|
||||||
@@ -94,6 +100,17 @@ void meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
|||||||
const gchar *mime_type,
|
const gchar *mime_type,
|
||||||
gint fd);
|
gint fd);
|
||||||
|
|
||||||
|
void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source);
|
||||||
|
|
||||||
|
uint32_t meta_wayland_data_source_get_actions (MetaWaylandDataSource *source);
|
||||||
|
uint32_t meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source);
|
||||||
|
uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source);
|
||||||
|
|
||||||
|
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||||
|
uint32_t dnd_actions);
|
||||||
|
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action);
|
||||||
|
|
||||||
const MetaWaylandDragDestFuncs *
|
const MetaWaylandDragDestFuncs *
|
||||||
meta_wayland_data_device_get_drag_dest_funcs (void);
|
meta_wayland_data_device_get_drag_dest_funcs (void);
|
||||||
|
|
||||||
|
@@ -63,6 +63,7 @@
|
|||||||
|
|
||||||
static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
|
static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
|
||||||
static void notify_modifiers (MetaWaylandKeyboard *keyboard);
|
static void notify_modifiers (MetaWaylandKeyboard *keyboard);
|
||||||
|
static guint evdev_code (const ClutterKeyEvent *event);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unbind_resource (struct wl_resource *resource)
|
unbind_resource (struct wl_resource *resource)
|
||||||
@@ -264,7 +265,7 @@ notify_key (MetaWaylandKeyboard *keyboard,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_modifiers (MetaWaylandKeyboard *keyboard)
|
apply_modifiers (MetaWaylandKeyboard *keyboard)
|
||||||
{
|
{
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
@@ -289,6 +290,16 @@ notify_modifiers (MetaWaylandKeyboard *keyboard)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notify_modifiers (MetaWaylandKeyboard *keyboard)
|
||||||
|
{
|
||||||
|
struct xkb_state *state;
|
||||||
|
|
||||||
|
state = keyboard->xkb_info.state;
|
||||||
|
keyboard->grab->interface->modifiers (keyboard->grab,
|
||||||
|
xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
|
meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
|
||||||
{
|
{
|
||||||
@@ -368,6 +379,33 @@ settings_changed (GSettings *settings,
|
|||||||
notify_key_repeat (keyboard);
|
notify_key_repeat (keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
default_grab_key (MetaWaylandKeyboardGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
MetaWaylandKeyboard *keyboard = grab->keyboard;
|
||||||
|
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
|
||||||
|
|
||||||
|
/* Synthetic key events are for autorepeat. Ignore those, as
|
||||||
|
* autorepeat in Wayland is done on the client side. */
|
||||||
|
if (event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return notify_key (keyboard, event->key.time, evdev_code (&event->key), is_press);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
default_grab_modifiers (MetaWaylandKeyboardGrab *grab,
|
||||||
|
ClutterModifierType modifiers)
|
||||||
|
{
|
||||||
|
apply_modifiers (grab->keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MetaWaylandKeyboardGrabInterface default_keyboard_grab_interface = {
|
||||||
|
default_grab_key,
|
||||||
|
default_grab_modifiers
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||||
struct wl_display *display)
|
struct wl_display *display)
|
||||||
@@ -385,6 +423,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
|||||||
|
|
||||||
keyboard->xkb_info.keymap_fd = -1;
|
keyboard->xkb_info.keymap_fd = -1;
|
||||||
|
|
||||||
|
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||||
|
keyboard->default_grab.keyboard = keyboard;
|
||||||
|
keyboard->grab = &keyboard->default_grab;
|
||||||
|
|
||||||
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
|
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
|
||||||
g_signal_connect (keyboard->settings, "changed",
|
g_signal_connect (keyboard->settings, "changed",
|
||||||
G_CALLBACK (settings_changed), keyboard);
|
G_CALLBACK (settings_changed), keyboard);
|
||||||
@@ -461,7 +503,7 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
|||||||
is_press ? "press" : "release",
|
is_press ? "press" : "release",
|
||||||
event->hardware_keycode);
|
event->hardware_keycode);
|
||||||
|
|
||||||
handled = notify_key (keyboard, event->time, evdev_code (event), is_press);
|
handled = keyboard->grab->interface->key (keyboard->grab, (const ClutterEvent *) event);
|
||||||
|
|
||||||
if (handled)
|
if (handled)
|
||||||
meta_verbose ("Sent event to wayland client\n");
|
meta_verbose ("Sent event to wayland client\n");
|
||||||
@@ -672,3 +714,18 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
|||||||
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
|
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
|
||||||
|
MetaWaylandKeyboardGrab *grab)
|
||||||
|
{
|
||||||
|
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||||
|
keyboard->grab = grab;
|
||||||
|
grab->keyboard = keyboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
|
||||||
|
{
|
||||||
|
keyboard->grab = &keyboard->default_grab;
|
||||||
|
}
|
||||||
|
@@ -49,6 +49,20 @@
|
|||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
struct _MetaWaylandKeyboardGrabInterface
|
||||||
|
{
|
||||||
|
gboolean (* key) (MetaWaylandKeyboardGrab *grab,
|
||||||
|
const ClutterEvent *event);
|
||||||
|
void (*modifiers) (MetaWaylandKeyboardGrab *grab,
|
||||||
|
ClutterModifierType modifiers);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaWaylandKeyboardGrab
|
||||||
|
{
|
||||||
|
const MetaWaylandKeyboardGrabInterface *interface;
|
||||||
|
MetaWaylandKeyboard *keyboard;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
@@ -72,6 +86,9 @@ struct _MetaWaylandKeyboard
|
|||||||
MetaWaylandXkbInfo xkb_info;
|
MetaWaylandXkbInfo xkb_info;
|
||||||
enum xkb_state_component mods_changed;
|
enum xkb_state_component mods_changed;
|
||||||
|
|
||||||
|
MetaWaylandKeyboardGrab *grab;
|
||||||
|
MetaWaylandKeyboardGrab default_grab;
|
||||||
|
|
||||||
GSettings *settings;
|
GSettings *settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -100,4 +117,9 @@ void meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
|||||||
struct wl_resource *seat_resource,
|
struct wl_resource *seat_resource,
|
||||||
uint32_t id);
|
uint32_t id);
|
||||||
|
|
||||||
|
void meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard,
|
||||||
|
MetaWaylandKeyboardGrab *grab);
|
||||||
|
void meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
|
||||||
|
|
||||||
|
|
||||||
#endif /* META_WAYLAND_KEYBOARD_H */
|
#endif /* META_WAYLAND_KEYBOARD_H */
|
||||||
|
@@ -2381,6 +2381,15 @@ meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface)
|
|||||||
surface->dnd.funcs->drop (data_device, surface);
|
surface->dnd.funcs->drop (data_device, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface)
|
||||||
|
{
|
||||||
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||||
|
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||||
|
|
||||||
|
surface->dnd.funcs->update (data_device, surface);
|
||||||
|
}
|
||||||
|
|
||||||
MetaWindow *
|
MetaWindow *
|
||||||
meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
|
meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
|
||||||
{
|
{
|
||||||
|
@@ -128,6 +128,8 @@ struct _MetaWaylandDragDestFuncs
|
|||||||
const ClutterEvent *event);
|
const ClutterEvent *event);
|
||||||
void (* drop) (MetaWaylandDataDevice *data_device,
|
void (* drop) (MetaWaylandDataDevice *data_device,
|
||||||
MetaWaylandSurface *surface);
|
MetaWaylandSurface *surface);
|
||||||
|
void (* update) (MetaWaylandDataDevice *data_device,
|
||||||
|
MetaWaylandSurface *surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWaylandSurface
|
struct _MetaWaylandSurface
|
||||||
@@ -240,6 +242,7 @@ void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface
|
|||||||
const ClutterEvent *event);
|
const ClutterEvent *event);
|
||||||
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
|
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
|
||||||
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
|
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
|
||||||
|
void meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface);
|
||||||
|
|
||||||
void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface);
|
void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface);
|
||||||
|
|
||||||
|
@@ -29,6 +29,8 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
|
|||||||
typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
|
typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
|
||||||
typedef struct _MetaWaylandPopup MetaWaylandPopup;
|
typedef struct _MetaWaylandPopup MetaWaylandPopup;
|
||||||
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
|
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
|
||||||
|
typedef struct _MetaWaylandKeyboardGrab MetaWaylandKeyboardGrab;
|
||||||
|
typedef struct _MetaWaylandKeyboardGrabInterface MetaWaylandKeyboardGrabInterface;
|
||||||
typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
||||||
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
||||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||||
#define META_WL_COMPOSITOR_VERSION 3
|
#define META_WL_COMPOSITOR_VERSION 3
|
||||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 2
|
#define META_WL_DATA_DEVICE_MANAGER_VERSION 3
|
||||||
#define META_XDG_SHELL_VERSION 1
|
#define META_XDG_SHELL_VERSION 1
|
||||||
#define META_WL_SHELL_VERSION 1
|
#define META_WL_SHELL_VERSION 1
|
||||||
#define META_WL_SEAT_VERSION 4
|
#define META_WL_SEAT_VERSION 4
|
||||||
|
@@ -108,6 +108,7 @@ enum {
|
|||||||
ATOM_DND_ACTION_MOVE,
|
ATOM_DND_ACTION_MOVE,
|
||||||
ATOM_DND_ACTION_COPY,
|
ATOM_DND_ACTION_COPY,
|
||||||
ATOM_DND_ACTION_ASK,
|
ATOM_DND_ACTION_ASK,
|
||||||
|
ATOM_DND_ACTION_PRIVATE,
|
||||||
N_DND_ATOMS
|
N_DND_ATOMS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,6 +127,7 @@ const gchar *atom_names[] = {
|
|||||||
"XdndActionMove",
|
"XdndActionMove",
|
||||||
"XdndActionCopy",
|
"XdndActionCopy",
|
||||||
"XdndActionAsk",
|
"XdndActionAsk",
|
||||||
|
"XdndActionPrivate",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,6 +137,19 @@ G_DEFINE_TYPE (MetaWaylandDataSourceXWayland, meta_wayland_data_source_xwayland,
|
|||||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||||
|
|
||||||
/* XDND helpers */
|
/* XDND helpers */
|
||||||
|
static Atom
|
||||||
|
action_to_atom (uint32_t action)
|
||||||
|
{
|
||||||
|
if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||||
|
return xdnd_atoms[ATOM_DND_ACTION_COPY];
|
||||||
|
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||||
|
return xdnd_atoms[ATOM_DND_ACTION_MOVE];
|
||||||
|
else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||||
|
return xdnd_atoms[ATOM_DND_ACTION_ASK];
|
||||||
|
else
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdnd_send_enter (MetaXWaylandSelection *selection_data,
|
xdnd_send_enter (MetaXWaylandSelection *selection_data,
|
||||||
Window dest)
|
Window dest)
|
||||||
@@ -217,10 +232,21 @@ xdnd_send_position (MetaXWaylandSelection *selection_data,
|
|||||||
int x,
|
int x,
|
||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||||
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
MetaSelectionBridge *selection = &selection_data->dnd.selection;
|
||||||
|
MetaWaylandDataSource *source = compositor->seat->data_device.dnd_data_source;
|
||||||
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
|
uint32_t action = 0, user_action, actions;
|
||||||
XEvent xev = { 0 };
|
XEvent xev = { 0 };
|
||||||
|
|
||||||
|
user_action = meta_wayland_data_source_get_user_action (source);
|
||||||
|
actions = meta_wayland_data_source_get_actions (source);
|
||||||
|
|
||||||
|
if (user_action & actions)
|
||||||
|
action = user_action;
|
||||||
|
if (!action)
|
||||||
|
action = actions;
|
||||||
|
|
||||||
xev.xclient.type = ClientMessage;
|
xev.xclient.type = ClientMessage;
|
||||||
xev.xclient.message_type = xdnd_atoms[ATOM_DND_POSITION];
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_POSITION];
|
||||||
xev.xclient.format = 32;
|
xev.xclient.format = 32;
|
||||||
@@ -230,7 +256,7 @@ xdnd_send_position (MetaXWaylandSelection *selection_data,
|
|||||||
xev.xclient.data.l[1] = 0;
|
xev.xclient.data.l[1] = 0;
|
||||||
xev.xclient.data.l[2] = (x << 16) | y;
|
xev.xclient.data.l[2] = (x << 16) | y;
|
||||||
xev.xclient.data.l[3] = time;
|
xev.xclient.data.l[3] = time;
|
||||||
xev.xclient.data.l[4] = xdnd_atoms[ATOM_DND_ACTION_COPY];
|
xev.xclient.data.l[4] = action_to_atom (action);
|
||||||
|
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
}
|
}
|
||||||
@@ -262,6 +288,8 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
|
|||||||
{
|
{
|
||||||
MetaDndBridge *selection = &selection_data->dnd;
|
MetaDndBridge *selection = &selection_data->dnd;
|
||||||
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
|
MetaWaylandDataSource *source = selection_data->dnd.selection.source;
|
||||||
|
uint32_t action = 0;
|
||||||
XEvent xev = { 0 };
|
XEvent xev = { 0 };
|
||||||
|
|
||||||
xev.xclient.type = ClientMessage;
|
xev.xclient.type = ClientMessage;
|
||||||
@@ -273,8 +301,9 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
|
|||||||
|
|
||||||
if (accepted)
|
if (accepted)
|
||||||
{
|
{
|
||||||
|
action = meta_wayland_data_source_get_current_action (source);
|
||||||
xev.xclient.data.l[1] = 1; /* Drop successful */
|
xev.xclient.data.l[1] = 1; /* Drop successful */
|
||||||
xev.xclient.data.l[2] = xdnd_atoms[ATOM_DND_ACTION_COPY];
|
xev.xclient.data.l[2] = action_to_atom (action);
|
||||||
}
|
}
|
||||||
|
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
@@ -283,7 +312,7 @@ xdnd_send_finished (MetaXWaylandSelection *selection_data,
|
|||||||
static void
|
static void
|
||||||
xdnd_send_status (MetaXWaylandSelection *selection_data,
|
xdnd_send_status (MetaXWaylandSelection *selection_data,
|
||||||
Window dest,
|
Window dest,
|
||||||
gboolean accepted)
|
uint32_t action)
|
||||||
{
|
{
|
||||||
MetaDndBridge *selection = &selection_data->dnd;
|
MetaDndBridge *selection = &selection_data->dnd;
|
||||||
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
@@ -296,12 +325,10 @@ xdnd_send_status (MetaXWaylandSelection *selection_data,
|
|||||||
|
|
||||||
xev.xclient.data.l[0] = selection->dnd_window;
|
xev.xclient.data.l[0] = selection->dnd_window;
|
||||||
xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */
|
xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */
|
||||||
|
xev.xclient.data.l[4] = action_to_atom (action);
|
||||||
|
|
||||||
if (accepted)
|
if (xev.xclient.data.l[4])
|
||||||
{
|
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
|
||||||
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
|
|
||||||
xev.xclient.data.l[4] = xdnd_atoms[ATOM_DND_ACTION_COPY];
|
|
||||||
}
|
|
||||||
|
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
}
|
}
|
||||||
@@ -387,6 +414,32 @@ x11_selection_data_free (X11SelectionData *data)
|
|||||||
g_slice_free (X11SelectionData, data);
|
g_slice_free (X11SelectionData, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x11_selection_data_send_finished (MetaSelectionBridge *selection,
|
||||||
|
gboolean success)
|
||||||
|
{
|
||||||
|
uint32_t action = meta_wayland_data_source_get_current_action (selection->source);
|
||||||
|
|
||||||
|
if (!selection->x11_selection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (success && action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||||
|
{
|
||||||
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
|
|
||||||
|
/* Request data deletion on the drag source */
|
||||||
|
XConvertSelection (xdisplay,
|
||||||
|
selection->selection_atom,
|
||||||
|
gdk_x11_get_xatom_by_name ("DELETE"),
|
||||||
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"),
|
||||||
|
selection->window,
|
||||||
|
CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
xdnd_send_finished (selection->x11_selection->selection_data,
|
||||||
|
selection->owner, success);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
x11_selection_data_finish (MetaSelectionBridge *selection,
|
x11_selection_data_finish (MetaSelectionBridge *selection,
|
||||||
gboolean success)
|
gboolean success)
|
||||||
@@ -395,13 +448,18 @@ x11_selection_data_finish (MetaSelectionBridge *selection,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (selection == &selection->x11_selection->selection_data->dnd.selection)
|
if (selection == &selection->x11_selection->selection_data->dnd.selection)
|
||||||
xdnd_send_finished (selection->x11_selection->selection_data,
|
x11_selection_data_send_finished (selection, success);
|
||||||
selection->owner, success);
|
|
||||||
|
|
||||||
g_clear_pointer (&selection->x11_selection,
|
g_clear_pointer (&selection->x11_selection,
|
||||||
(GDestroyNotify) x11_selection_data_free);
|
(GDestroyNotify) x11_selection_data_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x11_selection_data_close (X11SelectionData *data)
|
||||||
|
{
|
||||||
|
g_output_stream_close (data->stream, data->cancellable, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
x11_data_write_cb (GObject *object,
|
x11_data_write_cb (GObject *object,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -410,27 +468,34 @@ x11_data_write_cb (GObject *object,
|
|||||||
MetaSelectionBridge *selection = user_data;
|
MetaSelectionBridge *selection = user_data;
|
||||||
X11SelectionData *data = selection->x11_selection;
|
X11SelectionData *data = selection->x11_selection;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
gboolean success = TRUE;
|
||||||
|
|
||||||
g_output_stream_write_finish (G_OUTPUT_STREAM (object), res, &error);
|
g_output_stream_write_finish (G_OUTPUT_STREAM (object), res, &error);
|
||||||
|
|
||||||
if (data->incr)
|
if (error)
|
||||||
|
{
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
{
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warning ("Error writing from X11 selection: %s\n", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && data->incr)
|
||||||
{
|
{
|
||||||
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
XDeleteProperty (xdisplay, selection->window,
|
XDeleteProperty (xdisplay, selection->window,
|
||||||
gdk_x11_get_xatom_by_name ("_META_SELECTION"));
|
gdk_x11_get_xatom_by_name ("_META_SELECTION"));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (error)
|
|
||||||
{
|
{
|
||||||
if (error->domain != G_IO_ERROR ||
|
x11_selection_data_close (selection->x11_selection);
|
||||||
error->code != G_IO_ERROR_CANCELLED)
|
x11_selection_data_finish (selection, success);
|
||||||
g_warning ("Error writing from X11 selection: %s\n", error->message);
|
|
||||||
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data->incr)
|
|
||||||
x11_selection_data_finish (selection, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -687,6 +752,7 @@ meta_xwayland_selection_get_incr_chunk (MetaWaylandCompositor *compositor,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Transfer has completed */
|
/* Transfer has completed */
|
||||||
|
x11_selection_data_close (selection->x11_selection);
|
||||||
x11_selection_data_finish (selection, TRUE);
|
x11_selection_data_finish (selection, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,11 +801,15 @@ meta_x11_source_target (MetaWaylandDataSource *source,
|
|||||||
MetaWaylandDataSourceXWayland *source_xwayland =
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
||||||
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
||||||
MetaSelectionBridge *selection = source_xwayland->selection;
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
||||||
|
uint32_t action = 0;
|
||||||
|
|
||||||
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
||||||
{
|
{
|
||||||
|
if (mime_type)
|
||||||
|
action = meta_wayland_data_source_get_current_action (source);
|
||||||
|
|
||||||
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
||||||
selection->owner, mime_type != NULL);
|
selection->owner, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,10 +820,46 @@ meta_x11_source_cancel (MetaWaylandDataSource *source)
|
|||||||
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
||||||
MetaSelectionBridge *selection = source_xwayland->selection;
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
||||||
|
|
||||||
|
x11_selection_data_send_finished (selection, FALSE);
|
||||||
g_clear_pointer (&selection->x11_selection,
|
g_clear_pointer (&selection->x11_selection,
|
||||||
(GDestroyNotify) x11_selection_data_free);
|
(GDestroyNotify) x11_selection_data_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_x11_source_action (MetaWaylandDataSource *source,
|
||||||
|
uint32_t action)
|
||||||
|
{
|
||||||
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||||
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
||||||
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
||||||
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
||||||
|
|
||||||
|
if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
|
||||||
|
{
|
||||||
|
if (!meta_wayland_data_source_has_target (source))
|
||||||
|
action = 0;
|
||||||
|
|
||||||
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
||||||
|
selection->owner, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_x11_source_drop_performed (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_x11_source_drag_finished (MetaWaylandDataSource *source)
|
||||||
|
{
|
||||||
|
MetaWaylandDataSourceXWayland *source_xwayland =
|
||||||
|
META_WAYLAND_DATA_SOURCE_XWAYLAND (source);
|
||||||
|
MetaSelectionBridge *selection = source_xwayland->selection;
|
||||||
|
|
||||||
|
if (selection->x11_selection)
|
||||||
|
x11_selection_data_send_finished (selection, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland)
|
meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland)
|
||||||
{
|
{
|
||||||
@@ -768,6 +874,9 @@ meta_wayland_data_source_xwayland_class_init (MetaWaylandDataSourceXWaylandClass
|
|||||||
data_source_class->send = meta_x11_source_send;
|
data_source_class->send = meta_x11_source_send;
|
||||||
data_source_class->target = meta_x11_source_target;
|
data_source_class->target = meta_x11_source_target;
|
||||||
data_source_class->cancel = meta_x11_source_cancel;
|
data_source_class->cancel = meta_x11_source_cancel;
|
||||||
|
data_source_class->action = meta_x11_source_action;
|
||||||
|
data_source_class->drop_performed = meta_x11_source_drop_performed;
|
||||||
|
data_source_class->drag_finished = meta_x11_source_drag_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaWaylandDataSource *
|
static MetaWaylandDataSource *
|
||||||
@@ -831,11 +940,27 @@ meta_x11_drag_dest_drop (MetaWaylandDataDevice *data_device,
|
|||||||
meta_display_get_current_time_roundtrip (meta_get_display ()));
|
meta_display_get_current_time_roundtrip (meta_get_display ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_x11_drag_dest_update (MetaWaylandDataDevice *data_device,
|
||||||
|
MetaWaylandSurface *surface)
|
||||||
|
{
|
||||||
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||||
|
MetaWaylandSeat *seat = compositor->seat;
|
||||||
|
ClutterPoint pos;
|
||||||
|
|
||||||
|
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||||
|
xdnd_send_position (compositor->xwayland_manager.selection_data,
|
||||||
|
compositor->xwayland_manager.selection_data->dnd.dnd_dest,
|
||||||
|
clutter_get_current_event_time (),
|
||||||
|
pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
static const MetaWaylandDragDestFuncs meta_x11_drag_dest_funcs = {
|
static const MetaWaylandDragDestFuncs meta_x11_drag_dest_funcs = {
|
||||||
meta_x11_drag_dest_focus_in,
|
meta_x11_drag_dest_focus_in,
|
||||||
meta_x11_drag_dest_focus_out,
|
meta_x11_drag_dest_focus_out,
|
||||||
meta_x11_drag_dest_motion,
|
meta_x11_drag_dest_motion,
|
||||||
meta_x11_drag_dest_drop
|
meta_x11_drag_dest_drop,
|
||||||
|
meta_x11_drag_dest_update
|
||||||
};
|
};
|
||||||
|
|
||||||
const MetaWaylandDragDestFuncs *
|
const MetaWaylandDragDestFuncs *
|
||||||
@@ -1129,6 +1254,10 @@ meta_xwayland_selection_handle_selection_request (MetaWaylandCompositor *composi
|
|||||||
selection->timestamp);
|
selection->timestamp);
|
||||||
reply_selection_request (event, TRUE);
|
reply_selection_request (event, TRUE);
|
||||||
}
|
}
|
||||||
|
else if (data_source && event->target == gdk_x11_get_xatom_by_name ("DELETE"))
|
||||||
|
{
|
||||||
|
meta_wayland_data_source_notify_finish (data_source);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (data_source &&
|
if (data_source &&
|
||||||
@@ -1251,6 +1380,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
|
|||||||
if (event->window == dnd->selection.window)
|
if (event->window == dnd->selection.window)
|
||||||
{
|
{
|
||||||
MetaWaylandDataSource *data_source;
|
MetaWaylandDataSource *data_source;
|
||||||
|
uint32_t action = 0;
|
||||||
|
|
||||||
data_source = compositor->seat->data_device.dnd_data_source;
|
data_source = compositor->seat->data_device.dnd_data_source;
|
||||||
|
|
||||||
@@ -1263,6 +1393,19 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
|
|||||||
meta_wayland_data_source_set_has_target (data_source,
|
meta_wayland_data_source_set_has_target (data_source,
|
||||||
(event->data.l[1] & 1) != 0);
|
(event->data.l[1] & 1) != 0);
|
||||||
|
|
||||||
|
/* data.l[4] contains the action atom */
|
||||||
|
if (event->data.l[4])
|
||||||
|
{
|
||||||
|
if (((Atom) event->data.l[4]) == xdnd_atoms[ATOM_DND_ACTION_COPY] ||
|
||||||
|
((Atom) event->data.l[4]) == xdnd_atoms[ATOM_DND_ACTION_PRIVATE])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||||
|
else if (((Atom) event->data.l[4]) == xdnd_atoms[ATOM_DND_ACTION_MOVE])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||||
|
else if (((Atom) event->data.l[4]) == xdnd_atoms[ATOM_DND_ACTION_ASK])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_wayland_data_source_set_current_action (data_source, action);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (event->message_type == xdnd_atoms[ATOM_DND_FINISHED])
|
else if (event->message_type == xdnd_atoms[ATOM_DND_FINISHED])
|
||||||
@@ -1271,8 +1414,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
|
|||||||
if (compositor->seat->data_device.current_grab)
|
if (compositor->seat->data_device.current_grab)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device,
|
meta_wayland_data_source_notify_finish (data_source);
|
||||||
NULL);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1332,6 +1474,7 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
|
|||||||
{
|
{
|
||||||
ClutterEvent *motion;
|
ClutterEvent *motion;
|
||||||
ClutterPoint pos;
|
ClutterPoint pos;
|
||||||
|
uint32_t action = 0;
|
||||||
|
|
||||||
motion = clutter_event_new (CLUTTER_MOTION);
|
motion = clutter_event_new (CLUTTER_MOTION);
|
||||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||||
@@ -1340,11 +1483,19 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor
|
|||||||
clutter_event_set_source_device (motion, seat->pointer.device);
|
clutter_event_set_source_device (motion, seat->pointer.device);
|
||||||
clutter_event_set_time (motion, dnd->last_motion_time);
|
clutter_event_set_time (motion, dnd->last_motion_time);
|
||||||
|
|
||||||
|
if ((Atom) event->data.l[4] == xdnd_atoms[ATOM_DND_ACTION_COPY])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||||
|
else if ((Atom) event->data.l[4] == xdnd_atoms[ATOM_DND_ACTION_MOVE])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||||
|
else if ((Atom) event->data.l[4] == xdnd_atoms[ATOM_DND_ACTION_ASK])
|
||||||
|
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||||
|
|
||||||
|
meta_wayland_data_source_set_actions (dnd->selection.source, action);
|
||||||
|
|
||||||
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
|
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
|
||||||
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
xdnd_send_status (compositor->xwayland_manager.selection_data,
|
||||||
(Window) event->data.l[0],
|
(Window) event->data.l[0],
|
||||||
meta_wayland_data_source_has_target (
|
meta_wayland_data_source_get_current_action (dnd->selection.source));
|
||||||
dnd->selection.source));
|
|
||||||
|
|
||||||
clutter_event_free (motion);
|
clutter_event_free (motion);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
Reference in New Issue
Block a user