Code

- Move snap delay mechanism to the event context (used to be in SPCanvas)
authordvlierop2 <dvlierop2@users.sourceforge.net>
Sun, 29 Mar 2009 19:12:03 +0000 (19:12 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Sun, 29 Mar 2009 19:12:03 +0000 (19:12 +0000)
- Rename lots of variables and methods to make them easier to understand
- Add snapping to the connector tool

23 files changed:
src/arc-context.cpp
src/box3d-context.cpp
src/connector-context.cpp
src/desktop-events.cpp
src/display/sp-canvas.cpp
src/display/sp-canvas.h
src/event-context.cpp
src/event-context.h
src/gradient-context.cpp
src/knot.cpp
src/knot.h
src/knotholder.cpp
src/node-context.cpp
src/nodepath.cpp
src/pen-context.cpp
src/pencil-context.cpp
src/rect-context.cpp
src/select-context.cpp
src/seltrans.cpp
src/snap.cpp
src/spiral-context.cpp
src/star-context.cpp
src/text-context.cpp

index 115b5534c16137279b291f87c39aaae24e450262..e33985c2296f4b0992b695cee926ccfc2dc30e4a 100644 (file)
@@ -41,6 +41,7 @@
 #include "context-fns.h"
 #include "verbs.h"
 #include "shape-editor.h"
+#include "event-context.h"
 
 #include "arc-context.h"
 
@@ -221,7 +222,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
             if (event->button.button == 1 && !event_context->space_panning) {
 
                 dragging = true;
-                sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                sp_event_context_snap_window_open(event_context);
                 ac->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
 
                 /* Snap center */
@@ -265,7 +266,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
             event_context->xp = event_context->yp = 0;
             if (event->button.button == 1 && !event_context->space_panning) {
                 dragging = false;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the arc
                     sp_arc_finish(ac);
@@ -329,7 +330,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
                         sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                               event->button.time);
                         dragging = false;
-                        sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                        sp_event_context_snap_window_closed(event_context);
                         if (!event_context->within_tolerance) {
                             // we've been dragging, finish the rect
                             sp_arc_finish(ac);
index e8cee44b05f1ab4b90da783c64c8b913ae36e964..5fb85d793686ac94940eb5837e07ba1fb8db238a 100644 (file)
@@ -276,7 +276,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             event_context->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, event->button.state & GDK_CONTROL_MASK);
 
             dragging = true;
-            sp_canvas_set_snap_delay_active(desktop->canvas, true);
+            sp_event_context_snap_window_open(event_context);
 
             /*  */
             Geom::Point button_dt(desktop->w2d(button_w));
@@ -373,7 +373,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
         event_context->xp = event_context->yp = 0;
         if ( event->button.button == 1  && !event_context->space_panning) {
             dragging = false;
-            sp_canvas_set_snap_delay_active(desktop->canvas, false);
+            sp_event_context_snap_window_closed(event_context);
 
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the box
@@ -506,7 +506,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
                 sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                       event->button.time);
                 dragging = false;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the box
                     sp_box3d_finish(bc);
index e364336c48a86bca26949ea5316fc067cbe039d6..c8754972a931039407319df2df8a7cd39f8eae28 100644 (file)
@@ -290,8 +290,6 @@ sp_connector_context_setup(SPEventContext *ec)
     // Make sure we see all enter events for canvas items,
     // even if a mouse button is depressed.
     dt->canvas->gen_all_enter_events = true;
-
-    sp_canvas_set_snap_delay_active(dt->canvas, true);
 }
 
 
@@ -301,6 +299,7 @@ sp_connector_context_finish(SPEventContext *ec)
     SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(ec);
 
     spcc_connector_finish(cc);
+    cc->state = SP_CONNECTOR_CONTEXT_IDLE;
 
     if (((SPEventContextClass *) parent_class)->finish) {
         ((SPEventContextClass *) parent_class)->finish(ec);
@@ -315,8 +314,6 @@ sp_connector_context_finish(SPEventContext *ec)
     // Restore the default event generating behaviour.
     SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(ec);
     desktop->canvas->gen_all_enter_events = false;
-
-    sp_canvas_set_snap_delay_active(desktop->canvas, false);
 }
 
 
@@ -412,6 +409,7 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G
                 {
                     spcc_reset_colors(cc);
                     cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                    sp_event_context_snap_window_closed(event_context);
                 }
                 if (cc->state != SP_CONNECTOR_CONTEXT_IDLE) {
                     // Doing simething else like rerouting.
@@ -427,6 +425,7 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G
                     cc->selection->set(item_ungrouped);
                 }
                 ret = TRUE;
+
             }
             break;
         case GDK_ENTER_NOTIFY:
@@ -463,7 +462,7 @@ sp_connector_context_root_handler(SPEventContext *ec, GdkEvent *event)
             break;
 
         case GDK_MOTION_NOTIFY:
-            ret = connector_handle_motion_notify(cc, event->motion);
+               ret = connector_handle_motion_notify(cc, event->motion);
             break;
 
         case GDK_BUTTON_RELEASE:
@@ -512,6 +511,10 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
         connector_within_tolerance = true;
 
         Geom::Point const event_dt = cc->desktop->w2d(event_w);
+
+        SnapManager &m = cc->desktop->namedview->snap_manager;
+               m.setup(cc->desktop);
+
         switch (cc->state) {
             case SP_CONNECTOR_CONTEXT_STOP:
                 /* This is allowed, if we just cancelled curve */
@@ -529,16 +532,14 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
                     // Test whether we clicked on a connection point
                     cc->sid = conn_pt_handle_test(cc, p);
 
-                    Geom::Point pt2g = to_2geom(p);
+                    sp_event_context_snap_window_open(event_context);
 
                     if (!cc->sid) {
                         // This is the first point, so just snap it to the grid
                         // as there's no other points to go off.
-                        SnapManager &m = cc->desktop->namedview->snap_manager;
-                        m.setup(cc->desktop);
-                        m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE);
+                        m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
                     }
-                    spcc_connector_set_initial_point(cc, from_2geom(pt2g));
+                    spcc_connector_set_initial_point(cc, p);
 
                 }
                 cc->state = SP_CONNECTOR_CONTEXT_DRAGGING;
@@ -548,6 +549,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
             case SP_CONNECTOR_CONTEXT_DRAGGING:
             {
                 // This is the second click of a connector creation.
+               m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
 
                 spcc_connector_set_subsequent_point(cc, p);
                 spcc_connector_finish_segment(cc, p);
@@ -558,6 +560,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
                 }
                 cc_set_active_conn(cc, cc->newconn);
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                sp_event_context_snap_window_closed(event_context);
                 ret = TRUE;
                 break;
             }
@@ -576,12 +579,15 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
             cc_connector_rerouting_finish(cc, &p);
 
             cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+            sp_event_context_snap_window_closed(event_context);
 
             // Don't set ret to TRUE, so we drop through to the
             // parent handler which will open the context menu.
         }
         else if (cc->npoints != 0) {
             spcc_connector_finish(cc);
+            cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+            sp_event_context_snap_window_closed(event_context);
             ret = TRUE;
         }
     }
@@ -619,13 +625,16 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
     /* Find desktop coordinates */
     Geom::Point p = dt->w2d(event_w);
 
