Просмотр исходного кода

Build on Windows; add XInput gamepad implementation

rdb 10 лет назад
Родитель
Сommit
35add447e6

+ 1 - 0
dtool/src/parser-inc/windows.h

@@ -39,6 +39,7 @@ typedef unsigned long ULONG_PTR;
 // http://msdn.microsoft.com/en-us/library/cc230309.aspx
 // http://msdn.microsoft.com/en-us/library/cc230309.aspx
 typedef bool BOOL;
 typedef bool BOOL;
 typedef unsigned long DWORD;
 typedef unsigned long DWORD;
+typedef unsigned short WORD;
 typedef long LONG;
 typedef long LONG;
 typedef long UINT;
 typedef long UINT;
 typedef unsigned long ULONG;
 typedef unsigned long ULONG;

+ 5 - 0
panda/src/device/config_device.cxx

@@ -28,6 +28,7 @@
 #include "linuxJoystickDevice.h"
 #include "linuxJoystickDevice.h"
 #include "trackerNode.h"
 #include "trackerNode.h"
 #include "virtualMouse.h"
 #include "virtualMouse.h"
+#include "xInputDevice.h"
 
 
 #include "dconfig.h"
 #include "dconfig.h"
 
 
@@ -74,4 +75,8 @@ init_libdevice() {
   EvdevInputDevice::init_type();
   EvdevInputDevice::init_type();
   LinuxJoystickDevice::init_type();
   LinuxJoystickDevice::init_type();
 #endif
 #endif
+
+#ifdef _WIN32
+  XInputDevice::init_type();
+#endif
 }
 }

+ 7 - 2
panda/src/device/inputDeviceManager.cxx

