Code

Implementation of snap delay mechanism for guides
authorDiederik van Lierop <mailat-signdiedenrezidotnl>
Sun, 14 Feb 2010 08:18:22 +0000 (09:18 +0100)
committerDiederik van Lierop <mailat-signdiedenrezidotnl>
Sun, 14 Feb 2010 08:18:22 +0000 (09:18 +0100)
src/desktop-events.cpp
src/event-context.cpp
src/event-context.h
src/knot.cpp
src/rect-context.cpp
src/ui/tool/control-point.cpp

index cea478f85847c35d149ef913d8e6d63b32b26856..7cf075f269a2e98505954f716b0b74967a9f5871 100644 (file)
@@ -196,7 +196,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 // GDK_BUTTON_PRESS, we should not set it back to inactive here. That must be
                 // done by the context.
             }
-       default:
+    default:
             break;
     }
 
@@ -205,11 +205,17 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
 
 int sp_dt_hruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
 {
+    if (event->type == GDK_MOTION_NOTIFY) {
+        sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, DelayedSnapEvent::GUIDE_HRULER);
+    }
     return sp_dt_ruler_event(widget, event, dtw, true);
 }
 
 int sp_dt_vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
 {
+    if (event->type == GDK_MOTION_NOTIFY) {
+        sp_event_context_snap_delay_handler(dtw->desktop->event_context, (gpointer) widget, (gpointer) dtw, (GdkEventMotion *)event, DelayedSnapEvent::GUIDE_VRULER);
+    }
     return sp_dt_ruler_event(widget, event, dtw, false);
 }
 
@@ -230,7 +236,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
     SPDesktop *desktop = static_cast<SPDesktop*>(gtk_object_get_data(GTK_OBJECT(item->canvas), "SPDesktop"));
 
     switch (event->type) {
-       case GDK_2BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
             if (event->button.button == 1) {
                 drag_type = SP_DRAG_NONE;
                 sp_event_context_discard_delayed_snap_event(desktop->event_context);
@@ -239,7 +245,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                 ret = TRUE;
             }
             break;
-       case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_PRESS:
             if (event->button.button == 1) {
                 Geom::Point const event_w(event->button.x, event->button.y);
                 Geom::Point const event_dt(desktop->w2d(event_w));
@@ -279,6 +285,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                                            event->motion.y);
                 Geom::Point motion_dt(desktop->w2d(motion_w));
 
+                sp_event_context_snap_delay_handler(desktop->event_context, (gpointer) item, data, (GdkEventMotion *)event, DelayedSnapEvent::GUIDE_HANDLER);
+
                 // This is for snapping while dragging existing guidelines. New guidelines,
                 // which are dragged off the ruler, are being snapped in sp_dt_ruler_event
                 SnapManager &m = desktop->namedview->snap_manager;
@@ -321,7 +329,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     case SP_DRAG_MOVE_ORIGIN:
                     {
                         sp_guide_moveto(*guide, motion_dt, false);
-                       break;
+                        break;
                     }
                     case SP_DRAG_NONE:
                         g_assert_not_reached();
@@ -344,14 +352,14 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     SnapManager &m = desktop->namedview->snap_manager;
                     m.setup(desktop, true, NULL, NULL, guide);
                     if (drag_type == SP_DRAG_MOVE_ORIGIN) {
-                       // If we snap in guideConstrainedSnap() below, then motion_dt will
+                        // If we snap in guideConstrainedSnap() below, then motion_dt will
                         // be forced to be on the guide. If we don't snap however, then
                         // the origin should still be constrained to the guide. So let's
                         // do that explicitly first:
-                       Geom::Line line(guide->point_on_line, guide->angle());
+                        Geom::Line line(guide->point_on_line, guide->angle());
                         Geom::Coord t = line.nearestPoint(event_dt);
                         event_dt = line.pointAt(t);
-                       m.guideConstrainedSnap(event_dt, *guide);
+                        m.guideConstrainedSnap(event_dt, *guide);
                     } else {
                         m.guideFreeSnap(event_dt, guide->normal_to_line, drag_type);
                     }
@@ -380,8 +388,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                             }
                             case SP_DRAG_MOVE_ORIGIN:
                             {
-                               sp_guide_moveto(*guide, event_dt, true);
-                               break;
+                                sp_guide_moveto(*guide, event_dt, true);
+                                break;
                             }
                             case SP_DRAG_NONE:
                                 g_assert_not_reached();
