forked from AuroraMiddleware/gtk
x11: Implement gdk_drag_context_manage_dnd()
This includes managing input events and source-side DND events, as well as setting the appropriate cursor and emitting the signals that are expected in this mode of operation.
This commit is contained in:
parent
ed5da43afb
commit
bfee45e6f9
@ -89,6 +89,12 @@ struct _GdkX11DragContext
|
|||||||
|
|
||||||
GdkWindow *drag_window;
|
GdkWindow *drag_window;
|
||||||
|
|
||||||
|
GdkWindow *ipc_window;
|
||||||
|
GdkCursor *cursor;
|
||||||
|
GdkSeat *grab_seat;
|
||||||
|
GdkDragAction actions;
|
||||||
|
GdkDragAction current_action;
|
||||||
|
|
||||||
gint hot_x;
|
gint hot_x;
|
||||||
gint hot_y;
|
gint hot_y;
|
||||||
|
|
||||||
@ -106,6 +112,35 @@ struct _GdkX11DragContextClass
|
|||||||
GdkDragContextClass parent_class;
|
GdkDragContextClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gint keysym;
|
||||||
|
gint modifiers;
|
||||||
|
} GrabKey;
|
||||||
|
|
||||||
|
static GrabKey grab_keys[] = {
|
||||||
|
{ XK_Escape, 0 },
|
||||||
|
{ XK_space, 0 },
|
||||||
|
{ XK_KP_Space, 0 },
|
||||||
|
{ XK_Return, 0 },
|
||||||
|
{ XK_KP_Enter, 0 },
|
||||||
|
{ XK_Up, 0 },
|
||||||
|
{ XK_Up, Mod1Mask },
|
||||||
|
{ XK_Down, 0 },
|
||||||
|
{ XK_Down, Mod1Mask },
|
||||||
|
{ XK_Left, 0 },
|
||||||
|
{ XK_Left, Mod1Mask },
|
||||||
|
{ XK_Right, 0 },
|
||||||
|
{ XK_Right, Mod1Mask },
|
||||||
|
{ XK_KP_Up, 0 },
|
||||||
|
{ XK_KP_Up, Mod1Mask },
|
||||||
|
{ XK_KP_Down, 0 },
|
||||||
|
{ XK_KP_Down, Mod1Mask },
|
||||||
|
{ XK_KP_Left, 0 },
|
||||||
|
{ XK_KP_Left, Mod1Mask },
|
||||||
|
{ XK_KP_Right, 0 },
|
||||||
|
{ XK_KP_Right, Mod1Mask }
|
||||||
|
};
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
|
||||||
static GdkWindowCache *gdk_window_cache_get (GdkScreen *screen);
|
static GdkWindowCache *gdk_window_cache_get (GdkScreen *screen);
|
||||||
@ -135,6 +170,11 @@ static void xdnd_manage_source_filter (GdkDragContext *context,
|
|||||||
GdkWindow *window,
|
GdkWindow *window,
|
||||||
gboolean add_filter);
|
gboolean add_filter);
|
||||||
|
|
||||||
|
gboolean gdk_x11_drag_context_handle_event (GdkDragContext *context,
|
||||||
|
const GdkEvent *event);
|
||||||
|
void gdk_x11_drag_context_action_changed (GdkDragContext *context,
|
||||||
|
GdkDragAction action);
|
||||||
|
|
||||||
static GList *contexts;
|
static GList *contexts;
|
||||||
static GSList *window_caches;
|
static GSList *window_caches;
|
||||||
|
|
||||||
@ -195,6 +235,14 @@ static void gdk_x11_drag_context_set_hotspot (GdkDragContext *context,
|
|||||||
gint hot_y);
|
gint hot_y);
|
||||||
static void gdk_x11_drag_context_drop_done (GdkDragContext *context,
|
static void gdk_x11_drag_context_drop_done (GdkDragContext *context,
|
||||||
gboolean success);
|
gboolean success);
|
||||||
|
static gboolean gdk_x11_drag_context_manage_dnd (GdkDragContext *context,
|
||||||
|
GdkWindow *window,
|
||||||
|
GdkDragAction actions);
|
||||||
|
static void gdk_x11_drag_context_set_cursor (GdkDragContext *context,
|
||||||
|
GdkCursor *cursor);
|
||||||
|
static void gdk_x11_drag_context_cancel (GdkDragContext *context);
|
||||||
|
static void gdk_x11_drag_context_drop_performed (GdkDragContext *context,
|
||||||
|
guint32 time);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass)
|
gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass)
|
||||||
@ -216,6 +264,12 @@ gdk_x11_drag_context_class_init (GdkX11DragContextClass *klass)
|
|||||||
context_class->get_drag_window = gdk_x11_drag_context_get_drag_window;
|
context_class->get_drag_window = gdk_x11_drag_context_get_drag_window;
|
||||||
context_class->set_hotspot = gdk_x11_drag_context_set_hotspot;
|
context_class->set_hotspot = gdk_x11_drag_context_set_hotspot;
|
||||||
context_class->drop_done = gdk_x11_drag_context_drop_done;
|
context_class->drop_done = gdk_x11_drag_context_drop_done;
|
||||||
|
context_class->manage_dnd = gdk_x11_drag_context_manage_dnd;
|
||||||
|
context_class->set_cursor = gdk_x11_drag_context_set_cursor;
|
||||||
|
context_class->cancel = gdk_x11_drag_context_cancel;
|
||||||
|
context_class->drop_performed = gdk_x11_drag_context_drop_performed;
|
||||||
|
context_class->handle_event = gdk_x11_drag_context_handle_event;
|
||||||
|
context_class->action_changed = gdk_x11_drag_context_action_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2592,3 +2646,487 @@ gdk_x11_drag_context_drop_done (GdkDragContext *context,
|
|||||||
gdk_drag_anim_timeout, anim,
|
gdk_drag_anim_timeout, anim,
|
||||||
(GDestroyNotify) gdk_drag_anim_destroy);
|
(GDestroyNotify) gdk_drag_anim_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
drag_context_grab (GdkDragContext *context)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
GdkDevice *device = gdk_drag_context_get_device (context);
|
||||||
|
GdkWindow *root;
|
||||||
|
GdkSeat *seat;
|
||||||
|
gint keycode, i;
|
||||||
|
|
||||||
|
if (!x11_context->ipc_window)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
root = gdk_screen_get_root_window (gdk_window_get_screen (x11_context->ipc_window));
|
||||||
|
seat = gdk_device_get_seat (gdk_drag_context_get_device (context));
|
||||||
|
|
||||||
|
if (gdk_seat_grab (seat, x11_context->ipc_window,
|
||||||
|
GDK_SEAT_CAPABILITY_ALL, FALSE,
|
||||||
|
x11_context->cursor, NULL, NULL, NULL) != GDK_GRAB_SUCCESS)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_set_object (&x11_context->grab_seat, seat);
|
||||||
|
|
||||||
|
gdk_error_trap_push ();
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
|
||||||
|
{
|
||||||
|
keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
grab_keys[i].keysym);
|
||||||
|
if (keycode == NoSymbol)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef XINPUT_2
|
||||||
|
if (GDK_IS_X11_DEVICE_XI2 (device))
|
||||||
|
{
|
||||||
|
gint deviceid = gdk_x11_device_get_id (gdk_seat_get_keyboard (seat));
|
||||||
|
unsigned char mask[XIMaskLen(XI_LASTEVENT)];
|
||||||
|
XIGrabModifiers mods;
|
||||||
|
XIEventMask evmask;
|
||||||
|
gint num_mods;
|
||||||
|
|
||||||
|
memset (mask, 0, sizeof (mask));
|
||||||
|
XISetMask (mask, XI_KeyPress);
|
||||||
|
XISetMask (mask, XI_KeyRelease);
|
||||||
|
|
||||||
|
evmask.deviceid = deviceid;
|
||||||
|
evmask.mask_len = sizeof (mask);
|
||||||
|
evmask.mask = mask;
|
||||||
|
|
||||||
|
num_mods = 1;
|
||||||
|
mods.modifiers = grab_keys[i].modifiers;
|
||||||
|
|
||||||
|
XIGrabKeycode (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
deviceid,
|
||||||
|
keycode,
|
||||||
|
GDK_WINDOW_XID (root),
|
||||||
|
GrabModeAsync,
|
||||||
|
GrabModeAsync,
|
||||||
|
False,
|
||||||
|
&evmask,
|
||||||
|
num_mods,
|
||||||
|
&mods);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
XGrabKey (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
keycode, grab_keys[i].modifiers,
|
||||||
|
GDK_WINDOW_XID (root),
|
||||||
|
FALSE,
|
||||||
|
GrabModeAsync,
|
||||||
|
GrabModeAsync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
drag_context_ungrab (GdkDragContext *context)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
GdkDevice *keyboard;
|
||||||
|
GdkWindow *root;
|
||||||
|
gint keycode, i;
|
||||||
|
|
||||||
|
if (!x11_context->grab_seat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_seat_ungrab (x11_context->grab_seat);
|
||||||
|
|
||||||
|
keyboard = gdk_seat_get_keyboard (x11_context->grab_seat);
|
||||||
|
root = gdk_screen_get_root_window (gdk_window_get_screen (x11_context->ipc_window));
|
||||||
|
g_clear_object (&x11_context->grab_seat);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
|
||||||
|
{
|
||||||
|
keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
grab_keys[i].keysym);
|
||||||
|
if (keycode == NoSymbol)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef XINPUT_2
|
||||||
|
if (GDK_IS_X11_DEVICE_XI2 (keyboard))
|
||||||
|
{
|
||||||
|
XIGrabModifiers mods;
|
||||||
|
gint num_mods;
|
||||||
|
|
||||||
|
num_mods = 1;
|
||||||
|
mods.modifiers = grab_keys[i].modifiers;
|
||||||
|
|
||||||
|
XIUngrabKeycode (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
gdk_x11_device_get_id (keyboard),
|
||||||
|
keycode,
|
||||||
|
GDK_WINDOW_XID (root),
|
||||||
|
num_mods,
|
||||||
|
&mods);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* XINPUT_2 */
|
||||||
|
{
|
||||||
|
XUngrabKey (GDK_WINDOW_XDISPLAY (x11_context->ipc_window),
|
||||||
|
keycode, grab_keys[i].modifiers,
|
||||||
|
GDK_WINDOW_XID (root));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_x11_drag_context_manage_dnd (GdkDragContext *context,
|
||||||
|
GdkWindow *ipc_window,
|
||||||
|
GdkDragAction actions)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
|
||||||
|
if (x11_context->ipc_window)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
context->protocol = GDK_DRAG_PROTO_XDND;
|
||||||
|
x11_context->ipc_window = g_object_ref (ipc_window);
|
||||||
|
|
||||||
|
if (drag_context_grab (context))
|
||||||
|
{
|
||||||
|
x11_context->actions = actions;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_object (&x11_context->ipc_window);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_drag_context_set_cursor (GdkDragContext *context,
|
||||||
|
GdkCursor *cursor)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
|
||||||
|
if (!g_set_object (&x11_context->cursor, cursor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (x11_context->grab_seat)
|
||||||
|
{
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||||
|
gdk_device_grab (gdk_seat_get_pointer (x11_context->grab_seat),
|
||||||
|
x11_context->ipc_window,
|
||||||
|
GDK_OWNERSHIP_APPLICATION, FALSE,
|
||||||
|
GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||||
|
cursor, GDK_CURRENT_TIME);
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_drag_context_cancel (GdkDragContext *context)
|
||||||
|
{
|
||||||
|
drag_context_ungrab (context);
|
||||||
|
gdk_drag_drop_done (context, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_drag_context_drop_performed (GdkDragContext *context,
|
||||||
|
guint32 time_)
|
||||||
|
{
|
||||||
|
drag_context_ungrab (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BIG_STEP 20
|
||||||
|
#define SMALL_STEP 1
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_drag_get_current_actions (GdkModifierType state,
|
||||||
|
gint button,
|
||||||
|
GdkDragAction actions,
|
||||||
|
GdkDragAction *suggested_action,
|
||||||
|
GdkDragAction *possible_actions)
|
||||||
|
{
|
||||||
|
*suggested_action = 0;
|
||||||
|
*possible_actions = 0;
|
||||||
|
|
||||||
|
if ((button == GDK_BUTTON_MIDDLE || button == GDK_BUTTON_SECONDARY) && (actions & GDK_ACTION_ASK))
|
||||||
|
{
|
||||||
|
*suggested_action = GDK_ACTION_ASK;
|
||||||
|
*possible_actions = actions;
|
||||||
|
}
|
||||||
|
else if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
|
||||||
|
{
|
||||||
|
if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
|
||||||
|
{
|
||||||
|
if (actions & GDK_ACTION_LINK)
|
||||||
|
{
|
||||||
|
*suggested_action = GDK_ACTION_LINK;
|
||||||
|
*possible_actions = GDK_ACTION_LINK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state & GDK_CONTROL_MASK)
|
||||||
|
{
|
||||||
|
if (actions & GDK_ACTION_COPY)
|
||||||
|
{
|
||||||
|
*suggested_action = GDK_ACTION_COPY;
|
||||||
|
*possible_actions = GDK_ACTION_COPY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (actions & GDK_ACTION_MOVE)
|
||||||
|
{
|
||||||
|
*suggested_action = GDK_ACTION_MOVE;
|
||||||
|
*possible_actions = GDK_ACTION_MOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*possible_actions = actions;
|
||||||
|
|
||||||
|
if ((state & (GDK_MOD1_MASK)) && (actions & GDK_ACTION_ASK))
|
||||||
|
*suggested_action = GDK_ACTION_ASK;
|
||||||
|
else if (actions & GDK_ACTION_COPY)
|
||||||
|
*suggested_action = GDK_ACTION_COPY;
|
||||||
|
else if (actions & GDK_ACTION_MOVE)
|
||||||
|
*suggested_action = GDK_ACTION_MOVE;
|
||||||
|
else if (actions & GDK_ACTION_LINK)
|
||||||
|
*suggested_action = GDK_ACTION_LINK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_drag_update (GdkDragContext *context,
|
||||||
|
gdouble x_root,
|
||||||
|
gdouble y_root,
|
||||||
|
GdkModifierType mods,
|
||||||
|
guint32 evtime)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
GdkDragAction action, possible_actions;
|
||||||
|
GdkWindow *dest_window;
|
||||||
|
GdkDragProtocol protocol;
|
||||||
|
|
||||||
|
gdk_drag_get_current_actions (mods, GDK_BUTTON_PRIMARY, x11_context->actions,
|
||||||
|
&action, &possible_actions);
|
||||||
|
|
||||||
|
gdk_drag_find_window_for_screen (context,
|
||||||
|
x11_context->drag_window,
|
||||||
|
gdk_display_get_default_screen (gdk_display_get_default ()),
|
||||||
|
x_root, y_root, &dest_window, &protocol);
|
||||||
|
|
||||||
|
gdk_drag_motion (context, dest_window, protocol, x_root, y_root,
|
||||||
|
action, possible_actions, evtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_dnd_handle_motion_event (GdkDragContext *context,
|
||||||
|
const GdkEventMotion *event)
|
||||||
|
{
|
||||||
|
GdkModifierType state;
|
||||||
|
|
||||||
|
if (!gdk_event_get_state ((GdkEvent *) event, &state))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gdk_drag_update (context, event->x_root, event->y_root, state,
|
||||||
|
gdk_event_get_time ((GdkEvent *) event));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_dnd_handle_key_event (GdkDragContext *context,
|
||||||
|
const GdkEventKey *event)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
GdkModifierType state;
|
||||||
|
GdkWindow *root_window;
|
||||||
|
GdkDevice *pointer;
|
||||||
|
gint dx, dy;
|
||||||
|
|
||||||
|
dx = dy = 0;
|
||||||
|
state = event->state;
|
||||||
|
pointer = gdk_device_get_associated_device (gdk_event_get_device ((GdkEvent *) event));
|
||||||
|
|
||||||
|
if (event->type == GDK_KEY_PRESS)
|
||||||
|
{
|
||||||
|
switch (event->keyval)
|
||||||
|
{
|
||||||
|
case GDK_KEY_Escape:
|
||||||
|
gdk_drag_context_cancel (context);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case GDK_KEY_space:
|
||||||
|
case GDK_KEY_Return:
|
||||||
|
case GDK_KEY_ISO_Enter:
|
||||||
|
case GDK_KEY_KP_Enter:
|
||||||
|
case GDK_KEY_KP_Space:
|
||||||
|
if ((gdk_drag_context_get_selected_action (context) != 0) &&
|
||||||
|
(gdk_drag_context_get_dest_window (context) != NULL))
|
||||||
|
{
|
||||||
|
g_signal_emit_by_name (context, "drop-performed",
|
||||||
|
gdk_event_get_time ((GdkEvent *) event));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdk_drag_context_cancel (context);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case GDK_KEY_Up:
|
||||||
|
case GDK_KEY_KP_Up:
|
||||||
|
dy = (state & GDK_MOD1_MASK) ? -BIG_STEP : -SMALL_STEP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Down:
|
||||||
|
case GDK_KEY_KP_Down:
|
||||||
|
dy = (state & GDK_MOD1_MASK) ? BIG_STEP : SMALL_STEP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Left:
|
||||||
|
case GDK_KEY_KP_Left:
|
||||||
|
dx = (state & GDK_MOD1_MASK) ? -BIG_STEP : -SMALL_STEP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Right:
|
||||||
|
case GDK_KEY_KP_Right:
|
||||||
|
dx = (state & GDK_MOD1_MASK) ? BIG_STEP : SMALL_STEP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The state is not yet updated in the event, so we need
|
||||||
|
* to query it here. We could use XGetModifierMapping, but
|
||||||
|
* that would be overkill.
|
||||||
|
*/
|
||||||
|
root_window = gdk_screen_get_root_window (gdk_window_get_screen (x11_context->ipc_window));
|
||||||
|
gdk_window_get_device_position (root_window, pointer, NULL, NULL, &state);
|
||||||
|
|
||||||
|
if (dx != 0 || dy != 0)
|
||||||
|
{
|
||||||
|
x11_context->last_x += dx;
|
||||||
|
x11_context->last_y += dy;
|
||||||
|
gdk_device_warp (pointer,
|
||||||
|
gdk_window_get_screen (x11_context->ipc_window),
|
||||||
|
x11_context->last_x, x11_context->last_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_drag_update (context, x11_context->last_x, x11_context->last_y, state,
|
||||||
|
gdk_event_get_time ((GdkEvent *) event));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_dnd_handle_grab_broken_event (GdkDragContext *context,
|
||||||
|
const GdkEventGrabBroken *event)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
|
||||||
|
/* Don't cancel if we break the implicit grab from the initial button_press.
|
||||||
|
* Also, don't cancel if we re-grab on the widget or on our IPC window, for
|
||||||
|
* example, when changing the drag cursor.
|
||||||
|
*/
|
||||||
|
if (event->implicit ||
|
||||||
|
event->grab_window == x11_context->drag_window ||
|
||||||
|
event->grab_window == x11_context->ipc_window)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gdk_drag_context_cancel (context);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_dnd_handle_button_event (GdkDragContext *context,
|
||||||
|
const GdkEventButton *event)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* FIXME: Check the button matches */
|
||||||
|
if (event->button != x11_context->button)
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((gdk_drag_context_get_selected_action (context) != 0) &&
|
||||||
|
(gdk_drag_context_get_dest_window (context) != NULL))
|
||||||
|
{
|
||||||
|
g_signal_emit_by_name (context, "drop-performed",
|
||||||
|
gdk_event_get_time ((GdkEvent *) event));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdk_drag_context_cancel (context);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdk_dnd_handle_drag_status (GdkDragContext *context,
|
||||||
|
const GdkEventDND *event)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *context_x11 = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
GdkDragAction action;
|
||||||
|
|
||||||
|
if (context != event->context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
action = gdk_drag_context_get_selected_action (context);
|
||||||
|
|
||||||
|
if (action != context_x11->current_action)
|
||||||
|
{
|
||||||
|
context_x11->current_action = action;
|
||||||
|
g_signal_emit_by_name (context, "action-changed", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_dnd_handle_drop_finished (GdkDragContext *context,
|
||||||
|
const GdkEventDND *event)
|
||||||
|
{
|
||||||
|
if (context != event->context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_signal_emit_by_name (context, "dnd-finished");
|
||||||
|
gdk_drag_drop_done (context, TRUE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdk_x11_drag_context_handle_event (GdkDragContext *context,
|
||||||
|
const GdkEvent *event)
|
||||||
|
{
|
||||||
|
GdkX11DragContext *x11_context = GDK_X11_DRAG_CONTEXT (context);
|
||||||
|
|
||||||
|
if (!context->is_source)
|
||||||
|
return FALSE;
|
||||||
|
if (!x11_context->grab_seat && event->type != GDK_DROP_FINISHED)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case GDK_MOTION_NOTIFY:
|
||||||
|
return gdk_dnd_handle_motion_event (context, &event->motion);
|
||||||
|
case GDK_BUTTON_RELEASE:
|
||||||
|
return gdk_dnd_handle_button_event (context, &event->button);
|
||||||
|
case GDK_KEY_PRESS:
|
||||||
|
case GDK_KEY_RELEASE:
|
||||||
|
return gdk_dnd_handle_key_event (context, &event->key);
|
||||||
|
case GDK_GRAB_BROKEN:
|
||||||
|
return gdk_dnd_handle_grab_broken_event (context, &event->grab_broken);
|
||||||
|
case GDK_DRAG_STATUS:
|
||||||
|
return gdk_dnd_handle_drag_status (context, &event->dnd);
|
||||||
|
case GDK_DROP_FINISHED:
|
||||||
|
return gdk_dnd_handle_drop_finished (context, &event->dnd);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdk_x11_drag_context_action_changed (GdkDragContext *context,
|
||||||
|
GdkDragAction action)
|
||||||
|
{
|
||||||
|
GdkCursor *cursor;
|
||||||
|
|
||||||
|
cursor = gdk_drag_get_cursor (action);
|
||||||
|
gdk_drag_context_set_cursor (context, cursor);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user