@@ -30,9 +30,10 @@ InputDeviceManager *InputDeviceManager::_global_ptr = NULL;
 //       Access: Private
 //       Access: Private
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
+#ifdef PHAVE_LINUX_INPUT_H
 InputDeviceManager::
 InputDeviceManager::
 InputDeviceManager() : _inotify_fd(-1) {
 InputDeviceManager() : _inotify_fd(-1) {
-#ifdef PHAVE_LINUX_INPUT_H
+
   // Scan /dev/input for a list of input devices.
   // Scan /dev/input for a list of input devices.
   DIR *dir = opendir("/dev/input");
   DIR *dir = opendir("/dev/input");
   if (dir) {
   if (dir) {
@@ -70,8 +71,12 @@ InputDeviceManager() : _inotify_fd(-1) {
     device_cat.error()
     device_cat.error()
       << "Error adding inotify watch on /dev/input: " << strerror(errno) << "\n";
       << "Error adding inotify watch on /dev/input: " << strerror(errno) << "\n";
   }
   }
-#endif
 }
 }
+#else
+InputDeviceManager::
+InputDeviceManager() {
+}
+#endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: InputDeviceManager::Destructor
 //     Function: InputDeviceManager::Destructor

+ 1 - 1
panda/src/device/p3device_composite2.cxx

@@ -6,4 +6,4 @@
 #include "trackerData.cxx"
 #include "trackerData.cxx"
 #include "trackerNode.cxx"
 #include "trackerNode.cxx"
 #include "virtualMouse.cxx"
 #include "virtualMouse.cxx"
-
+#include "xInputDevice.cxx"

+ 214 - 0
panda/src/device/xInputDevice.cxx

@@ -0,0 +1,214 @@
+// Filename: xInputDevice.cxx
+// Created by:  rdb (21Jul15)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xInputDevice.h"
+
+#ifdef _WIN32
+#include "gamepadButton.h"
+
+#include <XInput.h>
+
+#ifndef XUSER_MAX_COUNT
+#define XUSER_MAX_COUNT 4
+#endif
+
+#ifndef XINPUT_CAPS_FFB_SUPPORTED
+#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
+#endif
+
+typedef DWORD (*pXInputGetState)(DWORD, XINPUT_STATE *);
+typedef DWORD (*pXInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES *);
+//typedef DWORD (*pXInputGetBatteryInformation)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *);
+
+static pXInputGetState get_state = NULL;
+static pXInputGetCapabilities get_capabilities = NULL;
+//static pXInputGetBatteryInformation get_battery_information = NULL;
+
+bool XInputDevice::_initialized = false;
+
+////////////////////////////////////////////////////////////////////
+//     Function: XInputDevice::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+XInputDevice::
+XInputDevice(DWORD user_index) :
+  _index(user_index),
+  _last_packet(-1),
+  _last_buttons(0) {
+
+  nassertv(user_index >= 0 && user_index < XUSER_MAX_COUNT);
+
+  if (!_initialized) {
+    nassertv(init_xinput());
+  }
+
+  if (get_capabilities != NULL) {
+    XINPUT_CAPABILITIES caps;
+    if (get_capabilities(_index, 0, &caps) == ERROR_SUCCESS) {
+      _is_connected = true;
+    } else {
+      _is_connected = false;
+    }
+
+    if (caps.Type == XINPUT_DEVTYPE_GAMEPAD) {
+      _device_class = DC_gamepad;
+    } else {
+      _device_class = DC_unknown;
+    }
+
+    if (caps.Flags & XINPUT_CAPS_FFB_SUPPORTED) {
+      _flags |= IDF_has_vibration;
+    }
+  }
+
+#if 0
+  if (get_battery_information != NULL) {
+    XINPUT_BATTERY_INFORMATION batt;
+    if (XInputGetBatteryInformation(_index, BATTERY_DEVTYPE_GAMEPAD, &batt) == ERROR_SUCCESS) {
+      if (batt.BatteryType == BATTERY_TYPE_DISCONNECTED) {
+        _is_connected = false;
+
+      } else if (batt.BatteryType != BATTERY_TYPE_WIRED) {
+        // This device has a battery.  Report the battery level.
+        _is_connected = true;
+        _flags |= IDF_has_battery;
+        _battery_level = batt.BatteryLevel;
+        _max_battery_level = BATTERY_LEVEL_FULL;
+      }
+    }
+  }
+#endif
+
+  _buttons.resize(16);
+
+  // Get the initial state.
+  XINPUT_STATE state;
+  if (get_state(_index, &state) != ERROR_SUCCESS) {
+    // Device was disconnected.
+    _is_connected = false;
+    return;
+  }
+
+  WORD buttons = state.Gamepad.wButtons;
+
+  set_button_map(0, GamepadButton::dpad_up());
+  set_button_state(0, (buttons & XINPUT_GAMEPAD_DPAD_UP) != 0);
+  set_button_map(1, GamepadButton::dpad_down());
+  set_button_state(1, (buttons & XINPUT_GAMEPAD_DPAD_DOWN) != 0);
+  set_button_map(2, GamepadButton::dpad_left());
+  set_button_state(2, (buttons & XINPUT_GAMEPAD_DPAD_LEFT) != 0);
+  set_button_map(3, GamepadButton::dpad_right());
+  set_button_state(3, (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0);
+  set_button_map(4, GamepadButton::start());
+  set_button_state(4, (buttons & XINPUT_GAMEPAD_START) != 0);
+  set_button_map(5, GamepadButton::back());
+  set_button_state(5, (buttons & XINPUT_GAMEPAD_BACK) != 0);
+  set_button_map(6, GamepadButton::lstick());
+  set_button_state(6, (buttons & XINPUT_GAMEPAD_LEFT_THUMB) != 0);
+  set_button_map(7, GamepadButton::rstick());
+  set_button_state(7, (buttons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0);
+  set_button_map(8, GamepadButton::lshoulder());
+  set_button_state(8, (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0);
+  set_button_map(9, GamepadButton::rshoulder());
+  set_button_state(9, (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0);
+  set_button_map(10, GamepadButton::guide());
+  set_button_state(10, (buttons & 0x0400) != 0);
+  set_button_map(11, GamepadButton::action_a());
+  set_button_state(11, (buttons & XINPUT_GAMEPAD_A) != 0);
+  set_button_map(12, GamepadButton::action_b());
+  set_button_state(12, (buttons & XINPUT_GAMEPAD_B) != 0);
+  set_button_map(13, GamepadButton::action_x());
+  set_button_state(13, (buttons & XINPUT_GAMEPAD_X) != 0);
+  set_button_map(14, GamepadButton::action_y());
+  set_button_state(14, (buttons & XINPUT_GAMEPAD_Y) != 0);
+
+  _last_buttons = buttons;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XInputDevice::init
+//       Access: Protected, Static
+//  Description: Initializes the XInput library.
+////////////////////////////////////////////////////////////////////
+bool XInputDevice::
+init_xinput() {
+  _initialized = true;
+  HMODULE module = LoadLibraryA("Xinput1_4.dll");
+  if (module) {
+    // Undocumented version (XInputGetStateEx) that includes a
+    // state bit for the guide button.
+    get_state = (pXInputGetState)GetProcAddress(module, MAKEINTRESOURCE(100));
+    if (get_state == NULL) {
+      get_state = (pXInputGetState)GetProcAddress(module, "XInputGetState");
+      if (get_state == NULL) {
+        device_cat.error()
+          << "Failed to find function XInputGetState in XInput DLL.\n";
+        return false;
+      }
+    }
+
+    get_capabilities = (pXInputGetCapabilities)GetProcAddress(module, "XInputGetCapabilities");
+    return true;
+  }
+
+  device_cat.error()
+    << "Failed to load Xinput1_4.dll.\n";
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InputDevice::do_poll
+//       Access: Public, Virtual
+//  Description: Polls the input device for new activity, to ensure
+//               it contains the latest events.  This will only have
+//               any effect for some types of input devices; others
+//               may be updated automatically, and this method will
+//               be a no-op.
+////////////////////////////////////////////////////////////////////
+void XInputDevice::
+do_poll() {
+  XINPUT_STATE state;
+
+  if (get_state(_index, &state) != ERROR_SUCCESS) {
+    // Device was disconnected.
+    _is_connected = false;
+    return;
+  } else {
+    _is_connected = true;
+  }
+
+  if (state.dwPacketNumber == _last_packet) {
+    // No change since last time we asked.
+    return;
+  }
+
+  WORD changed_buttons = _last_buttons ^ state.Gamepad.wButtons;
+
+  WORD mask = 1;
+  for (int i = 0; i < 16; ++i) {
+    if (changed_buttons & mask) {
+      set_button_state(i, (state.Gamepad.wButtons & mask) != 0);
+    }
+    mask <<= 1;
+    if (i == 10) {
+      mask <<= 1;
+    }
+  }
+
+  _last_buttons = state.Gamepad.wButtons;
+  _last_packet = state.dwPacketNumber;
+}
+
+#endif  // _WIN32

+ 50 - 0
panda/src/device/xInputDevice.h

@@ -0,0 +1,50 @@
+// Filename: xInputDevice.h
+// Created by:  rdb (21Jul15)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XINPUTDEVICE_H
+#define XINPUTDEVICE_H
+
+#include "pandabase.h"
+#include "inputDevice.h"
+
+#ifdef _WIN32
+
+////////////////////////////////////////////////////////////////////
+//       Class : XInputDevice
+// Description : This uses Microsoft's XInput library to interface
+//               with an Xbox 360 game controller.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_DEVICE XInputDevice : public InputDevice {
+PUBLISHED:
+  XInputDevice(DWORD user_index);
+
+  static bool init_xinput();
+
+public:
+  virtual void do_poll();
+
+private:
+  DWORD _index;
+  DWORD _last_packet;
+  WORD _last_buttons;
+
+  static bool _initialized;
+
+  // There are only four of these in existence.
+  //static XInputDevice _devices[4];
+};
+
+#endif  // _WIN32
+
+#endif

+ 1 - 1
panda/src/event/buttonEventList.h

@@ -35,7 +35,7 @@ class DatagramIterator;
 //               is desired.
 //               is desired.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_EVENT ButtonEventList : public ParamValueBase {
 class EXPCL_PANDA_EVENT ButtonEventList : public ParamValueBase {
-public:
+PUBLISHED:
   INLINE ButtonEventList();
   INLINE ButtonEventList();
   INLINE ButtonEventList(const ButtonEventList &copy);
   INLINE ButtonEventList(const ButtonEventList &copy);
   INLINE void operator = (const ButtonEventList &copy);
   INLINE void operator = (const ButtonEventList &copy);

+ 38 - 37
panda/src/windisplay/winGraphicsWindow.cxx

@@ -146,7 +146,7 @@ move_pointer(int device, int x, int y) {
   if (device == 0) {
   if (device == 0) {
     // Move the system mouse pointer.
     // Move the system mouse pointer.
     if (!_properties.get_foreground() )
     if (!_properties.get_foreground() )
-      //      !_input_devices[0].get_pointer().get_in_window())
+      //      !_input->get_pointer().get_in_window())
       {
       {
         // If the window doesn't have input focus, or the mouse isn't
         // If the window doesn't have input focus, or the mouse isn't
         // currently within the window, forget it.
         // currently within the window, forget it.
@@ -157,14 +157,14 @@ move_pointer(int device, int x, int y) {
     get_client_rect_screen(_hWnd, &view_rect);
     get_client_rect_screen(_hWnd, &view_rect);
 
 
     SetCursorPos(view_rect.left + x, view_rect.top + y);
     SetCursorPos(view_rect.left + x, view_rect.top + y);
-    _input_devices[0].set_pointer_in_window(x, y);
+    _input->set_pointer_in_window(x, y);
     return true;
     return true;
   } else {
   } else {
     // Move a raw mouse.
     // Move a raw mouse.
     if ((device < 1)||(device >= (int)_input_devices.size())) {
     if ((device < 1)||(device >= (int)_input_devices.size())) {
       return false;
       return false;
     }
     }
-    _input_devices[device].set_pointer_in_window(x, y);
+    //_input_devices[device].set_pointer_in_window(x, y);
     return true;
     return true;
   }
   }
 }
 }
@@ -587,7 +587,6 @@ open_window() {
 //               initializes a parallel array, _input_device_handle,
 //               initializes a parallel array, _input_device_handle,
 //               with the win32 handle of each raw input device.
 //               with the win32 handle of each raw input device.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 initialize_input_devices() {
 initialize_input_devices() {
   UINT nInputDevices;
   UINT nInputDevices;
@@ -597,9 +596,10 @@ initialize_input_devices() {
 
 
   // Clear the handle array, and set up the system keyboard/mouse
   // Clear the handle array, and set up the system keyboard/mouse
   memset(_input_device_handle, 0, sizeof(_input_device_handle));
   memset(_input_device_handle, 0, sizeof(_input_device_handle));
-  GraphicsWindowInputDevice device =
+  PT(GraphicsWindowInputDevice) device =
     GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
     GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
   add_input_device(device);
   add_input_device(device);
+  _input = device;
 
 
   // Try initializing the Raw Input function pointers.
   // Try initializing the Raw Input function pointers.
   if (pRegisterRawInputDevices==0) {
   if (pRegisterRawInputDevices==0) {
@@ -656,9 +656,9 @@ initialize_input_devices() {
           }
           }
           if (pound2) *pound2 = '.';
           if (pound2) *pound2 = '.';
           _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
           _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
-          GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(this, psName);
-          device.set_pointer_in_window(0,0);
-          add_input_device(device);
+          //GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(this, psName);
+          //device.set_pointer_in_window(0,0);
+          //add_input_device(device);
         }
         }
       }
       }
     }
     }
@@ -1578,8 +1578,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     SetCapture(hwnd);
     SetCapture(hwnd);
-    _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
-    _input_devices[0].button_down(MouseButton::button(0), get_message_time());
+    _input->set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+    _input->button_down(MouseButton::button(0), get_message_time());
 
 
     // A button-click in the window means to grab the keyboard focus.
     // A button-click in the window means to grab the keyboard focus.
     set_focus();
     set_focus();
@@ -1590,8 +1590,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     SetCapture(hwnd);
     SetCapture(hwnd);
-    _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
-    _input_devices[0].button_down(MouseButton::button(1), get_message_time());
+    _input->set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+    _input->button_down(MouseButton::button(1), get_message_time());
     // A button-click in the window means to grab the keyboard focus.
     // A button-click in the window means to grab the keyboard focus.
     set_focus();
     set_focus();
     return 0;
     return 0;
@@ -1601,8 +1601,8 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     SetCapture(hwnd);
     SetCapture(hwnd);
-    _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
-    _input_devices[0].button_down(MouseButton::button(2), get_message_time());
+    _input->set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+    _input->button_down(MouseButton::button(2), get_message_time());
     // A button-click in the window means to grab the keyboard focus.
     // A button-click in the window means to grab the keyboard focus.
     set_focus();
     set_focus();
     return 0;
     return 0;
@@ -1614,11 +1614,11 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       }
       }
       SetCapture(hwnd);
       SetCapture(hwnd);
       int whichButton = GET_XBUTTON_WPARAM(wparam);
       int whichButton = GET_XBUTTON_WPARAM(wparam);
-      _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+      _input->set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
       if (whichButton == XBUTTON1) {
       if (whichButton == XBUTTON1) {
-        _input_devices[0].button_down(MouseButton::button(3), get_message_time());
+        _input->button_down(MouseButton::button(3), get_message_time());
       } else if (whichButton == XBUTTON2) {
       } else if (whichButton == XBUTTON2) {
-        _input_devices[0].button_down(MouseButton::button(4), get_message_time());
+        _input->button_down(MouseButton::button(4), get_message_time());
       }
       }
     }
     }
     return 0;
     return 0;
@@ -1628,7 +1628,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     ReleaseCapture();
     ReleaseCapture();
-    _input_devices[0].button_up(MouseButton::button(0), get_message_time());
+    _input->button_up(MouseButton::button(0), get_message_time());
     return 0;
     return 0;
 
 
   case WM_MBUTTONUP:
   case WM_MBUTTONUP:
@@ -1636,7 +1636,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     ReleaseCapture();
     ReleaseCapture();
-    _input_devices[0].button_up(MouseButton::button(1), get_message_time());
+    _input->button_up(MouseButton::button(1), get_message_time());
     return 0;
     return 0;
 
 
   case WM_RBUTTONUP:
   case WM_RBUTTONUP:
@@ -1644,7 +1644,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       resend_lost_keypresses();
       resend_lost_keypresses();
     }
     }
     ReleaseCapture();
     ReleaseCapture();
-    _input_devices[0].button_up(MouseButton::button(2), get_message_time());
+    _input->button_up(MouseButton::button(2), get_message_time());
     return 0;
     return 0;
 
 
   case WM_XBUTTONUP:
   case WM_XBUTTONUP:
@@ -1655,9 +1655,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       ReleaseCapture();
       ReleaseCapture();
       int whichButton = GET_XBUTTON_WPARAM(wparam);
       int whichButton = GET_XBUTTON_WPARAM(wparam);
       if (whichButton == XBUTTON1) {
       if (whichButton == XBUTTON1) {
-        _input_devices[0].button_up(MouseButton::button(3), get_message_time());
+        _input->button_up(MouseButton::button(3), get_message_time());
       } else if (whichButton == XBUTTON2) {
       } else if (whichButton == XBUTTON2) {
-        _input_devices[0].button_up(MouseButton::button(4), get_message_time());
+        _input->button_up(MouseButton::button(4), get_message_time());
       }
       }
     }
     }
     return 0;
     return 0;
