summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2008-10-31 15:06:16 +0000
committerTed Gould <ted@canonical.com>2008-10-31 15:06:16 +0000
commit7e67d66e7817a9321c4e94b2184a9226b20b396a (patch)
treea857d7aae5f544c4243a331e4eb4e4629bbc27a9 /src/display
parentMerge from trunk (diff)
downloadinkscape-7e67d66e7817a9321c4e94b2184a9226b20b396a.tar.gz
inkscape-7e67d66e7817a9321c4e94b2184a9226b20b396a.zip
Merge from trunk
(bzr r6887)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/sp-canvas.cpp73
1 files changed, 44 insertions, 29 deletions
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 53dd6c62c..e9bf1633e 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1497,6 +1497,7 @@ static gint
sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
{
SPCanvas *canvas = SP_CANVAS (widget);
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
int retval = FALSE;
@@ -1531,7 +1532,13 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
- /* Pick the current item as if the button were not pressed, and
+ if (dt) {
+ // Snapping will be on hold if we're moving the mouse at high speeds. When starting
+ // drawing a new shape we really should snap though.
+ dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
+ }
+
+ /* Pick the current item as if the button were not pressed, and
* then process the event.
*/
canvas->state = event->state;
@@ -1541,7 +1548,9 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
break;
case GDK_BUTTON_RELEASE:
- /* Process the event as if the button were pressed, then repick
+ 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
*/
canvas->state = event->state;
@@ -1550,6 +1559,7 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event)
canvas->state = event->state;
pick_current_item (canvas, (GdkEvent *) event);
event->state ^= mask;
+
break;
default:
@@ -1583,7 +1593,7 @@ static inline void request_motions(GdkWindow *w, GdkEventMotion *event) {
static int
sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
{
- static guint32 prev_time;
+ static guint32 prev_time;
static boost::optional<Geom::Point> prev_pos;
int status;
@@ -1597,44 +1607,44 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
if (canvas->pixmap_gc == NULL) // canvas being deleted
return FALSE;
- // Snap when speed drops below e.g. 0.1 px/msec, or when no motion events have occured for 100 msec.
- // i.e. snap when we're at stand still. The speed threshold enforces snapping for tablets, which will never
- // be full at stand still and might keep spitting out motion events.
+ 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.
- // When moving at speeds around the speed limit, Inkscape might snap for one motion event but not for the
- // next, which will make the object that's being dragged jump from the snapped position to the mouse
- // position and back again. That could be annoying, but I don't see an easy way around this.
-
if (event->type == GDK_MOTION_NOTIFY) {
Geom::Point event_pos(event->x, event->y);
guint32 event_t = gdk_event_get_time ( (GdkEvent *) event );
- sp_canvas_snap_watchdog_kill(canvas);
- SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (dt) { // put snapping on hold
+ dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true);
+ }
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.1) {
- if (dt) {
- dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
- }
- } else {
- // We're moving fast, so postpone any snapping until the next GDK_MOTION_NOTIFY event.
- if (dt) {
- dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true);
- }
- // We must snap at some point in time though, so set a watchdog timer at 100 msec from
- // now, just in case there's no future motion event that's under the speed limit.
- sp_canvas_snap_watchdog_set(canvas, event);
+ 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
+ } 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
- if (dt) {
- dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(true);
- }
sp_canvas_snap_watchdog_set(canvas, event);
}
@@ -1656,12 +1666,17 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
gboolean sp_canvas_snap_watchdog_callback(gpointer data)
{
+ // Snap NOW! For this the "postponed" flag will be reset and an the last motion event will be repeated
+ SPCanvas *canvas = reinterpret_cast<SPCanvas *>(data);
+ if (!canvas->watchdog_event) {
+ return FALSE;
+ }
+
SPDesktop *dt = SP_ACTIVE_DESKTOP;
if (dt) {
dt->namedview->snap_manager.snapprefs.setSnapPostponedGlobally(false);
}
- SPCanvas *canvas = reinterpret_cast<SPCanvas *>(data);
emit_event(canvas, canvas->watchdog_event);
gdk_event_free(canvas->watchdog_event);
canvas->watchdog_event = NULL;
@@ -1673,7 +1688,7 @@ gboolean sp_canvas_snap_watchdog_callback(gpointer data)
void sp_canvas_snap_watchdog_set(SPCanvas *canvas, GdkEventMotion *event)
{
g_assert(canvas->watchdog_id == 0);
- canvas->watchdog_id = g_timeout_add(100, &sp_canvas_snap_watchdog_callback, canvas);
+ canvas->watchdog_id = g_timeout_add(400, &sp_canvas_snap_watchdog_callback, canvas);
g_assert(canvas->watchdog_event == NULL);
canvas->watchdog_event = gdk_event_copy( (GdkEvent *) event);
}