Add vtables for DND

This commit hides GdkDragContext and GdkDragContextClass, adds
vfuncs for most drag context functionality, and turns the X11 DND
implementation into GdkDragContextX11. We also add vfuncs to
GdkDisplay for gdk_drag_get_protocol and to GdkWindow for
gdk_drag_begin, and implemenet them for X11.
Other backends need similar treatment and are broken now.
This commit is contained in:
Matthias Clasen 2010-12-10 01:27:10 -05:00
parent 3c47c8467c
commit c53ec081ce
11 changed files with 924 additions and 935 deletions

View File

@ -2242,3 +2242,25 @@ gdk_display_get_app_launch_context (GdkDisplay *display)
{
return GDK_DISPLAY_GET_CLASS(display)->get_app_launch_context (display);
}
/**
* gdk_drag_get_protocol_for_display:
* @display: the #GdkDisplay where the destination window resides
* @xid: the windowing system id of the destination window.
* @protocol: location where the supported DND protocol is returned.
*
* Finds out the DND protocol supported by a window.
*
* Return value: the windowing system id of the window where the drop
* should happen. This may be @xid or the id of a proxy window,
* or zero if @xid does not support Drag and Drop.
*
* Since: 2.2
*/
GdkNativeWindow
gdk_drag_get_protocol_for_display (GdkDisplay *display,
GdkNativeWindow xid,
GdkDragProtocol *protocol)
{
return GDK_DISPLAY_GET_CLASS (display)->get_drag_protocol (display, xid, protocol, NULL);
}

View File