+    SnapManager &m = dt->namedview->snap_manager;
+       m.setup(dt);
+
     switch (cc->state) {
         case SP_CONNECTOR_CONTEXT_DRAGGING:
         {
             // This is movement during a connector creation.
-
-            if ( cc->npoints > 0 ) {
-                cc->selection->clear();
+               if ( cc->npoints > 0 ) {
+                       m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+                       cc->selection->clear();
                 spcc_connector_set_subsequent_point(cc, p);
                 ret = TRUE;
             }
@@ -635,6 +644,8 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
         {
             g_assert( SP_IS_PATH(cc->clickeditem));
 
+            m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+
             // Update the hidden path
             Geom::Matrix i2d = sp_item_i2d_affine(cc->clickeditem);
             Geom::Matrix d2i = i2d.inverse();
@@ -676,9 +687,12 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
     SPEventContext *event_context = SP_EVENT_CONTEXT(cc);
     if ( revent.button == 1 && !event_context->space_panning ) {
 
-        SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
+       SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
         SPDocument *doc = sp_desktop_document(desktop);
 
+        SnapManager &m = desktop->namedview->snap_manager;
+               m.setup(desktop);
+
         Geom::Point const event_w(revent.x, revent.y);
 
         /* Find desktop coordinates */
@@ -688,7 +702,9 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
             //case SP_CONNECTOR_CONTEXT_POINT:
             case SP_CONNECTOR_CONTEXT_DRAGGING:
             {
-                if (connector_within_tolerance)
+               m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+
+               if (connector_within_tolerance)
                 {
                     spcc_connector_finish_segment(cc, p);
                     return TRUE;
@@ -703,14 +719,17 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
                 }
                 cc_set_active_conn(cc, cc->newconn);
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                sp_event_context_snap_window_closed(event_context);
                 break;
             }
             case SP_CONNECTOR_CONTEXT_REROUTING:
             {
-                cc_connector_rerouting_finish(cc, &p);
+               m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE);
+               cc_connector_rerouting_finish(cc, &p);
 
                 sp_document_ensure_up_to_date(doc);
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                sp_event_context_snap_window_closed(event_context);
                 return TRUE;
                 break;
             }
@@ -737,6 +756,8 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
         case GDK_KP_Enter:
             if (cc->npoints != 0) {
                 spcc_connector_finish(cc);
+                cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
                 ret = TRUE;
             }
             break;
@@ -751,6 +772,7 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
                 sp_document_undo(doc);
 
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
+                sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
                 desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE,
                         _("Connector endpoint drag cancelled."));
                 ret = TRUE;
@@ -758,6 +780,7 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
             else if (cc->npoints != 0) {
                 // if drawing, cancel, otherwise pass it up for deselecting
                 cc->state = SP_CONNECTOR_CONTEXT_STOP;
+                sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(cc));
                 spcc_reset_colors(cc);
                 ret = TRUE;
             }
@@ -1000,7 +1023,6 @@ spcc_connector_finish(SPConnectorContext *const cc)
         delete cc->newConnRef;
         cc->newConnRef = NULL;
     }
-    cc->state = SP_CONNECTOR_CONTEXT_IDLE;
 }
 
 
@@ -1067,6 +1089,7 @@ endpt_handler(SPKnot */*knot*/, GdkEvent *event, SPConnectorContext *cc)
                 cc->clickedhandle = cc->active_handle;
                 cc_clear_active_conn(cc);
                 cc->state = SP_CONNECTOR_CONTEXT_REROUTING;
+                sp_event_context_snap_window_open(SP_EVENT_CONTEXT(cc));
 
                 // Disconnect from attached shape
                 unsigned ind = (cc->active_handle == cc->endpt_handle[0]) ? 0 : 1;
index f77f3de354c42f9719150951d9ed977567f5b32e..2a87d84a12d2dee8c9790c6d43f128d663c00f61 100644 (file)
@@ -72,7 +72,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
     static bool dragging = false;
     static SPCanvasItem *guide = NULL;
     static Geom::Point normal;
-    static bool snap_delay_temporarily_active = false;
+    static bool snap_window_temporarily_open = false;
     int wx, wy;
 
     SPDesktop *desktop = dtw->desktop;
