Code

- The snap-delay mechanism should now be more robust. From now on, it must be turned...
authordvlierop2 <dvlierop2@users.sourceforge.net>
Sun, 25 Jan 2009 13:35:08 +0000 (13:35 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Sun, 25 Jan 2009 13:35:08 +0000 (13:35 +0000)
- Creating single dots now snaps

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/draw-context.cpp
src/dropper-context.cpp
src/dyna-draw-context.cpp
src/gradient-context.cpp
src/knotholder.cpp
src/knotholder.h
src/nodepath.cpp
src/pen-context.cpp
src/pencil-context.cpp
src/pencil-context.h
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 3c8a50192fc2c3124ee5fa0c51a9aca5ce4602e2..da236ae8730672f7b1278afed563edd3a4538b39 100644 (file)
@@ -142,7 +142,7 @@ void sp_arc_context_selection_changed(Inkscape::Selection * selection, gpointer
     SPEventContext *ec = SP_EVENT_CONTEXT(ac);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     ec->shape_editor->set_item(item, SH_KNOTHOLDER);
 }
 
@@ -221,8 +221,9 @@ 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);
                 ac->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
-                
+
                 /* Snap center */
                 SnapManager &m = desktop->namedview->snap_manager;
                 m.setup(desktop);
@@ -252,7 +253,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent
 
                 Geom::Point const motion_w(event->motion.x, event->motion.y);
                 Geom::Point motion_dt(desktop->w2d(motion_w));
-                
+
                 sp_arc_drag(ac, motion_dt, event->motion.state);
 
                 gobble_motion_events(GDK_BUTTON1_MASK);
@@ -264,6 +265,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);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the arc
                     sp_arc_finish(ac);
@@ -327,6 +329,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);
                         if (!event_context->within_tolerance) {
                             // we've been dragging, finish the rect
                             sp_arc_finish(ac);
@@ -462,9 +465,9 @@ static void sp_arc_finish(SPArcContext *ac)
         SP_OBJECT(ac->item)->updateRepr();
 
         sp_canvas_end_forced_full_redraws(desktop->canvas);
-        
+
         sp_desktop_selection(desktop)->set(ac->item);
-        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC, 
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC,
                          _("Create ellipse"));
 
         ac->item = NULL;
index 2d20318e36cd5bae58bfb56612adbd5c21b953d7..2b76233f5c5cdf3d88a1eb62ec01bfef760081d4 100644 (file)
@@ -113,7 +113,7 @@ static void sp_box3d_context_init(Box3DContext *box3d_context)
 
     box3d_context->ctrl_dragged = false;
     box3d_context->extruded = false;
-    
+
     box3d_context->_vpdrag = NULL;
 
     new (&box3d_context->sel_changed_connection) sigc::connection();
@@ -157,7 +157,7 @@ static void sp_box3d_context_selection_changed(Inkscape::Selection *selection, g
     SPEventContext *ec = SP_EVENT_CONTEXT(bc);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     ec->shape_editor->set_item(item, SH_KNOTHOLDER);
 
     if (selection->perspList().size() == 1) {
@@ -167,7 +167,7 @@ static void sp_box3d_context_selection_changed(Inkscape::Selection *selection, g
 }
 
 /* create a default perspective in document defs if none is present
-   (can happen after 'vacuum defs' or when a pre-0.46 file is opened) */   
+   (can happen after 'vacuum defs' or when a pre-0.46 file is opened) */
 static void sp_box3d_context_check_for_persp_in_defs(SPDocument *document) {
     SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
 
@@ -271,12 +271,13 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             event_context->xp = (gint) button_w[Geom::X];
             event_context->yp = (gint) button_w[Geom::Y];
             event_context->within_tolerance = true;
-            
+
             // remember clicked item, *not* disregarding groups (since a 3D box is a group), honoring Alt
             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);
+
             /*  */
             Geom::Point button_dt(desktop->w2d(button_w));
             bc->drag_origin = from_2geom(button_dt);
@@ -372,6 +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);
 
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the box
@@ -504,6 +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);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the box
                     sp_box3d_finish(bc);
index 372918b80b4626461857773c202364ad79379698..6fa709b18915437322ef9827a8daacbb0e2786d9 100644 (file)
@@ -291,6 +291,8 @@ 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);
 }
 
 
@@ -314,6 +316,8 @@ 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);
 }
 
 
@@ -525,7 +529,7 @@ 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);
 
                     if (!cc->sid) {
@@ -568,12 +572,12 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const
         }
     } else if (bevent.button == 3) {
         if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) {
-            // A context menu is going to be triggered here, 
+            // A context menu is going to be triggered here,
             // so end the rerouting operation.
             cc_connector_rerouting_finish(cc, &p);
-                
+
             cc->state = SP_CONNECTOR_CONTEXT_IDLE;
-            
+
             // Don't set ret to TRUE, so we drop through to the
             // parent handler which will open the context menu.
         }
@@ -705,7 +709,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con
             case SP_CONNECTOR_CONTEXT_REROUTING:
             {
                 cc_connector_rerouting_finish(cc, &p);
-                
+
                 sp_document_ensure_up_to_date(doc);
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
                 return TRUE;
@@ -739,14 +743,14 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
             break;
         case GDK_Escape:
             if (cc->state == SP_CONNECTOR_CONTEXT_REROUTING) {
-                
+
                 SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
                 SPDocument *doc = sp_desktop_document(desktop);
 
                 cc_connector_rerouting_finish(cc, NULL);
-                
+
                 sp_document_undo(doc);
-                
+
                 cc->state = SP_CONNECTOR_CONTEXT_IDLE;
                 desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE,
                         _("Connector endpoint drag cancelled."));
@@ -771,7 +775,7 @@ cc_connector_rerouting_finish(SPConnectorContext *const cc, Geom::Point *const p
 {
     SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
     SPDocument *doc = sp_desktop_document(desktop);
-    
+
     // Clear the temporary path:
     cc->red_curve->reset();
     sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), NULL);
@@ -796,7 +800,7 @@ cc_connector_rerouting_finish(SPConnectorContext *const cc, Geom::Point *const p
     cc->clickeditem->setHidden(false);
     sp_conn_adjust_path(SP_PATH(cc->clickeditem));
     cc->clickeditem->updateRepr();
-    sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR, 
+    sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
                      _("Reroute connector"));
     cc_set_active_conn(cc, cc->clickeditem);
 }
@@ -1005,7 +1009,7 @@ static gboolean
 cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
 {
     g_assert (knot != NULL);
-    
+
     g_object_ref(knot);
 
     SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(
@@ -1016,7 +1020,7 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
     switch (event->type) {
         case GDK_ENTER_NOTIFY:
             sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE);
-            
+
             cc->active_handle = knot;
 
             if (knot->tip)
@@ -1024,24 +1028,24 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
                 knot->desktop->event_context->defaultMessageContext()->set(
                         Inkscape::NORMAL_MESSAGE, knot->tip);
             }
-            
+
             consumed = TRUE;
             break;
         case GDK_LEAVE_NOTIFY:
             sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE);
 
             cc->active_handle = NULL;
-            
+
             if (knot->tip) {
                 knot->desktop->event_context->defaultMessageContext()->clear();
             }
-            
+
             consumed = TRUE;
             break;
         default:
             break;
     }
-    
+
     g_object_unref(knot);
 
     return consumed;