@ -27,7 +27,7 @@
#include "config.h"
#include "gdkdnd.h"
#include "gdkinternals.h"
#include "gdkdisplay.h"
#include "gdkwindow.h"
@ -48,53 +48,6 @@
* the GTK+ documentation for more information.
*/
/**
* gdk_drag_find_window:
* @context: a #GdkDragContext.
* @drag_window: a window which may be at the pointer position, but
* should be ignored, since it is put up by the drag source as an icon.
* @x_root: the x position of the pointer in root coordinates.
* @y_root: the y position of the pointer in root coordinates.
* @dest_window: (out): location to store the destination window in.
* @protocol: (out): location to store the DND protocol in.
*
* Finds the destination window and DND protocol to use at the
* given pointer position.
*
* This function is called by the drag source to obtain the
* @dest_window and @protocol parameters for gdk_drag_motion().
**/
void
gdk_drag_find_window (GdkDragContext *context,
GdkWindow *drag_window,
gint x_root,
gint y_root,
GdkWindow **dest_window,
GdkDragProtocol *protocol)
{
gdk_drag_find_window_for_screen (context, drag_window,
gdk_window_get_screen (context->source_window),
x_root, y_root, dest_window, protocol);
}
/**
* gdk_drag_get_protocol:
* @xid: the windowing system id of the destination window.
* @protocol: location where the supported DND protocol is returned.
*
* Finds out the DND protocol supported by a window.
*
* Return value: the windowing system specific id for the window where
* the drop should happen. This may be @xid or the id of a proxy
* window, or zero if @xid doesn't support Drag and Drop.
**/
GdkNativeWindow
gdk_drag_get_protocol (GdkNativeWindow xid,
GdkDragProtocol *protocol)
{
return gdk_drag_get_protocol_for_display (gdk_display_get_default (), xid, protocol);
}
/**
* gdk_drag_context_list_targets:
* @context: a #GdkDragContext
@ -222,3 +175,283 @@ gdk_drag_context_get_protocol (GdkDragContext *context)
return context->protocol;
}
/**
* gdk_drag_context_set_device:
* @context: a #GdkDragContext
* @device: a #GdkDevice
*
* Associates a #GdkDevice to @context, so all Drag and Drop events
* for @context are emitted as if they came from this device.
*/
void
gdk_drag_context_set_device (GdkDragContext *context,
GdkDevice *device)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
g_return_if_fail (GDK_IS_DEVICE (device));
if (context->device)
g_object_unref (context->device);
context->device = device;
if (context->device)
g_object_ref (context->device);
}
/**
* gdk_drag_context_get_device:
* @context: a #GdkDragContext
*
* Returns the #GdkDevice associated to the drag context.
*
* Returns: (transfer none): The #GdkDevice associated to @context.
**/
GdkDevice *
gdk_drag_context_get_device (GdkDragContext *context)
{
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
return context->device;
}
G_DEFINE_TYPE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
static void
gdk_drag_context_init (GdkDragContext *context)
{
}
static void
gdk_drag_context_finalize (GObject *object)
{
GdkDragContext *context = GDK_DRAG_CONTEXT (object);
g_list_free (context->targets);
if (context->source_window)
g_object_unref (context->source_window);
if (context->dest_window)
g_object_unref (context->dest_window);
G_OBJECT_CLASS (gdk_drag_context_parent_class)->finalize (object);
}
static void
gdk_drag_context_class_init (GdkDragContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_drag_context_finalize;
}
/**
* gdk_drag_find_window_for_screen:
* @context: a #GdkDragContext
* @drag_window: a window which may be at the pointer position, but
* should be ignored, since it is put up by the drag source as an icon
* @screen: the screen where the destination window is sought
* @x_root: the x position of the pointer in root coordinates
* @y_root: the y position of the pointer in root coordinates
* @dest_window: (out): location to store the destination window in
* @protocol: (out): location to store the DND protocol in
*
* Finds the destination window and DND protocol to use at the
* given pointer position.
*
* This function is called by the drag source to obtain the
* @dest_window and @protocol parameters for gdk_drag_motion().
*
* Since: 2.2
*/
void
gdk_drag_find_window_for_screen (GdkDragContext *context,
GdkWindow *drag_window,
GdkScreen *screen,
gint x_root,
gint y_root,
GdkWindow **dest_window,
GdkDragProtocol *protocol)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
*dest_window = GDK_DRAG_CONTEXT_GET_CLASS (context)
->find_window (context, drag_window, screen, x_root, y_root, protocol);
}
/**
* gdk_drag_status:
* @context: a #GdkDragContext
* @action: the selected action which will be taken when a drop happens,
* or 0 to indicate that a drop will not be accepted
* @time_: the timestamp for this operation
*
* Selects one of the actions offered by the drag source.
*
* This function is called by the drag destination in response to
* gdk_drag_motion() called by the drag source.
*/
void
gdk_drag_status (GdkDragContext *context,
GdkDragAction action,
guint32 time_)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_DRAG_CONTEXT_GET_CLASS (context)->drag_status (context, action, time_);
}
/**
* gdk_drag_motion:
* @context: a #GdkDragContext
* @dest_window: the new destination window, obtained by
* gdk_drag_find_window()
* @protocol: the DND protocol in use, obtained by gdk_drag_find_window()
* @x_root: the x position of the pointer in root coordinates
* @y_root: the y position of the pointer in root coordinates
* @suggested_action: the suggested action
* @possible_actions: the possible actions
* @time_: the timestamp for this operation
*
* Updates the drag context when the pointer moves or the
* set of actions changes.
*
* This function is called by the drag source.
*/
gboolean
gdk_drag_motion (GdkDragContext *context,
GdkWindow *dest_window,
GdkDragProtocol protocol,
gint x_root,
gint y_root,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 time_)
{
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), FALSE);
return GDK_DRAG_CONTEXT_GET_CLASS (context)
->drag_motion (context,
dest_window,
protocol,
x_root,
y_root,
suggested_action,
possible_actions,
time_);
}
/**
* gdk_drag_abort:
* @context: a #GdkDragContext
* @time_: the timestamp for this operation
*
* Aborts a drag without dropping.
*
* This function is called by the drag source.
*/
void
gdk_drag_abort (GdkDragContext *context,
guint32 time_)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_DRAG_CONTEXT_GET_CLASS (context)->drag_abort (context, time_);
}
/**
* gdk_drag_drop:
* @context: a #GdkDragContext
* @time_: the timestamp for this operation
*
* Drops on the current destination.
*
* This function is called by the drag source.
*/
void
gdk_drag_drop (GdkDragContext *context,
guint32 time_)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_DRAG_CONTEXT_GET_CLASS (context)->drag_drop (context, time_);
}
/**
* gdk_drop_reply:
* @context: a #GdkDragContext
* @accepted: %TRUE if the drop is accepted
* @time_: the timestamp for this operation
*
* Accepts or rejects a drop.
*
* This function is called by the drag destination in response
* to a drop initiated by the drag source.
*/
void
gdk_drop_reply (GdkDragContext *context,
gboolean accepted,
guint32 time_)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_reply (context, accepted, time_);
}
/**
* gdk_drop_finish:
* @context: a #GtkDragContext
* @success: %TRUE if the data was successfully received
* @time_: the timestamp for this operation
*
* Ends the drag operation after a drop.
*
* This function is called by the drag destination.
*/
void
gdk_drop_finish (GdkDragContext *context,
gboolean success,
guint32 time_)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_finish (context, success, time_);
}
/**
* gdk_drag_drop_succeeded:
* @context: a #GdkDragContext
*
* Returns whether the dropped data has been successfully
* transferred. This function is intended to be used while
* handling a %GDK_DROP_FINISHED event, its return value is
* meaningless at other times.
*
* Return value: %TRUE if the drop was successful.
*
* Since: 2.6
**/
gboolean
gdk_drag_drop_succeeded (GdkDragContext *context)
{
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), FALSE);
return GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_status (context);
}
/**
* gdk_drag_get_selection:
* @context: a #GdkDragContext.
*
* Returns the selection atom for the current source window.
*
* Return value: the selection atom, or %GDK_NONE
*/
GdkAtom
gdk_drag_get_selection (GdkDragContext *context)
{
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_NONE);
return GDK_DRAG_CONTEXT_GET_CLASS (context)->get_selection (context);
}

