diff --git a/toonz/sources/include/tools/inputstate.h b/toonz/sources/include/tools/inputstate.h
new file mode 100644
index 0000000..5fd2109
--- /dev/null
+++ b/toonz/sources/include/tools/inputstate.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#ifndef INPUTSTATE_INCLUDED
+#define INPUTSTATE_INCLUDED
+
+// TnzTools includes
+#include <tools/tooltimer.h>
+#include <tools/keyhistory.h>
+
+// TnzCore includes
+#include <tcommon.h>
+#include <tsmartpointer.h>
+
+// Qt includes
+#include <Qt>
+
+// std includes
+#include <map>
+
+
+#undef DVAPI
+#undef DVVAR
+#ifdef TNZTOOLS_EXPORTS
+#define DVAPI DV_EXPORT_API
+#define DVVAR DV_EXPORT_VAR
+#else
+#define DVAPI DV_IMPORT_API
+#define DVVAR DV_IMPORT_VAR
+#endif
+
+
+//===================================================================
+
+
+//*****************************************************************************************
+//    TInputState definition
+//*****************************************************************************************
+
+class TInputState {
+public:
+  typedef qint64 DeviceId;
+  typedef long long TouchId;
+
+  typedef Qt::Key Key;
+  typedef TKeyHistoryT<Key> KeyHistory;
+  typedef KeyHistory::State KeyState;
+
+  typedef Qt::MouseButton Button;
+  typedef TKeyHistoryT<Button> ButtonHistory;
+  typedef ButtonHistory::State ButtonState;
+  typedef std::map<DeviceId, ButtonHistory::Pointer> ButtonHistoryMap;
+
+private:
+  TTimerTicks ticks;
+  KeyHistory::Pointer keyHistory_;
+  mutable ButtonHistoryMap buttonHistories_;
+
+  void touch(TTimerTicks ticks);
+
+public:
+  TInputState();
+  ~TInputState();
+
+  inline KeyHistory::Pointer keyHistory() const
+    { return keyHistory(); }
+  inline KeyState::Pointer keyState() const
+    { return keyHistory()->current(); }
+
+  inline void keyEvent(bool press, Key key, TTimerTicks ticks)
+    { touch(ticks); keyHistory()->change(press, key, this->ticks); }
+  inline void keyPress(Key key, TTimerTicks ticks)
+    { keyEvent(true, key, ticks); }
+  inline void keyRelease(Key key, TTimerTicks ticks)
+    { keyEvent(false, key, ticks); }
+
+  inline KeyState::Pointer keyFind(Key key) const
+    { return keyState()->find(key); }
+  inline bool isKeyPressed(Key key) const
+    { return keyFind(key); }
+  inline double howLongKeyPressed(Key key, TTimerTicks ticks, double timeOffset = 0.0)
+    { return KeyState::Holder::howLongPressed(keyFind(key), ticks, timeOffset); }
+  inline double howLongKeyPressed(Key key)
+    { return howLongKeyPressed(key, ticks); }
+
+  ButtonHistory::Pointer buttonHistory(DeviceId device) const;
+
+  inline const ButtonHistoryMap buttonHistories() const
+    { return buttonHistories_; }
+  inline ButtonState::Pointer buttonState(DeviceId device) const
+    { return buttonHistory(device)->current(); }
+
+  inline void buttonEvent(bool press, DeviceId device, Button button, TTimerTicks ticks)
+    { touch(ticks); buttonHistory(device)->change(press, button, this->ticks); }
+  inline void buttonPress(DeviceId device, Button button, TTimerTicks ticks)
+    { buttonEvent(true, device, button, ticks); }
+  inline void buttonRelease(DeviceId device, Button button, TTimerTicks ticks)
+    { buttonEvent(false, device, button, ticks); }
+  inline void buttonEvent(bool press, Button button, TTimerTicks ticks)
+    { buttonEvent(press, 0, button, ticks); }
+  inline void buttonPress(Button button, TTimerTicks ticks)
+    { buttonEvent(true, button, ticks); }
+  inline void buttonRelease(Button button, TTimerTicks ticks)
+    { buttonEvent(false, button, ticks); }
+
+  inline ButtonState::Pointer buttonFind(DeviceId device, Button button)
+    { return buttonState(device)->find(button); }
+  inline bool isButtonPressed(DeviceId device, Button button)
+    { return buttonFind(device, button); }
+  inline double howLongButtonPressed(DeviceId device, Button button, TTimerTicks ticks, double timeOffset = 0.0)
+    { return ButtonState::Holder::howLongPressed(buttonFind(device, button), ticks, timeOffset); }
+  inline double howLongButtonPressed(DeviceId device, Button button)
+    { return howLongButtonPressed(device, button, ticks); }
+
+  inline ButtonState::Pointer buttonFindDefault(Button button)
+    { return buttonFind(DeviceId(), button); }
+  inline bool isButtonPressedDefault(Button button)
+    { return isButtonPressed(DeviceId(), button); }
+  inline double howLongButtonPressedDefault(Button button, TTimerTicks ticks, double timeOffset = 0.0)
+    { return howLongButtonPressed(DeviceId(), button, ticks, timeOffset); }
+  inline double howLongButtonPressedDefault(Button button)
+    { return howLongButtonPressedDefault(button, ticks); }
+
+  ButtonState::Pointer buttonFindAny(Button button, DeviceId &outDevice);
+
+  inline ButtonState::Pointer buttonFindAny(Button button)
+    { DeviceId device; return buttonFindAny(button, device); }
+  inline bool isButtonPressedAny(Button button)
+    { return buttonFindAny(button); }
+  inline double howLongButtonPressedAny(Button button, TTimerTicks ticks, double timeOffset = 0.0)
+    { return ButtonState::Holder::howLongPressed(buttonFindAny(button), ticks, timeOffset); }
+  inline double howLongButtonPressedAny(Button button)
+    { return howLongButtonPressedAny(button, ticks); }
+
+  inline KeyState::Holder keyStateHolder(TTimerTicks ticks, double timeOffset = 0.0) const
+    { return KeyState::Holder(keyState(), ticks, timeOffset); }
+  inline KeyState::Holder keyStateHolder()
+    { return keyStateHolder(ticks); }
+  inline KeyHistory::Holder keyHistoryHolder(TTimerTicks ticks, double timeOffset = 0.0)
+    { return KeyHistory::Holder(keyHistory(), ticks, timeOffset); }
+  inline KeyHistory::Holder keyHistoryHolder()
+    { return keyHistoryHolder(ticks); }
+
+  inline ButtonState::Holder buttonStateHolder(DeviceId device, TTimerTicks ticks, double timeOffset = 0.0)
+    { return ButtonState::Holder(buttonState(device), ticks, timeOffset); }
+  inline ButtonState::Holder buttonStateHolder(DeviceId device)
+    { return buttonStateHolder(device, ticks); }
+  inline ButtonHistory::Holder buttonHistoryHolder(DeviceId device, long ticks, double timeOffset = 0.0)
+    { return ButtonHistory::Holder(buttonHistory(device), ticks, timeOffset); }
+  inline ButtonHistory::Holder buttonHistoryHolder(DeviceId device)
+    { return buttonHistoryHolder(device, ticks); }
+};
+
+
+#endif
diff --git a/toonz/sources/include/tools/keyhistory.h b/toonz/sources/include/tools/keyhistory.h
index c49a662..79537fb 100644
--- a/toonz/sources/include/tools/keyhistory.h
+++ b/toonz/sources/include/tools/keyhistory.h
@@ -72,7 +72,9 @@ public:
       { return howLongPressed(find(value), ticks, timeOffset); }
 
     static double howLongPressed(const Pointer &state, long ticks, double timeOffset) {
-      return state ? std::max(TToolTimer::step, (ticks - state.ticks)*TToolTimer::step + timeOffset) : 0.0;
+      return state
+           ? std::max(TToolTimer::step, (ticks - state->ticks)*TToolTimer::step + timeOffset)
+           : 0.0;
     }
   };
 