@@ -89,17 +89,17 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
             if (event->button.button == 1) {
                 dragging = true;
 
-                // FIXME: The snap delay mechanism won't work here, because it has been implemented for the canvas. Dragging
-                // guides off the ruler will send event to the ruler and not to the canvas, which bypasses sp_canvas_motion
+                // FIXME: The snap delay mechanism won't work here, because it has been implemented for the event context. Dragging
+                // guides off the ruler will send event to the ruler and not to the context, which bypasses sp_event_context_snap_delay_handler
                 // The snap manager will not notice the difference, so it'll check if the snap delay has been activated (This check
-                // is only needed for catching coding errors, i.e. to warn if the snap delay has not been implemented properly
+                // is only needed for catching coding errors, i.e. to warn if the snap window has not been implemented properly
                 // in some context)
-                if (desktop->canvas->context_snap_delay_active == false) {
-                                       // A dt_ruler_event might be emitted when dragging a guide of the rulers while drawing a Bezier curve
+                if (desktop->event_context->_snap_window_open == false) {
+                                       // A dt_ruler_event might be emitted when dragging a guide off the rulers while drawing a Bezier curve
                        // In such a situation, we're already in that specific context and the snap delay is already active. We should
                        // not set the snap delay to active again, because that will trigger a similar warning to the one above
-                       sp_canvas_set_snap_delay_active(desktop->canvas, true);
-                       snap_delay_temporarily_active = true;
+                       sp_event_context_snap_window_open(desktop->event_context);
+                       snap_window_temporarily_open = true;
                 }
 
                 Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
@@ -183,9 +183,9 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 dragging = false;
 
                 // See the comments in GDK_BUTTON_PRESS
-                if (snap_delay_temporarily_active) {
-                       sp_canvas_set_snap_delay_active(desktop->canvas, false);
-                       snap_delay_temporarily_active = false;
+                if (snap_window_temporarily_open) {
+                       sp_event_context_snap_window_closed(desktop->event_context);
+                       snap_window_temporarily_open = false;
                 }
 
                 gtk_object_destroy(GTK_OBJECT(guide));
@@ -251,7 +251,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
        case GDK_2BUTTON_PRESS:
             if (event->button.button == 1) {
                 drag_type = SP_DRAG_NONE;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(desktop->event_context);
                 sp_canvas_item_ungrab(item, event->button.time);
                 Inkscape::UI::Dialogs::GuidelinePropertiesDialog::showDialog(guide, desktop);
                 ret = TRUE;
@@ -267,7 +267,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     break;
                 }
 
-                sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                sp_event_context_snap_window_closed(desktop->event_context);
                 double tol = 40.0;
                 Geom::Point const event_w(event->button.x, event->button.y);
                 Geom::Point const event_dt(desktop->w2d(event_w));
@@ -398,7 +398,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     desktop->setPosition (from_2geom(event_dt));
                 }
                 drag_type = SP_DRAG_NONE;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(desktop->event_context);
                 sp_canvas_item_ungrab(item, event->button.time);
                 ret=TRUE;
             }
index 0f9e883ed4376a9db8a9bb700b9e282d381010b2..e0d885d36ba245c517ec026c42ea80486d450c73 100644 (file)
@@ -946,10 +946,6 @@ static void sp_canvas_dirty_rect(SPCanvas* canvas, int nl, int nt, int nr, int n
 static void sp_canvas_mark_rect(SPCanvas* canvas, int nl, int nt, int nr, int nb, uint8_t val);
 static int do_update (SPCanvas *canvas);
 
-static gboolean sp_canvas_snap_watchdog_callback(gpointer data);
-static void sp_canvas_snap_watchdog_set(SPCanvas *canvas, GdkEventMotion *event);
-static void sp_canvas_snap_watchdog_kill(SPCanvas *canvas);
-
 /**
  * Registers the SPCanvas class if necessary, and returns the type ID
  * associated to it.
@@ -1046,10 +1042,6 @@ sp_canvas_init (SPCanvas *canvas)
 #endif // ENABLE_LCMS
 
     canvas->is_scrolling = false;
-
-    canvas->watchdog_id = 0;
-    canvas->watchdog_event = NULL;
-    canvas->context_snap_delay_active = false;
 }
 
 /**
@@ -1288,7 +1280,7 @@ emit_event (SPCanvas *canvas, GdkEvent *event)
         if (!(mask & canvas->grabbed_event_mask)) return FALSE;
     }
 
-    /* Convert to world coordinates -- we have two cases because of diferent
+    /* Convert to world coordinates -- we have two cases because of different
      * offsets of the fields in the event structures.
      */
 
@@ -1497,7 +1489,6 @@ static gint
 sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
 {
     SPCanvas *canvas = SP_CANVAS (widget);
-    SPDesktop *dt = SP_ACTIVE_DESKTOP;
 
     int retval = FALSE;
 
@@ -1532,12 +1523,6 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
     case GDK_BUTTON_PRESS:
     case GDK_2BUTTON_PRESS:
     case GDK_3BUTTON_PRESS:
-       if (dt) {
-                       // Snapping will be on hold if we're moving the mouse at high speeds. When starting
-               // drawing a new shape we really should snap though.
-               dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
-               }
-
        /* Pick the current item as if the button were not pressed, and
          * then process the event.
          */
@@ -1548,9 +1533,7 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
         break;
 
     case GDK_BUTTON_RELEASE:
-       sp_canvas_snap_watchdog_callback(canvas); // If we have any pending snapping action, then invoke it now
-
-       /* Process the event as if the button were pressed, then repick
+               /* Process the event as if the button were pressed, then repick
          * after the button has been released
          */
         canvas->state = event->state;
@@ -1593,9 +1576,6 @@ static inline void request_motions(GdkWindow *w, GdkEventMotion *event) {
 static int
 sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
 {
-       static guint32 prev_time;
-       static boost::optional<Geom::Point> prev_pos;
-
        int status;
     SPCanvas *canvas = SP_CANVAS (widget);
 
@@ -1607,56 +1587,6 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
     if (canvas->pixmap_gc == NULL) // canvas being deleted
         return FALSE;
 
-    SPDesktop *dt = SP_ACTIVE_DESKTOP;
-
-    // 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
-                                                                                                    // Inkscape will get stuck in an unresponsive state
-
-    if (canvas->context_snap_delay_active && !c1 && !c2 && dt && dt->namedview->snap_manager.snapprefs.getSnapEnabledGlobally()) {
-       // Snap when speed drops below e.g. 0.02 px/msec, or when no motion events have occurred for some period.
-               // i.e. snap when we're at stand still. A speed threshold enforces snapping for tablets, which might never
-               // be fully at stand still and might keep spitting out motion events.
-               dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true); // put snapping on hold
-
-       Geom::Point event_pos(event->x, event->y);
-               guint32 event_t = gdk_event_get_time ( (GdkEvent *) event );
-
-               if (prev_pos) {
-                       Geom::Coord dist = Geom::L2(event_pos - *prev_pos);
-                       guint32 delta_t = event_t - prev_time;
-                       gdouble speed = delta_t > 0 ? dist/delta_t : 1000;
-                       if (speed > 0.02) { // Jitter threshold, might be needed for tablets
-                               // We're moving fast, so postpone any snapping until the next GDK_MOTION_NOTIFY event. We
-                               // will keep on postponing the snapping as long as the speed is high.
-                               // We must snap at some point in time though, so set a watchdog timer at some time from
-                               // now, just in case there's no future motion event that drops under the speed limit (when
-                               // stopping abruptly)
-                               sp_canvas_snap_watchdog_kill(canvas);
-                               sp_canvas_snap_watchdog_set(canvas, event); // 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
-                               // speed threshold is ineffective. In the extreme case the delay is set to zero, and snapping will
-                               // be immediate, as it used to be in the old days ;-).
-                       } else { // Speed is very low, so we're virtually at stand still
-                               // But if we're really standing still, then we should snap now. We could use some low-pass filtering,
-                               // otherwise snapping occurs for each jitter movement. For this filtering we'll leave the watchdog to expire,
-                               // snap, and set a new watchdog again.
-                               if (canvas->watchdog_id == 0) { // no watchdog has been set
-                                       // it might have already expired, so we'll set a new one; the snapping frequency will be limited by this
-                                       sp_canvas_snap_watchdog_set(canvas, event);
-                               } // 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
-                       sp_canvas_snap_watchdog_set(canvas, event);
-               }
-
-               prev_pos = event_pos;
-               prev_time = event_t;
-       }
-
     canvas->state = event->state;
        pick_current_item (canvas, (GdkEvent *) event);
        status = emit_event (canvas, (GdkEvent *) event);
@@ -1667,82 +1597,6 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
     return status;
 }
 
-gboolean sp_canvas_snap_watchdog_callback(gpointer data)
-{
-       // Snap NOW! For this the "postponed" flag will be reset and an the last motion event will be repeated
-       SPCanvas *canvas = reinterpret_cast<SPCanvas *>(data);
-       if (!canvas->watchdog_event) {
-               // This might occur when this method is called directly, i.e. not through the timer
-               return FALSE;
-       }
-
-       SPDesktop *dt = SP_ACTIVE_DESKTOP;
-       if (dt) {
-               dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
-       }
-
-       ((GdkEventMotion *)canvas->watchdog_event)->time = GDK_CURRENT_TIME;
-       emit_event(canvas, canvas->watchdog_event);
-       gdk_event_free(canvas->watchdog_event);
-       canvas->watchdog_event = NULL;
-       canvas->watchdog_id = 0;
-
-       return FALSE;
-}
-
-void sp_canvas_snap_watchdog_set(SPCanvas *canvas, GdkEventMotion *event)
-{
-       Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-       double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000);
-       g_assert(canvas->watchdog_id == 0);
-       canvas->watchdog_id = g_timeout_add(value, &sp_canvas_snap_watchdog_callback, canvas);
-       g_assert(canvas->watchdog_event == NULL);
-       canvas->watchdog_event = gdk_event_copy( (GdkEvent *) event);
-}
-
-void sp_canvas_snap_watchdog_kill(SPCanvas *canvas)
-{
-       if (canvas->watchdog_id) {
-        g_source_remove(canvas->watchdog_id); // Kill the watchdog
-        canvas->watchdog_id = 0;
-    }
-
-       if (canvas->watchdog_event) {
-               gdk_event_free(canvas->watchdog_event);
-               canvas->watchdog_event = NULL;
-       }
-}
-
-void sp_canvas_set_snap_delay_active(SPCanvas *canvas, bool snapping)
-{
-       // Only when canvas->context_snap_delay_active has been set, Inkscape will know that snapping is active
-       // and will delay any snapping events (but only when asked to through the preferences)
-
-       // When snapping is being delayed, then that will also mean that at some point the last event
-       // might be re-triggered. This should only occur when Inkscape is still in the same tool or context,
-       // and even more specifically, the tool should even be in the same state. If for example snapping is being delayed while
-       // creating a rectangle, then the rect-context will be active and it will be in the "dragging" state
-       // (see the static boolean variable "dragging" in the sp_rect_context_root_handler). The procedure is
-       // as follows: call sp_canvas_set_snap_delay_active(*, TRUE) when entering the "dragging" state, which will delay
-       // snapping from that moment on, and call sp_canvas_set_snap_delay_active(*, FALSE) when leaving the "dragging"
-       // state. This last call will also make sure that any pending snap events will be canceled.
-
-       if (!canvas) {
-               g_warning("sp_canvas_set_snap_delay_active() has been called without providing a canvas!");
-               return;
-       }
-
-       if (canvas->context_snap_delay_active == snapping) {
-               g_warning("Snapping was already allowed or disallowed! This is a bug, please report it.");
-       }
-
-       canvas->context_snap_delay_active = snapping;
-
-       if (snapping == false) {
-               sp_canvas_snap_watchdog_kill(canvas); // kill any pending snapping events
-       }
-}
-
 static void
 sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, int draw_x1, int draw_y1, int draw_x2, int draw_y2, int sw)
 {
index cb63374e1f1f500d3875fc88f30effb78aafe270..35e3fb5de863d56f4de46a597f28f061ea92f679 100644 (file)
@@ -193,10 +193,6 @@ struct SPCanvas {
 
     Geom::Rect getViewbox() const;
     NR::IRect getViewboxIntegers() const;
-
-    guint watchdog_id;
-    GdkEvent *watchdog_event;
-    bool context_snap_delay_active;
 };
 
 GtkWidget *sp_canvas_new_aa();
@@ -218,8 +214,6 @@ void sp_canvas_world_to_window(SPCanvas const *canvas, double worldx, double wor
 Geom::Point sp_canvas_window_to_world(SPCanvas const *canvas, Geom::Point const win);
 Geom::Point sp_canvas_world_to_window(SPCanvas const *canvas, Geom::Point const world);
 
-void sp_canvas_set_snap_delay_active(SPCanvas *canvas, bool snapping);
-
 #endif // SEEN_SP_CANVAS_H
 
 /*
index 7039c3b130c050ef37d87de12f61e4ae4f4c0991..5b845388bce1c8bdd44fd7a226d237fdf5850463 100644 (file)
@@ -43,6 +43,7 @@
 #include "shortcuts.h"
 #include "desktop.h"
 #include "desktop-handles.h"
+#include "sp-namedview.h"
 #include "selection.h"
 #include "file.h"
 #include "interface.h"
@@ -142,6 +143,7 @@ sp_event_context_init(SPEventContext *event_context)
     event_context->_grdrag = NULL;
     event_context->space_panning = false;
     event_context->shape_editor = NULL;
+    event_context->_delayed_snap_event = NULL;
 }
 
 /**
@@ -228,7 +230,7 @@ gint gobble_key_events(guint keyval, gint mask)
            && event_next->key.keyval == keyval
            && (!mask || (event_next->key.state & mask))) {
         if (event_next->type == GDK_KEY_PRESS)
-            i ++; 
+            i ++;
         // kill it
         gdk_event_free(event_next);
         // get next
@@ -464,7 +466,7 @@ static gint sp_event_context_private_root_handler(SPEventContext *event_context,
                     Inkscape::Rubberband::get(desktop)->move(motion_dt);
                 } else {
                     Inkscape::Rubberband::get(desktop)->start(desktop, motion_dt);
-                } 
+                }
                 if (zoom_rb == 2)
                     gobble_motion_events(GDK_BUTTON2_MASK);
             }
@@ -491,7 +493,7 @@ static gint sp_event_context_private_root_handler(SPEventContext *event_context,
 
                 // in slow complex drawings, some of the motion events are lost;
                 // to make up for this, we scroll it once again to the button-up event coordinates
-                // (i.e. canvas will always get scrolled all the way to the mouse release point, 
+                // (i.e. canvas will always get scrolled all the way to the mouse release point,
                 // even if few intermediate steps were visible)
                 Geom::Point const motion_w(event->button.x, event->button.y);
                 Geom::Point const moved_w( motion_w - button_w );
@@ -514,8 +516,8 @@ static gint sp_event_context_private_root_handler(SPEventContext *event_context,
                 // in the editing window). So we resteal them back and run our regular shortcut
                 // invoker on them.
                 unsigned int shortcut;
-                case GDK_Tab: 
-                case GDK_ISO_Left_Tab: 
+                case GDK_Tab:
+                case GDK_ISO_Left_Tab:
                 case GDK_F1:
                     shortcut = get_group0_keyval(&event->key);
                     if (event->key.state & GDK_SHIFT_MASK)
@@ -637,7 +639,7 @@ static gint sp_event_context_private_root_handler(SPEventContext *event_context,
                             desktop->updateNow();
                         }
                         ret= TRUE;
-                    } 
+                    }
                     break;
                 case GDK_Q:
                 case GDK_q:
@@ -747,7 +749,7 @@ public:
         Inkscape::Preferences::Observer(path),
         _ec(ec) {}
     virtual void notify(Inkscape::Preferences::Entry const &val)
-    {   
+    {
         if (((SPEventContextClass *) G_OBJECT_GET_CLASS(_ec))->set) {
             ((SPEventContextClass *) G_OBJECT_GET_CLASS(_ec))->set(_ec,
                 const_cast<Inkscape::Preferences::Entry*>(&val));
@@ -773,10 +775,10 @@ sp_event_context_new(GType type, SPDesktop *desktop, gchar const *pref_path, uns
     ec->_message_context = new Inkscape::MessageContext(desktop->messageStack());
     ec->key = key;
     ec->pref_observer = NULL;
-    
+
     if (pref_path) {
         ec->pref_observer = new ToolPrefObserver(pref_path, ec);
-        
+
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         prefs->addObserver(*(ec->pref_observer));
     }
@@ -865,6 +867,12 @@ sp_event_context_activate(SPEventContext *ec)
     g_return_if_fail(ec != NULL);
     g_return_if_fail(SP_IS_EVENT_CONTEXT(ec));
 
+    // Make sure no delayed snapping events are carried over after switching contexts
+    // (this is only an additional safety measure against sloppy coding, because each
+    // context should take care of this by itself. It might be hard to get each and every
+    // context perfect though)
+    sp_event_context_snap_window_closed(ec, false);
+
     if (((SPEventContextClass *) G_OBJECT_GET_CLASS(ec))->activate)
         ((SPEventContextClass *) G_OBJECT_GET_CLASS(ec))->activate(ec);
 }
@@ -888,13 +896,36 @@ sp_event_context_deactivate(SPEventContext *ec)
 gint
 sp_event_context_root_handler(SPEventContext * event_context, GdkEvent * event)
 {
-    gint ret;
+    //std::cout << "sp_event_context_root_handler" << std::endl;
+       switch (event->type) {
+               case GDK_MOTION_NOTIFY:
+                       sp_event_context_snap_delay_handler(event_context, NULL, NULL, (GdkEventMotion *)event, DelayedSnapEvent::EVENTCONTEXT_ROOT_HANDLER);
+                       break;
+               case GDK_BUTTON_RELEASE:
+                       sp_event_context_snap_watchdog_callback(event_context->_delayed_snap_event); // If we have any pending snapping action, then invoke it now
+                       break;
+               case GDK_BUTTON_PRESS:
+        case GDK_2BUTTON_PRESS:
+        case GDK_3BUTTON_PRESS:
+                       // Snapping will be on hold if we're moving the mouse at high speeds. When starting
+                       // drawing a new shape we really should snap though.
+                       event_context->desktop->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
+                       break;
+        default:
+               break;
+    }
 
-    ret = ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->root_handler(event_context, event);
+    return sp_event_context_virtual_root_handler(event_context, event);
+}
 
-    set_event_location(event_context->desktop, event);
+gint
+sp_event_context_virtual_root_handler(SPEventContext * event_context, GdkEvent * event)
+{
+       //std::cout << "sp_event_context_virtual_root_handler -> postponed: " << event_context->desktop->namedview->snap_manager.snapprefs.getSnapPostponedGlobally() << std::endl;
 
-    return ret;
+       gint ret = ((SPEventContextClass *) G_OBJECT_GET_CLASS(event_context))->root_handler(event_context, event);
+       set_event_location(event_context->desktop, event);
+       return ret;
 }
 
 /**
@@ -903,17 +934,41 @@ sp_event_context_root_handler(SPEventContext * event_context, GdkEvent * event)
 gint
 sp_event_context_item_handler(SPEventContext * event_context, SPItem * item, GdkEvent * event)
 {
-    gint ret;
+       //std::cout << "sp_event_context_item_handler" << std::endl;
+       switch (event->type) {
+               case GDK_MOTION_NOTIFY:
+                       sp_event_context_snap_delay_handler(event_context, item, NULL, (GdkEventMotion *)event, DelayedSnapEvent::EVENTCONTEXT_ITEM_HANDLER);
+                       break;
+               case GDK_BUTTON_RELEASE:
+                       sp_event_context_snap_watchdog_callback(event_context->_delayed_snap_event); // If we have any pending snapping action, then invoke it now
+                       break;
+               /*case GDK_BUTTON_PRESS:
+               case GDK_2BUTTON_PRESS:
+               case GDK_3BUTTON_PRESS:
+                       // Snapping will be on hold if we're moving the mouse at high speeds. When starting
+                       // drawing a new shape we really should snap though.
+                       event_context->desktop->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
+                       break;
+               */
+               default:
+                       break;
+       }
+
+    return sp_event_context_virtual_item_handler(event_context, item, event);
+}
 
-    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_root_handler(event_context, event);
-    } else {
-        set_event_location(event_context->desktop, event);
-    }
+       if (! ret) {
+               ret = sp_event_context_virtual_root_handler(event_context, event);
+       } else {
+               set_event_location(event_context->desktop, event);
+       }
 
-    return ret;
+       return ret;
 }
 
 /**
@@ -927,7 +982,7 @@ static void set_event_location(SPDesktop *desktop, GdkEvent *event)
 
     Geom::Point const button_w(event->button.x, event->button.y);
     Geom::Point const button_dt(desktop->w2d(button_w));
-    desktop-> setPosition (button_dt);
+    desktop->setPosition(button_dt);
     desktop->set_coordinate_status(button_dt);
 }
 
@@ -1105,6 +1160,155 @@ event_context_print_event_info(GdkEvent *event, bool print_return) {
     }
 }
 
+void sp_event_context_snap_delay_handler(SPEventContext *ec, SPItem* const item, SPKnot* const knot, GdkEventMotion *event, DelayedSnapEvent::DelayedSnapEventOrigin origin)
+{
+       static guint32 prev_time;
+       static boost::optional<Geom::Point> prev_pos;
+
+       // 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
+                                                                                                    // Inkscape will get stuck in an unresponsive state
+
+    if (ec->_snap_window_open && !c1 && !c2 && ec->desktop && ec->desktop->namedview->snap_manager.snapprefs.getSnapEnabledGlobally()) {
+       // Snap when speed drops below e.g. 0.02 px/msec, or when no motion events have occurred for some period.
+               // i.e. snap when we're at stand still. A speed threshold enforces snapping for tablets, which might never
+               // be fully at stand still and might keep spitting out motion events.
+       ec->desktop->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true); // put snapping on hold
+
+       Geom::Point event_pos(event->x, event->y);
+               guint32 event_t = gdk_event_get_time ( (GdkEvent *) event );
+
+               if (prev_pos) {
+                       Geom::Coord dist = Geom::L2(event_pos - *prev_pos);
+                       guint32 delta_t = event_t - prev_time;
+                       gdouble speed = delta_t > 0 ? dist/delta_t : 1000;
+                       //std::cout << "Mouse speed = " << speed << " px/msec " << std::endl;
+                       if (speed > 0.02) { // Jitter threshold, might be needed for tablets
+                               // We're moving fast, so postpone any snapping until the next GDK_MOTION_NOTIFY event. We
+                               // will keep on postponing the snapping as long as the speed is high.
+                               // We must snap at some point in time though, so set a watchdog timer at some time from
+                               // 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, 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
+                               // speed threshold is ineffective. In the extreme case the delay is set to zero, and snapping will
+                               // be immediate, as it used to be in the old days ;-).
+                       } else { // Speed is very low, so we're virtually at stand still
+                               // But if we're really standing still, then we should snap now. We could use some low-pass filtering,
+                               // otherwise snapping occurs for each jitter movement. For this filtering we'll leave the watchdog to expire,
+                               // 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 by this
+                                       ec->_delayed_snap_event = new DelayedSnapEvent(ec, item, knot, 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, event, origin);
+               }
+
+               prev_pos = event_pos;
+               prev_time = event_t;
+       }
+}
+
+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);
+
+       if (dse == NULL) {
+               // This might occur when this method is called directly, i.e. not through the timer
+               // E.g. on GDK_BUTTON_RELEASE in sp_event_context_root_handler()
+               return FALSE;
+       }
+
+       SPEventContext *ec = dse->getEventContext();
+       if (ec == NULL || ec->desktop == NULL) {
+               return false;
+       }
+
+       SPDesktop *dt = ec->desktop;
+       dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
+
+       switch (dse->getOrigin()) {
+               case DelayedSnapEvent::EVENTCONTEXT_ROOT_HANDLER:
+                       sp_event_context_virtual_root_handler(ec, dse->getEvent());
+                       break;
+               case DelayedSnapEvent::EVENTCONTEXT_ITEM_HANDLER:
+                       g_assert(dse->getItem() != NULL);
+                       sp_event_context_virtual_item_handler(ec, dse->getItem(), dse->getEvent());
+                       break;
+               case DelayedSnapEvent::KNOT_HANDLER:
+                       g_assert(dse->getKnot() != NULL);
+                       sp_knot_handler_request_position(dse->getEvent(), dse->getKnot());
+                       break;
+               default:
+                       g_warning("Origin of snap-delay event has not been defined!;");
+                       break;
+       }
+
+       ec->_delayed_snap_event = NULL;
+       delete dse;
+
+       return FALSE; //Kills the timer and stops it from executing this callback over and over again.
+}
+
+void sp_event_context_snap_window_open(SPEventContext *ec, bool show_debug_warnings)
+{
+       // Only when ec->_snap_window_open has been set, Inkscape will know that snapping is active
+       // and will delay any snapping events (but only when asked to through the preferences)
+
+       // When snapping is being delayed, then that will also mean that at some point the last event
+       // might be re-triggered. This should only occur when Inkscape is still in the same tool or context,
+       // and even more specifically, the tool should even be in the same state. If for example snapping is being delayed while
+       // creating a rectangle, then the rect-context will be active and it will be in the "dragging" state
+       // (see the static boolean variable "dragging" in the sp_rect_context_root_handler). The procedure is
+       // as follows: call sp_event_context_snap_window_open(*, TRUE) when entering the "dragging" state, which will delay
+       // snapping from that moment on, and call sp_event_context_snap_window_open(*, FALSE) when leaving the "dragging"
+       // state. This last call will also make sure that any pending snap events will be canceled.
+
+       //std::cout << "sp_event_context_snap_window_open" << std::endl;
+       if (!ec) {
+               if (show_debug_warnings) {
+                       g_warning("sp_event_context_snap_window_open() has been called without providing an event context!");
+               }
+               return;
+       }
+
+       if (ec->_snap_window_open == true && show_debug_warnings) {
+               g_warning("Snap window was already open! This is a bug, please report it.");
+       }
+
+       ec->_snap_window_open = true;
+}
+
+void sp_event_context_snap_window_closed(SPEventContext *ec, bool show_debug_warnings)
+{
+       //std::cout << "sp_event_context_snap_window_closed" << std::endl;
+       if (!ec) {
+               if (show_debug_warnings) {
+                       g_warning("sp_event_context_snap_window_closed() has been called without providing an event context!");
+               }
+               return;
+       }
+
+       if (ec->_snap_window_open == false && show_debug_warnings) {
+               g_warning("Snap window was already closed! This is a bug, please report it.");
+       }
+
+       ec->_snap_window_open = false;
+
+       delete ec->_delayed_snap_event;
+       ec->_delayed_snap_event = NULL;
+}
+
+
+
 /*
   Local Variables:
   mode:c++
index df4aa6eab4070252ff07425613cd0be6838056e6..638ac56f744ca2907a1ad317f0b010ea227005ee 100644 (file)
@@ -20,6 +20,7 @@
 #include <glib-object.h>
 #include <gdk/gdktypes.h>
 #include <gdk/gdkevents.h>
+#include "knot.h"
 
 #include "2geom/forward.h"
 #include "preferences.h"
@@ -28,6 +29,7 @@ struct GrDrag;
 struct SPDesktop;
 struct SPItem;
 class ShapeEditor;
+struct SPEventContext;
 
 namespace Inkscape {
     class MessageContext;
@@ -37,6 +39,52 @@ namespace Inkscape {
     }
 }
 
+gboolean sp_event_context_snap_watchdog_callback(gpointer data);
+void sp_event_context_snap_window_open(SPEventContext *ec, bool show_debug_warnings = true);
+void sp_event_context_snap_window_closed(SPEventContext *ec, bool show_debug_warnings = true);
+
+class DelayedSnapEvent
+{
+public:
+       enum DelayedSnapEventOrigin {
+               UNDEFINED_HANDLER = 0,
+               EVENTCONTEXT_ROOT_HANDLER,
+               EVENTCONTEXT_ITEM_HANDLER,
+               KNOT_HANDLER
+       };
+
+       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)
+       {
+               Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+               double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000);
+               _timer_id = g_timeout_add(value, &sp_event_context_snap_watchdog_callback, this);
+               _event = gdk_event_copy((GdkEvent*) event);
+               ((GdkEventMotion *)_event)->time = GDK_CURRENT_TIME;
+       }
+
+       ~DelayedSnapEvent()     {
+               if (_timer_id > 0) g_source_remove(_timer_id); // Kill the watchdog
+               if (_event != NULL) gdk_event_free(_event); // Remove the copy of the original event
+       }
+
+       SPEventContext* getEventContext() {return _event_context;}
+       DelayedSnapEventOrigin getOrigin() {return _origin;}
+       GdkEvent* getEvent() {return _event;}
+       SPItem* getItem() {return _item;}
+       SPKnot* getKnot() {return _knot;}
+
+private:
+       guint _timer_id;
+       GdkEvent* _event;
+       SPItem* _item;
+       SPKnot* _knot;
+       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);
+
 /**
  * Base class for Event processors.
  */