View File

@ -36,7 +36,11 @@
G_BEGIN_DECLS
/* Object that holds information about a drag in progress.
* this is used on both source and destination sides.
*/
typedef struct _GdkDragContext GdkDragContext;
typedef struct _GdkDragContextClass GdkDragContextClass;
/**
* GdkDragAction:
@ -81,19 +85,13 @@ typedef enum
{
GDK_DRAG_PROTO_MOTIF,
GDK_DRAG_PROTO_XDND,
GDK_DRAG_PROTO_ROOTWIN, /* A root window with nobody claiming
* drags */
GDK_DRAG_PROTO_NONE, /* Not a valid drag window */
GDK_DRAG_PROTO_WIN32_DROPFILES, /* The simple WM_DROPFILES dnd */
GDK_DRAG_PROTO_OLE2, /* The complex OLE2 dnd (not implemented) */
GDK_DRAG_PROTO_LOCAL /* Intra-app */
GDK_DRAG_PROTO_ROOTWIN,
GDK_DRAG_PROTO_NONE,
GDK_DRAG_PROTO_WIN32_DROPFILES,
GDK_DRAG_PROTO_OLE2,
GDK_DRAG_PROTO_LOCAL
} GdkDragProtocol;
/* Object that holds information about a drag in progress.
* this is used on both source and destination sides.
*/
typedef struct _GdkDragContextClass GdkDragContextClass;
#define GDK_TYPE_DRAG_CONTEXT (gdk_drag_context_get_type ())
#define GDK_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAG_CONTEXT, GdkDragContext))
@ -102,39 +100,8 @@ typedef struct _GdkDragContextClass GdkDragContextClass;
#define GDK_IS_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAG_CONTEXT))
#define GDK_DRAG_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAG_CONTEXT, GdkDragContextClass))
struct _GdkDragContext {
GObject parent_instance;
/*< public >*/
GdkDragProtocol GSEAL (protocol);
gboolean GSEAL (is_source);
GdkWindow *GSEAL (source_window);
GdkWindow *GSEAL (dest_window);
GList *GSEAL (targets);
GdkDragAction GSEAL (actions);
GdkDragAction GSEAL (suggested_action);
GdkDragAction GSEAL (action);
guint32 GSEAL (start_time);
/*< private >*/
gpointer GSEAL (windowing_data);
};
struct _GdkDragContextClass {
GObjectClass parent_class;
};
/* Drag and Drop */
GType gdk_drag_context_get_type (void) G_GNUC_CONST;
GdkDragContext * gdk_drag_context_new (void);
GType gdk_drag_context_get_type (void) G_GNUC_CONST;
void gdk_drag_context_set_device (GdkDragContext *context,
GdkDevice *device);
@ -164,8 +131,12 @@ GdkAtom gdk_drag_get_selection (GdkDragContext *context);
/* Source side */
GdkDragContext * gdk_drag_begin (GdkWindow *window,
GList *targets);
GdkDragContext * gdk_drag_begin (GdkWindow *window,
GList *targets);
GdkDragContext * gdk_drag_begin_for_device (GdkWindow *window,
GdkDevice *device,
GList *targets);
GdkNativeWindow gdk_drag_get_protocol_for_display (GdkDisplay *display,
GdkNativeWindow xid,
@ -179,18 +150,6 @@ void gdk_drag_find_window_for_screen (GdkDragContext *context,
GdkWindow **dest_window,
GdkDragProtocol *protocol);
#ifndef GDK_MULTIHEAD_SAFE
GdkNativeWindow gdk_drag_get_protocol (GdkNativeWindow xid,
GdkDragProtocol *protocol);
void gdk_drag_find_window (GdkDragContext *context,
GdkWindow *drag_window,
gint x_root,
gint y_root,
GdkWindow **dest_window,
GdkDragProtocol *protocol);
#endif /* GDK_MULTIHEAD_SAFE */
gboolean gdk_drag_motion (GdkDragContext *context,
GdkWindow *dest_window,
GdkDragProtocol protocol,

View File

@ -305,6 +305,10 @@ struct _GdkDisplayClass
GdkFilterFunc func,
gpointer data);
GdkAppLaunchContext * (*get_app_launch_context) (GdkDisplay *display);
GdkNativeWindow (*get_drag_protocol) (GdkDisplay *display,
GdkNativeWindow winid,
GdkDragProtocol *protocol,
guint *version);
/* Signals */
@ -409,6 +413,59 @@ struct _GdkScreenClass
void (*monitors_changed) (GdkScreen *screen);
};
struct _GdkDragContextClass {
GObjectClass parent_class;
GdkWindow * (*find_window) (GdkDragContext *context,
GdkWindow *drag_window,
GdkScreen *screen,
gint x_root,
gint y_root,
GdkDragProtocol *protocol);
GdkAtom (*get_selection) (GdkDragContext *context);
gboolean (*drag_motion) (GdkDragContext *context,
GdkWindow *dest_window,
GdkDragProtocol protocol,
gint root_x,
gint root_y,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 time_);
void (*drag_status) (GdkDragContext *context,
GdkDragAction action,
guint32 time_);
void (*drag_abort) (GdkDragContext *context,
guint32 time_);
void (*drag_drop) (GdkDragContext *context,
guint32 time_);
void (*drop_reply) (GdkDragContext *context,
gboolean accept,
guint32 time_);
void (*drop_finish) (GdkDragContext *context,
gboolean success,
guint32 time_);
gboolean (*drop_status) (GdkDragContext *context);
};
struct _GdkDragContext {
GObject parent_instance;
GdkDragProtocol protocol;
gboolean is_source;
GdkWindow *source_window;
GdkWindow *dest_window;
GList *targets;
GdkDragAction actions;
GdkDragAction suggested_action;
GdkDragAction action;
guint32 start_time;
GdkDevice *device;
};
extern GSList *_gdk_displays;
extern gchar *_gdk_display_name;
extern gint _gdk_screen_number;

