From bd80360f39d70d4a2622064a4fa0f29dd829d1ed Mon Sep 17 00:00:00 2001 From: =?utf8?q?Krzysztof=20Kosi=C5=84ski?= Date: Sat, 6 Feb 2010 22:45:14 +0100 Subject: [PATCH] Fix performance regressions in the node tool and a stupid crash bug when deleting more than one stretch of selected nodes --- src/ui/tool/control-point-selection.cpp | 2 +- src/ui/tool/control-point-selection.h | 3 -- src/ui/tool/control-point.cpp | 1 + src/ui/tool/event-utils.cpp | 47 +++++++++++++++++++++++-- src/ui/tool/event-utils.h | 5 ++- src/ui/tool/multi-path-manipulator.cpp | 9 +++-- src/ui/tool/node.cpp | 2 +- src/ui/tool/path-manipulator.cpp | 10 +++--- 8 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index de19fef8d..638318dbf 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -344,7 +344,7 @@ void ControlPointSelection::_updateTransformHandles(bool preserve_center) bool ControlPointSelection::_keyboardMove(GdkEventKey const &event, Geom::Point const &dir) { if (held_control(event)) return false; - unsigned num = 1 + consume_same_key_events(shortcut_key(event), 0); + unsigned num = 1 + combine_key_events(shortcut_key(event), 0); Geom::Point delta = dir * num; if (held_shift(event)) delta *= 10; diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 025f9bb61..93fba56f5 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -15,8 +15,6 @@ #include #include #include -#include -#include #include #include #include <2geom/forward.h> @@ -43,7 +41,6 @@ class ControlPointSelection : public Manipulator { public: ControlPointSelection(SPDesktop *d, SPCanvasGroup *th_group); ~ControlPointSelection(); - typedef std::list connlist_type; typedef std::tr1::unordered_set< SelectableControlPoint * > set_type; typedef set_type Set; // convenience alias diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index 06092b7d5..90d879c66 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -337,6 +337,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event) return false; case GDK_MOTION_NOTIFY: + combine_motion_events(_desktop->canvas, event->motion, 0); if (_event_grab && !_desktop->event_context->space_panning) { _desktop->snapindicator->remove_snaptarget(); bool transferred = false; diff --git a/src/ui/tool/event-utils.cpp b/src/ui/tool/event-utils.cpp index 6912897da..91b2cdb04 100644 --- a/src/ui/tool/event-utils.cpp +++ b/src/ui/tool/event-utils.cpp @@ -8,8 +8,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include #include #include +#include "display/sp-canvas.h" #include "ui/tool/event-utils.h" namespace Inkscape { @@ -28,7 +30,7 @@ guint shortcut_key(GdkEventKey const &event) return shortcut_key; } -unsigned consume_same_key_events(guint keyval, gint mask) +unsigned combine_key_events(guint keyval, gint mask) { GdkEvent *event_next; gint i = 0; @@ -37,7 +39,7 @@ unsigned consume_same_key_events(guint keyval, gint mask) // while the next event is also a key notify with the same keyval and mask, while (event_next && (event_next->type == GDK_KEY_PRESS || event_next->type == GDK_KEY_RELEASE) && event_next->key.keyval == keyval - && (!mask || (event_next->key.state & mask))) { + && (!mask || event_next->key.state & mask)) { if (event_next->type == GDK_KEY_PRESS) i ++; // kill it @@ -51,6 +53,47 @@ unsigned consume_same_key_events(guint keyval, gint mask) return i; } +unsigned combine_motion_events(SPCanvas *canvas, GdkEventMotion &event, gint mask) +{ + GdkEvent *event_next; + gint i = 0; + event.x -= canvas->x0; + event.y -= canvas->y0; + + event_next = gdk_event_get(); + // while the next event is also a motion notify + while (event_next && event_next->type == GDK_MOTION_NOTIFY + && (!mask || event_next->motion.state & mask)) + { + if (event_next->motion.device == event.device) { + GdkEventMotion &next = event_next->motion; + event.send_event = next.send_event; + event.time = next.time; + event.x = next.x; + event.y = next.y; + event.state = next.state; + event.is_hint = next.is_hint; + event.x_root = next.x_root; + event.y_root = next.y_root; + if (event.axes && next.axes) { + memcpy(event.axes, next.axes, event.device->num_axes); + } + } + + // kill it + gdk_event_free(event_next); + event_next = gdk_event_get(); + i++; + } + // otherwise, put it back onto the queue + if (event_next) + gdk_event_put(event_next); + event.x += canvas->x0; + event.y += canvas->y0; + + return i; +} + /** Returns the modifier state valid after this event. Use this when you process events * that change the modifier state. Currently handles only Shift, Ctrl, Alt. */ unsigned state_after_event(GdkEvent *event) diff --git a/src/ui/tool/event-utils.h b/src/ui/tool/event-utils.h index 74907d61c..784855f56 100644 --- a/src/ui/tool/event-utils.h +++ b/src/ui/tool/event-utils.h @@ -14,6 +14,8 @@ #include #include <2geom/point.h> +struct SPCanvas; + namespace Inkscape { namespace UI { @@ -109,7 +111,8 @@ inline bool held_button(E const &event) { } guint shortcut_key(GdkEventKey const &event); -unsigned consume_same_key_events(guint keyval, gint mask); +unsigned combine_key_events(guint keyval, gint mask); +unsigned combine_motion_events(SPCanvas *canvas, GdkEventMotion &event, gint mask); unsigned state_after_event(GdkEvent *event); } // namespace UI diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index c34ef066e..5d7b520c8 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -516,12 +516,15 @@ bool MultiPathManipulator::event(GdkEvent *event) break; } break; + case GDK_MOTION_NOTIFY: + combine_motion_events(_desktop->canvas, event->motion, 0); + for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) { + if (i->second->event(event)) return true; + } + break; default: break; } - for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) { - if (i->second->event(event)) return true; - } return false; } diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 6419acf6d..9f1e25877 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -858,7 +858,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) // Build the list of unselected nodes. typedef ControlPointSelection::Set Set; - Set nodes = _selection.allPoints(); + Set &nodes = _selection.allPoints(); for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) { if (!(*i)->selected()) { Node *n = static_cast(*i); diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 43955edbf..b1a86dd77 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -522,7 +522,7 @@ void PathManipulator::deleteNodes(bool keep_shape) sel_end = sel_beg; while (num_selected > 0) { - while (!sel_beg->selected()) { + while (sel_beg && !sel_beg->selected()) { sel_beg = sel_beg.next(); } sel_end = sel_beg; @@ -532,6 +532,7 @@ void PathManipulator::deleteNodes(bool keep_shape) } num_selected -= _deleteStretch(sel_beg, sel_end, keep_shape); + sel_beg = sel_end; } ++i; } @@ -1294,11 +1295,12 @@ void PathManipulator::_commit(Glib::ustring const &annotation) void PathManipulator::_updateDragPoint(Geom::Point const &evp) { // TODO find a way to make this faster (no transform required) - Geom::PathVector pv = _spcurve->get_pathvector() * (_edit_transform * _i2d_transform); + Geom::Matrix to_desktop = _edit_transform * _i2d_transform; + Geom::PathVector pv = _spcurve->get_pathvector(); boost::optional pvp - = Geom::nearestPoint(pv, _desktop->w2d(evp)); + = Geom::nearestPoint(pv, _desktop->w2d(evp) * to_desktop.inverse()); if (!pvp) return; - Geom::Point nearest_point = _desktop->d2w(pv.at(pvp->path_nr).pointAt(pvp->t)); + Geom::Point nearest_point = _desktop->d2w(pv.at(pvp->path_nr).pointAt(pvp->t) * to_desktop); double fracpart; std::list::iterator spi = _subpaths.begin(); -- 2.30.2