#include "gtkstock.h"
#include "gtkwindow.h"
-static GSList *drag_widgets = NULL;
static GSList *source_widgets = NULL;
typedef struct _GtkDragSourceSite GtkDragSourceSite;
gint start_x, start_y; /* Initial position */
gint cur_x, cur_y; /* Current Position */
+ guint32 grab_time; /* timestamp for initial grab */
GList *selections; /* selections we've claimed */
GtkDragDestInfo *proxy_dest; /* Set if this is a proxy drag */
guint drop_timeout; /* Timeout for aborting drop */
guint destroy_icon : 1; /* If true, destroy icon_window
*/
+ guint have_grab : 1; /* Do we still have the pointer grab
+ */
};
struct _GtkDragDestSite
GdkDragAction actions,
GdkDragAction *suggested_action,
GdkDragAction *possible_actions);
-static GdkCursor * gtk_drag_get_cursor (GdkDragAction action);
-static GtkWidget *gtk_drag_get_ipc_widget (void);
+static GdkCursor * gtk_drag_get_cursor (GdkDisplay *display,
+ GdkDragAction action);
+static GtkWidget *gtk_drag_get_ipc_widget (GdkScreen *screen);
static void gtk_drag_release_ipc_widget (GtkWidget *widget);
static gboolean gtk_drag_highlight_expose (GtkWidget *widget,
static struct {
GdkDragAction action;
- const char *bits;
- const char *mask;
+ const guchar *bits;
+ const guchar *mask;
GdkCursor *cursor;
} drag_cursors[] = {
{ GDK_ACTION_DEFAULT, 0 },
*************************************************************/
static GtkWidget *
-gtk_drag_get_ipc_widget (void)
+gtk_drag_get_ipc_widget (GdkScreen *screen)
{
GtkWidget *result;
+ GSList *drag_widgets = g_object_get_data (G_OBJECT (screen),
+ "gtk-dnd-ipc-widgets");
if (drag_widgets)
{
GSList *tmp = drag_widgets;
result = drag_widgets->data;
drag_widgets = drag_widgets->next;
+ g_object_set_data (G_OBJECT (screen),
+ "gtk-dnd-ipc-widgets",
+ drag_widgets);
g_slist_free_1 (tmp);
}
else
{
- result = gtk_invisible_new ();
+ result = gtk_invisible_new_for_screen (screen);
gtk_widget_show (result);
}
static void
gtk_drag_release_ipc_widget (GtkWidget *widget)
{
+ GdkScreen *screen = gtk_widget_get_screen (widget);
+ GSList *drag_widgets = g_object_get_data (G_OBJECT (screen),
+ "gtk-dnd-ipc-widgets");
drag_widgets = g_slist_prepend (drag_widgets, widget);
+ g_object_set_data (G_OBJECT (screen),
+ "gtk-dnd-ipc-widgets",
+ drag_widgets);
}
static guint32
}
static GdkCursor *
-gtk_drag_get_cursor (GdkDragAction action)
+gtk_drag_get_cursor (GdkDisplay *display,
+ GdkDragAction action)
{
gint i;
for (i = 0 ; i < n_drag_cursors - 1; i++)
if (drag_cursors[i].action == action)
break;
+ if (drag_cursors[i].cursor != NULL)
+ {
+ if (display != gdk_cursor_get_display (drag_cursors[i].cursor))
+ {
+ gdk_cursor_unref (drag_cursors[i].cursor);
+ drag_cursors[i].cursor = NULL;
+ }
+ }
if (drag_cursors[i].cursor == NULL)
{
- GdkColor fg, bg;
+ GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
+ GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
+ GdkScreen *screen = gdk_display_get_default_screen (display);
+ GdkWindow *window = gdk_screen_get_root_window (screen);
GdkPixmap *pixmap =
- gdk_bitmap_create_from_data (NULL,
- drag_cursors[i].bits,
- CURSOR_WIDTH, CURSOR_HEIGHT);
+ gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].bits, CURSOR_WIDTH, CURSOR_HEIGHT);
+
GdkPixmap *mask =
- gdk_bitmap_create_from_data (NULL,
- drag_cursors[i].mask,
- CURSOR_WIDTH, CURSOR_HEIGHT);
+ gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT);
- gdk_color_white (gdk_colormap_get_system (), &bg);
- gdk_color_black (gdk_colormap_get_system (), &fg);
-
drag_cursors[i].cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, 0, 0);
gdk_pixmap_unref (pixmap);
g_return_if_fail (widget != NULL);
g_return_if_fail (context != NULL);
- selection_widget = gtk_drag_get_ipc_widget ();
+ selection_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget));
gdk_drag_context_ref (context);
gtk_widget_ref (widget);
if (target != GDK_NONE)
{
- GtkWidget *selection_widget = gtk_drag_get_ipc_widget ();
+ GtkWidget *selection_widget = gtk_drag_get_ipc_widget (gdk_drawable_get_screen (context->source_window));
gdk_drag_context_ref (context);
site->target_list = gtk_target_list_new (targets, n_targets);
else
site->target_list = NULL;
-
site->actions = actions;
site->do_proxy = FALSE;
+ site->proxy_window = NULL;
gtk_drag_dest_set_internal (widget, site);
}
GtkDragFindData *data)
{
GtkAllocation new_allocation;
+ gint allocation_to_window_x = 0;
+ gint allocation_to_window_y = 0;
gint x_offset = 0;
gint y_offset = 0;
if (widget->parent)
{
- gint tx, ty, twidth, theight;
+ gint tx, ty;
GdkWindow *window = widget->window;
- /* Correct for the fact that the allocation is relative
- * to the parent window for window widgets, not to widget->window.
+ /* Compute the offset from allocation-relative to
+ * window-relative coordinates.
*/
+ allocation_to_window_x = widget->allocation.x;
+ allocation_to_window_y = widget->allocation.y;
+
if (!GTK_WIDGET_NO_WINDOW (widget))
{
+ /* The allocation is relative to the parent window for
+ * window widgets, not to widget->window.
+ */
gdk_window_get_position (window, &tx, &ty);
- new_allocation.x -= tx;
- new_allocation.y -= ty;
+ allocation_to_window_x -= tx;
+ allocation_to_window_y -= ty;
}
+ new_allocation.x = 0 + allocation_to_window_x;
+ new_allocation.y = 0 + allocation_to_window_y;
+
while (window && window != widget->parent->window)
- {
- gdk_window_get_size (window, &twidth, &theight);
+ {
+ GdkRectangle window_rect = { 0, 0, 0, 0 };
+
+ gdk_window_get_size (window, &window_rect.width, &window_rect.height);
- if (new_allocation.x < 0)
- {
- new_allocation.width += new_allocation.x;
- new_allocation.x = 0;
- }
- if (new_allocation.y < 0)
- {
- new_allocation.height += new_allocation.y;
- new_allocation.y = 0;
- }
- if (new_allocation.x + new_allocation.width > twidth)
- new_allocation.width = twidth - new_allocation.x;
- if (new_allocation.y + new_allocation.height > theight)
- new_allocation.height = theight - new_allocation.y;
+ gdk_rectangle_intersect (&new_allocation, &window_rect, &new_allocation);
gdk_window_get_position (window, &tx, &ty);
new_allocation.x += tx;
{
data->found = data->callback (widget,
data->context,
- data->x - new_allocation.x - x_offset,
- data->y - new_allocation.y - y_offset,
+ data->x - x_offset - allocation_to_window_x,
+ data->y - y_offset - allocation_to_window_y,
data->time);
/* If so, send a "drag_leave" to the last widget */
if (data->found)
dest_info->proxy_source = NULL;
}
- ipc_widget = gtk_drag_get_ipc_widget ();
+ ipc_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget));
context = gdk_drag_begin (ipc_widget->window,
dest_info->context->targets);
{
GtkDragDestSite *site = data;
+ if (site->proxy_window)
+ g_object_unref (site->proxy_window);
+
if (site->target_list)
gtk_target_list_unref (site->target_list);
tmp_list = tmp_list->prev;
}
- ipc_widget = gtk_drag_get_ipc_widget ();
+ ipc_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget));
source_widgets = g_slist_prepend (source_widgets, ipc_widget);
context = gdk_drag_begin (ipc_widget->window, targets);
gtk_drag_get_event_actions (event, info->button, actions,
&suggested_action, &possible_actions);
- info->cursor = gtk_drag_get_cursor (suggested_action);
+ info->cursor = gtk_drag_get_cursor (gtk_widget_get_display (widget), suggested_action);
/* Set cur_x, cur_y here so if the "drag_begin" signal shows
* the drag icon, it will be in the right place
}
else
{
- gint x, y;
- gdk_window_get_pointer (GDK_ROOT_PARENT (), &x, &y, NULL);
-
- info->cur_x = x;
- info->cur_y = y;
+ gdk_window_get_pointer (gtk_widget_get_root_window (widget),
+ &info->cur_x, &info->cur_y, NULL);
}
gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_begin",
}
}
+ info->have_grab = TRUE;
+ info->grab_time = time;
+
return info->context;
}
gint width, height;
GdkPixmap *pixmap;
GdkPixmap *mask;
-
+ GdkScreen *screen;
+ GdkColormap *colormap;
+
g_return_if_fail (context != NULL);
g_return_if_fail (pixbuf != NULL || stock_id != NULL);
g_return_if_fail (pixbuf == NULL || stock_id == NULL);
-
- gtk_widget_push_colormap (gdk_rgb_get_colormap ());
+
+ screen = gdk_drawable_get_screen (context->source_window);
+ colormap = gdk_screen_get_rgb_colormap (screen);
+
+ gtk_widget_push_colormap (colormap);
window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_screen (GTK_WINDOW (window), screen);
gtk_widget_pop_colormap ();
gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
gdk_pixbuf_get_height (pixbuf));
gtk_widget_realize (window);
- gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128);
+ gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf, colormap, &pixmap, &mask, 128);
gdk_window_set_back_pixmap (window->window, pixmap, FALSE);
gtk_widget_push_colormap (colormap);
window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_screen (GTK_WINDOW (window), gdk_drawable_get_screen (context->source_window));
gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
* Changes the default drag icon. GTK+ retains references for the
* arguments, and will release them when they are no longer needed.
* This function is obsolete. The default icon should now be changed
- * via the stock system by changing the stock pixbuf for %GTK_STOCK_DND.
+ * via the stock system by changing the stock pixbuf for #GTK_STOCK_DND.
**/
void
gtk_drag_set_default_icon (GdkColormap *colormap,
}
}
}
- else
+ else if (info->have_grab)
{
- cursor = gtk_drag_get_cursor (event->dnd.context->action);
+ cursor = gtk_drag_get_cursor (gtk_widget_get_display (widget),
+ event->dnd.context->action);
if (info->cursor != cursor)
{
gdk_pointer_grab (widget->window, FALSE,
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_RELEASE_MASK,
NULL,
- cursor, event->dnd.time);
+ cursor, info->grab_time);
info->cursor = cursor;
}
tmp_list = tmp_list->next;
}
- gtk_selection_owner_set (info->ipc_widget, selection, time);
+ gtk_selection_owner_set_for_display (gtk_widget_get_display (info->widget),
+ info->ipc_widget,
+ selection,
+ time);
info->selections = g_list_prepend (info->selections,
GUINT_TO_POINTER (selection));
gtk_drag_source_release_selections (GtkDragSourceInfo *info,
guint32 time)
{
+ GdkDisplay *display = gtk_widget_get_display (info->widget);
GList *tmp_list = info->selections;
+
while (tmp_list)
{
GdkAtom selection = GDK_POINTER_TO_ATOM (tmp_list->data);
- if (gdk_selection_owner_get (selection) == info->ipc_widget->window)
- gtk_selection_owner_set (NULL, selection, time);
+ if (gdk_selection_owner_get_for_display (display, selection) == info->ipc_widget->window)
+ gtk_selection_owner_set_for_display (display, NULL, selection, time);
+
tmp_list = tmp_list->next;
}
{
GdkEvent send_event;
GtkWidget *source_widget = info->widget;
+ GdkDisplay *display = gtk_widget_get_display (source_widget);
- gdk_pointer_ungrab (time);
- gdk_keyboard_ungrab (time);
-
+ info->have_grab = FALSE;
+
+ gdk_display_pointer_ungrab (display, time);
+ gdk_display_keyboard_ungrab (display, time);
gtk_grab_remove (info->ipc_widget);
gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget),
gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget),
GTK_SIGNAL_FUNC (gtk_drag_motion_cb),
info);
+ gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget),
+ GTK_SIGNAL_FUNC (gtk_drag_key_cb),
+ info);
/* Send on a release pair to the the original
* widget to convince it to release its grab. We need to
*/
send_event.button.type = GDK_BUTTON_RELEASE;
- send_event.button.window = GDK_ROOT_PARENT ();
+ send_event.button.window = gtk_widget_get_root_window (source_widget);
send_event.button.send_event = TRUE;
send_event.button.time = time;
send_event.button.x = 0;
send_event.button.axes = NULL;
send_event.button.state = 0;
send_event.button.button = info->button;
- send_event.button.device = gdk_device_get_core_pointer ();
+ send_event.button.device = gdk_display_get_core_pointer (display);
send_event.button.x_root = 0;
send_event.button.y_root = 0;
if (event->is_hint)
{
- gdk_window_get_pointer (GDK_ROOT_PARENT(), &x_root, &y_root, NULL);
+ GdkWindow *root_window = gtk_widget_get_root_window (widget);
+
+ gdk_window_get_pointer (root_window, &x_root, &y_root, NULL);
event->x_root = x_root;
event->y_root = y_root;
}
{
GtkDragSourceInfo *info = (GtkDragSourceInfo *)data;
GdkModifierType state;
+ GdkWindow *root_window;
if (event->type == GDK_KEY_PRESS)
{
* to query it here. We could use XGetModifierMapping, but
* that would be overkill.
*/
- gdk_window_get_pointer (GDK_ROOT_PARENT(), NULL, NULL, &state);
+ root_window = gtk_widget_get_root_window (widget);
+ gdk_window_get_pointer (root_window, NULL, NULL, &state);
event->state = state;
gtk_drag_update (info, info->cur_x, info->cur_y, (GdkEvent *)event);
* @current_x: current X coordinate
* @current_y: current Y coordinate
*
- * Checks to see if a mouse drag starting at (start_x, start_y) and ending
- * at (current_x, current_y) has passed the GTK drag threshhold, and thus
+ * Checks to see if a mouse drag starting at (@start_x, @start_y) and ending
+ * at (@current_x, @current_y) has passed the GTK+ drag threshhold, and thus
* should trigger the beginning of a drag-and-drop operation.
*
- * Return Value: If the drag threshold has been passed.
+ * Return Value: %TRUE if the drag threshold has been passed.
**/
gboolean
gtk_drag_check_threshold (GtkWidget *widget,