View File

@ -10686,6 +10686,39 @@ gdk_window_register_dnd (GdkWindow *window)
GDK_WINDOW_IMPL_GET_CLASS (window->impl)->register_dnd (window);
}
/**
* gdk_drag_begin:
* @window: the source window for this drag.
* @targets: (transfer none) (element-type GdkAtom): the offered targets,
* as list of #GdkAtom<!-- -->s
*
* Starts a drag and creates a new drag context for it.
*
* This function is called by the drag source.
*
* Return value: (transfer full): a newly created #GdkDragContext.
*/
GdkDragContext *
gdk_drag_begin (GdkWindow *window,
GList *targets)
{
GdkDeviceManager *device_manager;
GdkDevice *device;
device_manager = gdk_display_get_device_manager (gdk_window_get_display (window));
device = gdk_device_manager_get_client_pointer (device_manager);
return gdk_drag_begin_for_device (window, device, targets);
}
GdkDragContext *
gdk_drag_begin_for_device (GdkWindow *window,
GdkDevice *device,
GList *targets)
{
return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, targets);
}
/**
* gdk_window_lookup:
* @anid: a native window handle

View File

@ -238,6 +238,9 @@ struct _GdkWindowImplClass
gdouble opacity);
void (* destroy_notify) (GdkWindow *window);
void (* register_dnd) (GdkWindow *window);
GdkDragContext * (*drag_begin) (GdkWindow *window,
GdkDevice *device,
GList *targets);
};
/* Interface Functions */