@@ -57,7 +105,7 @@ struct SPEventContext : public GObject {
     gint tolerance;
     bool within_tolerance;  ///< are we still within tolerance of origin
 
-    SPItem *item_to_select; ///< the item where mouse_press occurred, to 
+    SPItem *item_to_select; ///< the item where mouse_press occurred, to
                             ///< be selected if this is a click not drag
 
     Inkscape::MessageContext *defaultMessageContext() {
@@ -74,6 +122,9 @@ struct SPEventContext : public GObject {
     ShapeEditor* shape_editor;
 
     bool space_panning;
+
+    bool _snap_window_open;
+    DelayedSnapEvent *_delayed_snap_event;
 };
 
 /**
@@ -101,7 +152,9 @@ void sp_event_context_activate(SPEventContext *ec);
 void sp_event_context_deactivate(SPEventContext *ec);
 
 gint sp_event_context_root_handler(SPEventContext *ec, GdkEvent *event);
+gint sp_event_context_virtual_root_handler(SPEventContext *ec, GdkEvent *event);
 gint sp_event_context_item_handler(SPEventContext *ec, SPItem *item, GdkEvent *event);
+gint sp_event_context_virtual_item_handler(SPEventContext *ec, SPItem *item, GdkEvent *event);
 
 void sp_event_root_menu_popup(SPDesktop *desktop, SPItem *item, GdkEvent *event);
 
index 16df41f7a82f6aa418ea38e8879214b59000defd..03c3c947cb418a9579e9cc5a512bdfe8ea29f698 100644 (file)
@@ -114,8 +114,6 @@ static void sp_gradient_context_dispose(GObject *object)
     SPGradientContext *rc = SP_GRADIENT_CONTEXT(object);
     SPEventContext *ec = SP_EVENT_CONTEXT(object);
 
-    sp_canvas_set_snap_delay_active(ec->desktop->canvas, false);
-
     ec->enableGrDrag(false);
 
     if (rc->_message_context) {
@@ -219,7 +217,7 @@ static void sp_gradient_context_setup(SPEventContext *ec)
     rc->subselcon = new sigc::connection (ec->desktop->connectToolSubselectionChanged(sigc::bind (sigc::ptr_fun(&gradient_subselection_changed), rc)));
     gradient_selection_changed(selection, rc);
 
-    sp_canvas_set_snap_delay_active(ec->desktop->canvas, true);
+    sp_event_context_snap_window_open(ec);
 }
 
 void
index fab622bbd10ac3d190d149947e3c6c4801ded606..ae8a7f7c500c32aeb8516d99efa74fe0acda6c2b 100644 (file)
@@ -29,7 +29,6 @@
 #include "message-context.h"
 #include "event-context.h"
 
-
 #define KNOT_EVENT_MASK (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | \
                         GDK_POINTER_MOTION_MASK | \
                         GDK_POINTER_MOTION_HINT_MASK | \
@@ -318,8 +317,8 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
             if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
                 Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y));
                 sp_knot_start_dragging(knot, p, (gint) event->button.x, (gint) event->button.y, event->button.time);
-                if (knot->desktop->canvas->context_snap_delay_active == false) {
-                                       sp_canvas_set_snap_delay_active(knot->desktop->canvas, true);
+                if (knot->desktop->event_context->_snap_window_open == false) {
+                                       sp_event_context_snap_window_open(knot->desktop->event_context);
                                        snap_delay_temporarily_active = true;
                                }
                 consumed = TRUE;
@@ -327,7 +326,15 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
             break;
        case GDK_BUTTON_RELEASE:
             if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
-                knot->pressure = 0;
+                if (snap_delay_temporarily_active) {
+                       if (knot->desktop->event_context->_snap_window_open == true) {
+                               sp_event_context_snap_window_closed(knot->desktop->event_context);
+                       }
+                                       snap_delay_temporarily_active = false;
+                               }
+                sp_event_context_snap_watchdog_callback(knot->desktop->event_context->_delayed_snap_event);
+
+               knot->pressure = 0;
                 if (transform_escaped) {
                     transform_escaped = false;
                     consumed = TRUE;
@@ -353,13 +360,6 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
                     grabbed = FALSE;
                     moved = FALSE;
                     consumed = TRUE;
-
-                    if (snap_delay_temporarily_active) {
-                       if (knot->desktop->canvas->context_snap_delay_active == true) {
-                               sp_canvas_set_snap_delay_active(knot->desktop->canvas, false);
-                       }
-                                               snap_delay_temporarily_active = false;
-                                       }
                 }
             }
             break;
@@ -391,14 +391,8 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
                                      SP_KNOT_DRAGGING,
                                      TRUE);
                 }
-                Geom::Point const motion_w(event->motion.x, event->motion.y);
-                Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
-                Geom::Point p = motion_dt - knot->grabbed_rel_pos;
-                sp_knot_request_position (knot, p, event->motion.state);
-                knot->desktop->scroll_to_point (motion_dt);
-                knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
-                if (event->motion.state & GDK_BUTTON1_MASK)
-                    gobble_motion_events(GDK_BUTTON1_MASK);
+                sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, DelayedSnapEvent::KNOT_HANDLER);
+                sp_knot_handler_request_position(event, knot);
                 moved = TRUE;
             }
             break;
@@ -428,35 +422,35 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
             break;
        case GDK_KEY_PRESS: // keybindings for knot
             switch (get_group0_keyval(&event->key)) {
-               case GDK_Escape:
-                    sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
-                    if (!nograb) {
-                        sp_canvas_item_ungrab(knot->item, event->button.time);
-                    }
-                    if (moved) {
-                        sp_knot_set_flag(knot,
-                                         SP_KNOT_DRAGGING,
-                                         FALSE);
-                        g_signal_emit(knot,
-                                      knot_signals[UNGRABBED], 0,
-                                      event->button.state);
-                        sp_document_undo(sp_desktop_document(knot->desktop));
-                        knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
-                        transform_escaped = true;
-                        consumed = TRUE;
-                    }
-                    grabbed = FALSE;
-                    moved = FALSE;
-                    if (snap_delay_temporarily_active) {
-                                               sp_canvas_set_snap_delay_active(knot->desktop->canvas, false);
-                                               snap_delay_temporarily_active = false;
+                               case GDK_Escape:
+                                                       sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
+                                                       if (!nograb) {
+                                                               sp_canvas_item_ungrab(knot->item, event->button.time);
+                                                       }
+                                                       if (moved) {
+                                                               sp_knot_set_flag(knot,
+                                                                                                SP_KNOT_DRAGGING,
+                                                                                                FALSE);
+                                                               g_signal_emit(knot,
+                                                                                         knot_signals[UNGRABBED], 0,
+                                                                                         event->button.state);
+                                                               sp_document_undo(sp_desktop_document(knot->desktop));
+                                                               knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
+                                                               transform_escaped = true;
+                                                               consumed = TRUE;
+                                                       }
+                                                       grabbed = FALSE;
+                                                       moved = FALSE;
+                                                       if (snap_delay_temporarily_active) {
+                                                               sp_event_context_snap_window_closed(knot->desktop->event_context);
+                                                               snap_delay_temporarily_active = false;
+                                                       }
+                                                       break;
+                               default:
+                                                       consumed = FALSE;
+                                                       break;
                                        }
-                    break;
-               default:
-                    consumed = FALSE;
-                    break;
-            }
-            break;
+                                       break;
        default:
             break;
     }
@@ -466,6 +460,18 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
     return consumed;
 }
 
+void sp_knot_handler_request_position(GdkEvent *event, SPKnot *knot)
+{
+       Geom::Point const motion_w(event->motion.x, event->motion.y);
+       Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
+       Geom::Point p = motion_dt - knot->grabbed_rel_pos;
+       sp_knot_request_position (knot, p, event->motion.state);
+       knot->desktop->scroll_to_point (motion_dt);
+       knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
+       if (event->motion.state & GDK_BUTTON1_MASK)
+               gobble_motion_events(GDK_BUTTON1_MASK);
+}
+
 /**
  * Return new knot object.
  */
index 07c2640c3b563767b8173835ea99571c0f5b44d0..351c7f7be0cab0cce83f2f04c71331b6b132349e 100644 (file)
@@ -33,7 +33,7 @@ class SPKnotClass;
 
 /**
  * Desktop-bound visual control object.
- * 
+ *
  * A knot is a draggable object, with callbacks to change something by
  * dragging it, visuably represented by a canvas item (mostly square).
  */
@@ -174,6 +174,7 @@ void sp_knot_set_position(SPKnot *knot, Geom::Point const &p, guint state);
 /** Moves knot without any signal. */
 void sp_knot_moveto(SPKnot *knot, Geom::Point const &p);
 
+void sp_knot_handler_request_position(GdkEvent *event, SPKnot *knot);
 Geom::Point sp_knot_position(SPKnot const *knot);
 
 
index 60c1f80846a965a882401b4a16846771644573c9..773b9249c513a7a804a19116f56cddd3f545d4ff 100644 (file)
@@ -139,7 +139,7 @@ KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state)
 {
     if (this->dragging == false) {
        this->dragging = true;
-       //sp_canvas_set_snap_delay_active(desktop->canvas, true);
+       //sp_event_context_snap_window_open(desktop->canvas);
     }
 
        // this was a local change and the knotholder does not need to be recreated:
@@ -165,7 +165,7 @@ void
 KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/)
 {
        this->dragging = false;
-       //sp_canvas_set_snap_delay_active(desktop->canvas, false);
+       //sp_event_context_snap_window_closed(desktop->canvas);
 
        if (this->released) {
         this->released(this->item);
index f40d1b7fc79927f69c76674e3e46ec790e45cb14..44dbabcb0dbf059310b0002621f10148d8464c95 100644 (file)
@@ -294,7 +294,7 @@ sp_node_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                 if (!(event->button.state & GDK_SHIFT_MASK)) {
                     if (!nc->drag) {
                         if (se->has_nodepath() && selection->single() /* && item_over */) {
-                               sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                               sp_event_context_snap_window_open(event_context);
                                // save drag origin
                             bool over_stroke = se->is_over_stroke(Geom::Point(event->button.x, event->button.y), true);
                             //only dragging curves
@@ -425,13 +425,13 @@ sp_node_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                                     }
                                     desktop->updateNow();
                                 }
-                               sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                               sp_event_context_snap_window_closed(event_context);
                                 break;
                             case GDK_2BUTTON_PRESS:
                                 //add a node
                                 se->add_node_near_point();
                                 nc->added_node = true;
-                                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                                sp_event_context_snap_window_closed(event_context);
                                 break;
                             default:
                                 break;
index ed356e5c49ff2940c777877250000fd27ee0c6df..b92a3bf85a7b2e76268297785906c6559055ffb7 100644 (file)
@@ -3590,7 +3590,7 @@ static void node_grabbed(SPKnot *knot, guint state, gpointer data)
     }
 
     n->is_dragging = true;
-    //sp_canvas_set_snap_delay_active(n->subpath->nodepath->desktop->canvas, true);
+    //sp_event_context_snap_window_open(n->subpath->nodepath->desktop->canvas);
     // Reconstruct and store the location of the mouse pointer at the time when we started dragging (needed for snapping)
     n->subpath->nodepath->drag_origin_mouse = knot->grabbed_rel_pos + knot->drag_origin;
 
@@ -3608,7 +3608,7 @@ static void node_ungrabbed(SPKnot */*knot*/, guint /*state*/, gpointer data)
 
    n->dragging_out = NULL;
    n->is_dragging = false;
-   //sp_canvas_set_snap_delay_active(n->subpath->nodepath->desktop->canvas, false);
+   //sp_event_context_snap_window_closed(n->subpath->nodepath->desktop->canvas);
    n->subpath->nodepath->drag_origin_mouse = Geom::Point(NR_HUGE, NR_HUGE);
    sp_canvas_end_forced_full_redraws(n->subpath->nodepath->desktop->canvas);
 
index 7ffabcefdcc5051853634607147d904e3083c884..beece2b31f44f70b896ae07ae0c582b76efef467 100644 (file)
@@ -208,8 +208,6 @@ sp_pen_context_setup(SPEventContext *ec)
 
     pc = SP_PEN_CONTEXT(ec);
 
-    sp_canvas_set_snap_delay_active(pc->desktop->canvas, true);
-
     if (((SPEventContextClass *) pen_parent_class)->setup) {
         ((SPEventContextClass *) pen_parent_class)->setup(ec);
     }
@@ -265,7 +263,7 @@ sp_pen_context_finish(SPEventContext *ec)
 {
     SPPenContext *pc = SP_PEN_CONTEXT(ec);
 
-    sp_canvas_set_snap_delay_active(pc->desktop->canvas, false);
+    sp_event_context_snap_window_closed(ec, false); //TODO: Detailed implementation of the snap window; now it's simply always open
 
     if (pc->npoints != 0) {
         pen_cancel (pc);
@@ -369,6 +367,8 @@ sp_pen_context_root_handler(SPEventContext *ec, GdkEvent *event)
 {
     SPPenContext *const pc = SP_PEN_CONTEXT(ec);
 
+    sp_event_context_snap_window_open(ec, false); //TODO: Detailed implementation of the snap window; now it's simply always open
+
     gint ret = FALSE;
 
     switch (event->type) {
index fc2088a17af0f8e242058f501581e8e704524a7e..4b87e86b55a0e7c517c85abb039b2d67169ddfd8 100644 (file)
@@ -255,7 +255,7 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
                 /* Set first point of sequence */
                SnapManager &m = desktop->namedview->snap_manager;
                                m.setup(desktop);
-                               sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                               sp_event_context_snap_window_open(event_context);
 
                 if (anchor) {
                     p = anchor->dp;
@@ -349,7 +349,7 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
             /* We may be idle or already freehand */
             if ( mevent.state & GDK_BUTTON1_MASK && pc->is_drawing ) {
                 if (pc->state == SP_PENCIL_CONTEXT_IDLE) {
-                       sp_canvas_set_snap_delay_active(dt->canvas, false);
+                       sp_event_context_snap_window_closed(event_context);
                 }
                pc->state = SP_PENCIL_CONTEXT_FREEHAND;
 
@@ -417,7 +417,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
                 /* Releasing button in idle mode means single click */
                 /* We have already set up start point/anchor in button_press */
                 pc->state = SP_PENCIL_CONTEXT_ADDLINE;
-                //sp_canvas_set_snap_delay_active(dt->canvas, true);
+                //sp_event_context_snap_window_open(dt->canvas);
                 ret = TRUE;
                 break;
             case SP_PENCIL_CONTEXT_ADDLINE:
@@ -431,7 +431,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
                 spdc_set_endpoint(pc, p);
                 spdc_finish_endpoint(pc);
                 pc->state = SP_PENCIL_CONTEXT_IDLE;
-                sp_canvas_set_snap_delay_active(dt->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 ret = TRUE;
                 break;
             case SP_PENCIL_CONTEXT_FREEHAND:
@@ -445,7 +445,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
                     }
 
                     pc->state = SP_PENCIL_CONTEXT_SKETCH;
-                    //sp_canvas_set_snap_delay_active(dt->canvas, true);
+                    //sp_event_context_snap_window_open(dt->canvas);
                 } else {
                     /* Finish segment now */
                     /// \todo fixme: Clean up what follows (Lauris)
@@ -465,7 +465,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
                         pc->green_anchor = sp_draw_anchor_destroy(pc->green_anchor);
                     }
                     pc->state = SP_PENCIL_CONTEXT_IDLE;
-                    // sp_canvas_set_snap_delay_active(dt->canvas, false);
+                    // sp_event_context_snap_window_closed(dt->canvas);
                     // reset sketch mode too
                     pc->sketch_n = 0;
                 }
@@ -498,7 +498,7 @@ pencil_cancel (SPPencilContext *const pc)
 
     pc->is_drawing = false;
     pc->state = SP_PENCIL_CONTEXT_IDLE;
-    sp_canvas_set_snap_delay_active(pc->desktop->canvas, false);
+    sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(pc));
 
     pc->red_curve->reset();
     sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL);
@@ -589,7 +589,7 @@ pencil_handle_key_release(SPPencilContext *const pc, guint const keyval, guint c
                     pc->green_anchor = sp_draw_anchor_destroy(pc->green_anchor);
                 }
                 pc->state = SP_PENCIL_CONTEXT_IDLE;
-                sp_canvas_set_snap_delay_active(pc->desktop->canvas, false);
+                sp_event_context_snap_window_closed(SP_EVENT_CONTEXT(pc));
                 pc->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Finishing freehand sketch"));
                 ret = TRUE;
             }
index 3650e05b1115d5da06d6fb4097f09802dc9dc76d..9c1c704ddac10021da8b40caead1c6a089d7982f 100644 (file)
@@ -257,7 +257,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
             event_context->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, TRUE);
 
             dragging = true;
-            sp_canvas_set_snap_delay_active(desktop->canvas, true);
+            sp_event_context_snap_window_open(event_context);
 
             /* Position center */
             Geom::Point button_dt(desktop->w2d(button_w));
@@ -306,7 +306,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
         event_context->xp = event_context->yp = 0;
         if (event->button.button == 1 && !event_context->space_panning) {
             dragging = false;
-            sp_canvas_set_snap_delay_active(desktop->canvas, false);
+            sp_event_context_snap_window_closed(event_context);
 
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the rect
@@ -381,7 +381,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
                 sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                       event->button.time);
                 dragging = false;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the rect
                     sp_rect_finish(rc);
index b2a05dca2217567ab785f6bea5e767da91e1c2e9..e30ef53d2a65e2b2c2b8f5cf8d3e67d1fdb43c08 100644 (file)
@@ -212,6 +212,7 @@ sp_select_context_abort(SPEventContext *event_context)
             seltrans->ungrab();
             sc->moved = FALSE;
             sc->dragging = FALSE;
+            sp_event_context_snap_window_closed(event_context);
             drag_escaped = 1;
 
             if (sc->item) {
@@ -323,6 +324,7 @@ sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkE
                     // pass the event to root handler which will perform rubberband, shift-click, ctrl-click, ctrl-drag
                 } else {
                     sc->dragging = TRUE;
+                    sp_event_context_snap_window_open(event_context);
                     sc->moved = FALSE;
 
                     sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
@@ -427,6 +429,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                         desktop->setCurrentLayer(reinterpret_cast<SPObject *>(clicked_item));
                         sp_desktop_selection(desktop)->clear();
                         sc->dragging = false;
+                        sp_event_context_snap_window_closed(event_context);
 
                         sp_canvas_end_forced_full_redraws(desktop->canvas);
                     } else { // switch tool
@@ -497,6 +500,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                     // if it's not click and ctrl or alt was pressed (the latter with some selection
                     // but not with shift) we want to drag rather than rubberband
                     sc->dragging = TRUE;
+                    sp_event_context_snap_window_open(event_context);
 
                     sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
                 }
@@ -547,7 +551,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                         ret = TRUE;
                     } else {
                         sc->dragging = FALSE;
-
+                        sp_event_context_snap_window_closed(event_context);
                         sp_canvas_end_forced_full_redraws(desktop->canvas);
                     }
                 } else {
@@ -596,7 +600,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                         }
                     }
                     sc->dragging = FALSE;