@@ -1777,7 +1777,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
 
     if (ime_aware) {
     if (ime_aware) {
       wstring ws;
       wstring ws;
-      _input_devices[0].candidate(ws, 0, 0, 0);
+      _input->candidate(ws, 0, 0, 0);
     }
     }
 
 
     break;
     break;
@@ -1808,7 +1808,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
                                                ime_buffer, ime_buffer_size_bytes);
                                                ime_buffer, ime_buffer_size_bytes);
         size_t num_chars = result_size / sizeof(wchar_t);
         size_t num_chars = result_size / sizeof(wchar_t);
         for (size_t i = 0; i < num_chars; ++i) {
         for (size_t i = 0; i < num_chars; ++i) {
-          _input_devices[0].keystroke(ime_buffer[i]);
+          _input->keystroke(ime_buffer[i]);
         }
         }
       }
       }
 
 
@@ -1821,7 +1821,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size);
         result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size);
         size_t num_chars = result_size / sizeof(wchar_t);
         size_t num_chars = result_size / sizeof(wchar_t);
 
 
-        _input_devices[0].candidate(wstring(ime_buffer, num_chars),
+        _input->candidate(wstring(ime_buffer, num_chars),
                                     min(cursor_pos, delta_start),
                                     min(cursor_pos, delta_start),
                                     max(cursor_pos, delta_start),
                                     max(cursor_pos, delta_start),
                                     cursor_pos);
                                     cursor_pos);