View File

@ -87,56 +87,6 @@ gdk_drag_context_new (void)
return (GdkDragContext *)g_object_new (gdk_drag_context_get_type (), NULL);
}
/**
* gdk_drag_context_set_device:
* @context: a #GdkDragContext
* @device: a #GdkDevice
*
* Associates a #GdkDevice to @context, so all Drag and Drop events
* for @context are emitted as if they came from this device.
**/
void
gdk_drag_context_set_device (GdkDragContext *context,
GdkDevice *device)
{
GdkDragContextPrivate *private;
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
g_return_if_fail (GDK_IS_DEVICE (device));
private = GDK_DRAG_CONTEXT_PRIVATE (context);
if (private->device)
{
g_object_unref (private->device);
private->device = NULL;
}
if (device)
private->device = g_object_ref (device);
}
/**
* gdk_drag_context_get_device:
* @context: a #GdkDragContext
*
* Returns the #GdkDevice associated to the drag context.
*
* Returns: The #GdkDevice associated to @context.
**/
GdkDevice *
gdk_drag_context_get_device (GdkDragContext *context)
{
GdkDragContextPrivate *private;
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
private = GDK_DRAG_CONTEXT_PRIVATE (context);
return private->device;
}
GdkDragContext *_gdk_quartz_drag_source_context = NULL;
GdkDragContext *

View File

@ -98,7 +98,6 @@ typedef enum {
* this is used on both source and destination sides.
*/
struct _GdkDragContextPrivateWin32 {
GdkDevice *device;
gboolean being_finalized;
gint ref_count;
IUnknown *iface;
@ -204,39 +203,6 @@ gdk_drag_context_new (void)
return g_object_new (GDK_TYPE_DRAG_CONTEXT, NULL);
}
GdkDevice *
gdk_drag_context_get_device (GdkDragContext *context)
{
GdkDragContextPrivateWin32 *private;
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
private = PRIVATE_DATA (context);
return private->device;
}
void
gdk_drag_context_set_device (GdkDragContext *context,
GdkDevice *device)
{
GdkDragContextPrivateWin32 *private;
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
g_return_if_fail (GDK_IS_DEVICE (device));
private = PRIVATE_DATA (context);
if (private->device)
{
g_object_unref (private->device);
private->device = NULL;
}
if (device)
private->device = g_object_ref (device);
}
static GdkDragContext *
gdk_drag_context_find (gboolean is_source,
GdkWindow *source,

View File

@ -2704,6 +2704,10 @@ gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
}
extern GdkAppLaunchContext *_gdk_x11_display_get_app_launch_context (GdkDisplay *display);
extern GdkNativeWindow _gdk_x11_display_get_drag_protocol (GdkDisplay *display,
GdkNativeWindow xid,
GdkDragProtocol *protocol,
guint *version);
static void
_gdk_display_x11_class_init (GdkDisplayX11Class * class)
@ -2733,5 +2737,6 @@ _gdk_display_x11_class_init (GdkDisplayX11Class * class)
display_class->send_client_message = gdk_x11_display_send_client_message;
display_class->add_client_message_filter = gdk_x11_display_add_client_message_filter;
display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
display_class->get_drag_protocol = _gdk_x11_display_get_drag_protocol;
}

File diff suppressed because it is too large Load Diff

View File

@ -4965,6 +4965,10 @@ gdk_x11_window_get_xid (GdkWindow *window)
return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
}
extern GdkDragContext * _gdk_x11_window_drag_begin (GdkWindow *window,
GdkDevice *device,
GList *targets);
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
{
@ -5043,5 +5047,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
impl_class->set_opacity = gdk_x11_window_set_opacity;
impl_class->destroy_notify = gdk_x11_window_destroy_notify;
impl_class->register_dnd = _gdk_x11_window_register_dnd;
impl_class->drag_begin = _gdk_x11_window_drag_begin;
}