@@ -1127,7 +1131,7 @@ static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item)
 
     // Set center connection point.
     if ( cc->connpthandle == NULL ) {
-        SPKnot *knot = sp_knot_new(cc->desktop, 
+        SPKnot *knot = sp_knot_new(cc->desktop,
                 _("<b>Connection point</b>: click or drag to create a new connector"));
 
         knot->setShape(SP_KNOT_SHAPE_SQUARE);
@@ -1200,7 +1204,7 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item)
 
         // Create the handle if it doesn't exist
         if ( cc->endpt_handle[i] == NULL ) {
-            SPKnot *knot = sp_knot_new(cc->desktop, 
+            SPKnot *knot = sp_knot_new(cc->desktop,
                     _("<b>Connector endpoint</b>: drag to reroute or connect to new shapes"));
 
             knot->setShape(SP_KNOT_SHAPE_SQUARE);
index e2c3ba40eb4900d69c5084943a059370641be782..fbbbfee197d3e045adf249ade89da14a63c562ec 100644 (file)
@@ -88,6 +88,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
     case GDK_BUTTON_PRESS:
             if (event->button.button == 1) {
                 dragging = true;
+                sp_canvas_set_snap_delay_active(desktop->canvas, true);
                 Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                 Geom::Point const event_dt(desktop->w2d(event_w));
 
@@ -142,14 +143,14 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
             if (dragging) {
                 Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                 Geom::Point event_dt(desktop->w2d(event_w));
-                
+
                 SnapManager &m = desktop->namedview->snap_manager;
                 m.setup(desktop);
                 m.guideSnap(event_dt, normal);
-                
+
                 sp_guideline_set_position(SP_GUIDELINE(guide), from_2geom(event_dt));
                 desktop->set_coordinate_status(to_2geom(event_dt));
-                desktop->setPosition(to_2geom(event_dt));                
+                desktop->setPosition(to_2geom(event_dt));
             }
             break;
     case GDK_BUTTON_RELEASE:
@@ -157,12 +158,13 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 gdk_pointer_ungrab(event->button.time);
                 Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                 Geom::Point event_dt(desktop->w2d(event_w));
-                
+
                 SnapManager &m = desktop->namedview->snap_manager;
                 m.setup(desktop);
                 m.guideSnap(event_dt, normal);
-                                
+
                 dragging = false;
+                sp_canvas_set_snap_delay_active(desktop->canvas, false);
                 gtk_object_destroy(GTK_OBJECT(guide));
                 guide = NULL;
                 if ((horiz ? wy : wx) >= 0) {
@@ -172,7 +174,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                     sp_repr_set_point(repr, "position", from_2geom(event_dt));
                     SP_OBJECT_REPR(desktop->namedview)->appendChild(repr);
                     Inkscape::GC::release(repr);
-                    sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE, 
+                    sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
                                      _("Create guide"));
                 }
                 desktop->set_coordinate_status(from_2geom(event_dt));
@@ -209,6 +211,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
        case GDK_2BUTTON_PRESS:
             if (event->button.button == 1) {
                 dragging = false;
+                sp_canvas_set_snap_delay_active(desktop->canvas, false);
                 sp_canvas_item_ungrab(item, event->button.time);
                 Inkscape::UI::Dialogs::GuidelinePropertiesDialog::showDialog(guide, desktop);
                 ret = TRUE;
@@ -224,6 +227,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     break;
                 }
                 dragging = true;
+                sp_canvas_set_snap_delay_active(desktop->canvas, true);
                 sp_canvas_item_grab(item,
                                     ( GDK_BUTTON_RELEASE_MASK  |
                                       GDK_BUTTON_PRESS_MASK    |
@@ -238,13 +242,13 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                 Geom::Point const motion_w(event->motion.x,
                                          event->motion.y);
                 Geom::Point motion_dt(to_2geom(desktop->w2d(from_2geom(motion_w))));
-                
-                // This is for snapping while dragging existing guidelines. New guidelines, 
+
+                // 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;
                 m.setup(desktop);
                 m.guideSnap(motion_dt, to_2geom(guide->normal_to_line));
-                
+
                 sp_guide_moveto(*guide, from_2geom(motion_dt), false);
                 moved = true;
                 desktop->set_coordinate_status(from_2geom(motion_dt));
@@ -280,6 +284,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     desktop->setPosition (from_2geom(event_dt));
                 }
                 dragging = false;
+                sp_canvas_set_snap_delay_active(desktop->canvas, false);
                 sp_canvas_item_ungrab(item, event->button.time);
                 ret=TRUE;
             }
@@ -406,7 +411,7 @@ void snoop_extended(GdkEvent* event, SPDesktop *desktop)
                 // device shows up.
                 it->second = tools_active(desktop);
             }
-            
+
             it = toolToUse.find(name);
             if (it != toolToUse.end() ) {
                 tools_switch(desktop, it->second);
index e5ef2c80d5bc92c4b9a92784cb69e6e4890ac271..edd64f021b5fcdc29ba6b0a993f5a5c16a5fd896 100644 (file)
@@ -946,8 +946,8 @@ 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 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);
 
 /**
@@ -1049,6 +1049,7 @@ sp_canvas_init (SPCanvas *canvas)
 
     canvas->watchdog_id = 0;
     canvas->watchdog_event = NULL;
+    canvas->context_snap_delay_active = false;
 }
 
 /**
@@ -1234,7 +1235,7 @@ sp_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
     }
 
     widget->allocation = *allocation;
-    
+
     if (GTK_WIDGET_REALIZED (widget)) {
         gdk_window_move_resize (widget->window,
                                 widget->allocation.x, widget->allocation.y,
@@ -1531,12 +1532,12 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
     case GDK_BUTTON_PRESS:
     case GDK_2BUTTON_PRESS:
     case GDK_3BUTTON_PRESS:
-       if (dt) { 
+       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. 
+               // 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.
          */
@@ -1547,8 +1548,8 @@ 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 
-        
+       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
          * after the button has been released
          */
@@ -1558,7 +1559,7 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
         canvas->state = event->state;
         pick_current_item (canvas, (GdkEvent *) event);
         event->state ^= mask;
-        
+
         break;
 
     default:
@@ -1594,7 +1595,7 @@ 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);
 
@@ -1605,61 +1606,53 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
 
     if (canvas->pixmap_gc == NULL) // canvas being deleted
         return FALSE;
-    
+
     SPDesktop *dt = SP_ACTIVE_DESKTOP;
-    
+
     // Snap when speed drops below e.g. 0.02 px/msec, or when no motion events have occured 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.
-    if (dt) {
-           bool const c1 = event->type == GDK_MOTION_NOTIFY;
-           bool const c21 = event->state & GDK_BUTTON1_MASK; // Snapping only occurs when dragging with the left mouse button down
-           bool const c22 = event->state & GDK_BUTTON2_MASK; // We shouldn't hold back any events when other mouse buttons have been
-           bool const c23 = 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
-           bool const c3 = dt->namedview->snap_manager.snapprefs.getSnapEnabledGlobally();
-           if (c1 && c21 && (!c22) && (!c23) && c3) {          
-               Geom::Point event_pos(event->x, event->y);
-               guint32 event_t = gdk_event_get_time ( (GdkEvent *) event );
-                       
-               dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true); // put snapping on hold
-                       
-               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 << "speed = " << speed << " px/msec " << "| time passed = " << delta_t << " 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 
-                               // stoppping 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);
+       if (canvas->context_snap_delay_active && dt && dt->namedview->snap_manager.snapprefs.getSnapEnabledGlobally()) {
+               Geom::Point event_pos(event->x, event->y);
+               guint32 event_t = gdk_event_get_time ( (GdkEvent *) event );
+
+               dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true); // put snapping on hold
+
+               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 << "speed = " << speed << " px/msec " << "| time passed = " << delta_t << " 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)
+                               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
                        }
-                               
-               prev_pos = event_pos;
-               prev_time = event_t;
-           }
+               } 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);
 
@@ -1672,50 +1665,80 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
     return status;
 }
 
-gboolean sp_canvas_snap_watchdog_callback(gpointer data) 
+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  
+       // 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) {
                return FALSE;
-       }       
-       
+       }
+
        SPDesktop *dt = SP_ACTIVE_DESKTOP;
        if (dt) {
                dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
        }
-       
+
        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) 
+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); 
+       canvas->watchdog_event = gdk_event_copy( (GdkEvent *) event);
 }
 
-void sp_canvas_snap_watchdog_kill(SPCanvas *canvas) 
+void sp_canvas_snap_watchdog_kill(SPCanvas *canvas)
 {
-       if (canvas->watchdog_id) { 
+       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)
 {
@@ -1731,7 +1754,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
     // Mark the region clean
     sp_canvas_mark_rect(canvas, x0, y0, x1, y1, 0);
 
-    buf.buf_rowstride = sw * 4; 
+    buf.buf_rowstride = sw * 4;
     buf.rect.x0 = x0;
     buf.rect.y0 = y0;
     buf.rect.x1 = x1;
@@ -2020,7 +2043,7 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1)
     } else {
         // paths only, so 1M works faster
         // 1M is the cached buffer and we need 4 channels
-        setup.max_pixels = 262144; 
+        setup.max_pixels = 262144;
     }
 
     // Start the clock
@@ -2282,7 +2305,7 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear,
 
     int ix = (int) round(cx); // ix and iy are the new canvas coordinates (integer screen pixels)
     int iy = (int) round(cy); // cx might be negative, so (int)(cx + 0.5) will not do!
-    int dx = ix - canvas->x0; // dx and dy specify the displacement (scroll) of the 
+    int dx = ix - canvas->x0; // dx and dy specify the displacement (scroll) of the
     int dy = iy - canvas->y0; // canvas w.r.t its previous position
 
     canvas->dx0 = cx; // here the 'd' stands for double, not delta!
index 2c416b8a759049c28090aebc2270816dc8d88c95..cb63374e1f1f500d3875fc88f30effb78aafe270 100644 (file)
@@ -193,9 +193,10 @@ 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();
@@ -217,6 +218,8 @@ 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 98fee29bf4bff9449b27ab296248b04179f7a319..5e3ff82dc4539154b6379478f8c0e370297d4db0 100644 (file)
@@ -697,7 +697,7 @@ spdc_flush_white(SPDrawContext *dc, SPCurve *gc)
             item->updateRepr();
         }
 