@@ -397,12 +405,12 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                         sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
                                      _("Delete guide"));
                     }
+                    sp_event_context_discard_delayed_snap_event(desktop->event_context);
                     moved = false;
                     desktop->set_coordinate_status(from_2geom(event_dt));
                     desktop->setPosition (from_2geom(event_dt));
                 }
                 drag_type = SP_DRAG_NONE;
-                sp_event_context_discard_delayed_snap_event(desktop->event_context);
                 sp_canvas_item_ungrab(item, event->button.time);
                 ret=TRUE;
             }
@@ -444,6 +452,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     sp_guide_remove(guide);
                     sp_document_done(doc, SP_VERB_NONE, _("Delete guide"));
                     ret = TRUE;
+                    sp_event_context_discard_delayed_snap_event(desktop->event_context);
                     break;
                 }
                 case GDK_Shift_L:
index 77c10765bdb37e014c4a29a5f784024bfe1a48f7..397ec6b80ae9019dc1f35de7752e9f9bdeb5c01e 100644 (file)
@@ -43,6 +43,8 @@
 #include "shortcuts.h"
 #include "desktop.h"
 #include "desktop-handles.h"
+#include "desktop-events.h"
+#include "widgets/desktop-widget.h"
 #include "sp-namedview.h"
 #include "selection.h"
 #include "file.h"
@@ -59,6 +61,7 @@
 #include "lpe-tool-context.h"
 #include "ui/tool/control-point.h"
 #include "shape-editor.h"
+#include "sp-guide.h"
 
 static void sp_event_context_class_init(SPEventContextClass *klass);
 static void sp_event_context_init(SPEventContext *event_context);
