Kaynağa Gözat

Code to record a mouse trail added

Josh Yelon 18 yıl önce
ebeveyn
işleme
f64547dd1b

+ 31 - 0
panda/src/device/mouseAndKeyboard.cxx

@@ -40,11 +40,13 @@ MouseAndKeyboard(GraphicsWindow *window, int device, const string &name) :
   _pixel_size_output = define_output("pixel_size", EventStoreVec2::get_class_type());
   _xy_output = define_output("xy", EventStoreVec2::get_class_type());
   _button_events_output = define_output("button_events", ButtonEventList::get_class_type());
+  _pointer_events_output = define_output("pointer_events", PointerEventList::get_class_type());
 
   _pixel_xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _pixel_size = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _button_events = new ButtonEventList;
+  _pointer_events = new PointerEventList;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -60,6 +62,26 @@ set_source(GraphicsWindow *window, int device) {
   _device = device;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MouseAndKeyboard::get_source_window
+//       Access: Public
+//  Description: Returns the associated source window.
+////////////////////////////////////////////////////////////////////
+PT(GraphicsWindow) MouseAndKeyboard::
+get_source_window() const {
+  return _window;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseAndKeyboard::get_source_device
+//       Access: Public
+//  Description: Returns the associated source device.
+////////////////////////////////////////////////////////////////////
+int MouseAndKeyboard::
+get_source_device() const {
+  return _device;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MouseAndKeyboard::do_transmit_data
 //       Access: Protected, Virtual
@@ -85,6 +107,15 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
     }
     output.set_data(_button_events_output, EventParameter(_button_events));
   }
+  if (_window->has_pointer_event(_device)) {
+    // Fill up the pointer events.
+    _pointer_events->clear();
+    while (_window->has_pointer_event(_device)) {
+      PointerEvent be = _window->get_pointer_event(_device);
+      _pointer_events->add_event(be);
+    }
+    output.set_data(_pointer_events_output, EventParameter(_pointer_events));
+  }
 
   // Get the window size.
   WindowProperties properties = _window->get_properties();

+ 7 - 0
panda/src/device/mouseAndKeyboard.h

@@ -23,6 +23,7 @@
 
 #include "dataNode.h"
 #include "buttonEventList.h"
+#include "pointerEventList.h"
 #include "linmath_events.h"
 #include "pointerTo.h"
 #include "graphicsWindow.h"
@@ -52,6 +53,10 @@ PUBLISHED:
   MouseAndKeyboard(GraphicsWindow *window, int device, const string &name);
   void set_source(GraphicsWindow *window, int device);
 
+public:
+  PT(GraphicsWindow) get_source_window() const;
+  int                get_source_device() const;
+  
 protected:
   // Inherited from DataNode
   virtual void do_transmit_data(DataGraphTraverser *trav,
@@ -64,11 +69,13 @@ private:
   int _pixel_size_output;
   int _xy_output;
   int _button_events_output;
+  int _pointer_events_output;
 
   PT(EventStoreVec2) _pixel_xy;
   PT(EventStoreVec2) _pixel_size;
   PT(EventStoreVec2) _xy;
   PT(ButtonEventList) _button_events;
+  PT(PointerEventList) _pointer_events;
 
   PT(GraphicsWindow) _window;
   int _device;

+ 10 - 3
panda/src/display/graphicsWindow.I

@@ -44,7 +44,14 @@ is_fullscreen() const {
   return _properties.get_fullscreen();
 }
 
-
-
-
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::add_input_device
+//       Access: Protected
+//  Description: Adds a GraphicsWindowInputDevice to the vector.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+add_input_device(const GraphicsWindowInputDevice &device) {
+  _input_devices.push_back(device);
+  _input_devices.back().set_device_index(_input_devices.size()-1);
+}
 

+ 85 - 0
panda/src/display/graphicsWindow.cxx

@@ -337,6 +337,54 @@ has_keyboard(int device) const {
   return result;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::enable_pointer_events
+//       Access: Published
+//  Description: Turn on the generation of pointer events.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+enable_pointer_events(int device) {
+  MutexHolder holder(_input_lock);
+  nassertv(device >= 0 && device < (int)_input_devices.size());
+  _input_devices[device].enable_pointer_events();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::disable_pointer_events
+//       Access: Published
+//  Description: Turn off the generation of pointer events.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+disable_pointer_events(int device) {
+  MutexHolder holder(_input_lock);
+  nassertv(device >= 0 && device < (int)_input_devices.size());
+  _input_devices[device].disable_pointer_events();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::enable_pointer_mode
+//       Access: Published
+//  Description: See GraphicsWindowInputDevice::enable_pointer_mode
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+enable_pointer_mode(int device, double speed) {
+  MutexHolder holder(_input_lock);
+  nassertv(device >= 0 && device < (int)_input_devices.size());
+  _input_devices[device].enable_pointer_mode(speed);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::disable_pointer_events
+//       Access: Published
+//  Description: See GraphicsWindowInputDevice::disable_pointer_mode
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+disable_pointer_mode(int device) {
+  MutexHolder holder(_input_lock);
+  nassertv(device >= 0 && device < (int)_input_devices.size());
+  _input_devices[device].disable_pointer_mode();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_pointer
 //       Access: Published
@@ -418,6 +466,43 @@ get_button_event(int device) {
   return result;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::has_pointer_event
+//       Access: Public
+//  Description: Returns true if the indicated device has a pending
+//               pointer event (a mouse movement).  If this returns
+//               true, the particular event may be extracted via
+//               get_pointer_event().
+////////////////////////////////////////////////////////////////////
+bool GraphicsWindow::
+has_pointer_event(int device) const {
+  bool result;
+  {
+    MutexHolder holder(_input_lock);
+    nassertr(device >= 0 && device < (int)_input_devices.size(), false);
+    result = _input_devices[device].has_pointer_event();
+  }
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::get_pointer_event
+//       Access: Public
+//  Description: Assuming a previous call to has_pointer_event()
+//               returned true, this returns the pending pointer event.
+////////////////////////////////////////////////////////////////////
+PointerEvent GraphicsWindow::
+get_pointer_event(int device) {
+  PointerEvent result;
+  {
+    MutexHolder holder(_input_lock);
+    nassertr(device >= 0 && device < (int)_input_devices.size(), PointerEvent());
+    nassertr(_input_devices[device].has_pointer_event(), PointerEvent());
+    result = _input_devices[device].get_pointer_event();
+  }
+  return result;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::verify_window_sizes
 //       Access: Public, Virtual

+ 8 - 0
panda/src/display/graphicsWindow.h

@@ -73,6 +73,11 @@ PUBLISHED:
   bool has_keyboard(int device) const;
   
 
+  void enable_pointer_events(int device);
+  void disable_pointer_events(int device);
+  void enable_pointer_mode(int device, double speed);
+  void disable_pointer_mode(int device);
+
   MouseData get_pointer(int device) const;
   virtual bool move_pointer(int device, int x, int y);
   virtual void close_ime();
@@ -81,6 +86,8 @@ public:
   // No need to publish these.
   bool has_button_event(int device) const;
   ButtonEvent get_button_event(int device);
+  bool has_pointer_event(int device) const;
+  PointerEvent get_pointer_event(int device);
 
   virtual int verify_window_sizes(int numsizes, int *dimen);
 
@@ -115,6 +122,7 @@ private:
   static unsigned int parse_color_mask(const string &word);
 
 protected:
+  INLINE void add_input_device(const GraphicsWindowInputDevice &device);
   typedef vector_GraphicsWindowInputDevice InputDevices;
   InputDevices _input_devices;
   Mutex _input_lock;

+ 49 - 6
panda/src/display/graphicsWindowInputDevice.I

@@ -67,6 +67,51 @@ get_pointer() const {
   return _mouse_data;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::get_raw_pointer
+//       Access: Public
+//  Description: Returns the MouseData associated with the input
+//               device's pointer, in raw form (ie, prior to any
+//               pointer_mode interpretation).
+////////////////////////////////////////////////////////////////////
+INLINE const MouseData &GraphicsWindowInputDevice::
+get_raw_pointer() const {
+  return _true_mouse_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::set_device_index
+//       Access: Public
+//  Description: Set the device index.  This is reported in pointer 
+//               events.  The device index will be equal to the position
+//               of the GraphicsWindowInputDevice in the window's list.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+set_device_index(int index) {
+  _device_index = index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::enable_pointer_events
+//       Access: Public
+//  Description: Enables the generation of mouse-movement events.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+enable_pointer_events() {
+  _enable_pointer_events = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::disable_pointer_events
+//       Access: Public
+//  Description: Disables the generation of mouse-movement events.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+disable_pointer_events() {
+  _enable_pointer_events = false;
+  _pointer_events.clear();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::set_pointer_in_window
 //       Access: Public
@@ -75,10 +120,8 @@ get_pointer() const {
 //               the given pixel coordinates.
 ////////////////////////////////////////////////////////////////////
 INLINE void GraphicsWindowInputDevice::
-set_pointer_in_window(int x, int y) {
-  _mouse_data._in_window = true;
-  _mouse_data._xpos = x;
-  _mouse_data._ypos = y;
+set_pointer_in_window(int x, int y, double time) {
+  set_pointer(true, x, y, time);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -89,8 +132,8 @@ set_pointer_in_window(int x, int y) {
 //               window.
 ////////////////////////////////////////////////////////////////////
 INLINE void GraphicsWindowInputDevice::
-set_pointer_out_of_window() {
-  _mouse_data._in_window = false;
+set_pointer_out_of_window(double time) {
+  set_pointer(false, _mouse_data._xpos, _mouse_data._ypos, time);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 143 - 9
panda/src/display/graphicsWindowInputDevice.cxx

@@ -45,9 +45,17 @@
 //               the named constructors, below.
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice::
-GraphicsWindowInputDevice(const string &name, int flags) :
+GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags) :
+  _host(host),
   _name(name),
-  _flags(flags)
+  _flags(flags),
+  _device_index(0),
+  _event_sequence(0),
+  _pointer_mode_enable(false),
+  _pointer_speed(1.0),
+  _pointer_true_x(0.0),
+  _pointer_true_y(0.0),
+  _enable_pointer_events(false)
 {
 }
 
@@ -58,8 +66,8 @@ GraphicsWindowInputDevice(const string &name, int flags) :
 //               only has a pointing device, no keyboard.
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice GraphicsWindowInputDevice::
-pointer_only(const string &name) {
-  return GraphicsWindowInputDevice(name, IDF_has_pointer);
+pointer_only(GraphicsWindow *host, const string &name) {
+  return GraphicsWindowInputDevice(host, name, IDF_has_pointer);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -69,8 +77,8 @@ pointer_only(const string &name) {
 //               only has a keyboard, no pointing device.
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice GraphicsWindowInputDevice::
-keyboard_only(const string &name) {
-  return GraphicsWindowInputDevice(name, IDF_has_keyboard);
+keyboard_only(GraphicsWindow *host, const string &name) {
+  return GraphicsWindowInputDevice(host, name, IDF_has_keyboard);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -80,9 +88,9 @@ keyboard_only(const string &name) {
 //               has both a keyboard and pointer.
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice GraphicsWindowInputDevice::
-pointer_and_keyboard(const string &name) {
+pointer_and_keyboard(GraphicsWindow *host, const string &name) {
   return
-    GraphicsWindowInputDevice(name, IDF_has_pointer | IDF_has_keyboard);
+    GraphicsWindowInputDevice(host, name, IDF_has_pointer | IDF_has_keyboard);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -92,10 +100,20 @@ pointer_and_keyboard(const string &name) {
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice::
 GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy) :
+  _host(copy._host),
   _name(copy._name),
   _flags(copy._flags),
+  _device_index(copy._device_index),
+  _event_sequence(copy._event_sequence),
+  _pointer_mode_enable(copy._pointer_mode_enable),
+  _pointer_speed(copy._pointer_speed),
+  _pointer_true_x(copy._pointer_true_x),
+  _pointer_true_y(copy._pointer_true_y),
+  _enable_pointer_events(copy._enable_pointer_events),
   _mouse_data(copy._mouse_data),
-  _button_events(copy._button_events)
+  _true_mouse_data(copy._true_mouse_data),
+  _button_events(copy._button_events),
+  _pointer_events(copy._pointer_events)
 {
 }
 
@@ -106,10 +124,20 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy) :
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 operator = (const GraphicsWindowInputDevice &copy) {
+  _host = copy._host;
   _name = copy._name;
   _flags = copy._flags;
+  _device_index = copy._device_index;
+  _event_sequence = copy._event_sequence;
+  _pointer_mode_enable = copy._pointer_mode_enable;
+  _pointer_speed = copy._pointer_speed;
+  _pointer_true_x = copy._pointer_true_x;
+  _pointer_true_y = copy._pointer_true_y;
+  _enable_pointer_events = copy._enable_pointer_events;
   _mouse_data = copy._mouse_data;
+  _true_mouse_data = copy._true_mouse_data;
   _button_events = copy._button_events;
+  _pointer_events = copy._pointer_events;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -148,6 +176,112 @@ get_button_event() {
   return be;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::has_pointer_event
+//       Access: Public
+//  Description: Returns true if this device has a pending pointer
+//               event (a mouse movement), or false otherwise.  If 
+//               this returns true, the particular event may be
+//               extracted via get_pointer_event().
+////////////////////////////////////////////////////////////////////
+bool GraphicsWindowInputDevice::
+has_pointer_event() const {
+  return !_pointer_events.empty();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::get_pointer_event
+//       Access: Public
+//  Description: Assuming a previous call to has_pointer_event()
+//               returned true, this returns the pending pointer event.
+////////////////////////////////////////////////////////////////////
+PointerEvent GraphicsWindowInputDevice::
+get_pointer_event() {
+  PointerEvent be = _pointer_events.front();
+  _pointer_events.pop_front();
+  return be;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::enable_pointer_mode
+//       Access: Public
+//  Description: There are two modes: raw mode, and pointer mode.
+//               In pointer mode, the mouse stops when it reaches the
+//               edges of the window.  In raw mode, the mouse ignores
+//               the screen boundaries and can continue indefinitely,
+//               even into negative coordinates.  In raw mode, each
+//               "blip" from the mouse hardware corresponds to a
+//               change of 1 unit in the mouse's (x,y) coordinate.
+//               In pointer mode, a variety of speed adjustment factors
+//               and concepts like "mouse acceleration" may be applied.
+//
+//               Mouse zero represents the system mouse pointer.  This
+//               is by definition a pointer, not a raw mouse.  It is
+//               an error to try to enable or disable pointer mode on
+//               mouse zero.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindowInputDevice::
+enable_pointer_mode(double speed) {
+  nassertv(_device_index != 0);
+  _pointer_mode_enable = true;
+  _pointer_speed = speed;
+  _pointer_true_x = _host->get_x_size() * 0.5;
+  _pointer_true_y = _host->get_y_size() * 0.5;
+  _mouse_data._in_window = true;
+  _mouse_data._xpos = int(_pointer_true_x + 0.5);
+  _mouse_data._ypos = int(_pointer_true_y + 0.5);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::disable_pointer_mode
+//       Access: Public
+//  Description: see enable_pointer_mode.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindowInputDevice::
+disable_pointer_mode() {
+  nassertv(_device_index != 0);
+  _pointer_mode_enable = false;
+  _pointer_speed = 1.0;
+  _pointer_true_x = 0.0;
+  _pointer_true_y = 0.0;
+  _mouse_data = _true_mouse_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::set_pointer
+//       Access: Public
+//  Description: Records that a mouse movement has taken place.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindowInputDevice::
+set_pointer(bool inwin, int x, int y, double time) {
+  int delta_x = x - _true_mouse_data._xpos;
+  int delta_y = y - _true_mouse_data._ypos;
+  _true_mouse_data._in_window = inwin;
+  _true_mouse_data._xpos = x;
+  _true_mouse_data._ypos = y;
+
+  if (_pointer_mode_enable) {
+    _pointer_true_x += (delta_x * _pointer_speed);
+    _pointer_true_y += (delta_y * _pointer_speed);
+    double xhi = _host->get_x_size();
+    double yhi = _host->get_y_size();
+    if (_pointer_true_x < 0.0) _pointer_true_x = 0.0;
+    if (_pointer_true_y < 0.0) _pointer_true_y = 0.0;
+    if (_pointer_true_x > xhi) _pointer_true_x = xhi;
+    if (_pointer_true_y > yhi) _pointer_true_y = yhi;
+    _mouse_data._in_window = true;
+    _mouse_data._xpos = int(_pointer_true_x + 0.5);
+    _mouse_data._ypos = int(_pointer_true_y + 0.5);
+  } else {
+    _mouse_data = _true_mouse_data;
+  }
+  
+  if (_enable_pointer_events) {
+    int seq = _event_sequence ++;
+    _pointer_events.push_back(PointerEvent(_device_index, _mouse_data, seq, time));
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::button_down
 //       Access: Public

+ 37 - 10
panda/src/display/graphicsWindowInputDevice.h

@@ -22,6 +22,7 @@
 #include "pandabase.h"
 
 #include "buttonEvent.h"
+#include "pointerEvent.h"
 #include "mouseData.h"
 #include "clockObject.h"
 
@@ -38,26 +39,37 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_DISPLAY GraphicsWindowInputDevice {
 private:
-  GraphicsWindowInputDevice(const string &name, int flags);
+  GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags);
 
 public:
-  static GraphicsWindowInputDevice pointer_only(const string &name);
-  static GraphicsWindowInputDevice keyboard_only(const string &name);
-  static GraphicsWindowInputDevice pointer_and_keyboard(const string &name);
-
+  static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name);
+  static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name);
+  static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name);
+  
   INLINE GraphicsWindowInputDevice();
   GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy);
   void operator = (const GraphicsWindowInputDevice &copy);
   ~GraphicsWindowInputDevice();
-
+  
   INLINE string get_name() const;
   INLINE bool has_pointer() const;
   INLINE bool has_keyboard() const;
 
+  INLINE void set_device_index(int index);
+  
   INLINE const MouseData &get_pointer() const;
-
+  INLINE const MouseData &get_raw_pointer() const;
+  
+  INLINE void enable_pointer_events();
+  INLINE void disable_pointer_events();
+  
+  INLINE void enable_pointer_mode(double speed);
+  INLINE void disable_pointer_mode();
+  
   bool has_button_event() const;
   ButtonEvent get_button_event();
+  bool has_pointer_event() const;
+  PointerEvent get_pointer_event();
 
 public:
   // The following interface is for the various kinds of
@@ -69,8 +81,9 @@ public:
   void candidate(const wstring &candidate_string, size_t highlight_start, 
                  size_t higlight_end, size_t cursor_pos);
 
-  INLINE void set_pointer_in_window(int x, int y);
-  INLINE void set_pointer_out_of_window();
+  INLINE void set_pointer_in_window(int x, int y, double time = ClockObject::get_global_clock()->get_frame_time());
+  INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
+  void set_pointer(bool inwin, int x, int y, double time);
 
 public:
   // We need these methods to make VC++ happy when we try to
@@ -86,11 +99,25 @@ private:
     IDF_has_keyboard   = 0x02
   };
   typedef pdeque<ButtonEvent> ButtonEvents;
-
+  typedef pdeque<PointerEvent> PointerEvents;
+  
+  GraphicsWindow *_host;
+  
   string _name;
   int _flags;
+  int _device_index;
+  int _event_sequence;
+  
+  bool   _pointer_mode_enable;
+  double _pointer_speed;
+  double _pointer_true_x;
+  double _pointer_true_y;
+  
+  bool _enable_pointer_events;
   MouseData _mouse_data;
+  MouseData _true_mouse_data;
   ButtonEvents _button_events;
+  PointerEvents _pointer_events;
 };
 
 #include "graphicsWindowInputDevice.I"

+ 16 - 8
panda/src/event/pointerEvent.I

@@ -24,7 +24,8 @@
 ////////////////////////////////////////////////////////////////////
 INLINE PointerEvent::
 PointerEvent() :
-  _pointer(-1),
+  _device(-1),
+  _sequence(0),
   _time(0.0)
 {
 }
@@ -35,9 +36,10 @@ PointerEvent() :
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE PointerEvent::
-PointerEvent(int pointer, const MouseData &data, double time) :
-  _pointer(pointer),
+PointerEvent(int dev, const MouseData &data, int seq, double time) :
+  _device(dev),
   _data(data),
+  _sequence(seq),
   _time(time)
 {
 }
@@ -49,8 +51,9 @@ PointerEvent(int pointer, const MouseData &data, double time) :
 ////////////////////////////////////////////////////////////////////
 INLINE PointerEvent::
 PointerEvent(const PointerEvent &copy) :
-  _pointer(copy._pointer),
+  _device(copy._device),
   _data(copy._data),
+  _sequence(copy._sequence),
   _time(copy._time)
 {
 }
@@ -62,8 +65,9 @@ PointerEvent(const PointerEvent &copy) :
 ////////////////////////////////////////////////////////////////////
 INLINE void PointerEvent::
 operator = (const PointerEvent &copy) {
-  _pointer = copy._pointer;
+  _device = copy._device;
   _data = copy._data;
+  _sequence = copy._sequence;
   _time = copy._time;
 }
 
@@ -75,9 +79,10 @@ operator = (const PointerEvent &copy) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool PointerEvent::
 operator == (const PointerEvent &other) const {
-  return (_pointer == other._pointer &&
+  return (_device == other._device &&
           _data._xpos == other._data._xpos &&
           _data._ypos == other._data._ypos &&
+          _sequence == other._sequence &&
           _data._in_window == other._data._in_window);
 }
 
@@ -98,8 +103,11 @@ operator != (const PointerEvent &other) const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool PointerEvent::
 operator < (const PointerEvent &other) const {
-  if (_pointer != other._pointer) {
-    return _pointer < other._pointer;
+  if (_device != other._device) {
+    return _device < other._device;
+  }
+  if (_sequence != other._sequence) {
+    return _sequence < other._sequence;
   }
   if (_data._xpos != other._data._xpos) {
     return _data._xpos < other._data._xpos;

+ 6 - 5
panda/src/event/pointerEvent.cxx

@@ -27,9 +27,8 @@
 ////////////////////////////////////////////////////////////////////
 void PointerEvent::
 output(ostream &out) const {
-  out << "pointer " << _pointer << " to "
-      << _data._xpos << "," << _data._ypos
-      << (_data._in_window ? " in" : " out");
+  out << (_data._in_window ? "In@" : "Out@")
+      << _data._xpos << "," << _data._ypos << " ";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -39,10 +38,11 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 void PointerEvent::
 write_datagram(Datagram &dg) const {
-  dg.add_int8(_pointer);
+  dg.add_int8(_device);
   dg.add_bool(_data._in_window);
   dg.add_int32(_data._xpos);
   dg.add_int32(_data._ypos);
+  dg.add_int32(_sequence);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -52,9 +52,10 @@ write_datagram(Datagram &dg) const {
 ////////////////////////////////////////////////////////////////////
 void PointerEvent::
 read_datagram(DatagramIterator &scan) {
-  _pointer = scan.get_int8();
+  _device = scan.get_int8();
   _data._in_window = scan.get_bool();
   _data._xpos = scan.get_int32();
   _data._ypos = scan.get_int32();
+  _sequence = scan.get_int32();
   _time = 0.0;
 }

+ 3 - 2
panda/src/event/pointerEvent.h

@@ -34,7 +34,7 @@ public:
 
   INLINE PointerEvent();
   INLINE PointerEvent(const PointerEvent &copy);
-  INLINE PointerEvent(int pointer, const MouseData &data, double time);
+  INLINE PointerEvent(int dev, const MouseData &data, int seq, double time);
   INLINE void operator = (const PointerEvent &copy);
 
   INLINE bool operator == (const PointerEvent &other) const;
@@ -47,8 +47,9 @@ public:
   void read_datagram(DatagramIterator &scan);
 
 public:
-  int       _pointer;
+  int       _device;
   MouseData _data;
+  int       _sequence;
   double    _time;
 };
 

+ 66 - 1
panda/src/event/pointerEventList.I

@@ -59,7 +59,7 @@ add_event(const PointerEvent &event) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerEventList::get_num_events
-//       Access: Public
+//       Access: Published
 //  Description: Returns the number of events in the list.
 ////////////////////////////////////////////////////////////////////
 INLINE int PointerEventList::
@@ -67,6 +67,61 @@ get_num_events() const {
   return _events.size();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_x
+//       Access: Published
+//  Description: Get the x-coordinate of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE int PointerEventList::
+get_x(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._data._xpos;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_y
+//       Access: Published
+//  Description: Get the y-coordinate of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE int PointerEventList::
+get_y(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._data._ypos;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_in_window
+//       Access: Published
+//  Description: Get the in-window flag of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE bool PointerEventList::
+get_in_window(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._data._in_window;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_sequence
+//       Access: Published
+//  Description: Get the sequence number of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE int PointerEventList::
+get_sequence(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._sequence;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::get_time
+//       Access: Published
+//  Description: Get the timestamp of the nth event.
+////////////////////////////////////////////////////////////////////
+INLINE double PointerEventList::
+get_time(int evt) const {
+  nassertr((evt >= 0) && (evt < (int)_events.size()), 0);
+  return _events[evt]._time;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerEventList::get_event
 //       Access: Public
@@ -93,3 +148,13 @@ INLINE void PointerEventList::
 clear() {
   _events.clear();
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerEventList::pop_front
+//       Access: Public
+//  Description: Discards the first event on the list.
+////////////////////////////////////////////////////////////////////
+INLINE void PointerEventList::
+pop_front() {
+  _events.pop_front();
+}

+ 0 - 2
panda/src/event/pointerEventList.cxx

@@ -29,7 +29,6 @@ TypeHandle PointerEventList::_type_handle;
 ////////////////////////////////////////////////////////////////////
 void PointerEventList::
 add_events(const PointerEventList &other) {
-  _events.reserve(_events.size() + other._events.size());
   Events::const_iterator ei;
   for (ei = other._events.begin(); ei != other._events.end(); ++ei) {
     _events.push_back(*ei);
@@ -138,7 +137,6 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 
   int num_events = scan.get_uint16();
   _events.clear();
-  _events.reserve(num_events);
   for (int i = 0; i < num_events; i++) {
     PointerEvent event;
     event.read_datagram(scan);

+ 10 - 2
panda/src/event/pointerEventList.h

@@ -39,15 +39,23 @@ class DatagramIterator;
 //               is desired.
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_EVENT PointerEventList : public EventStoreValueBase {
+PUBLISHED:
+  INLINE int get_num_events() const;
+  INLINE int    get_x(int n) const;
+  INLINE int    get_y(int n) const;
+  INLINE bool   get_in_window(int n) const;
+  INLINE int    get_sequence(int n) const;
+  INLINE double get_time(int n) const;
+  
 public:
   INLINE PointerEventList();
   INLINE PointerEventList(const PointerEventList &copy);
   INLINE void operator = (const PointerEventList &copy);
 
   INLINE void add_event(const PointerEvent &event);
-  INLINE int get_num_events() const;
   INLINE const PointerEvent &get_event(int n) const;
   INLINE void clear();
+  INLINE void pop_front();
 
   void add_events(const PointerEventList &other);
   
@@ -55,7 +63,7 @@ public:
   void write(ostream &out, int indent_level = 0) const;
 
 private:
-  typedef pvector<PointerEvent> Events;
+  typedef pdeque<PointerEvent> Events;
   Events _events;
 
 public:

+ 6 - 6
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -79,8 +79,8 @@ glxGraphicsWindow(GraphicsPipe *pipe,
   _net_wm_state_remove = glx_pipe->_net_wm_state_remove;
 
   GraphicsWindowInputDevice device =
-    GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
-  _input_devices.push_back(device);
+    GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
+  add_input_device(device);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1080,8 +1080,8 @@ open_raw_mice()
 	  inf._io_buffer = "";
 	  _mouse_device_info.push_back(inf);
 	  GraphicsWindowInputDevice device =
-	    GraphicsWindowInputDevice::pointer_only(full_id);
-	  _input_devices.push_back(device);
+	    GraphicsWindowInputDevice::pointer_only(this, full_id);
+          add_input_device(device);
 	  glxdisplay_cat.info() << "Raw mouse " <<
 	    inf._input_device_index << " detected: " << full_id << "\n";
 	  any_mice = true;
@@ -1150,8 +1150,8 @@ poll_raw_mice()
     }
     const input_event *events = (const input_event *)(inf._io_buffer.c_str());
     GraphicsWindowInputDevice &dev = _input_devices[inf._input_device_index];
-    int x = dev.get_pointer().get_x();
-    int y = dev.get_pointer().get_y();
+    int x = _input_devices[i].get_raw_pointer().get_x();
+    int y = _input_devices[i].get_raw_pointer().get_y();
     for (int i=0; i<nevents; i++) {
       if (events[i].type == EV_REL) {
 	if (events[i].code == REL_X) x += events[i].value;

+ 2 - 2
panda/src/putil/mouseData.I

@@ -25,8 +25,8 @@
 INLINE MouseData::
 MouseData() {
   _in_window = false;
-  _xpos = 0;
-  _ypos = 0;
+  _xpos = 0.0;
+  _ypos = 0.0;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/putil/mouseData.h

@@ -43,8 +43,8 @@ PUBLISHED:
 
 public:
   bool _in_window;
-  int _xpos;
-  int _ypos;
+  double _xpos;
+  double _ypos;
 };
 
 INLINE ostream &operator << (ostream &out, const MouseData &md);

+ 31 - 0
panda/src/tform/mouseWatcher.I

@@ -619,3 +619,34 @@ without_region(MouseWatcherRegion *region, const MouseWatcherParameter &param) {
   region->without_region(param);
   throw_event_pattern(_without_pattern, region, ButtonHandle::none());
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::get_trail_log
+//       Access: Published
+//  Description: Obtain the mouse trail log.  This is a PointerEventList.
+//               Does not make a copy, therefore, this PointerEventList
+//               will be updated each time process_events gets called.
+//
+//               To use trail logging, you need to enable the
+//               generation of pointer events in the
+//               GraphicsWindowInputDevice and set the trail log
+//               duration in the MouseWatcher. Otherwise, the
+//               trail log will be empty.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(PointerEventList) MouseWatcher::
+get_trail_log() const {
+  return _trail_log;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::num_trail_recent
+//       Access: Published
+//  Description: This counter indicates how many events were added
+//               to the trail log this frame.  The trail log is
+//               updated once per frame, during the process_events
+//               operation.  
+////////////////////////////////////////////////////////////////////
+INLINE int MouseWatcher::
+num_trail_recent() const {
+  return _num_trail_recent;
+}

+ 158 - 6
panda/src/tform/mouseWatcher.cxx

@@ -29,6 +29,9 @@
 #include "dataNodeTransmit.h"
 #include "transformState.h"
 #include "displayRegion.h"
+#include "geomVertexWriter.h"
+#include "geomLinestrips.h"
+#include "geomPoints.h"
 #include "dcast.h"
 #include "indent.h"
 #include "mutexHolder.h"
@@ -51,6 +54,7 @@ MouseWatcher(const string &name) :
   _pixel_size_input = define_input("pixel_size", EventStoreVec2::get_class_type());
   _xy_input = define_input("xy", EventStoreVec2::get_class_type());
   _button_events_input = define_input("button_events", ButtonEventList::get_class_type());
+  _pointer_events_input = define_input("pointer_events", PointerEventList::get_class_type());
 
   _pixel_xy_output = define_output("pixel_xy", EventStoreVec2::get_class_type());
   _pixel_size_output = define_output("pixel_size", EventStoreVec2::get_class_type());
@@ -59,6 +63,7 @@ MouseWatcher(const string &name) :
 
   _pixel_xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
+  _pixel_size = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
   _button_events = new ButtonEventList;
 
   _has_mouse = false;
@@ -68,20 +73,24 @@ MouseWatcher(const string &name) :
   _button_down = false;
   _eh = (EventHandler *)NULL;
   _display_region = (DisplayRegion *)NULL;
-
+  
   _inactivity_timeout = inactivity_timeout;
   _has_inactivity_timeout = !IS_NEARLY_ZERO(_inactivity_timeout);
   
+  _num_trail_recent = 0;
+  _trail_log_duration = 0.0;
+  _trail_log = new PointerEventList();
+  
   _inactivity_timeout_event = "inactivity_timeout";
   _last_activity = 0.0;
   _inactivity_state = IS_active;
-
+  
   // When this flag is true, the mouse pointer is allowed to be
   // "entered" into multiple regions simultaneously; when false, it
   // will only be "within" multiple regions, but "entered" into the
   // topmost of those.
   _enter_multiple = false;
-
+  
   // When this flag is true, moving the pointer into a region is
   // enough to click it.  The click is simulated with mouse button
   // one.
@@ -344,6 +353,128 @@ get_group(int n) const {
   return _groups[n];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::set_trail_log_duration
+//       Access: Published
+//  Description: If the duration is nonzero, causes the MouseWatcher
+//               to log the mouse's trail.  Events older than the
+//               specified duration are discarded.  If the duration is
+//               zero, logging is disabled.
+////////////////////////////////////////////////////////////////////
+void MouseWatcher::
+set_trail_log_duration(double duration) {
+  if (duration < 0.0) {
+    duration = 0.0;
+  }
+  _trail_log_duration = duration;
+  discard_excess_trail_log();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::discard_excess_trail_log
+//       Access: Private
+//  Description: Discards trail log events whose age exceed the
+//               desired log duration.  Keeps one event that is beyond
+//               the specified age, because otherwise, it is not always
+//               possible to determine where the mouse was for the
+//               full logging duration.  If the duration is zero, this
+//               method discards all trail events.
+////////////////////////////////////////////////////////////////////
+void MouseWatcher::
+discard_excess_trail_log() {
+  if (_trail_log_duration == 0.0) {
+    _trail_log->clear();
+  } else {
+    if (_trail_log->get_num_events() >= 2) {
+      double old = ClockObject::get_global_clock()->get_frame_time() - _trail_log_duration;
+      while ((_trail_log->get_num_events() >= 2)&&
+             (_trail_log->get_time(0) <= old)&&
+             (_trail_log->get_time(1) <= old)) {
+        _trail_log->pop_front();
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::get_trail_node
+//       Access: Published
+//  Description: Returns a GeomNode that represents the mouse trail.
+//               The intent is that you should reparent this GeomNode
+//               to Render2D, and then forget about it.  The
+//               MouseWatcher will continually update the trail node.
+//               There is only one trail node, it does not create a
+//               new one each time you call get_trail_node.
+//
+//               This is not a particularly beautiful way to render
+//               a mouse trail.  It is intended more for debugging
+//               purposes than for finished applications.  Even so,
+//               It is suggested that you might want to apply a line
+//               thickness and antialias mode to the line --- doing
+//               so makes it look a lot better.
+////////////////////////////////////////////////////////////////////
+PT(GeomNode) MouseWatcher::
+get_trail_node() {
+  if (_trail_node == 0) {
+    _trail_node = new GeomNode("Mouse Trail Node");
+    update_trail_node();
+  }
+  return _trail_node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::clear_trail_node
+//       Access: Published
+//  Description: If you have previously fetched the trail node
+//               using get_trail_node, then the MouseWatcher is
+//               continually updating the trail node every frame.
+//               Using clear_trail_node causes the MouseWatcher to
+//               forget the trail node and stop updating it.
+////////////////////////////////////////////////////////////////////
+void MouseWatcher::
+clear_trail_node() {
+  _trail_node = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcher::update_trail_node
+//       Access: Private
+//  Description: Causes the trail node to represent the mouse trail.
+////////////////////////////////////////////////////////////////////
+void MouseWatcher::
+update_trail_node() {
+  if (_trail_node == 0) {
+    return;
+  }
+  _trail_node->remove_all_geoms();
+
+  if (_trail_log->get_num_events() < 2) {
+    return;
+  }
+  
+  PT(GeomVertexData) data = new GeomVertexData
+    ("mouseTrailSegs", GeomVertexFormat::get_v3(), Geom::UH_static);
+  
+  GeomVertexWriter vertex(data, InternalName::get_vertex());
+    
+  PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
+  
+  double xscale = 2.0 / _pixel_size->get_value().get_x();
+  double yscale = 2.0 / _pixel_size->get_value().get_y();
+  
+  for (int i=0; i<(int)_trail_log->get_num_events(); i++) {
+    double x = (_trail_log->get_x(i) * xscale) - 1.0;
+    double y = (_trail_log->get_y(i) * yscale) - 1.0;
+    vertex.add_data3f(LVecBase3f(x,0.0,-y));
+    lines->add_vertex(i);
+  }
+  lines->close_primitive();
+
+  PT(Geom) l_geom = new Geom(data);
+  l_geom->add_primitive(lines);
+  _trail_node->add_geom(l_geom);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MouseWatcher::note_activity
 //       Access: Published
@@ -1242,6 +1373,12 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   _internal_suppress = 0;
   _external_suppress = 0;
 
+  // We always pass the pixel_size data through.
+  EventStoreVec2 *pixel_size;
+  DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_ptr());
+  output.set_data(_pixel_size_output, pixel_size);
+  _pixel_size = pixel_size;
+
   if (!input.has_data(_xy_input)) {
     // No mouse in the window.
     set_no_mouse();
@@ -1305,6 +1442,24 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
     }
   }
 
+  // Code for recording the mouse trail.
+  _num_trail_recent = 0;
+  if (input.has_data(_pointer_events_input) && (_trail_log_duration > 0.0)) {
+    const PointerEventList *this_pointer_events;
+    DCAST_INTO_V(this_pointer_events, input.get_data(_pointer_events_input).get_ptr());
+    _num_trail_recent = this_pointer_events->get_num_events();
+    for (int i = 0; i < _num_trail_recent; i++) {
+      _trail_log->add_event(this_pointer_events->get_event(i));
+    }
+  }
+  if (_trail_log->get_num_events() > 0) {
+    discard_excess_trail_log();
+    update_trail_node();
+  }
+  if (_num_trail_recent > _trail_log->get_num_events()) {
+    _num_trail_recent = _trail_log->get_num_events();
+  }
+  
   // If the mouse is over a particular region, or still considered
   // owned by a region because of a recent button-down event, that
   // region determines whether we suppress events below us.
@@ -1481,7 +1636,4 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   if (_button_events->get_num_events() != 0) {
     output.set_data(_button_events_output, EventParameter(_button_events));
   }
-
-  // We always pass the pixel_size data through.
-  output.set_data(_pixel_size_output, input.get_data(_pixel_size_input));
 }

+ 20 - 3
panda/src/tform/mouseWatcher.h

@@ -30,6 +30,8 @@
 #include "modifierButtons.h"
 #include "buttonHandle.h"
 #include "buttonEventList.h"
+#include "pointerEvent.h"
+#include "pointerEventList.h"
 #include "linmath_events.h"
 #include "bitArray.h"
 #include "clockObject.h"
@@ -130,7 +132,13 @@ PUBLISHED:
 
   INLINE void set_inactivity_timeout_event(const string &event);
   INLINE const string &get_inactivity_timeout_event() const;
-
+  
+  INLINE CPT(PointerEventList) get_trail_log() const;
+  INLINE int   num_trail_recent() const;
+  void         set_trail_log_duration(double duration);
+  PT(GeomNode) get_trail_node();
+  void         clear_trail_node();
+  
   void note_activity();
 
 public:
@@ -184,7 +192,9 @@ protected:
 
 private:
   void consider_keyboard_suppress(const MouseWatcherRegion *region);
-
+  void discard_excess_trail_log();
+  void update_trail_node();
+  
 private:
   // This wants to be a set, but because you cannot export sets across
   // dlls in windows, we will make it a vector instead
@@ -198,6 +208,11 @@ private:
   LPoint2f _mouse_pixel;
   BitArray _current_buttons_down;
 
+  PT(PointerEventList) _trail_log;
+  int _num_trail_recent;
+  double _trail_log_duration;
+  PT(GeomNode) _trail_node;
+  
   Regions _current_regions;
   PT(MouseWatcherRegion) _preferred_region;
   PT(MouseWatcherRegion) _preferred_button_down_region;
@@ -215,7 +230,7 @@ private:
   string _without_pattern;
 
   PT(PandaNode) _geometry;
-
+  
   EventHandler *_eh;
   ModifierButtons _mods;
   DisplayRegion *_display_region;
@@ -251,6 +266,7 @@ private:
   int _pixel_size_input;
   int _xy_input;
   int _button_events_input;
+  int _pointer_events_input;
 
   // outputs
   int _pixel_xy_output;
@@ -260,6 +276,7 @@ private:
 
   PT(EventStoreVec2) _pixel_xy;
   PT(EventStoreVec2) _xy;
+  PT(EventStoreVec2) _pixel_size;
   PT(ButtonEventList) _button_events;
 
 public:

+ 6 - 6
panda/src/windisplay/winGraphicsWindow.cxx

@@ -459,8 +459,8 @@ initialize_input_devices() {
   // Clear the handle array, and set up the system keyboard/mouse
   memset(_input_device_handle, 0, sizeof(_input_device_handle));
   GraphicsWindowInputDevice device =
-    GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
-  _input_devices.push_back(device);
+    GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
+  add_input_device(device);
   
   // Try initializing the Raw Input function pointers.
   if (pRegisterRawInputDevices==0) {
@@ -517,9 +517,9 @@ initialize_input_devices() {
           }
           if (pound2) *pound2 = '.';
           _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
-          GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(psName);
+          GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(this, psName);
           device.set_pointer_in_window(0,0);
-          _input_devices.push_back(device);
+          add_input_device(device);
         }
       }
     }
@@ -2183,8 +2183,8 @@ handle_raw_input(HRAWINPUT hraw) {
       if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
         _input_devices[i].set_pointer_in_window(adjx, adjy);
       } else {
-        int oldx = _input_devices[i].get_pointer().get_x();
-        int oldy = _input_devices[i].get_pointer().get_y();
+        int oldx = _input_devices[i].get_raw_pointer().get_x();
+        int oldy = _input_devices[i].get_raw_pointer().get_y();
         _input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy);
       }