-        sp_document_done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL, 
+        sp_document_done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL,
                          _("Draw path"));
 
         // When quickly drawing several subpaths with Shift, the next subpath may be finished and
@@ -834,7 +834,7 @@ void spdc_create_single_dot(SPEventContext *ec, Geom::Point const &pt, char cons
     /* put the circle where the mouse click occurred and set the diameter to the
        current stroke width, multiplied by the amount specified in the preferences */
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-    
+
     Geom::Matrix const i2d (sp_item_i2d_affine (item));
     Geom::Point pp = pt * i2d;
     double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0);
index 1f6842a5ca34236cd5304338b36188b28a572639..985e3ac5153cecf1194f03502a2d4db8bacbdbc5 100644 (file)
@@ -144,11 +144,11 @@ guint32 sp_dropper_context_get_color(SPEventContext *ec)
 {
     SPDropperContext *dc = SP_DROPPER_CONTEXT(ec);
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-    
+
     int pick = prefs->getInt("/tools/dropper/pick",
                                        SP_DROPPER_PICK_VISIBLE);
     bool setalpha = prefs->getBool("/tools/dropper/setalpha", true);
-    
+
     return SP_RGBA32_F_COMPOSE(dc->R, dc->G, dc->B,
         (pick == SP_DROPPER_PICK_ACTUAL && setalpha) ? dc->alpha : 1.0);
 }
@@ -324,7 +324,7 @@ static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEv
 
 
                 if (!(sp_desktop_selection(desktop)->isEmpty())) {
-                    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_DROPPER, 
+                    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_DROPPER,
                                      _("Set picked color"));
                 }
 
index 8cab1690b5778ff48c3c9be53f4e29b1ebe50478..75aef13ef28a25b87211e28385673340f362f49a 100644 (file)
@@ -335,7 +335,7 @@ sp_dyna_draw_apply(SPDynaDrawContext *dc, Geom::Point p)
     // If force is below the absolute threshold DYNA_EPSILON,
     // or we haven't yet reached DYNA_VEL_START (i.e. at the beginning of stroke)
     // _and_ the force is below the (higher) DYNA_EPSILON_START threshold,
-    // discard this move. 
+    // discard this move.
     // This prevents flips, blobs, and jerks caused by microscopic tremor of the tablet pen,
     // especially bothersome at the start of the stroke where we don't yet have the inertia to
     // smooth them out.
@@ -433,7 +433,7 @@ sp_dyna_draw_brush(SPDynaDrawContext *dc)
     // get the real brush point, not the same as pointer (affected by hatch tracking and/or mass
     // drag)
     Geom::Point brush = sp_dyna_draw_get_vpoint(dc, dc->cur);
-    Geom::Point brush_w = SP_EVENT_CONTEXT(dc)->desktop->d2w(brush); 
+    Geom::Point brush_w = SP_EVENT_CONTEXT(dc)->desktop->d2w(brush);
 
     double trace_thick = 1;
     if (dc->trace_bg) {
@@ -617,7 +617,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                 } else {
                     dc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Select a guide path</b> to track with <b>Ctrl</b>"));
                 }
-            } 
+            }
 
             if ( dc->is_drawing && (event->motion.state & GDK_BUTTON1_MASK) && !event_context->space_panning) {
                 dc->dragging = TRUE;
@@ -712,7 +712,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                             } else {
                                 // looks like we're starting to lose speed,
                                 // so _gradually_ let go attraction to prevent jerks
-                                target = (dc->hatch_spacing * speed + hatch_dist * (SPEED_NORMAL - speed))/SPEED_NORMAL;                            
+                                target = (dc->hatch_spacing * speed + hatch_dist * (SPEED_NORMAL - speed))/SPEED_NORMAL;
                             }
                             if (!IS_NAN(dot) && dot < -0.5) {// flip
                                 target = -target;
@@ -735,7 +735,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                             }
 
                         } else {
-                            // this is the first motion event, set the dist 
+                            // this is the first motion event, set the dist
                             dc->hatch_spacing = hatch_dist;
                         }
 
@@ -773,8 +773,8 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             }
 
             // Draw the hatching circle if necessary