@@ -137,6 +140,7 @@ static void sp_event_context_init(SPEventContext *event_context) {
     event_context->space_panning = false;
     event_context->shape_editor = NULL;
     event_context->_delayed_snap_event = NULL;
+    event_context->_dse_callback_in_process = false;
 }
 
 /**
@@ -902,7 +906,8 @@ void sp_event_context_deactivate(SPEventContext *ec) {
  * Calls virtual root_handler(), the main event handling function.
  */
 gint sp_event_context_root_handler(SPEventContext * event_context,
-        GdkEvent * event) {
+        GdkEvent * event)
+{
     switch (event->type) {
     case GDK_MOTION_NOTIFY:
         sp_event_context_snap_delay_handler(event_context, NULL, NULL,
@@ -931,12 +936,8 @@ gint sp_event_context_root_handler(SPEventContext * event_context,
     return sp_event_context_virtual_root_handler(event_context, event);
 }
 
-gint sp_event_context_virtual_root_handler(SPEventContext * event_context,
-        GdkEvent * event) {
-    gint
-            ret =
-                    ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->root_handler(
-                            event_context, event);
+gint sp_event_context_virtual_root_handler(SPEventContext * event_context, GdkEvent * event) {
+    gint ret = ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->root_handler(event_context, event);
     set_event_location(event_context->desktop, event);
     return ret;
 }
@@ -948,7 +949,7 @@ gint sp_event_context_item_handler(SPEventContext * event_context,
         SPItem * item, GdkEvent * event) {
     switch (event->type) {
     case GDK_MOTION_NOTIFY:
-        sp_event_context_snap_delay_handler(event_context, item, NULL, (GdkEventMotion *) event, DelayedSnapEvent::EVENTCONTEXT_ITEM_HANDLER);
+        sp_event_context_snap_delay_handler(event_context, (gpointer) item, NULL, (GdkEventMotion *) event, DelayedSnapEvent::EVENTCONTEXT_ITEM_HANDLER);
         break;
     case GDK_BUTTON_RELEASE:
         if (event_context->_delayed_snap_event) {
@@ -970,12 +971,8 @@ gint sp_event_context_item_handler(SPEventContext * event_context,
     return sp_event_context_virtual_item_handler(event_context, item, event);
 }
 
-gint sp_event_context_virtual_item_handler(SPEventContext * event_context,
-        SPItem * item, GdkEvent * event) {
-    gint
-            ret =
-                    ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->item_handler(
-                            event_context, item, event);
+gint sp_event_context_virtual_item_handler(SPEventContext * event_context, SPItem * item, GdkEvent * event) {
+    gint ret = ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->item_handler(event_context, item, event);
 
     if (!ret) {
         ret = sp_event_context_virtual_root_handler(event_context, event);
@@ -1156,12 +1153,28 @@ void event_context_print_event_info(GdkEvent *event, bool print_return) {
     }
 }
 
+/**
+ * \brief Analyses the current event, calculates the mouse speed, turns snapping off (temporarily) if the
+ * mouse speed is above a threshold, and stores the current event such that it can be re-triggered when needed
+ * (re-triggering is controlled by a watchdog timer)
+ *
+ * \param ec Pointer to the event context
+ * \param dse_item Pointer that store a reference to a canvas or to an item
+ * \param dse_item2 Another pointer, storing a reference to a knot or controlpoint
+ * \param event Pointer to the motion event
+ * \param origin Identifier (enum) specifying where the delay (and the call to this method) were initiated
+ */
 void sp_event_context_snap_delay_handler(SPEventContext *ec,
-        SPItem* const item, SPKnot* const knot, GdkEventMotion *event,
-        DelayedSnapEvent::DelayedSnapEventOrigin origin) {
+        gpointer const dse_item, gpointer const dse_item2, GdkEventMotion *event,
+        DelayedSnapEvent::DelayedSnapEventOrigin origin)
+{
     static guint32 prev_time;
     static boost::optional<Geom::Point> prev_pos;
 
+    if (ec->_dse_callback_in_process) {
+        return;
+    }
+
     // Snapping occurs when dragging with the left mouse button down, or when hovering e.g. in the pen tool with left mouse button up
     bool const c1 = event->state & GDK_BUTTON2_MASK; // We shouldn't hold back any events when other mouse buttons have been
     bool const c2 = event->state & GDK_BUTTON3_MASK; // pressed, e.g. when scrolling with the middle mouse button; if we do then
@@ -1199,7 +1212,7 @@ void sp_event_context_snap_delay_handler(SPEventContext *ec,
                 // now, just in case there's no future motion event that drops under the speed limit (when
                 // stopping abruptly)
                 delete ec->_delayed_snap_event;
-                ec->_delayed_snap_event = new DelayedSnapEvent(ec, item, knot,
+                ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
                         event, origin); // watchdog is reset, i.e. pushed forward in time
                 // If the watchdog expires before a new motion event is received, we will snap (as explained
                 // above). This means however that when the timer is too short, we will always snap and that the
@@ -1211,14 +1224,14 @@ void sp_event_context_snap_delay_handler(SPEventContext *ec,
                 // snap, and set a new watchdog again.
                 if (ec->_delayed_snap_event == NULL) { // no watchdog has been set
                     // it might have already expired, so we'll set a new one; the snapping frequency will be limited this way
-                    ec->_delayed_snap_event = new DelayedSnapEvent(ec, item,
-                            knot, event, origin);
+                    ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item,
+                            dse_item2, event, origin);
                 } // else: watchdog has been set before and we'll wait for it to expire
             }
         } else {
             // This is the first GDK_MOTION_NOTIFY event, so postpone snapping and set the watchdog
             g_assert(ec->_delayed_snap_event == NULL);
-            ec->_delayed_snap_event = new DelayedSnapEvent(ec, item, knot,
+            ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
                     event, origin);
         }
 
@@ -1227,6 +1240,10 @@ void sp_event_context_snap_delay_handler(SPEventContext *ec,
     }
 }
 
+/**
+ * \brief When the snap delay watchdog timer barks, this method will be called and will re-inject the last motion
+ * event in an appropriate place, with snapping being turned on again
+ */
 gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
     // Snap NOW! For this the "postponed" flag will be reset and the last motion event will be repeated
     DelayedSnapEvent *dse = reinterpret_cast<DelayedSnapEvent*> (data);
@@ -1241,24 +1258,27 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
     if (ec == NULL || ec->desktop == NULL) {
         return false;
     }
+    ec->_dse_callback_in_process = true;
 
     SPDesktop *dt = ec->desktop;
     dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
 
+    // Depending on where the delayed snap event originated from, we will inject it back at it's origin
+    // The switch below takes care of that and prepares the relevant parameters
     switch (dse->getOrigin()) {
     case DelayedSnapEvent::EVENTCONTEXT_ROOT_HANDLER:
         sp_event_context_virtual_root_handler(ec, dse->getEvent());
         break;
     case DelayedSnapEvent::EVENTCONTEXT_ITEM_HANDLER: {
         SPItem* item = NULL;
-        item = dse->getItem();
+        item = SP_ITEM(dse->getItem());
         if (item && SP_IS_ITEM(item)) {
             sp_event_context_virtual_item_handler(ec, item, dse->getEvent());
         }
     }
         break;
     case DelayedSnapEvent::KNOT_HANDLER: {
-        SPKnot* knot = dse->getKnot();
+        SPKnot* knot = SP_KNOT(dse->getItem2());
         if (knot && SP_IS_KNOT(knot)) {
             sp_knot_handler_request_position(dse->getEvent(), knot);
         }
@@ -1266,10 +1286,35 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
         break;
     case DelayedSnapEvent::CONTROL_POINT_HANDLER: {
         using Inkscape::UI::ControlPoint;
-        ControlPoint *point = reinterpret_cast<ControlPoint*> (dse->getKnot());
+        ControlPoint *point = reinterpret_cast<ControlPoint*> (dse->getItem2());
         point->_eventHandler(dse->getEvent());
     }
         break;
+    case DelayedSnapEvent::GUIDE_HANDLER: {
+        gpointer item = dse->getItem();
+        gpointer item2 = dse->getItem2();
+        if (item && item2) {
+            g_assert(SP_IS_CANVAS_ITEM(item));
+            g_assert(SP_IS_GUIDE(item2));
+            sp_dt_guide_event(SP_CANVAS_ITEM(item), dse->getEvent(), item2);
+        }
+    }
+        break;
+    case DelayedSnapEvent::GUIDE_HRULER:
+    case DelayedSnapEvent::GUIDE_VRULER: {
+        gpointer item = dse->getItem();
+        gpointer item2 = dse->getItem2();
+        if (item && item2) {
+            g_assert(GTK_IS_WIDGET(item));
+            g_assert(SP_IS_DESKTOP_WIDGET(item2));
+            if (dse->getOrigin() == DelayedSnapEvent::GUIDE_HRULER) {
+                sp_dt_hruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
+            } else {
+                sp_dt_vruler_event(GTK_WIDGET(item), dse->getEvent(), SP_DESKTOP_WIDGET(item2));
+            }
+        }
+    }
+        break;
     default:
         g_warning("Origin of snap-delay event has not been defined!;");
         break;
@@ -1278,6 +1323,8 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
     ec->_delayed_snap_event = NULL;
     delete dse;
 
+    ec->_dse_callback_in_process = false;
+
     return FALSE; //Kills the timer and stops it from executing this callback over and over again.
 }
 
index be06f0a3411eb490b57113849fe2d974fdf7986e..76c74e26c63978f60a1de36528dc3ab1fb4dbb69 100644 (file)
@@ -50,11 +50,14 @@ public:
         EVENTCONTEXT_ROOT_HANDLER,
         EVENTCONTEXT_ITEM_HANDLER,
         KNOT_HANDLER,
-        CONTROL_POINT_HANDLER
+        CONTROL_POINT_HANDLER,
+        GUIDE_HANDLER,
+        GUIDE_HRULER,
+        GUIDE_VRULER
     };
 
-    DelayedSnapEvent(SPEventContext *event_context, SPItem* const item, SPKnot* knot, GdkEventMotion const *event, DelayedSnapEvent::DelayedSnapEventOrigin const origin)
-    : _timer_id(0), _event(NULL), _item(item), _knot(knot), _origin(origin), _event_context(event_context)
+    DelayedSnapEvent(SPEventContext *event_context, gpointer const dse_item, gpointer dse_item2, GdkEventMotion const *event, DelayedSnapEvent::DelayedSnapEventOrigin const origin)
+    : _timer_id(0), _event(NULL), _item(dse_item), _item2(dse_item2), _origin(origin), _event_context(event_context)
     {
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000);
@@ -71,19 +74,19 @@ public:
     SPEventContext* getEventContext() {return _event_context;}
     DelayedSnapEventOrigin getOrigin() {return _origin;}
     GdkEvent* getEvent() {return _event;}
-    SPItem* getItem() {return _item;}
-    SPKnot* getKnot() {return _knot;}
+    gpointer getItem() {return _item;}
+    gpointer getItem2() {return _item2;}
 
 private:
     guint _timer_id;
     GdkEvent* _event;
-    SPItem* _item;
-    SPKnot* _knot;
+    gpointer _item;
+    gpointer _item2;
     DelayedSnapEventOrigin _origin;
     SPEventContext* _event_context;
 };
 
-void sp_event_context_snap_delay_handler(SPEventContext *ec, SPItem* const item, SPKnot* const knot, GdkEventMotion *event, DelayedSnapEvent::DelayedSnapEventOrigin origin);
+void sp_event_context_snap_delay_handler(SPEventContext *ec, gpointer const dse_item, gpointer const dse_item2, GdkEventMotion *event, DelayedSnapEvent::DelayedSnapEventOrigin origin);
 
 /**
  * Base class for Event processors.
@@ -124,6 +127,7 @@ struct SPEventContext : public GObject {
     bool space_panning;
 
     DelayedSnapEvent *_delayed_snap_event;
+    bool _dse_callback_in_process;
 };
 
 /**
index cc26653e5f7d996af169d7556412be1a80090c11..04520ed228564c7ab49564ea6673308ca7bf33ea 100644 (file)
@@ -384,7 +384,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
                                      SP_KNOT_DRAGGING,
                                      TRUE);
                 }
-                sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, DelayedSnapEvent::KNOT_HANDLER);
+                sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, (gpointer) knot, (GdkEventMotion *)event, DelayedSnapEvent::KNOT_HANDLER);
                 sp_knot_handler_request_position(event, knot);
                 moved = TRUE;
             }
index a3c3ab0b5a048cab4203b639a457280d474b781e..7ae27c13de4327bd5ef3da72083ebe1af389d586 100644 (file)
@@ -122,15 +122,15 @@ static void sp_rect_context_init(SPRectContext *rect_context)
 static void sp_rect_context_finish(SPEventContext *ec)
 {
     SPRectContext *rc = SP_RECT_CONTEXT(ec);
-       SPDesktop *desktop = ec->desktop;
+    SPDesktop *desktop = ec->desktop;
 
-       sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
-       sp_rect_finish(rc);
+    sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
+    sp_rect_finish(rc);
     rc->sel_changed_connection.disconnect();
 
     if (((SPEventContextClass *) parent_class)->finish) {
-               ((SPEventContextClass *) parent_class)->finish(ec);
-       }
+        ((SPEventContextClass *) parent_class)->finish(ec);
+    }
 }
 
 
@@ -396,14 +396,14 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
             break;
 
         case GDK_Escape:
-               if (dragging) {
-                       dragging = false;
-                       sp_event_context_discard_delayed_snap_event(event_context);
-                       // if drawing, cancel, otherwise pass it up for deselecting
-                       sp_rect_cancel(rc);
-                       ret = TRUE;
-               }
-               break;
+            if (dragging) {
+                dragging = false;
+                sp_event_context_discard_delayed_snap_event(event_context);
+                // if drawing, cancel, otherwise pass it up for deselecting
+                sp_rect_cancel(rc);
+                ret = TRUE;
+            }
+            break;
 
         case GDK_space:
             if (dragging) {
@@ -534,8 +534,8 @@ static void sp_rect_finish(SPRectContext *rc)
     if ( rc->item != NULL ) {
         SPRect *rect = SP_RECT(rc->item);
         if (rect->width.computed == 0 || rect->height.computed == 0) {
-               sp_rect_cancel(rc); // Don't allow the creating of zero sized rectangle, for example when the start and and point snap to the snap grid point
-               return;
+            sp_rect_cancel(rc); // Don't allow the creating of zero sized rectangle, for example when the start and and point snap to the snap grid point
+            return;
         }
 
         SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(rc);
@@ -554,14 +554,14 @@ static void sp_rect_finish(SPRectContext *rc)
 
 static void sp_rect_cancel(SPRectContext *rc)
 {
-       SPDesktop *desktop = SP_EVENT_CONTEXT(rc)->desktop;
+    SPDesktop *desktop = SP_EVENT_CONTEXT(rc)->desktop;
 
-       sp_desktop_selection(desktop)->clear();
-       sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
+    sp_desktop_selection(desktop)->clear();
+    sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
 
     if (rc->item != NULL) {
-       SP_OBJECT(rc->item)->deleteObject();
-       rc->item = NULL;
+        SP_OBJECT(rc->item)->deleteObject();
+        rc->item = NULL;
     }
 
     rc->within_tolerance = false;
index 90d879c66d09bfd1d586164088e2d2689d11e555..a03a8b639ade684bff24c123edceb37d3c8db4ed 100644 (file)
@@ -369,7 +369,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
                 _desktop->scroll_to_point(new_pos);
                 _desktop->set_coordinate_status(_position);
                 sp_event_context_snap_delay_handler(_desktop->event_context, NULL,
-                    reinterpret_cast<SPKnot*>(this), &event->motion,
+                    (gpointer) this, &event->motion,
                     DelayedSnapEvent::CONTROL_POINT_HANDLER);
             }
             return true;