@@ -1843,7 +1843,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     // poorly defined.  Now we are using RegisterClassW etc., which
     // poorly defined.  Now we are using RegisterClassW etc., which
     // means WM_CHAR is absolutely supposed to be utf-16.
     // means WM_CHAR is absolutely supposed to be utf-16.
     if (!_ime_open) {
     if (!_ime_open) {
-      _input_devices[0].keystroke(wparam);
+      _input->keystroke(wparam);
     }
     }
     break;
     break;
 
 
@@ -1975,7 +1975,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             if (lptstr != NULL)  {
             if (lptstr != NULL)  {
               char *pChar;
               char *pChar;
               for (pChar=lptstr; *pChar!=NULL; pChar++) {
               for (pChar=lptstr; *pChar!=NULL; pChar++) {
-                _input_devices[0].keystroke((uchar)*pChar);
+                _input->keystroke((uchar)*pChar);
               }
               }
               GlobalUnlock(hglb);
               GlobalUnlock(hglb);
             }
             }
@@ -2098,7 +2098,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         << "killfocus\n";
         << "killfocus\n";
     }
     }
 
 
-    _input_devices[0].focus_lost(get_message_time());
+    _input->focus_lost(get_message_time());
     properties.set_foreground(false);
     properties.set_foreground(false);
     system_changed_properties(properties);
     system_changed_properties(properties);
     break;
     break;