-            if (event->motion.state & GDK_CONTROL_MASK) { 
-                if (dc->hatch_spacing == 0 && hatch_dist != 0) { 
+            if (event->motion.state & GDK_CONTROL_MASK) {
+                if (dc->hatch_spacing == 0 && hatch_dist != 0) {
                     // Haven't set spacing yet: gray, center free, update radius live
                     Geom::Point c = desktop->w2d(motion_w);
                     Geom::Matrix const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
@@ -859,7 +859,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             dc->hatch_livarot_path = NULL;
             dc->just_started_drawing = false;
 
-            if (dc->hatch_spacing != 0 && !dc->keep_selected) { 
+            if (dc->hatch_spacing != 0 && !dc->keep_selected) {
                 // we do not select the newly drawn path, so increase spacing by step
                 if (dc->hatch_spacing_step == 0) {
                     dc->hatch_spacing_step = dc->hatch_spacing;
@@ -1026,7 +1026,7 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
         } else {
             if (dc->keep_selected) {
                 sp_desktop_selection(desktop)->set(dc->repr);
-            } 
+            }
         }
 
     } else {
@@ -1036,14 +1036,14 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
         dc->repr = NULL;
     }
 
-    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC, 
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC,
                      _("Draw calligraphic stroke"));
 }
 
 static void
 add_cap(SPCurve *curve,
         Geom::Point const &from,
-        Geom::Point const &to, 
+        Geom::Point const &to,
         double rounding)
 {
     if (Geom::L2( to - from ) > DYNA_EPSILON) {
@@ -1062,7 +1062,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
             dc->cal1->is_empty() ||
             dc->cal2->is_empty() ||
             (dc->cal1->get_segment_count() <= 0) ||
-            dc->cal1->first_path()->closed() 
+            dc->cal1->first_path()->closed()
             ) {
             dc->cal1->reset();
             dc->cal2->reset();
@@ -1072,7 +1072,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
         SPCurve *rev_cal2 = dc->cal2->create_reverse();
         if (
             (rev_cal2->get_segment_count() <= 0) ||
-            rev_cal2->first_path()->closed() 
+            rev_cal2->first_path()->closed()
             ) {
             rev_cal2->unref();
             dc->cal1->reset();
@@ -1089,7 +1089,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
             !dc_cal1_firstseg ||
             !rev_cal2_firstseg ||
             !dc_cal1_lastseg ||
-            !rev_cal2_lastseg 
+            !rev_cal2_lastseg
             ) {
             rev_cal2->unref();
             dc->cal1->reset();
index b4f52a7c9bf7fa909564ca540d335badf1d677fd..e9b46a2c29df5e3275d09c8a3d0af12665c68f79 100644 (file)
@@ -114,6 +114,8 @@ 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) {
@@ -140,7 +142,7 @@ const gchar *gr_handle_descr [] = {
     N_("Radial gradient <b>mid stop</b>")
 };
 
-static void 
+static void
 gradient_selection_changed (Inkscape::Selection *, gpointer data)
 {
     SPGradientContext *rc = (SPGradientContext *) data;
@@ -216,6 +218,8 @@ static void sp_gradient_context_setup(SPEventContext *ec)
     rc->selcon = new sigc::connection (selection->connectChanged( sigc::bind (sigc::ptr_fun(&gradient_selection_changed), rc)));
     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);
 }
 
 void
@@ -271,7 +275,7 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi
         // remember the coord of the dragger to reselect it later
         coords.push_back(dragger->point);
         // for all draggables of dragger
-        for (GSList const* j = dragger->draggables; j != NULL; j = j->next) { 
+        for (GSList const* j = dragger->draggables; j != NULL; j = j->next) {
             GrDraggable *d = (GrDraggable *) j->data;
 
             // find the gradient
@@ -279,9 +283,9 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi
             SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false);
 
             // these draggable types cannot have a next draggabe to insert a stop between them
-            if (d->point_type == POINT_LG_END || 
-                d->point_type == POINT_RG_FOCUS || 
-                d->point_type == POINT_RG_R1 || 
+            if (d->point_type == POINT_LG_END ||
+                d->point_type == POINT_RG_FOCUS ||
+                d->point_type == POINT_RG_R1 ||
                 d->point_type == POINT_RG_R2) {
                 continue;
             }
@@ -299,7 +303,7 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi
             // if there's a next stop,
             if (next_stop) {
                 GrDragger *dnext = NULL;
-                // find its dragger 
+                // find its dragger
                 // (complex because it may have different types, and because in radial,
                 // more than one dragger may correspond to a stop, so we must distinguish)
                 if (type == POINT_LG_BEGIN || type == POINT_LG_MID) {
@@ -311,14 +315,14 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi
                     if (type == POINT_RG_CENTER || type == POINT_RG_MID1) {
                         if (next_stop == last_stop)
                             dnext = drag->getDraggerFor (item, POINT_RG_R1, p_i+1, fs);
-                        else 
+                        else
                             dnext = drag->getDraggerFor (item, POINT_RG_MID1, p_i+1, fs);
-                    } 
-                    if ((type == POINT_RG_MID2) || 
+                    }
+                    if ((type == POINT_RG_MID2) ||
                         (type == POINT_RG_CENTER && dnext && !dnext->isSelected())) {
                         if (next_stop == last_stop)
                             dnext = drag->getDraggerFor (item, POINT_RG_R2, p_i+1, fs);
-                        else 
+                        else
                             dnext = drag->getDraggerFor (item, POINT_RG_MID2, p_i+1, fs);
                     }
                 }
@@ -354,7 +358,7 @@ sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc)
     if (g_slist_length(these_stops) == 0 && drag->numSelected() == 1) {
         // if a single stop is selected, add between that stop and the next one
         GrDragger *dragger = (GrDragger *) drag->selected->data;
-        for (GSList const* j = dragger->draggables; j != NULL; j = j->next) { 
+        for (GSList const* j = dragger->draggables; j != NULL; j = j->next) {
             GrDraggable *d = (GrDraggable *) j->data;
             SPGradient *gradient = sp_item_gradient (d->item, d->fill_or_stroke);
             SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false);
@@ -428,10 +432,10 @@ sp_gradient_simplify(SPGradientContext *rc, double tolerance)
                 guint32 const c0 = sp_stop_get_rgba32(stop0);
                 guint32 const c2 = sp_stop_get_rgba32(stop2);
                 guint32 const c1r = sp_stop_get_rgba32(stop1);
-                guint32 c1 = average_color (c0, c2, 
+                guint32 c1 = average_color (c0, c2,
                        (stop1->offset - stop0->offset) / (stop2->offset - stop0->offset));
 
-                double diff = 
+                double diff =
                     sqr(SP_RGBA32_R_F(c1) - SP_RGBA32_R_F(c1r)) +
                     sqr(SP_RGBA32_G_F(c1) - SP_RGBA32_G_F(c1r)) +
                     sqr(SP_RGBA32_B_F(c1) - SP_RGBA32_B_F(c1r)) +
@@ -630,7 +634,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
             } else {
                 dragging = false;
 
-                // unless clicked with Ctrl (to enable Ctrl+doubleclick).  
+                // unless clicked with Ctrl (to enable Ctrl+doubleclick).
                 if (event->button.state & GDK_CONTROL_MASK) {
                     ret = TRUE;
                     break;
@@ -667,7 +671,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                 event_context->item_to_select = NULL;
                 ret = TRUE;
             }
-            Inkscape::Rubberband::get(desktop)->stop(); 
+            Inkscape::Rubberband::get(desktop)->stop();
         }
         break;
     case GDK_KEY_PRESS:
index 0cb9fc423e410469a33994f2364ba0d5a17391ec..eaf5658f803dc5cb3db25637b366875dfece1846 100644 (file)
@@ -30,6 +30,8 @@
 #include "sp-pattern.h"
 #include "style.h"
 #include "live_effects/lpeobject.h"
+#include "desktop.h"
+#include "display/sp-canvas.h"
 
 #include "xml/repr.h" // for debugging only
 
@@ -53,6 +55,8 @@ KnotHolder::KnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFun
 
     this->repr = repr;
     this->local_change = FALSE;
+
+    this->dragging = false;
 }
 
 KnotHolder::~KnotHolder() {
@@ -89,7 +93,7 @@ KnotHolder::update_knots()
 void
 KnotHolder::knot_clicked_handler(SPKnot *knot, guint state)
 {
-    KnotHolder *knot_holder = this;
+       KnotHolder *knot_holder = this;
 
     for(std::list<KnotHolderEntity *>::iterator i = knot_holder->entity.begin(); i != knot_holder->entity.end(); ++i) {
         KnotHolderEntity *e = *i;
@@ -133,7 +137,12 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state)
 void
 KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state)
 {
-    // this was a local change and the knotholder does not need to be recreated:
+    if (this->dragging == false) {
+       this->dragging = true;
+       sp_canvas_set_snap_delay_active(desktop->canvas, true);
+    }
+
+       // this was a local change and the knotholder does not need to be recreated:
     this->local_change = TRUE;
 
     for(std::list<KnotHolderEntity *>::iterator i = this->entity.begin(); i != this->entity.end(); ++i) {
@@ -155,7 +164,10 @@ KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state)
 void
 KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/)
 {
-    if (this->released) {
+       this->dragging = false;
+       sp_canvas_set_snap_delay_active(desktop->canvas, false);
+
+       if (this->released) {
         this->released(this->item);
     } else {
         SPObject *object = (SPObject *) this->item;
index 310adab6192b15e87d1ee81fb08056c947333b53..fa1abd071efd4e226efdfcc5fb470f803b8c3184 100644 (file)
@@ -60,6 +60,8 @@ protected:
     SPKnotHolderReleasedFunc released;
 
     gboolean local_change; ///< if true, no need to recreate knotholder if repr was changed.
+
+    bool dragging;
 };
 
 /**
index add070d1f8b31571bc70ef390278eaa5911911dc..cc38acbe5183210d5bb599b2a182625523b6ddcc 100644 (file)
@@ -306,7 +306,7 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object,
         Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(object));
         if (lpe && lpe->isVisible() && lpe->showOrigPath()) {
             np->show_helperpath = true;
-        }            
+        }
     }
     np->straight_path = false;
     if (IS_LIVEPATHEFFECT(object) && item) {
@@ -314,7 +314,7 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object,
     } else {
         np->item = SP_ITEM(object);
     }
-    
+
     np->drag_origin_mouse = Geom::Point(NR_HUGE, NR_HUGE);
 
     // we need to update item's transform from the repr here,
@@ -1064,7 +1064,7 @@ static void sp_nodepath_set_line_type(Inkscape::NodePath::Node *end, NRPathcode
                 start->type = Inkscape::NodePath::NODE_SMOOTH;
             if (end->type == Inkscape::NodePath::NODE_AUTO)
                 end->type = Inkscape::NodePath::NODE_SMOOTH;
-    
+
             start->n.pos = start->pos;
             end->p.pos = end->pos;
 
@@ -1152,10 +1152,10 @@ sp_node_side_is_line (Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeSi
             other_to_me = &othernode->n;
         } else if (&node->n == side) {
             other_to_me = &othernode->p;
-        } 
+        }
         if (!other_to_me)
             return false;
-        bool is_line = 
+        bool is_line =
              (Geom::L2(othernode->pos - other_to_me->pos) < 1e-6 &&
               Geom::L2(node->pos - side->pos) < 1e-6);
         return is_line;
@@ -1164,7 +1164,7 @@ sp_node_side_is_line (Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeSi
 /**
  * Same as sp_nodepath_set_node_type(), but also converts, if necessary, adjacent segments from
  * lines to curves.  If adjacent to one line segment, pulls out or rotates opposite handle to align
- * with that segment, procucing half-smooth node. If already half-smooth, pull out the second handle too. 
+ * with that segment, procucing half-smooth node. If already half-smooth, pull out the second handle too.
  * If already cusp and set to cusp, retracts handles.
 */
 void sp_nodepath_convert_node_type(Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeType type)
@@ -1178,9 +1178,9 @@ void sp_nodepath_convert_node_type(Inkscape::NodePath::Node *node, Inkscape::Nod
 
     if (type == Inkscape::NodePath::NODE_SYMM || type == Inkscape::NodePath::NODE_SMOOTH) {
 
-/* 
+/*
   Here's the algorithm of converting node to smooth (Shift+S or toolbar button), in pseudocode:
+
         if (two_handles) {
             // do nothing, adjust_handles called via set_node_type will line them up
         } else if (one_handle) {
@@ -1337,19 +1337,19 @@ void sp_node_moveto(Inkscape::NodePath::Node *node, Geom::Point p)
  * Call sp_node_moveto() for node selection and handle possible snapping.
  */
 static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, Geom::Coord dx, Geom::Coord dy,
-                                            bool const snap, bool constrained = false, 
+                                            bool const snap, bool constrained = false,
                                             Inkscape::Snapper::ConstraintLine const &constraint = Geom::Point())
 {
     Geom::Point delta(dx, dy);
     Geom::Point best_pt = delta;
     Inkscape::SnappedPoint best;
-    
-    if (snap) {    
+
+    if (snap) {
         /* When dragging a (selected) node, it should only snap to other nodes (i.e. unselected nodes), and
-         * not to itself. The snapper however can not tell which nodes are selected and which are not, so we 
+         * not to itself. The snapper however can not tell which nodes are selected and which are not, so we
          * must provide that information. */
-          
-        // Build a list of the unselected nodes to which the snapper should snap 
+
+        // Build a list of the unselected nodes to which the snapper should snap
         std::vector<Geom::Point> unselected_nodes;
         for (GList *spl = nodepath->subpaths; spl != NULL; spl = spl->next) {
             Inkscape::NodePath::SubPath *subpath = (Inkscape::NodePath::SubPath *) spl->data;
@@ -1357,20 +1357,20 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath,
                 Inkscape::NodePath::Node *node = (Inkscape::NodePath::Node *) nl->data;
                 if (!node->selected) {
                     unselected_nodes.push_back(to_2geom(node->pos));
-                }    
+                }
             }
-        }        
-        
+        }
+
         SnapManager &m = nodepath->desktop->namedview->snap_manager;
-        
-        // When only the node closest to the mouse pointer is to be snapped 
+
+        // When only the node closest to the mouse pointer is to be snapped
         // then we will not even try to snap to other points and discard those immediately
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-        bool closest_only = prefs->getBool("/options/snapclosestonly/value", false); 
-        
+        bool closest_only = prefs->getBool("/options/snapclosestonly/value", false);
+
         Inkscape::NodePath::Node *closest_node = NULL;
         Geom::Coord closest_dist = NR_HUGE;
-        
+
        if (closest_only) {
                for (GList *l = nodepath->selected; l != NULL; l = l->next) {
                        Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
@@ -1379,25 +1379,25 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath,
                                closest_node = n;
                                closest_dist = dist;
                        }
-               }                       
+               }
         }
-        
+
        // Iterate through all selected nodes
        m.setup(nodepath->desktop, false, SP_PATH(nodepath->item), &unselected_nodes);
        for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
             if (!closest_only || n == closest_node) { //try to snap either all selected nodes or only the closest one
-                   Inkscape::SnappedPoint s;            
+                   Inkscape::SnappedPoint s;
                    if (constrained) {
                        Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint;
                        dedicated_constraint.setPoint(n->pos);
                        s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta), dedicated_constraint);
                    } else {
                        s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta));
-                   }            
-                   
+                   }
+
                    if (s.getSnapped()) {
-                       s.setPointerDistance(Geom::L2(nodepath->drag_origin_mouse - n->origin));                            
+                       s.setPointerDistance(Geom::L2(nodepath->drag_origin_mouse - n->origin));
                        if (!s.isOtherSnapBetter(best, true)) {
                                best = s;
                                best_pt = from_2geom(s.getPoint()) - n->pos;
@@ -1405,11 +1405,11 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath,
                    }
             }
         }
-                        
+
         if (best.getSnapped()) {
             nodepath->desktop->snapindicator->set_new_snaptarget(best);
         } else {
-            nodepath->desktop->snapindicator->remove_snaptarget();    
+            nodepath->desktop->snapindicator->remove_snaptarget();
         }
     }
 
@@ -2296,13 +2296,13 @@ static void do_node_selected_join(Inkscape::NodePath::Path *nodepath, Inkscape::
     }
 
     if (b == sb->first) {
-        // copy all nodes from b to a, forward 
+        // copy all nodes from b to a, forward
         sp_nodepath_node_new(sa, NULL,Inkscape::NodePath::NODE_CUSP, code, &p, &c, &sb->first->n.pos);
         for (n = sb->first->n.other; n != NULL; n = n->n.other) {
             sp_nodepath_node_new(sa, NULL, (Inkscape::NodePath::NodeType)n->type, (NRPathcode)n->code, &n->p.pos, &n->pos, &n->n.pos);
         }
     } else if (b == sb->last) {
-        // copy all nodes from b to a, backward 
+        // copy all nodes from b to a, backward
         sp_nodepath_node_new(sa, NULL,Inkscape::NodePath::NODE_CUSP, code, &p, &c, &sb->last->p.pos);
         for (n = sb->last->p.other; n != NULL; n = n->p.other) {
             sp_nodepath_node_new(sa, NULL, (Inkscape::NodePath::NodeType)n->type, (NRPathcode)n->n.other->code, &n->n.pos, &n->pos, &n->p.pos);
@@ -3333,7 +3333,7 @@ static void sp_node_adjust_handle(Inkscape::NodePath::Node *node, gint which_adj
     }
 
     if (node->type == Inkscape::NodePath::NODE_SYMM) {
-        // symmetrize 
+        // symmetrize
         me->pos = 2 * node->pos - other->pos;
         return;
     } else {
@@ -3403,16 +3403,16 @@ static void sp_node_adjust_handles_auto(Inkscape::NodePath::Node *node)
 
     Geom::Point leg_prev = to_2geom(node->p.other->pos - node->pos);
     Geom::Point leg_next = to_2geom(node->n.other->pos - node->pos);
+
     double norm_leg_prev = Geom::L2(leg_prev);
     double norm_leg_next = Geom::L2(leg_next);
+
     Geom::Point delta;
     if (norm_leg_next > 0.0) {
         delta = (norm_leg_prev / norm_leg_next) * leg_next - leg_prev;
         delta.normalize();
     }
+
     node->p.pos = node->pos - norm_leg_prev / 3 * delta;
     node->n.pos = node->pos + norm_leg_next / 3 * delta;
 }
@@ -3584,9 +3584,10 @@ 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);
     // 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;  
-    
+    n->subpath->nodepath->drag_origin_mouse = knot->grabbed_rel_pos + knot->drag_origin;
+
     sp_canvas_force_full_redraw_after_interruptions(n->subpath->nodepath->desktop->canvas, 5);
 
     sp_nodepath_remember_origins (n->subpath->nodepath);
@@ -3601,6 +3602,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);
    n->subpath->nodepath->drag_origin_mouse = Geom::Point(NR_HUGE, NR_HUGE);
    sp_canvas_end_forced_full_redraws(n->subpath->nodepath->desktop->canvas);
 
@@ -3798,16 +3800,16 @@ node_request(SPKnot */*knot*/, Geom::Point const &p, guint state, gpointer data)
             // move the node to the closest point
             sp_nodepath_selected_nodes_move(n->subpath->nodepath,
                                             n->origin[Geom::X] + c[Geom::X] - n->pos[Geom::X],
-                                            n->origin[Geom::Y] + c[Geom::Y] - n->pos[Geom::Y], 
+                                            n->origin[Geom::Y] + c[Geom::Y] - n->pos[Geom::Y],
                                             true);
 
         } else {  // constraining to hor/vert
 
             if (fabs(p[Geom::X] - n->origin[Geom::X]) > fabs(p[Geom::Y] - n->origin[Geom::Y])) { // snap to hor
                 sp_nodepath_selected_nodes_move(n->subpath->nodepath,
-                                                p[Geom::X] - n->pos[Geom::X], 
+                                                p[Geom::X] - n->pos[Geom::X],
                                                 n->origin[Geom::Y] - n->pos[Geom::Y],
-                                                true, 
+                                                true,
                                                 true, Inkscape::Snapper::ConstraintLine(component_vectors[Geom::X]));
             } else { // snap to vert
                 sp_nodepath_selected_nodes_move(n->subpath->nodepath,
@@ -3935,10 +3937,10 @@ static gboolean node_handle_request(SPKnot *knot, Geom::Point &p, guint state, g
     SnapManager &m = desktop->namedview->snap_manager;
     m.setup(desktop, true, n->subpath->nodepath->item);
     Inkscape::SnappedPoint s;
-    
+
     if ((state & GDK_SHIFT_MASK) != 0) {
        // We will not try to snap when the shift-key is pressed
-       // so remove the old snap indicator and don't wait for it to time-out  
+       // so remove the old snap indicator and don't wait for it to time-out
        desktop->snapindicator->remove_snaptarget();
     }
 
@@ -3968,7 +3970,7 @@ static gboolean node_handle_request(SPKnot *knot, Geom::Point &p, guint state, g
             s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
         }
     }
-    
+
     s.getPoint(p);
 
     sp_node_adjust_handle(n, -which);
@@ -4613,7 +4615,7 @@ sp_nodepath_node_new(Inkscape::NodePath::SubPath *sp, Inkscape::NodePath::Node *
     n->pos      = *pos;
     n->p.pos    = *ppos;
     n->n.pos    = *npos;
-    
+
     n->dragging_out = NULL;
 
     Inkscape::NodePath::Node *prev;
index 1762d668c00d3ba7ccffaffe10b47b25b3eacaf8..804c736bee91c1af5b30dbf913674810eefa6d43 100644 (file)
@@ -148,7 +148,7 @@ sp_pen_context_init(SPPenContext *pc)
     pc->c1 = NULL;
     pc->cl0 = NULL;
     pc->cl1 = NULL;
-    
+
     pc->events_disabled = 0;
 
     pc->num_clicks = 0;
@@ -209,6 +209,8 @@ 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);
     }
@@ -241,7 +243,7 @@ sp_pen_context_setup(SPEventContext *ec)
 }
 
 static void
-pen_cancel (SPPenContext *const pc) 
+pen_cancel (SPPenContext *const pc)
 {
     pc->num_clicks = 0;
     pc->state = SP_PEN_CONTEXT_STOP;
@@ -264,6 +266,8 @@ sp_pen_context_finish(SPEventContext *ec)
 {
     SPPenContext *pc = SP_PEN_CONTEXT(ec);
 
+    sp_canvas_set_snap_delay_active(pc->desktop->canvas, false);
+
     if (pc->npoints != 0) {
         pen_cancel (pc);
     }
@@ -332,7 +336,7 @@ spdc_endpoint_snap_handle(SPPenContext const *const pc, Geom::Point &p, guint co
     }
 }
 
-static gint 
+static gint
 sp_pen_context_item_handler(SPEventContext *ec, SPItem *item, GdkEvent *event)
 {
     SPPenContext *const pc = SP_PEN_CONTEXT(ec);
@@ -417,7 +421,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
     SPDrawContext * const dc = SP_DRAW_CONTEXT(pc);
     SPDesktop * const desktop = SP_EVENT_CONTEXT_DESKTOP(dc);
     Geom::Point const event_w(bevent.x, bevent.y);
-    Geom::Point const event_dt(desktop->w2d(event_w));
+    Geom::Point event_dt(desktop->w2d(event_w));
     SPEventContext *event_context = SP_EVENT_CONTEXT(pc);
 
     gint ret = FALSE;
@@ -453,7 +457,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
                     case SP_PEN_CONTEXT_CLOSE:
                         break;
                     case SP_PEN_CONTEXT_STOP:
-                        /* This is allowed, if we just cancelled curve */
+                        /* This is allowed, if we just canceled curve */
                         pc->state = SP_PEN_CONTEXT_POINT;
                         break;
                     default:
@@ -463,13 +467,20 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
             case SP_PEN_CONTEXT_MODE_DRAG:
                 switch (pc->state) {
                     case SP_PEN_CONTEXT_STOP:
-                        /* This is allowed, if we just cancelled curve */
+                        /* This is allowed, if we just canceled curve */
                     case SP_PEN_CONTEXT_POINT:
                         if (pc->npoints == 0) {
 
+                               Geom::Point p;
                             if (bevent.state & GDK_CONTROL_MASK) {
-                                spdc_create_single_dot(event_context, event_dt, "/tools/freehand/pen", bevent.state);
-                                ret = TRUE;
+                               p = event_dt;
+                               if (!(bevent.state & GDK_SHIFT_MASK)) {
+                                       SnapManager &m = desktop->namedview->snap_manager;
+                                       m.setup(desktop);
+                                                                       m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
+                               }
+                                                               spdc_create_single_dot(event_context, p, "/tools/freehand/pen", bevent.state);
+                                                               ret = TRUE;
                                 break;
                             }
 
@@ -478,7 +489,6 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
 
                             /* Set start anchor */
                             pc->sa = anchor;
-                            Geom::Point p;
                             if (anchor && !sp_pen_context_has_waiting_LPE(pc)) {
                                 /* Adjust point to anchor if needed; if we have a waiting LPE, we need
                                    a fresh path to be created so don't continue an existing one */
@@ -591,7 +601,7 @@ pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion const &mevent)
         // allow scrolling
         return FALSE;
     }
-   
+
     if (pc->events_disabled) {
         // skip motion events if pen events are disabled
         return FALSE;
@@ -765,7 +775,7 @@ pen_handle_button_release(SPPenContext *const pc, GdkEventButton const &revent)
                         ret = TRUE;
                         break;
                     case SP_PEN_CONTEXT_STOP:
-                        /* This is allowed, if we just cancelled curve */
+                        /* This is allowed, if we just canceled curve */
                         pc->state = SP_PEN_CONTEXT_POINT;
                         ret = TRUE;
                         break;
@@ -964,7 +974,8 @@ pen_lastpoint_toline (SPPenContext *const pc)
 static gint
 pen_handle_key_press(SPPenContext *const pc, GdkEvent *event)
 {
-    gint ret = FALSE;
+
+       gint ret = FALSE;
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     gdouble const nudge = prefs->getDoubleLimited("/options/nudgedistance/value", 2, 0, 1000); // in px
 
@@ -1201,7 +1212,7 @@ spdc_pen_set_initial_point(SPPenContext *const pc, Geom::Point const p)
  * Show the status message for the current line/curve segment.
  * This type of message always shows angle/distance as the last
  * two parameters ("angle %3.2f&#176;, distance %s").
- */ 
+ */
 static void
 spdc_pen_set_angle_distance_status_message(SPPenContext *const pc, Geom::Point const p, int pc_point_to_compare, gchar const *message)
 {
@@ -1343,7 +1354,7 @@ spdc_pen_finish(SPPenContext *const pc, gboolean const closed)
     pc->num_clicks = 0;
 
     pen_disable_events(pc);
-    
+
     SPDesktop *const desktop = pc->desktop;
     pc->_message_context->clear();
     desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Drawing finished"));
@@ -1379,7 +1390,7 @@ pen_disable_events(SPPenContext *const pc) {
 static void
 pen_enable_events(SPPenContext *const pc) {
   g_return_if_fail(pc->events_disabled != 0);
-  
+
   pc->events_disabled--;
 }
 
index d089146b808171f016d4ba2ca59adba64fa7de8f..a8c3112acd0617ce65e091d5c2d5bdf29f5bb088 100644 (file)
@@ -252,9 +252,17 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
                 break;
             default:
                 /* Set first point of sequence */
+               SnapManager &m = desktop->namedview->snap_manager;
+                               m.setup(desktop);
+                               sp_canvas_set_snap_delay_active(desktop->canvas, true);
+
                 if (bevent.state & GDK_CONTROL_MASK) {
-                    spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state);
-                    ret = true;
+                       if (!(bevent.state & GDK_SHIFT_MASK)) {
+                               m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
+                       }
+                                       spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state);
+                                       sp_canvas_set_snap_delay_active(desktop->canvas, false);
+                                       ret = true;
                     break;
                 }
                 if (anchor) {
@@ -263,23 +271,15 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
                 } else {
 
                     if (!(bevent.state & GDK_SHIFT_MASK)) {
-
-                        // This is the first click of a new curve; deselect item so that
+                                               // This is the first click of a new curve; deselect item so that
                         // this curve is not combined with it (unless it is drawn from its
                         // anchor, which is handled by the sibling branch above)
                         selection->clear();
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path"));
-                        SnapManager &m = desktop->namedview->snap_manager;
-                        m.setup(desktop);
-                        Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
-                        if (s.getSnapped()) {
-                               s.getPoint(p);
-                               pc->prev_snap_was_succesful = true;
-                        } else {
-                               pc->prev_snap_was_succesful = false;
-                        }
+                        m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
                     } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) {
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path"));
+                        m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
                     }
                 }
                 pc->sa = anchor;
@@ -296,14 +296,15 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
 static gint
 pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mevent)
 {
-    if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) {
+       SPDesktop *const dt = pc->desktop;
+
+       if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) {
         // mouse was accidentally moved during Ctrl+click;
         // ignore the motion and create a single point
         pc->is_drawing = false;
         return TRUE;
     }
     gint ret = FALSE;
-    SPDesktop *const dt = pc->desktop;
 
     SPEventContext *event_context = SP_EVENT_CONTEXT(pc);
     if (event_context->space_panning || mevent.state & GDK_BUTTON2_MASK || mevent.state & GDK_BUTTON3_MASK) {
@@ -355,7 +356,11 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
         default:
             /* We may be idle or already freehand */
             if ( mevent.state & GDK_BUTTON1_MASK && pc->is_drawing ) {
-                pc->state = SP_PENCIL_CONTEXT_FREEHAND;
+                if (pc->state == SP_PENCIL_CONTEXT_IDLE) {
+                       sp_canvas_set_snap_delay_active(dt->canvas, false);
+                }
+               pc->state = SP_PENCIL_CONTEXT_FREEHAND;
+
                 if ( !pc->sa && !pc->green_anchor ) {
                     /* Create green anchor */
                     pc->green_anchor = sp_draw_anchor_new(pc, pc->green_curve, TRUE, pc->p[0]);
@@ -364,27 +369,13 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
                  * fixme: I am not sure whether we want to snap to anchors
                  * in middle of freehand (Lauris)
                  */
-                SnapManager &m = dt->namedview->snap_manager;
-                
                 if (anchor) {
                     p = anchor->dp;
-                } else if ((mevent.state & GDK_SHIFT_MASK) == 0) {
-                    m.setup(dt);
-                    Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
-                    if (s.getSnapped()) {
-                       s.getPoint(p);
-                       pc->prev_snap_was_succesful = true;
-                    } else {
-                       pc->prev_snap_was_succesful = false;
-                    }
                 }
+
                 if ( pc->npoints != 0) { // buttonpress may have happened before we entered draw context!
-                       if (!(pc->prev_snap_was_succesful && m.snapprefs.getSnapPostponedGlobally())) {
-                           // When snapping is enabled but temporarily on hold because the mouse is moving 
-                        // fast, then we don't want to add nodes off-grid
-                        spdc_add_freehand_point(pc, p, mevent.state);
-                           ret = TRUE;
-                       }
+                                       spdc_add_freehand_point(pc, p, mevent.state);
+                                       ret = TRUE;
                 }
 
                 if (anchor && !pc->anchor_statusbar) {
@@ -436,6 +427,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
                 if (!(revent.state & GDK_CONTROL_MASK)) {
                     // Ctrl+click creates a single point so only set context in ADDLINE mode when Ctrl isn't pressed
                     pc->state = SP_PENCIL_CONTEXT_ADDLINE;
+                    //sp_canvas_set_snap_delay_active(dt->canvas, true);
                 }
                 ret = TRUE;
                 break;
@@ -450,6 +442,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);
                 ret = TRUE;
                 break;
             case SP_PENCIL_CONTEXT_FREEHAND:
@@ -463,6 +456,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);
                 } else {
                     /* Finish segment now */
                     /// \todo fixme: Clean up what follows (Lauris)
@@ -482,6 +476,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);
                     // reset sketch mode too
                     pc->sketch_n = 0;
                 }
@@ -504,7 +499,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re
 }
 
 static void
-pencil_cancel (SPPencilContext *const pc) 
+pencil_cancel (SPPencilContext *const pc)
 {
     if (pc->grab) {
         /* Release grab now */
@@ -513,8 +508,8 @@ 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);
 
     pc->red_curve->reset();
     sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL);
@@ -605,6 +600,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);
                 pc->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Finishing freehand sketch"));
                 ret = TRUE;
             }
@@ -715,11 +711,13 @@ static void
 interpolate(SPPencilContext *pc)
 {
 
-    g_assert( pc->ps.size() > 1 );
+    if ( pc->ps.size() <= 1 ) {
+       return;
+    }
 
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
-    double const tolerance_sq = 0.02 * square( pc->desktop->w2d().descrim() * 
+    double const tolerance_sq = 0.02 * square( pc->desktop->w2d().descrim() *
                                                tol) * exp(0.2*tol - 2);
 
     g_assert(is_zero(pc->req_tangent)
@@ -733,7 +731,7 @@ interpolate(SPPencilContext *pc)
 
     Geom::Point * b = g_new(Geom::Point, 4*n_points);
     Geom::Point * points = g_new(Geom::Point, 4*n_points);
-    for (unsigned int i = 0; i < pc->ps.size(); i++) { 
+    for (unsigned int i = 0; i < pc->ps.size(); i++) {
         points[i] = pc->ps[i];
     }
 
@@ -747,7 +745,7 @@ interpolate(SPPencilContext *pc)
     {
         /* Fit and draw and reset state */
         pc->green_curve->moveto(b[0]);
-        for (int c = 0; c < n_segs; c++) { 
+        for (int c = 0; c < n_segs; c++) {
             pc->green_curve->curveto(b[4*c+1], b[4*c+2], b[4*c+3]);
         }
         sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), pc->green_curve);
@@ -781,7 +779,7 @@ sketch_interpolate(SPPencilContext *pc)
 
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
-    double const tolerance_sq = 0.02 * square( pc->desktop->w2d().descrim() * 
+    double const tolerance_sq = 0.02 * square( pc->desktop->w2d().descrim() *
                                                tol) * exp(0.2*tol - 2);
 
     bool average_all_sketches = prefs->getBool("/tools/freehand/pencil/average_all_sketches", true);
@@ -796,7 +794,7 @@ sketch_interpolate(SPPencilContext *pc)
 
     Geom::Point * b = g_new(Geom::Point, 4*n_points);
     Geom::Point * points = g_new(Geom::Point, 4*n_points);
-    for (unsigned i = 0; i < pc->ps.size(); i++) { 
+    for (unsigned i = 0; i < pc->ps.size(); i++) {
         points[i] = pc->ps[i];
     }
 
@@ -809,7 +807,7 @@ sketch_interpolate(SPPencilContext *pc)
     if ( n_segs > 0)
     {
         Geom::Path fit(b[0]);
-        for (int c = 0; c < n_segs; c++) { 
+        for (int c = 0; c < n_segs; c++) {
             fit.appendNew<Geom::CubicBezier>(b[4*c+1], b[4*c+2], b[4*c+3]);
         }
         Geom::Piecewise<Geom::D2<Geom::SBasis> > fit_pwd2 = fit.toPwSb();
@@ -866,7 +864,7 @@ fit_and_split(SPPencilContext *pc)
              || is_unit_vector(pc->req_tangent));
     Geom::Point const tHatEnd(0, 0);
     int const n_segs = Geom::bezier_fit_cubic_full(b, NULL, pc->p, pc->npoints,
-                                                pc->req_tangent, tHatEnd, 
+                                                pc->req_tangent, tHatEnd,
                                                 tolerance_sq, 1);
     if ( n_segs > 0
          && unsigned(pc->npoints) < G_N_ELEMENTS(pc->p) )
index c3b34b6473e995ee86920dad43cb2494c4f66c19..cbcf2b98e4e16afed55642605934a22c77255251 100644 (file)
@@ -31,7 +31,6 @@ struct SPPencilContext : public SPDrawContext {
     Geom::Point req_tangent;
 
     bool is_drawing;
-    bool prev_snap_was_succesful;
 
     std::vector<Geom::Point> ps;
 
index 65292851be4c59c79e1a67957a456af8248ea2a5..c63e1dc2ab5505db9f10a90b3a58ff35f2461545 100644 (file)
@@ -151,7 +151,7 @@ void sp_rect_context_selection_changed(Inkscape::Selection *selection, gpointer
     SPEventContext *ec = SP_EVENT_CONTEXT(rc);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     ec->shape_editor->set_item(item, SH_KNOTHOLDER);
 }
 
@@ -257,17 +257,18 @@ 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);
 
             /* Position center */
             Geom::Point button_dt(desktop->w2d(button_w));
             rc->center = from_2geom(button_dt);
-            
+
             /* Snap center */
             SnapManager &m = desktop->namedview->snap_manager;
             m.setup(desktop);
             m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt);
             rc->center = from_2geom(button_dt);
-            
+
             sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
                                 ( GDK_KEY_PRESS_MASK |
                                   GDK_BUTTON_RELEASE_MASK       |
@@ -275,7 +276,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
                                   GDK_POINTER_MOTION_HINT_MASK       |
                                   GDK_BUTTON_PRESS_MASK ),
                                 NULL, event->button.time);
-                                
+
             ret = TRUE;
         }
         break;
@@ -295,7 +296,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
 
             Geom::Point const motion_w(event->motion.x, event->motion.y);
             Geom::Point motion_dt(desktop->w2d(motion_w));
-            
+
             sp_rect_drag(*rc, motion_dt, event->motion.state); // this will also handle the snapping
             gobble_motion_events(GDK_BUTTON1_MASK);
             ret = TRUE;
@@ -305,6 +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);
 
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the rect
@@ -379,6 +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);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the rect
                     sp_rect_finish(rc);
index 1daf6b0e56967be6363dfba5b2c67f47feb2b4df..c7b305dd201aee4fd63487469a607cfefa216d8c 100644 (file)
@@ -326,7 +326,7 @@ sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkE
                     sc->moved = FALSE;
 
                     sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
-                    
+
                     // remember the clicked item in sc->item:
                     if (sc->item) {
                         sp_object_unref(sc->item, NULL);
@@ -511,10 +511,10 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                             item_in_group = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), TRUE);
                             group_at_point = desktop->group_at_point(Geom::Point(event->button.x, event->button.y));
 
-                            // group-at-point is meant to be topmost item if it's a group, 
+                            // group-at-point is meant to be topmost item if it's a group,
                             // not topmost group of all items at point
-                            if (group_at_point != item_in_group && 
-                                !(group_at_point && item_at_point && 
+                            if (group_at_point != item_in_group &&
+                                !(group_at_point && item_at_point &&
                                   group_at_point->isAncestorOf(item_at_point)))
                                 group_at_point = NULL;
 
@@ -673,7 +673,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                     sp_canvas_item_ungrab(sc->grabbed, event->button.time);
                     sc->grabbed = NULL;
                 }
-                
+
                 desktop->updateNow();
             }
             if (event->button.button == 1) {
@@ -902,7 +902,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
                         }
                         ret = TRUE;
                     }
-                    break;                  
+                    break;
                 case GDK_g:
                 case GDK_G:
                     if (MOD__SHIFT_ONLY) {
index 0fd15593c78ae910c35670e33bc357a6e8354ea5..b1917edfd523393abfe150eea325634e1a0ca162 100644 (file)
@@ -366,6 +366,8 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
        }
     }
 
+       sp_canvas_set_snap_delay_active(_desktop->canvas, true);
+
     // The lines below are useful for debugging any snapping issues, as they'll spit out all points that are considered for snapping
 
     /*std::cout << "Number of snap points:  " << _snap_points.size() << std::endl;
@@ -432,6 +434,8 @@ void Inkscape::SelTrans::ungrab()
     _grabbed = false;
     _show_handles = true;
 
+    sp_canvas_set_snap_delay_active(_desktop->canvas, false);
+
     Inkscape::Selection *selection = sp_desktop_selection(_desktop);
     _updateVolatileState();
 
index 24cfefe0ba53024633648f31a275a5e41d597560..11ba077e449976e42031fd4112a347c9b5f8b621 100644 (file)
@@ -13,7 +13,7 @@
  *
  * Copyright (C) 2006-2007 Johan Engelen <johan@shouraizou.nl>
  * Copyrigth (C) 2004      Nathan Hurst
- * Copyright (C) 1999-2008 Authors
+ * Copyright (C) 1999-2009 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -162,7 +162,12 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp
                                              bool first_point,
                                              Geom::OptRect const &bbox_to_snap) const
 {
-    if (!someSnapperMightSnap()) {
+       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 (!someSnapperMightSnap()) {
         return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false);
     }
 
@@ -286,7 +291,12 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P
                                                     bool first_point,
                                                     Geom::OptRect const &bbox_to_snap) const
 {
-    if (!someSnapperMightSnap()) {
+       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 (!someSnapperMightSnap()) {
         return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false);
     }
 
@@ -317,6 +327,11 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con
 {
     // This method is used to snap a guide to nodes, while dragging the guide around
 
+       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 ( !(object.GuidesMightSnap() && snapprefs.getSnapEnabledGlobally()) || snapprefs.getSnapPostponedGlobally() ) {
         return;
     }
index ce9ea1e03fabbbafb96c4c71eac50a72d188fc89..35d5144a7881d58f8b67f87321bd848fc10b6fa6 100644 (file)
@@ -149,7 +149,7 @@ sp_spiral_context_selection_changed(Inkscape::Selection *selection, gpointer dat
     SPEventContext *ec = SP_EVENT_CONTEXT(sc);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     ec->shape_editor->set_item(item, SH_KNOTHOLDER);
 }
 
@@ -221,6 +221,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);
                 sc->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
 
                 SnapManager &m = desktop->namedview->snap_manager;
@@ -254,7 +255,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
 
                 Geom::Point const motion_w(event->motion.x, event->motion.y);
                 Geom::Point motion_dt(event_context->desktop->w2d(motion_w));
-                
+
                 SnapManager &m = desktop->namedview->snap_manager;
                 m.setup(desktop, true, sc->item);
                 m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt);
@@ -269,6 +270,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);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the spiral
                     sp_spiral_finish(sc);
@@ -328,6 +330,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);
                         if (!event_context->within_tolerance) {
                             // we've been dragging, finish the rect
                             sp_spiral_finish(sc);
@@ -404,8 +407,8 @@ sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state)
     m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g);
 
     Geom::Point const p0 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, sc->center));
-    Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g)));        
-    
+    Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g)));
+
     SPSpiral *spiral = SP_SPIRAL(sc->item);
 
     Geom::Point const delta = p1 - p0;
@@ -447,7 +450,7 @@ sp_spiral_finish(SPSpiralContext *sc)
         sp_canvas_end_forced_full_redraws(desktop->canvas);
 
         sp_desktop_selection(desktop)->set(sc->item);
-        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL, 
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL,
                          _("Create spiral"));
 
         sc->item = NULL;
index 9dc2db296dcb978d09c40f14b2d9edf518051107..da79d4719a9852ce62e294b91516ac7e919f9750 100644 (file)
@@ -156,7 +156,7 @@ sp_star_context_selection_changed (Inkscape::Selection * selection, gpointer dat
     SPEventContext *ec = SP_EVENT_CONTEXT (sc);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     ec->shape_editor->set_item(item, SH_KNOTHOLDER);
 }
 
@@ -202,7 +202,7 @@ sp_star_context_set (SPEventContext *ec, Inkscape::Preferences::Entry *val)
 {
     SPStarContext *sc = SP_STAR_CONTEXT (ec);
     Glib::ustring path = val->getEntryName();
-    
+
     if (path == "magnitude") {
         sc->magnitude = CLAMP (val->getInt(5), 3, 1024);
     } else if (path == "proportion") {
@@ -235,9 +235,10 @@ 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);
 
             sc->center = Inkscape::setup_for_drag_start(desktop, event_context, event);
-            
+
             /* Snap center */
             SnapManager &m = desktop->namedview->snap_manager;
             m.setup(desktop, true);
@@ -269,7 +270,7 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent
 
             Geom::Point const motion_w(event->motion.x, event->motion.y);
             Geom::Point motion_dt(desktop->w2d(motion_w));
-            
+
             sp_star_drag (sc, motion_dt, event->motion.state);
 
             gobble_motion_events(GDK_BUTTON1_MASK);
@@ -281,6 +282,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);
             if (!event_context->within_tolerance) {
                 // we've been dragging, finish the star
                 sp_star_finish (sc);
@@ -340,6 +342,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);
                 if (!event_context->within_tolerance) {
                     // we've been dragging, finish the rect
                     sp_star_finish(sc);
@@ -413,11 +416,11 @@ static void sp_star_drag(SPStarContext *sc, Geom::Point p, guint state)
     SnapManager &m = desktop->namedview->snap_manager;
     m.setup(desktop, true, sc->item);
     Geom::Point pt2g = to_2geom(p);
-    m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g);    
-    
+    m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g);
+
     Geom::Point const p0 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, sc->center));
     Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g)));
