[nautilus/wip/ernestask/gtk4-continued: 17/144] canvas: Use custom event objects for event synthesis
- From: Ernestas Kulik <ernestask src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/ernestask/gtk4-continued: 17/144] canvas: Use custom event objects for event synthesis
- Date: Mon, 11 Feb 2019 13:20:51 +0000 (UTC)
commit 9b6b318b4913f24f9cc8e9e1fb0ea60f3860ac5d
Author: Ernestas Kulik <ernestask gnome org>
Date: Mon Jun 4 09:26:30 2018 +0300
canvas: Use custom event objects for event synthesis
Since GdkEvent is now closed off and doesn’t exactly allow synthesizing
events outside GTK+, a mechanism for life support is required. This
commit adds a new event type to use in the canvas view.
Additionally, this commit replaces button event handling with a gesture.
eel/eel-canvas.c | 381 +++++++++++++++---------------------
eel/eel-canvas.h | 16 +-
eel/eel-event.c | 199 +++++++++++++++++++
eel/eel-event.h | 59 ++++++
eel/meson.build | 2 +
src/nautilus-canvas-container.c | 419 ++++++++++++++++++++++------------------
src/nautilus-canvas-item.c | 123 +++++++-----
src/nautilus-canvas-private.h | 5 +-
src/nautilus-canvas-view.c | 31 ++-
9 files changed, 745 insertions(+), 490 deletions(-)
---
diff --git a/eel/eel-canvas.c b/eel/eel-canvas.c
index 154dbd6b2..06deef763 100644
--- a/eel/eel-canvas.c
+++ b/eel/eel-canvas.c
@@ -93,7 +93,7 @@ enum
static void eel_canvas_item_class_init (EelCanvasItemClass *klass);
static void eel_canvas_item_init (EelCanvasItem *item);
static int emit_event (EelCanvas *canvas,
- GdkEvent *event);
+ EelEvent *event);
static guint item_signals[ITEM_LAST_SIGNAL];
@@ -1069,36 +1069,11 @@ is_descendant (EelCanvasItem *item,
static void
eel_canvas_item_grab_focus (EelCanvasItem *item)
{
- EelCanvasItem *focused_item;
- GdkEvent ev;
-
g_return_if_fail (EEL_IS_CANVAS_ITEM (item));
g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas)));
- focused_item = item->canvas->focused_item;
-
- if (focused_item)
- {
- ev.focus_change.type = GDK_FOCUS_CHANGE;
- ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas));
- ev.focus_change.send_event = FALSE;
- ev.focus_change.in = FALSE;
-
- emit_event (item->canvas, &ev);
- }
-
item->canvas->focused_item = item;
gtk_widget_grab_focus (GTK_WIDGET (item->canvas));
-
- if (focused_item)
- {
- ev.focus_change.type = GDK_FOCUS_CHANGE;
- ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas));
- ev.focus_change.send_event = FALSE;
- ev.focus_change.in = TRUE;
-
- emit_event (item->canvas, &ev);
- }
}
@@ -1916,8 +1891,6 @@ static void eel_canvas_realize (GtkWidget *widget);
static void eel_canvas_unrealize (GtkWidget *widget);
static void eel_canvas_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
-static gint eel_canvas_button (GtkWidget *widget,
- GdkEventButton *event);
static gint eel_canvas_motion (GtkWidget *widget,
GdkEventMotion *event);
static gint eel_canvas_draw (GtkWidget *widget,
@@ -1926,10 +1899,6 @@ static gint eel_canvas_key (GtkWidget *widget,
GdkEventKey *event);
static gint eel_canvas_crossing (GtkWidget *widget,
GdkEventCrossing *event);
-static gint eel_canvas_focus_in (GtkWidget *widget,
- GdkEventFocus *event);
-static gint eel_canvas_focus_out (GtkWidget *widget,
- GdkEventFocus *event);
static void eel_canvas_request_update_real (EelCanvas *canvas);
static GtkLayoutClass *canvas_parent_class;
@@ -2002,6 +1971,18 @@ eel_canvas_set_property (GObject *object,
}
}
+static void
+eel_canvas_dispose (GObject *object)
+{
+ EelCanvas *canvas;
+
+ canvas = EEL_CANVAS (object);
+
+ g_clear_object (&canvas->pick_event);
+
+ G_OBJECT_CLASS (canvas_parent_class)->dispose (object);
+}
+
static void
eel_canvas_accessible_adjustment_changed (GtkAdjustment *adjustment,
gpointer data)
@@ -2129,6 +2110,7 @@ eel_canvas_class_init (EelCanvasClass *klass)
gobject_class->set_property = eel_canvas_set_property;
gobject_class->get_property = eel_canvas_get_property;
+ gobject_class->dispose = eel_canvas_dispose;
widget_class->destroy = eel_canvas_destroy;
widget_class->map = eel_canvas_map;
@@ -2136,16 +2118,12 @@ eel_canvas_class_init (EelCanvasClass *klass)
widget_class->realize = eel_canvas_realize;
widget_class->unrealize = eel_canvas_unrealize;
widget_class->size_allocate = eel_canvas_size_allocate;
- widget_class->button_press_event = eel_canvas_button;
- widget_class->button_release_event = eel_canvas_button;
widget_class->motion_notify_event = eel_canvas_motion;
widget_class->draw = eel_canvas_draw;
widget_class->key_press_event = eel_canvas_key;
widget_class->key_release_event = eel_canvas_key;
widget_class->enter_notify_event = eel_canvas_crossing;
widget_class->leave_notify_event = eel_canvas_crossing;
- widget_class->focus_in_event = eel_canvas_focus_in;
- widget_class->focus_out_event = eel_canvas_focus_out;
klass->request_update = eel_canvas_request_update_real;
@@ -2166,23 +2144,27 @@ panic_root_destroyed (GtkWidget *object,
static void
eel_canvas_init (EelCanvas *canvas)
{
+ GtkWidget *widget;
guint width, height;
- gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE);
- gtk_widget_set_redraw_on_allocate (GTK_WIDGET (canvas), FALSE);
+ widget = GTK_WIDGET (canvas);
+
+ gtk_widget_set_can_focus (widget, TRUE);
+ gtk_widget_set_redraw_on_allocate (widget, FALSE);
canvas->scroll_x1 = 0.0;
canvas->scroll_y1 = 0.0;
- gtk_layout_get_size (GTK_LAYOUT (canvas),
- &width, &height);
+
+ gtk_layout_get_size (GTK_LAYOUT (canvas), &width, &height);
+
canvas->scroll_x2 = width;
canvas->scroll_y2 = height;
canvas->pixels_per_unit = 1.0;
- canvas->pick_event.type = GDK_LEAVE_NOTIFY;
- canvas->pick_event.crossing.x = 0;
- canvas->pick_event.crossing.y = 0;
+ canvas->pick_event = eel_event_new ();
+
+ eel_event_set_event_type (canvas->pick_event, GDK_LEAVE_NOTIFY);
gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas), NULL);
gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas), NULL);
@@ -2366,8 +2348,7 @@ eel_canvas_realize (GtkWidget *widget)
| GDK_KEY_PRESS_MASK
| GDK_KEY_RELEASE_MASK
| GDK_ENTER_NOTIFY_MASK
- | GDK_LEAVE_NOTIFY_MASK
- | GDK_FOCUS_CHANGE_MASK));
+ | GDK_LEAVE_NOTIFY_MASK));
/* Create our own temporary pixmap gc and realize all the items */
@@ -2570,13 +2551,18 @@ eel_canvas_size_allocate (GtkWidget *widget,
static int
emit_event (EelCanvas *canvas,
- GdkEvent *event)
+ EelEvent *event)
{
- GdkEvent ev;
+ GdkEventType event_type;
+ g_autoptr (EelEvent) ev = NULL;
gint finished;
EelCanvasItem *item;
EelCanvasItem *parent;
guint mask;
+ gdouble world_x;
+ gdouble world_y;
+
+ event_type = eel_event_get_event_type (event);
/* Could be an old pick event */
if (!gtk_widget_get_realized (GTK_WIDGET (canvas)))
@@ -2594,7 +2580,7 @@ emit_event (EelCanvas *canvas,
if (canvas->grabbed_item)
{
- switch (event->type)
+ switch (eel_event_get_event_type (event))
{
case GDK_ENTER_NOTIFY:
{
@@ -2653,49 +2639,20 @@ emit_event (EelCanvas *canvas,
}
}
- /* Convert to world coordinates -- we have two cases because of diferent
- * offsets of the fields in the event structures.
- */
-
- ev = *event;
-
- switch (ev.type)
- {
- case GDK_ENTER_NOTIFY:
- case GDK_LEAVE_NOTIFY:
- {
- eel_canvas_window_to_world (canvas,
- ev.crossing.x, ev.crossing.y,
- &ev.crossing.x, &ev.crossing.y);
- }
- break;
+ ev = eel_event_copy (event);
- case GDK_MOTION_NOTIFY:
- case GDK_BUTTON_PRESS:
- case GDK_2BUTTON_PRESS:
- case GDK_3BUTTON_PRESS:
- case GDK_BUTTON_RELEASE:
- {
- eel_canvas_window_to_world (canvas,
- ev.motion.x, ev.motion.y,
- &ev.motion.x, &ev.motion.y);
- }
- break;
+ eel_event_get_coords (ev, &world_x, &world_y);
+ eel_canvas_window_to_world (canvas, world_x, world_y, &world_x, &world_y);
- default:
- {
- }
- break;
- }
+ eel_event_set_coords (ev, world_x, world_y);
/* Choose where we send the event */
item = canvas->current_item;
if (canvas->focused_item
- && ((event->type == GDK_KEY_PRESS) ||
- (event->type == GDK_KEY_RELEASE) ||
- (event->type == GDK_FOCUS_CHANGE)))
+ && ((event_type == GDK_KEY_PRESS) ||
+ (event_type == GDK_KEY_RELEASE)))
{
item = canvas->focused_item;
}
@@ -2711,9 +2668,11 @@ emit_event (EelCanvas *canvas,
{
g_object_ref (item);
- g_signal_emit (
- G_OBJECT (item), item_signals[ITEM_EVENT], 0,
- &ev, &finished);
+ g_signal_emit (item,
+ item_signals[ITEM_EVENT],
+ 0,
+ ev,
+ &finished);
parent = item->parent;
g_object_unref (item);
@@ -2729,13 +2688,13 @@ emit_event (EelCanvas *canvas,
*/
static int
pick_current_item (EelCanvas *canvas,
- GdkEvent *event)
+ EelEvent *event)
{
+ GdkEventType event_type;
int button_down;
- double x, y;
- int cx, cy;
int retval;
+ event_type = eel_event_get_event_type (event);
retval = FALSE;
/* If a button is down, we'll perform enter and leave events on the
@@ -2757,39 +2716,23 @@ pick_current_item (EelCanvas *canvas,
* re-pick the current item if the current one gets deleted. Also,
* synthesize an enter event.
*/
- if (event != &canvas->pick_event)
+ if (event != canvas->pick_event)
{
- if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE))
+ if (event_type == GDK_MOTION_NOTIFY || event_type == GDK_BUTTON_RELEASE)
{
- /* these fields have the same offsets in both types of events */
-
- canvas->pick_event.crossing.type = GDK_ENTER_NOTIFY;
- canvas->pick_event.crossing.window = event->motion.window;
- canvas->pick_event.crossing.send_event = event->motion.send_event;
- canvas->pick_event.crossing.subwindow = NULL;
- canvas->pick_event.crossing.x = event->motion.x;
- canvas->pick_event.crossing.y = event->motion.y;
- canvas->pick_event.crossing.mode = GDK_CROSSING_NORMAL;
- canvas->pick_event.crossing.detail = GDK_NOTIFY_NONLINEAR;
- canvas->pick_event.crossing.focus = FALSE;
- canvas->pick_event.crossing.state = event->motion.state;
-
- /* these fields don't have the same offsets in both types of events */
-
- if (event->type == GDK_MOTION_NOTIFY)
- {
- canvas->pick_event.crossing.x_root = event->motion.x_root;
- canvas->pick_event.crossing.y_root = event->motion.y_root;
- }
- else
- {
- canvas->pick_event.crossing.x_root = event->button.x_root;
- canvas->pick_event.crossing.y_root = event->button.y_root;
- }
+ gdouble x;
+ gdouble y;
+
+ eel_event_get_coords (event, &x, &y);
+
+ eel_event_set_coords (canvas->pick_event, x, y);
+ eel_event_set_event_type (canvas->pick_event, GDK_ENTER_NOTIFY);
+ eel_event_set_state (canvas->pick_event, eel_event_get_state (event));
}
else
{
- canvas->pick_event = *event;
+ g_clear_object (&canvas->pick_event);
+ canvas->pick_event = g_object_ref (event);
}
}
@@ -2802,20 +2745,14 @@ pick_current_item (EelCanvas *canvas,
/* LeaveNotify means that there is no current item, so we don't look for one */
- if (canvas->pick_event.type != GDK_LEAVE_NOTIFY)
+ if (eel_event_get_event_type (canvas->pick_event) != GDK_LEAVE_NOTIFY)
{
- /* these fields don't have the same offsets in both types of events */
+ gdouble x;
+ gdouble y;
+ gint cx;
+ gint cy;
- if (canvas->pick_event.type == GDK_ENTER_NOTIFY)
- {
- x = canvas->pick_event.crossing.x;
- y = canvas->pick_event.crossing.y;
- }
- else
- {
- x = canvas->pick_event.motion.x;
- y = canvas->pick_event.motion.y;
- }
+ eel_event_get_coords (canvas->pick_event, &x, &y);
/* canvas pixel coords */
@@ -2851,15 +2788,14 @@ pick_current_item (EelCanvas *canvas,
&& (canvas->current_item != NULL)
&& !canvas->left_grabbed_item)
{
- GdkEvent new_event;
+ g_autoptr (EelEvent) new_event = NULL;
+
+ new_event = eel_event_copy (canvas->pick_event);
- new_event = canvas->pick_event;
- new_event.type = GDK_LEAVE_NOTIFY;
+ eel_event_set_event_type (new_event, GDK_LEAVE_NOTIFY);
- new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
- new_event.crossing.subwindow = NULL;
canvas->in_repick = TRUE;
- retval = emit_event (canvas, &new_event);
+ retval = emit_event (canvas, new_event);
canvas->in_repick = FALSE;
}
@@ -2879,36 +2815,39 @@ pick_current_item (EelCanvas *canvas,
if (canvas->current_item != NULL)
{
- GdkEvent new_event;
+ g_autoptr (EelEvent) new_event = NULL;
- new_event = canvas->pick_event;
- new_event.type = GDK_ENTER_NOTIFY;
- new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
- new_event.crossing.subwindow = NULL;
- retval = emit_event (canvas, &new_event);
+ new_event = eel_event_copy (canvas->pick_event);
+
+ eel_event_set_event_type (new_event, GDK_ENTER_NOTIFY);
+
+ retval = emit_event (canvas, new_event);
}
return retval;
}
-/* Button event handler for the canvas */
-static gint
-eel_canvas_button (GtkWidget *widget,
- GdkEventButton *event)
+gboolean
+eel_canvas_handle_event (EelCanvas *canvas,
+ EelEvent *event)
{
- EelCanvas *canvas;
- int mask;
- int retval;
+ guint button;
+ GdkWindow *event_window;
+ GdkWindow *bin_window;
+ GdkEventType event_type;
+ gint mask;
+ gboolean handled = FALSE;
- g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE);
+ g_return_val_if_fail (EEL_IS_CANVAS (canvas), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- retval = FALSE;
-
- canvas = EEL_CANVAS (widget);
+ button = eel_event_get_button (event);
+ event_window = eel_event_get_window (event);
+ bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (canvas));
+ event_type = eel_event_get_event_type (event);
/* Don't handle extra mouse button events */
- if (event->button > 5)
+ if (button > 5)
{
return FALSE;
}
@@ -2917,12 +2856,12 @@ eel_canvas_button (GtkWidget *widget,
* dispatch normally regardless of the event's window if an item has
* has a pointer grab in effect
*/
- if (!canvas->grabbed_item && event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)))
+ if (canvas->grabbed_item == NULL && event_window != bin_window)
{
- return retval;
+ return FALSE;
}
- switch (event->button)
+ switch (button)
{
case 1:
{
@@ -2958,7 +2897,7 @@ eel_canvas_button (GtkWidget *widget,
mask = 0;
}
- switch (event->type)
+ switch (event_type)
{
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
@@ -2967,12 +2906,17 @@ eel_canvas_button (GtkWidget *widget,
/* Pick the current item as if the button were not pressed, and
* then process the event.
*/
- event->state ^= mask;
- canvas->state = event->state;
- pick_current_item (canvas, (GdkEvent *) event);
- event->state ^= mask;
- canvas->state = event->state;
- retval = emit_event (canvas, (GdkEvent *) event);
+ canvas->state = eel_event_get_state (event);
+
+ canvas->state ^= mask;
+ eel_event_set_state (event, canvas->state);
+
+ pick_current_item (canvas, event);
+
+ canvas->state ^= mask;
+ eel_event_set_state (event, canvas->state);
+
+ handled = emit_event (canvas, event);
}
break;
@@ -2981,12 +2925,16 @@ eel_canvas_button (GtkWidget *widget,
/* Process the event as if the button were pressed, then repick
* after the button has been released
*/
- canvas->state = event->state;
- retval = emit_event (canvas, (GdkEvent *) event);
- event->state ^= mask;
- canvas->state = event->state;
- pick_current_item (canvas, (GdkEvent *) event);
- event->state ^= mask;
+ canvas->state = eel_event_get_state (event);
+
+ handled = emit_event (canvas, event);
+
+ canvas->state ^= mask;
+ eel_event_set_state (event, canvas->state);
+
+ pick_current_item (canvas, event);
+
+ eel_event_set_state (event, canvas->state ^ mask);
}
break;
@@ -2994,54 +2942,65 @@ eel_canvas_button (GtkWidget *widget,
g_assert_not_reached ();
}
- return retval;
+ return handled;
}
/* Motion event handler for the canvas */
static gint
eel_canvas_motion (GtkWidget *widget,
- GdkEventMotion *event)
+ GdkEventMotion *gdk_event)
{
EelCanvas *canvas;
+ g_autoptr (EelEvent) event = NULL;
+ GdkWindow *event_window;
+ GdkWindow *bin_window;
g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (gdk_event != NULL, FALSE);
canvas = EEL_CANVAS (widget);
+ event = eel_event_new_from_gdk_event ((GdkEvent *) gdk_event);
+ event_window = eel_event_get_window (event);
+ bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (canvas));
- if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)))
+ if (event_window != bin_window)
{
return FALSE;
}
- canvas->state = event->state;
- pick_current_item (canvas, (GdkEvent *) event);
- return emit_event (canvas, (GdkEvent *) event);
+ canvas->state = eel_event_get_state (event);
+
+ pick_current_item (canvas, event);
+
+ return emit_event (canvas, event);
}
/* Key event handler for the canvas */
static gint
eel_canvas_key (GtkWidget *widget,
- GdkEventKey *event)
+ GdkEventKey *gdk_event)
{
EelCanvas *canvas;
+ g_autoptr (EelEvent) event = NULL;
g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (gdk_event != NULL, FALSE);
canvas = EEL_CANVAS (widget);
+ event = eel_event_new_from_gdk_event ((GdkEvent *) gdk_event);
- if (emit_event (canvas, (GdkEvent *) event))
+ if (emit_event (canvas, event))
{
return TRUE;
}
- if (event->type == GDK_KEY_RELEASE)
+
+ if (gdk_event_get_event_type ((GdkEvent *) gdk_event) == GDK_KEY_RELEASE)
{
- return GTK_WIDGET_CLASS (canvas_parent_class)->key_release_event (widget, event);
+ return GTK_WIDGET_CLASS (canvas_parent_class)->key_release_event (widget, gdk_event);
}
else
{
- return GTK_WIDGET_CLASS (canvas_parent_class)->key_press_event (widget, event);
+ return GTK_WIDGET_CLASS (canvas_parent_class)->key_press_event (widget, gdk_event);
}
}
@@ -3049,63 +3008,31 @@ eel_canvas_key (GtkWidget *widget,
/* Crossing event handler for the canvas */
static gint
eel_canvas_crossing (GtkWidget *widget,
- GdkEventCrossing *event)
+ GdkEventCrossing *gdk_event)
{
EelCanvas *canvas;
+ g_autoptr (EelEvent) event = NULL;
+ GdkWindow *event_window;
+ GdkWindow *bin_window;
g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (gdk_event != NULL, FALSE);
canvas = EEL_CANVAS (widget);
+ event = eel_event_new_from_gdk_event ((GdkEvent *) gdk_event);
+ event_window = eel_event_get_window (event);
+ bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (canvas));
- if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)))
+ if (event_window != bin_window)
{
return FALSE;
}
- canvas->state = event->state;
- return pick_current_item (canvas, (GdkEvent *) event);
-}
-
-/* Focus in handler for the canvas */
-static gint
-eel_canvas_focus_in (GtkWidget *widget,
- GdkEventFocus *event)
-{
- EelCanvas *canvas;
-
- canvas = EEL_CANVAS (widget);
-
- if (canvas->focused_item)
- {
- return emit_event (canvas, (GdkEvent *) event);
- }
- else
- {
- return FALSE;
- }
-}
-
-/* Focus out handler for the canvas */
-static gint
-eel_canvas_focus_out (GtkWidget *widget,
- GdkEventFocus *event)
-{
- EelCanvas *canvas;
-
- canvas = EEL_CANVAS (widget);
+ canvas->state = eel_event_get_state (event);
- if (canvas->focused_item)
- {
- return emit_event (canvas, (GdkEvent *) event);
- }
- else
- {
- return FALSE;
- }
+ return pick_current_item (canvas, event);
}
-
static cairo_region_t *
eel_cairo_get_clip_region (cairo_t *cr)
{
@@ -3248,7 +3175,7 @@ update_again:
while (canvas->need_repick)
{
canvas->need_repick = FALSE;
- pick_current_item (canvas, &canvas->pick_event);
+ pick_current_item (canvas, canvas->pick_event);
}
/* it is possible that during picking we emitted an event in which
@@ -4129,7 +4056,7 @@ eel_canvas_item_class_init (EelCanvasItemClass *klass)
boolean_handled_accumulator, NULL,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
- GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+ EEL_TYPE_EVENT);
item_signals[ITEM_DESTROY] =
g_signal_new ("destroy",
diff --git a/eel/eel-canvas.h b/eel/eel-canvas.h
index 62e50a857..d81477eca 100644
--- a/eel/eel-canvas.h
+++ b/eel/eel-canvas.h
@@ -39,6 +39,8 @@
#include <gdk/gdk.h>
#include <stdarg.h>
+#include "eel-event.h"
+
G_BEGIN_DECLS
@@ -172,10 +174,7 @@ struct _EelCanvasItemClass {
/* Signal: an event ocurred for an item of this type. The (x, y)
* coordinates are in the canvas world coordinate system.
*/
- gboolean (* event) (EelCanvasItem *item, GdkEvent *event);
-
- /* Reserved for future expansion */
- gpointer spare_vmethods [4];
+ gboolean (* event) (EelCanvasItem *item, EelEvent *event);
};
@@ -342,7 +341,7 @@ struct _EelCanvas {
EelCanvasItem *focused_item;
/* Event on which selection of current item is based */
- GdkEvent pick_event;
+ EelEvent *pick_event;
/* Scrolling region */
double scroll_x1, scroll_y1;
@@ -361,7 +360,7 @@ struct _EelCanvas {
int zoom_xofs, zoom_yofs;
/* Last known modifier state, for deferred repick when a button is down */
- int state;
+ GdkModifierType state;
/* Event mask specified when grabbing an item */
guint grabbed_event_mask;
@@ -465,6 +464,9 @@ void eel_canvas_window_to_world (EelCanvas *canvas,
void eel_canvas_world_to_window (EelCanvas *canvas,
double worldx, double worldy, double *winx, double *winy);
+gboolean eel_canvas_handle_event (EelCanvas *canvas,
+ EelEvent *event);
+
/* Accessible implementation */
GType eel_canvas_accessible_get_type (void);
@@ -494,4 +496,4 @@ struct _EelCanvasItemAccessibleClass
GtkAccessibleClass parent_class;
};
-G_END_DECLS
\ No newline at end of file
+G_END_DECLS
diff --git a/eel/eel-event.c b/eel/eel-event.c
new file mode 100644
index 000000000..13582692d
--- /dev/null
+++ b/eel/eel-event.c
@@ -0,0 +1,199 @@
+/* Copyright (C) 2018 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "eel-event.h"
+
+struct _EelEvent
+{
+ GObject parent_instance;
+
+ GdkEventType type;
+
+ GdkWindow *window;
+
+ gdouble x;
+ gdouble y;
+
+ guint button;
+
+ GdkModifierType state;
+
+ guint32 time;
+};
+
+G_DEFINE_TYPE (EelEvent, eel_event, G_TYPE_OBJECT)
+
+static void
+eel_event_init (EelEvent *self)
+{
+ self->type = GDK_NOTHING;
+ self->window = NULL;
+ self->x = 0.0;
+ self->y = 0.0;
+ self->button = 0;
+ self->state = 0;
+ self->time = 0;
+}
+
+static void
+eel_event_class_init (EelEventClass *klass)
+{
+}
+
+GdkEventType
+eel_event_get_event_type (EelEvent *self)
+{
+ g_return_val_if_fail (EEL_IS_EVENT (self), GDK_NOTHING);
+
+ return self->type;
+}
+
+void
+eel_event_set_event_type (EelEvent *self,
+ GdkEventType type)
+{
+ g_return_if_fail (EEL_IS_EVENT (self));
+ g_return_if_fail (type >= GDK_NOTHING && type < GDK_EVENT_LAST);
+
+ self->type = type;
+}
+
+GdkWindow *
+eel_event_get_window (EelEvent *self)
+{
+ g_return_val_if_fail (EEL_IS_EVENT (self), NULL);
+
+ return self->window;
+}
+
+void
+eel_event_set_window (EelEvent *self,
+ GdkWindow *window)
+{
+ g_return_if_fail (EEL_IS_EVENT (self));
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ self->window = window;
+}
+
+void
+eel_event_get_coords (EelEvent *self,
+ gdouble *x,
+ gdouble *y)
+{
+ g_return_if_fail (EEL_IS_EVENT (self));
+
+ if (x != NULL)
+ {
+ *x = self->x;
+ }
+ if (y != NULL)
+ {
+ *y = self->y;
+ }
+}
+
+void
+eel_event_set_coords (EelEvent *self,
+ gdouble x,
+ gdouble y)
+{
+ g_return_if_fail (EEL_IS_EVENT (self));
+
+ self->x = x;
+ self->y = y;
+}
+
+guint
+eel_event_get_button (EelEvent *self)
+{
+ g_return_val_if_fail (EEL_IS_EVENT (self), 0);
+
+ return self->button;
+}
+
+GdkModifierType
+eel_event_get_state (EelEvent *self)
+{
+ g_return_val_if_fail (EEL_IS_EVENT (self), 0);
+
+ return self->state;
+}
+
+void
+eel_event_set_state (EelEvent *self,
+ GdkModifierType state)
+{
+ g_return_if_fail (EEL_IS_EVENT (self));
+
+ self->state = state;
+}
+
+guint32
+eel_event_get_time (EelEvent *self)
+{
+ g_return_val_if_fail (EEL_IS_EVENT (self), 0);
+
+ return self->time;
+}
+
+EelEvent *
+eel_event_copy (EelEvent *self)
+{
+ EelEvent *event;
+
+ g_return_val_if_fail (EEL_IS_EVENT (self), NULL);
+
+ event = eel_event_new ();
+
+ event->type = self->type;
+ event->window = self->window;
+ event->x = self->x;
+ event->y = self->y;
+ event->button = self->button;
+ event->state = self->state;
+ event->time = self->time;
+
+ return event;
+}
+
+EelEvent *
+eel_event_new (void)
+{
+ return g_object_new (EEL_TYPE_EVENT, NULL);
+}
+
+EelEvent *
+eel_event_new_from_gdk_event (const GdkEvent *gdk_event)
+{
+ EelEvent *event;
+
+ g_return_val_if_fail (gdk_event != NULL, NULL);
+
+ event = eel_event_new ();
+
+ event->type = gdk_event_get_event_type (gdk_event);
+ event->window = gdk_event_get_window (gdk_event);
+ event->time = gdk_event_get_time (gdk_event);
+
+ gdk_event_get_coords (gdk_event, &event->x, &event->y);
+ gdk_event_get_button (gdk_event, &event->button);
+ gdk_event_get_state (gdk_event, &event->state);
+
+ return event;
+}
diff --git a/eel/eel-event.h b/eel/eel-event.h
new file mode 100644
index 000000000..26dc3c458
--- /dev/null
+++ b/eel/eel-event.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2018 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define EEL_TYPE_EVENT (eel_event_get_type ())
+
+G_DECLARE_FINAL_TYPE (EelEvent, eel_event, EEL, EVENT, GObject)
+
+GdkEventType eel_event_get_event_type (EelEvent *event);
+void eel_event_set_event_type (EelEvent *event,
+ GdkEventType type);
+
+GdkWindow *eel_event_get_window (EelEvent *event);
+void eel_event_set_window (EelEvent *event,
+ GdkWindow *window);
+
+void eel_event_get_coords (EelEvent *event,
+ gdouble *x,
+ gdouble *y);
+void eel_event_set_coords (EelEvent *event,
+ gdouble x,
+ gdouble y);
+
+guint eel_event_get_button (EelEvent *event);
+void eel_event_set_button (EelEvent *event,
+ guint button);
+
+GdkModifierType eel_event_get_state (EelEvent *event);
+void eel_event_set_state (EelEvent *event,
+ GdkModifierType state);
+
+guint32 eel_event_get_time (EelEvent *event);
+
+EelEvent *eel_event_copy (EelEvent *event);
+
+EelEvent *eel_event_new (void);
+EelEvent *eel_event_new_from_gdk_event (const GdkEvent *gdk_event);
+
+G_END_DECLS
diff --git a/eel/meson.build b/eel/meson.build
index 5437bdc4c..c646f9e6f 100644
--- a/eel/meson.build
+++ b/eel/meson.build
@@ -5,6 +5,8 @@ libeel_2_sources = [
'eel-canvas.c',
'eel-debug.h',
'eel-debug.c',
+ 'eel-event.c',
+ 'eel-event.h',
'eel-glib-extensions.h',
'eel-graphic-effects.h',
'eel-graphic-effects.c',
diff --git a/src/nautilus-canvas-container.c b/src/nautilus-canvas-container.c
index 598db03d3..94d4d09d3 100644
--- a/src/nautilus-canvas-container.c
+++ b/src/nautilus-canvas-container.c
@@ -124,7 +124,8 @@ static GType nautilus_canvas_container_accessible_get_type (void);
static void preview_selected_items (NautilusCanvasContainer *container);
static void activate_selected_items (NautilusCanvasContainer *container);
static void activate_selected_items_alternate (NautilusCanvasContainer *container,
- NautilusCanvasIcon *icon);
+ NautilusCanvasIcon *icon,
+ EelEvent *event);
static NautilusCanvasIcon *get_first_selected_icon (NautilusCanvasContainer *container);
static NautilusCanvasIcon *get_nth_selected_icon (NautilusCanvasContainer *container,
int index);
@@ -189,7 +190,6 @@ enum
ACTIVATE_PREVIEWER,
BAND_SELECT_STARTED,
BAND_SELECT_ENDED,
- BUTTON_PRESS,
CAN_ACCEPT_ITEM,
CONTEXT_CLICK_BACKGROUND,
CONTEXT_CLICK_SELECTION,
@@ -1433,9 +1433,13 @@ redo_layout (NautilusCanvasContainer *container)
/* Container-level icon handling functions. */
static gboolean
-button_event_modifies_selection (GdkEventButton *event)
+button_event_modifies_selection (EelEvent *event)
{
- return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
+ GdkModifierType state;
+
+ state = eel_event_get_state (event);
+
+ return (state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
}
/* invalidate the cached label sizes for all the icons */
@@ -1723,11 +1727,13 @@ rubberband_timeout_callback (gpointer data)
static void
stop_rubberbanding (NautilusCanvasContainer *container,
- GdkEventButton *event);
+ const GdkEvent *event);
static void
start_rubberbanding (NautilusCanvasContainer *container,
- GdkEventButton *event)
+ gdouble x,
+ gdouble y,
+ const GdkEvent *event)
{
AtkObject *accessible;
NautilusCanvasContainerDetails *details;
@@ -1747,7 +1753,7 @@ start_rubberbanding (NautilusCanvasContainer *container,
g_signal_emit (container,
signals[BAND_SELECT_STARTED], 0);
- band_info->device = event->device;
+ band_info->device = gdk_event_get_device (event);
for (p = details->icons; p != NULL; p = p->next)
{
@@ -1755,9 +1761,12 @@ start_rubberbanding (NautilusCanvasContainer *container,
icon->was_selected_before_rubberband = icon->is_selected;
}
- eel_canvas_window_to_world
- (EEL_CANVAS (container), event->x, event->y,
- &band_info->start_x, &band_info->start_y);
+ x += gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)));
+ y += gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)));
+
+ eel_canvas_window_to_world (EEL_CANVAS (container),
+ x, y,
+ &band_info->start_x, &band_info->start_y);
band_info->selection_rectangle = eel_canvas_item_new
(eel_canvas_root
@@ -1774,8 +1783,8 @@ start_rubberbanding (NautilusCanvasContainer *container,
atk_object_set_name (accessible, "selection");
atk_object_set_description (accessible, _("The selection rectangle"));
- band_info->prev_x = event->x - gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE
(container)));
- band_info->prev_y = event->y - gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE
(container)));
+ band_info->prev_x = x - gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE
(container)));
+ band_info->prev_y = y - gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE
(container)));
band_info->active = TRUE;
@@ -1792,12 +1801,12 @@ start_rubberbanding (NautilusCanvasContainer *container,
| GDK_BUTTON_RELEASE_MASK
| GDK_SCROLL_MASK),
NULL,
- (GdkEvent *) event);
+ event);
}
static void
stop_rubberbanding (NautilusCanvasContainer *container,
- GdkEventButton *event)
+ const GdkEvent *event)
{
NautilusCanvasRubberbandInfo *band_info;
GList *icons;
@@ -1805,7 +1814,7 @@ stop_rubberbanding (NautilusCanvasContainer *container,
band_info = &container->details->rubberband_info;
- if (event != NULL && event->device != band_info->device)
+ if (event != NULL && gdk_event_get_device (event) != band_info->device)
{
return;
}
@@ -2528,6 +2537,10 @@ keyboard_move_to (NautilusCanvasContainer *container,
NautilusCanvasIcon *from,
GdkEventKey *event)
{
+ GdkModifierType state;
+
+ gdk_event_get_state ((GdkEvent *) event, &state);
+
if (icon == NULL)
{
return;
@@ -2535,15 +2548,11 @@ keyboard_move_to (NautilusCanvasContainer *container,
set_focus (container, icon, TRUE);
- if (event != NULL &&
- (event->state & GDK_CONTROL_MASK) != 0 &&
- (event->state & GDK_SHIFT_MASK) == 0)
+ if ((state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) == 0)
{
clear_keyboard_rubberband_start (container);
}
- else if (event != NULL &&
- (event->state & GDK_CONTROL_MASK) != 0 &&
- (event->state & GDK_SHIFT_MASK) != 0)
+ else if ((state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) != 0)
{
/* Do rubberband selection */
EelDRect rect;
@@ -2560,9 +2569,7 @@ keyboard_move_to (NautilusCanvasContainer *container,
rubberband_select (container, &rect);
}
}
- else if (event != NULL &&
- (event->state & GDK_CONTROL_MASK) == 0 &&
- (event->state & GDK_SHIFT_MASK) != 0)
+ else if ((state & GDK_CONTROL_MASK) == 0 && (state & GDK_SHIFT_MASK) != 0)
{
/* Select range */
NautilusCanvasIcon *start_icon;
@@ -2761,8 +2768,11 @@ keyboard_arrow_key (NautilusCanvasContainer *container,
static gboolean
is_rectangle_selection_event (GdkEventKey *event)
{
- return (event->state & GDK_CONTROL_MASK) != 0 &&
- (event->state & GDK_SHIFT_MASK) != 0;
+ GdkModifierType state;
+
+ gdk_event_get_state ((GdkEvent *) event, &state);
+
+ return (state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) != 0;
}
static void
@@ -2871,19 +2881,20 @@ keyboard_up (NautilusCanvasContainer *container,
static void
keyboard_space (NautilusCanvasContainer *container,
- GdkEventKey *event)
+ GdkEventKey *gdk_event)
{
+ g_autoptr (EelEvent) event = NULL;
+ GdkModifierType state;
NautilusCanvasIcon *icon;
- if (!has_selection (container) &&
- container->details->focus != NULL)
+ event = eel_event_new_from_gdk_event ((GdkEvent *) gdk_event);
+ state = eel_event_get_state (event);
+
+ if (!has_selection (container) && container->details->focus != NULL)
{
- keyboard_move_to (container,
- container->details->focus,
- NULL, NULL);
+ keyboard_move_to (container, container->details->focus, NULL, NULL);
}
- else if ((event->state & GDK_CONTROL_MASK) != 0 &&
- (event->state & GDK_SHIFT_MASK) == 0)
+ else if ((state & GDK_CONTROL_MASK) != 0 && (state & GDK_SHIFT_MASK) == 0)
{
/* Control-space toggles the selection state of the current icon. */
if (container->details->focus != NULL)
@@ -2914,9 +2925,9 @@ keyboard_space (NautilusCanvasContainer *container,
}
}
}
- else if ((event->state & GDK_SHIFT_MASK) != 0)
+ else if ((state & GDK_SHIFT_MASK) != 0)
{
- activate_selected_items_alternate (container, NULL);
+ activate_selected_items_alternate (container, NULL, event);
}
else
{
@@ -3211,29 +3222,43 @@ style_updated (GtkWidget *widget)
}
}
-static gboolean
-button_press_event (GtkWidget *widget,
- GdkEventButton *event)
+static void
+on_multi_press_gesture_pressed (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ gpointer user_data)
{
+ GtkWidget *widget;
NautilusCanvasContainer *container;
+ GdkEventSequence *sequence;
+ const GdkEvent *gdk_event;
+ guint button;
+ EelEvent *event;
gboolean selection_changed;
- gboolean return_value;
gboolean clicked_on_icon;
+ widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
container = NAUTILUS_CANVAS_CONTAINER (widget);
- container->details->button_down_time = event->time;
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
+ gdk_event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+ event = eel_event_new_from_gdk_event (gdk_event);
+
+ container->details->button_down_time = gdk_event_get_time (gdk_event);
/* Forget about the old keyboard selection now that we've started mousing. */
clear_keyboard_rubberband_start (container);
- if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
+ if (n_press >= 2)
{
/* We use our own double-click detection. */
- return TRUE;
+ eel_canvas_handle_event (EEL_CANVAS (widget), event);
+ return;
}
/* Invoke the canvas event handler and see if an item picks up the event. */
- clicked_on_icon = GTK_WIDGET_CLASS (nautilus_canvas_container_parent_class)->button_press_event (widget,
event);
+ clicked_on_icon = eel_canvas_handle_event (EEL_CANVAS (widget), event);
if (!gtk_widget_has_focus (widget))
{
@@ -3242,13 +3267,12 @@ button_press_event (GtkWidget *widget,
if (clicked_on_icon)
{
- return TRUE;
+ return;
}
clear_focus (container);
- if (event->button == DRAG_BUTTON &&
- event->type == GDK_BUTTON_PRESS)
+ if (button == DRAG_BUTTON)
{
/* Clear the last click icon for double click */
container->details->double_click_icon[1] = container->details->double_click_icon[0];
@@ -3256,7 +3280,7 @@ button_press_event (GtkWidget *widget,
}
/* Button 1 does rubber banding. */
- if (event->button == RUBBERBAND_BUTTON)
+ if (button == RUBBERBAND_BUTTON)
{
if (!button_event_modifies_selection (event))
{
@@ -3268,63 +3292,58 @@ button_press_event (GtkWidget *widget,
}
}
- start_rubberbanding (container, event);
- return TRUE;
+ start_rubberbanding (container, x, y, gdk_event);
+ return;
}
/* Prevent multi-button weirdness such as bug 6181 */
if (container->details->rubberband_info.active)
{
- return TRUE;
+ return;
}
/* Button 2 may be passed to the window manager. */
- if (event->button == MIDDLE_BUTTON)
+ if (button == MIDDLE_BUTTON)
{
selection_changed = unselect_all (container);
if (selection_changed)
{
g_signal_emit (container, signals[SELECTION_CHANGED], 0);
}
- g_signal_emit (widget, signals[MIDDLE_CLICK], 0, event);
- return TRUE;
+ g_signal_emit (widget, signals[MIDDLE_CLICK], 0, gdk_event);
+ return;
}
/* Button 3 does a contextual menu. */
- if (event->button == CONTEXTUAL_MENU_BUTTON)
+ if (button == CONTEXTUAL_MENU_BUTTON)
{
selection_changed = unselect_all (container);
if (selection_changed)
{
g_signal_emit (container, signals[SELECTION_CHANGED], 0);
}
- g_signal_emit (widget, signals[CONTEXT_CLICK_BACKGROUND], 0, event);
- return TRUE;
+ g_signal_emit (widget, signals[CONTEXT_CLICK_BACKGROUND], 0, gdk_event);
+ return;
}
-
- /* Otherwise, we emit a button_press message. */
- g_signal_emit (widget,
- signals[BUTTON_PRESS], 0, event,
- &return_value);
- return return_value;
}
static void
nautilus_canvas_container_did_not_drag (NautilusCanvasContainer *container,
- GdkEventButton *event)
+ EelEvent *event)
{
NautilusCanvasContainerDetails *details;
- gboolean selection_changed;
+ GdkModifierType state;
+ guint button;
static gint64 last_click_time = 0;
static gint click_count = 0;
- gint double_click_time;
- gint64 current_time;
details = container->details;
+ state = eel_event_get_state (event);
+ button = eel_event_get_button (event);
if (details->icon_selected_on_button_down &&
- ((event->state & GDK_CONTROL_MASK) != 0 ||
- (event->state & GDK_SHIFT_MASK) == 0))
+ ((state & GDK_CONTROL_MASK) != 0 ||
+ (state & GDK_SHIFT_MASK) == 0))
{
if (button_event_modifies_selection (event))
{
@@ -3335,22 +3354,26 @@ nautilus_canvas_container_did_not_drag (NautilusCanvasContainer *container,
}
else
{
+ gboolean selection_changed;
+
details->range_selection_base_icon = details->drag_icon;
selection_changed = select_one_unselect_others
(container, details->drag_icon);
if (selection_changed)
{
- g_signal_emit (container,
- signals[SELECTION_CHANGED], 0);
+ g_signal_emit (container, signals[SELECTION_CHANGED], 0);
}
}
}
if (details->drag_icon != NULL &&
- (details->single_click_mode ||
- event->button == MIDDLE_BUTTON))
+ (details->single_click_mode || button == MIDDLE_BUTTON))
{
+ gint double_click_time;
+ gint64 current_time;
+ guint32 event_time;
+
/* Determine click count */
g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container))),
"gtk-double-click-time", &double_click_time,
@@ -3372,9 +3395,10 @@ nautilus_canvas_container_did_not_drag (NautilusCanvasContainer *container,
* the selection or pressing for a very long time, or double clicking.
*/
+ event_time = eel_event_get_time (event);
if (click_count == 0 &&
- event->time - details->button_down_time < MAX_CLICK_TIME &&
+ event_time - details->button_down_time < MAX_CLICK_TIME &&
!button_event_modifies_selection (event))
{
/* It's a tricky UI issue whether this should activate
@@ -3385,9 +3409,9 @@ nautilus_canvas_container_did_not_drag (NautilusCanvasContainer *container,
* NautilusList goes the other way because its "links" seem
* much more link-like.
*/
- if (event->button == MIDDLE_BUTTON)
+ if (button == MIDDLE_BUTTON)
{
- activate_selected_items_alternate (container, NULL);
+ activate_selected_items_alternate (container, NULL, event);
}
else
{
@@ -3441,53 +3465,56 @@ clear_drag_state (NautilusCanvasContainer *container)
container->details->drag_state = DRAG_STATE_INITIAL;
}
-static gboolean
-button_release_event (GtkWidget *widget,
- GdkEventButton *event)
+static void
+on_multi_press_gesture_released (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ gpointer user_data)
{
+ GtkWidget *widget;
NautilusCanvasContainer *container;
NautilusCanvasContainerDetails *details;
+ guint button;
+ GdkEventSequence *sequence;
+ const GdkEvent *gdk_event;
+ g_autoptr (EelEvent) event = NULL;
+ widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
container = NAUTILUS_CANVAS_CONTAINER (widget);
details = container->details;
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
+ gdk_event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
+ event = eel_event_new_from_gdk_event (gdk_event);
- if (event->button == RUBBERBAND_BUTTON && details->rubberband_info.active)
+ if (button == RUBBERBAND_BUTTON && details->rubberband_info.active)
{
- stop_rubberbanding (container, event);
- return TRUE;
+ stop_rubberbanding (container, gdk_event);
+ return;
}
- if (event->button == details->drag_button)
+ if (button == details->drag_button)
{
details->drag_button = 0;
- switch (details->drag_state)
+ if (details->drag_state == DRAG_STATE_MOVE_OR_COPY)
{
- case DRAG_STATE_MOVE_OR_COPY:
+ if (!details->drag_started)
{
- if (!details->drag_started)
- {
- nautilus_canvas_container_did_not_drag (container, event);
- }
- else
- {
- nautilus_canvas_dnd_end_drag (container);
- DEBUG ("Ending drag from canvas container");
- }
+ nautilus_canvas_container_did_not_drag (container, event);
}
- break;
-
- default:
+ else
{
+ nautilus_canvas_dnd_end_drag (container);
+ DEBUG ("Ending drag from canvas container");
}
- break;
}
clear_drag_state (container);
- return TRUE;
}
- return GTK_WIDGET_CLASS (nautilus_canvas_container_parent_class)->button_release_event (widget, event);
+ eel_canvas_handle_event (EEL_CANVAS (widget), event);
}
static int
@@ -3509,13 +3536,19 @@ motion_notify_event (GtkWidget *widget,
{
case DRAG_STATE_MOVE_OR_COPY:
{
+ gdouble x;
+ gdouble y;
+
if (details->drag_started)
{
break;
}
- eel_canvas_window_to_world
- (EEL_CANVAS (container), event->x, event->y, &world_x, &world_y);
+ gdk_event_get_coords ((GdkEvent *) event, &x, &y);
+
+ eel_canvas_window_to_world (EEL_CANVAS (container),
+ x, y,
+ &world_x, &world_y);
if (gtk_drag_check_threshold (widget,
details->drag_x,
@@ -3592,11 +3625,16 @@ key_press_event (GtkWidget *widget,
{
NautilusCanvasContainer *container;
gboolean handled;
+ guint keyval;
+ GdkModifierType state;
container = NAUTILUS_CANVAS_CONTAINER (widget);
handled = FALSE;
- switch (event->keyval)
+ gdk_event_get_keyval ((GdkEvent *) event, &keyval);
+ gdk_event_get_state ((GdkEvent *) event, &state);
+
+ switch (keyval)
{
case GDK_KEY_Home:
case GDK_KEY_KP_Home:
@@ -3618,7 +3656,7 @@ key_press_event (GtkWidget *widget,
case GDK_KEY_KP_Left:
{
/* Don't eat Alt-Left, as that is used for history browsing */
- if ((event->state & GDK_MOD1_MASK) == 0)
+ if ((state & GDK_MOD1_MASK) == 0)
{
keyboard_left (container, event);
handled = TRUE;
@@ -3630,7 +3668,7 @@ key_press_event (GtkWidget *widget,
case GDK_KEY_KP_Up:
{
/* Don't eat Alt-Up, as that is used for alt-shift-Up */
- if ((event->state & GDK_MOD1_MASK) == 0)
+ if ((state & GDK_MOD1_MASK) == 0)
{
keyboard_up (container, event);
handled = TRUE;
@@ -3642,7 +3680,7 @@ key_press_event (GtkWidget *widget,
case GDK_KEY_KP_Right:
{
/* Don't eat Alt-Right, as that is used for history browsing */
- if ((event->state & GDK_MOD1_MASK) == 0)
+ if ((state & GDK_MOD1_MASK) == 0)
{
keyboard_right (container, event);
handled = TRUE;
@@ -3654,7 +3692,7 @@ key_press_event (GtkWidget *widget,
case GDK_KEY_KP_Down:
{
/* Don't eat Alt-Down, as that is used for Open */
- if ((event->state & GDK_MOD1_MASK) == 0)
+ if ((state & GDK_MOD1_MASK) == 0)
{
keyboard_down (container, event);
handled = TRUE;
@@ -3675,7 +3713,7 @@ key_press_event (GtkWidget *widget,
* background popup even if something is selected.
* The other cases are handled by the "popup-menu" GtkWidget signal.
*/
- if (event->state & GDK_CONTROL_MASK)
+ if (state & GDK_CONTROL_MASK)
{
handled = handle_popups (container, (GdkEvent *) event,
"context_click_background");
@@ -3686,7 +3724,7 @@ key_press_event (GtkWidget *widget,
case GDK_KEY_v:
{
/* Eat Control + v to not enable type ahead */
- if ((event->state & GDK_CONTROL_MASK) != 0)
+ if ((state & GDK_CONTROL_MASK) != 0)
{
handled = TRUE;
}
@@ -3780,16 +3818,6 @@ nautilus_canvas_container_class_init (NautilusCanvasContainerClass *class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- signals[BUTTON_PRESS]
- = g_signal_new ("button-press",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NautilusCanvasContainerClass,
- button_press),
- NULL, NULL,
- g_cclosure_marshal_generic,
- G_TYPE_BOOLEAN, 1,
- GDK_TYPE_EVENT);
signals[ACTIVATE]
= g_signal_new ("activate",
G_TYPE_FROM_CLASS (class),
@@ -3807,9 +3835,10 @@ nautilus_canvas_container_class_init (NautilusCanvasContainerClass *class)
G_STRUCT_OFFSET (NautilusCanvasContainerClass,
activate_alternate),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 2,
+ G_TYPE_POINTER,
+ EEL_TYPE_EVENT);
signals[ACTIVATE_PREVIEWER]
= g_signal_new ("activate-previewer",
G_TYPE_FROM_CLASS (class),
@@ -4029,8 +4058,6 @@ nautilus_canvas_container_class_init (NautilusCanvasContainerClass *class)
widget_class->get_preferred_height = get_prefered_height;
widget_class->realize = realize;
widget_class->unrealize = unrealize;
- widget_class->button_press_event = button_press_event;
- widget_class->button_release_event = button_release_event;
widget_class->motion_notify_event = motion_notify_event;
widget_class->key_press_event = key_press_event;
widget_class->style_updated = style_updated;
@@ -4184,6 +4211,20 @@ nautilus_canvas_container_init (NautilusCanvasContainer *container)
setup_prefs = TRUE;
}
+
+ details->multi_press_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (container));
+
+#if 0
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (details->multi_press_gesture),
+ GTK_PHASE_CAPTURE);
+#endif
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (details->multi_press_gesture),
+ 0);
+
+ g_signal_connect (details->multi_press_gesture, "pressed",
+ G_CALLBACK (on_multi_press_gesture_pressed), NULL);
+ g_signal_connect (details->multi_press_gesture, "released",
+ G_CALLBACK (on_multi_press_gesture_released), NULL);
}
typedef struct
@@ -4195,11 +4236,14 @@ typedef struct
static gboolean
handle_canvas_double_click (NautilusCanvasContainer *container,
NautilusCanvasIcon *icon,
- GdkEventButton *event)
+ EelEvent *event)
{
NautilusCanvasContainerDetails *details;
+ guint button;
+
+ button = eel_event_get_button (event);
- if (event->button != DRAG_BUTTON)
+ if (button != DRAG_BUTTON)
{
return FALSE;
}
@@ -4232,33 +4276,37 @@ handle_canvas_double_click (NautilusCanvasContainer *container,
static gboolean
handle_canvas_button_press (NautilusCanvasContainer *container,
NautilusCanvasIcon *icon,
- GdkEventButton *event)
+ EelEvent *event)
{
NautilusCanvasContainerDetails *details;
+ GdkEventType event_type;
+ guint button;
+ GdkModifierType state;
details = container->details;
-
- if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
+ event_type = eel_event_get_event_type (event);
+ if (event_type == GDK_2BUTTON_PRESS || event_type == GDK_3BUTTON_PRESS)
{
return TRUE;
}
+ button = eel_event_get_button (event);
+ state = eel_event_get_state (event);
- if (event->button != DRAG_BUTTON
- && event->button != CONTEXTUAL_MENU_BUTTON
- && event->button != DRAG_MENU_BUTTON)
+ if (button != DRAG_BUTTON
+ && button != CONTEXTUAL_MENU_BUTTON
+ && button != DRAG_MENU_BUTTON)
{
return TRUE;
}
- if ((event->button == DRAG_BUTTON) &&
- event->type == GDK_BUTTON_PRESS)
+ if (button == DRAG_BUTTON && event_type == GDK_BUTTON_PRESS)
{
/* The next double click has to be on this icon */
details->double_click_icon[1] = details->double_click_icon[0];
details->double_click_icon[0] = icon;
details->double_click_button[1] = details->double_click_button[0];
- details->double_click_button[0] = event->button;
+ details->double_click_button[0] = button;
}
if (handle_canvas_double_click (container, icon, event))
@@ -4269,13 +4317,13 @@ handle_canvas_button_press (NautilusCanvasContainer *container,
return TRUE;
}
- if (event->button == DRAG_BUTTON
- || event->button == DRAG_MENU_BUTTON)
+ if (button == DRAG_BUTTON || button == DRAG_MENU_BUTTON)
{
- details->drag_button = event->button;
+ details->drag_button = button;
details->drag_icon = icon;
- details->drag_x = event->x;
- details->drag_y = event->y;
+
+ eel_event_get_coords (event, &details->drag_x, &details->drag_y);
+
details->drag_state = DRAG_STATE_MOVE_OR_COPY;
details->drag_started = FALSE;
}
@@ -4285,8 +4333,8 @@ handle_canvas_button_press (NautilusCanvasContainer *container,
*/
details->icon_selected_on_button_down = icon->is_selected;
- if ((event->button == DRAG_BUTTON || event->button == MIDDLE_BUTTON) &&
- (event->state & GDK_SHIFT_MASK) != 0)
+ if ((button == DRAG_BUTTON || button == MIDDLE_BUTTON) &&
+ (state & GDK_SHIFT_MASK) != 0)
{
NautilusCanvasIcon *start_icon;
@@ -4299,7 +4347,7 @@ handle_canvas_button_press (NautilusCanvasContainer *container,
details->range_selection_base_icon = icon;
}
if (select_range (container, start_icon, icon,
- (event->state & GDK_CONTROL_MASK) == 0))
+ (state & GDK_CONTROL_MASK) == 0))
{
g_signal_emit (container,
signals[SELECTION_CHANGED], 0);
@@ -4324,13 +4372,14 @@ handle_canvas_button_press (NautilusCanvasContainer *container,
}
}
- if (event->button == CONTEXTUAL_MENU_BUTTON)
+ if (button == CONTEXTUAL_MENU_BUTTON)
{
clear_drag_state (container);
g_signal_emit (container,
signals[CONTEXT_CLICK_SELECTION], 0,
- event);
+ /* Handlers expect a GdkEvent, not EelEvent. */
+ gtk_get_current_event ());
}
@@ -4339,65 +4388,55 @@ handle_canvas_button_press (NautilusCanvasContainer *container,
static int
item_event_callback (EelCanvasItem *item,
- GdkEvent *event,
+ EelEvent *event,
gpointer data)
{
NautilusCanvasContainer *container;
NautilusCanvasIcon *icon;
- GdkEventButton *event_button;
+ GdkEventType event_type;
container = NAUTILUS_CANVAS_CONTAINER (data);
-
icon = NAUTILUS_CANVAS_ITEM (item)->user_data;
+
g_assert (icon != NULL);
- event_button = &event->button;
+ event_type = eel_event_get_event_type (event);
+ if (event_type == GDK_MOTION_NOTIFY)
+ {
+ return GDK_EVENT_PROPAGATE;
+ }
+ if (event_type == GDK_BUTTON_PRESS)
+ {
+ container->details->double_clicked = FALSE;
- switch (event->type)
+ return handle_canvas_button_press (container, icon, event);
+ }
+ if (event_type == GDK_BUTTON_RELEASE)
{
- case GDK_MOTION_NOTIFY:
- {
- return FALSE;
- }
+ guint button;
- case GDK_BUTTON_PRESS:
+ button = eel_event_get_button (event);
+ if (button == DRAG_BUTTON && container->details->double_clicked)
{
- container->details->double_clicked = FALSE;
- if (handle_canvas_button_press (container, icon, event_button))
+ GdkModifierType state;
+
+ state = eel_event_get_state (event);
+
+ if (!button_event_modifies_selection (event))
{
- /* Stop the event from being passed along further. Returning
- * TRUE ain't enough.
- */
- return TRUE;
+ activate_selected_items (container);
}
- return FALSE;
- }
-
- case GDK_BUTTON_RELEASE:
- {
- if (event_button->button == DRAG_BUTTON
- && container->details->double_clicked)
+ else if ((state & GDK_CONTROL_MASK) == 0 &&
+ (state & GDK_SHIFT_MASK) != 0)
{
- if (!button_event_modifies_selection (event_button))
- {
- activate_selected_items (container);
- }
- else if ((event_button->state & GDK_CONTROL_MASK) == 0 &&
- (event_button->state & GDK_SHIFT_MASK) != 0)
- {
- activate_selected_items_alternate (container, icon);
- }
+ activate_selected_items_alternate (container, icon, event);
}
- /* fall through */
}
-
- default:
- {
- container->details->double_clicked = FALSE;
- return FALSE;
- }
- break;
}
+
+ container->details->double_clicked = FALSE;
+
+ return GDK_EVENT_PROPAGATE;
}
GtkWidget *
@@ -4752,9 +4791,10 @@ preview_selected_items (NautilusCanvasContainer *container)
static void
activate_selected_items_alternate (NautilusCanvasContainer *container,
- NautilusCanvasIcon *icon)
+ NautilusCanvasIcon *icon,
+ EelEvent *event)
{
- GList *selection;
+ g_autoptr (GList) selection = NULL;
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container));
@@ -4766,13 +4806,14 @@ activate_selected_items_alternate (NautilusCanvasContainer *container,
{
selection = nautilus_canvas_container_get_selection (container);
}
+
if (selection != NULL)
{
g_signal_emit (container,
signals[ACTIVATE_ALTERNATE], 0,
- selection);
+ selection,
+ event);
}
- g_list_free (selection);
}
static NautilusIconInfo *
diff --git a/src/nautilus-canvas-item.c b/src/nautilus-canvas-item.c
index 42181e8c4..94f505b1c 100644
--- a/src/nautilus-canvas-item.c
+++ b/src/nautilus-canvas-item.c
@@ -1455,68 +1455,91 @@ get_label_layout (PangoLayout **layout_cache,
/* handle events */
-static int
-nautilus_canvas_item_event (EelCanvasItem *item,
- GdkEvent *event)
+static gboolean
+nautilus_canvas_item_enter_notify_event (EelCanvasItem *item,
+ EelEvent *event)
{
NautilusCanvasItem *canvas_item;
- GdkCursor *cursor;
- GdkWindow *cursor_window;
canvas_item = NAUTILUS_CANVAS_ITEM (item);
- cursor_window = ((GdkEventAny *) event)->window;
- switch (event->type)
+ if (!canvas_item->details->is_prelit)
{
- case GDK_ENTER_NOTIFY:
+ canvas_item->details->is_prelit = TRUE;
+ nautilus_canvas_item_invalidate_label_size (canvas_item);
+ eel_canvas_item_request_update (item);
+ eel_canvas_item_send_behind (item,
+ NAUTILUS_CANVAS_CONTAINER
(item->canvas)->details->rubberband_info.selection_rectangle);
+
+ /* show a hand cursor */
+ if (in_single_click_mode ())
{
- if (!canvas_item->details->is_prelit)
- {
- canvas_item->details->is_prelit = TRUE;
- nautilus_canvas_item_invalidate_label_size (canvas_item);
- eel_canvas_item_request_update (item);
- eel_canvas_item_send_behind (item,
- NAUTILUS_CANVAS_CONTAINER
(item->canvas)->details->rubberband_info.selection_rectangle);
-
- /* show a hand cursor */
- if (in_single_click_mode ())
- {
- cursor = gdk_cursor_new_for_display (gdk_display_get_default (),
- GDK_HAND2);
- gdk_window_set_cursor (cursor_window, cursor);
- g_object_unref (cursor);
+ GdkDisplay *display;
+ g_autoptr (GdkCursor) cursor = NULL;
+ GdkWindow *window;
- canvas_item->details->cursor_window = g_object_ref (cursor_window);
- }
- }
- return TRUE;
- }
+ display = gdk_display_get_default ();
+ cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+ window = eel_event_get_window (event);
- case GDK_LEAVE_NOTIFY:
- {
- if (canvas_item->details->is_prelit
- || canvas_item->details->is_highlighted_for_drop)
- {
- /* When leaving, turn of the prelight state and the
- * higlighted for drop. The latter gets turned on
- * by the drag&drop motion callback.
- */
- canvas_item->details->is_prelit = FALSE;
- canvas_item->details->is_highlighted_for_drop = FALSE;
- nautilus_canvas_item_invalidate_label_size (canvas_item);
- eel_canvas_item_request_update (item);
-
- /* show default cursor */
- gdk_window_set_cursor (cursor_window, NULL);
- g_clear_object (&canvas_item->details->cursor_window);
- }
- return TRUE;
+ gdk_window_set_cursor (window, cursor);
+
+ canvas_item->details->cursor_window = g_object_ref (window);
}
+ }
- default:
- /* Don't eat up other events; canvas container might use them. */
- return FALSE;
+ return GDK_EVENT_STOP;
+}
+
+static gboolean
+nautilus_canvas_item_leave_notify_event (EelCanvasItem *item,
+ EelEvent *event)
+{
+ NautilusCanvasItem *canvas_item;
+
+ canvas_item = NAUTILUS_CANVAS_ITEM (item);
+
+ if (canvas_item->details->is_prelit
+ || canvas_item->details->is_highlighted_for_drop)
+ {
+ GdkWindow *window;
+
+ window = eel_event_get_window (event);
+
+ /* When leaving, turn of the prelight state and the
+ * higlighted for drop. The latter gets turned on
+ * by the drag&drop motion callback.
+ */
+ canvas_item->details->is_prelit = FALSE;
+ canvas_item->details->is_highlighted_for_drop = FALSE;
+ nautilus_canvas_item_invalidate_label_size (canvas_item);
+ eel_canvas_item_request_update (item);
+
+ /* show default cursor */
+ gdk_window_set_cursor (window, NULL);
+ g_clear_object (&canvas_item->details->cursor_window);
}
+
+ return GDK_EVENT_STOP;
+}
+
+static gboolean
+nautilus_canvas_item_event (EelCanvasItem *item,
+ EelEvent *event)
+{
+ GdkEventType event_type;
+
+ event_type = eel_event_get_event_type (event);
+ if (event_type == GDK_ENTER_NOTIFY)
+ {
+ return nautilus_canvas_item_enter_notify_event (item, event);
+ }
+ if (event_type == GDK_LEAVE_NOTIFY)
+ {
+ return nautilus_canvas_item_leave_notify_event (item, event);
+ }
+
+ return GDK_EVENT_PROPAGATE;
}
static gboolean
diff --git a/src/nautilus-canvas-private.h b/src/nautilus-canvas-private.h
index e60e86299..2e19e4e27 100644
--- a/src/nautilus-canvas-private.h
+++ b/src/nautilus-canvas-private.h
@@ -151,7 +151,8 @@ struct NautilusCanvasContainerDetails {
/* Drag state. Valid only if drag_button is non-zero. */
guint drag_button;
NautilusCanvasIcon *drag_icon;
- int drag_x, drag_y;
+ gdouble drag_x;
+ gdouble drag_y;
DragState drag_state;
gboolean drag_started;
@@ -202,6 +203,8 @@ struct NautilusCanvasContainerDetails {
eel_boolean_bit is_populating_container : 1;
eel_boolean_bit needs_resort : 1;
eel_boolean_bit selection_needs_resort : 1;
+
+ GtkGesture *multi_press_gesture;
};
/* Private functions shared by mutiple files. */
diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c
index 6674433d2..11e2551fb 100644
--- a/src/nautilus-canvas-view.c
+++ b/src/nautilus-canvas-view.c
@@ -1054,36 +1054,35 @@ canvas_container_activate_previewer_callback (NautilusCanvasContainer *container
static void
canvas_container_activate_alternate_callback (NautilusCanvasContainer *container,
GList *file_list,
+ EelEvent *event,
NautilusCanvasView *canvas_view)
{
- GdkEvent *event;
- GdkEventButton *button_event;
- GdkEventKey *key_event;
- gboolean open_in_tab, open_in_window;
+ GdkEventType event_type;
+ GdkModifierType state;
+ gboolean open_in_tab;
+ gboolean open_in_window;
NautilusWindowOpenFlags flags;
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
- flags = 0;
- event = gtk_get_current_event ();
+ event_type = eel_event_get_event_type (event);
+ state = eel_event_get_state (event);
open_in_tab = FALSE;
open_in_window = FALSE;
+ flags = 0;
- if (event->type == GDK_BUTTON_PRESS ||
- event->type == GDK_BUTTON_RELEASE ||
- event->type == GDK_2BUTTON_PRESS ||
- event->type == GDK_3BUTTON_PRESS)
+ if (event_type == GDK_BUTTON_PRESS ||
+ event_type == GDK_BUTTON_RELEASE ||
+ event_type == GDK_2BUTTON_PRESS ||
+ event_type == GDK_3BUTTON_PRESS)
{
- button_event = (GdkEventButton *) event;
- open_in_window = ((button_event->state & GDK_SHIFT_MASK) != 0);
+ open_in_window = (state & GDK_SHIFT_MASK) != 0;
open_in_tab = !open_in_window;
}
- else if (event->type == GDK_KEY_PRESS ||
- event->type == GDK_KEY_RELEASE)
+ else if (event_type == GDK_KEY_PRESS || event_type == GDK_KEY_RELEASE)
{
- key_event = (GdkEventKey *) event;
- open_in_tab = ((key_event->state & GDK_SHIFT_MASK) != 0);
+ open_in_tab = (state & GDK_SHIFT_MASK) != 0;
}
if (open_in_tab)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]