@@ -2409,9 +2409,9 @@ show_error_message(DWORD message_id) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_keypress(ButtonHandle key, int x, int y, double time) {
 handle_keypress(ButtonHandle key, int x, int y, double time) {
-  _input_devices[0].set_pointer_in_window(x, y);
+  _input->set_pointer_in_window(x, y);
   if (key != ButtonHandle::none()) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].button_down(key, time);
+    _input->button_down(key, time);
   }
   }
 }
 }
 
 
@@ -2425,7 +2425,7 @@ handle_keypress(ButtonHandle key, int x, int y, double time) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_keyresume(ButtonHandle key, double time) {
 handle_keyresume(ButtonHandle key, double time) {
   if (key != ButtonHandle::none()) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].button_resume_down(key, time);
+    _input->button_resume_down(key, time);
   }
   }
 }
 }
 
 
@@ -2437,7 +2437,7 @@ handle_keyresume(ButtonHandle key, double time) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_keyrelease(ButtonHandle key, double time) {
 handle_keyrelease(ButtonHandle key, double time) {
   if (key != ButtonHandle::none()) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].button_up(key, time);
+    _input->button_up(key, time);
   }
   }
 }
 }
 
 
@@ -2449,7 +2449,7 @@ handle_keyrelease(ButtonHandle key, double time) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_raw_keypress(ButtonHandle key, double time) {
 handle_raw_keypress(ButtonHandle key, double time) {
   if (key != ButtonHandle::none()) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].raw_button_down(key, time);
+    _input->raw_button_down(key, time);
   }
   }
 }
 }
 
 