-    
+
     SPStar *star = SP_STAR(sc->item);
 
     double const sides = (gdouble) sc->magnitude;
@@ -460,7 +463,7 @@ sp_star_finish (SPStarContext * sc)
         sp_canvas_end_forced_full_redraws(desktop->canvas);
 
         sp_desktop_selection(desktop)->set(sc->item);
-        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, 
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
                          _("Create star"));
 
         sc->item = NULL;
index ad9211cbac0e363ef79d759c38fd2416288f3317..6e4b637b85d26b5163ec5821284f6d42850d99f7 100644 (file)
@@ -353,6 +353,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);
                     }
                     ret = TRUE;
                 }
@@ -369,6 +370,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);
                     ret = TRUE;
                 }
             }
@@ -380,12 +382,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);
                 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);
                 ret = TRUE;
             }
             break;
@@ -1011,7 +1015,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
                                         sp_document_maybe_done(sp_desktop_document(desktop), "kern:left", SP_VERB_CONTEXT_TEXT,
                                                                _("Kern to the left"));
                                     } else {
-                                        if (MOD__CTRL) 
+                                        if (MOD__CTRL)
                                             tc->text_sel_end.cursorLeftWithControl();
                                         else
                                             tc->text_sel_end.cursorLeft();
@@ -1314,7 +1318,7 @@ sp_text_paste_inline(SPEventContext *ec)
 
         Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
         Glib::ustring const clip_text = refClipboard->wait_for_text();
-        
+
         if (!clip_text.empty()) {
                // Fix for 244940
                // The XML standard defines the following as valid characters
@@ -1342,7 +1346,7 @@ sp_text_paste_inline(SPEventContext *ec)
                        itr = text.erase(itr);
                    }
                }
-               
+
             if (!tc->text) { // create text if none (i.e. if nascent_object)
                 sp_text_context_setup_text(tc);
                 tc->nascent_object = 0; // we don't need it anymore, having created a real <text>
@@ -1430,7 +1434,7 @@ sp_text_context_selection_changed(Inkscape::Selection *selection, SPTextContext
     SPEventContext *ec = SP_EVENT_CONTEXT(tc);
 
     ec->shape_editor->unset_item(SH_KNOTHOLDER);
-    SPItem *item = selection->singleItem(); 
+    SPItem *item = selection->singleItem();
     if (item && SP_IS_FLOWTEXT (item) && SP_FLOWTEXT(item)->has_internal_frame()) {
         ec->shape_editor->set_item(item, SH_KNOTHOLDER);
     }