Compare commits

..

1 Commits

Author SHA1 Message Date
Руслан Ижбулатов
d2b509fb23 Fix some alignment issues
* Use GRAPHENE_ALIGN16 to ensure that GtkSnapshotState size
  is a multiple of 16
* Use G_STATIC_ASSERT instead of g_return_val_if_fail to make
  the wrong size (if it turns out to be wrong) be a compile-time
  erorr instead of a runtime one
2018-06-11 12:43:14 +00:00
497 changed files with 30983 additions and 28565 deletions

View File

@@ -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:

View File

@@ -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
View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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
View 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;
}

View File

@@ -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));

View File

@@ -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">

View File

@@ -22,6 +22,7 @@ demos = files([
'editable_cells.c',
'entry_buffer.c',
'entry_completion.c',
'event_axes.c',
'expander.c',
'filtermodel.c',
'fishbowl.c',

View File

@@ -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 });

View File

@@ -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;

View File

@@ -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

View File

@@ -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");

View File

@@ -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 */

View File

@@ -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];

View File

@@ -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);

View File

@@ -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>

View File

@@ -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);

View File

@@ -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>

View File

@@ -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

View File

@@ -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: [

View File

@@ -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);
}

View File

@@ -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" />

View File

@@ -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

View File

@@ -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

View File

@@ -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 widgets #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
#GdkSurfaces mask for the input device, if set. Otherwise, it is filtered
against the #GdkSurfaces 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>

View File

@@ -355,6 +355,7 @@ content_files = [
'input-handling.xml',
'migrating-2to4.xml',
'migrating-3to4.xml',
'mir.xml',
'osx.sgml',
'other_software.sgml',
'overview.xml',

View File

@@ -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>

View 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>

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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',

View File

@@ -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)

View File

@@ -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__ */

View File

@@ -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)
{

View File

@@ -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>

View File

@@ -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

View File

@@ -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",

View File

@@ -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 *

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 *

View File

@@ -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);

View File

@@ -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
View 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
View 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 doesnt 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
View 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

View File

@@ -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;
}

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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)

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 *

View File

@@ -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,

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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
* its 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__ */

View File

@@ -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',

View File

@@ -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

View File

@@ -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. */
}

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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",

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -139,6 +139,8 @@ struct _GdkWaylandDisplay
struct xkb_context *xkb_context;
GdkWaylandSelection *selection;
GPtrArray *monitors;
gint64 last_bell_time_ms;

View 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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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__ */

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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',

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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