-
+                    sp_event_context_snap_window_closed(event_context);
                     sp_canvas_end_forced_full_redraws(desktop->canvas);
 
                     if (sc->item) {
index f3ad2849c4ed802d04397b9f2cd2254b9fe98c37..e6c53acfeb0163ea88a81fc671973deb55fa3a8a 100644 (file)
@@ -368,7 +368,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
        }
     }
 
-       sp_canvas_set_snap_delay_active(_desktop->canvas, true);
+       //sp_event_context_snap_window_open(_desktop->event_context);
 
     if ((x != -1) && (y != -1)) {
         sp_canvas_item_show(_norm);
@@ -422,7 +422,7 @@ void Inkscape::SelTrans::ungrab()
     _grabbed = false;
     _show_handles = true;
 
-    sp_canvas_set_snap_delay_active(_desktop->canvas, false);
+    //sp_event_context_snap_window_closed(_desktop->event_context);
 
     _desktop->snapindicator->remove_snapsource();
 
index 2b9a45a1d5b3965dd8ab8c041a1bfd70e784defc..19455ba73be27785ef87a8cbee0fb8632a90e521 100644 (file)
@@ -32,6 +32,7 @@
 #include "desktop.h"
 #include "sp-guide.h"
 #include "preferences.h"
+#include "event-context.h"
 using std::vector;
 
 /**
@@ -160,12 +161,14 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp
                                              bool first_point,
                                              Geom::OptRect const &bbox_to_snap) const
 {
-    if (_desktop->canvas->context_snap_delay_active == false) {
-        g_warning("context_snap_delay_active has not been set to true by the current context. Please report this!");
-        // When the context goes into dragging-mode, then Inkscape should call this: sp_canvas_set_snap_delay_active(desktop->canvas, true);
-    }
+       if (_desktop->event_context->_snap_window_open == false) {
+               g_warning("context_snap_window_open has not been set to true by the current context. Please report this!");
+               // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context);
+       }
+
+       //std::cout << "SnapManager::freeSnap -> postponed: " << snapprefs.getSnapPostponedGlobally() << std::endl;
 
-    if (!someSnapperMightSnap()) {
+       if (!someSnapperMightSnap()) {
         return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false);
     }
 
@@ -293,12 +296,12 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P
                                                     bool first_point,
                                                     Geom::OptRect const &bbox_to_snap) const
 {
-    if (_desktop->canvas->context_snap_delay_active == false) {
-        g_warning("context_snap_delay_active has not been set to true by the current context. Please report this!");
-        // When the context goes into dragging-mode, then Inkscape should call this: sp_canvas_set_snap_delay_active(desktop->canvas, true);
-    }
+       if (_desktop->event_context->_snap_window_open == false) {
+               g_warning("context_snap_window_open has not been set to true by the current context. Please report this!");
+               // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context);
+       }
 
-    if (!someSnapperMightSnap()) {
+       if (!someSnapperMightSnap()) {
         return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false);
     }
 
@@ -331,10 +334,10 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con
 {
     // This method is used to snap a guide to nodes or to other guides, while dragging the guide around. Will not snap to grids!
 
-    if (_desktop->canvas->context_snap_delay_active == false) {
-        g_warning("context_snap_delay_active has not been set to true by the current context. Please report this!");
-        // When the context goes into dragging-mode, then Inkscape should call this: sp_canvas_set_snap_delay_active(desktop->canvas, true);
-    }
+       if (_desktop->event_context->_snap_window_open == false) {
+                       g_warning("context_snap_window_open has not been set to true by the current context. Please report this!");
+                       // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context);
+       }
 
     if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) {
         return;
index e91f550dc070dbb1c37806b86b5c840a3d6b98a3..67ee82b358abc213709fbc249c65dbb2a87a5bc4 100644 (file)
@@ -220,7 +220,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
             if (event->button.button == 1 && !event_context->space_panning) {
 
                 dragging = TRUE;
-                sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                sp_event_context_snap_window_open(event_context);
                 sc->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
 
                 SnapManager &m = desktop->namedview->snap_manager;
@@ -269,7 +269,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
             event_context->xp = event_context->yp = 0;
             if (event->button.button == 1 && !event_context->space_panning) {
                 dragging = FALSE;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the spiral
                     sp_spiral_finish(sc);
@@ -329,7 +329,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                         sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                               event->button.time);
                         dragging = false;
-                        sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                        sp_event_context_snap_window_closed(event_context);
                         if (!event_context->within_tolerance) {
                             // we've been dragging, finish the rect
                             sp_spiral_finish(sc);
index b2c56cc7f72ed7f145102ed646e60b7ef6a70eed..5361219aa7c105fa61249b091306568bc67900cc 100644 (file)
@@ -234,7 +234,7 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent
         if (event->button.button == 1 && !event_context->space_panning) {
 
             dragging = TRUE;
-            sp_canvas_set_snap_delay_active(desktop->canvas, true);
+            sp_event_context_snap_window_open(event_context);
 
             sc->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
 
@@ -281,7 +281,7 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent
         event_context->xp = event_context->yp = 0;
         if (event->button.button == 1 && !event_context->space_panning) {
             dragging = FALSE;
-            sp_canvas_set_snap_delay_active(desktop->canvas, false);
+            sp_event_context_snap_window_closed(event_context);
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the star
                 sp_star_finish (sc);
@@ -341,7 +341,7 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent
                 sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
                                       event->button.time);
                 dragging = false;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the rect
                     sp_star_finish(sc);
index d743d45c2a3ab6af07a353bb710341f97bcbe8e0..a5af083859fc182a7c56d43ffd7bddc64b1f711d 100644 (file)
@@ -352,7 +352,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve
                         sp_text_context_update_cursor(tc);
                         sp_text_context_update_text_selection(tc);
                         tc->dragging = 1;
-                        sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                        sp_event_context_snap_window_open(event_context);
                     }
                     ret = TRUE;
                 }
@@ -369,7 +369,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve
                     sp_text_context_update_cursor(tc);
                     sp_text_context_update_text_selection(tc);
                     tc->dragging = 2;
-                    sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                    sp_event_context_snap_window_open(event_context);
                     ret = TRUE;
                 }
             }
@@ -381,14 +381,14 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve
                 sp_text_context_update_cursor(tc);
                 sp_text_context_update_text_selection(tc);
                 tc->dragging = 3;
-                sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                sp_event_context_snap_window_open(event_context);
                 ret = TRUE;
             }
             break;
         case GDK_BUTTON_RELEASE:
             if (event->button.button == 1 && tc->dragging && !event_context->space_panning) {
                 tc->dragging = 0;
-                sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                sp_event_context_snap_window_closed(event_context);
                 ret = TRUE;
             }
             break;
@@ -1392,7 +1392,7 @@ sp_text_get_selected_text(SPEventContext const *ec)
 
 SPCSSAttr *
 sp_text_get_style_at_cursor(SPEventContext const *ec)
-{ 
+{
     if (!SP_IS_TEXT_CONTEXT(ec))
         return NULL;
     SPTextContext const *tc = SP_TEXT_CONTEXT(ec);