@@ -232,15 +234,15 @@ private:
 
 public:
   TKeyHistoryT()
-    { states.insert(StatePointer(new State())); }
+    { states[TTimerTicks()] = StatePointer(new State()); }
 
   StatePointer current() const
-    { return states.back(); }
+    { return states.rbegin()->second; }
 
   StatePointer change(bool press, Type value, TTimerTicks ticks)  {
     StatePointer state = current()->change(press, value, ticks);
-    if (state != current() && state.ticks > states.rbegin()->first)
-      states.insert(state.ticks, state);
+    if (state != current() && state->ticks > states.rbegin()->first)
+      states[state->ticks] = state;
     autoRemove();
     return current();
   }
diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h
index dbb38ef..84fa7a4 100644
--- a/toonz/sources/include/tools/track.h
+++ b/toonz/sources/include/tools/track.h
@@ -4,8 +4,9 @@
 #define TRACK_INCLUDED
 
 // TnzTools includes
-#include <tools/keyhistory.h>
-#include <tools/tooltimer.h>
+#include <tools/inputstate.h>
+
+// TnzCore includes
 #include <tcommon.h>
 #include <tgeometry.h>
 
@@ -38,6 +39,7 @@ class TTrackModifier;
 typedef TSmartPointerT<TTrack> TTrackP;
 typedef TSmartPointerT<TTrackHandler> TTrackHandlerP;
 typedef TSmartPointerT<TTrackModifier> TTrackModifierP;
