Compare commits
1 Commits
dnd-test
...
lrn/alignf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2b509fb23 |
@@ -44,7 +44,7 @@ msys2-mingw32:
|
||||
<<: *mingw-defaults
|
||||
|
||||
.flatpak-defaults: &flatpak-defaults
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
|
||||
image: registry.gitlab.com/alatiera/gnome-nightly-oci/gnome-master:latest
|
||||
stage: flatpak
|
||||
artifacts:
|
||||
paths:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
FROM fedora:28
|
||||
|
||||
RUN dnf -y install \
|
||||
hicolor-icon-theme \
|
||||
adwaita-icon-theme \
|
||||
atk-devel \
|
||||
at-spi2-atk-devel \
|
||||
|
||||
8
NEWS
8
NEWS
@@ -27,8 +27,8 @@ Overview of Changes in GTK+ 3.94.0
|
||||
* Applications can now create their own GtkSnapshot objects for
|
||||
intermediate rendering.
|
||||
|
||||
* Widget event signals have been replaced by event controllers,
|
||||
and some new event controllers have been introduced for this:
|
||||
* Widget event signals have been replaced by event controller, and
|
||||
some new event controllers have been introduced for this:
|
||||
GtkEventControllerMotion
|
||||
GtkEventControllerKey
|
||||
GtkGestureStylus
|
||||
@@ -68,10 +68,6 @@ Overview of Changes in GTK+ 3.94.0
|
||||
gtk_widget_draw
|
||||
gtk_render_icon_surface
|
||||
|
||||
* Incomplete transitions:
|
||||
The ::event signal is not still there, but it will be removed
|
||||
The DND apis are not finalized yet
|
||||
|
||||
* Translation updates:
|
||||
Croatian
|
||||
Esperanto
|
||||
|
||||
@@ -87,14 +87,14 @@ find_toplevel_at_pointer (GdkDisplay *display)
|
||||
return widget ? gtk_widget_get_toplevel (widget) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
released_cb (GtkGestureMultiPress *gesture,
|
||||
guint n_press,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gboolean *clicked)
|
||||
static gboolean
|
||||
release_event_cb (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gboolean *clicked)
|
||||
{
|
||||
*clicked = TRUE;
|
||||
if (gdk_event_get_event_type (event) == GDK_BUTTON_RELEASE)
|
||||
*clicked = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Asks the user to click on a window, then waits for them click
|
||||
@@ -132,12 +132,10 @@ query_for_toplevel (GdkDisplay *display,
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING,
|
||||
FALSE, cursor, NULL, NULL, NULL) == GDK_GRAB_SUCCESS)
|
||||
{
|
||||
GtkGesture *gesture = gtk_gesture_multi_press_new ();
|
||||
gboolean clicked = FALSE;
|
||||
|
||||
g_signal_connect (gesture, "released",
|
||||
G_CALLBACK (released_cb), &clicked);
|
||||
gtk_widget_add_controller (popup, GTK_EVENT_CONTROLLER (gesture));
|
||||
g_signal_connect (popup, "event",
|
||||
G_CALLBACK (release_event_cb), &clicked);
|
||||
|
||||
/* Process events until clicked is set by our button release event handler.
|
||||
* We pass in may_block=TRUE since we want to wait if there
|
||||
@@ -146,8 +144,6 @@ query_for_toplevel (GdkDisplay *display,
|
||||
while (!clicked)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
gdk_seat_ungrab (gdk_device_get_seat (device));
|
||||
|
||||
toplevel = find_toplevel_at_pointer (display);
|
||||
if (toplevel == popup)
|
||||
toplevel = NULL;
|
||||
|
||||
@@ -120,7 +120,7 @@ get_image_paintable (GtkImage *image)
|
||||
|
||||
static void
|
||||
drag_begin (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
@@ -128,16 +128,17 @@ drag_begin (GtkWidget *widget,
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (paintable)
|
||||
{
|
||||
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
|
||||
gtk_drag_set_icon_paintable (context, paintable, -2, -2);
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drag_data_get (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
@@ -149,8 +150,9 @@ drag_data_get (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
if (gtk_selection_data_get_length (selection_data) > 0)
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
<file>editable_cells.c</file>
|
||||
<file>entry_buffer.c</file>
|
||||
<file>entry_completion.c</file>
|
||||
<file>event_axes.c</file>
|
||||
<file>expander.c</file>
|
||||
<file>filtermodel.c</file>
|
||||
<file>fishbowl.c</file>
|
||||
|
||||
666
demos/gtk-demo/event_axes.c
Normal file
666
demos/gtk-demo/event_axes.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/* Touch and Drawing Tablets
|
||||
*
|
||||
* Demonstrates advanced handling of event information from exotic
|
||||
* input devices.
|
||||
*
|
||||
* On one hand, this snippet demonstrates management of drawing tablets,
|
||||
* those contain additional information for the pointer other than
|
||||
* X/Y coordinates. Tablet pads events are mapped to actions, which
|
||||
* are both defined and interpreted by the application.
|
||||
*
|
||||
* Input axes are dependent on hardware devices, on linux/unix you
|
||||
* can see the device axes through xinput list <device>. Each time
|
||||
* a different hardware device is used to move the pointer, the
|
||||
* master device will be updated to match the axes it provides,
|
||||
* these changes can be tracked through GdkDevice::changed, or
|
||||
* checking gdk_event_get_source_device().
|
||||
*
|
||||
* On the other hand, this demo handles basic multitouch events,
|
||||
* each event coming from an specific touchpoint will contain a
|
||||
* GdkEventSequence that's unique for its lifetime, so multiple
|
||||
* touchpoints can be tracked.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct {
|
||||
GdkDevice *last_source;
|
||||
GdkDeviceTool *last_tool;
|
||||
gdouble *axes;
|
||||
GdkRGBA color;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
} AxesInfo;
|
||||
|
||||
typedef struct {
|
||||
GHashTable *pointer_info; /* GdkDevice -> AxesInfo */
|
||||
GHashTable *touch_info; /* GdkEventSequence -> AxesInfo */
|
||||
} EventData;
|
||||
|
||||
const gchar *colors[] = {
|
||||
"black",
|
||||
"orchid",
|
||||
"fuchsia",
|
||||
"indigo",
|
||||
"thistle",
|
||||
"sienna",
|
||||
"azure",
|
||||
"plum",
|
||||
"lime",
|
||||
"navy",
|
||||
"maroon",
|
||||
"burlywood"
|
||||
};
|
||||
|
||||
static GtkPadActionEntry pad_actions[] = {
|
||||
{ GTK_PAD_ACTION_BUTTON, 1, -1, N_("Nuclear strike"), "pad.nuke" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 2, -1, N_("Release siberian methane reserves"), "pad.heat" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 3, -1, N_("Release solar flare"), "pad.fry" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 4, -1, N_("De-stabilize Oort cloud"), "pad.fall" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 5, -1, N_("Ignite WR-104"), "pad.burst" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 6, -1, N_("Lart whoever asks about this button"), "pad.lart" },
|
||||
{ GTK_PAD_ACTION_RING, -1, -1, N_("Earth axial tilt"), "pad.tilt" },
|
||||
{ GTK_PAD_ACTION_STRIP, -1, -1, N_("Extent of weak nuclear force"), "pad.dissolve" },
|
||||
};
|
||||
|
||||
static const gchar *pad_action_results[] = {
|
||||
"☢",
|
||||
"♨",
|
||||
"☼",
|
||||
"☄",
|
||||
"⚡",
|
||||
"💫",
|
||||
"◑",
|
||||
"⚛"
|
||||
};
|
||||
|
||||
static guint cur_color = 0;
|
||||
static guint pad_action_timeout_id = 0;
|
||||
|
||||
static AxesInfo *
|
||||
axes_info_new (void)
|
||||
{
|
||||
AxesInfo *info;
|
||||
|
||||
info = g_new0 (AxesInfo, 1);
|
||||
gdk_rgba_parse (&info->color, colors[cur_color]);
|
||||
|
||||
cur_color = (cur_color + 1) % G_N_ELEMENTS (colors);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static EventData *
|
||||
event_data_new (void)
|
||||
{
|
||||
EventData *data;
|
||||
|
||||
data = g_new0 (EventData, 1);
|
||||
data->pointer_info = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_free);
|
||||
data->touch_info = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_free);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
event_data_free (EventData *data)
|
||||
{
|
||||
g_hash_table_destroy (data->pointer_info);
|
||||
g_hash_table_destroy (data->touch_info);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
update_axes_from_event (GdkEvent *event,
|
||||
EventData *data)
|
||||
{
|
||||
GdkDevice *device, *source_device;
|
||||
GdkEventSequence *sequence;
|
||||
GdkDeviceTool *tool;
|
||||
GdkEventType type;
|
||||
gdouble x, y;
|
||||
AxesInfo *info;
|
||||
|
||||
device = gdk_event_get_device (event);
|
||||
source_device = gdk_event_get_source_device (event);
|
||||
sequence = gdk_event_get_event_sequence (event);
|
||||
tool = gdk_event_get_device_tool (event);
|
||||
type = gdk_event_get_event_type (event);
|
||||
|
||||
if (type == GDK_TOUCH_END ||
|
||||
type == GDK_TOUCH_CANCEL)
|
||||
{
|
||||
g_hash_table_remove (data->touch_info, sequence);
|
||||
return;
|
||||
}
|
||||
else if (type == GDK_LEAVE_NOTIFY)
|
||||
{
|
||||
g_hash_table_remove (data->pointer_info, device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!source_device)
|
||||
return;
|
||||
|
||||
if (!sequence)
|
||||
{
|
||||
info = g_hash_table_lookup (data->pointer_info, device);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
info = axes_info_new ();
|
||||
g_hash_table_insert (data->pointer_info, device, info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
info = g_hash_table_lookup (data->touch_info, sequence);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
info = axes_info_new ();
|
||||
g_hash_table_insert (data->touch_info, sequence, info);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->last_source != source_device)
|
||||
info->last_source = source_device;
|
||||
|
||||
if (info->last_tool != tool)
|
||||
info->last_tool = tool;
|
||||
|
||||
g_clear_pointer (&info->axes, g_free);
|
||||
|
||||
if (type == GDK_TOUCH_BEGIN ||
|
||||
type == GDK_TOUCH_UPDATE)
|
||||
{
|
||||
gboolean emulating_pointer;
|
||||
|
||||
gdk_event_get_touch_emulating_pointer (event, &emulating_pointer);
|
||||
if (sequence && emulating_pointer)
|
||||
g_hash_table_remove (data->pointer_info, device);
|
||||
}
|
||||
if (type == GDK_MOTION_NOTIFY ||
|
||||
type == GDK_BUTTON_PRESS ||
|
||||
type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
gdouble *axes;
|
||||
guint n_axes;
|
||||
|
||||
gdk_event_get_axes (event, &axes, &n_axes);
|
||||
info->axes = g_memdup (axes, sizeof (double) * n_axes);
|
||||
}
|
||||
|
||||
if (gdk_event_get_coords (event, &x, &y))
|
||||
{
|
||||
info->x = x;
|
||||
info->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_cb (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
update_axes_from_event (event, user_data);
|
||||
gtk_widget_queue_draw (widget);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
render_arrow (cairo_t *cr,
|
||||
gdouble x_diff,
|
||||
gdouble y_diff,
|
||||
const gchar *label)
|
||||
{
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_new_path (cr);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, x_diff, y_diff);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_move_to (cr, x_diff, y_diff);
|
||||
cairo_show_text (cr, label);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_axes_info (cairo_t *cr,
|
||||
AxesInfo *info,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gdouble pressure, tilt_x, tilt_y, distance, wheel, rotation, slider;
|
||||
GdkAxisFlags axes = gdk_device_get_axes (info->last_source);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1);
|
||||
gdk_cairo_set_source_rgba (cr, &info->color);
|
||||
|
||||
cairo_move_to (cr, 0, info->y);
|
||||
cairo_line_to (cr, width, info->y);
|
||||
cairo_move_to (cr, info->x, 0);
|
||||
cairo_line_to (cr, info->x, height);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_translate (cr, info->x, info->y);
|
||||
|
||||
if (!info->axes)
|
||||
{
|
||||
cairo_restore (cr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_PRESSURE)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_PRESSURE,
|
||||
&pressure);
|
||||
|
||||
pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 100);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, pressure, 1, 0, 0, pressure);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 1, 0);
|
||||
|
||||
cairo_set_source (cr, pattern);
|
||||
|
||||
cairo_arc (cr, 0, 0, 100, 0, 2 * G_PI);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_XTILT &&
|
||||
axes & GDK_AXIS_FLAG_YTILT)
|
||||
{
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_XTILT,
|
||||
&tilt_x);
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_YTILT,
|
||||
&tilt_y);
|
||||
|
||||
render_arrow (cr, tilt_x * 100, tilt_y * 100, "Tilt");
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_DISTANCE)
|
||||
{
|
||||
double dashes[] = { 5.0, 5.0 };
|
||||
cairo_text_extents_t extents;
|
||||
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_DISTANCE,
|
||||
&distance);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_move_to (cr, distance * 100, 0);
|
||||
|
||||
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
||||
cairo_set_dash (cr, dashes, 2, 0.0);
|
||||
cairo_arc (cr, 0, 0, distance * 100, 0, 2 * G_PI);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_move_to (cr, 0, -distance * 100);
|
||||
cairo_text_extents (cr, "Distance", &extents);
|
||||
cairo_rel_move_to (cr, -extents.width / 2, 0);
|
||||
cairo_show_text (cr, "Distance");
|
||||
|
||||
cairo_move_to (cr, 0, 0);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_WHEEL)
|
||||
{
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_WHEEL,
|
||||
&wheel);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_set_line_width (cr, 10);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
|
||||
|
||||
cairo_new_sub_path (cr);
|
||||
cairo_arc (cr, 0, 0, 100, 0, wheel * 2 * G_PI);
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_ROTATION)
|
||||
{
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_ROTATION,
|
||||
&rotation);
|
||||
rotation *= 2 * G_PI;
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_rotate (cr, - G_PI / 2);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_line_width (cr, 5);
|
||||
|
||||
cairo_new_sub_path (cr);
|
||||
cairo_arc (cr, 0, 0, 100, 0, rotation);
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (axes & GDK_AXIS_FLAG_SLIDER)
|
||||
{
|
||||
cairo_pattern_t *pattern, *mask;
|
||||
|
||||
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_SLIDER,
|
||||
&slider);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_move_to (cr, 0, -10);
|
||||
cairo_rel_line_to (cr, 0, -50);
|
||||
cairo_rel_line_to (cr, 10, 0);
|
||||
cairo_rel_line_to (cr, -5, 50);
|
||||
cairo_close_path (cr);
|
||||
|
||||
cairo_clip_preserve (cr);
|
||||
|
||||
pattern = cairo_pattern_create_linear (0, -10, 0, -60);
|
||||
cairo_pattern_add_color_stop_rgb (pattern, 0, 0, 1, 0);
|
||||
cairo_pattern_add_color_stop_rgb (pattern, 1, 1, 0, 0);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
mask = cairo_pattern_create_linear (0, -10, 0, -60);
|
||||
cairo_pattern_add_color_stop_rgba (mask, 0, 0, 0, 0, 1);
|
||||
cairo_pattern_add_color_stop_rgba (mask, slider, 0, 0, 0, 1);
|
||||
cairo_pattern_add_color_stop_rgba (mask, slider, 0, 0, 0, 0);
|
||||
cairo_pattern_add_color_stop_rgba (mask, 1, 0, 0, 0, 0);
|
||||
cairo_mask (cr, mask);
|
||||
cairo_pattern_destroy (mask);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
tool_type_to_string (GdkDeviceToolType tool_type)
|
||||
{
|
||||
switch (tool_type)
|
||||
{
|
||||
case GDK_DEVICE_TOOL_TYPE_PEN:
|
||||
return "Pen";
|
||||
case GDK_DEVICE_TOOL_TYPE_ERASER:
|
||||
return "Eraser";
|
||||
case GDK_DEVICE_TOOL_TYPE_BRUSH:
|
||||
return "Brush";
|
||||
case GDK_DEVICE_TOOL_TYPE_PENCIL:
|
||||
return "Pencil";
|
||||
case GDK_DEVICE_TOOL_TYPE_AIRBRUSH:
|
||||
return "Airbrush";
|
||||
case GDK_DEVICE_TOOL_TYPE_MOUSE:
|
||||
return "Mouse";
|
||||
case GDK_DEVICE_TOOL_TYPE_LENS:
|
||||
return "Lens cursor";
|
||||
case GDK_DEVICE_TOOL_TYPE_UNKNOWN:
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_device_info (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
GdkEventSequence *sequence,
|
||||
gint *y,
|
||||
AxesInfo *info)
|
||||
{
|
||||
PangoLayout *layout;
|
||||
GString *string;
|
||||
gint height;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
g_string_append_printf (string, "Source: %s",
|
||||
gdk_device_get_name (info->last_source));
|
||||
|
||||
if (sequence)
|
||||
g_string_append_printf (string, "\nSequence: %d",
|
||||
GPOINTER_TO_UINT (sequence));
|
||||
|
||||
if (info->last_tool)
|
||||
{
|
||||
const gchar *tool_type;
|
||||
guint64 serial;
|
||||
|
||||
tool_type = tool_type_to_string (gdk_device_tool_get_tool_type (info->last_tool));
|
||||
serial = gdk_device_tool_get_serial (info->last_tool);
|
||||
g_string_append_printf (string, "\nTool: %s", tool_type);
|
||||
|
||||
if (serial != 0)
|
||||
g_string_append_printf (string, ", Serial: %" G_GINT64_MODIFIER "x", serial);
|
||||
}
|
||||
|
||||
cairo_move_to (cr, 10, *y);
|
||||
layout = gtk_widget_create_pango_layout (widget, string->str);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
cairo_stroke (cr);
|
||||
|
||||
pango_layout_get_pixel_size (layout, NULL, &height);
|
||||
|
||||
gdk_cairo_set_source_rgba (cr, &info->color);
|
||||
cairo_set_line_width (cr, 10);
|
||||
cairo_move_to (cr, 0, *y);
|
||||
|
||||
*y = *y + height;
|
||||
cairo_line_to (cr, 0, *y);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
g_object_unref (layout);
|
||||
g_string_free (string, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_cb (GtkDrawingArea *da,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (da);
|
||||
EventData *data = user_data;
|
||||
AxesInfo *info;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
gint y = 0;
|
||||
|
||||
/* Draw Abs info */
|
||||
g_hash_table_iter_init (&iter, data->pointer_info);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
{
|
||||
info = value;
|
||||
draw_axes_info (cr, info, width, height);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, data->touch_info);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
{
|
||||
info = value;
|
||||
draw_axes_info (cr, info, width, height);
|
||||
}
|
||||
|
||||
/* Draw name, color legend and misc data */
|
||||
g_hash_table_iter_init (&iter, data->pointer_info);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
{
|
||||
info = value;
|
||||
draw_device_info (widget, cr, NULL, &y, info);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, data->touch_info);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
info = value;
|
||||
draw_device_info (widget, cr, key, &y, info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_label_text (GtkWidget *label,
|
||||
const gchar *text)
|
||||
{
|
||||
gchar *markup = NULL;
|
||||
|
||||
if (text)
|
||||
markup = g_strdup_printf ("<span font='48.0'>%s</span>", text);
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||
g_free (markup);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
reset_label_text_timeout_cb (gpointer user_data)
|
||||
{
|
||||
GtkWidget *label = user_data;
|
||||
|
||||
update_label_text (label, NULL);
|
||||
pad_action_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_label_and_timeout (GtkWidget *label,
|
||||
const gchar *text)
|
||||
{
|
||||
if (pad_action_timeout_id)
|
||||
g_source_remove (pad_action_timeout_id);
|
||||
|
||||
update_label_text (label, text);
|
||||
pad_action_timeout_id = g_timeout_add (200, reset_label_text_timeout_cb, label);
|
||||
}
|
||||
|
||||
static void
|
||||
on_action_activate (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *label = user_data;
|
||||
const gchar *result;
|
||||
gchar *str;
|
||||
|
||||
result = g_object_get_data (G_OBJECT (action), "action-result");
|
||||
|
||||
if (!parameter)
|
||||
update_label_and_timeout (label, result);
|
||||
else
|
||||
{
|
||||
str = g_strdup_printf ("%s %.2f", result, g_variant_get_double (parameter));
|
||||
update_label_and_timeout (label, str);
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_pad_controller (GtkWidget *window,
|
||||
GtkWidget *label)
|
||||
{
|
||||
GtkPadController *pad_controller;
|
||||
GSimpleActionGroup *action_group;
|
||||
GSimpleAction *action;
|
||||
gint i;
|
||||
|
||||
action_group = g_simple_action_group_new ();
|
||||
pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (action_group),
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (pad_actions); i++)
|
||||
{
|
||||
if (pad_actions[i].type == GTK_PAD_ACTION_BUTTON)
|
||||
{
|
||||
action = g_simple_action_new (pad_actions[i].action_name, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = g_simple_action_new_stateful (pad_actions[i].action_name,
|
||||
G_VARIANT_TYPE_DOUBLE, NULL);
|
||||
}
|
||||
|
||||
g_signal_connect (action, "activate",
|
||||
G_CALLBACK (on_action_activate), label);
|
||||
g_object_set_data (G_OBJECT (action), "action-result",
|
||||
(gpointer) pad_action_results[i]);
|
||||
g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (action));
|
||||
g_object_unref (action);
|
||||
}
|
||||
|
||||
gtk_pad_controller_set_action_entries (pad_controller, pad_actions,
|
||||
G_N_ELEMENTS (pad_actions));
|
||||
gtk_widget_add_controller (window, GTK_EVENT_CONTROLLER (pad_controller));
|
||||
|
||||
g_object_unref (action_group);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_event_axes (GtkWidget *toplevel)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
EventData *event_data;
|
||||
GtkWidget *label;
|
||||
GtkWidget *overlay;
|
||||
GtkWidget *da;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Touch and Drawing Tablets");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
gtk_widget_set_support_multidevice (window, TRUE);
|
||||
|
||||
event_data = event_data_new ();
|
||||
g_object_set_data_full (G_OBJECT (window), "gtk-demo-event-data",
|
||||
event_data, (GDestroyNotify) event_data_free);
|
||||
|
||||
da = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 400);
|
||||
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 400);
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_cb, event_data, NULL);
|
||||
gtk_widget_set_can_focus (da, TRUE);
|
||||
gtk_widget_grab_focus (da);
|
||||
|
||||
g_signal_connect (da, "event",
|
||||
G_CALLBACK (event_cb), event_data);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_START);
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
gtk_container_add (GTK_CONTAINER (window), overlay);
|
||||
gtk_container_add (GTK_CONTAINER (overlay), da);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), label);
|
||||
|
||||
init_pad_controller (da, label);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -135,42 +135,55 @@ static void set_cursor_if_appropriate (GtkTextView *text_view,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
static void
|
||||
released_cb (GtkGestureMultiPress *gesture,
|
||||
guint n_press,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
GtkWidget *text_view)
|
||||
/* Links can also be activated by clicking or tapping.
|
||||
*/
|
||||
static gboolean
|
||||
event_cb (GtkWidget *text_view,
|
||||
GdkEvent *ev)
|
||||
{
|
||||
GtkTextIter start, end, iter;
|
||||
GtkTextBuffer *buffer;
|
||||
int tx, ty;
|
||||
gdouble ex, ey;
|
||||
int x, y;
|
||||
GdkEventType type;
|
||||
|
||||
if (gtk_gesture_single_get_button (GTK_GESTURE_SINGLE (gesture)) > 1)
|
||||
return;
|
||||
type = gdk_event_get_event_type (ev);
|
||||
|
||||
gdk_event_get_coords (ev, &ex, &ey);
|
||||
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
|
||||
GTK_TEXT_WINDOW_WIDGET,
|
||||
x, y, &tx, &ty);
|
||||
ex, ey, &x, &y);
|
||||
|
||||
if (type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
guint button;
|
||||
|
||||
gdk_event_get_button (ev, &button);
|
||||
if (button != GDK_BUTTON_PRIMARY)
|
||||
return FALSE;
|
||||
}
|
||||
else if (type == GDK_MOTION_NOTIFY)
|
||||
{
|
||||
set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
|
||||
return FALSE;
|
||||
}
|
||||
else if (type == GDK_TOUCH_END)
|
||||
{
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
|
||||
|
||||
/* we shouldn't follow a link if the user has selected something */
|
||||
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
|
||||
if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y))
|
||||
follow_if_link (text_view, &iter);
|
||||
}
|
||||
|
||||
static void
|
||||
motion_cb (GtkEventControllerMotion *controller,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
GtkTextView *text_view)
|
||||
{
|
||||
set_cursor_if_appropriate (text_view, x, y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean hovering_over_link = FALSE;
|
||||
@@ -246,16 +259,8 @@ do_hypertext (GtkWidget *do_widget)
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), view);
|
||||
gtk_widget_add_controller (view, controller);
|
||||
|
||||
controller = GTK_EVENT_CONTROLLER (gtk_gesture_multi_press_new ());
|
||||
g_signal_connect (controller, "released",
|
||||
G_CALLBACK (released_cb), view);
|
||||
gtk_widget_add_controller (view, controller);
|
||||
|
||||
controller = gtk_event_controller_motion_new ();
|
||||
g_signal_connect (controller, "motion",
|
||||
G_CALLBACK (motion_cb), view);
|
||||
gtk_widget_add_controller (view, controller);
|
||||
g_signal_connect (view, "event",
|
||||
G_CALLBACK (event_cb), NULL);
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="extra_buttons_box">
|
||||
<property name="visible">0</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="reply-button">
|
||||
|
||||
@@ -22,6 +22,7 @@ demos = files([
|
||||
'editable_cells.c',
|
||||
'entry_buffer.c',
|
||||
'entry_completion.c',
|
||||
'event_axes.c',
|
||||
'expander.c',
|
||||
'filtermodel.c',
|
||||
'fishbowl.c',
|
||||
|
||||
@@ -3,24 +3,14 @@
|
||||
* Demonstrates practical handling of drawing tablets in a real world
|
||||
* usecase.
|
||||
*/
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
enum {
|
||||
COLOR_SET,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint area_signals[N_SIGNALS] = { 0, };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
GdkRGBA draw_color;
|
||||
GtkPadController *pad_controller;
|
||||
gdouble brush_size;
|
||||
} DrawingArea;
|
||||
|
||||
typedef struct
|
||||
@@ -28,30 +18,8 @@ typedef struct
|
||||
GtkWidgetClass parent_class;
|
||||
} DrawingAreaClass;
|
||||
|
||||
static GtkPadActionEntry pad_actions[] = {
|
||||
{ GTK_PAD_ACTION_BUTTON, 1, -1, N_("Black"), "pad.black" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 2, -1, N_("Pink"), "pad.pink" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 3, -1, N_("Green"), "pad.green" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 4, -1, N_("Red"), "pad.red" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 5, -1, N_("Purple"), "pad.purple" },
|
||||
{ GTK_PAD_ACTION_BUTTON, 6, -1, N_("Orange"), "pad.orange" },
|
||||
{ GTK_PAD_ACTION_STRIP, -1, -1, N_("Brush size"), "pad.brush_size" },
|
||||
};
|
||||
|
||||
static const gchar *pad_colors[] = {
|
||||
"black",
|
||||
"pink",
|
||||
"green",
|
||||
"red",
|
||||
"purple",
|
||||
"orange"
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (DrawingArea, drawing_area, GTK_TYPE_WIDGET)
|
||||
|
||||
static void drawing_area_set_color (DrawingArea *area,
|
||||
GdkRGBA *color);
|
||||
|
||||
static void
|
||||
drawing_area_ensure_surface (DrawingArea *area,
|
||||
gint width,
|
||||
@@ -147,82 +115,6 @@ drawing_area_snapshot (GtkWidget *widget,
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
on_pad_button_activate (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
DrawingArea *area)
|
||||
{
|
||||
const gchar *color = g_object_get_data (G_OBJECT (action), "color");
|
||||
GdkRGBA rgba;
|
||||
|
||||
gdk_rgba_parse (&rgba, color);
|
||||
drawing_area_set_color (area, &rgba);
|
||||
}
|
||||
|
||||
static void
|
||||
on_pad_knob_change (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
DrawingArea *area)
|
||||
{
|
||||
gdouble value = g_variant_get_double (parameter);
|
||||
|
||||
area->brush_size = value;
|
||||
}
|
||||
|
||||
static void
|
||||
drawing_area_hierarchy_changed (GtkWidget *widget,
|
||||
GtkWidget *previous_toplevel)
|
||||
{
|
||||
DrawingArea *area = (DrawingArea *) widget;
|
||||
GSimpleActionGroup *action_group;
|
||||
GSimpleAction *action;
|
||||
GtkWidget *toplevel;
|
||||
gint i;
|
||||
|
||||
if (previous_toplevel && area->pad_controller)
|
||||
{
|
||||
gtk_widget_remove_controller (previous_toplevel,
|
||||
GTK_EVENT_CONTROLLER (area->pad_controller));
|
||||
area->pad_controller = NULL;
|
||||
}
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (area));
|
||||
if (!GTK_IS_WINDOW (toplevel))
|
||||
return;
|
||||
|
||||
action_group = g_simple_action_group_new ();
|
||||
area->pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (action_group),
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (pad_actions); i++)
|
||||
{
|
||||
if (pad_actions[i].type == GTK_PAD_ACTION_BUTTON)
|
||||
{
|
||||
action = g_simple_action_new (pad_actions[i].action_name, NULL);
|
||||
g_object_set_data (G_OBJECT (action), "color",
|
||||
(gpointer) pad_colors[i]);
|
||||
g_signal_connect (action, "activate",
|
||||
G_CALLBACK (on_pad_button_activate), area);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = g_simple_action_new_stateful (pad_actions[i].action_name,
|
||||
G_VARIANT_TYPE_DOUBLE, NULL);
|
||||
g_signal_connect (action, "activate",
|
||||
G_CALLBACK (on_pad_knob_change), area);
|
||||
}
|
||||
|
||||
g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (action));
|
||||
g_object_unref (action);
|
||||
}
|
||||
|
||||
gtk_pad_controller_set_action_entries (area->pad_controller, pad_actions,
|
||||
G_N_ELEMENTS (pad_actions));
|
||||
|
||||
gtk_widget_add_controller (toplevel,
|
||||
GTK_EVENT_CONTROLLER (area->pad_controller));
|
||||
}
|
||||
|
||||
static void
|
||||
drawing_area_class_init (DrawingAreaClass *klass)
|
||||
{
|
||||
@@ -232,14 +124,6 @@ drawing_area_class_init (DrawingAreaClass *klass)
|
||||
widget_class->snapshot = drawing_area_snapshot;
|
||||
widget_class->map = drawing_area_map;
|
||||
widget_class->unmap = drawing_area_unmap;
|
||||
widget_class->hierarchy_changed = drawing_area_hierarchy_changed;
|
||||
|
||||
area_signals[COLOR_SET] =
|
||||
g_signal_new ("color-set",
|
||||
G_TYPE_FROM_CLASS (widget_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, GDK_TYPE_RGBA);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -251,12 +135,12 @@ drawing_area_apply_stroke (DrawingArea *area,
|
||||
{
|
||||
if (gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER)
|
||||
{
|
||||
cairo_set_line_width (area->cr, 10 * pressure * area->brush_size);
|
||||
cairo_set_line_width (area->cr, 10 * pressure);
|
||||
cairo_set_operator (area->cr, CAIRO_OPERATOR_DEST_OUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_set_line_width (area->cr, 4 * pressure * area->brush_size);
|
||||
cairo_set_line_width (area->cr, 4 * pressure);
|
||||
cairo_set_operator (area->cr, CAIRO_OPERATOR_SATURATE);
|
||||
}
|
||||
|
||||
@@ -264,6 +148,8 @@ drawing_area_apply_stroke (DrawingArea *area,
|
||||
area->draw_color.green, area->draw_color.blue,
|
||||
area->draw_color.alpha * pressure);
|
||||
|
||||
//cairo_set_source_rgba (area->cr, 0, 0, 0, pressure);
|
||||
|
||||
cairo_line_to (area->cr, x, y);
|
||||
cairo_stroke (area->cr);
|
||||
cairo_move_to (area->cr, x, y);
|
||||
@@ -339,15 +225,11 @@ drawing_area_new (void)
|
||||
return g_object_new (drawing_area_get_type (), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
drawing_area_set_color (DrawingArea *area,
|
||||
GdkRGBA *color)
|
||||
{
|
||||
if (gdk_rgba_equal (&area->draw_color, color))
|
||||
return;
|
||||
|
||||
area->draw_color = *color;
|
||||
g_signal_emit (area, area_signals[COLOR_SET], 0, &area->draw_color);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -360,14 +242,6 @@ color_button_color_set (GtkColorButton *button,
|
||||
drawing_area_set_color (draw_area, &color);
|
||||
}
|
||||
|
||||
static void
|
||||
drawing_area_color_set (DrawingArea *area,
|
||||
GdkRGBA *color,
|
||||
GtkColorButton *button)
|
||||
{
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (button), color);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paint (GtkWidget *toplevel)
|
||||
{
|
||||
@@ -389,8 +263,6 @@ do_paint (GtkWidget *toplevel)
|
||||
colorbutton = gtk_color_button_new ();
|
||||
g_signal_connect (colorbutton, "color-set",
|
||||
G_CALLBACK (color_button_color_set), draw_area);
|
||||
g_signal_connect (draw_area, "color-set",
|
||||
G_CALLBACK (drawing_area_color_set), colorbutton);
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (colorbutton),
|
||||
&(GdkRGBA) { 0, 0, 0, 1 });
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ entry_size_allocate_cb (GtkEntry *entry,
|
||||
static void
|
||||
entry_icon_press_cb (GtkEntry *entry,
|
||||
GtkEntryIconPosition icon_pos,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *popover = user_data;
|
||||
|
||||
@@ -151,10 +151,11 @@ create_search_menu (GtkWidget *entry)
|
||||
static void
|
||||
icon_press_cb (GtkEntry *entry,
|
||||
gint position,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (position == GTK_ENTRY_ICON_PRIMARY)
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -26,6 +26,17 @@ changed_cb (GtkEditable *editable)
|
||||
g_message ("changed: %s", text);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_event_cb (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GtkSearchBar *bar)
|
||||
{
|
||||
if (gdk_event_get_event_type (event) == GDK_KEY_PRESS)
|
||||
return gtk_search_bar_handle_event (bar, event);
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
search_changed (GtkSearchEntry *entry,
|
||||
GtkLabel *label)
|
||||
@@ -91,7 +102,7 @@ do_search_entry2 (GtkWidget *do_widget)
|
||||
gtk_box_pack_start (GTK_BOX (vbox), searchbar);
|
||||
|
||||
/* Hook the search bar to key presses */
|
||||
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (searchbar), window);
|
||||
g_signal_connect (window, "event", G_CALLBACK (window_event_cb), searchbar);
|
||||
|
||||
/* Help */
|
||||
label = gtk_label_new ("Start Typing to search");
|
||||
|
||||
@@ -295,7 +295,6 @@ start_puzzle (GdkPaintable *puzzle)
|
||||
grid = gtk_grid_new ();
|
||||
gtk_widget_set_can_focus (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (frame), grid);
|
||||
gtk_aspect_frame_set (GTK_ASPECT_FRAME (frame), 0.5, 0.5, (float) gdk_paintable_get_intrinsic_aspect_ratio (puzzle), FALSE);
|
||||
|
||||
/* Add a key event controller so people can use the arrow
|
||||
* keys to move the puzzle */
|
||||
|
||||
@@ -376,9 +376,10 @@ search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *w
|
||||
|
||||
static void
|
||||
get_image_data (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection,
|
||||
guint target_info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *image;
|
||||
@@ -398,9 +399,10 @@ get_image_data (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
get_scalable_image_data (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection,
|
||||
guint target_info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *uris[2];
|
||||
|
||||
@@ -353,6 +353,7 @@ update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget)
|
||||
static void
|
||||
on_entry_icon_release (GtkEntry *entry,
|
||||
GtkEntryIconPosition icon_pos,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (icon_pos != GTK_ENTRY_ICON_SECONDARY)
|
||||
@@ -966,8 +967,8 @@ background_loaded_cb (GObject *source,
|
||||
return;
|
||||
}
|
||||
|
||||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||||
gtk_widget_set_size_request (child, 110, 70);
|
||||
child = gtk_image_new_from_pixbuf (pixbuf);
|
||||
gtk_widget_show (child);
|
||||
gtk_flow_box_insert (GTK_FLOW_BOX (bd->flowbox), child, -1);
|
||||
child = gtk_widget_get_parent (child);
|
||||
g_object_set_data_full (G_OBJECT (child), "filename", bd->filename, g_free);
|
||||
@@ -995,7 +996,8 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 110, 70);
|
||||
gdk_pixbuf_fill (pixbuf, 0xffffffff);
|
||||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||||
child = gtk_image_new_from_pixbuf (pixbuf);
|
||||
gtk_widget_show (child);
|
||||
gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), child, -1);
|
||||
|
||||
location = "/usr/share/backgrounds/gnome";
|
||||
@@ -1080,7 +1082,7 @@ set_accel (GtkApplication *app, GtkWidget *widget)
|
||||
typedef struct
|
||||
{
|
||||
GtkTextView tv;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
} MyTextView;
|
||||
|
||||
typedef GtkTextViewClass MyTextViewClass;
|
||||
@@ -1093,23 +1095,18 @@ my_text_view_init (MyTextView *tv)
|
||||
}
|
||||
|
||||
static void
|
||||
my_tv_snapshot_layer (GtkTextView *widget,
|
||||
GtkTextViewLayer layer,
|
||||
GtkSnapshot *snapshot)
|
||||
my_tv_draw_layer (GtkTextView *widget,
|
||||
GtkTextViewLayer layer,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MyTextView *tv = (MyTextView *)widget;
|
||||
|
||||
if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->texture)
|
||||
if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT && tv->pixbuf)
|
||||
{
|
||||
gtk_snapshot_push_opacity (snapshot, 0.333);
|
||||
gtk_snapshot_append_texture (snapshot,
|
||||
tv->texture,
|
||||
&GRAPHENE_RECT_INIT(
|
||||
0, 0,
|
||||
gdk_texture_get_width (tv->texture),
|
||||
gdk_texture_get_height (tv->texture)
|
||||
));
|
||||
gtk_snapshot_pop (snapshot);
|
||||
cairo_save (cr);
|
||||
gdk_cairo_set_source_pixbuf (cr, tv->pixbuf, 0.0, 0.0);
|
||||
cairo_paint_with_alpha (cr, 0.333);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1118,7 +1115,7 @@ my_tv_finalize (GObject *object)
|
||||
{
|
||||
MyTextView *tv = (MyTextView *)object;
|
||||
|
||||
g_clear_object (&tv->texture);
|
||||
g_clear_object (&tv->pixbuf);
|
||||
|
||||
G_OBJECT_CLASS (my_text_view_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -1130,24 +1127,20 @@ my_text_view_class_init (MyTextViewClass *class)
|
||||
GObjectClass *o_class = G_OBJECT_CLASS (class);
|
||||
|
||||
o_class->finalize = my_tv_finalize;
|
||||
tv_class->snapshot_layer = my_tv_snapshot_layer;
|
||||
tv_class->draw_layer = my_tv_draw_layer;
|
||||
}
|
||||
|
||||
static void
|
||||
my_text_view_set_background (MyTextView *tv, const gchar *filename)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GFile *file;
|
||||
|
||||
g_clear_object (&tv->texture);
|
||||
g_clear_object (&tv->pixbuf);
|
||||
|
||||
if (filename == NULL)
|
||||
return;
|
||||
|
||||
file = g_file_new_for_path (filename);
|
||||
tv->texture = gdk_texture_new_from_file (file, &error);
|
||||
g_object_unref (file);
|
||||
|
||||
tv->pixbuf = gdk_pixbuf_new_from_file (filename, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
|
||||
@@ -2226,9 +2226,6 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Save the current document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorToolItem"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
@@ -3583,4 +3580,4 @@ bad things might happen.</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
</interface>
|
||||
|
||||
@@ -71,7 +71,7 @@ straightforward manner.
|
||||
void gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time);
|
||||
void gdk_drag_finish (GdkDragContext *context,
|
||||
void gdk_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time);
|
||||
GdkAtom gdk_drag_get_selection (GdkDragContext *context);
|
||||
|
||||
@@ -171,6 +171,7 @@ gdk_rgba_get_type
|
||||
<FILE>gdksurface</FILE>
|
||||
GdkSurface
|
||||
GdkSurfaceType
|
||||
GdkSurfaceClass
|
||||
GdkSurfaceHints
|
||||
GdkGeometry
|
||||
GdkGravity
|
||||
@@ -193,6 +194,7 @@ gdk_surface_is_visible
|
||||
gdk_surface_is_viewable
|
||||
gdk_surface_is_input_only
|
||||
gdk_surface_get_state
|
||||
gdk_surface_withdraw
|
||||
gdk_surface_iconify
|
||||
gdk_surface_deiconify
|
||||
gdk_surface_stick
|
||||
@@ -280,6 +282,8 @@ gdk_surface_get_toplevel
|
||||
gdk_surface_get_children
|
||||
gdk_surface_get_children_with_user_data
|
||||
gdk_surface_peek_children
|
||||
gdk_surface_get_events
|
||||
gdk_surface_set_events
|
||||
gdk_surface_set_icon_name
|
||||
gdk_surface_set_transient_for
|
||||
gdk_surface_set_role
|
||||
@@ -297,6 +301,8 @@ gdk_surface_get_support_multidevice
|
||||
gdk_surface_set_support_multidevice
|
||||
gdk_surface_get_device_cursor
|
||||
gdk_surface_set_device_cursor
|
||||
gdk_surface_get_device_events
|
||||
gdk_surface_set_device_events
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_surface_coords_from_parent
|
||||
@@ -646,7 +652,7 @@ gdk_event_get_scancode
|
||||
gdk_event_get_pointer_emulated
|
||||
gdk_event_get_crossing_detail
|
||||
gdk_event_get_crossing_mode
|
||||
gdk_event_get_drop
|
||||
gdk_event_get_drag_context
|
||||
gdk_event_get_focus_in
|
||||
gdk_event_get_grab_surface
|
||||
gdk_event_get_motion_history
|
||||
@@ -655,6 +661,7 @@ gdk_event_get_key_is_modifier
|
||||
gdk_event_get_pad_axis_value
|
||||
gdk_event_get_pad_button
|
||||
gdk_event_get_pad_group_mode
|
||||
gdk_event_get_string
|
||||
gdk_event_get_touch_emulating_pointer
|
||||
gdk_event_get_touchpad_angle_delta
|
||||
gdk_event_get_touchpad_deltas
|
||||
@@ -691,7 +698,7 @@ gdk_event_get_type
|
||||
|
||||
<SECTION>
|
||||
<FILE>gdkpaintable</FILE>
|
||||
<TITLE>GdkPaintable</TITLE>
|
||||
<TITLE>GdkPaintable/TITLE>
|
||||
GdkPaintable
|
||||
GdkPaintableFlags
|
||||
gdk_paintable_get_current_image
|
||||
@@ -772,60 +779,38 @@ gdk_cursor_get_type
|
||||
<SECTION>
|
||||
<TITLE>Drag and Drop</TITLE>
|
||||
<FILE>dnd</FILE>
|
||||
GdkDrag
|
||||
GdkDrop
|
||||
GdkDragContext
|
||||
GdkDragCancelReason
|
||||
gdk_drag_drop_done
|
||||
gdk_drag_begin
|
||||
GdkDragAction
|
||||
GDK_ACTION_ALL
|
||||
|
||||
gdk_drag_get_display
|
||||
gdk_drag_get_actions
|
||||
gdk_drag_get_suggested_action
|
||||
gdk_drag_get_selected_action
|
||||
gdk_drag_get_formats
|
||||
gdk_drag_get_device
|
||||
gdk_drag_get_drag_surface
|
||||
gdk_drag_set_hotspot
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_drag_action_is_unique
|
||||
|
||||
<SUBSECTION>
|
||||
gdk_drop_get_display
|
||||
gdk_drop_get_device
|
||||
gdk_drop_get_surface
|
||||
gdk_drop_get_formats
|
||||
gdk_drop_get_actions
|
||||
gdk_drop_get_drag
|
||||
gdk_drop_status
|
||||
gdk_drop_finish
|
||||
gdk_drop_read_async
|
||||
gdk_drop_read_finish
|
||||
gdk_drop_read_value_async
|
||||
gdk_drop_read_value_finish
|
||||
gdk_drop_read_text_async
|
||||
gdk_drop_read_text_finish
|
||||
GdkDragAction
|
||||
gdk_drag_status
|
||||
|
||||
gdk_drag_context_get_display
|
||||
gdk_drag_context_get_actions
|
||||
gdk_drag_context_get_suggested_action
|
||||
gdk_drag_context_get_selected_action
|
||||
gdk_drag_context_get_formats
|
||||
gdk_drag_context_get_device
|
||||
gdk_drag_context_get_source_surface
|
||||
gdk_drag_context_get_dest_surface
|
||||
gdk_drag_context_get_drag_surface
|
||||
gdk_drag_context_set_hotspot
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GDK_DRAG
|
||||
GDK_TYPE_DRAG
|
||||
GDK_IS_DRAG
|
||||
GDK_DRAG_CLASS
|
||||
GDK_DRAG_GET_CLASS
|
||||
GDK_IS_DRAG_CLASS
|
||||
GDK_DRAG_CONTEXT
|
||||
GDK_TYPE_DRAG_CONTEXT
|
||||
GDK_IS_DRAG_CONTEXT
|
||||
GDK_DRAG_CONTEXT_CLASS
|
||||
GDK_DRAG_CONTEXT_GET_CLASS
|
||||
GDK_IS_DRAG_CONTEXT_CLASS
|
||||
GDK_TYPE_DRAG_ACTION
|
||||
GDK_TYPE_DRAG_PROTOCOL
|
||||
GDK_TYPE_DROP
|
||||
GDK_DROP
|
||||
GDK_IS_DROP
|
||||
|
||||
<SUBSECTION Private>
|
||||
GdkDragClass
|
||||
gdk_drag_get_type
|
||||
GdkDropClass
|
||||
gdk_drop_get_type
|
||||
GdkDragContextClass
|
||||
gdk_drag_context_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
@@ -868,6 +853,7 @@ gdk_x11_screen_lookup_visual
|
||||
gdk_x11_screen_supports_net_wm_hint
|
||||
gdk_x11_screen_get_number_of_desktops
|
||||
gdk_x11_screen_get_current_desktop
|
||||
gdk_x11_surface_foreign_new_for_display
|
||||
gdk_x11_surface_lookup_for_display
|
||||
gdk_x11_surface_get_xid
|
||||
gdk_x11_surface_set_theme_variant
|
||||
@@ -1264,7 +1250,6 @@ gdk_clipboard_get_type
|
||||
<SECTION>
|
||||
<FILE>gdkcontentprovider</FILE>
|
||||
GdkContentProvider
|
||||
GdkContentProviderClass
|
||||
gdk_content_provider_new_for_value
|
||||
gdk_content_provider_new_for_bytes
|
||||
gdk_content_provider_ref_formats
|
||||
@@ -1280,6 +1265,7 @@ GDK_CONTENT_PROVIDER_CLASS
|
||||
GDK_CONTENT_PROVIDER_GET_CLASS
|
||||
GDK_IS_CONTENT_PROVIDER
|
||||
GDK_IS_CONTENT_PROVIDER_CLASS
|
||||
GdkContentProviderClass
|
||||
gdk_content_provider_get_type
|
||||
</SECTION>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ gdk_app_launch_context_get_type
|
||||
gdk_clipboard_get_type
|
||||
gdk_content_deserializer_get_type
|
||||
gdk_content_formats_get_type
|
||||
gdk_content_provider_get_type
|
||||
gdk_content_serializer_get_type
|
||||
gdk_cursor_get_type
|
||||
gdk_device_get_type
|
||||
@@ -10,8 +9,7 @@ gdk_device_pad_get_type
|
||||
gdk_device_tool_get_type
|
||||
gdk_display_get_type
|
||||
gdk_display_manager_get_type
|
||||
gdk_drag_get_type
|
||||
gdk_drop_get_type
|
||||
gdk_drag_context_get_type
|
||||
gdk_event_get_type
|
||||
gdk_frame_clock_get_type
|
||||
gdk_gl_context_get_type
|
||||
|
||||
@@ -87,22 +87,16 @@ images = [
|
||||
'images/zoom_out_cursor.png',
|
||||
]
|
||||
|
||||
src_dir = [ gdkinc ]
|
||||
|
||||
if x11_enabled
|
||||
src_dir += [ gdkx11_inc ]
|
||||
endif
|
||||
|
||||
if wayland_enabled
|
||||
src_dir += [ gdkwayland_inc ]
|
||||
endif
|
||||
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
|
||||
gnome.gtkdoc('gdk4',
|
||||
mode: 'none',
|
||||
main_xml: 'gdk4-docs.xml',
|
||||
src_dir: src_dir,
|
||||
src_dir: [
|
||||
gdkinc,
|
||||
gdkx11_inc,
|
||||
gdkwayland_inc,
|
||||
],
|
||||
dependencies: libgtk_dep,
|
||||
gobject_typesfile: join_paths(meson.current_source_dir(), 'gdk4.types'),
|
||||
scan_args: [
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
here</ulink>.</para>
|
||||
|
||||
<para>Finally the window size is set using gtk_window_set_default_size and
|
||||
the window is then shown by GTK via gtk_widget_show().</para>
|
||||
the window is then shown by GTK via gtk_widget_show_all().</para>
|
||||
|
||||
<para>When you exit the window, by for example pressing the X,
|
||||
the g_application_run() in the main loop returns with a number
|
||||
@@ -488,28 +488,23 @@ example_app_window_class_init (ExampleAppWindowClass *class)
|
||||
<para>In this step, we make our application show the content of
|
||||
all the files that it is given on the commandline.</para>
|
||||
|
||||
<para>To this end, we add a member to the struct in application
|
||||
<para>To this end, we add a private struct to our application
|
||||
window subclass and keep a reference to the #GtkStack there.
|
||||
The first member of the struct should be the parent type from
|
||||
which the class is derived. Here, ExampleAppWindow is derived
|
||||
from GtkApplicationWindow.
|
||||
The gtk_widget_class_bind_template_child() function
|
||||
The gtk_widget_class_bind_template_child_private() function
|
||||
arranges things so that after instantiating the template, the
|
||||
@stack member of the struct will point to the widget of
|
||||
@stack member of the private struct will point to the widget of
|
||||
the same name from the template.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><![CDATA[
|
||||
...
|
||||
|
||||
struct _ExampleAppWindow
|
||||
struct _ExampleAppWindowPrivate
|
||||
{
|
||||
GtkApplicationWindow parent;
|
||||
|
||||
GtkWidget *stack;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
...
|
||||
|
||||
@@ -518,7 +513,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
|
||||
{
|
||||
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||
"/org/gtk/exampleapp/window.ui");
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||
}
|
||||
|
||||
...
|
||||
@@ -538,21 +533,25 @@ void
|
||||
example_app_window_open (ExampleAppWindow *win,
|
||||
GFile *file)
|
||||
{
|
||||
ExampleAppWindowPrivate *priv;
|
||||
gchar *basename;
|
||||
GtkWidget *scrolled, *view;
|
||||
gchar *contents;
|
||||
gsize length;
|
||||
|
||||
priv = example_app_window_get_instance_private (win);
|
||||
basename = g_file_get_basename (file);
|
||||
|
||||
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_widget_show (scrolled);
|
||||
gtk_widget_set_hexpand (scrolled, TRUE);
|
||||
gtk_widget_set_vexpand (scrolled, TRUE);
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_widget_show (view);
|
||||
gtk_container_add (GTK_CONTAINER (scrolled), view);
|
||||
gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
|
||||
gtk_stack_add_titled (GTK_STACK (priv->stack), scrolled, basename, basename);
|
||||
|
||||
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
|
||||
{
|
||||
@@ -719,11 +718,14 @@ example_app_class_init (ExampleAppClass *class)
|
||||
static void
|
||||
example_app_window_init (ExampleAppWindow *win)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (win));
|
||||
win->settings = g_settings_new ("org.gtk.exampleapp");
|
||||
ExampleAppWindowPrivate *priv;
|
||||
|
||||
g_settings_bind (win->settings, "transition",
|
||||
win->stack, "transition-type",
|
||||
priv = example_app_window_get_instance_private (win);
|
||||
gtk_widget_init_template (GTK_WIDGET (win));
|
||||
priv->settings = g_settings_new ("org.gtk.exampleapp");
|
||||
|
||||
g_settings_bind (priv->settings, "transition",
|
||||
priv->stack, "transition-type",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -821,6 +823,7 @@ static void
|
||||
search_text_changed (GtkEntry *entry,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
ExampleAppWindowPrivate *priv;
|
||||
const gchar *text;
|
||||
GtkWidget *tab;
|
||||
GtkWidget *view;
|
||||
@@ -832,7 +835,9 @@ search_text_changed (GtkEntry *entry,
|
||||
if (text[0] == '\0')
|
||||
return;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
priv = example_app_window_get_instance_private (win);
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));
|
||||
view = gtk_bin_get_child (GTK_BIN (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
@@ -973,12 +978,12 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
{
|
||||
...
|
||||
|
||||
action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
|
||||
action = (GAction*) g_property_action_new ("show-lines", priv->lines, "visible");
|
||||
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||
g_object_unref (action);
|
||||
|
||||
g_object_bind_property (win->lines, "visible",
|
||||
win->lines_label, "visible",
|
||||
g_object_bind_property (priv->lines, "visible",
|
||||
priv->lines_label, "visible",
|
||||
G_BINDING_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@@ -385,6 +385,7 @@
|
||||
<xi:include href="osx.sgml" />
|
||||
<xi:include href="broadway.xml" />
|
||||
<xi:include href="wayland.xml" />
|
||||
<xi:include href="mir.xml" />
|
||||
</part>
|
||||
|
||||
<xi:include href="glossary.xml" />
|
||||
|
||||
@@ -679,6 +679,8 @@ gtk_combo_box_get_active_id
|
||||
gtk_combo_box_set_active_id
|
||||
gtk_combo_box_get_model
|
||||
gtk_combo_box_set_model
|
||||
gtk_combo_box_popup_for_device
|
||||
gtk_combo_box_popup
|
||||
gtk_combo_box_popdown
|
||||
gtk_combo_box_get_popup_accessible
|
||||
gtk_combo_box_get_row_separator_func
|
||||
@@ -1722,6 +1724,8 @@ gtk_menu_attach
|
||||
gtk_menu_popup_at_rect
|
||||
gtk_menu_popup_at_widget
|
||||
gtk_menu_popup_at_pointer
|
||||
gtk_menu_popup_for_device
|
||||
gtk_menu_popup
|
||||
gtk_menu_set_accel_group
|
||||
gtk_menu_get_accel_group
|
||||
gtk_menu_set_accel_path
|
||||
@@ -4861,6 +4865,7 @@ gtk_style_context_get_parent
|
||||
gtk_style_context_get_path
|
||||
gtk_style_context_get_property
|
||||
gtk_style_context_get_display
|
||||
gtk_style_context_get_frame_clock
|
||||
gtk_style_context_get_state
|
||||
gtk_style_context_get_valist
|
||||
gtk_style_context_get_section
|
||||
@@ -4883,6 +4888,7 @@ gtk_style_context_remove_class
|
||||
gtk_style_context_has_class
|
||||
gtk_style_context_list_classes
|
||||
gtk_style_context_set_display
|
||||
gtk_style_context_set_frame_clock
|
||||
gtk_style_context_set_state
|
||||
gtk_style_context_set_scale
|
||||
gtk_style_context_get_scale
|
||||
@@ -4903,10 +4909,12 @@ gtk_render_check
|
||||
gtk_render_expander
|
||||
gtk_render_focus
|
||||
gtk_render_frame
|
||||
gtk_render_frame_gap
|
||||
gtk_render_handle
|
||||
gtk_render_layout
|
||||
gtk_render_line
|
||||
gtk_render_option
|
||||
gtk_render_slider
|
||||
gtk_render_activity
|
||||
gtk_render_icon
|
||||
gtk_render_insertion_cursor
|
||||
@@ -4930,6 +4938,7 @@ gtk_border_get_type
|
||||
<FILE>gtkcssprovider</FILE>
|
||||
<TITLE>GtkCssProvider</TITLE>
|
||||
GtkCssProvider
|
||||
gtk_css_provider_get_default
|
||||
gtk_css_provider_get_named
|
||||
gtk_css_provider_load_from_data
|
||||
gtk_css_provider_load_from_file
|
||||
@@ -5006,7 +5015,6 @@ gtk_selection_data_get_type
|
||||
<TITLE>Drag and Drop</TITLE>
|
||||
GtkDestDefaults
|
||||
GtkDragResult
|
||||
|
||||
<SUBSECTION Destination Side>
|
||||
gtk_drag_dest_set
|
||||
gtk_drag_dest_unset
|
||||
@@ -5018,13 +5026,13 @@ gtk_drag_dest_add_image_targets
|
||||
gtk_drag_dest_add_uri_targets
|
||||
gtk_drag_dest_set_track_motion
|
||||
gtk_drag_dest_get_track_motion
|
||||
gtk_drag_finish
|
||||
gtk_drag_get_data
|
||||
gtk_drag_get_source_widget
|
||||
gtk_drag_highlight
|
||||
gtk_drag_unhighlight
|
||||
|
||||
<SUBSECTION Source Side>
|
||||
gtk_drag_begin
|
||||
gtk_drag_begin_with_coordinates
|
||||
gtk_drag_cancel
|
||||
gtk_drag_set_icon_widget
|
||||
gtk_drag_set_icon_paintable
|
||||
@@ -6009,8 +6017,6 @@ gtk_overlay_get_overlay_pass_through
|
||||
gtk_overlay_set_overlay_pass_through
|
||||
gtk_overlay_get_measure_overlay
|
||||
gtk_overlay_set_measure_overlay
|
||||
gtk_overlay_get_clip_overlay
|
||||
gtk_overlay_set_clip_overlay
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_OVERLAY
|
||||
@@ -6458,7 +6464,7 @@ gtk_gesture_single_get_type
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkeventcontrollerscroll</FILE>
|
||||
<TITLE>GtkEventControllerScroll</TITLE>
|
||||
<TITLE>GtkEventControlerScroll</TITLE>
|
||||
GtkEventControllerScroll
|
||||
GtkEventControllerScrollFlags
|
||||
gtk_event_controller_scroll_new
|
||||
@@ -6479,7 +6485,7 @@ gtk_event_controller_scroll_get_type
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkeventcontrollermotion</FILE>
|
||||
<TITLE>GtkEventControllerMotion</TITLE>
|
||||
<TITLE>GtkEventControlerMotion</TITLE>
|
||||
GtkEventControllerMotion
|
||||
gtk_event_controller_motion_new
|
||||
|
||||
@@ -6497,7 +6503,7 @@ gtk_event_controller_motion_get_type
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkeventcontrollerkey</FILE>
|
||||
<TITLE>GtkEventControllerKey</TITLE>
|
||||
<TITLE>GtkEventControlerKey</TITLE>
|
||||
GtkEventControllerKey
|
||||
gtk_event_controller_key_new
|
||||
|
||||
|
||||
@@ -118,7 +118,6 @@ gtk_page_setup_get_type
|
||||
@DISABLE_ON_W32@gtk_page_setup_unix_dialog_get_type
|
||||
gtk_paned_get_type
|
||||
gtk_paper_size_get_type
|
||||
gtk_picture_get_type
|
||||
gtk_popover_get_type
|
||||
gtk_popover_menu_get_type
|
||||
@DISABLE_ON_W32@gtk_printer_get_type
|
||||
|
||||
@@ -179,6 +179,41 @@
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="event-masks">
|
||||
<title>Event masks</title>
|
||||
|
||||
<para>
|
||||
Each widget instance has a basic event mask and another per input device,
|
||||
which determine the types of input event it receives. Each event mask set
|
||||
on a widget is added to the corresponding (basic or per-device) event mask
|
||||
for the widget’s #GdkSurface, and all child #GdkSurfaces.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Filtering events against event masks happens inside #GdkSurface, which
|
||||
exposes event masks to the windowing system to reduce the number of events
|
||||
GDK receives from it. On receiving an event, it is filtered against the
|
||||
#GdkSurface’s mask for the input device, if set. Otherwise, it is filtered
|
||||
against the #GdkSurface’s basic event mask.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This means that widgets must add to the event mask for each event type
|
||||
they expect to receive, using gtk_widget_set_events() or
|
||||
gtk_widget_add_events() to preserve the existing mask. Widgets which are
|
||||
aware of floating devices should use gtk_widget_set_device_events() or
|
||||
gtk_widget_add_device_events(), and must explicitly enable the device
|
||||
using gtk_widget_set_device_enabled(). See the #GdkDeviceManager
|
||||
documentation for more information.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
All standard widgets set the event mask for all events they expect to
|
||||
receive, and it is not necessary to modify this. Masks should be set when
|
||||
implementing a new widget.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Touch events</title>
|
||||
|
||||
|
||||
@@ -355,6 +355,7 @@ content_files = [
|
||||
'input-handling.xml',
|
||||
'migrating-2to4.xml',
|
||||
'migrating-3to4.xml',
|
||||
'mir.xml',
|
||||
'osx.sgml',
|
||||
'other_software.sgml',
|
||||
'overview.xml',
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
<para>
|
||||
The steps outlined in the following sections assume that your
|
||||
application is working with GTK+ 3.24, which is the final stable
|
||||
application is working with GTK+ 3.22, which is the final stable
|
||||
release of GTK+ 3.x. It includes all the necessary APIs and tools
|
||||
to help you port your application to GTK+ 4. If you are still using
|
||||
an older version of GTK+ 3.x, you should first get your application
|
||||
to build and work with the latest minor release in the 3.24 series.
|
||||
to build and work with the latest minor release in the 3.22 series.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
@@ -34,7 +34,7 @@
|
||||
widgets have been deprecated. These deprecations are clearly spelled
|
||||
out in the API reference, with hints about the recommended replacements.
|
||||
The API reference for GTK+ 3 also includes an
|
||||
<ulink url="https://developer.gnome.org/gtk3/3.24/api-index-deprecated.html">index</ulink> of all deprecated symbols.
|
||||
<ulink url="https://developer.gnome.org/gtk3/3.22/api-index-deprecated.html">index</ulink> of all deprecated symbols.
|
||||
</para>
|
||||
<para>
|
||||
To verify that your program does not use any deprecated symbols,
|
||||
@@ -79,13 +79,13 @@
|
||||
<title>Review your window creation flags</title>
|
||||
<para>
|
||||
GTK+ 4 removes the GDK_WA_CURSOR flag. Instead, just use
|
||||
gdk_window_set_cursor() to set a cursor on the window after
|
||||
gdk_surface_set_cursor() to set a cursor on the window after
|
||||
creating it.
|
||||
</para>
|
||||
<para>
|
||||
GTK+ 4 also removes the GDK_WA_VISUAL flag, and always uses
|
||||
an RGBA visual for windows. To prepare your code for this,
|
||||
use gdk_window_set_visual (gdk_screen_get_rgba_visual ()) after
|
||||
use gdk_surface_set_visual (gdk_screen_get_rgba_visual ()) after
|
||||
creating your window.
|
||||
</para>
|
||||
<para>
|
||||
@@ -169,14 +169,6 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Stop using GtkWidget event signals</title>
|
||||
<para>
|
||||
Event controllers and #GtkGestures replace event signals in GTK+ 4. They
|
||||
have been backported to GTK+ 3.x so you can prepare for this change.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -319,15 +311,6 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Adapt to GtkWidget's size allocation changes</title>
|
||||
<para>
|
||||
The #GtkWidget::size-allocate signal now takes the baseline as an
|
||||
argument, so you no longer need to call gtk_widget_get_allocated_baseline()
|
||||
to get it.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Switch to GtkWidget's children APIs</title>
|
||||
<para>
|
||||
@@ -449,7 +432,8 @@
|
||||
<title>GtkWidget event signals are removed</title>
|
||||
<para>
|
||||
Event controllers and #GtkGestures have already been introduced in GTK+ 3 to handle
|
||||
input for many cases. In GTK+ 4, the traditional widget signals for handling input,
|
||||
input for many cases. In GTK+ 4, even more are available, such as #GtkEventControllerScroll
|
||||
and GtkEventControllerMotion, and the traditional widget signals for handling input,
|
||||
such as #GtkWidget::motion-event or #GtkWidget::event have been removed.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
35
docs/reference/gtk/mir.xml
Normal file
35
docs/reference/gtk/mir.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||
]>
|
||||
<refentry id="gtk-mir">
|
||||
<refmeta>
|
||||
<refentrytitle>Using GTK+ with Mir</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo>GTK Library</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>Using GTK+ with Mir</refname>
|
||||
<refpurpose>
|
||||
Mir-specific aspects of using GTK+
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Using GTK+ with Mir</title>
|
||||
|
||||
<para>
|
||||
The GDK Mir backend provides support for running GTK+ applications
|
||||
under Mir based display servers. To run your application in this way,
|
||||
select the Mir backend by setting <literal>GDK_BACKEND=mir</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Currently, the Mir backend does not use any additional commandline
|
||||
options or environment variables.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
@@ -435,6 +435,11 @@ nevertheless.
|
||||
<listitem><para>Selects the Wayland backend for connecting to Wayland display servers</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>mir</term>
|
||||
<listitem><para>Selects the Mir backend for connecting to Mir display servers</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
Since 3.10, this environment variable can contain a comma-separated list
|
||||
of backend names, which are tried in order. The list may also contain
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static gboolean
|
||||
window_key_pressed (GtkEventController *controller,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
GdkModifierType state,
|
||||
GtkSearchBar *search_bar)
|
||||
{
|
||||
return gtk_search_bar_handle_event (search_bar,
|
||||
gtk_get_current_event ());
|
||||
}
|
||||
|
||||
static void
|
||||
activate_cb (GtkApplication *app,
|
||||
gpointer user_data)
|
||||
@@ -9,12 +20,12 @@ activate_cb (GtkApplication *app,
|
||||
GtkWidget *box;
|
||||
GtkWidget *entry;
|
||||
GtkWidget *menu_button;
|
||||
GtkEventController *controller;
|
||||
|
||||
window = gtk_application_window_new (app);
|
||||
gtk_widget_show (window);
|
||||
|
||||
search_bar = gtk_search_bar_new ();
|
||||
gtk_widget_set_valign (search_bar, GTK_ALIGN_START);
|
||||
gtk_container_add (GTK_CONTAINER (window), search_bar);
|
||||
gtk_widget_show (search_bar);
|
||||
|
||||
@@ -29,7 +40,12 @@ activate_cb (GtkApplication *app,
|
||||
gtk_box_pack_start (GTK_BOX (box), menu_button);
|
||||
|
||||
gtk_search_bar_connect_entry (GTK_SEARCH_BAR (search_bar), GTK_ENTRY (entry));
|
||||
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (search_bar), window);
|
||||
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_object_set_data_full (G_OBJECT (window), "controller", controller, g_object_unref);
|
||||
g_signal_connect (controller, "key-pressed",
|
||||
G_CALLBACK (window_key_pressed), search_bar);
|
||||
gtk_widget_add_controller (window, controller);
|
||||
}
|
||||
|
||||
gint
|
||||
|
||||
@@ -61,6 +61,9 @@ static GdkSurface * gdk_broadway_device_surface_at_position (GdkDevice *de
|
||||
gdouble *win_y,
|
||||
GdkModifierType *mask,
|
||||
gboolean get_toplevel);
|
||||
static void gdk_broadway_device_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkEventMask event_mask);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GdkBroadwayDevice, gdk_broadway_device, GDK_TYPE_DEVICE)
|
||||
@@ -78,6 +81,7 @@ gdk_broadway_device_class_init (GdkBroadwayDeviceClass *klass)
|
||||
device_class->grab = gdk_broadway_device_grab;
|
||||
device_class->ungrab = gdk_broadway_device_ungrab;
|
||||
device_class->surface_at_position = gdk_broadway_device_surface_at_position;
|
||||
device_class->select_surface_events = gdk_broadway_device_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -321,3 +325,9 @@ gdk_broadway_device_surface_at_position (GdkDevice *device,
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_device_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ struct _GdkBroadwayDisplay
|
||||
/* Keyboard related information */
|
||||
GdkKeymap *keymap;
|
||||
|
||||
/* drag and drop information */
|
||||
GdkDragContext *current_dest_drag;
|
||||
|
||||
GdkBroadwayServer *server;
|
||||
|
||||
gpointer move_resize_data;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkproperty.h"
|
||||
@@ -34,56 +34,56 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define GDK_TYPE_BROADWAY_DRAG (gdk_broadway_drag_get_type ())
|
||||
#define GDK_BROADWAY_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_BROADWAY_DRAG, GdkBroadwayDrag))
|
||||
#define GDK_BROADWAY_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_DRAG, GdkBroadwayDragClass))
|
||||
#define GDK_IS_BROADWAY_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_BROADWAY_DRAG))
|
||||
#define GDK_IS_BROADWAY_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_DRAG))
|
||||
#define GDK_BROADWAY_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_DRAG, GdkBroadwayDragClass))
|
||||
#define GDK_TYPE_BROADWAY_DRAG_CONTEXT (gdk_broadway_drag_context_get_type ())
|
||||
#define GDK_BROADWAY_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_BROADWAY_DRAG_CONTEXT, GdkBroadwayDragContext))
|
||||
#define GDK_BROADWAY_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_DRAG_CONTEXT, GdkBroadwayDragContextClass))
|
||||
#define GDK_IS_BROADWAY_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_BROADWAY_DRAG_CONTEXT))
|
||||
#define GDK_IS_BROADWAY_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_DRAG_CONTEXT))
|
||||
#define GDK_BROADWAY_DRAG_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_DRAG_CONTEXT, GdkBroadwayDragContextClass))
|
||||
|
||||
#ifdef GDK_COMPILATION
|
||||
typedef struct _GdkBroadwayDrag GdkBroadwayDrag;
|
||||
typedef struct _GdkBroadwayDragContext GdkBroadwayDragContext;
|
||||
#else
|
||||
typedef GdkDrag GdkBroadwayDrag;
|
||||
typedef GdkDragContext GdkBroadwayDragContext;
|
||||
#endif
|
||||
typedef struct _GdkBroadwayDragClass GdkBroadwayDragClass;
|
||||
typedef struct _GdkBroadwayDragContextClass GdkBroadwayDragContextClass;
|
||||
|
||||
GType gdk_broadway_drag_get_type (void);
|
||||
GType gdk_broadway_drag_context_get_type (void);
|
||||
|
||||
struct _GdkBroadwayDrag {
|
||||
GdkDrag context;
|
||||
struct _GdkBroadwayDragContext {
|
||||
GdkDragContext context;
|
||||
};
|
||||
|
||||
struct _GdkBroadwayDragClass
|
||||
struct _GdkBroadwayDragContextClass
|
||||
{
|
||||
GdkDragClass parent_class;
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
|
||||
static void gdk_broadway_drag_finalize (GObject *object);
|
||||
static void gdk_broadway_drag_context_finalize (GObject *object);
|
||||
|
||||
static GList *contexts;
|
||||
|
||||
G_DEFINE_TYPE (GdkBroadwayDrag, gdk_broadway_drag, GDK_TYPE_DRAG)
|
||||
G_DEFINE_TYPE (GdkBroadwayDragContext, gdk_broadway_drag_context, GDK_TYPE_DRAG_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_init (GdkBroadwayDrag *dragcontext)
|
||||
gdk_broadway_drag_context_init (GdkBroadwayDragContext *dragcontext)
|
||||
{
|
||||
contexts = g_list_prepend (contexts, dragcontext);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_finalize (GObject *object)
|
||||
gdk_broadway_drag_context_finalize (GObject *object)
|
||||
{
|
||||
GdkDrag *context = GDK_DRAG (object);
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (object);
|
||||
|
||||
contexts = g_list_remove (contexts, context);
|
||||
|
||||
G_OBJECT_CLASS (gdk_broadway_drag_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (gdk_broadway_drag_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/* Drag Contexts */
|
||||
|
||||
GdkDrag *
|
||||
GdkDragContext *
|
||||
_gdk_broadway_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
@@ -91,12 +91,12 @@ _gdk_broadway_surface_drag_begin (GdkSurface *surface,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkDrag *new_context;
|
||||
GdkDragContext *new_context;
|
||||
|
||||
g_return_val_if_fail (surface != NULL, NULL);
|
||||
g_return_val_if_fail (GDK_SURFACE_IS_BROADWAY (surface), NULL);
|
||||
|
||||
new_context = g_object_new (GDK_TYPE_BROADWAY_DRAG,
|
||||
new_context = g_object_new (GDK_TYPE_BROADWAY_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
"content", content,
|
||||
NULL);
|
||||
@@ -104,6 +104,38 @@ _gdk_broadway_surface_drag_begin (GdkSurface *surface,
|
||||
return new_context;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drag_drop (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drag_abort (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
/* Destination side */
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_surface_register_dnd (GdkSurface *surface)
|
||||
{
|
||||
@@ -115,9 +147,15 @@ _gdk_broadway_display_init_dnd (GdkDisplay *display)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_drag_class_init (GdkBroadwayDragClass *klass)
|
||||
gdk_broadway_drag_context_class_init (GdkBroadwayDragContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_broadway_drag_finalize;
|
||||
object_class->finalize = gdk_broadway_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_broadway_drag_context_drag_status;
|
||||
context_class->drag_abort = gdk_broadway_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_broadway_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_broadway_drag_context_drop_finish;
|
||||
}
|
||||
|
||||
@@ -285,6 +285,7 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
|
||||
event->key.state = message->key.state;
|
||||
event->key.hardware_keycode = message->key.key;
|
||||
gdk_event_set_scancode (event, message->key.key);
|
||||
event->key.length = 0;
|
||||
gdk_event_set_device (event, gdk_seat_get_keyboard (seat));
|
||||
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
|
||||
@@ -46,7 +46,7 @@ void gdk_broadway_surface_set_nodes (GdkSurface *surface,
|
||||
GPtrArray *node_textures);
|
||||
|
||||
void _gdk_broadway_surface_register_dnd (GdkSurface *surface);
|
||||
GdkDrag * _gdk_broadway_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDragContext * _gdk_broadway_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
@@ -101,6 +101,7 @@ void _gdk_broadway_display_get_maximal_cursor_size (GdkDisplay *display,
|
||||
void _gdk_broadway_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes);
|
||||
gint _gdk_broadway_display_text_property_to_utf8_list (GdkDisplay *display,
|
||||
GdkAtom encoding,
|
||||
|
||||
@@ -207,6 +207,7 @@ void
|
||||
_gdk_broadway_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes)
|
||||
{
|
||||
GdkSurfaceImplBroadway *impl;
|
||||
@@ -322,7 +323,11 @@ gdk_surface_broadway_show (GdkSurface *surface,
|
||||
impl = GDK_SURFACE_IMPL_BROADWAY (surface->impl);
|
||||
impl->visible = TRUE;
|
||||
|
||||
/* FIXME: update state ? */
|
||||
if (surface->event_mask & GDK_STRUCTURE_MASK)
|
||||
_gdk_make_event (GDK_SURFACE (surface), GDK_MAP, NULL, FALSE);
|
||||
|
||||
if (surface->parent && surface->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
|
||||
_gdk_make_event (GDK_SURFACE (surface), GDK_MAP, NULL, FALSE);
|
||||
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
|
||||
if (_gdk_broadway_server_surface_show (broadway_display->server, impl->id))
|
||||
@@ -339,7 +344,11 @@ gdk_surface_broadway_hide (GdkSurface *surface)
|
||||
impl = GDK_SURFACE_IMPL_BROADWAY (surface->impl);
|
||||
impl->visible = FALSE;
|
||||
|
||||
/* FIXME: update state ? */
|
||||
if (surface->event_mask & GDK_STRUCTURE_MASK)
|
||||
_gdk_make_event (GDK_SURFACE (surface), GDK_UNMAP, NULL, FALSE);
|
||||
|
||||
if (surface->parent && surface->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
|
||||
_gdk_make_event (GDK_SURFACE (surface), GDK_UNMAP, NULL, FALSE);
|
||||
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
|
||||
|
||||
@@ -611,6 +620,24 @@ gdk_surface_broadway_get_device_state (GdkSurface *surface,
|
||||
return child != NULL;
|
||||
}
|
||||
|
||||
static GdkEventMask
|
||||
gdk_surface_broadway_get_events (GdkSurface *surface)
|
||||
{
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_broadway_set_events (GdkSurface *surface,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
if (!GDK_SURFACE_DESTROYED (surface))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_broadway_input_shape_combine_region (GdkSurface *surface,
|
||||
const cairo_region_t *shape_region,
|
||||
@@ -1332,6 +1359,8 @@ gdk_surface_impl_broadway_class_init (GdkSurfaceImplBroadwayClass *klass)
|
||||
impl_class->show = gdk_surface_broadway_show;
|
||||
impl_class->hide = gdk_surface_broadway_hide;
|
||||
impl_class->withdraw = gdk_surface_broadway_withdraw;
|
||||
impl_class->set_events = gdk_surface_broadway_set_events;
|
||||
impl_class->get_events = gdk_surface_broadway_get_events;
|
||||
impl_class->raise = gdk_surface_broadway_raise;
|
||||
impl_class->lower = gdk_surface_broadway_lower;
|
||||
impl_class->restack_toplevel = gdk_surface_broadway_restack_toplevel;
|
||||
|
||||
@@ -43,19 +43,8 @@ clienthtml_h = custom_target('clienthtml.h',
|
||||
],
|
||||
)
|
||||
|
||||
broadwayjs_h = custom_target('broadwayjs.h',
|
||||
input : ['broadway.js'],
|
||||
output : 'broadwayjs.h',
|
||||
command : [
|
||||
gen_c_array,
|
||||
'--array-name=broadway_js',
|
||||
'--output=@OUTPUT@',
|
||||
'@INPUT0@',
|
||||
],
|
||||
)
|
||||
|
||||
libgdk_broadway = static_library('gdk-broadway',
|
||||
clienthtml_h, broadwayjs_h,
|
||||
clienthtml_h,
|
||||
gdk_broadway_sources, gdkconfig, gdkenum_h,
|
||||
include_directories: [confinc, gdkinc],
|
||||
c_args: [
|
||||
@@ -69,6 +58,17 @@ libgdk_broadway = static_library('gdk-broadway',
|
||||
|
||||
broadwayd_syslib = os_win32 ? find_library('ws2_32') : shmlib
|
||||
|
||||
broadwayjs_h = custom_target('broadwayjs.h',
|
||||
input : ['broadway.js'],
|
||||
output : 'broadwayjs.h',
|
||||
command : [
|
||||
gen_c_array,
|
||||
'--array-name=broadway_js',
|
||||
'--output=@OUTPUT@',
|
||||
'@INPUT0@',
|
||||
],
|
||||
)
|
||||
|
||||
executable('gtk4-broadwayd',
|
||||
clienthtml_h, broadwayjs_h,
|
||||
'broadwayd.c', 'broadway-server.c', 'broadway-output.c',
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkAppLaunchContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkClipboard, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkContentProvider, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkCursor, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDevice, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplayManager, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrag, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDragContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawingContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkFrameClock, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLContext, g_object_unref)
|
||||
|
||||
@@ -33,6 +33,4 @@ void gdk_display_set_cursor_theme (GdkDisplay *display,
|
||||
int size);
|
||||
gboolean gdk_running_in_sandbox (void);
|
||||
|
||||
const gchar * gdk_get_startup_notification_id (void);
|
||||
|
||||
#endif /* __GDK__PRIVATE_H__ */
|
||||
|
||||
50
gdk/gdk.c
50
gdk/gdk.c
@@ -154,36 +154,6 @@ static const GDebugKey gdk_debug_keys[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef G_HAS_CONSTRUCTORS
|
||||
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
|
||||
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(stash_desktop_startup_notification_id)
|
||||
#endif
|
||||
G_DEFINE_CONSTRUCTOR(stash_desktop_startup_notification_id)
|
||||
#endif
|
||||
|
||||
static gchar *startup_notification_id = NULL;
|
||||
|
||||
static void
|
||||
stash_desktop_startup_notification_id (void)
|
||||
{
|
||||
const char *desktop_startup_id;
|
||||
|
||||
desktop_startup_id = g_getenv ("DESKTOP_STARTUP_ID");
|
||||
if (desktop_startup_id && *desktop_startup_id != '\0')
|
||||
{
|
||||
if (!g_utf8_validate (desktop_startup_id, -1, NULL))
|
||||
g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
|
||||
else
|
||||
startup_notification_id = g_strdup (desktop_startup_id ? desktop_startup_id : "");
|
||||
}
|
||||
|
||||
/* Clear the environment variable so it won't be inherited by
|
||||
* child processes and confuse things.
|
||||
*/
|
||||
g_unsetenv ("DESKTOP_STARTUP_ID");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
register_resources (gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
@@ -216,10 +186,6 @@ gdk_pre_parse (void)
|
||||
G_N_ELEMENTS (gdk_debug_keys));
|
||||
}
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
#ifndef G_HAS_CONSTRUCTORS
|
||||
stash_desktop_startup_notification_id ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*< private >
|
||||
@@ -250,22 +216,6 @@ gdk_display_open_default (void)
|
||||
return display;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
*
|
||||
* gdk_get_startup_notification_id
|
||||
*
|
||||
* Returns the original value of the DESKTOP_STARTUP_ID environment
|
||||
* variable if it was defined and valid, or %NULL otherwise.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the original value of the
|
||||
* DESKTOP_STARTUP_ID environment variable, or %NULL.
|
||||
*/
|
||||
const gchar *
|
||||
gdk_get_startup_notification_id (void)
|
||||
{
|
||||
return startup_notification_id;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_running_in_sandbox (void)
|
||||
{
|
||||
|
||||
@@ -44,9 +44,8 @@
|
||||
#include <gdk/gdkdevicetool.h>
|
||||
#include <gdk/gdkdisplay.h>
|
||||
#include <gdk/gdkdisplaymanager.h>
|
||||
#include <gdk/gdkdrag.h>
|
||||
#include <gdk/gdkdnd.h>
|
||||
#include <gdk/gdkdrawcontext.h>
|
||||
#include <gdk/gdkdrop.h>
|
||||
#include <gdk/gdkenumtypes.h>
|
||||
#include <gdk/gdkevents.h>
|
||||
#include <gdk/gdkframeclock.h>
|
||||
|
||||
@@ -716,7 +716,8 @@ file_uri_deserializer_finish (GObject *source,
|
||||
return;
|
||||
}
|
||||
|
||||
str = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
str = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (
|
||||
g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (stream))));
|
||||
uris = g_uri_list_extract_uris (str);
|
||||
g_free (str);
|
||||
|
||||
@@ -737,8 +738,6 @@ file_uri_deserializer_finish (GObject *source,
|
||||
g_value_take_boxed (value, g_slist_reverse (l));
|
||||
}
|
||||
g_strfreev (uris);
|
||||
|
||||
gdk_content_deserializer_return_success (deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -895,8 +895,8 @@ init (void)
|
||||
gdk_content_register_serializer (G_TYPE_STRING,
|
||||
mime,
|
||||
string_serializer,
|
||||
(gpointer) charset,
|
||||
NULL);
|
||||
mime,
|
||||
g_free);
|
||||
}
|
||||
gdk_content_register_serializer (G_TYPE_STRING,
|
||||
"text/plain",
|
||||
|
||||
@@ -61,7 +61,12 @@
|
||||
* the commonly available names that are shared with the CSS specification.
|
||||
* Other names may be available, depending on the platform in use.
|
||||
* Another option to create a cursor is to use gdk_cursor_new_from_texture()
|
||||
* and provide an image to use for the cursor.
|
||||
* and provide an image to use for the cursor. Depending on the #GdkDisplay
|
||||
* in use, the type of supported images may be limited. See
|
||||
* gdk_display_supports_cursor_alpha(),
|
||||
* gdk_display_supports_cursor_color(),
|
||||
* gdk_display_get_default_cursor_size() and
|
||||
* gdk_display_get_maximal_cursor_size() for the limitations that might apply.
|
||||
*
|
||||
* To ease work with unsupported cursors, a fallback cursor can be provided.
|
||||
* If a #GdkSurface cannot use a cursor because of the reasons mentioned above,
|
||||
@@ -341,6 +346,18 @@ gdk_cursor_new_from_name (const gchar *name,
|
||||
*
|
||||
* Creates a new cursor from a #GdkTexture.
|
||||
*
|
||||
* Not all GDK backends support RGBA cursors. If they are not
|
||||
* supported, a monochrome approximation will be displayed.
|
||||
* The functions gdk_display_supports_cursor_alpha() and
|
||||
* gdk_display_supports_cursor_color() can be used to determine
|
||||
* whether RGBA cursors are supported;
|
||||
* gdk_display_get_default_cursor_size() and
|
||||
* gdk_display_get_maximal_cursor_size() give information about
|
||||
* cursor sizes.
|
||||
*
|
||||
* On the X backend, support for RGBA cursors requires a
|
||||
* sufficently new version of the X Render extension.
|
||||
*
|
||||
* Returns: a new #GdkCursor.
|
||||
*/
|
||||
GdkCursor *
|
||||
|
||||
@@ -112,6 +112,9 @@ struct _GdkDeviceClass
|
||||
double *win_y,
|
||||
GdkModifierType *mask,
|
||||
gboolean get_toplevel);
|
||||
void (* select_surface_events) (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkEventMask event_mask);
|
||||
};
|
||||
|
||||
void _gdk_device_set_associated_device (GdkDevice *device,
|
||||
|
||||
@@ -47,6 +47,8 @@ typedef struct _GdkDeviceTool GdkDeviceTool;
|
||||
*
|
||||
* Indicates the specific type of tool being used being a tablet. Such as an
|
||||
* airbrush, pencil, etc.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_DEVICE_TOOL_TYPE_UNKNOWN,
|
||||
|
||||
@@ -492,6 +492,8 @@ gdk_display_put_event_nocopy (GdkDisplay *display,
|
||||
GdkEvent *event)
|
||||
{
|
||||
_gdk_event_queue_append (display, event);
|
||||
/* If the main loop is blocking in a different thread, wake it up */
|
||||
g_main_context_wakeup (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,7 +633,8 @@ get_current_toplevel (GdkDisplay *display,
|
||||
pointer_surface = _gdk_device_surface_at_position (device, &x, &y, &state, TRUE);
|
||||
|
||||
if (pointer_surface != NULL &&
|
||||
GDK_SURFACE_DESTROYED (pointer_surface))
|
||||
(GDK_SURFACE_DESTROYED (pointer_surface) ||
|
||||
GDK_SURFACE_TYPE (pointer_surface) == GDK_SURFACE_FOREIGN))
|
||||
pointer_surface = NULL;
|
||||
|
||||
*x_out = round (x);
|
||||
@@ -1280,26 +1283,6 @@ gdk_display_notify_startup_complete (GdkDisplay *display,
|
||||
GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_get_startup_notification_id:
|
||||
* @display: a #GdkDisplay
|
||||
*
|
||||
* Gets the startup notification ID for a Wayland display, or %NULL
|
||||
* if no ID has been defined.
|
||||
*
|
||||
* Returns: the startup notification ID for @display, or %NULL
|
||||
*/
|
||||
const gchar *
|
||||
gdk_display_get_startup_notification_id (GdkDisplay *display)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
||||
|
||||
if (GDK_DISPLAY_GET_CLASS (display)->get_startup_notification_id == NULL)
|
||||
return NULL;
|
||||
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_startup_notification_id (display);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_pause_events (GdkDisplay *display)
|
||||
{
|
||||
@@ -1330,15 +1313,17 @@ _gdk_display_event_data_free (GdkDisplay *display,
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkSurfaceAttr *attributes)
|
||||
_gdk_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes)
|
||||
{
|
||||
GDK_DISPLAY_GET_CLASS (display)->create_surface_impl (display,
|
||||
surface,
|
||||
real_parent,
|
||||
attributes);
|
||||
surface,
|
||||
real_parent,
|
||||
event_mask,
|
||||
attributes);
|
||||
}
|
||||
|
||||
GdkSurface *
|
||||
|
||||
@@ -94,8 +94,6 @@ gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_display_notify_startup_complete (GdkDisplay *display,
|
||||
const gchar *startup_id);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const gchar * gdk_display_get_startup_notification_id (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkAppLaunchContext *gdk_display_get_app_launch_context (GdkDisplay *display);
|
||||
|
||||
@@ -136,8 +136,6 @@ struct _GdkDisplayClass
|
||||
|
||||
void (*notify_startup_complete) (GdkDisplay *display,
|
||||
const gchar *startup_id);
|
||||
const gchar * (*get_startup_notification_id) (GdkDisplay *display);
|
||||
|
||||
void (*event_data_copy) (GdkDisplay *display,
|
||||
const GdkEvent *event,
|
||||
GdkEvent *new_event);
|
||||
@@ -146,6 +144,7 @@ struct _GdkDisplayClass
|
||||
void (*create_surface_impl) (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes);
|
||||
|
||||
GdkKeymap * (*get_keymap) (GdkDisplay *display);
|
||||
@@ -232,9 +231,10 @@ void _gdk_display_event_data_copy (GdkDisplay *display
|
||||
GdkEvent *new_event);
|
||||
void _gdk_display_event_data_free (GdkDisplay *display,
|
||||
GdkEvent *event);
|
||||
void gdk_display_create_surface_impl (GdkDisplay *display,
|
||||
void _gdk_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes);
|
||||
GdkSurface * _gdk_display_create_surface (GdkDisplay *display);
|
||||
|
||||
|
||||
954
gdk/gdkdnd.c
Normal file
954
gdk/gdkdnd.c
Normal file
@@ -0,0 +1,954 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkcontentserializer.h"
|
||||
#include "gdkcursor.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
|
||||
typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
|
||||
|
||||
struct _GdkDragContextPrivate
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkDevice *device;
|
||||
GdkContentFormats *formats;
|
||||
};
|
||||
|
||||
static struct {
|
||||
GdkDragAction action;
|
||||
const gchar *name;
|
||||
GdkCursor *cursor;
|
||||
} drag_cursors[] = {
|
||||
{ GDK_ACTION_DEFAULT, NULL, NULL },
|
||||
{ GDK_ACTION_ASK, "dnd-ask", NULL },
|
||||
{ GDK_ACTION_COPY, "dnd-copy", NULL },
|
||||
{ GDK_ACTION_MOVE, "dnd-move", NULL },
|
||||
{ GDK_ACTION_LINK, "dnd-link", NULL },
|
||||
{ 0, "dnd-none", NULL },
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONTENT,
|
||||
PROP_DEVICE,
|
||||
PROP_DISPLAY,
|
||||
PROP_FORMATS,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
enum {
|
||||
CANCEL,
|
||||
DROP_PERFORMED,
|
||||
DND_FINISHED,
|
||||
ACTION_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
static GList *contexts = NULL;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* SECTION:dnd
|
||||
* @title: Drag And Drop
|
||||
* @short_description: Functions for controlling drag and drop handling
|
||||
*
|
||||
* These functions provide a low level interface for drag and drop.
|
||||
* The X backend of GDK supports both the Xdnd and Motif drag and drop
|
||||
* protocols transparently, the Win32 backend supports the WM_DROPFILES
|
||||
* protocol.
|
||||
*
|
||||
* GTK+ provides a higher level abstraction based on top of these functions,
|
||||
* and so they are not normally needed in GTK+ applications.
|
||||
* See the [Drag and Drop][gtk3-Drag-and-Drop] section of
|
||||
* the GTK+ documentation for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GdkDragContext:
|
||||
*
|
||||
* The GdkDragContext struct contains only private fields and
|
||||
* should not be accessed directly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_display:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Gets the #GdkDisplay that the drag context was created for.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkDisplay
|
||||
**/
|
||||
GdkDisplay *
|
||||
gdk_drag_context_get_display (GdkDragContext *context)
|
||||
{
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_formats:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Retrieves the formats supported by this context.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkContentFormats
|
||||
**/
|
||||
GdkContentFormats *
|
||||
gdk_drag_context_get_formats (GdkDragContext *context)
|
||||
{
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return priv->formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_actions:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Determines the bitmask of actions proposed by the source if
|
||||
* gdk_drag_context_get_suggested_action() returns %GDK_ACTION_ASK.
|
||||
*
|
||||
* Returns: the #GdkDragAction flags
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_context_get_actions (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_ACTION_DEFAULT);
|
||||
|
||||
return context->actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_suggested_action:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Determines the suggested drag action of the context.
|
||||
*
|
||||
* Returns: a #GdkDragAction value
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_context_get_suggested_action (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0);
|
||||
|
||||
return context->suggested_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_selected_action:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Determines the action chosen by the drag destination.
|
||||
*
|
||||
* Returns: a #GdkDragAction value
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_context_get_selected_action (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0);
|
||||
|
||||
return context->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_source_surface:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Returns the #GdkSurface where the DND operation started.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkSurface
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drag_context_get_source_surface (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return context->source_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_dest_surface:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Returns the destination surface for the DND operation.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkSurface
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drag_context_get_dest_surface (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return context->dest_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
return priv->device;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_init (GdkDragContext *context)
|
||||
{
|
||||
contexts = g_list_prepend (contexts, context);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (gobject);
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT:
|
||||
context->content = g_value_dup_object (value);
|
||||
if (context->content)
|
||||
{
|
||||
g_assert (priv->formats == NULL);
|
||||
priv->formats = gdk_content_provider_ref_formats (context->content);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_dup_object (value);
|
||||
g_assert (priv->device != NULL);
|
||||
priv->display = gdk_device_get_display (priv->device);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
if (priv->formats)
|
||||
{
|
||||
GdkContentFormats *override = g_value_dup_boxed (value);
|
||||
if (override)
|
||||
{
|
||||
gdk_content_formats_unref (priv->formats);
|
||||
priv->formats = override;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->formats = g_value_dup_boxed (value);
|
||||
g_assert (priv->formats != NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (gobject);
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT:
|
||||
g_value_set_object (value, context->content);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, priv->display);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
g_value_set_boxed (value, priv->formats);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_finalize (GObject *object)
|
||||
{
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (object);
|
||||
GdkDragContextPrivate *priv = gdk_drag_context_get_instance_private (context);
|
||||
|
||||
contexts = g_list_remove (contexts, context);
|
||||
|
||||
g_clear_object (&context->content);
|
||||
g_clear_pointer (&priv->formats, gdk_content_formats_unref);
|
||||
|
||||
if (context->source_surface)
|
||||
g_object_unref (context->source_surface);
|
||||
|
||||
if (context->dest_surface)
|
||||
g_object_unref (context->dest_surface);
|
||||
|
||||
G_OBJECT_CLASS (gdk_drag_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_read_local_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drag_context_read_local_async);
|
||||
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Reading not implemented."));
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_drag_context_read_local_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, context), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drag_context_read_local_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_class_init (GdkDragContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gdk_drag_context_get_property;
|
||||
object_class->set_property = gdk_drag_context_set_property;
|
||||
object_class->finalize = gdk_drag_context_finalize;
|
||||
|
||||
/**
|
||||
* GdkDragContext:content:
|
||||
*
|
||||
* The #GdkContentProvider or %NULL if the context is not a source-side
|
||||
* context.
|
||||
*/
|
||||
properties[PROP_CONTENT] =
|
||||
g_param_spec_object ("content",
|
||||
"Content",
|
||||
"The content being dragged",
|
||||
GDK_TYPE_CONTENT_PROVIDER,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDragContext:device:
|
||||
*
|
||||
* The #GdkDevice that is performing the drag.
|
||||
*/
|
||||
properties[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"Device",
|
||||
"The device performing the drag",
|
||||
GDK_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDragContext:display:
|
||||
*
|
||||
* The #GdkDisplay that the drag context belongs to.
|
||||
*/
|
||||
properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display this drag belongs to",
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDragContext:formats:
|
||||
*
|
||||
* The possible formats that the context can provide its data in.
|
||||
*/
|
||||
properties[PROP_FORMATS] =
|
||||
g_param_spec_boxed ("formats",
|
||||
"Formats",
|
||||
"The possible formats for data",
|
||||
GDK_TYPE_CONTENT_FORMATS,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDragContext::cancel:
|
||||
* @context: The object on which the signal is emitted
|
||||
* @reason: The reason the context was cancelled
|
||||
*
|
||||
* The drag and drop operation was cancelled.
|
||||
*/
|
||||
signals[CANCEL] =
|
||||
g_signal_new (g_intern_static_string ("cancel"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragContextClass, cancel),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__ENUM,
|
||||
G_TYPE_NONE, 1, GDK_TYPE_DRAG_CANCEL_REASON);
|
||||
|
||||
/**
|
||||
* GdkDragContext::drop-performed:
|
||||
* @context: The object on which the signal is emitted
|
||||
* @time: the time at which the drop happened.
|
||||
*
|
||||
* The drag and drop operation was performed on an accepting client.
|
||||
*/
|
||||
signals[DROP_PERFORMED] =
|
||||
g_signal_new (g_intern_static_string ("drop-performed"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragContextClass, drop_performed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__INT,
|
||||
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
|
||||
/**
|
||||
* GdkDragContext::dnd-finished:
|
||||
* @context: The object on which the signal is emitted
|
||||
*
|
||||
* The drag and drop operation was finished, the drag destination
|
||||
* finished reading all data. The drag source can now free all
|
||||
* miscellaneous data.
|
||||
*/
|
||||
signals[DND_FINISHED] =
|
||||
g_signal_new (g_intern_static_string ("dnd-finished"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragContextClass, dnd_finished),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkDragContext::action-changed:
|
||||
* @context: The object on which the signal is emitted
|
||||
* @action: The action currently chosen
|
||||
*
|
||||
* A new action is being chosen for the drag and drop operation.
|
||||
*/
|
||||
signals[ACTION_CHANGED] =
|
||||
g_signal_new (g_intern_static_string ("action-changed"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragContextClass, action_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__FLAGS,
|
||||
G_TYPE_NONE, 1, GDK_TYPE_DRAG_ACTION);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_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_finish:
|
||||
* @context: a #GdkDragContext
|
||||
* @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_);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_write_done (GObject *content,
|
||||
GAsyncResult *result,
|
||||
gpointer task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (gdk_content_provider_write_mime_type_finish (GDK_CONTENT_PROVIDER (content), result, &error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_write_serialize_done (GObject *content,
|
||||
GAsyncResult *result,
|
||||
gpointer task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (gdk_content_serialize_finish (result, &error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_context_write_async (GdkDragContext *context,
|
||||
const char *mime_type,
|
||||
GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentFormats *formats, *mime_formats;
|
||||
GTask *task;
|
||||
GType gtype;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (context->content);
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (mime_type == g_intern_string (mime_type));
|
||||
g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drag_context_write_async);
|
||||
|
||||
formats = gdk_content_provider_ref_formats (context->content);
|
||||
if (gdk_content_formats_contain_mime_type (formats, mime_type))
|
||||
{
|
||||
gdk_content_provider_write_mime_type_async (context->content,
|
||||
mime_type,
|
||||
stream,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drag_context_write_done,
|
||||
task);
|
||||
gdk_content_formats_unref (formats);
|
||||
return;
|
||||
}
|
||||
|
||||
mime_formats = gdk_content_formats_new ((const gchar *[2]) { mime_type, NULL }, 1);
|
||||
mime_formats = gdk_content_formats_union_serialize_gtypes (mime_formats);
|
||||
gtype = gdk_content_formats_match_gtype (formats, mime_formats);
|
||||
if (gtype != G_TYPE_INVALID)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert (gtype != G_TYPE_INVALID);
|
||||
|
||||
g_value_init (&value, gtype);
|
||||
if (gdk_content_provider_get_value (context->content, &value, &error))
|
||||
{
|
||||
gdk_content_serialize_async (stream,
|
||||
mime_type,
|
||||
&value,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drag_context_write_serialize_done,
|
||||
g_object_ref (task));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible formats to transfer clipboard contents."));
|
||||
}
|
||||
|
||||
gdk_content_formats_unref (mime_formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_context_write_finish (GdkDragContext *context,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, context), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drag_context_write_async, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_async:
|
||||
* @context: a #GdkDragContext
|
||||
* @mime_types: (array zero-terminated=1) (element-type utf8): pointer to an array of mime types
|
||||
* @io_priority: the io priority for the read operation
|
||||
* @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to @callback
|
||||
*
|
||||
* Asynchronously read the dropped data from a DND context
|
||||
* in a format that complies with one of the mime types.
|
||||
*/
|
||||
void
|
||||
gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (mime_types != NULL && mime_types[0] != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types));
|
||||
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->read_async (context,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_finish:
|
||||
* @context: a #GdkDragContext
|
||||
* @out_mime_type: (out) (type utf8): return location for the used mime type
|
||||
* @result: a #GAsyncResult
|
||||
* @error: (allow-none): location to store error information on failure, or %NULL
|
||||
*
|
||||
* Finishes an async drop read operation, see gdk_drop_read_async().
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the #GInputStream, or %NULL
|
||||
*/
|
||||
GInputStream *
|
||||
gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_is_tagged (result, gdk_drag_context_read_local_async))
|
||||
{
|
||||
return gdk_drag_context_read_local_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GDK_DRAG_CONTEXT_GET_CLASS (context)->read_finish (context, out_mime_type, result, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_get_drag_surface:
|
||||
* @context: a #GdkDragContext
|
||||
*
|
||||
* Returns the surface on which the drag icon should be rendered
|
||||
* during the drag operation. Note that the surface may not be
|
||||
* available until the drag operation has begun. GDK will move
|
||||
* the surface in accordance with the ongoing drag operation.
|
||||
* The surface is owned by @context and will be destroyed when
|
||||
* the drag operation is over.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the drag surface, or %NULL
|
||||
*/
|
||||
GdkSurface *
|
||||
gdk_drag_context_get_drag_surface (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
|
||||
|
||||
if (GDK_DRAG_CONTEXT_GET_CLASS (context)->get_drag_surface)
|
||||
return GDK_DRAG_CONTEXT_GET_CLASS (context)->get_drag_surface (context);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_context_set_hotspot:
|
||||
* @context: a #GdkDragContext
|
||||
* @hot_x: x coordinate of the drag surface hotspot
|
||||
* @hot_y: y coordinate of the drag surface hotspot
|
||||
*
|
||||
* Sets the position of the drag surface that will be kept
|
||||
* under the cursor hotspot. Initially, the hotspot is at the
|
||||
* top left corner of the drag surface.
|
||||
*/
|
||||
void
|
||||
gdk_drag_context_set_hotspot (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
gint hot_y)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
if (GDK_DRAG_CONTEXT_GET_CLASS (context)->set_hotspot)
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->set_hotspot (context, hot_x, hot_y);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_drop_done:
|
||||
* @context: a #GdkDragContext
|
||||
* @success: whether the drag was ultimatively successful
|
||||
*
|
||||
* Inform GDK if the drop ended successfully. Passing %FALSE
|
||||
* for @success may trigger a drag cancellation animation.
|
||||
*
|
||||
* This function is called by the drag source, and should
|
||||
* be the last call before dropping the reference to the
|
||||
* @context.
|
||||
*
|
||||
* The #GdkDragContext will only take the first gdk_drag_drop_done()
|
||||
* call as effective, if this function is called multiple times,
|
||||
* all subsequent calls will be ignored.
|
||||
*/
|
||||
void
|
||||
gdk_drag_drop_done (GdkDragContext *context,
|
||||
gboolean success)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
if (context->drop_done)
|
||||
return;
|
||||
|
||||
context->drop_done = TRUE;
|
||||
|
||||
if (GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_done)
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->drop_done (context, success);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_context_set_cursor (GdkDragContext *context,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
if (GDK_DRAG_CONTEXT_GET_CLASS (context)->set_cursor)
|
||||
GDK_DRAG_CONTEXT_GET_CLASS (context)->set_cursor (context, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_context_cancel (GdkDragContext *context,
|
||||
GdkDragCancelReason reason)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
|
||||
g_signal_emit (context, signals[CANCEL], 0, reason);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_context_handle_source_event (GdkEvent *event)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
GList *l;
|
||||
|
||||
for (l = contexts; l; l = l->next)
|
||||
{
|
||||
context = l->data;
|
||||
|
||||
if (!context->is_source)
|
||||
continue;
|
||||
|
||||
if (!GDK_DRAG_CONTEXT_GET_CLASS (context)->handle_event)
|
||||
continue;
|
||||
|
||||
if (GDK_DRAG_CONTEXT_GET_CLASS (context)->handle_event (context, event))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkCursor *
|
||||
gdk_drag_get_cursor (GdkDragContext *context,
|
||||
GdkDragAction action)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0 ; i < G_N_ELEMENTS (drag_cursors) - 1; i++)
|
||||
if (drag_cursors[i].action == action)
|
||||
break;
|
||||
|
||||
if (drag_cursors[i].cursor == NULL)
|
||||
drag_cursors[i].cursor = gdk_cursor_new_from_name (drag_cursors[i].name, NULL);
|
||||
|
||||
return drag_cursors[i].cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_context_commit_drag_status (GdkDragContext *context)
|
||||
{
|
||||
GdkDragContextClass *context_class;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
|
||||
g_return_if_fail (!context->is_source);
|
||||
|
||||
context_class = GDK_DRAG_CONTEXT_GET_CLASS (context);
|
||||
|
||||
if (context_class->commit_drag_status)
|
||||
context_class->commit_drag_status (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_context_handle_dest_event (GdkEvent *event)
|
||||
{
|
||||
GdkDragContext *context = NULL;
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
context = event->dnd.context;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
gdk_drag_context_commit_drag_status (context);
|
||||
return TRUE;;
|
||||
}
|
||||
152
gdk/gdkdnd.h
Normal file
152
gdk/gdkdnd.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DND_H__
|
||||
#define __GDK_DND_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkdevice.h>
|
||||
#include <gdk/gdkevents.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#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))
|
||||
#define GDK_IS_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAG_CONTEXT))
|
||||
|
||||
/**
|
||||
* GdkDragAction:
|
||||
* @GDK_ACTION_DEFAULT: Means nothing, and should not be used.
|
||||
* @GDK_ACTION_COPY: Copy the data.
|
||||
* @GDK_ACTION_MOVE: Move the data, i.e. first copy it, then delete
|
||||
* it from the source using the DELETE target of the X selection protocol.
|
||||
* @GDK_ACTION_LINK: Add a link to the data. Note that this is only
|
||||
* useful if source and destination agree on what it means.
|
||||
* @GDK_ACTION_PRIVATE: Special action which tells the source that the
|
||||
* destination will do something that the source doesn’t understand.
|
||||
* @GDK_ACTION_ASK: Ask the user what to do with the data.
|
||||
*
|
||||
* Used in #GdkDragContext to indicate what the destination
|
||||
* should do with the dropped data.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_ACTION_DEFAULT = 1 << 0,
|
||||
GDK_ACTION_COPY = 1 << 1,
|
||||
GDK_ACTION_MOVE = 1 << 2,
|
||||
GDK_ACTION_LINK = 1 << 3,
|
||||
GDK_ACTION_PRIVATE = 1 << 4,
|
||||
GDK_ACTION_ASK = 1 << 5
|
||||
} GdkDragAction;
|
||||
|
||||
/**
|
||||
* GdkDragCancelReason:
|
||||
* @GDK_DRAG_CANCEL_NO_TARGET: There is no suitable drop target.
|
||||
* @GDK_DRAG_CANCEL_USER_CANCELLED: Drag cancelled by the user
|
||||
* @GDK_DRAG_CANCEL_ERROR: Unspecified error.
|
||||
*
|
||||
* Used in #GdkDragContext to the reason of a cancelled DND operation.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_DRAG_CANCEL_NO_TARGET,
|
||||
GDK_DRAG_CANCEL_USER_CANCELLED,
|
||||
GDK_DRAG_CANCEL_ERROR
|
||||
} GdkDragCancelReason;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drag_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drag_context_get_display (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDevice * gdk_drag_context_get_device (GdkDragContext *context);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats *gdk_drag_context_get_formats (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_context_get_actions (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_context_get_suggested_action (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_context_get_selected_action (GdkDragContext *context);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_context_get_source_surface (GdkDragContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_context_get_dest_surface (GdkDragContext *context);
|
||||
|
||||
/* Destination side */
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_async (GdkDragContext *context,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GInputStream * gdk_drop_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/* Source side */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragContext * gdk_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drag_drop_done (GdkDragContext *context,
|
||||
gboolean success);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_context_get_drag_surface (GdkDragContext *context);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drag_context_set_hotspot (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
gint hot_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DND_H__ */
|
||||
124
gdk/gdkdndprivate.h
Normal file
124
gdk/gdkdndprivate.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2010, Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DND_PRIVATE_H__
|
||||
#define __GDK_DND_PRIVATE_H__
|
||||
|
||||
#include "gdkdnd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAG_CONTEXT, 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))
|
||||
|
||||
typedef struct _GdkDragContextClass GdkDragContextClass;
|
||||
|
||||
|
||||
struct _GdkDragContextClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
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_finish) (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time_);
|
||||
void (* read_async) (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream * (* read_finish) (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GdkSurface* (*get_drag_surface) (GdkDragContext *context);
|
||||
void (*set_hotspot) (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
gint hot_y);
|
||||
void (*drop_done) (GdkDragContext *context,
|
||||
gboolean success);
|
||||
|
||||
void (*set_cursor) (GdkDragContext *context,
|
||||
GdkCursor *cursor);
|
||||
void (*cancel) (GdkDragContext *context,
|
||||
GdkDragCancelReason reason);
|
||||
void (*drop_performed) (GdkDragContext *context,
|
||||
guint32 time);
|
||||
void (*dnd_finished) (GdkDragContext *context);
|
||||
|
||||
gboolean (*handle_event) (GdkDragContext *context,
|
||||
const GdkEvent *event);
|
||||
void (*action_changed) (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
void (*commit_drag_status) (GdkDragContext *context);
|
||||
};
|
||||
|
||||
struct _GdkDragContext {
|
||||
GObject parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
gboolean is_source;
|
||||
GdkSurface *source_surface;
|
||||
GdkSurface *dest_surface;
|
||||
GdkSurface *drag_surface;
|
||||
|
||||
GdkContentProvider *content;
|
||||
GdkDragAction actions;
|
||||
GdkDragAction suggested_action;
|
||||
GdkDragAction action;
|
||||
|
||||
guint drop_done : 1; /* Whether gdk_drag_drop_done() was performed */
|
||||
};
|
||||
|
||||
void gdk_drag_context_set_cursor (GdkDragContext *context,
|
||||
GdkCursor *cursor);
|
||||
void gdk_drag_context_cancel (GdkDragContext *context,
|
||||
GdkDragCancelReason reason);
|
||||
gboolean gdk_drag_context_handle_source_event (GdkEvent *event);
|
||||
gboolean gdk_drag_context_handle_dest_event (GdkEvent *event);
|
||||
GdkCursor * gdk_drag_get_cursor (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
void gdk_drag_abort (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
void gdk_drag_drop (GdkDragContext *context,
|
||||
guint32 time_);
|
||||
|
||||
void gdk_drag_context_write_async (GdkDragContext *context,
|
||||
const char *mime_type,
|
||||
GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean gdk_drag_context_write_finish (GdkDragContext *context,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
792
gdk/gdkdrag.c
792
gdk/gdkdrag.c
@@ -1,792 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkcontentserializer.h"
|
||||
#include "gdkcursor.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
|
||||
static struct {
|
||||
GdkDragAction action;
|
||||
const gchar *name;
|
||||
GdkCursor *cursor;
|
||||
} drag_cursors[] = {
|
||||
{ GDK_ACTION_ASK, "dnd-ask", NULL },
|
||||
{ GDK_ACTION_COPY, "dnd-copy", NULL },
|
||||
{ GDK_ACTION_MOVE, "dnd-move", NULL },
|
||||
{ GDK_ACTION_LINK, "dnd-link", NULL },
|
||||
{ 0, "dnd-none", NULL },
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONTENT,
|
||||
PROP_DEVICE,
|
||||
PROP_DISPLAY,
|
||||
PROP_FORMATS,
|
||||
PROP_SELECTED_ACTION,
|
||||
PROP_ACTIONS,
|
||||
PROP_SURFACE,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
enum {
|
||||
CANCEL,
|
||||
DROP_PERFORMED,
|
||||
DND_FINISHED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
typedef struct _GdkDragPrivate GdkDragPrivate;
|
||||
|
||||
struct _GdkDragPrivate {
|
||||
GdkSurface *surface;
|
||||
|
||||
GdkDisplay *display;
|
||||
GdkDevice *device;
|
||||
GdkContentFormats *formats;
|
||||
GdkContentProvider *content;
|
||||
|
||||
GdkDragAction actions;
|
||||
GdkDragAction selected_action;
|
||||
|
||||
guint drop_done : 1; /* Whether gdk_drag_drop_done() was performed */
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
static GList *drags = NULL;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkDrag, gdk_drag, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* SECTION:dnd
|
||||
* @title: Drag And Drop
|
||||
* @short_description: Functions for controlling drag and drop handling
|
||||
*
|
||||
* These functions provide a low level interface for drag and drop.
|
||||
*
|
||||
* The GdkDrag object represents the source side of an ongoing DND operation.
|
||||
* It is created when a drag is started, and stays alive for duration of
|
||||
* the DND operation.
|
||||
*
|
||||
* The GdkDrop object represents the target side of an ongoing DND operation.
|
||||
*
|
||||
* GTK+ provides a higher level abstraction based on top of these functions,
|
||||
* and so they are not normally needed in GTK+ applications. See the
|
||||
* [Drag and Drop][gtk4-Drag-and-Drop] section of the GTK+ documentation
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GdkDrag:
|
||||
*
|
||||
* The GdkDrag struct contains only private fields and
|
||||
* should not be accessed directly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* gdk_drag_get_display:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Gets the #GdkDisplay that the drag object was created for.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkDisplay
|
||||
**/
|
||||
GdkDisplay *
|
||||
gdk_drag_get_display (GdkDrag *drag)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
|
||||
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_get_formats:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Retrieves the formats supported by this GdkDrag object.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkContentFormats
|
||||
**/
|
||||
GdkContentFormats *
|
||||
gdk_drag_get_formats (GdkDrag *drag)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
|
||||
|
||||
return priv->formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_get_actions:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Determines the bitmask of possible actions proposed by the source.
|
||||
*
|
||||
* Returns: the #GdkDragAction flags
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_get_actions (GdkDrag *drag)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), 0);
|
||||
|
||||
return priv->actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_get_selected_action:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Determines the action chosen by the drag destination.
|
||||
*
|
||||
* Returns: a #GdkDragAction value
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drag_get_selected_action (GdkDrag *drag)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), 0);
|
||||
|
||||
return priv->selected_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_get_device:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Returns the #GdkDevice associated to the GdkDrag object.
|
||||
*
|
||||
* Returns: (transfer none): The #GdkDevice associated to @drag.
|
||||
**/
|
||||
GdkDevice *
|
||||
gdk_drag_get_device (GdkDrag *drag)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
|
||||
|
||||
return priv->device;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_init (GdkDrag *drag)
|
||||
{
|
||||
drags = g_list_prepend (drags, drag);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrag *drag = GDK_DRAG (gobject);
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT:
|
||||
priv->content = g_value_dup_object (value);
|
||||
if (priv->content)
|
||||
{
|
||||
g_assert (priv->formats == NULL);
|
||||
priv->formats = gdk_content_provider_ref_formats (priv->content);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_dup_object (value);
|
||||
g_assert (priv->device != NULL);
|
||||
priv->display = gdk_device_get_display (priv->device);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
if (priv->formats)
|
||||
{
|
||||
GdkContentFormats *override = g_value_dup_boxed (value);
|
||||
if (override)
|
||||
{
|
||||
gdk_content_formats_unref (priv->formats);
|
||||
priv->formats = override;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->formats = g_value_dup_boxed (value);
|
||||
g_assert (priv->formats != NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SELECTED_ACTION:
|
||||
{
|
||||
GdkDragAction action = g_value_get_flags (value);
|
||||
gdk_drag_set_selected_action (drag, action);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_ACTIONS:
|
||||
{
|
||||
GdkDragAction actions = g_value_get_flags (value);
|
||||
gdk_drag_set_actions (drag, actions);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
g_assert (priv->surface != NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrag *drag = GDK_DRAG (gobject);
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTENT:
|
||||
g_value_set_object (value, priv->content);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, priv->display);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
g_value_set_boxed (value, priv->formats);
|
||||
break;
|
||||
|
||||
case PROP_SELECTED_ACTION:
|
||||
g_value_set_flags (value, priv->selected_action);
|
||||
break;
|
||||
|
||||
case PROP_ACTIONS:
|
||||
g_value_set_flags (value, priv->actions);
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
g_value_set_object (value, priv->surface);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_finalize (GObject *object)
|
||||
{
|
||||
GdkDrag *drag = GDK_DRAG (object);
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
drags = g_list_remove (drags, drag);
|
||||
|
||||
g_clear_object (&priv->content);
|
||||
g_clear_pointer (&priv->formats, gdk_content_formats_unref);
|
||||
|
||||
g_clear_object (&priv->surface);
|
||||
|
||||
G_OBJECT_CLASS (gdk_drag_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_class_init (GdkDragClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gdk_drag_get_property;
|
||||
object_class->set_property = gdk_drag_set_property;
|
||||
object_class->finalize = gdk_drag_finalize;
|
||||
|
||||
/**
|
||||
* GdkDrag:content:
|
||||
*
|
||||
* The #GdkContentProvider.
|
||||
*/
|
||||
properties[PROP_CONTENT] =
|
||||
g_param_spec_object ("content",
|
||||
"Content",
|
||||
"The content being dragged",
|
||||
GDK_TYPE_CONTENT_PROVIDER,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrag:device:
|
||||
*
|
||||
* The #GdkDevice that is performing the drag.
|
||||
*/
|
||||
properties[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"Device",
|
||||
"The device performing the drag",
|
||||
GDK_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrag:display:
|
||||
*
|
||||
* The #GdkDisplay that the drag belongs to.
|
||||
*/
|
||||
properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display this drag belongs to",
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrag:formats:
|
||||
*
|
||||
* The possible formats that the drag can provide its data in.
|
||||
*/
|
||||
properties[PROP_FORMATS] =
|
||||
g_param_spec_boxed ("formats",
|
||||
"Formats",
|
||||
"The possible formats for data",
|
||||
GDK_TYPE_CONTENT_FORMATS,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_SELECTED_ACTION] =
|
||||
g_param_spec_flags ("selected-action",
|
||||
"Selected action",
|
||||
"The currently selected action",
|
||||
GDK_TYPE_DRAG_ACTION,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_ACTIONS] =
|
||||
g_param_spec_flags ("actions",
|
||||
"Actions",
|
||||
"The possible actions",
|
||||
GDK_TYPE_DRAG_ACTION,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_SURFACE] =
|
||||
g_param_spec_object ("surface",
|
||||
"Surface",
|
||||
"The surface where the drag originates",
|
||||
GDK_TYPE_SURFACE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrag::cancel:
|
||||
* @drag: The object on which the signal is emitted
|
||||
* @reason: The reason the drag was cancelled
|
||||
*
|
||||
* The drag operation was cancelled.
|
||||
*/
|
||||
signals[CANCEL] =
|
||||
g_signal_new (g_intern_static_string ("cancel"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragClass, cancel),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__ENUM,
|
||||
G_TYPE_NONE, 1, GDK_TYPE_DRAG_CANCEL_REASON);
|
||||
|
||||
/**
|
||||
* GdkDrag::drop-performed:
|
||||
* @drag: The object on which the signal is emitted
|
||||
*
|
||||
* The drag operation was performed on an accepting client.
|
||||
*/
|
||||
signals[DROP_PERFORMED] =
|
||||
g_signal_new (g_intern_static_string ("drop-performed"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragClass, drop_performed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkDrag::dnd-finished:
|
||||
* @drag: The object on which the signal is emitted
|
||||
*
|
||||
* The drag operation was finished, the destination
|
||||
* finished reading all data. The drag object can now
|
||||
* free all miscellaneous data.
|
||||
*/
|
||||
signals[DND_FINISHED] =
|
||||
g_signal_new (g_intern_static_string ("dnd-finished"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GdkDragClass, dnd_finished),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_write_done (GObject *content,
|
||||
GAsyncResult *result,
|
||||
gpointer task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (gdk_content_provider_write_mime_type_finish (GDK_CONTENT_PROVIDER (content), result, &error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_write_serialize_done (GObject *content,
|
||||
GAsyncResult *result,
|
||||
gpointer task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (gdk_content_serialize_finish (result, &error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_write_async (GdkDrag *drag,
|
||||
const char *mime_type,
|
||||
GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
GdkContentFormats *formats, *mime_formats;
|
||||
GTask *task;
|
||||
GType gtype;
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG (drag));
|
||||
g_return_if_fail (priv->content);
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (mime_type == g_intern_string (mime_type));
|
||||
g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
task = g_task_new (drag, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drag_write_async);
|
||||
|
||||
formats = gdk_content_provider_ref_formats (priv->content);
|
||||
if (gdk_content_formats_contain_mime_type (formats, mime_type))
|
||||
{
|
||||
gdk_content_provider_write_mime_type_async (priv->content,
|
||||
mime_type,
|
||||
stream,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drag_write_done,
|
||||
task);
|
||||
gdk_content_formats_unref (formats);
|
||||
return;
|
||||
}
|
||||
|
||||
mime_formats = gdk_content_formats_new ((const gchar *[2]) { mime_type, NULL }, 1);
|
||||
mime_formats = gdk_content_formats_union_serialize_gtypes (mime_formats);
|
||||
gtype = gdk_content_formats_match_gtype (formats, mime_formats);
|
||||
if (gtype != G_TYPE_INVALID)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert (gtype != G_TYPE_INVALID);
|
||||
|
||||
g_value_init (&value, gtype);
|
||||
if (gdk_content_provider_get_value (priv->content, &value, &error))
|
||||
{
|
||||
gdk_content_serialize_async (stream,
|
||||
mime_type,
|
||||
&value,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drag_write_serialize_done,
|
||||
g_object_ref (task));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible formats to transfer clipboard contents."));
|
||||
}
|
||||
|
||||
gdk_content_formats_unref (mime_formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_write_finish (GdkDrag *drag,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, drag), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drag_write_async, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_set_actions (GdkDrag *drag,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
if (priv->actions == actions)
|
||||
return;
|
||||
|
||||
priv->actions = actions;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (drag), properties[PROP_ACTIONS]);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_set_selected_action (GdkDrag *drag,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
GdkCursor *cursor;
|
||||
|
||||
if (priv->selected_action == action)
|
||||
return;
|
||||
|
||||
priv->selected_action = action;
|
||||
|
||||
cursor = gdk_drag_get_cursor (drag, action);
|
||||
gdk_drag_set_cursor (drag, cursor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (drag), properties[PROP_SELECTED_ACTION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_get_drag_surface:
|
||||
* @drag: a #GdkDrag
|
||||
*
|
||||
* Returns the surface on which the drag icon should be rendered
|
||||
* during the drag operation. Note that the surface may not be
|
||||
* available until the drag operation has begun. GDK will move
|
||||
* the surface in accordance with the ongoing drag operation.
|
||||
* The surface is owned by @drag and will be destroyed when
|
||||
* the drag operation is over.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the drag surface, or %NULL
|
||||
*/
|
||||
GdkSurface *
|
||||
gdk_drag_get_drag_surface (GdkDrag *drag)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
|
||||
|
||||
if (GDK_DRAG_GET_CLASS (drag)->get_drag_surface)
|
||||
return GDK_DRAG_GET_CLASS (drag)->get_drag_surface (drag);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_set_hotspot:
|
||||
* @drag: a #GdkDrag
|
||||
* @hot_x: x coordinate of the drag surface hotspot
|
||||
* @hot_y: y coordinate of the drag surface hotspot
|
||||
*
|
||||
* Sets the position of the drag surface that will be kept
|
||||
* under the cursor hotspot. Initially, the hotspot is at the
|
||||
* top left corner of the drag surface.
|
||||
*/
|
||||
void
|
||||
gdk_drag_set_hotspot (GdkDrag *drag,
|
||||
gint hot_x,
|
||||
gint hot_y)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG (drag));
|
||||
|
||||
if (GDK_DRAG_GET_CLASS (drag)->set_hotspot)
|
||||
GDK_DRAG_GET_CLASS (drag)->set_hotspot (drag, hot_x, hot_y);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_drop_done:
|
||||
* @drag: a #GdkDrag
|
||||
* @success: whether the drag was ultimatively successful
|
||||
*
|
||||
* Inform GDK if the drop ended successfully. Passing %FALSE
|
||||
* for @success may trigger a drag cancellation animation.
|
||||
*
|
||||
* This function is called by the drag source, and should
|
||||
* be the last call before dropping the reference to the
|
||||
* @drag.
|
||||
*
|
||||
* The #GdkDrag will only take the first gdk_drag_drop_done()
|
||||
* call as effective, if this function is called multiple times,
|
||||
* all subsequent calls will be ignored.
|
||||
*/
|
||||
void
|
||||
gdk_drag_drop_done (GdkDrag *drag,
|
||||
gboolean success)
|
||||
{
|
||||
GdkDragPrivate *priv = gdk_drag_get_instance_private (drag);
|
||||
|
||||
g_return_if_fail (GDK_IS_DRAG (drag));
|
||||
|
||||
if (priv->drop_done)
|
||||
return;
|
||||
|
||||
priv->drop_done = TRUE;
|
||||
|
||||
if (GDK_DRAG_GET_CLASS (drag)->drop_done)
|
||||
GDK_DRAG_GET_CLASS (drag)->drop_done (drag, success);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_set_cursor (GdkDrag *drag,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG (drag));
|
||||
|
||||
if (GDK_DRAG_GET_CLASS (drag)->set_cursor)
|
||||
GDK_DRAG_GET_CLASS (drag)->set_cursor (drag, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_cancel (GdkDrag *drag,
|
||||
GdkDragCancelReason reason)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DRAG (drag));
|
||||
|
||||
g_signal_emit (drag, signals[CANCEL], 0, reason);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_handle_source_event (GdkEvent *event)
|
||||
{
|
||||
GdkDrag *drag;
|
||||
GList *l;
|
||||
|
||||
for (l = drags; l; l = l->next)
|
||||
{
|
||||
drag = l->data;
|
||||
|
||||
if (!GDK_DRAG_GET_CLASS (drag)->handle_event)
|
||||
continue;
|
||||
|
||||
if (GDK_DRAG_GET_CLASS (drag)->handle_event (drag, event))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkCursor *
|
||||
gdk_drag_get_cursor (GdkDrag *drag,
|
||||
GdkDragAction action)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0 ; i < G_N_ELEMENTS (drag_cursors) - 1; i++)
|
||||
if (drag_cursors[i].action == action)
|
||||
break;
|
||||
|
||||
if (drag_cursors[i].cursor == NULL)
|
||||
drag_cursors[i].cursor = gdk_cursor_new_from_name (drag_cursors[i].name, NULL);
|
||||
|
||||
return drag_cursors[i].cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drag_action_is_unique:
|
||||
* @action: a #GdkDragAction
|
||||
*
|
||||
* Checks if @action represents a single action or if it
|
||||
* includes multiple flags that can be selected from.
|
||||
*
|
||||
* When @action is 0 - ie no action was given, %TRUE
|
||||
* is returned.
|
||||
*
|
||||
* Returns: %TRUE if exactly one action was given
|
||||
**/
|
||||
gboolean
|
||||
gdk_drag_action_is_unique (GdkDragAction action)
|
||||
{
|
||||
return (action & (action - 1)) == 0;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DND_H__
|
||||
#define __GDK_DND_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkdevice.h>
|
||||
#include <gdk/gdkevents.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DRAG (gdk_drag_get_type ())
|
||||
#define GDK_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAG, GdkDrag))
|
||||
#define GDK_IS_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAG))
|
||||
|
||||
/**
|
||||
* GdkDragCancelReason:
|
||||
* @GDK_DRAG_CANCEL_NO_TARGET: There is no suitable drop target.
|
||||
* @GDK_DRAG_CANCEL_USER_CANCELLED: Drag cancelled by the user
|
||||
* @GDK_DRAG_CANCEL_ERROR: Unspecified error.
|
||||
*
|
||||
* Used in #GdkDrag to the reason of a cancelled DND operation.
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_DRAG_CANCEL_NO_TARGET,
|
||||
GDK_DRAG_CANCEL_USER_CANCELLED,
|
||||
GDK_DRAG_CANCEL_ERROR
|
||||
} GdkDragCancelReason;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drag_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drag_get_display (GdkDrag *drag);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDevice * gdk_drag_get_device (GdkDrag *drag);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats *gdk_drag_get_formats (GdkDrag *drag);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_get_actions (GdkDrag *drag);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_get_selected_action (GdkDrag *drag);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_drag_action_is_unique (GdkDragAction action);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDrag * gdk_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drag_drop_done (GdkDrag *drag,
|
||||
gboolean success);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_drag_get_drag_surface (GdkDrag *drag);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drag_set_hotspot (GdkDrag *drag,
|
||||
gint hot_x,
|
||||
gint hot_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DND_H__ */
|
||||
@@ -1,86 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2010, Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DND_PRIVATE_H__
|
||||
#define __GDK_DND_PRIVATE_H__
|
||||
|
||||
#include "gdkdrag.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAG, GdkDragClass))
|
||||
#define GDK_IS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAG))
|
||||
#define GDK_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAG, GdkDragClass))
|
||||
|
||||
typedef struct _GdkDragClass GdkDragClass;
|
||||
|
||||
|
||||
struct _GdkDragClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
GdkSurface* (*get_drag_surface) (GdkDrag *drag);
|
||||
void (*set_hotspot) (GdkDrag *drag,
|
||||
gint hot_x,
|
||||
gint hot_y);
|
||||
void (*drop_done) (GdkDrag *drag,
|
||||
gboolean success);
|
||||
|
||||
void (*set_cursor) (GdkDrag *drag,
|
||||
GdkCursor *cursor);
|
||||
void (*cancel) (GdkDrag *drag,
|
||||
GdkDragCancelReason reason);
|
||||
void (*drop_performed) (GdkDrag *drag,
|
||||
guint32 time);
|
||||
void (*dnd_finished) (GdkDrag *drag);
|
||||
|
||||
gboolean (*handle_event) (GdkDrag *drag,
|
||||
const GdkEvent *event);
|
||||
};
|
||||
|
||||
struct _GdkDrag {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
void gdk_drag_set_cursor (GdkDrag *drag,
|
||||
GdkCursor *cursor);
|
||||
void gdk_drag_set_actions (GdkDrag *drag,
|
||||
GdkDragAction actions);
|
||||
void gdk_drag_set_selected_action (GdkDrag *drag,
|
||||
GdkDragAction action);
|
||||
|
||||
void gdk_drag_cancel (GdkDrag *drag,
|
||||
GdkDragCancelReason reason);
|
||||
gboolean gdk_drag_handle_source_event (GdkEvent *event);
|
||||
GdkCursor * gdk_drag_get_cursor (GdkDrag *drag,
|
||||
GdkDragAction action);
|
||||
|
||||
void gdk_drag_write_async (GdkDrag *drag,
|
||||
const char *mime_type,
|
||||
GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean gdk_drag_write_finish (GdkDrag *drag,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
990
gdk/gdkdrop.c
990
gdk/gdkdrop.c
@@ -1,990 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdropprivate.h"
|
||||
|
||||
#include "gdkcontentdeserializer.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkcontentserializer.h"
|
||||
#include "gdkcursor.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkpipeiostreamprivate.h"
|
||||
#include "gdksurface.h"
|
||||
|
||||
typedef struct _GdkDropPrivate GdkDropPrivate;
|
||||
|
||||
struct _GdkDropPrivate {
|
||||
GdkDevice *device;
|
||||
GdkDrag *drag;
|
||||
GdkContentFormats *formats;
|
||||
GdkSurface *surface;
|
||||
GdkDragAction actions;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ACTIONS,
|
||||
PROP_DEVICE,
|
||||
PROP_DISPLAY,
|
||||
PROP_DRAG,
|
||||
PROP_FORMATS,
|
||||
PROP_SURFACE,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkDrop, gdk_drop, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* GdkDrop:
|
||||
*
|
||||
* The GdkDrop struct contains only private fields and
|
||||
* should not be accessed directly.
|
||||
*/
|
||||
|
||||
static void
|
||||
gdk_drop_default_status (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_local_write_done (GObject *drag,
|
||||
GAsyncResult *result,
|
||||
gpointer stream)
|
||||
{
|
||||
/* we don't care about the error, we just want to clean up */
|
||||
gdk_drag_write_finish (GDK_DRAG (drag), result, NULL);
|
||||
|
||||
/* XXX: Do we need to close_async() here? */
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_local_async (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkContentFormats *content_formats;
|
||||
const char *mime_type;
|
||||
GTask *task;
|
||||
GdkContentProvider *content;
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_drop_read_local_async);
|
||||
|
||||
if (priv->drag == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Drag'n'drop from other applications is not supported."));
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (priv->drag, "content", &content, NULL);
|
||||
content_formats = gdk_content_provider_ref_formats (content);
|
||||
g_object_unref (content);
|
||||
content_formats = gdk_content_formats_union_serialize_mime_types (content_formats);
|
||||
mime_type = gdk_content_formats_match_mime_type (content_formats, formats);
|
||||
|
||||
if (mime_type != NULL)
|
||||
{
|
||||
GOutputStream *output_stream;
|
||||
GIOStream *stream;
|
||||
|
||||
stream = gdk_pipe_io_stream_new ();
|
||||
output_stream = g_io_stream_get_output_stream (stream);
|
||||
gdk_drag_write_async (priv->drag,
|
||||
mime_type,
|
||||
output_stream,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drop_read_local_write_done,
|
||||
g_object_ref (output_stream));
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
g_task_return_pointer (task, g_object_ref (g_io_stream_get_input_stream (stream)), g_object_unref);
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible formats to transfer contents."));
|
||||
}
|
||||
|
||||
gdk_content_formats_unref (content_formats);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_drop_read_local_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_local_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (gobject);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIONS:
|
||||
gdk_drop_set_actions (self, g_value_get_flags (value));
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_dup_object (value);
|
||||
g_assert (priv->device != NULL);
|
||||
if (priv->surface)
|
||||
g_assert (gdk_surface_get_display (priv->surface) == gdk_device_get_display (priv->device));
|
||||
break;
|
||||
|
||||
case PROP_DRAG:
|
||||
priv->drag = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
priv->formats = g_value_dup_boxed (value);
|
||||
g_assert (priv->formats != NULL);
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
g_assert (priv->surface != NULL);
|
||||
if (priv->device)
|
||||
g_assert (gdk_surface_get_display (priv->surface) == gdk_device_get_display (priv->device));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (gobject);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIONS:
|
||||
g_value_set_flags (value, priv->actions);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, gdk_device_get_display (priv->device));
|
||||
break;
|
||||
|
||||
case PROP_DRAG:
|
||||
g_value_set_object (value, priv->drag);
|
||||
break;
|
||||
|
||||
case PROP_FORMATS:
|
||||
g_value_set_boxed (value, priv->formats);
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
g_value_set_object (value, priv->surface);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_finalize (GObject *object)
|
||||
{
|
||||
GdkDrop *self = GDK_DROP (object);
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->device);
|
||||
g_clear_object (&priv->drag);
|
||||
|
||||
G_OBJECT_CLASS (gdk_drop_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_class_init (GdkDropClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->status = gdk_drop_default_status;
|
||||
|
||||
object_class->get_property = gdk_drop_get_property;
|
||||
object_class->set_property = gdk_drop_set_property;
|
||||
object_class->finalize = gdk_drop_finalize;
|
||||
|
||||
/**
|
||||
* GdkDrop:actions:
|
||||
*
|
||||
* The possible actions for this drop
|
||||
*/
|
||||
properties[PROP_ACTIONS] =
|
||||
g_param_spec_flags ("actions",
|
||||
"Actions",
|
||||
"The possible actions for this drop",
|
||||
GDK_TYPE_DRAG_ACTION,
|
||||
GDK_ACTION_ALL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:device:
|
||||
*
|
||||
* The #GdkDevice performing the drop
|
||||
*/
|
||||
properties[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"Device",
|
||||
"The device performing the drop",
|
||||
GDK_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:display:
|
||||
*
|
||||
* The #GdkDisplay that the drop belongs to.
|
||||
*/
|
||||
properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display this drag belongs to",
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:drag:
|
||||
*
|
||||
* The #GdkDrag that initiated this drop
|
||||
*/
|
||||
properties[PROP_DRAG] =
|
||||
g_param_spec_object ("drag",
|
||||
"Drag",
|
||||
"The drag that initiated this drop",
|
||||
GDK_TYPE_DRAG,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:formats:
|
||||
*
|
||||
* The possible formats that the drop can provide its data in.
|
||||
*/
|
||||
properties[PROP_FORMATS] =
|
||||
g_param_spec_boxed ("formats",
|
||||
"Formats",
|
||||
"The possible formats for data",
|
||||
GDK_TYPE_CONTENT_FORMATS,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkDrop:surface:
|
||||
*
|
||||
* The #GdkSurface the drop happens on
|
||||
*/
|
||||
properties[PROP_SURFACE] =
|
||||
g_param_spec_object ("surface",
|
||||
"Surface",
|
||||
"The surface the drop is happening on",
|
||||
GDK_TYPE_SURFACE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_init (GdkDrop *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_display:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Gets the #GdkDisplay that @self was created for.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkDisplay
|
||||
**/
|
||||
GdkDisplay *
|
||||
gdk_drop_get_display (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return gdk_device_get_display (priv->device);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_device:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkDevice performing the drop.
|
||||
*
|
||||
* Returns: (transfer none): The #GdkDevice performing the drop.
|
||||
**/
|
||||
GdkDevice *
|
||||
gdk_drop_get_device (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->device;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_formats:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkContentFormats that the drop offers the data
|
||||
* to be read in.
|
||||
*
|
||||
* Returns: (transfer none): The possible #GdkContentFormats
|
||||
**/
|
||||
GdkContentFormats *
|
||||
gdk_drop_get_formats (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_surface:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the #GdkSurface performing the drop.
|
||||
*
|
||||
* Returns: (transfer none): The #GdkSurface performing the drop.
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_drop_get_surface (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
|
||||
return priv->surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_actions:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* Returns the possible actions for this #GdkDrop. If this value
|
||||
* contains multiple actions - ie gdk_drag_action_is_unique()
|
||||
* returns %FALSE for the result - gdk_drag_finish() must choose
|
||||
* the action to use when accepting the drop.
|
||||
*
|
||||
* This value may change over the lifetime of the #GdkDrop both
|
||||
* as a response to source side actions as well as to calls to
|
||||
* gdk_drop_status() or gdk_drag_finish(). The source side will
|
||||
* not change this value anymore once a drop has started.
|
||||
*
|
||||
* Returns: The possible #GdkDragActions
|
||||
**/
|
||||
GdkDragAction
|
||||
gdk_drop_get_actions (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), 0);
|
||||
|
||||
return priv->actions;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_set_actions (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail ((actions & GDK_ACTION_ASK) == 0);
|
||||
|
||||
if (priv->actions == actions)
|
||||
return;
|
||||
|
||||
priv->actions = actions;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_get_drag:
|
||||
* @self: a #GdkDrop
|
||||
*
|
||||
* If this is an in-app drag-and-drop operation, returns the #GdkDrag
|
||||
* that corresponds to this drop.
|
||||
*
|
||||
* If it is not, %NULL is returned.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the corresponding #GdkDrag
|
||||
**/
|
||||
GdkDrag *
|
||||
gdk_drop_get_drag (GdkDrop *self)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), 0);
|
||||
|
||||
return priv->drag;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_status:
|
||||
* @self: a #GdkDrop
|
||||
* @actions: Supported actions of the destination, or 0 to indicate
|
||||
* that a drop will not be accepted
|
||||
*
|
||||
* Selects all actions that are potentially supported by the destination.
|
||||
*
|
||||
* When calling this function, do not restrict the passed in actions to
|
||||
* the ones provided by gdk_drop_get_actions(). Those actions may
|
||||
* change in the future, even depending on the actions you provide here.
|
||||
*
|
||||
* This function should be called by drag destinations in response to
|
||||
* %GDK_DRAG_ENTER or %GDK_DRAG_MOTION events. If the destination does
|
||||
* not yet know the exact actions it supports, it should set any possible
|
||||
* actions first and then later call this function again.
|
||||
*/
|
||||
void
|
||||
gdk_drop_status (GdkDrop *self,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
|
||||
GDK_DROP_GET_CLASS (self)->status (self, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @action: the action performed by the destination or 0 if the drop
|
||||
* failed
|
||||
*
|
||||
* Ends the drag operation after a drop.
|
||||
*
|
||||
* The @action must be a single action selected from the actions
|
||||
* available via gdk_drop_get_actions().
|
||||
**/
|
||||
void
|
||||
gdk_drop_finish (GdkDrop *self,
|
||||
GdkDragAction action)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (gdk_drag_action_is_unique (action));
|
||||
|
||||
GDK_DROP_GET_CLASS (self)->finish (self, action);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_internal (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
|
||||
if (priv->drag)
|
||||
{
|
||||
gdk_drop_read_local_async (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
GDK_DROP_GET_CLASS (self)->read_async (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_async:
|
||||
* @self: a #GdkDrop
|
||||
* @mime_types: (array zero-terminated=1) (element-type utf8):
|
||||
* pointer to an array of mime types
|
||||
* @io_priority: the io priority for the read operation
|
||||
* @cancellable: (allow-none): optional #GCancellable object,
|
||||
* %NULL to ignore
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when
|
||||
* the request is satisfied
|
||||
* @user_data: (closure): the data to pass to @callback
|
||||
*
|
||||
* Asynchronously read the dropped data from a #GdkDrop
|
||||
* in a format that complies with one of the mime types.
|
||||
*/
|
||||
void
|
||||
gdk_drop_read_async (GdkDrop *self,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (mime_types != NULL && mime_types[0] != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
formats = gdk_content_formats_new (mime_types, g_strv_length ((char **) mime_types));
|
||||
|
||||
gdk_drop_read_internal (self, formats, io_priority, cancellable, callback, user_data);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @out_mime_type: (out) (type utf8): return location for the used mime type
|
||||
* @result: a #GAsyncResult
|
||||
* @error: (allow-none): location to store error information on failure, or %NULL
|
||||
*
|
||||
* Finishes an async drop read operation, see gdk_drop_read_async().
|
||||
*
|
||||
* Returns: (nullable) (transfer full): the #GInputStream, or %NULL
|
||||
*/
|
||||
GInputStream *
|
||||
gdk_drop_read_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DROP (self), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_is_tagged (result, gdk_drop_read_local_async))
|
||||
{
|
||||
return gdk_drop_read_local_finish (self, out_mime_type, result, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GDK_DROP_GET_CLASS (self)->read_finish (self, out_mime_type, result, error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GTask *task = data;
|
||||
GError *error = NULL;
|
||||
GValue *value;
|
||||
|
||||
value = g_task_get_task_data (task);
|
||||
|
||||
if (!gdk_content_deserialize_finish (result, value, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_pointer (task, value, NULL);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_got_stream (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GError *error = NULL;
|
||||
GTask *task = data;
|
||||
const char *mime_type;
|
||||
|
||||
stream = gdk_drop_read_finish (GDK_DROP (source), &mime_type, result, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_content_deserialize_async (stream,
|
||||
mime_type,
|
||||
G_VALUE_TYPE (g_task_get_task_data (task)),
|
||||
g_task_get_priority (task),
|
||||
g_task_get_cancellable (task),
|
||||
gdk_drop_read_value_done,
|
||||
task);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
free_value (gpointer value)
|
||||
{
|
||||
g_value_unset (value);
|
||||
g_slice_free (GValue, value);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_read_value_internal (GdkDrop *self,
|
||||
GType type,
|
||||
gpointer source_tag,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkContentFormatsBuilder *builder;
|
||||
GdkContentFormats *formats;
|
||||
GValue *value;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, source_tag);
|
||||
value = g_slice_new0 (GValue);
|
||||
g_value_init (value, type);
|
||||
g_task_set_task_data (task, value, free_value);
|
||||
|
||||
if (priv->drag)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GdkContentProvider *content;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (priv->drag, "content", &content, NULL);
|
||||
|
||||
res = gdk_content_provider_get_value (content, value, &error);
|
||||
|
||||
g_object_unref (content);
|
||||
|
||||
if (res)
|
||||
{
|
||||
g_task_return_pointer (task, value, NULL);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fall through to regular stream transfer */
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
gdk_content_formats_builder_add_gtype (builder, type);
|
||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||
formats = gdk_content_formats_union_deserialize_mime_types (formats);
|
||||
|
||||
gdk_drop_read_internal (self,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
gdk_drop_read_value_got_stream,
|
||||
task);
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_value_async:
|
||||
* @self: a #GdkDrop
|
||||
* @type: a #GType to read
|
||||
* @io_priority: the [I/O priority][io-priority]
|
||||
* of the request.
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the drag operation's contents converted to the given
|
||||
* @type. When the operation is finished @callback will be called.
|
||||
* You can then call gdk_drop_read_value_finish() to get the resulting
|
||||
* #GValue.
|
||||
*
|
||||
* For local drag'n'drop operations that are available in the given #GType, the
|
||||
* value will be copied directly. Otherwise, GDK will try to use
|
||||
* gdk_content_deserialize_async() to convert the data.
|
||||
**/
|
||||
void
|
||||
gdk_drop_read_value_async (GdkDrop *self,
|
||||
GType type,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
gdk_drop_read_value_internal (self,
|
||||
type,
|
||||
gdk_drop_read_value_async,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_value_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @result: a #GAsyncResult
|
||||
* @error: a #GError location to store the error occurring, or %NULL to
|
||||
* ignore.
|
||||
*
|
||||
* Finishes an async drop read started with
|
||||
* gdk_drop_read_value_async().
|
||||
*
|
||||
* Returns: (transfer none): a #GValue containing the result.
|
||||
**/
|
||||
const GValue *
|
||||
gdk_drop_read_value_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_value_async, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_text_async:
|
||||
* @self: a #GdkDrop
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the drag operation's contents converted to a string.
|
||||
* When the operation is finished @callback will be called. You can then
|
||||
* call gdk_drop_read_text_finish() to get the result.
|
||||
*
|
||||
* This is a simple wrapper around gdk_drop_read_value_async(). Use
|
||||
* that function or gdk_drop_read_async() directly if you need more
|
||||
* control over the operation.
|
||||
**/
|
||||
void
|
||||
gdk_drop_read_text_async (GdkDrop *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DROP (self));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
gdk_drop_read_value_internal (self,
|
||||
G_TYPE_STRING,
|
||||
gdk_drop_read_text_async,
|
||||
G_PRIORITY_DEFAULT,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_drop_read_text_finish:
|
||||
* @self: a #GdkDrop
|
||||
* @result: a #GAsyncResult
|
||||
* @error: a #GError location to store the error occurring, or %NULL to
|
||||
* ignore.
|
||||
*
|
||||
* Finishes an asynchronous read started with
|
||||
* gdk_drop_read_text_async().
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a new string or %NULL on error.
|
||||
**/
|
||||
char *
|
||||
gdk_drop_read_text_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_drop_read_text_async, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
value = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
return g_value_dup_string (value);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drop_do_emit_event (GdkEvent *event,
|
||||
gboolean dont_queue)
|
||||
{
|
||||
if (dont_queue)
|
||||
{
|
||||
_gdk_event_emit (event);
|
||||
g_object_unref (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdk_event_queue_append (gdk_event_get_display (event), event);
|
||||
}
|
||||
}
|
||||
void
|
||||
gdk_drop_emit_enter_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_ENTER);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_motion_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_MOTION);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
event->dnd.x_root = x_root;
|
||||
event->dnd.y_root = y_root;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_leave_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DRAG_LEAVE);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_emit_drop_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time)
|
||||
{
|
||||
GdkDropPrivate *priv = gdk_drop_get_instance_private (self);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DROP_START);
|
||||
event->any.surface = g_object_ref (priv->surface);
|
||||
event->dnd.drop = g_object_ref (self);
|
||||
event->dnd.time = time;
|
||||
event->dnd.x_root = x_root;
|
||||
event->dnd.y_root = y_root;
|
||||
gdk_event_set_device (event, priv->device);
|
||||
|
||||
gdk_drop_do_emit_event (event, dont_queue);
|
||||
}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GDK_DROP_H__
|
||||
#define __GDK_DROP_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrop, g_object_unref)
|
||||
|
||||
#define GDK_TYPE_DROP (gdk_drop_get_type ())
|
||||
#define GDK_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DROP, GdkDrop))
|
||||
#define GDK_IS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DROP))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drop_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drop_get_display (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDevice * gdk_drop_get_device (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_drop_get_surface (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_drop_get_formats (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drop_get_actions (GdkDrop *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDrag * gdk_drop_get_drag (GdkDrop *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_status (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_finish (GdkDrop *self,
|
||||
GdkDragAction action);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_async (GdkDrop *self,
|
||||
const char **mime_types,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GInputStream * gdk_drop_read_finish (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_value_async (GdkDrop *self,
|
||||
GType type,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GValue * gdk_drop_read_value_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_drop_read_text_async (GdkDrop *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char * gdk_drop_read_text_finish (GdkDrop *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_DROP_H__ */
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_DROP_PRIVATE_H__
|
||||
#define __GDK_DROP_PRIVATE_H__
|
||||
|
||||
#include "gdkdrop.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DROP, GdkDropClass))
|
||||
#define GDK_IS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DROP))
|
||||
#define GDK_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DROP, GdkDropClass))
|
||||
|
||||
typedef struct _GdkDropClass GdkDropClass;
|
||||
|
||||
|
||||
struct _GdkDrop {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkDropClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* status) (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
void (* finish) (GdkDrop *self,
|
||||
GdkDragAction action);
|
||||
|
||||
void (* read_async) (GdkDrop *self,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream * (* read_finish) (GdkDrop *self,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
};
|
||||
|
||||
void gdk_drop_set_actions (GdkDrop *self,
|
||||
GdkDragAction actions);
|
||||
|
||||
void gdk_drop_emit_enter_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_motion_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_leave_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
guint32 time);
|
||||
void gdk_drop_emit_drop_event (GdkDrop *self,
|
||||
gboolean dont_queue,
|
||||
double x_root,
|
||||
double y_root,
|
||||
guint32 time);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -28,8 +28,7 @@
|
||||
#include "gdkeventsprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdkdropprivate.h"
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -165,14 +164,14 @@ gdk_event_class_init (GdkEventClass *klass)
|
||||
void
|
||||
_gdk_event_emit (GdkEvent *event)
|
||||
{
|
||||
if (gdk_drag_handle_source_event (event))
|
||||
return;
|
||||
|
||||
if (gdk_surface_handle_event (event))
|
||||
if (gdk_drag_context_handle_source_event (event))
|
||||
return;
|
||||
|
||||
if (_gdk_event_func)
|
||||
(*_gdk_event_func) (event, _gdk_event_data);
|
||||
|
||||
if (gdk_drag_context_handle_dest_event (event))
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
@@ -631,6 +630,11 @@ gdk_event_copy (const GdkEvent *event)
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
new_event->key.string = g_strdup (event->key.string);
|
||||
break;
|
||||
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
if (event->crossing.child_surface != NULL)
|
||||
@@ -641,7 +645,12 @@ gdk_event_copy (const GdkEvent *event)
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
g_object_ref (event->dnd.drop);
|
||||
g_object_ref (event->dnd.context);
|
||||
break;
|
||||
|
||||
case GDK_EXPOSE:
|
||||
if (event->expose.region)
|
||||
new_event->expose.region = cairo_region_copy (event->expose.region);
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_PRESS:
|
||||
@@ -693,6 +702,11 @@ gdk_event_finalize (GObject *object)
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
g_free (event->key.string);
|
||||
break;
|
||||
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
g_clear_object (&event->crossing.child_surface);
|
||||
@@ -702,7 +716,8 @@ gdk_event_finalize (GObject *object)
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
g_clear_object (&event->dnd.drop);
|
||||
if (event->dnd.context != NULL)
|
||||
g_object_unref (event->dnd.context);
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_PRESS:
|
||||
@@ -718,6 +733,11 @@ gdk_event_finalize (GObject *object)
|
||||
g_free (event->touch.axes);
|
||||
break;
|
||||
|
||||
case GDK_EXPOSE:
|
||||
if (event->expose.region)
|
||||
cairo_region_destroy (event->expose.region);
|
||||
break;
|
||||
|
||||
case GDK_MOTION_NOTIFY:
|
||||
g_clear_object (&event->motion.tool);
|
||||
g_free (event->motion.axes);
|
||||
@@ -815,6 +835,9 @@ gdk_event_get_time (const GdkEvent *event)
|
||||
case GDK_NOTHING:
|
||||
case GDK_DELETE:
|
||||
case GDK_DESTROY:
|
||||
case GDK_EXPOSE:
|
||||
case GDK_MAP:
|
||||
case GDK_UNMAP:
|
||||
case GDK_GRAB_BROKEN:
|
||||
case GDK_EVENT_LAST:
|
||||
default:
|
||||
@@ -888,6 +911,9 @@ gdk_event_get_state (const GdkEvent *event,
|
||||
case GDK_NOTHING:
|
||||
case GDK_DELETE:
|
||||
case GDK_DESTROY:
|
||||
case GDK_EXPOSE:
|
||||
case GDK_MAP:
|
||||
case GDK_UNMAP:
|
||||
case GDK_GRAB_BROKEN:
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
@@ -1283,6 +1309,37 @@ gdk_event_get_key_group (const GdkEvent *event,
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_event_get_string:
|
||||
* @event: a #GdkEvent
|
||||
* @string: (out) (transfer none): return location for the string
|
||||
*
|
||||
* Extracts a string from an event. The string is an
|
||||
* approximation of the keyval in a key event.
|
||||
*
|
||||
* Returns: %TRUE on success, otherwise %FALSE
|
||||
**/
|
||||
gboolean
|
||||
gdk_event_get_string (const GdkEvent *event,
|
||||
const char **string)
|
||||
{
|
||||
gboolean fetched = TRUE;
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
*string = event->key.string;
|
||||
break;
|
||||
default:
|
||||
*string = NULL;
|
||||
fetched = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_event_get_key_is_modifier:
|
||||
* @event: a #GdkEvent
|
||||
@@ -2004,15 +2061,17 @@ gdk_event_is_sent (const GdkEvent *event)
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_event_get_drop:
|
||||
* gdk_event_get_drag_context:
|
||||
* @event: a #GdkEvent
|
||||
* @context: (out) (transfer none): return location for the drag context
|
||||
*
|
||||
* Gets the #GdkDrop from a DND event.
|
||||
* Gets the drag context from a DND event.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the drop
|
||||
* Returns: %TRUE on success, otherwise %FALSE
|
||||
**/
|
||||
GdkDrop *
|
||||
gdk_event_get_drop (const GdkEvent *event)
|
||||
gboolean
|
||||
gdk_event_get_drag_context (const GdkEvent *event,
|
||||
GdkDragContext **context)
|
||||
{
|
||||
if (!event)
|
||||
return FALSE;
|
||||
@@ -2022,10 +2081,11 @@ gdk_event_get_drop (const GdkEvent *event)
|
||||
event->any.type == GDK_DRAG_MOTION ||
|
||||
event->any.type == GDK_DROP_START)
|
||||
{
|
||||
return event->dnd.drop;
|
||||
*context = event->dnd.context;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2450,6 +2510,8 @@ gdk_event_get_axes (GdkEvent *event,
|
||||
*
|
||||
* Returns: (transfer container) (element-type GdkTimeCoord) (nullable): a list
|
||||
* of time and coordinates
|
||||
*
|
||||
* Since: 3.94
|
||||
*/
|
||||
GList *
|
||||
gdk_event_get_motion_history (const GdkEvent *event)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkdrag.h>
|
||||
#include <gdk/gdkdnd.h>
|
||||
#include <gdk/gdkdevice.h>
|
||||
#include <gdk/gdkdevicetool.h>
|
||||
|
||||
@@ -67,6 +67,8 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* Use this macro as the return value for continuing the propagation of
|
||||
* an event handler.
|
||||
*
|
||||
* Since: 3.4
|
||||
*/
|
||||
#define GDK_EVENT_PROPAGATE (FALSE)
|
||||
|
||||
@@ -75,6 +77,8 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* Use this macro as the return value for stopping the propagation of
|
||||
* an event handler.
|
||||
*
|
||||
* Since: 3.4
|
||||
*/
|
||||
#define GDK_EVENT_STOP (TRUE)
|
||||
|
||||
@@ -83,6 +87,8 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* The primary button. This is typically the left mouse button, or the
|
||||
* right button in a left-handed setup.
|
||||
*
|
||||
* Since: 3.4
|
||||
*/
|
||||
#define GDK_BUTTON_PRIMARY (1)
|
||||
|
||||
@@ -90,6 +96,8 @@ G_BEGIN_DECLS
|
||||
* GDK_BUTTON_MIDDLE:
|
||||
*
|
||||
* The middle button.
|
||||
*
|
||||
* Since: 3.4
|
||||
*/
|
||||
#define GDK_BUTTON_MIDDLE (2)
|
||||
|
||||
@@ -98,12 +106,15 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* The secondary button. This is typically the right mouse button, or the
|
||||
* left button in a left-handed setup.
|
||||
*
|
||||
* Since: 3.4
|
||||
*/
|
||||
#define GDK_BUTTON_SECONDARY (3)
|
||||
|
||||
|
||||
|
||||
typedef struct _GdkEventAny GdkEventAny;
|
||||
typedef struct _GdkEventExpose GdkEventExpose;
|
||||
typedef struct _GdkEventMotion GdkEventMotion;
|
||||
typedef struct _GdkEventButton GdkEventButton;
|
||||
typedef struct _GdkEventTouch GdkEventTouch;
|
||||
@@ -144,6 +155,8 @@ typedef void (*GdkEventFunc) (GdkEvent *event,
|
||||
* hidden or destroyed, usually when the user clicks on a special icon in the
|
||||
* title bar.
|
||||
* @GDK_DESTROY: the surface has been destroyed.
|
||||
* @GDK_EXPOSE: all or part of the surface has become visible and needs to be
|
||||
* redrawn.
|
||||
* @GDK_MOTION_NOTIFY: the pointer (usually a mouse) has moved.
|
||||
* @GDK_BUTTON_PRESS: a mouse button has been pressed.
|
||||
* @GDK_BUTTON_RELEASE: a mouse button has been released.
|
||||
@@ -154,6 +167,8 @@ typedef void (*GdkEventFunc) (GdkEvent *event,
|
||||
* @GDK_FOCUS_CHANGE: the keyboard focus has entered or left the surface.
|
||||
* @GDK_CONFIGURE: the size, position or stacking order of the surface has changed.
|
||||
* Note that GTK+ discards these events for %GDK_SURFACE_CHILD surfaces.
|
||||
* @GDK_MAP: the surface has been mapped.
|
||||
* @GDK_UNMAP: the surface has been unmapped.
|
||||
* @GDK_PROXIMITY_IN: an input device has moved into contact with a sensing
|
||||
* surface (e.g. a touchscreen or graphics tablet).
|
||||
* @GDK_PROXIMITY_OUT: an input device has moved out of contact with a sensing
|
||||
@@ -201,6 +216,7 @@ typedef enum
|
||||
GDK_NOTHING,
|
||||
GDK_DELETE,
|
||||
GDK_DESTROY,
|
||||
GDK_EXPOSE,
|
||||
GDK_MOTION_NOTIFY,
|
||||
GDK_BUTTON_PRESS,
|
||||
GDK_BUTTON_RELEASE,
|
||||
@@ -210,6 +226,8 @@ typedef enum
|
||||
GDK_LEAVE_NOTIFY,
|
||||
GDK_FOCUS_CHANGE,
|
||||
GDK_CONFIGURE,
|
||||
GDK_MAP,
|
||||
GDK_UNMAP,
|
||||
GDK_PROXIMITY_IN,
|
||||
GDK_PROXIMITY_OUT,
|
||||
GDK_DRAG_ENTER,
|
||||
@@ -273,7 +291,7 @@ typedef enum
|
||||
* @GDK_SCROLL_LEFT: the surface is scrolled to the left.
|
||||
* @GDK_SCROLL_RIGHT: the surface is scrolled to the right.
|
||||
* @GDK_SCROLL_SMOOTH: the scrolling is determined by the delta values
|
||||
* in scroll events. See gdk_event_get_scroll_deltas()
|
||||
* in scroll events. See gdk_event_get_scroll_deltas(). Since: 3.4
|
||||
*
|
||||
* Specifies the direction for scroll events.
|
||||
*/
|
||||
@@ -403,6 +421,9 @@ gboolean gdk_event_get_key_is_modifier (const GdkEvent *event,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_key_group (const GdkEvent *event,
|
||||
guint *group);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_string (const GdkEvent *event,
|
||||
const char **string);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_scroll_direction (const GdkEvent *event,
|
||||
@@ -492,7 +513,8 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_is_sent (const GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDrop * gdk_event_get_drop (const GdkEvent *event);
|
||||
gboolean gdk_event_get_drag_context (const GdkEvent *event,
|
||||
GdkDragContext **context);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_event_get_crossing_mode (const GdkEvent *event,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define __GDK_EVENTS_PRIVATE_H__
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkdrag.h>
|
||||
#include <gdk/gdkdnd.h>
|
||||
#include <gdk/gdkdevice.h>
|
||||
#include <gdk/gdkdevicetool.h>
|
||||
|
||||
@@ -63,6 +63,23 @@ struct _GdkEventAny
|
||||
GdkDisplay *display;
|
||||
};
|
||||
|
||||
/*
|
||||
* GdkEventExpose:
|
||||
* @type: the type of the event (%GDK_EXPOSE)
|
||||
* @surface: the surface which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @area: bounding box of @region.
|
||||
* @region: the region that needs to be redrawn.
|
||||
*
|
||||
* Generated when all or part of a surface becomes visible and needs to be
|
||||
* redrawn.
|
||||
*/
|
||||
struct _GdkEventExpose
|
||||
{
|
||||
GdkEventAny any;
|
||||
cairo_region_t *region;
|
||||
};
|
||||
|
||||
/*
|
||||
* GdkEventMotion:
|
||||
* @type: the type of the event.
|
||||
@@ -244,10 +261,22 @@ struct _GdkEventScroll
|
||||
* @keyval: the key that was pressed or released. See the
|
||||
* `gdk/gdkkeysyms.h` header file for a
|
||||
* complete list of GDK key codes.
|
||||
* @length: the length of @string.
|
||||
* @string: a string containing an approximation of the text that
|
||||
* would result from this keypress. The only correct way to handle text
|
||||
* input of text is using input methods (see #GtkIMContext), so this
|
||||
* field is deprecated and should never be used.
|
||||
* (gdk_unicode_to_keyval() provides a non-deprecated way of getting
|
||||
* an approximate translation for a key.) The string is encoded in the
|
||||
* encoding of the current locale (Note: this for backwards compatibility:
|
||||
* strings in GTK+ and GDK are typically in UTF-8.) and NUL-terminated.
|
||||
* In some cases, the translation of the key code will be a single
|
||||
* NUL byte, in which case looking at @length is necessary to distinguish
|
||||
* it from the an empty translation.
|
||||
* @hardware_keycode: the raw code of the key that was pressed or released.
|
||||
* @group: the keyboard group.
|
||||
* @is_modifier: a flag that indicates if @hardware_keycode is mapped to a
|
||||
* modifier
|
||||
* modifier. Since 2.10
|
||||
*
|
||||
* Describes a key press or key release event.
|
||||
*/
|
||||
@@ -257,6 +286,8 @@ struct _GdkEventKey
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint keyval;
|
||||
gint length;
|
||||
gchar *string;
|
||||
guint16 hardware_keycode;
|
||||
guint16 key_scancode;
|
||||
guint8 group;
|
||||
@@ -383,6 +414,8 @@ struct _GdkEventProximity
|
||||
* is unmapped), or if the same application grabs the pointer or keyboard
|
||||
* again. Note that implicit grabs (which are initiated by button presses)
|
||||
* can also cause #GdkEventGrabBroken events.
|
||||
*
|
||||
* Since: 2.8
|
||||
*/
|
||||
struct _GdkEventGrabBroken {
|
||||
GdkEventAny any;
|
||||
@@ -397,7 +430,7 @@ struct _GdkEventGrabBroken {
|
||||
* %GDK_DRAG_MOTION or %GDK_DROP_START)
|
||||
* @surface: the surface which received the event.
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @drop: the #GdkDrop for the current DND operation.
|
||||
* @context: the #GdkDragContext for the current DND operation.
|
||||
* @time: the time of the event in milliseconds.
|
||||
* @x_root: the x coordinate of the pointer relative to the root of the
|
||||
* screen, only set for %GDK_DRAG_MOTION and %GDK_DROP_START.
|
||||
@@ -408,7 +441,7 @@ struct _GdkEventGrabBroken {
|
||||
*/
|
||||
struct _GdkEventDND {
|
||||
GdkEventAny any;
|
||||
GdkDrop *drop;
|
||||
GdkDragContext *context;
|
||||
|
||||
guint32 time;
|
||||
gshort x_root, y_root;
|
||||
@@ -503,6 +536,8 @@ struct _GdkEventTouchpadPinch {
|
||||
* device may have different current modes.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD button presses and releases.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadButton {
|
||||
GdkEventAny any;
|
||||
@@ -527,6 +562,8 @@ struct _GdkEventPadButton {
|
||||
* @value: The current value for the given axis.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD interaction with tactile sensors.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadAxis {
|
||||
GdkEventAny any;
|
||||
@@ -550,6 +587,8 @@ struct _GdkEventPadAxis {
|
||||
* device may have different current modes.
|
||||
*
|
||||
* Generated during %GDK_SOURCE_TABLET_PAD mode switches in a group.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
struct _GdkEventPadGroupMode {
|
||||
GdkEventAny any;
|
||||
@@ -562,6 +601,7 @@ struct _GdkEventPadGroupMode {
|
||||
* GdkEvent:
|
||||
* @type: the #GdkEventType
|
||||
* @any: a #GdkEventAny
|
||||
* @expose: a #GdkEventExpose
|
||||
* @motion: a #GdkEventMotion
|
||||
* @button: a #GdkEventButton
|
||||
* @touch: a #GdkEventTouch
|
||||
@@ -613,6 +653,7 @@ struct _GdkEventPadGroupMode {
|
||||
union _GdkEvent
|
||||
{
|
||||
GdkEventAny any;
|
||||
GdkEventExpose expose;
|
||||
GdkEventMotion motion;
|
||||
GdkEventButton button;
|
||||
GdkEventTouch touch;
|
||||
|
||||
@@ -58,6 +58,8 @@ typedef struct _GdkFrameClockClass GdkFrameClockClass;
|
||||
* #GdkFrameClockPhase is used to represent the different paint clock
|
||||
* phases that can be requested. The elements of the enumeration
|
||||
* correspond to the signals of #GdkFrameClock.
|
||||
*
|
||||
* Since: 3.8
|
||||
**/
|
||||
typedef enum {
|
||||
GDK_FRAME_CLOCK_PHASE_NONE = 0,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -150,6 +150,7 @@ struct _GdkSurface
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
GdkEventMask event_mask;
|
||||
guint8 surface_type;
|
||||
|
||||
guint8 resize_count;
|
||||
@@ -205,6 +206,7 @@ struct _GdkSurface
|
||||
cairo_region_t *input_shape;
|
||||
|
||||
GList *devices_inside;
|
||||
GHashTable *device_events;
|
||||
|
||||
GdkFrameClock *frame_clock; /* NULL to use from parent or default */
|
||||
|
||||
@@ -291,8 +293,6 @@ GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
void gdk_surface_get_unscaled_size (GdkSurface *surface,
|
||||
int *unscaled_width,
|
||||
int *unscaled_height);
|
||||
gboolean gdk_surface_handle_event (GdkEvent *event);
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Interfaces provided by windowing code *
|
||||
|
||||
@@ -50,6 +50,8 @@ typedef struct _GdkMonitorClass GdkMonitorClass;
|
||||
*
|
||||
* This enumeration describes how the red, green and blue components
|
||||
* of physical pixels on an output device are laid out.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_SUBPIXEL_LAYOUT_UNKNOWN,
|
||||
|
||||
@@ -643,8 +643,8 @@ gdk_paintable_new_empty (int intrinsic_width,
|
||||
{
|
||||
GdkEmptyPaintable *result;
|
||||
|
||||
g_return_val_if_fail (intrinsic_width >= 0, NULL);
|
||||
g_return_val_if_fail (intrinsic_height >= 0, NULL);
|
||||
g_return_val_if_fail (intrinsic_width < 0, NULL);
|
||||
g_return_val_if_fail (intrinsic_height < 0, NULL);
|
||||
|
||||
result = g_object_new (GDK_TYPE_EMPTY_PAINTABLE, NULL);
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ G_BEGIN_DECLS
|
||||
* @GDK_SEAT_CAPABILITY_ALL: The union of all capabilities
|
||||
*
|
||||
* Flags describing the seat capabilities.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_SEAT_CAPABILITY_NONE = 0,
|
||||
@@ -69,6 +71,8 @@ typedef enum {
|
||||
* grabbed. A typical action would be ensuring the surface is
|
||||
* visible, although there's room for other initialization
|
||||
* actions.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
typedef void (* GdkSeatGrabPrepareFunc) (GdkSeat *seat,
|
||||
GdkSurface *surface,
|
||||
|
||||
511
gdk/gdksurface.c
511
gdk/gdksurface.c
@@ -97,8 +97,6 @@
|
||||
|
||||
enum {
|
||||
MOVED_TO_RECT,
|
||||
SIZE_CHANGED,
|
||||
RENDER,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@@ -107,7 +105,6 @@ enum {
|
||||
PROP_CURSOR,
|
||||
PROP_DISPLAY,
|
||||
PROP_STATE,
|
||||
PROP_MAPPED,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
@@ -274,13 +271,6 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
GDK_TYPE_SURFACE_STATE, GDK_SURFACE_STATE_WITHDRAWN,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_MAPPED] =
|
||||
g_param_spec_boolean ("mapped",
|
||||
P_("Mapped"),
|
||||
P_("Mapped"),
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, properties);
|
||||
|
||||
/**
|
||||
@@ -320,31 +310,6 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
G_TYPE_POINTER,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
signals[SIZE_CHANGED] =
|
||||
g_signal_new (g_intern_static_string ("size-changed"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT);
|
||||
|
||||
signals[RENDER] =
|
||||
g_signal_new (g_intern_static_string ("render"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
g_signal_accumulator_true_handled,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_BOOLEAN,
|
||||
1,
|
||||
CAIRO_GOBJECT_TYPE_REGION);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -356,6 +321,9 @@ seat_removed_cb (GdkDisplay *display,
|
||||
|
||||
surface->devices_inside = g_list_remove (surface->devices_inside, device);
|
||||
g_hash_table_remove (surface->device_cursor, device);
|
||||
|
||||
if (surface->device_events)
|
||||
g_hash_table_remove (surface->device_events, device);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -368,8 +336,16 @@ gdk_surface_finalize (GObject *object)
|
||||
|
||||
if (!GDK_SURFACE_DESTROYED (surface))
|
||||
{
|
||||
g_warning ("losing last reference to undestroyed surface");
|
||||
_gdk_surface_destroy (surface, FALSE);
|
||||
if (GDK_SURFACE_TYPE (surface) != GDK_SURFACE_FOREIGN)
|
||||
{
|
||||
g_warning ("losing last reference to undestroyed surface");
|
||||
_gdk_surface_destroy (surface, FALSE);
|
||||
}
|
||||
else
|
||||
/* We use TRUE here, to keep us from actually calling
|
||||
* XDestroyWindow() on the window
|
||||
*/
|
||||
_gdk_surface_destroy (surface, TRUE);
|
||||
}
|
||||
|
||||
if (surface->impl)
|
||||
@@ -393,6 +369,9 @@ gdk_surface_finalize (GObject *object)
|
||||
if (surface->device_cursor)
|
||||
g_hash_table_destroy (surface->device_cursor);
|
||||
|
||||
if (surface->device_events)
|
||||
g_hash_table_destroy (surface->device_events);
|
||||
|
||||
if (surface->devices_inside)
|
||||
g_list_free (surface->devices_inside);
|
||||
|
||||
@@ -451,10 +430,6 @@ gdk_surface_get_property (GObject *object,
|
||||
g_value_set_flags (value, surface->state);
|
||||
break;
|
||||
|
||||
case PROP_MAPPED:
|
||||
g_value_set_boolean (value, GDK_SURFACE_IS_MAPPED (surface));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -626,6 +601,45 @@ _gdk_surface_update_size (GdkSurface *surface)
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
}
|
||||
|
||||
static GdkEventMask
|
||||
get_native_device_event_mask (GdkSurface *private,
|
||||
GdkDevice *device)
|
||||
{
|
||||
GdkEventMask event_mask;
|
||||
|
||||
if (device)
|
||||
event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
|
||||
else
|
||||
event_mask = private->event_mask;
|
||||
|
||||
if (private->surface_type == GDK_SURFACE_FOREIGN)
|
||||
return event_mask;
|
||||
else
|
||||
{
|
||||
GdkEventMask mask;
|
||||
|
||||
mask = private->event_mask;
|
||||
|
||||
/* We need thse for all native surfaces so we can
|
||||
emulate events on children: */
|
||||
mask |=
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_TOUCH_MASK |
|
||||
GDK_POINTER_MOTION_MASK |
|
||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_SCROLL_MASK;
|
||||
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkEventMask
|
||||
get_native_event_mask (GdkSurface *private)
|
||||
{
|
||||
return get_native_device_event_mask (private, NULL);
|
||||
}
|
||||
|
||||
GdkSurface*
|
||||
gdk_surface_new (GdkDisplay *display,
|
||||
GdkSurface *parent,
|
||||
@@ -633,6 +647,7 @@ gdk_surface_new (GdkDisplay *display,
|
||||
{
|
||||
GdkSurface *surface;
|
||||
gboolean native;
|
||||
GdkEventMask event_mask;
|
||||
|
||||
g_return_val_if_fail (attributes != NULL, NULL);
|
||||
|
||||
@@ -687,12 +702,20 @@ gdk_surface_new (GdkDisplay *display,
|
||||
#endif
|
||||
break;
|
||||
case GDK_SURFACE_CHILD:
|
||||
if (GDK_SURFACE_TYPE (parent) == GDK_SURFACE_FOREIGN)
|
||||
{
|
||||
g_warning (G_STRLOC "Child surfaces must not be created as children of\n"
|
||||
"a surface of type GDK_SURFACE_FOREIGN");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning (G_STRLOC "cannot make surfaces of type %d", surface->surface_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->event_mask = GDK_ALL_EVENTS_MASK;
|
||||
|
||||
if (attributes->wclass == GDK_INPUT_OUTPUT)
|
||||
{
|
||||
surface->input_only = FALSE;
|
||||
@@ -722,8 +745,10 @@ gdk_surface_new (GdkDisplay *display,
|
||||
|
||||
if (native)
|
||||
{
|
||||
event_mask = get_native_event_mask (surface);
|
||||
|
||||
/* Create the impl */
|
||||
gdk_display_create_surface_impl (display, surface, parent, attributes);
|
||||
_gdk_display_create_surface_impl (display, surface, parent, event_mask, attributes);
|
||||
surface->impl_surface = surface;
|
||||
}
|
||||
else
|
||||
@@ -922,70 +947,81 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface,
|
||||
case GDK_SURFACE_TOPLEVEL:
|
||||
case GDK_SURFACE_CHILD:
|
||||
case GDK_SURFACE_TEMP:
|
||||
case GDK_SURFACE_FOREIGN:
|
||||
case GDK_SURFACE_SUBSURFACE:
|
||||
if (surface->parent)
|
||||
if (surface->surface_type == GDK_SURFACE_FOREIGN && !foreign_destroy)
|
||||
{
|
||||
if (surface->parent->children)
|
||||
surface->parent->children = g_list_remove_link (surface->parent->children, &surface->children_list_node);
|
||||
|
||||
if (!recursing &&
|
||||
GDK_SURFACE_IS_MAPPED (surface))
|
||||
{
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
gdk_surface_invalidate_in_parent (surface);
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->gl_paint_context)
|
||||
{
|
||||
/* Make sure to destroy if current */
|
||||
g_object_run_dispose (G_OBJECT (surface->gl_paint_context));
|
||||
g_object_unref (surface->gl_paint_context);
|
||||
surface->gl_paint_context = NULL;
|
||||
}
|
||||
|
||||
if (surface->frame_clock)
|
||||
{
|
||||
g_object_run_dispose (G_OBJECT (surface->frame_clock));
|
||||
gdk_surface_set_frame_clock (surface, NULL);
|
||||
}
|
||||
|
||||
tmp = surface->children;
|
||||
surface->children = NULL;
|
||||
/* No need to free children list, its all made up of in-struct nodes */
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
temp_surface = tmp->data;
|
||||
tmp = tmp->next;
|
||||
|
||||
if (temp_surface)
|
||||
_gdk_surface_destroy_hierarchy (temp_surface,
|
||||
TRUE,
|
||||
recursing_native || gdk_surface_has_impl (surface),
|
||||
foreign_destroy);
|
||||
}
|
||||
|
||||
_gdk_surface_clear_update_area (surface);
|
||||
|
||||
impl_class = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
|
||||
|
||||
if (gdk_surface_has_impl (surface))
|
||||
impl_class->destroy (surface, recursing_native, foreign_destroy);
|
||||
else
|
||||
{
|
||||
/* hide to make sure we repaint and break grabs */
|
||||
gdk_surface_hide (surface);
|
||||
if (surface->parent)
|
||||
{
|
||||
if (surface->parent->children)
|
||||
surface->parent->children = g_list_remove_link (surface->parent->children, &surface->children_list_node);
|
||||
|
||||
if (!recursing &&
|
||||
GDK_SURFACE_IS_MAPPED (surface))
|
||||
{
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
gdk_surface_invalidate_in_parent (surface);
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->gl_paint_context)
|
||||
{
|
||||
/* Make sure to destroy if current */
|
||||
g_object_run_dispose (G_OBJECT (surface->gl_paint_context));
|
||||
g_object_unref (surface->gl_paint_context);
|
||||
surface->gl_paint_context = NULL;
|
||||
}
|
||||
|
||||
if (surface->frame_clock)
|
||||
{
|
||||
g_object_run_dispose (G_OBJECT (surface->frame_clock));
|
||||
gdk_surface_set_frame_clock (surface, NULL);
|
||||
}
|
||||
|
||||
if (surface->surface_type == GDK_SURFACE_FOREIGN)
|
||||
g_assert (surface->children == NULL);
|
||||
else
|
||||
{
|
||||
tmp = surface->children;
|
||||
surface->children = NULL;
|
||||
/* No need to free children list, its all made up of in-struct nodes */
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
temp_surface = tmp->data;
|
||||
tmp = tmp->next;
|
||||
|
||||
if (temp_surface)
|
||||
_gdk_surface_destroy_hierarchy (temp_surface,
|
||||
TRUE,
|
||||
recursing_native || gdk_surface_has_impl (surface),
|
||||
foreign_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
_gdk_surface_clear_update_area (surface);
|
||||
|
||||
impl_class = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
|
||||
|
||||
if (gdk_surface_has_impl (surface))
|
||||
impl_class->destroy (surface, recursing_native, foreign_destroy);
|
||||
else
|
||||
{
|
||||
/* hide to make sure we repaint and break grabs */
|
||||
gdk_surface_hide (surface);
|
||||
}
|
||||
|
||||
surface->state |= GDK_SURFACE_STATE_WITHDRAWN;
|
||||
surface->parent = NULL;
|
||||
surface->destroyed = TRUE;
|
||||
|
||||
surface_remove_from_pointer_info (surface, display);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
|
||||
}
|
||||
|
||||
surface->state |= GDK_SURFACE_STATE_WITHDRAWN;
|
||||
surface->parent = NULL;
|
||||
surface->destroyed = TRUE;
|
||||
|
||||
surface_remove_from_pointer_info (surface, display);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1657,13 +1693,20 @@ static void
|
||||
gdk_surface_process_updates_recurse (GdkSurface *surface,
|
||||
cairo_region_t *expose_region)
|
||||
{
|
||||
gboolean handled;
|
||||
GdkEvent *event;
|
||||
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
/* Paint the surface before the children, clipped to the surface region */
|
||||
g_signal_emit (surface, signals[RENDER], 0, expose_region, &handled);
|
||||
|
||||
event = gdk_event_new (GDK_EXPOSE);
|
||||
event->any.surface = g_object_ref (surface);
|
||||
event->any.send_event = FALSE;
|
||||
event->expose.region = cairo_region_reference (expose_region);
|
||||
|
||||
_gdk_event_emit (event);
|
||||
g_object_unref (event);
|
||||
}
|
||||
|
||||
/* Process and remove any invalid area on the native surface by creating
|
||||
@@ -2242,8 +2285,10 @@ _gdk_surface_update_viewable (GdkSurface *surface)
|
||||
{
|
||||
gboolean viewable;
|
||||
|
||||
if (gdk_surface_is_toplevel (surface) ||
|
||||
surface->parent->viewable)
|
||||
if (surface->surface_type == GDK_SURFACE_FOREIGN)
|
||||
viewable = TRUE;
|
||||
else if (gdk_surface_is_toplevel (surface) ||
|
||||
surface->parent->viewable)
|
||||
viewable = GDK_SURFACE_IS_MAPPED (surface);
|
||||
else
|
||||
viewable = FALSE;
|
||||
@@ -2283,7 +2328,6 @@ gdk_surface_show_internal (GdkSurface *surface, gboolean raise)
|
||||
{
|
||||
surface->state = 0;
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
|
||||
}
|
||||
|
||||
did_show = _gdk_surface_update_viewable (surface);
|
||||
@@ -2299,6 +2343,15 @@ gdk_surface_show_internal (GdkSurface *surface, gboolean raise)
|
||||
impl_class->show (surface, !did_show ? was_mapped : TRUE);
|
||||
}
|
||||
|
||||
if (!was_mapped && !gdk_surface_has_impl (surface))
|
||||
{
|
||||
if (surface->event_mask & GDK_STRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_MAP, NULL, FALSE);
|
||||
|
||||
if (surface->parent && surface->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_MAP, NULL, FALSE);
|
||||
}
|
||||
|
||||
if (!was_mapped || did_raise)
|
||||
{
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
@@ -2334,7 +2387,7 @@ gdk_surface_show_unraised (GdkSurface *surface)
|
||||
* other surfaces with the same parent surface appear below @surface.
|
||||
* This is true whether or not the surfaces are visible.
|
||||
*
|
||||
* If @surface is a toplevel, the window manager may choose to deny the
|
||||
* If @surface is a toplevel, the surface manager may choose to deny the
|
||||
* request to move the surface in the Z-order, gdk_surface_raise() only
|
||||
* requests the restack, does not guarantee it.
|
||||
*/
|
||||
@@ -2555,7 +2608,6 @@ gdk_surface_hide (GdkSurface *surface)
|
||||
{
|
||||
surface->state = GDK_SURFACE_STATE_WITHDRAWN;
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
|
||||
}
|
||||
|
||||
if (was_mapped)
|
||||
@@ -2602,11 +2654,198 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
|
||||
if (was_mapped && !gdk_surface_has_impl (surface))
|
||||
{
|
||||
if (surface->event_mask & GDK_STRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_UNMAP, NULL, FALSE);
|
||||
|
||||
if (surface->parent && surface->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_UNMAP, NULL, FALSE);
|
||||
}
|
||||
|
||||
/* Invalidate the rect */
|
||||
if (was_mapped)
|
||||
gdk_surface_invalidate_in_parent (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_withdraw:
|
||||
* @surface: a toplevel #GdkSurface
|
||||
*
|
||||
* Withdraws a surface (unmaps it and asks the surface manager to forget about it).
|
||||
* This function is not really useful as gdk_surface_hide() automatically
|
||||
* withdraws toplevel surfaces before hiding them.
|
||||
**/
|
||||
void
|
||||
gdk_surface_withdraw (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplClass *impl_class;
|
||||
gboolean was_mapped;
|
||||
GdkGLContext *current_context;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
|
||||
|
||||
if (gdk_surface_has_impl (surface))
|
||||
{
|
||||
impl_class = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
|
||||
impl_class->withdraw (surface);
|
||||
|
||||
if (was_mapped)
|
||||
{
|
||||
if (surface->event_mask & GDK_STRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_UNMAP, NULL, FALSE);
|
||||
|
||||
if (surface->parent && surface->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
|
||||
_gdk_make_event (surface, GDK_UNMAP, NULL, FALSE);
|
||||
}
|
||||
|
||||
current_context = gdk_gl_context_get_current ();
|
||||
if (current_context != NULL && gdk_gl_context_get_surface (current_context) == surface)
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
recompute_visible_regions (surface, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_set_events:
|
||||
* @surface: a #GdkSurface
|
||||
* @event_mask: event mask for @surface
|
||||
*
|
||||
* The event mask for a surface determines which events will be reported
|
||||
* for that surface from all master input devices. For example, an event mask
|
||||
* including #GDK_BUTTON_PRESS_MASK means the surface should report button
|
||||
* press events. The event mask is the bitwise OR of values from the
|
||||
* #GdkEventMask enumeration.
|
||||
*
|
||||
* See the [input handling overview][event-masks] for details.
|
||||
**/
|
||||
void
|
||||
gdk_surface_set_events (GdkSurface *surface,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
GdkSurfaceImplClass *impl_class;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
surface->event_mask = event_mask;
|
||||
|
||||
if (gdk_surface_has_impl (surface))
|
||||
{
|
||||
impl_class = GDK_SURFACE_IMPL_GET_CLASS (surface->impl);
|
||||
impl_class->set_events (surface,
|
||||
get_native_event_mask (surface));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_get_events:
|
||||
* @surface: a #GdkSurface
|
||||
*
|
||||
* Gets the event mask for @surface for all master input devices. See
|
||||
* gdk_surface_set_events().
|
||||
*
|
||||
* Returns: event mask for @surface
|
||||
**/
|
||||
GdkEventMask
|
||||
gdk_surface_get_events (GdkSurface *surface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), 0);
|
||||
|
||||
if (surface->destroyed)
|
||||
return 0;
|
||||
|
||||
return surface->event_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_set_device_events:
|
||||
* @surface: a #GdkSurface
|
||||
* @device: #GdkDevice to enable events for.
|
||||
* @event_mask: event mask for @surface
|
||||
*
|
||||
* Sets the event mask for a given device (Normally a floating device, not
|
||||
* attached to any visible pointer) to @surface. For example, an event mask
|
||||
* including #GDK_BUTTON_PRESS_MASK means the surface should report button
|
||||
* press events. The event mask is the bitwise OR of values from the
|
||||
* #GdkEventMask enumeration.
|
||||
*
|
||||
* See the [input handling overview][event-masks] for details.
|
||||
**/
|
||||
void
|
||||
gdk_surface_set_device_events (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
GdkEventMask device_mask;
|
||||
GdkSurface *native;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return;
|
||||
|
||||
if (G_UNLIKELY (!surface->device_events))
|
||||
surface->device_events = g_hash_table_new (NULL, NULL);
|
||||
|
||||
if (event_mask == 0)
|
||||
{
|
||||
/* FIXME: unsetting events on a master device
|
||||
* would restore surface->event_mask
|
||||
*/
|
||||
g_hash_table_remove (surface->device_events, device);
|
||||
}
|
||||
else
|
||||
g_hash_table_insert (surface->device_events, device,
|
||||
GINT_TO_POINTER (event_mask));
|
||||
|
||||
native = gdk_surface_get_toplevel (surface);
|
||||
|
||||
device_mask = get_native_device_event_mask (surface, device);
|
||||
GDK_DEVICE_GET_CLASS (device)->select_surface_events (device, native, device_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_get_device_events:
|
||||
* @surface: a #GdkSurface.
|
||||
* @device: a #GdkDevice.
|
||||
*
|
||||
* Returns the event mask for @surface corresponding to an specific device.
|
||||
*
|
||||
* Returns: device event mask for @surface
|
||||
**/
|
||||
GdkEventMask
|
||||
gdk_surface_get_device_events (GdkSurface *surface,
|
||||
GdkDevice *device)
|
||||
{
|
||||
GdkEventMask mask;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), 0);
|
||||
g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return 0;
|
||||
|
||||
if (!surface->device_events)
|
||||
return 0;
|
||||
|
||||
mask = GPOINTER_TO_INT (g_hash_table_lookup (surface->device_events, device));
|
||||
|
||||
/* FIXME: device could be controlled by surface->event_mask */
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_move_resize_toplevel (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
@@ -2847,19 +3086,24 @@ gdk_surface_set_cursor_internal (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
GdkPointerSurfaceInfo *pointer_info;
|
||||
GdkDisplay *display;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return;
|
||||
|
||||
g_assert (gdk_surface_get_display (surface) == gdk_device_get_display (device));
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
pointer_info = _gdk_display_get_pointer_info (display, device);
|
||||
if (surface->surface_type == GDK_SURFACE_FOREIGN)
|
||||
GDK_DEVICE_GET_CLASS (device)->set_surface_cursor (device, surface, cursor);
|
||||
else
|
||||
{
|
||||
GdkPointerSurfaceInfo *pointer_info;
|
||||
GdkDisplay *display;
|
||||
|
||||
if (_gdk_surface_event_parent_of (surface, pointer_info->surface_under_pointer))
|
||||
update_cursor (display, device);
|
||||
display = gdk_surface_get_display (surface);
|
||||
pointer_info = _gdk_display_get_pointer_info (display, device);
|
||||
|
||||
if (_gdk_surface_event_parent_of (surface, pointer_info->surface_under_pointer))
|
||||
update_cursor (display, device);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2893,7 +3137,7 @@ gdk_surface_get_cursor (GdkSurface *surface)
|
||||
*
|
||||
* Note that @cursor must be for the same display as @surface.
|
||||
*
|
||||
* Use gdk_cursor_new_from_name() or gdk_cursor_new_from_texture() to
|
||||
* Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to
|
||||
* create the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR.
|
||||
* Passing %NULL for the @cursor argument to gdk_surface_set_cursor() means
|
||||
* that @surface will use the cursor of its parent surface. Most surfaces
|
||||
@@ -2980,7 +3224,7 @@ gdk_surface_get_device_cursor (GdkSurface *surface,
|
||||
* @cursor: a #GdkCursor
|
||||
*
|
||||
* Sets a specific #GdkCursor for a given device when it gets inside @surface.
|
||||
* Use gdk_cursor_new_fromm_name() or gdk_cursor_new_from_texture() to create
|
||||
* Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to create
|
||||
* the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR. Passing
|
||||
* %NULL for the @cursor argument to gdk_surface_set_cursor() means that
|
||||
* @surface will use the cursor of its parent surface. Most surfaces should
|
||||
@@ -3421,7 +3665,7 @@ gdk_surface_merge_child_input_shapes (GdkSurface *surface)
|
||||
* gdk_surface_get_modal_hint:
|
||||
* @surface: A toplevel #GdkSurface.
|
||||
*
|
||||
* Determines whether or not the window manager is hinted that @surface
|
||||
* Determines whether or not the surface manager is hinted that @surface
|
||||
* has modal behaviour.
|
||||
*
|
||||
* Returns: whether or not the surface has the modal hint set.
|
||||
@@ -3885,8 +4129,11 @@ _gdk_make_event (GdkSurface *surface,
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
case GDK_CONFIGURE:
|
||||
case GDK_MAP:
|
||||
case GDK_UNMAP:
|
||||
case GDK_DELETE:
|
||||
case GDK_DESTROY:
|
||||
case GDK_EXPOSE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -4400,7 +4647,7 @@ gdk_surface_set_transient_for (GdkSurface *surface,
|
||||
* @x: (out): return location for X position of surface frame
|
||||
* @y: (out): return location for Y position of surface frame
|
||||
*
|
||||
* Obtains the top-left corner of the window manager frame in root
|
||||
* Obtains the top-left corner of the surface manager frame in root
|
||||
* surface coordinates.
|
||||
*
|
||||
**/
|
||||
@@ -5113,10 +5360,10 @@ gdk_surface_register_dnd (GdkSurface *surface)
|
||||
*
|
||||
* This function is called by the drag source.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a newly created #GdkDrag or
|
||||
* Returns: (transfer full) (nullable): a newly created #GdkDragContext or
|
||||
* %NULL on error.
|
||||
*/
|
||||
GdkDrag *
|
||||
GdkDragContext *
|
||||
gdk_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
@@ -5440,7 +5687,6 @@ void
|
||||
gdk_surface_set_state (GdkSurface *surface,
|
||||
GdkSurfaceState new_state)
|
||||
{
|
||||
gboolean was_mapped, mapped;
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
if (new_state == surface->state)
|
||||
@@ -5451,12 +5697,8 @@ gdk_surface_set_state (GdkSurface *surface,
|
||||
* inconsistent state to the user.
|
||||
*/
|
||||
|
||||
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
|
||||
|
||||
surface->state = new_state;
|
||||
|
||||
mapped = GDK_SURFACE_IS_MAPPED (surface);
|
||||
|
||||
_gdk_surface_update_viewable (surface);
|
||||
|
||||
/* We only really send the event to toplevels, since
|
||||
@@ -5468,15 +5710,13 @@ gdk_surface_set_state (GdkSurface *surface,
|
||||
{
|
||||
case GDK_SURFACE_TOPLEVEL:
|
||||
case GDK_SURFACE_TEMP: /* ? */
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
|
||||
g_object_notify (G_OBJECT (surface), "state");
|
||||
break;
|
||||
case GDK_SURFACE_FOREIGN:
|
||||
case GDK_SURFACE_CHILD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (was_mapped != mapped)
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5486,16 +5726,3 @@ gdk_synthesize_surface_state (GdkSurface *surface,
|
||||
{
|
||||
gdk_surface_set_state (surface, (surface->state | set_flags) & ~unset_flags);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_surface_handle_event (GdkEvent *event)
|
||||
{
|
||||
if (gdk_event_get_event_type (event) == GDK_CONFIGURE)
|
||||
{
|
||||
g_signal_emit (gdk_event_get_surface (event), signals[SIZE_CHANGED], 0,
|
||||
event->configure.width, event->configure.height);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -45,9 +45,10 @@ typedef struct _GdkGeometry GdkGeometry;
|
||||
* @GDK_SURFACE_CHILD: child surface (used to implement e.g. #GtkEntry)
|
||||
* @GDK_SURFACE_TEMP: override redirect temporary surface (used to implement
|
||||
* #GtkMenu)
|
||||
* @GDK_SURFACE_FOREIGN: foreign surface (see gdk_surface_foreign_new())
|
||||
* @GDK_SURFACE_SUBSURFACE: subsurface; This surface is visually
|
||||
* tied to a toplevel, and is moved/stacked with it. Currently this window
|
||||
* type is only implemented in Wayland
|
||||
* type is only implemented in Wayland. Since 3.14
|
||||
*
|
||||
* Describes the kind of surface.
|
||||
*/
|
||||
@@ -56,6 +57,7 @@ typedef enum
|
||||
GDK_SURFACE_TOPLEVEL,
|
||||
GDK_SURFACE_CHILD,
|
||||
GDK_SURFACE_TEMP,
|
||||
GDK_SURFACE_FOREIGN,
|
||||
GDK_SURFACE_SUBSURFACE
|
||||
} GdkSurfaceType;
|
||||
|
||||
@@ -215,6 +217,9 @@ typedef enum
|
||||
*
|
||||
* In general, when multiple flags are set, flipping should take precedence over
|
||||
* sliding, which should take precedence over resizing.
|
||||
*
|
||||
* Since: 3.22
|
||||
* Stability: Unstable
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@@ -261,6 +266,8 @@ typedef enum
|
||||
*
|
||||
* Indicates which monitor (in a multi-head setup) a surface should span over
|
||||
* when in fullscreen mode.
|
||||
*
|
||||
* Since: 3.8
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
@@ -370,15 +377,16 @@ struct _GdkGeometry
|
||||
* @GDK_SURFACE_STATE_ABOVE: the surface is kept above other surfaces.
|
||||
* @GDK_SURFACE_STATE_BELOW: the surface is kept below other surfaces.
|
||||
* @GDK_SURFACE_STATE_FOCUSED: the surface is presented as focused (with active decorations).
|
||||
* @GDK_SURFACE_STATE_TILED: the surface is in a tiled state. Deprecated
|
||||
* @GDK_SURFACE_STATE_TOP_TILED: whether the top edge is tiled
|
||||
* @GDK_SURFACE_STATE_TOP_RESIZABLE: whether the top edge is resizable
|
||||
* @GDK_SURFACE_STATE_RIGHT_TILED: whether the right edge is tiled
|
||||
* @GDK_SURFACE_STATE_RIGHT_RESIZABLE: whether the right edge is resizable
|
||||
* @GDK_SURFACE_STATE_BOTTOM_TILED: whether the bottom edge is tiled
|
||||
* @GDK_SURFACE_STATE_BOTTOM_RESIZABLE: whether the bottom edge is resizable
|
||||
* @GDK_SURFACE_STATE_LEFT_TILED: whether the left edge is tiled
|
||||
* @GDK_SURFACE_STATE_LEFT_RESIZABLE: whether the left edge is resizable
|
||||
* @GDK_SURFACE_STATE_TILED: the surface is in a tiled state, Since 3.10. Since 3.91.2, this
|
||||
* is deprecated in favor of per-edge information.
|
||||
* @GDK_SURFACE_STATE_TOP_TILED: whether the top edge is tiled, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_TOP_RESIZABLE: whether the top edge is resizable, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_RIGHT_TILED: whether the right edge is tiled, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_RIGHT_RESIZABLE: whether the right edge is resizable, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_BOTTOM_TILED: whether the bottom edge is tiled, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_BOTTOM_RESIZABLE: whether the bottom edge is resizable, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_LEFT_TILED: whether the left edge is tiled, Since 3.91.2
|
||||
* @GDK_SURFACE_STATE_LEFT_RESIZABLE: whether the left edge is resizable, Since 3.91.2
|
||||
*
|
||||
* Specifies the state of a toplevel surface.
|
||||
*/
|
||||
@@ -460,6 +468,8 @@ void gdk_surface_show (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_hide (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_withdraw (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_show_unraised (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_move (GdkSurface *surface,
|
||||
@@ -675,6 +685,19 @@ GDK_AVAILABLE_IN_ALL
|
||||
GList * gdk_surface_get_children_with_user_data (GdkSurface *surface,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkEventMask gdk_surface_get_events (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_set_events (GdkSurface *surface,
|
||||
GdkEventMask event_mask);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_set_device_events (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkEventMask event_mask);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkEventMask gdk_surface_get_device_events (GdkSurface *surface,
|
||||
GdkDevice *device);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_set_icon_list (GdkSurface *surface,
|
||||
GList *surfaces);
|
||||
|
||||
@@ -76,6 +76,10 @@ struct _GdkSurfaceImplClass
|
||||
gint rect_anchor_dx,
|
||||
gint rect_anchor_dy);
|
||||
|
||||
GdkEventMask (* get_events) (GdkSurface *surface);
|
||||
void (* set_events) (GdkSurface *surface,
|
||||
GdkEventMask event_mask);
|
||||
|
||||
void (* get_geometry) (GdkSurface *surface,
|
||||
gint *x,
|
||||
gint *y,
|
||||
@@ -193,7 +197,7 @@ struct _GdkSurfaceImplClass
|
||||
gdouble opacity);
|
||||
void (* destroy_notify) (GdkSurface *surface);
|
||||
void (* register_dnd) (GdkSurface *surface);
|
||||
GdkDrag * (*drag_begin) (GdkSurface *surface,
|
||||
GdkDragContext * (*drag_begin) (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider*content,
|
||||
GdkDragAction actions,
|
||||
|
||||
@@ -123,8 +123,7 @@ typedef struct _GdkContentProvider GdkContentProvider;
|
||||
typedef struct _GdkCursor GdkCursor;
|
||||
typedef struct _GdkTexture GdkTexture;
|
||||
typedef struct _GdkDevice GdkDevice;
|
||||
typedef struct _GdkDrag GdkDrag;
|
||||
typedef struct _GdkDrop GdkDrop;
|
||||
typedef struct _GdkDragContext GdkDragContext;
|
||||
|
||||
typedef struct _GdkClipboard GdkClipboard;
|
||||
typedef struct _GdkDisplayManager GdkDisplayManager;
|
||||
@@ -196,9 +195,9 @@ typedef enum
|
||||
* @GDK_MODIFIER_RESERVED_23_MASK: A reserved bit flag; do not use in your own code
|
||||
* @GDK_MODIFIER_RESERVED_24_MASK: A reserved bit flag; do not use in your own code
|
||||
* @GDK_MODIFIER_RESERVED_25_MASK: A reserved bit flag; do not use in your own code
|
||||
* @GDK_SUPER_MASK: the Super modifier
|
||||
* @GDK_HYPER_MASK: the Hyper modifier
|
||||
* @GDK_META_MASK: the Meta modifier
|
||||
* @GDK_SUPER_MASK: the Super modifier. Since 2.10
|
||||
* @GDK_HYPER_MASK: the Hyper modifier. Since 2.10
|
||||
* @GDK_META_MASK: the Meta modifier. Since 2.10
|
||||
* @GDK_MODIFIER_RESERVED_29_MASK: A reserved bit flag; do not use in your own code
|
||||
* @GDK_RELEASE_MASK: not used in GDK itself. GTK+ uses it to differentiate
|
||||
* between (keyval, modifiers) pairs from key press and release events.
|
||||
@@ -210,7 +209,7 @@ typedef enum
|
||||
*
|
||||
* Like the X Window System, GDK supports 8 modifier keys and 5 mouse buttons.
|
||||
*
|
||||
* GDK recognizes which of the Meta, Super or Hyper keys are mapped
|
||||
* Since 2.10, GDK recognizes which of the Meta, Super or Hyper keys are mapped
|
||||
* to Mod2 - Mod5, and indicates this by setting %GDK_SUPER_MASK,
|
||||
* %GDK_HYPER_MASK or %GDK_META_MASK in the state field of key events.
|
||||
*
|
||||
@@ -299,6 +298,8 @@ typedef enum
|
||||
* invoking menu shortcuts (accelerators), whereas on Apple computers
|
||||
* it’s the Command key (which correspond to %GDK_CONTROL_MASK and
|
||||
* %GDK_MOD2_MASK, respectively).
|
||||
*
|
||||
* Since: 3.4
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
@@ -320,7 +321,7 @@ typedef enum
|
||||
* @GDK_GRAB_NOT_VIEWABLE: the grab surface or the @confine_to surface are not
|
||||
* viewable.
|
||||
* @GDK_GRAB_FROZEN: the resource is frozen by an active grab of another client.
|
||||
* @GDK_GRAB_FAILED: the grab failed for some other reason
|
||||
* @GDK_GRAB_FAILED: the grab failed for some other reason. Since 3.16
|
||||
*
|
||||
* Returned by gdk_device_grab() to indicate success or the reason for the
|
||||
* failure of the grab attempt.
|
||||
@@ -369,12 +370,13 @@ typedef enum
|
||||
* @GDK_PROPERTY_CHANGE_MASK: receive property change events
|
||||
* @GDK_PROXIMITY_IN_MASK: receive proximity in events
|
||||
* @GDK_PROXIMITY_OUT_MASK: receive proximity out events
|
||||
* @GDK_SUBSTRUCTURE_MASK: receive events about surface configuration changes of child surfaces
|
||||
* @GDK_SUBSTRUCTURE_MASK: receive events about surface configuration changes of
|
||||
* child surfaces
|
||||
* @GDK_SCROLL_MASK: receive scroll events
|
||||
* @GDK_TOUCH_MASK: receive touch events
|
||||
* @GDK_SMOOTH_SCROLL_MASK: receive smooth scrolling events
|
||||
@GDK_TOUCHPAD_GESTURE_MASK: receive touchpad gesture events
|
||||
* @GDK_TABLET_PAD_MASK: receive tablet pad events
|
||||
* @GDK_TOUCH_MASK: receive touch events. Since 3.4
|
||||
* @GDK_SMOOTH_SCROLL_MASK: receive smooth scrolling events. Since 3.4
|
||||
@GDK_TOUCHPAD_GESTURE_MASK: receive touchpad gesture events. Since 3.18
|
||||
* @GDK_TABLET_PAD_MASK: receive tablet pad events. Since 3.22
|
||||
* @GDK_ALL_EVENTS_MASK: the combination of all the above event masks.
|
||||
*
|
||||
* A set of bit-flags to indicate which events a surface is to receive.
|
||||
@@ -384,6 +386,11 @@ typedef enum
|
||||
* See the [input handling overview][chap-input-handling] for details of
|
||||
* [event masks][event-masks] and [event propagation][event-propagation].
|
||||
*
|
||||
* Since GTK 3.8, motion events are already compressed by default, independent
|
||||
* of this mechanism. This compression can be disabled with
|
||||
* gdk_surface_set_event_compression(). See the documentation of that function
|
||||
* for details.
|
||||
*
|
||||
* If %GDK_TOUCH_MASK is enabled, the surface will receive touch events
|
||||
* from touch-enabled devices. Those will come as sequences of #GdkEventTouch
|
||||
* with type %GDK_TOUCH_UPDATE, enclosed by two events with
|
||||
@@ -424,10 +431,12 @@ typedef enum
|
||||
* @GDK_GL_ERROR_NOT_AVAILABLE: OpenGL support is not available
|
||||
* @GDK_GL_ERROR_UNSUPPORTED_FORMAT: The requested visual format is not supported
|
||||
* @GDK_GL_ERROR_UNSUPPORTED_PROFILE: The requested profile is not supported
|
||||
* @GDK_GL_ERROR_COMPILATION_FAILED: The shader compilation failed
|
||||
* @GDK_GL_ERROR_LINK_FAILED: The shader linking failed
|
||||
* @GDK_GL_ERROR_COMPILATION_FAILED: The shader compilation failed (available since 3.22)
|
||||
* @GDK_GL_ERROR_LINK_FAILED: The shader linking failed (available since 3.22)
|
||||
*
|
||||
* Error enumeration for #GdkGLContext.
|
||||
*
|
||||
* Since: 3.16
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
@@ -444,6 +453,8 @@ typedef enum {
|
||||
* @GDK_VULKAN_ERROR_NOT_AVAILABLE: Vulkan support is not available on this Surface
|
||||
*
|
||||
* Error enumeration for #GdkVulkanContext.
|
||||
*
|
||||
* Since: 3.90
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
@@ -507,9 +518,9 @@ typedef enum
|
||||
* @GDK_AXIS_XTILT: the axis is used for x tilt information.
|
||||
* @GDK_AXIS_YTILT: the axis is used for y tilt information.
|
||||
* @GDK_AXIS_WHEEL: the axis is used for wheel information.
|
||||
* @GDK_AXIS_DISTANCE: the axis is used for pen/tablet distance information
|
||||
* @GDK_AXIS_ROTATION: the axis is used for pen rotation information
|
||||
* @GDK_AXIS_SLIDER: the axis is used for pen slider information
|
||||
* @GDK_AXIS_DISTANCE: the axis is used for pen/tablet distance information. (Since: 3.22)
|
||||
* @GDK_AXIS_ROTATION: the axis is used for pen rotation information. (Since: 3.22)
|
||||
* @GDK_AXIS_SLIDER: the axis is used for pen slider information. (Since: 3.22)
|
||||
* @GDK_AXIS_LAST: a constant equal to the numerically highest axis value.
|
||||
*
|
||||
* An enumeration describing the way in which a device
|
||||
@@ -548,6 +559,8 @@ typedef enum
|
||||
* @GDK_AXIS_FLAG_SLIDER: Slider axis is present
|
||||
*
|
||||
* Flags describing the current capabilities of a device/tool.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
@@ -562,35 +575,6 @@ typedef enum
|
||||
GDK_AXIS_FLAG_SLIDER = 1 << GDK_AXIS_SLIDER,
|
||||
} GdkAxisFlags;
|
||||
|
||||
/**
|
||||
* GdkDragAction:
|
||||
* @GDK_ACTION_COPY: Copy the data.
|
||||
* @GDK_ACTION_MOVE: Move the data, i.e. first copy it, then delete
|
||||
* it from the source using the DELETE target of the X selection protocol.
|
||||
* @GDK_ACTION_LINK: Add a link to the data. Note that this is only
|
||||
* useful if source and destination agree on what it means.
|
||||
* @GDK_ACTION_ASK: Ask the user what to do with the data.
|
||||
*
|
||||
* Used in #GdkDrag to indicate what the destination
|
||||
* should do with the dropped data.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_ACTION_COPY = 1 << 0,
|
||||
GDK_ACTION_MOVE = 1 << 1,
|
||||
GDK_ACTION_LINK = 1 << 2,
|
||||
GDK_ACTION_ASK = 1 << 3
|
||||
} GdkDragAction;
|
||||
|
||||
/**
|
||||
* GDK_ACTION_ALL:
|
||||
*
|
||||
* Defines all possible DND actions. This can be used in gdk_drop_status()
|
||||
* messages when any drop can be accepted or a more specific drop method
|
||||
* is not yet known.
|
||||
*/
|
||||
#define GDK_ACTION_ALL (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TYPES_H__ */
|
||||
|
||||
@@ -15,9 +15,8 @@ gdk_public_sources = files([
|
||||
'gdkdevicetool.c',
|
||||
'gdkdisplay.c',
|
||||
'gdkdisplaymanager.c',
|
||||
'gdkdrag.c',
|
||||
'gdkdnd.c',
|
||||
'gdkdrawcontext.c',
|
||||
'gdkdrop.c',
|
||||
'gdkevents.c',
|
||||
'gdkframeclock.c',
|
||||
'gdkframeclockidle.c',
|
||||
@@ -65,9 +64,8 @@ gdk_public_headers = files([
|
||||
'gdkdevicetool.h',
|
||||
'gdkdisplay.h',
|
||||
'gdkdisplaymanager.h',
|
||||
'gdkdrag.h',
|
||||
'gdkdnd.h',
|
||||
'gdkdrawcontext.h',
|
||||
'gdkdrop.h',
|
||||
'gdkevents.h',
|
||||
'gdkframeclock.h',
|
||||
'gdkframetimings.h',
|
||||
|
||||
@@ -527,6 +527,16 @@ drag_operation_to_drag_action (NSDragOperation operation)
|
||||
/* GDK and Quartz drag operations do not map 1:1.
|
||||
* This mapping represents about the best that we
|
||||
* can come up.
|
||||
*
|
||||
* Note that NSDragOperationPrivate and GDK_ACTION_PRIVATE
|
||||
* have almost opposite meanings: the GDK one means that the
|
||||
* destination is solely responsible for the action; the Quartz
|
||||
* one means that the source and destination will agree
|
||||
* privately on the action. NSOperationGeneric is close in meaning
|
||||
* to GDK_ACTION_PRIVATE but there is a problem: it will be
|
||||
* sent for any ordinary drag, and likely not understood
|
||||
* by any intra-widget drag (since the source & dest are the
|
||||
* same).
|
||||
*/
|
||||
|
||||
if (operation & NSDragOperationGeneric)
|
||||
@@ -559,13 +569,11 @@ drag_action_to_drag_operation (GdkDragAction action)
|
||||
static void
|
||||
update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
{
|
||||
GdkDragAction action;
|
||||
|
||||
g_assert (current_context != NULL);
|
||||
|
||||
GDK_QUARTZ_DRAG_CONTEXT (current_context)->dragging_info = sender;
|
||||
action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
|
||||
gdk_drag_context_set_actions (current_context, action, action);
|
||||
current_context->suggested_action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
|
||||
current_context->actions = current_context->suggested_action;
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
|
||||
@@ -76,6 +76,9 @@ static GdkSurface * gdk_quartz_device_core_surface_at_position (GdkDevice
|
||||
gdouble *win_y,
|
||||
GdkModifierType *mask,
|
||||
gboolean get_toplevel);
|
||||
static void gdk_quartz_device_core_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkEventMask event_mask);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GdkQuartzDeviceCore, gdk_quartz_device_core, GDK_TYPE_DEVICE)
|
||||
@@ -93,6 +96,7 @@ gdk_quartz_device_core_class_init (GdkQuartzDeviceCoreClass *klass)
|
||||
device_class->grab = gdk_quartz_device_core_grab;
|
||||
device_class->ungrab = gdk_quartz_device_core_ungrab;
|
||||
device_class->surface_at_position = gdk_quartz_device_core_surface_at_position;
|
||||
device_class->select_surface_events = gdk_quartz_device_core_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -345,3 +349,10 @@ gdk_quartz_device_core_surface_at_position (GdkDevice *device,
|
||||
return found_window;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_device_core_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
/* The mask is set in the common code. */
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ void _gdk_quartz_display_after_process_all_updates (GdkDisplay *display);
|
||||
void _gdk_quartz_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *window,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes);
|
||||
|
||||
/* Display methods - keymap */
|
||||
|
||||
@@ -46,6 +46,7 @@ _gdk_quartz_surface_drag_begin (GdkSurface *window,
|
||||
_gdk_quartz_drag_source_context = g_object_new (GDK_TYPE_QUARTZ_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
NULL);
|
||||
_gdk_quartz_drag_source_context->is_source = TRUE;
|
||||
|
||||
_gdk_quartz_drag_source_context->source_surface = window;
|
||||
g_object_ref (window);
|
||||
@@ -69,6 +70,22 @@ gdk_quartz_drag_context_drag_abort (GdkDragContext *context,
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time)
|
||||
{
|
||||
context->action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_surface_register_dnd (GdkSurface *window)
|
||||
{
|
||||
@@ -100,6 +117,8 @@ gdk_quartz_drag_context_class_init (GdkQuartzDragContextClass *klass)
|
||||
|
||||
object_class->finalize = gdk_quartz_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_quartz_drag_context_drag_status;
|
||||
context_class->drag_abort = gdk_quartz_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_quartz_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_quartz_drag_context_drop_finish;
|
||||
}
|
||||
|
||||
@@ -1113,6 +1113,8 @@ fill_key_event (GdkSurface *window,
|
||||
{
|
||||
GdkEventPrivate *priv;
|
||||
GdkQuartzDeviceManagerCore *device_manager;
|
||||
gchar buf[7];
|
||||
gunichar c = 0;
|
||||
|
||||
priv = (GdkEventPrivate *) event;
|
||||
priv->windowing_data = [nsevent retain];
|
||||
@@ -1187,6 +1189,44 @@ fill_key_event (GdkSurface *window,
|
||||
gdk_keymap_add_virtual_modifiers (gdk_display_get_keymap (_gdk_display),
|
||||
&event->key.state);
|
||||
|
||||
event->key.string = NULL;
|
||||
|
||||
/* Fill in ->string since apps depend on it, taken from the x11 backend. */
|
||||
if (event->key.keyval != GDK_KEY_VoidSymbol)
|
||||
c = gdk_keyval_to_unicode (event->key.keyval);
|
||||
|
||||
if (c)
|
||||
{
|
||||
gsize bytes_written;
|
||||
gint len;
|
||||
|
||||
len = g_unichar_to_utf8 (c, buf);
|
||||
buf[len] = '\0';
|
||||
|
||||
event->key.string = g_locale_from_utf8 (buf, len,
|
||||
NULL, &bytes_written,
|
||||
NULL);
|
||||
if (event->key.string)
|
||||
event->key.length = bytes_written;
|
||||
}
|
||||
else if (event->key.keyval == GDK_KEY_Escape)
|
||||
{
|
||||
event->key.length = 1;
|
||||
event->key.string = g_strdup ("\033");
|
||||
}
|
||||
else if (event->key.keyval == GDK_KEY_Return ||
|
||||
event->key.keyval == GDK_KEY_KP_Enter)
|
||||
{
|
||||
event->key.length = 1;
|
||||
event->key.string = g_strdup ("\r");
|
||||
}
|
||||
|
||||
if (!event->key.string)
|
||||
{
|
||||
event->key.length = 0;
|
||||
event->key.string = g_strdup ("");
|
||||
}
|
||||
|
||||
GDK_NOTE(EVENTS,
|
||||
g_message ("key %s:\t\twindow: %p key: %12s %d",
|
||||
type == GDK_KEY_PRESS ? "press" : "release",
|
||||
|
||||
@@ -731,6 +731,7 @@ void
|
||||
_gdk_quartz_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *window,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes)
|
||||
{
|
||||
GdkSurfaceImplQuartz *impl;
|
||||
@@ -1614,6 +1615,22 @@ gdk_surface_quartz_get_device_state (GdkSurface *window,
|
||||
x, y, mask) != NULL;
|
||||
}
|
||||
|
||||
static GdkEventMask
|
||||
gdk_surface_quartz_get_events (GdkSurface *window)
|
||||
{
|
||||
if (GDK_SURFACE_DESTROYED (window))
|
||||
return 0;
|
||||
else
|
||||
return window->event_mask;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_quartz_set_events (GdkSurface *window,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
/* The mask is set in the common code. */
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_surface_set_urgency_hint (GdkSurface *window,
|
||||
gboolean urgent)
|
||||
@@ -2729,6 +2746,8 @@ gdk_surface_impl_quartz_class_init (GdkSurfaceImplQuartzClass *klass)
|
||||
impl_class->show = gdk_surface_quartz_show;
|
||||
impl_class->hide = gdk_surface_quartz_hide;
|
||||
impl_class->withdraw = gdk_surface_quartz_withdraw;
|
||||
impl_class->set_events = gdk_surface_quartz_set_events;
|
||||
impl_class->get_events = gdk_surface_quartz_get_events;
|
||||
impl_class->raise = gdk_surface_quartz_raise;
|
||||
impl_class->lower = gdk_surface_quartz_lower;
|
||||
impl_class->restack_toplevel = gdk_surface_quartz_restack_toplevel;
|
||||
|
||||
@@ -52,13 +52,13 @@ static void
|
||||
gdk_wayland_clipboard_discard_offer (GdkWaylandClipboard *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->offer_formats, gdk_content_formats_unref);
|
||||
g_clear_pointer (&cb->offer, wl_data_offer_destroy);
|
||||
g_clear_pointer (&cb->offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_clipboard_discard_source (GdkWaylandClipboard *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->source, wl_data_source_destroy);
|
||||
g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevicepadprivate.h"
|
||||
#include "gdkdevicetoolprivate.h"
|
||||
#include "gdkdropprivate.h"
|
||||
#include "gdkprimary-wayland.h"
|
||||
#include "gdkseatprivate.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
@@ -247,8 +246,10 @@ struct _GdkWaylandSeat
|
||||
GdkClipboard *clipboard;
|
||||
GdkClipboard *primary_clipboard;
|
||||
struct wl_data_device *data_device;
|
||||
GdkDrag *drag;
|
||||
GdkDrop *drop;
|
||||
GdkDragContext *drop_context;
|
||||
|
||||
/* Source/dest for non-local dnd */
|
||||
GdkSurface *foreign_dnd_surface;
|
||||
|
||||
/* Some tracking on gesture events */
|
||||
guint gesture_n_fingers;
|
||||
@@ -863,6 +864,13 @@ gdk_wayland_device_surface_at_position (GdkDevice *device,
|
||||
return pointer->focus;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
|
||||
{
|
||||
@@ -876,6 +884,7 @@ gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
|
||||
device_class->grab = gdk_wayland_device_grab;
|
||||
device_class->ungrab = gdk_wayland_device_ungrab;
|
||||
device_class->surface_at_position = gdk_wayland_device_surface_at_position;
|
||||
device_class->select_surface_events = gdk_wayland_device_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1087,7 +1096,7 @@ gdk_wayland_seat_discard_pending_offer (GdkWaylandSeat *seat)
|
||||
gdk_content_formats_unref (ignore);
|
||||
seat->pending_builder = NULL;
|
||||
}
|
||||
g_clear_pointer (&seat->pending_offer, wl_data_offer_destroy);
|
||||
g_clear_pointer (&seat->pending_offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
seat->pending_source_actions = 0;
|
||||
seat->pending_action = 0;
|
||||
}
|
||||
@@ -1131,6 +1140,8 @@ data_offer_source_actions (void *data,
|
||||
uint32_t source_actions)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkDragContext *drop_context;
|
||||
GdkDevice *device;
|
||||
|
||||
if (offer == seat->pending_offer)
|
||||
{
|
||||
@@ -1138,16 +1149,15 @@ data_offer_source_actions (void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat->drop == NULL)
|
||||
device = gdk_seat_get_pointer (GDK_SEAT (seat));
|
||||
drop_context = gdk_wayland_device_get_drop_context (device);
|
||||
if (drop_context == NULL)
|
||||
return;
|
||||
|
||||
gdk_wayland_drop_set_source_actions (seat->drop, source_actions);
|
||||
drop_context->actions = gdk_wayland_actions_to_gdk_actions (source_actions);
|
||||
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1156,6 +1166,8 @@ data_offer_action (void *data,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkDragContext *drop_context;
|
||||
GdkDevice *device;
|
||||
|
||||
if (offer == seat->pending_offer)
|
||||
{
|
||||
@@ -1163,16 +1175,15 @@ data_offer_action (void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat->drop == NULL)
|
||||
device = gdk_seat_get_pointer (GDK_SEAT (seat));
|
||||
drop_context = gdk_wayland_device_get_drop_context (device);
|
||||
if (drop_context == NULL)
|
||||
return;
|
||||
|
||||
gdk_wayland_drop_set_action (seat->drop, action);
|
||||
drop_context->action = gdk_wayland_actions_to_gdk_actions (action);
|
||||
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_emit_event (drop_context, GDK_DRAG_MOTION,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static const struct wl_data_offer_listener data_offer_listener = {
|
||||
@@ -1214,7 +1225,7 @@ data_device_enter (void *data,
|
||||
struct wl_data_offer *offer)
|
||||
{
|
||||
GdkWaylandSeat *seat = data;
|
||||
GdkSurface *dest_surface;
|
||||
GdkSurface *dest_surface, *dnd_owner;
|
||||
GdkContentFormats *formats;
|
||||
GdkDevice *device;
|
||||
|
||||
@@ -1254,13 +1265,22 @@ data_device_enter (void *data,
|
||||
seat->pending_builder = NULL;
|
||||
seat->pending_offer = NULL;
|
||||
|
||||
seat->drop = gdk_wayland_drop_new (device, seat->drag, formats, dest_surface, offer, serial);
|
||||
seat->drop_context = _gdk_wayland_drop_context_new (device, formats, offer);
|
||||
|
||||
dnd_owner = seat->foreign_dnd_surface;
|
||||
|
||||
_gdk_wayland_drag_context_set_source_surface (seat->drop_context, dnd_owner);
|
||||
|
||||
_gdk_wayland_drag_context_set_dest_surface (seat->drop_context,
|
||||
dest_surface, serial);
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context,
|
||||
wl_fixed_to_double (x),
|
||||
wl_fixed_to_double (y));
|
||||
|
||||
gdk_wayland_seat_discard_pending_offer (seat);
|
||||
|
||||
gdk_drop_emit_enter_event (seat->drop,
|
||||
FALSE,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context, GDK_DRAG_ENTER,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1272,17 +1292,18 @@ data_device_leave (void *data,
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("data device leave, data device %p", data_device));
|
||||
|
||||
if (seat->drop == NULL)
|
||||
if (seat->drop_context == NULL)
|
||||
return;
|
||||
|
||||
g_object_unref (seat->pointer_info.focus);
|
||||
seat->pointer_info.focus = NULL;
|
||||
|
||||
gdk_drop_emit_leave_event (seat->drop,
|
||||
FALSE,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context, -1, -1);
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context, GDK_DRAG_LEAVE,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_set_dest_surface (seat->drop_context, NULL, 0);
|
||||
|
||||
g_clear_object (&seat->drop);
|
||||
g_clear_object (&seat->drop_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1298,18 +1319,18 @@ data_device_motion (void *data,
|
||||
g_message ("data device motion, data_device = %p, time = %d, x = %f, y = %f",
|
||||
data_device, time, wl_fixed_to_double (x), wl_fixed_to_double (y)));
|
||||
|
||||
if (seat->drop == NULL)
|
||||
if (seat->drop_context == NULL)
|
||||
return;
|
||||
|
||||
/* Update pointer state, so device state queries work during DnD */
|
||||
seat->pointer_info.surface_x = wl_fixed_to_double (x);
|
||||
seat->pointer_info.surface_y = wl_fixed_to_double (y);
|
||||
|
||||
gdk_drop_emit_motion_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
time);
|
||||
_gdk_wayland_drag_context_set_coords (seat->drop_context,
|
||||
wl_fixed_to_double (x),
|
||||
wl_fixed_to_double (y));
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context,
|
||||
GDK_DRAG_MOTION, time);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1321,11 +1342,8 @@ data_device_drop (void *data,
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("data device drop, data device %p", data_device));
|
||||
|
||||
gdk_drop_emit_drop_event (seat->drop,
|
||||
FALSE,
|
||||
seat->pointer_info.surface_x,
|
||||
seat->pointer_info.surface_y,
|
||||
GDK_CURRENT_TIME);
|
||||
_gdk_wayland_drag_context_emit_event (seat->drop_context,
|
||||
GDK_DROP_START, GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2009,6 +2027,73 @@ keyboard_handle_leave (void *data,
|
||||
|
||||
static gboolean keyboard_repeat (gpointer data);
|
||||
|
||||
static void
|
||||
translate_keyboard_string (GdkEventKey *event)
|
||||
{
|
||||
gunichar c = 0;
|
||||
gchar buf[7];
|
||||
|
||||
/* Fill in event->string crudely, since various programs
|
||||
* depend on it.
|
||||
*/
|
||||
event->string = NULL;
|
||||
|
||||
if (event->keyval != GDK_KEY_VoidSymbol)
|
||||
c = gdk_keyval_to_unicode (event->keyval);
|
||||
|
||||
if (c)
|
||||
{
|
||||
gsize bytes_written;
|
||||
gint len;
|
||||
|
||||
/* Apply the control key - Taken from Xlib */
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
if ((c >= '@' && c < '\177') || c == ' ')
|
||||
c &= 0x1F;
|
||||
else if (c == '2')
|
||||
{
|
||||
event->string = g_memdup ("\0\0", 2);
|
||||
event->length = 1;
|
||||
buf[0] = '\0';
|
||||
return;
|
||||
}
|
||||
else if (c >= '3' && c <= '7')
|
||||
c -= ('3' - '\033');
|
||||
else if (c == '8')
|
||||
c = '\177';
|
||||
else if (c == '/')
|
||||
c = '_' & 0x1F;
|
||||
}
|
||||
|
||||
len = g_unichar_to_utf8 (c, buf);
|
||||
buf[len] = '\0';
|
||||
|
||||
event->string = g_locale_from_utf8 (buf, len,
|
||||
NULL, &bytes_written,
|
||||
NULL);
|
||||
if (event->string)
|
||||
event->length = bytes_written;
|
||||
}
|
||||
else if (event->keyval == GDK_KEY_Escape)
|
||||
{
|
||||
event->length = 1;
|
||||
event->string = g_strdup ("\033");
|
||||
}
|
||||
else if (event->keyval == GDK_KEY_Return ||
|
||||
event->keyval == GDK_KEY_KP_Enter)
|
||||
{
|
||||
event->length = 1;
|
||||
event->string = g_strdup ("\r");
|
||||
}
|
||||
|
||||
if (!event->string)
|
||||
{
|
||||
event->length = 0;
|
||||
event->string = g_strdup ("");
|
||||
}
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
get_keyboard_settings (GdkWaylandSeat *seat)
|
||||
{
|
||||
@@ -2124,15 +2209,17 @@ deliver_key_event (GdkWaylandSeat *seat,
|
||||
event->key.keyval = sym;
|
||||
event->key.is_modifier = _gdk_wayland_keymap_key_is_modifier (keymap, key);
|
||||
|
||||
translate_keyboard_string (&event->key);
|
||||
|
||||
_gdk_wayland_display_deliver_event (seat->display, event);
|
||||
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("keyboard %s event%s, code %d, sym %d, "
|
||||
"mods 0x%x",
|
||||
"string %s, mods 0x%x",
|
||||
(state ? "press" : "release"),
|
||||
(from_key_repeat ? " (repeat)" : ""),
|
||||
event->key.hardware_keycode, event->key.keyval,
|
||||
event->key.state));
|
||||
event->key.string, event->key.state));
|
||||
|
||||
if (!xkb_keymap_key_repeats (xkb_keymap, key))
|
||||
return;
|
||||
@@ -4010,7 +4097,7 @@ tablet_pad_group_handle_buttons (void *data,
|
||||
uint32_t *p;
|
||||
|
||||
GDK_DISPLAY_NOTE (seat->display, EVENTS,
|
||||
g_message ("tablet pad group handle buttons, pad group = %p, n_buttons = %" G_GSIZE_FORMAT,
|
||||
g_message ("tablet pad group handle buttons, pad group = %p, n_buttons = %ld",
|
||||
wp_tablet_pad_group, buttons->size));
|
||||
|
||||
wl_array_for_each (p, buttons)
|
||||
@@ -4444,12 +4531,6 @@ pointer_surface_update_scale (GdkDevice *device)
|
||||
gdk_wayland_device_update_surface_cursor (device);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_seat_update_cursor_scale (GdkWaylandSeat *seat)
|
||||
{
|
||||
pointer_surface_update_scale (seat->master_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_enter (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
@@ -4490,6 +4571,12 @@ static const struct wl_surface_listener pointer_surface_listener = {
|
||||
pointer_surface_leave
|
||||
};
|
||||
|
||||
static GdkSurface *
|
||||
create_foreign_dnd_surface (GdkDisplay *display)
|
||||
{
|
||||
return gdk_surface_new_popup (display, &(GdkRectangle) { 0, 0, 1, 1 });
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_pointer_data_finalize (GdkWaylandPointerData *pointer)
|
||||
{
|
||||
@@ -4519,11 +4606,11 @@ gdk_wayland_seat_finalize (GObject *object)
|
||||
gdk_wayland_pointer_data_finalize (&seat->pointer_info);
|
||||
/* FIXME: destroy data_device */
|
||||
g_clear_object (&seat->keyboard_settings);
|
||||
g_clear_object (&seat->drag);
|
||||
g_clear_object (&seat->drop);
|
||||
g_clear_object (&seat->drop_context);
|
||||
g_clear_object (&seat->clipboard);
|
||||
g_clear_object (&seat->primary_clipboard);
|
||||
g_hash_table_destroy (seat->touches);
|
||||
gdk_surface_destroy (seat->foreign_dnd_surface);
|
||||
zwp_tablet_seat_v2_destroy (seat->wp_tablet_seat);
|
||||
stop_key_repeat (seat);
|
||||
|
||||
@@ -4865,6 +4952,7 @@ _gdk_wayland_display_create_seat (GdkWaylandDisplay *display_wayland,
|
||||
seat->keymap = _gdk_wayland_keymap_new (display);
|
||||
seat->display = display;
|
||||
seat->touches = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_free);
|
||||
seat->foreign_dnd_surface = create_foreign_dnd_surface (display);
|
||||
seat->wl_seat = wl_seat;
|
||||
|
||||
wl_seat_add_listener (seat->wl_seat, &seat_listener, seat);
|
||||
@@ -5058,15 +5146,6 @@ gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_seat_set_drag (GdkSeat *seat,
|
||||
GdkDrag *drag)
|
||||
{
|
||||
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
|
||||
|
||||
g_set_object (&wayland_seat->drag, drag);
|
||||
}
|
||||
|
||||
struct wl_data_device *
|
||||
gdk_wayland_device_get_data_device (GdkDevice *gdk_device)
|
||||
{
|
||||
@@ -5110,6 +5189,14 @@ gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
|
||||
return GDK_WAYLAND_SEAT (seat)->wl_seat;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_device_get_drop_context (GdkDevice *device)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (device);
|
||||
|
||||
return GDK_WAYLAND_SEAT (seat)->drop_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_device_get_node_path:
|
||||
* @device: a #GdkDevice
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkmonitor-wayland.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
@@ -55,8 +54,6 @@
|
||||
|
||||
#include "wm-button-layout-translation.h"
|
||||
|
||||
#include "gdk/gdk-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:wayland_interaction
|
||||
* @Short_description: Wayland backend-specific functions
|
||||
@@ -669,6 +666,8 @@ _gdk_wayland_display_open (const gchar *display_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display_wayland->selection = gdk_wayland_selection_new ();
|
||||
|
||||
gdk_display_emit_opened (display);
|
||||
|
||||
return display;
|
||||
@@ -694,6 +693,12 @@ gdk_wayland_display_dispose (GObject *object)
|
||||
display_wayland->event_source = NULL;
|
||||
}
|
||||
|
||||
if (display_wayland->selection)
|
||||
{
|
||||
gdk_wayland_selection_free (display_wayland->selection);
|
||||
display_wayland->selection = NULL;
|
||||
}
|
||||
|
||||
g_list_free_full (display_wayland->async_roundtrips, (GDestroyNotify) wl_callback_destroy);
|
||||
|
||||
if (display_wayland->known_globals)
|
||||
@@ -812,9 +817,19 @@ gdk_wayland_display_make_default (GdkDisplay *display)
|
||||
g_free (display_wayland->startup_notification_id);
|
||||
display_wayland->startup_notification_id = NULL;
|
||||
|
||||
startup_id = gdk_get_startup_notification_id ();
|
||||
if (startup_id)
|
||||
display_wayland->startup_notification_id = g_strdup (startup_id);
|
||||
startup_id = g_getenv ("DESKTOP_STARTUP_ID");
|
||||
if (startup_id && *startup_id != '\0')
|
||||
{
|
||||
if (!g_utf8_validate (startup_id, -1, NULL))
|
||||
g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
|
||||
else
|
||||
display_wayland->startup_notification_id = g_strdup (startup_id);
|
||||
|
||||
/* Clear the environment variable so it won't be inherited by
|
||||
* child processes and confuse things.
|
||||
*/
|
||||
g_unsetenv ("DESKTOP_STARTUP_ID");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -850,21 +865,6 @@ gdk_wayland_display_get_next_serial (GdkDisplay *display)
|
||||
return ++serial;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_display_get_startup_notification_id:
|
||||
* @display: (type GdkX11Display): a #GdkDisplay
|
||||
*
|
||||
* Gets the startup notification ID for a Wayland display, or %NULL
|
||||
* if no ID has been defined.
|
||||
*
|
||||
* Returns: the startup notification ID for @display, or %NULL
|
||||
*/
|
||||
const gchar *
|
||||
gdk_wayland_display_get_startup_notification_id (GdkDisplay *display)
|
||||
{
|
||||
return GDK_WAYLAND_DISPLAY (display)->startup_notification_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_display_set_startup_notification_id:
|
||||
* @display: (type GdkWaylandDisplay): a #GdkDisplay
|
||||
@@ -1013,7 +1013,6 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class)
|
||||
display_class->supports_input_shapes = gdk_wayland_display_supports_input_shapes;
|
||||
display_class->get_app_launch_context = _gdk_wayland_display_get_app_launch_context;
|
||||
display_class->get_next_serial = gdk_wayland_display_get_next_serial;
|
||||
display_class->get_startup_notification_id = gdk_wayland_display_get_startup_notification_id;
|
||||
display_class->notify_startup_complete = gdk_wayland_display_notify_startup_complete;
|
||||
display_class->create_surface_impl = _gdk_wayland_display_create_surface_impl;
|
||||
display_class->get_keymap = _gdk_wayland_display_get_keymap;
|
||||
@@ -1219,9 +1218,6 @@ open_shared_memory (void)
|
||||
|
||||
if (force_shm_open)
|
||||
{
|
||||
#if defined (__FreeBSD__)
|
||||
ret = shm_open (SHM_ANON, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600);
|
||||
#else
|
||||
char name[NAME_MAX - 1] = "";
|
||||
|
||||
sprintf (name, "/gdk-wayland-%x", g_random_int ());
|
||||
@@ -1232,7 +1228,6 @@ open_shared_memory (void)
|
||||
shm_unlink (name);
|
||||
else if (errno == EEXIST)
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
while (ret < 0 && errno == EINTR);
|
||||
@@ -1361,6 +1356,15 @@ _gdk_wayland_is_shm_surface (cairo_surface_t *surface)
|
||||
return cairo_surface_get_user_data (surface, &gdk_wayland_shm_surface_cairo_key) != NULL;
|
||||
}
|
||||
|
||||
GdkWaylandSelection *
|
||||
gdk_wayland_display_get_selection (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
return display_wayland->selection;
|
||||
}
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSD_FONT_ANTIALIASING_MODE_NONE,
|
||||
@@ -1884,20 +1888,9 @@ transform_to_string (int transform)
|
||||
static void
|
||||
update_scale (GdkDisplay *display)
|
||||
{
|
||||
GList *seats;
|
||||
GList *l;
|
||||
|
||||
g_list_foreach (gdk_wayland_display_get_toplevel_surfaces (display),
|
||||
(GFunc)gdk_wayland_surface_update_scale,
|
||||
NULL);
|
||||
seats = gdk_display_list_seats (display);
|
||||
for (l = seats; l; l = l->next)
|
||||
{
|
||||
GdkSeat *seat = l->data;
|
||||
|
||||
gdk_wayland_seat_update_cursor_scale (GDK_WAYLAND_SEAT (seat));
|
||||
}
|
||||
g_list_free (seats);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -139,6 +139,8 @@ struct _GdkWaylandDisplay
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
GdkWaylandSelection *selection;
|
||||
|
||||
GPtrArray *monitors;
|
||||
|
||||
gint64 last_bell_time_ms;
|
||||
|
||||
589
gdk/wayland/gdkdnd-wayland.c
Normal file
589
gdk/wayland/gdkdnd-wayland.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DRAG_CONTEXT (gdk_wayland_drag_context_get_type ())
|
||||
#define GDK_WAYLAND_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContext))
|
||||
#define GDK_WAYLAND_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContextClass))
|
||||
#define GDK_IS_WAYLAND_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DRAG_CONTEXT))
|
||||
#define GDK_IS_WAYLAND_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DRAG_CONTEXT))
|
||||
#define GDK_WAYLAND_DRAG_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContextClass))
|
||||
|
||||
typedef struct _GdkWaylandDragContext GdkWaylandDragContext;
|
||||
typedef struct _GdkWaylandDragContextClass GdkWaylandDragContextClass;
|
||||
|
||||
struct _GdkWaylandDragContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
GdkSurface *dnd_surface;
|
||||
struct wl_surface *dnd_wl_surface;
|
||||
struct wl_data_source *data_source;
|
||||
struct wl_data_offer *offer;
|
||||
GdkDragAction selected_action;
|
||||
uint32_t serial;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
gint hot_x;
|
||||
gint hot_y;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDragContextClass
|
||||
{
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
|
||||
static GList *contexts;
|
||||
|
||||
GType gdk_wayland_drag_context_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDragContext, gdk_wayland_drag_context, GDK_TYPE_DRAG_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (object);
|
||||
GdkDragContext *context = GDK_DRAG_CONTEXT (object);
|
||||
GdkSurface *dnd_surface;
|
||||
|
||||
contexts = g_list_remove (contexts, context);
|
||||
|
||||
if (context->is_source)
|
||||
{
|
||||
gdk_drag_context_set_cursor (context, NULL);
|
||||
}
|
||||
|
||||
g_clear_pointer (&wayland_context->data_source, (GDestroyNotify) wl_data_source_destroy);
|
||||
g_clear_pointer (&wayland_context->offer, (GDestroyNotify) wl_data_offer_destroy);
|
||||
|
||||
dnd_surface = wayland_context->dnd_surface;
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_drag_context_parent_class)->finalize (object);
|
||||
|
||||
if (dnd_surface)
|
||||
gdk_surface_destroy (dnd_surface);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_emit_event (GdkDragContext *context,
|
||||
GdkEventType type,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkEvent *event;
|
||||
|
||||
switch ((guint) type)
|
||||
{
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->is_source)
|
||||
surface = gdk_drag_context_get_source_surface (context);
|
||||
else
|
||||
surface = gdk_drag_context_get_dest_surface (context);
|
||||
|
||||
event = gdk_event_new (type);
|
||||
event->any.surface = g_object_ref (surface);
|
||||
event->dnd.context = g_object_ref (context);
|
||||
event->dnd.time = time_;
|
||||
event->dnd.x_root = GDK_WAYLAND_DRAG_CONTEXT (context)->x;
|
||||
event->dnd.y_root = GDK_WAYLAND_DRAG_CONTEXT (context)->y;
|
||||
gdk_event_set_device (event, gdk_drag_context_get_device (context));
|
||||
|
||||
gdk_display_put_event (gdk_surface_get_display (surface), event);
|
||||
g_object_unref (event);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
gdk_to_wl_actions (GdkDragAction action)
|
||||
{
|
||||
uint32_t dnd_actions = 0;
|
||||
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE))
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
if (action & GDK_ACTION_ASK)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
return dnd_actions;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drag_context_set_action (GdkDragContext *context,
|
||||
GdkDragAction action)
|
||||
{
|
||||
context->suggested_action = context->action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drag_abort (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drag_drop (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
}
|
||||
|
||||
/* Destination side */
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_context_set_status (GdkDragContext *context,
|
||||
gboolean accepted)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
|
||||
if (!context->dest_surface)
|
||||
return;
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
if (mimetypes[i] != g_intern_static_string ("DELETE"))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < n_mimetypes)
|
||||
{
|
||||
wl_data_offer_accept (context_wayland->offer, context_wayland->serial, mimetypes[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wl_data_offer_accept (context_wayland->offer, context_wayland->serial, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_commit_status (GdkDragContext *context)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display;
|
||||
uint32_t dnd_actions, all_actions = 0;
|
||||
|
||||
display = gdk_device_get_display (gdk_drag_context_get_device (context));
|
||||
|
||||
dnd_actions = gdk_to_wl_actions (wayland_context->selected_action);
|
||||
|
||||
if (dnd_actions != 0)
|
||||
all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
|
||||
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
|
||||
wl_data_offer_set_actions (wayland_context->offer, all_actions, dnd_actions);
|
||||
|
||||
gdk_wayland_drop_context_set_status (context, wayland_context->selected_action != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context;
|
||||
|
||||
wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
wayland_context->selected_action = action;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display = gdk_device_get_display (gdk_drag_context_get_device (context));
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
if (success && wayland_context->selected_action &&
|
||||
wayland_context->selected_action != GDK_ACTION_ASK)
|
||||
{
|
||||
gdk_wayland_drag_context_commit_status (context);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_OFFER_FINISH_SINCE_VERSION)
|
||||
wl_data_offer_finish (wayland_context->offer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_read_async (GdkDragContext *context,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
GdkDisplay *display;
|
||||
GInputStream *stream;
|
||||
const char *mime_type;
|
||||
int pipe_fd[2];
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
display = gdk_drag_context_get_display (context),
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_drag_context_read_async);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
|
||||
g_message ("%p: read for %s", context, s);
|
||||
g_free (s); );
|
||||
mime_type = gdk_content_formats_match_mime_type (formats,
|
||||
gdk_drag_context_get_formats (context));
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
|
||||
if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_data_offer_receive (wayland_context->offer, mime_type, pipe_fd[1]);
|
||||
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
|
||||
close (pipe_fd[1]);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_wayland_drag_context_read_finish (GdkDragContext *context,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (context)), NULL);
|
||||
task = G_TASK (result);
|
||||
g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_drag_context_read_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (task);
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_init (GdkWaylandDragContext *context_wayland)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = GDK_DRAG_CONTEXT (context_wayland);
|
||||
contexts = g_list_prepend (contexts, context);
|
||||
|
||||
context->action = GDK_ACTION_COPY;
|
||||
context->suggested_action = GDK_ACTION_COPY;
|
||||
context->actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
gdk_wayland_drag_context_get_drag_surface (GdkDragContext *context)
|
||||
{
|
||||
return GDK_WAYLAND_DRAG_CONTEXT (context)->dnd_surface;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_set_hotspot (GdkDragContext *context,
|
||||
gint hot_x,
|
||||
gint hot_y)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
gint prev_hot_x = context_wayland->hot_x;
|
||||
gint prev_hot_y = context_wayland->hot_y;
|
||||
const GdkRectangle damage_rect = { .width = 1, .height = 1 };
|
||||
|
||||
context_wayland->hot_x = hot_x;
|
||||
context_wayland->hot_y = hot_y;
|
||||
|
||||
if (prev_hot_x == hot_x && prev_hot_y == hot_y)
|
||||
return;
|
||||
|
||||
_gdk_wayland_surface_offset_next_wl_buffer (context_wayland->dnd_surface,
|
||||
-hot_x, -hot_y);
|
||||
gdk_surface_invalidate_rect (context_wayland->dnd_surface, &damage_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_set_cursor (GdkDragContext *context,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
GdkDevice *device = gdk_drag_context_get_device (context);
|
||||
|
||||
gdk_wayland_seat_set_global_cursor (gdk_device_get_seat (device), cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_action_changed (GdkDragContext *context,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkCursor *cursor;
|
||||
|
||||
cursor = gdk_drag_get_cursor (context, action);
|
||||
gdk_drag_context_set_cursor (context, cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drop_performed (GdkDragContext *context,
|
||||
guint32 time_)
|
||||
{
|
||||
gdk_drag_context_set_cursor (context, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_cancel (GdkDragContext *context,
|
||||
GdkDragCancelReason reason)
|
||||
{
|
||||
gdk_drag_context_set_cursor (context, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_drop_done (GdkDragContext *context,
|
||||
gboolean success)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (context_wayland->dnd_surface)
|
||||
gdk_surface_hide (context_wayland->dnd_surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_wayland_drag_context_finalize;
|
||||
|
||||
context_class->drag_status = gdk_wayland_drag_context_drag_status;
|
||||
context_class->drag_abort = gdk_wayland_drag_context_drag_abort;
|
||||
context_class->drag_drop = gdk_wayland_drag_context_drag_drop;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->drop_finish = gdk_wayland_drag_context_drop_finish;
|
||||
context_class->read_async = gdk_wayland_drag_context_read_async;
|
||||
context_class->read_finish = gdk_wayland_drag_context_read_finish;
|
||||
context_class->get_drag_surface = gdk_wayland_drag_context_get_drag_surface;
|
||||
context_class->set_hotspot = gdk_wayland_drag_context_set_hotspot;
|
||||
context_class->drop_done = gdk_wayland_drag_context_drop_done;
|
||||
context_class->set_cursor = gdk_wayland_drag_context_set_cursor;
|
||||
context_class->action_changed = gdk_wayland_drag_context_action_changed;
|
||||
context_class->drop_performed = gdk_wayland_drag_context_drop_performed;
|
||||
context_class->cancel = gdk_wayland_drag_context_cancel;
|
||||
context_class->commit_drag_status = gdk_wayland_drag_context_commit_status;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_surface_register_dnd (GdkSurface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
create_dnd_surface (GdkDisplay *display)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
|
||||
surface = gdk_surface_new_popup (display, &(GdkRectangle) { 0, 0, 100, 100 });
|
||||
|
||||
gdk_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_DND);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
GdkDragContext *context;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
|
||||
|
||||
context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
"content", content,
|
||||
NULL);
|
||||
context = GDK_DRAG_CONTEXT (context_wayland);
|
||||
context->source_surface = g_object_ref (surface);
|
||||
context->is_source = TRUE;
|
||||
|
||||
context_wayland->dnd_surface = create_dnd_surface (gdk_surface_get_display (surface));
|
||||
context_wayland->dnd_wl_surface = gdk_wayland_surface_get_wl_surface (context_wayland->dnd_surface);
|
||||
context_wayland->data_source =
|
||||
gdk_wayland_selection_get_data_source (surface);
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_context_get_formats (context), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
wl_data_source_offer (context_wayland->data_source, mimetypes[i]);
|
||||
}
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
wl_data_source_set_actions (context_wayland->data_source,
|
||||
gdk_to_wl_actions (actions));
|
||||
}
|
||||
|
||||
wl_data_device_start_drag (gdk_wayland_device_get_data_device (device),
|
||||
context_wayland->data_source,
|
||||
gdk_wayland_surface_get_wl_surface (surface),
|
||||
context_wayland->dnd_wl_surface,
|
||||
_gdk_wayland_display_get_serial (display_wayland));
|
||||
|
||||
gdk_seat_ungrab (gdk_device_get_seat (device));
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
GdkDragContext *
|
||||
_gdk_wayland_drop_context_new (GdkDevice *device,
|
||||
GdkContentFormats *formats,
|
||||
struct wl_data_offer *offer)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
GdkDragContext *context;
|
||||
|
||||
context_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT,
|
||||
"device", device,
|
||||
"formats", formats,
|
||||
NULL);
|
||||
context = GDK_DRAG_CONTEXT (context_wayland);
|
||||
context->is_source = FALSE;
|
||||
context_wayland->offer = offer;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_coords (GdkDragContext *context,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GdkWaylandDragContext *context_wayland;
|
||||
|
||||
context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||
context_wayland->x = x;
|
||||
context_wayland->y = y;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
|
||||
GdkSurface *surface)
|
||||
{
|
||||
if (context->source_surface)
|
||||
g_object_unref (context->source_surface);
|
||||
|
||||
context->source_surface = surface ? g_object_ref (surface) : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_drag_context_set_dest_surface (GdkDragContext *context,
|
||||
GdkSurface *dest_surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
if (context->dest_surface)
|
||||
g_object_unref (context->dest_surface);
|
||||
|
||||
context->dest_surface = dest_surface ? g_object_ref (dest_surface) : NULL;
|
||||
GDK_WAYLAND_DRAG_CONTEXT (context)->serial = serial;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = contexts; l; l = l->next)
|
||||
{
|
||||
GdkWaylandDragContext *wayland_context = l->data;
|
||||
|
||||
if (wayland_context->data_source == source)
|
||||
return l->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_wayland_drag_context_lookup_by_source_surface (GdkSurface *surface)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = contexts; l; l = l->next)
|
||||
{
|
||||
if (surface == gdk_drag_context_get_source_surface (l->data))
|
||||
return l->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_data_source *
|
||||
gdk_wayland_drag_context_get_data_source (GdkDragContext *context)
|
||||
{
|
||||
return GDK_WAYLAND_DRAG_CONTEXT (context)->data_source;
|
||||
}
|
||||
@@ -1,409 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdragprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DRAG (gdk_wayland_drag_get_type ())
|
||||
#define GDK_WAYLAND_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DRAG, GdkWaylandDrag))
|
||||
#define GDK_WAYLAND_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DRAG, GdkWaylandDragClass))
|
||||
#define GDK_IS_WAYLAND_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DRAG))
|
||||
#define GDK_IS_WAYLAND_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DRAG))
|
||||
#define GDK_WAYLAND_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DRAG, GdkWaylandDragClass))
|
||||
|
||||
typedef struct _GdkWaylandDrag GdkWaylandDrag;
|
||||
typedef struct _GdkWaylandDragClass GdkWaylandDragClass;
|
||||
|
||||
struct _GdkWaylandDrag
|
||||
{
|
||||
GdkDrag drag;
|
||||
GdkSurface *dnd_surface;
|
||||
struct wl_surface *dnd_wl_surface;
|
||||
struct wl_data_source *data_source;
|
||||
struct wl_data_offer *offer;
|
||||
uint32_t serial;
|
||||
gint hot_x;
|
||||
gint hot_y;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDragClass
|
||||
{
|
||||
GdkDragClass parent_class;
|
||||
};
|
||||
|
||||
static GList *drags;
|
||||
|
||||
GType gdk_wayland_drag_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDrag, gdk_wayland_drag, GDK_TYPE_DRAG)
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandDrag *wayland_drag = GDK_WAYLAND_DRAG (object);
|
||||
GdkDrag *drag = GDK_DRAG (object);
|
||||
GdkSurface *dnd_surface;
|
||||
|
||||
drags = g_list_remove (drags, drag);
|
||||
|
||||
gdk_drag_set_cursor (drag, NULL);
|
||||
|
||||
g_clear_pointer (&wayland_drag->data_source, wl_data_source_destroy);
|
||||
g_clear_pointer (&wayland_drag->offer, wl_data_offer_destroy);
|
||||
|
||||
dnd_surface = wayland_drag->dnd_surface;
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_drag_parent_class)->finalize (object);
|
||||
|
||||
if (dnd_surface)
|
||||
gdk_surface_destroy (dnd_surface);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
gdk_to_wl_actions (GdkDragAction action)
|
||||
{
|
||||
uint32_t dnd_actions = 0;
|
||||
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK))
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
if (action & GDK_ACTION_ASK)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
return dnd_actions;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_init (GdkWaylandDrag *drag_wayland)
|
||||
{
|
||||
GdkDrag *drag;
|
||||
|
||||
drag = GDK_DRAG (drag_wayland);
|
||||
drags = g_list_prepend (drags, drag);
|
||||
|
||||
gdk_drag_set_selected_action (drag, GDK_ACTION_COPY);
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
gdk_wayland_drag_get_drag_surface (GdkDrag *drag)
|
||||
{
|
||||
return GDK_WAYLAND_DRAG (drag)->dnd_surface;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_set_hotspot (GdkDrag *drag,
|
||||
gint hot_x,
|
||||
gint hot_y)
|
||||
{
|
||||
GdkWaylandDrag *drag_wayland = GDK_WAYLAND_DRAG (drag);
|
||||
gint prev_hot_x = drag_wayland->hot_x;
|
||||
gint prev_hot_y = drag_wayland->hot_y;
|
||||
const GdkRectangle damage_rect = { .width = 1, .height = 1 };
|
||||
|
||||
drag_wayland->hot_x = hot_x;
|
||||
drag_wayland->hot_y = hot_y;
|
||||
|
||||
if (prev_hot_x == hot_x && prev_hot_y == hot_y)
|
||||
return;
|
||||
|
||||
_gdk_wayland_surface_offset_next_wl_buffer (drag_wayland->dnd_surface,
|
||||
-hot_x, -hot_y);
|
||||
gdk_surface_invalidate_rect (drag_wayland->dnd_surface, &damage_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_set_cursor (GdkDrag *drag,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
GdkDevice *device = gdk_drag_get_device (drag);
|
||||
|
||||
if (device != NULL)
|
||||
gdk_wayland_seat_set_global_cursor (gdk_device_get_seat (device), cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_drop_performed (GdkDrag *drag,
|
||||
guint32 time_)
|
||||
{
|
||||
gdk_drag_set_cursor (drag, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_cancel (GdkDrag *drag,
|
||||
GdkDragCancelReason reason)
|
||||
{
|
||||
gdk_drag_set_cursor (drag, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_drop_done (GdkDrag *drag,
|
||||
gboolean success)
|
||||
{
|
||||
GdkWaylandDrag *drag_wayland = GDK_WAYLAND_DRAG (drag);
|
||||
GdkDevice *device = gdk_drag_get_device (drag);
|
||||
|
||||
gdk_wayland_seat_set_drag (gdk_device_get_seat (device), drag);
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (drag_wayland->dnd_surface)
|
||||
gdk_surface_hide (drag_wayland->dnd_surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_class_init (GdkWaylandDragClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkDragClass *drag_class = GDK_DRAG_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_wayland_drag_finalize;
|
||||
|
||||
drag_class->get_drag_surface = gdk_wayland_drag_get_drag_surface;
|
||||
drag_class->set_hotspot = gdk_wayland_drag_set_hotspot;
|
||||
drag_class->drop_done = gdk_wayland_drag_drop_done;
|
||||
drag_class->set_cursor = gdk_wayland_drag_set_cursor;
|
||||
drag_class->drop_performed = gdk_wayland_drag_drop_performed;
|
||||
drag_class->cancel = gdk_wayland_drag_cancel;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_surface_register_dnd (GdkSurface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
create_dnd_surface (GdkDisplay *display)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
|
||||
surface = gdk_surface_new_popup (display, &(GdkRectangle) { 0, 0, 100, 100 });
|
||||
|
||||
gdk_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_DND);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static inline GdkDragAction
|
||||
_wl_to_gdk_actions (uint32_t dnd_actions)
|
||||
{
|
||||
GdkDragAction actions = 0;
|
||||
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
actions |= GDK_ACTION_COPY;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
actions |= GDK_ACTION_MOVE;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
actions |= GDK_ACTION_ASK;
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_target (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("data source target, source = %p, mime_type = %s",
|
||||
source, mime_type));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_write_done (GObject *drag,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_drag_write_finish (GDK_DRAG (drag), result, &error))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (gdk_drag_get_display (GDK_DRAG (drag)), DND, g_message ("%p: failed to write stream: %s", drag, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_send (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
GOutputStream *stream;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_get_display (drag), DND, g_message ("%p: data source send request for %s on fd %d\n",
|
||||
source, mime_type, fd));
|
||||
|
||||
//mime_type = gdk_intern_mime_type (mime_type);
|
||||
mime_type = g_intern_string (mime_type);
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
|
||||
gdk_drag_write_async (drag,
|
||||
mime_type,
|
||||
stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_wayland_drag_write_done,
|
||||
drag);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_cancelled (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_get_display (drag), EVENTS,
|
||||
g_message ("data source cancelled, source = %p", source));
|
||||
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_drop_performed (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
|
||||
g_signal_emit_by_name (drag, "drop-performed");
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_finished (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_action (void *data,
|
||||
struct wl_data_source *source,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkDrag *drag = data;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_get_display (drag), EVENTS,
|
||||
g_message ("data source action, source = %p action=%x",
|
||||
source, action));
|
||||
|
||||
gdk_drag_set_selected_action (drag, _wl_to_gdk_actions (action));
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener = {
|
||||
data_source_target,
|
||||
data_source_send,
|
||||
data_source_cancelled,
|
||||
data_source_dnd_drop_performed,
|
||||
data_source_dnd_finished,
|
||||
data_source_action,
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_create_data_source (GdkDrag *drag)
|
||||
{
|
||||
GdkWaylandDrag *drag_wayland = GDK_WAYLAND_DRAG (drag);
|
||||
GdkDisplay *display = gdk_drag_get_display (drag);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
drag_wayland->data_source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (drag_wayland->data_source,
|
||||
&data_source_listener,
|
||||
drag);
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drag_get_formats (drag), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
wl_data_source_offer (drag_wayland->data_source, mimetypes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GdkDrag *
|
||||
_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkWaylandDrag *drag_wayland;
|
||||
GdkDrag *drag;
|
||||
GdkSeat *seat;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
GdkCursor *cursor;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
|
||||
seat = gdk_device_get_seat (device);
|
||||
|
||||
drag_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG,
|
||||
"surface", surface,
|
||||
"device", device,
|
||||
"content", content,
|
||||
"actions", actions,
|
||||
NULL);
|
||||
|
||||
drag = GDK_DRAG (drag_wayland);
|
||||
|
||||
drag_wayland->dnd_surface = create_dnd_surface (gdk_surface_get_display (surface));
|
||||
drag_wayland->dnd_wl_surface = gdk_wayland_surface_get_wl_surface (drag_wayland->dnd_surface);
|
||||
|
||||
gdk_wayland_drag_create_data_source (drag);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
wl_data_source_set_actions (drag_wayland->data_source,
|
||||
gdk_to_wl_actions (actions));
|
||||
}
|
||||
|
||||
gdk_wayland_seat_set_drag (seat, drag);
|
||||
|
||||
wl_data_device_start_drag (gdk_wayland_device_get_data_device (device),
|
||||
drag_wayland->data_source,
|
||||
gdk_wayland_surface_get_wl_surface (surface),
|
||||
drag_wayland->dnd_wl_surface,
|
||||
_gdk_wayland_display_get_serial (display_wayland));
|
||||
|
||||
cursor = gdk_drag_get_cursor (drag, gdk_drag_get_selected_action (drag));
|
||||
gdk_drag_set_cursor (drag, cursor);
|
||||
|
||||
gdk_seat_ungrab (seat);
|
||||
|
||||
return drag;
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdropprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DROP (gdk_wayland_drop_get_type ())
|
||||
#define GDK_WAYLAND_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DROP, GdkWaylandDrop))
|
||||
#define GDK_WAYLAND_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
|
||||
#define GDK_IS_WAYLAND_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DROP))
|
||||
#define GDK_IS_WAYLAND_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DROP))
|
||||
#define GDK_WAYLAND_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DROP, GdkWaylandDropClass))
|
||||
|
||||
typedef struct _GdkWaylandDrop GdkWaylandDrop;
|
||||
typedef struct _GdkWaylandDropClass GdkWaylandDropClass;
|
||||
|
||||
struct _GdkWaylandDrop
|
||||
{
|
||||
GdkDrop drop;
|
||||
|
||||
struct wl_data_offer *offer;
|
||||
uint32_t source_actions;
|
||||
uint32_t action;
|
||||
GdkDragAction selected_action;
|
||||
uint32_t serial;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDropClass
|
||||
{
|
||||
GdkDropClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_wayland_drop_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandDrop, gdk_wayland_drop, GDK_TYPE_DROP)
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_finalize (GObject *object)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (object);
|
||||
|
||||
g_clear_pointer (&wayland_drop->offer, wl_data_offer_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_drop_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
gdk_to_wl_actions (GdkDragAction action)
|
||||
{
|
||||
uint32_t dnd_actions = 0;
|
||||
|
||||
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK))
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (action & GDK_ACTION_MOVE)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
if (action & GDK_ACTION_ASK)
|
||||
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
|
||||
return dnd_actions;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_drop_set_status (GdkWaylandDrop *drop_wayland,
|
||||
gboolean accepted)
|
||||
{
|
||||
if (accepted)
|
||||
{
|
||||
const char *const *mimetypes;
|
||||
gsize i, n_mimetypes;
|
||||
|
||||
mimetypes = gdk_content_formats_get_mime_types (gdk_drop_get_formats (GDK_DROP (drop_wayland)), &n_mimetypes);
|
||||
for (i = 0; i < n_mimetypes; i++)
|
||||
{
|
||||
if (mimetypes[i] != g_intern_static_string ("DELETE"))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < n_mimetypes)
|
||||
{
|
||||
wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, mimetypes[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wl_data_offer_accept (drop_wayland->offer, drop_wayland->serial, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
uint32_t dnd_actions;
|
||||
|
||||
display = gdk_drop_get_display (GDK_DROP (wayland_drop));
|
||||
|
||||
dnd_actions = gdk_to_wl_actions (wayland_drop->selected_action);
|
||||
|
||||
if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >=
|
||||
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
if (gdk_drag_action_is_unique (wayland_drop->selected_action))
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_drop->offer, dnd_actions, dnd_actions);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_data_offer_set_actions (wayland_drop->offer,
|
||||
dnd_actions | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_wayland_drop_drop_set_status (wayland_drop, wayland_drop->selected_action != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_status (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop;
|
||||
|
||||
wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
wayland_drop->selected_action = action;
|
||||
|
||||
gdk_wayland_drop_commit_status (wayland_drop);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_finish (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
GdkDisplay *display = gdk_drop_get_display (drop);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
wayland_drop->selected_action = action;
|
||||
|
||||
if (action)
|
||||
{
|
||||
gdk_wayland_drop_commit_status (wayland_drop);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_OFFER_FINISH_SINCE_VERSION)
|
||||
wl_data_offer_finish (wayland_drop->offer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_read_async (GdkDrop *drop,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
GdkDisplay *display;
|
||||
GInputStream *stream;
|
||||
const char *mime_type;
|
||||
int pipe_fd[2];
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
display = gdk_drop_get_display (drop),
|
||||
task = g_task_new (drop, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_wayland_drop_read_async);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
|
||||
g_message ("%p: read for %s", drop, s);
|
||||
g_free (s); );
|
||||
mime_type = gdk_content_formats_match_mime_type (formats,
|
||||
gdk_drop_get_formats (drop));
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("No compatible transfer format found"));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, (gpointer) mime_type, NULL);
|
||||
|
||||
if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_data_offer_receive (wayland_drop->offer, mime_type, pipe_fd[1]);
|
||||
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
|
||||
close (pipe_fd[1]);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_wayland_drop_read_finish (GdkDrop *drop,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (drop)), NULL);
|
||||
task = G_TASK (result);
|
||||
g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_drop_read_async, NULL);
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_task_get_task_data (task);
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_class_init (GdkWaylandDropClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_wayland_drop_finalize;
|
||||
|
||||
drop_class->status = gdk_wayland_drop_status;
|
||||
drop_class->finish = gdk_wayland_drop_finish;
|
||||
drop_class->read_async = gdk_wayland_drop_read_async;
|
||||
drop_class->read_finish = gdk_wayland_drop_read_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_init (GdkWaylandDrop *drop)
|
||||
{
|
||||
}
|
||||
|
||||
GdkDrop *
|
||||
gdk_wayland_drop_new (GdkDevice *device,
|
||||
GdkDrag *drag,
|
||||
GdkContentFormats *formats,
|
||||
GdkSurface *surface,
|
||||
struct wl_data_offer *offer,
|
||||
uint32_t serial)
|
||||
|
||||
{
|
||||
GdkWaylandDrop *drop;
|
||||
|
||||
drop = g_object_new (GDK_TYPE_WAYLAND_DROP,
|
||||
"device", device,
|
||||
"drag", drag,
|
||||
"formats", formats,
|
||||
"surface", surface,
|
||||
NULL);
|
||||
drop->offer = offer;
|
||||
drop->serial = serial;
|
||||
|
||||
return GDK_DROP (drop);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drop_update_actions (GdkWaylandDrop *drop)
|
||||
{
|
||||
GdkDragAction gdk_actions = 0;
|
||||
uint32_t wl_actions;
|
||||
|
||||
if (drop->action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
wl_actions = drop->source_actions;
|
||||
else
|
||||
wl_actions = drop->action;
|
||||
|
||||
if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
gdk_actions |= GDK_ACTION_COPY;
|
||||
if (wl_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
gdk_actions |= GDK_ACTION_MOVE;
|
||||
|
||||
gdk_drop_set_actions (GDK_DROP (drop), gdk_actions);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drop_set_source_actions (GdkDrop *drop,
|
||||
uint32_t source_actions)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
|
||||
wayland_drop->source_actions = source_actions;
|
||||
|
||||
gdk_wayland_drop_update_actions (wayland_drop);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_drop_set_action (GdkDrop *drop,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
|
||||
|
||||
wayland_drop->action = action;
|
||||
|
||||
gdk_wayland_drop_update_actions (wayland_drop);
|
||||
}
|
||||
|
||||
@@ -62,20 +62,20 @@ gdk_wayland_primary_discard_pending (GdkWaylandPrimary *cb)
|
||||
gdk_content_formats_unref (ignore);
|
||||
cb->pending_builder = NULL;
|
||||
}
|
||||
g_clear_pointer (&cb->pending, gtk_primary_selection_offer_destroy);
|
||||
g_clear_pointer (&cb->pending, (GDestroyNotify) gtk_primary_selection_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_discard_offer (GdkWaylandPrimary *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->offer_formats, gdk_content_formats_unref);
|
||||
g_clear_pointer (&cb->offer, gtk_primary_selection_offer_destroy);
|
||||
g_clear_pointer (&cb->offer, (GDestroyNotify) gtk_primary_selection_offer_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_primary_discard_source (GdkWaylandPrimary *cb)
|
||||
{
|
||||
g_clear_pointer (&cb->source, gtk_primary_selection_source_destroy);
|
||||
g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -95,7 +95,7 @@ void gdk_wayland_surface_attach_image (GdkSurface
|
||||
const cairo_region_t *damage);
|
||||
|
||||
void _gdk_wayland_surface_register_dnd (GdkSurface *surface);
|
||||
GdkDrag *_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDragContext *_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
@@ -104,21 +104,33 @@ GdkDrag *_gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
void _gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *surface,
|
||||
int x,
|
||||
int y);
|
||||
GdkDrop * gdk_wayland_drop_new (GdkDevice *device,
|
||||
GdkDrag *drag,
|
||||
GdkContentFormats *formats,
|
||||
GdkSurface *surface,
|
||||
struct wl_data_offer *offer,
|
||||
uint32_t serial);
|
||||
void gdk_wayland_drop_set_source_actions (GdkDrop *drop,
|
||||
uint32_t source_actions);
|
||||
void gdk_wayland_drop_set_action (GdkDrop *drop,
|
||||
uint32_t action);
|
||||
GdkDragContext * _gdk_wayland_drop_context_new (GdkDevice *device,
|
||||
GdkContentFormats *formats,
|
||||
struct wl_data_offer *offer);
|
||||
void _gdk_wayland_drag_context_set_source_surface (GdkDragContext *context,
|
||||
GdkSurface *surface);
|
||||
void _gdk_wayland_drag_context_set_dest_surface (GdkDragContext *context,
|
||||
GdkSurface *dest_surface,
|
||||
uint32_t serial);
|
||||
void _gdk_wayland_drag_context_emit_event (GdkDragContext *context,
|
||||
GdkEventType type,
|
||||
guint32 time_);
|
||||
void _gdk_wayland_drag_context_set_coords (GdkDragContext *context,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
void _gdk_wayland_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkSurfaceAttr *attributes);
|
||||
void gdk_wayland_drag_context_set_action (GdkDragContext *context,
|
||||
GdkDragAction action);
|
||||
|
||||
GdkDragContext * gdk_wayland_drag_context_lookup_by_data_source (struct wl_data_source *source);
|
||||
GdkDragContext * gdk_wayland_drag_context_lookup_by_source_surface (GdkSurface *surface);
|
||||
struct wl_data_source * gdk_wayland_drag_context_get_data_source (GdkDragContext *context);
|
||||
|
||||
void _gdk_wayland_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes);
|
||||
|
||||
gint _gdk_wayland_display_text_property_to_utf8_list (GdkDisplay *display,
|
||||
GdkAtom encoding,
|
||||
@@ -144,7 +156,7 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
|
||||
void gdk_wayland_device_set_selection (GdkDevice *gdk_device,
|
||||
struct wl_data_source *source);
|
||||
|
||||
GdkDrag* gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
|
||||
GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
|
||||
|
||||
void gdk_wayland_device_unset_touch_grab (GdkDevice *device,
|
||||
GdkEventSequence *sequence);
|
||||
@@ -180,6 +192,14 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
|
||||
struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
|
||||
gboolean _gdk_wayland_is_shm_surface (cairo_surface_t *surface);
|
||||
|
||||
GdkWaylandSelection * gdk_wayland_display_get_selection (GdkDisplay *display);
|
||||
GdkWaylandSelection * gdk_wayland_selection_new (void);
|
||||
void gdk_wayland_selection_free (GdkWaylandSelection *selection);
|
||||
|
||||
|
||||
struct wl_data_source * gdk_wayland_selection_get_data_source (GdkSurface *owner);
|
||||
void gdk_wayland_selection_unset_data_source (GdkDisplay *display);
|
||||
|
||||
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config);
|
||||
EGLSurface gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
|
||||
@@ -189,8 +209,6 @@ struct gtk_surface1 * gdk_wayland_surface_get_gtk_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
|
||||
GdkCursor *cursor);
|
||||
void gdk_wayland_seat_set_drag (GdkSeat *seat,
|
||||
GdkDrag *drag);
|
||||
|
||||
struct wl_output *gdk_wayland_surface_get_wl_output (GdkSurface *surface);
|
||||
|
||||
|
||||
@@ -41,6 +41,4 @@ struct _GdkWaylandSeatClass
|
||||
|
||||
GType gdk_wayland_seat_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gdk_wayland_seat_update_cursor_scale (GdkWaylandSeat *seat);
|
||||
|
||||
#endif /* __GDK_WAYLAND_SEAT_H__ */
|
||||
|
||||
@@ -28,10 +28,215 @@
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkcontentformatsprivate.h"
|
||||
#include "gdkdndprivate.h"
|
||||
#include "gdkproperty.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _GdkWaylandSelection
|
||||
{
|
||||
struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */
|
||||
};
|
||||
|
||||
GdkWaylandSelection *
|
||||
gdk_wayland_selection_new (void)
|
||||
{
|
||||
GdkWaylandSelection *selection;
|
||||
|
||||
selection = g_new0 (GdkWaylandSelection, 1);
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_selection_free (GdkWaylandSelection *selection)
|
||||
{
|
||||
if (selection->dnd_source)
|
||||
wl_data_source_destroy (selection->dnd_source);
|
||||
|
||||
g_free (selection);
|
||||
}
|
||||
|
||||
static inline GdkDragAction
|
||||
_wl_to_gdk_actions (uint32_t dnd_actions)
|
||||
{
|
||||
GdkDragAction actions = 0;
|
||||
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
actions |= GDK_ACTION_COPY;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
actions |= GDK_ACTION_MOVE;
|
||||
if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
actions |= GDK_ACTION_ASK;
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_target (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("data source target, source = %p, mime_type = %s",
|
||||
source, mime_type));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_context_write_done (GObject *context,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_drag_context_write_finish (GDK_DRAG_CONTEXT (context), result, &error))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (GDK_DRAG_CONTEXT (context)), DND, g_message ("%p: failed to write stream: %s", context, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_send (void *data,
|
||||
struct wl_data_source *source,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
GOutputStream *stream;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), DND, g_message ("%p: data source send request for %s on fd %d\n",
|
||||
source, mime_type, fd));
|
||||
|
||||
//mime_type = gdk_intern_mime_type (mime_type);
|
||||
mime_type = g_intern_string (mime_type);
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
|
||||
gdk_drag_context_write_async (context,
|
||||
mime_type,
|
||||
stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_wayland_drag_context_write_done,
|
||||
context);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_cancelled (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = data;
|
||||
GdkDragContext *context;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
|
||||
GDK_DISPLAY_NOTE (display, EVENTS,
|
||||
g_message ("data source cancelled, source = %p", source));
|
||||
|
||||
if (source != wayland_selection->dnd_source)
|
||||
return;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (context)
|
||||
gdk_drag_context_cancel (context, GDK_DRAG_CANCEL_ERROR);
|
||||
|
||||
gdk_wayland_selection_unset_data_source (display);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_drop_performed (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (context, "drop-performed", GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_dnd_finished (void *data,
|
||||
struct wl_data_source *source)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (context, "dnd-finished");
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_action (void *data,
|
||||
struct wl_data_source *source,
|
||||
uint32_t action)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
|
||||
context = gdk_wayland_drag_context_lookup_by_data_source (source);
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_drag_context_get_display (context), EVENTS,
|
||||
g_message ("data source action, source = %p action=%x",
|
||||
source, action));
|
||||
|
||||
context->action = _wl_to_gdk_actions (action);
|
||||
g_signal_emit_by_name (context, "action-changed", context->action);
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener = {
|
||||
data_source_target,
|
||||
data_source_send,
|
||||
data_source_cancelled,
|
||||
data_source_dnd_drop_performed,
|
||||
data_source_dnd_finished,
|
||||
data_source_action,
|
||||
};
|
||||
|
||||
struct wl_data_source *
|
||||
gdk_wayland_selection_get_data_source (GdkSurface *owner)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (owner);
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
gpointer source = NULL;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
|
||||
if (wayland_selection->dnd_source)
|
||||
return wayland_selection->dnd_source;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (owner));
|
||||
|
||||
source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
|
||||
wl_data_source_add_listener (source,
|
||||
&data_source_listener,
|
||||
wayland_selection);
|
||||
|
||||
wayland_selection->dnd_source = source;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_selection_unset_data_source (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
wayland_selection->dnd_source = NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
_gdk_wayland_display_text_property_to_utf8_list (GdkDisplay *display,
|
||||
GdkAtom encoding,
|
||||
|
||||
@@ -556,6 +556,7 @@ void
|
||||
_gdk_wayland_display_create_surface_impl (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GdkSurface *real_parent,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurfaceAttr *attributes)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
@@ -2639,6 +2640,8 @@ gdk_wayland_surface_show (GdkSurface *surface,
|
||||
gdk_wayland_surface_create_surface (surface);
|
||||
|
||||
gdk_wayland_surface_map (surface);
|
||||
|
||||
_gdk_make_event (surface, GDK_MAP, NULL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2820,6 +2823,22 @@ gdk_surface_wayland_withdraw (GdkSurface *surface)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_wayland_set_events (GdkSurface *surface,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
GDK_SURFACE (surface)->event_mask = event_mask;
|
||||
}
|
||||
|
||||
static GdkEventMask
|
||||
gdk_surface_wayland_get_events (GdkSurface *surface)
|
||||
{
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return 0;
|
||||
else
|
||||
return GDK_SURFACE (surface)->event_mask;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_wayland_raise (GdkSurface *surface)
|
||||
{
|
||||
@@ -4020,6 +4039,8 @@ _gdk_surface_impl_wayland_class_init (GdkSurfaceImplWaylandClass *klass)
|
||||
impl_class->show = gdk_wayland_surface_show;
|
||||
impl_class->hide = gdk_wayland_surface_hide;
|
||||
impl_class->withdraw = gdk_surface_wayland_withdraw;
|
||||
impl_class->set_events = gdk_surface_wayland_set_events;
|
||||
impl_class->get_events = gdk_surface_wayland_get_events;
|
||||
impl_class->raise = gdk_surface_wayland_raise;
|
||||
impl_class->lower = gdk_surface_wayland_lower;
|
||||
impl_class->restack_toplevel = gdk_surface_wayland_restack_toplevel;
|
||||
|
||||
@@ -54,8 +54,6 @@ void gdk_wayland_display_set_cursor_theme (GdkDisplay *di
|
||||
const gchar *theme,
|
||||
gint size);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const gchar * gdk_wayland_display_get_startup_notification_id (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_display_set_startup_notification_id (GdkDisplay *display,
|
||||
const char *startup_id);
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ gdk_wayland_sources = files([
|
||||
'gdkcursor-wayland.c',
|
||||
'gdkdevice-wayland.c',
|
||||
'gdkdisplay-wayland.c',
|
||||
'gdkdrag-wayland.c',
|
||||
'gdkdrop-wayland.c',
|
||||
'gdkdnd-wayland.c',
|
||||
'gdkeventsource.c',
|
||||
'gdkglcontext-wayland.c',
|
||||
'gdkkeys-wayland.c',
|
||||
|
||||
@@ -280,7 +280,7 @@ Otherwise it's similar to how the clipboard works. Only the DnD server
|
||||
#include "gdkclipboard-win32.h"
|
||||
#include "gdkclipdrop-win32.h"
|
||||
#include "gdkhdataoutputstream-win32.h"
|
||||
#include "gdk/gdkdragprivate.h"
|
||||
#include "gdk/gdkdndprivate.h"
|
||||
#include "gdkwin32dnd.h"
|
||||
#include "gdkwin32dnd-private.h"
|
||||
#include "gdkwin32.h"
|
||||
@@ -1540,6 +1540,8 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
win32_clipdrop->GetUpdatedClipboardFormats = GetProcAddress (user32, "GetUpdatedClipboardFormats");
|
||||
FreeLibrary (user32);
|
||||
|
||||
win32_clipdrop->dnd_target_state = GDK_WIN32_DND_NONE;
|
||||
|
||||
atoms = g_array_sized_new (FALSE, TRUE, sizeof (GdkAtom), GDK_WIN32_ATOM_INDEX_LAST);
|
||||
g_array_set_size (atoms, GDK_WIN32_ATOM_INDEX_LAST);
|
||||
cfs = g_array_sized_new (FALSE, TRUE, sizeof (UINT), GDK_WIN32_CF_INDEX_LAST);
|
||||
@@ -1873,6 +1875,32 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
win32_clipdrop->dnd_thread_id = GPOINTER_TO_UINT (g_async_queue_pop (win32_clipdrop->dnd_queue));
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_dropfiles_store (gchar *data)
|
||||
{
|
||||
/* FIXME: REMOVE ALL THAT STUFF
|
||||
if (data != NULL)
|
||||
{
|
||||
g_assert (clipdrop->dropfiles_prop == NULL);
|
||||
|
||||
clipdrop->dropfiles_prop = g_new (GdkSelProp, 1);
|
||||
clipdrop->dropfiles_prop->data = (guchar *) data;
|
||||
clipdrop->dropfiles_prop->length = strlen (data) + 1;
|
||||
clipdrop->dropfiles_prop->bitness = 8;
|
||||
clipdrop->dropfiles_prop->target = _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clipdrop->dropfiles_prop != NULL)
|
||||
{
|
||||
g_free (clipdrop->dropfiles_prop->data);
|
||||
g_free (clipdrop->dropfiles_prop);
|
||||
}
|
||||
clipdrop->dropfiles_prop = NULL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#define CLIPBOARD_IDLE_ABORT_TIME 30
|
||||
|
||||
static const gchar *
|
||||
@@ -1939,7 +1967,7 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
}
|
||||
|
||||
/* If GetClipboardFormatNameW() used up all the space, it means that
|
||||
* we probably need a bigger buffer, but cap this at 1 megabyte.
|
||||
* we probably need a bigger buffer, but cap this at 1 kilobyte.
|
||||
*/
|
||||
if (gcfn_result == 0 || registered_name_w_len > 1024 * 1024)
|
||||
{
|
||||
@@ -1966,22 +1994,12 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
/* This turns an arbitrary string into a string that
|
||||
* *looks* like a mime/type, such as:
|
||||
* "application/x.windows.FOO_BAR" from "FOO_BAR".
|
||||
* Does nothing for strings that already look like a mime/type
|
||||
* (no spaces, one slash, with at least one char on each side of the slash).
|
||||
*/
|
||||
const gchar *
|
||||
_gdk_win32_get_clipboard_format_name_as_interned_mimetype (gchar *w32format_name)
|
||||
{
|
||||
gchar *mime_type;
|
||||
const gchar *result;
|
||||
gchar *space = strchr (w32format_name, ' ');
|
||||
gchar *slash = strchr (w32format_name, '/');
|
||||
|
||||
if (space == NULL &&
|
||||
slash > w32format_name &&
|
||||
slash[1] != '\0' &&
|
||||
strchr (&slash[1], '/') == NULL)
|
||||
return g_intern_string (w32format_name);
|
||||
|
||||
mime_type = g_strdup_printf ("application/x.windows.%s", w32format_name);
|
||||
result = g_intern_string (mime_type);
|
||||
@@ -2040,16 +2058,15 @@ _gdk_win32_get_compatibility_contentformats_for_w32format (UINT w32format)
|
||||
|
||||
/* Turn W32 format into a GDK content format and add it
|
||||
* to the array of W32 format <-> GDK content format pairs
|
||||
* and/or to a GDK contentformat builder.
|
||||
* and/or to a list of GDK content formats.
|
||||
* Also add compatibility GDK content formats for that W32 format.
|
||||
* The added content format string is always interned.
|
||||
* Ensures that duplicates are not added to the pairs array
|
||||
* (builder already takes care of that for itself).
|
||||
* Ensures that duplicates are not added.
|
||||
*/
|
||||
void
|
||||
_gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GArray *pairs,
|
||||
GdkContentFormatsBuilder *builder)
|
||||
_gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GArray *array,
|
||||
GList **list)
|
||||
{
|
||||
gboolean predef;
|
||||
gchar *w32format_name = _gdk_win32_get_clipboard_format_name (w32format, &predef);
|
||||
@@ -2064,45 +2081,47 @@ _gdk_win32_add_w32format_to_pairs (UINT w32format,
|
||||
GDK_NOTE (DND, g_print ("Maybe add as-is format %s (%s) (0x%p)\n", w32format_name, interned_w32format_name, interned_w32format_name));
|
||||
g_free (w32format_name);
|
||||
|
||||
if (pairs && interned_w32format_name != 0)
|
||||
if (array && interned_w32format_name != 0)
|
||||
{
|
||||
for (j = 0; j < pairs->len; j++)
|
||||
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
|
||||
for (j = 0; j < array->len; j++)
|
||||
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
|
||||
break;
|
||||
if (j == pairs->len)
|
||||
if (j == array->len)
|
||||
{
|
||||
pair.w32format = w32format;
|
||||
pair.contentformat = interned_w32format_name;
|
||||
pair.transmute = FALSE;
|
||||
g_array_append_val (pairs, pair);
|
||||
g_array_append_val (array, pair);
|
||||
}
|
||||
}
|
||||
if (builder != NULL && interned_w32format_name != 0)
|
||||
gdk_content_formats_builder_add_mime_type (builder, interned_w32format_name);
|
||||
|
||||
if (list && interned_w32format_name != 0 && g_list_find (*list, interned_w32format_name) == NULL)
|
||||
*list = g_list_prepend (*list, (gpointer) interned_w32format_name);
|
||||
}
|
||||
|
||||
comp_pairs = _gdk_win32_get_compatibility_contentformats_for_w32format (w32format);
|
||||
|
||||
if (pairs != NULL && comp_pairs != NULL)
|
||||
if (array && comp_pairs != NULL)
|
||||
for (i = 0; i < comp_pairs->len; i++)
|
||||
{
|
||||
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
|
||||
|
||||
for (j = 0; j < pairs->len; j++)
|
||||
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
|
||||
g_array_index (pairs, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
|
||||
for (j = 0; j < array->len; j++)
|
||||
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
|
||||
g_array_index (array, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
|
||||
break;
|
||||
|
||||
if (j == pairs->len)
|
||||
g_array_append_val (pairs, pair);
|
||||
if (j == array->len)
|
||||
g_array_append_val (array, pair);
|
||||
}
|
||||
|
||||
if (builder != NULL && comp_pairs != NULL)
|
||||
if (list && comp_pairs != NULL)
|
||||
for (i = 0; i < comp_pairs->len; i++)
|
||||
{
|
||||
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
|
||||
|
||||
gdk_content_formats_builder_add_mime_type (builder, pair.contentformat);
|
||||
if (g_list_find (*list, pair.contentformat) == NULL)
|
||||
*list = g_list_prepend (*list, (gpointer) pair.contentformat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,42 +236,42 @@ GType gdk_win32_clipdrop_get_type (void) G_GNUC
|
||||
|
||||
void _gdk_win32_clipdrop_init (void);
|
||||
|
||||
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
|
||||
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
|
||||
|
||||
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
gboolean *is_predefined);
|
||||
void _gdk_win32_add_w32format_to_pairs (UINT format,
|
||||
GArray *array,
|
||||
GdkContentFormatsBuilder *builder);
|
||||
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
|
||||
GArray *array);
|
||||
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
|
||||
gboolean *is_predefined);
|
||||
void _gdk_win32_add_w32format_to_pairs (UINT format,
|
||||
GArray *array,
|
||||
GList **list);
|
||||
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
|
||||
GArray *array);
|
||||
|
||||
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
|
||||
UINT to_w32format,
|
||||
const guchar *data,
|
||||
gint length,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
|
||||
UINT to_w32format,
|
||||
const guchar *data,
|
||||
gint length,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
|
||||
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
|
||||
const gchar *to_contentformat,
|
||||
HANDLE hdata,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
|
||||
const gchar *to_contentformat,
|
||||
HANDLE hdata,
|
||||
guchar **set_data,
|
||||
gsize *set_data_length);
|
||||
|
||||
|
||||
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
|
||||
GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
|
||||
GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -190,6 +190,13 @@ gdk_device_virtual_ungrab (GdkDevice *device,
|
||||
_gdk_display_device_grab_update (display, device, device, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_virtual_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
|
||||
{
|
||||
@@ -203,6 +210,7 @@ gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
|
||||
device_class->grab = gdk_device_virtual_grab;
|
||||
device_class->ungrab = gdk_device_virtual_ungrab;
|
||||
device_class->surface_at_position = _gdk_device_win32_surface_at_position;
|
||||
device_class->select_surface_events = gdk_device_virtual_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -222,7 +222,8 @@ _gdk_device_win32_surface_at_position (GdkDevice *device,
|
||||
do {
|
||||
window = gdk_win32_handle_table_lookup (hwnd);
|
||||
|
||||
if (window != NULL)
|
||||
if (window != NULL &&
|
||||
GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
|
||||
break;
|
||||
|
||||
screen_to_client (hwnd, screen_pt, &client_pt);
|
||||
@@ -278,6 +279,13 @@ _gdk_device_win32_surface_at_position (GdkDevice *device,
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_win32_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
|
||||
{
|
||||
@@ -291,6 +299,7 @@ gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
|
||||
device_class->grab = gdk_device_win32_grab;
|
||||
device_class->ungrab = gdk_device_win32_ungrab;
|
||||
device_class->surface_at_position = _gdk_device_win32_surface_at_position;
|
||||
device_class->select_surface_events = gdk_device_win32_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -211,6 +211,13 @@ gdk_device_wintab_surface_at_position (GdkDevice *device,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_wintab_select_surface_events (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
GdkEventMask event_mask)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab,
|
||||
GdkSurface *window,
|
||||
@@ -296,6 +303,7 @@ gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
|
||||
device_class->grab = gdk_device_wintab_grab;
|
||||
device_class->ungrab = gdk_device_wintab_ungrab;
|
||||
device_class->surface_at_position = gdk_device_wintab_surface_at_position;
|
||||
device_class->select_surface_events = gdk_device_wintab_select_surface_events;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1036,16 +1036,52 @@ gdk_input_other_event (GdkDisplay *display,
|
||||
if (!(translated_buttons & button_mask))
|
||||
{
|
||||
event->any.type = GDK_BUTTON_RELEASE;
|
||||
masktest = GDK_BUTTON_RELEASE_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->any.type = GDK_BUTTON_PRESS;
|
||||
masktest = GDK_BUTTON_PRESS_MASK;
|
||||
}
|
||||
source_device->button_state ^= button_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->any.type = GDK_MOTION_NOTIFY;
|
||||
masktest = GDK_POINTER_MOTION_MASK;
|
||||
if (source_device->button_state & (1 << 0))
|
||||
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
|
||||
if (source_device->button_state & (1 << 1))
|
||||
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
|
||||
if (source_device->button_state & (1 << 2))
|
||||
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
|
||||
}
|
||||
|
||||
/* Now we can check if the window wants the event, and
|
||||
* propagate if necessary.
|
||||
*/
|
||||
while ((gdk_surface_get_device_events (window, GDK_DEVICE (source_device)) & masktest) == 0 &&
|
||||
(gdk_device_get_device_type (GDK_DEVICE (source_device)) == GDK_DEVICE_TYPE_SLAVE &&
|
||||
(gdk_surface_get_events (window) & masktest) == 0))
|
||||
{
|
||||
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
|
||||
|
||||
if (window->parent == NULL)
|
||||
return FALSE;
|
||||
|
||||
impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
|
||||
pt.x = x * impl->surface_scale;
|
||||
pt.y = y * impl->surface_scale;
|
||||
ClientToScreen (GDK_SURFACE_HWND (window), &pt);
|
||||
g_object_unref (window);
|
||||
window = window->parent;
|
||||
impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
|
||||
g_object_ref (window);
|
||||
ScreenToClient (GDK_SURFACE_HWND (window), &pt);
|
||||
x = pt.x / impl->surface_scale;
|
||||
y = pt.y / impl->surface_scale;
|
||||
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n",
|
||||
GDK_SURFACE_HWND (window), x, y));
|
||||
}
|
||||
|
||||
event->any.surface = window;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user