@@ -2461,7 +2461,7 @@ handle_raw_keypress(ButtonHandle key, double time) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_raw_keyrelease(ButtonHandle key, double time) {
 handle_raw_keyrelease(ButtonHandle key, double time) {
   if (key != ButtonHandle::none()) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].raw_button_up(key, time);
+    _input->raw_button_up(key, time);
   }
   }
 }
 }
 
 
@@ -2777,7 +2777,7 @@ handle_raw_input(HRAWINPUT hraw) {
   if (raw->header.hDevice == 0) {
   if (raw->header.hDevice == 0) {
     return;
     return;
   }
   }
-
+/*
   for (int i = 1; i < (int)(_input_devices.size()); ++i) {
   for (int i = 1; i < (int)(_input_devices.size()); ++i) {
     if (_input_device_handle[i] == raw->header.hDevice) {
     if (_input_device_handle[i] == raw->header.hDevice) {
       int adjx = raw->data.mouse.lLastX;
       int adjx = raw->data.mouse.lLastX;
@@ -2823,6 +2823,7 @@ handle_raw_input(HRAWINPUT hraw) {
       }
       }
     }
     }
   }
   }
+*/
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -2832,7 +2833,7 @@ handle_raw_input(HRAWINPUT hraw) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool WinGraphicsWindow::
 bool WinGraphicsWindow::
 handle_mouse_motion(int x, int y) {
 handle_mouse_motion(int x, int y) {
-  _input_devices[0].set_pointer_in_window(x, y);
+  _input->set_pointer_in_window(x, y);
   return false;
   return false;
 }
 }
 
 
@@ -2844,7 +2845,7 @@ handle_mouse_motion(int x, int y) {
 void WinGraphicsWindow::
 void WinGraphicsWindow::
 handle_mouse_exit() {
 handle_mouse_exit() {
   // note: 'mouse_motion' is considered the 'entry' event
   // note: 'mouse_motion' is considered the 'entry' event
-  _input_devices[0].set_pointer_out_of_window();
+  _input->set_pointer_out_of_window();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 2
panda/src/windisplay/winGraphicsWindow.h

@@ -110,7 +110,7 @@ protected:
 
 
   virtual DWORD make_style(bool fullscreen);
   virtual DWORD make_style(bool fullscreen);
 
 
-  virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, 
+  virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size,
                                           DWORD &bitdepth);
                                           DWORD &bitdepth);
 
 
   virtual void support_overlay_window(bool flag);
   virtual void support_overlay_window(bool flag);
@@ -179,6 +179,8 @@ private:
   bool _lalt_down;
   bool _lalt_down;
   bool _ralt_down;
   bool _ralt_down;
 
 
+  GraphicsWindowInputDevice *_input;
+
   // following adds support platform specfic window processing
   // following adds support platform specfic window processing
   // functions.
   // functions.
   typedef pset<GraphicsWindowProc*> WinProcClasses;
   typedef pset<GraphicsWindowProc*> WinProcClasses;
@@ -276,7 +278,7 @@ private:
       return get_class_type();
       return get_class_type();
     }
     }
     virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
     virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-    
+
   private:
   private:
     static TypeHandle _type_handle;
     static TypeHandle _type_handle;
   };
   };