+typedef std::vector<TTrackP> TTrackList;
 
 //===================================================================
 
@@ -85,11 +87,10 @@ public:
 class DVAPI TTrackHandler : public TSmartObject {
   DECLARE_CLASS_CODE
 public:
-  TSmartObject &owner;
   TTrack &original;
   std::vector<TTrackP> tracks;
-  TTrackHandler(TSmartObject &owner, TTrack &original):
-    owner(owner), original(original) { }
+  TTrackHandler(TTrack &original):
+    original(original) { }
 };
 
 
@@ -119,8 +120,6 @@ class DVAPI TTrack : public TSmartObject {
 
 public:
   typedef long long Id;
-  typedef long long TouchId;
-  typedef qint64 DeviceId;
 
   static const double epsilon;
 
@@ -129,10 +128,10 @@ private:
 
 public:
   const Id id;
-  const DeviceId deviceId;
-  const TouchId touchId;
-  const TKeyHistoryT<Qt::Key>::Holder keyHistory;
-  const TKeyHistoryT<Qt::MouseButton>::Holder buttonHistory;
+  const TInputState::DeviceId deviceId;
+  const TInputState::TouchId touchId;
+  const TInputState::KeyHistory::Holder keyHistory;
+  const TInputState::ButtonHistory::Holder buttonHistory;
   const TTrackModifierP modifier;
 
   TTrackHandlerP handler;
@@ -146,10 +145,10 @@ private:
 public:
 
   explicit TTrack(
-    DeviceId deviceId = 0,
-    TouchId touchId = 0,
-    const TKeyHistoryT<Qt::Key>::Holder &keyHistory = TKeyHistoryT<Qt::Key>::Holder(),
-    const TKeyHistoryT<Qt::MouseButton>::Holder &buttonHistory = TKeyHistoryT<Qt::MouseButton>::Holder()
+    TInputState::DeviceId deviceId = TInputState::DeviceId(),
+    TInputState::TouchId touchId = TInputState::TouchId(),
+    const TInputState::KeyHistory::Holder &keyHistory = TInputState::KeyHistory::Holder(),
+    const TInputState::ButtonHistory::Holder &buttonHistory = TInputState::ButtonHistory::Holder()
   );
 
   explicit TTrack(const TTrackModifierP &modifier);
diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt
index a56b0e5..cfaa257 100644
--- a/toonz/sources/tnztools/CMakeLists.txt
+++ b/toonz/sources/tnztools/CMakeLists.txt
@@ -45,6 +45,7 @@ set(HEADERS
     ../include/tools/toolutils.h
     ../include/tools/tooltimer.h
     ../include/tools/keyhistory.h
+    ../include/tools/inputstate.h
     ../include/tools/track.h
 )
 
@@ -111,6 +112,7 @@ set(SOURCES
     toonzvectorbrushtool.cpp
     tooltimer.cpp
     keyhistory.cpp
+    inputstate.cpp
     track.cpp
 )
 
diff --git a/toonz/sources/tnztools/inputstate.cpp b/toonz/sources/tnztools/inputstate.cpp
new file mode 100644
index 0000000..db414e0
--- /dev/null
+++ b/toonz/sources/tnztools/inputstate.cpp
@@ -0,0 +1,44 @@
+
+
+#include <tools/inputstate.h>
+
+
+//*****************************************************************************************
+//    TInputState static members
+//*****************************************************************************************
+
+TInputState::TInputState():
+  ticks(),
+  keyHistory_(new KeyHistory())
+  { }
+
+TInputState::~TInputState()
+  { }
+
+void
+TInputState::touch(TTimerTicks ticks) {
+  if (this->ticks < ticks)
+    this->ticks = ticks;
+  else
+    ++this->ticks;
+}
+
+TInputState::ButtonHistory::Pointer
+TInputState::buttonHistory(DeviceId device) const {
+  ButtonHistory::Pointer &history = buttonHistories_[device];
+  if (!history) history = new ButtonHistory();
+  return history;
+}
+
+TInputState::ButtonState::Pointer
+TInputState::buttonFindAny(Button button, DeviceId &outDevice) {
+  for(ButtonHistoryMap::const_iterator i = buttonHistories_.begin(); i != buttonHistories_.end(); ++i) {
+    ButtonState::Pointer state = i->second->current()->find(button);
+    if (state) {
+      outDevice = i->first;
+      return state;
+    }
+  }
+  outDevice = DeviceId();
+  return ButtonState::Pointer();
+}
diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp
index c949044..b603517 100644
--- a/toonz/sources/tnztools/track.cpp
+++ b/toonz/sources/tnztools/track.cpp
@@ -32,10 +32,10 @@ TTrackModifier::calcPoint(double originalIndex) {
 //*****************************************************************************************
 
 TTrack::TTrack(
-  DeviceId deviceId,
-  TouchId touchId,
-  const TKeyHistoryT<Qt::Key>::Holder &keyHistory,
-  const TKeyHistoryT<Qt::MouseButton>::Holder &buttonHistory
+  TInputState::DeviceId deviceId,
+  TInputState::TouchId touchId,
+  const TInputState::KeyHistory::Holder &keyHistory,
+  const TInputState::ButtonHistory::Holder &buttonHistory
 ):
   id(++lastId),
   deviceId(deviceId),
@@ -84,14 +84,17 @@ TTrack::push_back(const TTrackPoint &point) {
   points_.push_back(point);
   if (size() == 1) return;
 
-  const TTrackPoint &prev = *(points_.end() - 2);
+  const TTrackPoint &prev = *(points_.rbegin() + 1);
   TTrackPoint &p = points_.back();
 
+  // fix originalIndex
   if (p.originalIndex < prev.originalIndex)
       p.originalIndex = prev.originalIndex;
-  if (p.time < prev.time)
-      p.time = prev.time;
 
+  // fix time
+  p.time = std::max(p.time, prev.time + TToolTimer::step);
+
+  // calculate length
   TPointD d = p.position - prev.position;
   p.length = prev.length + sqrt(d.x*d.x + d.y*d.y);
 }