Multiple fixes for joystick interface: * fix off-by-one error where wxJoystickEvent ZPosition was taken from rudder axis * correctly generate and post joystick movement events * check driver capabilities and events against axis and button count class limits * implement movement thresholds * add new interface to get axis position by index, allowing caller to iterate over axes rather than calling axis-specific functions * add new interface to get button position by index, rather than a bitfield of all buttons (will allow devices with >32 buttons) --- include/wx/mac/carbon/joystick.h.orig 2007-03-07 12:25:30.000000000 -0500 +++ include/wx/mac/carbon/joystick.h 2007-03-07 12:26:12.000000000 -0500 @@ -32,6 +32,8 @@ class WXDLLEXPORT wxJoystick: public wxO //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition() const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition() const; int GetButtonState() const; int GetPOVPosition() const; --- include/wx/mac/corefoundation/joystick.h.orig 2007-03-07 12:25:30.000000000 -0500 +++ include/wx/mac/corefoundation/joystick.h 2007-03-07 12:26:21.000000000 -0500 @@ -32,6 +32,8 @@ class WXDLLEXPORT wxJoystick: public wxO //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition() const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition() const; int GetButtonState() const; int GetPOVPosition() const; --- include/wx/mac/classic/joystick.h.orig 2007-03-07 12:25:30.000000000 -0500 +++ include/wx/mac/classic/joystick.h 2007-03-07 12:26:36.000000000 -0500 @@ -32,6 +32,8 @@ class WXDLLEXPORT wxJoystick: public wxO //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition() const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition() const; int GetButtonState() const; int GetPOVPosition() const; --- include/wx/msw/joystick.h.orig 2007-03-07 12:25:30.000000000 -0500 +++ include/wx/msw/joystick.h 2007-03-07 12:26:47.000000000 -0500 @@ -32,6 +32,8 @@ class WXDLLIMPEXP_ADV wxJoystick: public //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition(void) const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition(void) const; int GetButtonState(void) const; int GetPOVPosition(void) const; --- include/wx/unix/joystick.h.orig 2007-03-07 11:13:20.000000000 -0500 +++ include/wx/unix/joystick.h 2007-03-07 11:14:21.000000000 -0500 @@ -36,6 +36,8 @@ class WXDLLEXPORT wxJoystick: public wxO //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition() const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition() const; int GetButtonState() const; int GetPOVPosition() const; --- include/wx/palmos/joystick.h.orig 2007-03-07 12:25:30.000000000 -0500 +++ include/wx/palmos/joystick.h 2007-03-07 12:27:00.000000000 -0500 @@ -32,6 +32,8 @@ class WXDLLIMPEXP_ADV wxJoystick: public //////////////////////////////////////////////////////////////////////////// wxPoint GetPosition(void) const; + int GetPosition(unsigned axis) const; + bool GetButtonState(unsigned button) const; int GetZPosition(void) const; int GetButtonState(void) const; int GetPOVPosition(void) const; --- src/mac/carbon/joystick.cpp.orig 2007-03-07 12:24:58.000000000 -0500 +++ src/mac/carbon/joystick.cpp 2007-03-07 12:28:29.000000000 -0500 @@ -32,6 +32,18 @@ wxPoint wxJoystick::GetPosition() const return wxPoint(0, 0); } +int wxJoystick::GetPosition(unsigned axis) const +{ + // TODO + return 0; +} + +bool wxJoystick::GetButtonState(unsigned id) const +{ + // TODO + return false; +} + int wxJoystick::GetZPosition() const { // TODO --- src/mac/classic/joystick.cpp.orig 2007-03-07 12:24:58.000000000 -0500 +++ src/mac/classic/joystick.cpp 2007-03-07 12:28:41.000000000 -0500 @@ -30,6 +30,18 @@ wxPoint wxJoystick::GetPosition() const return wxPoint(0, 0); } +int wxJoystick::GetPosition(unsigned axis) const +{ + // TODO + return 0; +} + +bool wxJoystick::GetButtonState(unsigned id) const +{ + // TODO + return false; +} + int wxJoystick::GetZPosition() const { // TODO --- src/msw/joystick.cpp.orig 2007-03-07 12:24:58.000000000 -0500 +++ src/msw/joystick.cpp 2007-03-07 12:39:44.000000000 -0500 @@ -87,6 +87,26 @@ wxPoint wxJoystick::GetPosition() const return wxPoint(0,0); } +int wxJoystick::GetPosition(unsigned axis) const +{ + switch (axis) { + case 0: + return GetPosition().x; + case 1: + return GetPosition().y; + case 2: + return GetZPosition(); + case 3: + return GetRudderPosition(); + case 4: + return GetUPosition(); + case 5: + return GetVPosition(); + default: + return 0; + } +} + int wxJoystick::GetZPosition() const { JOYINFO joyInfo; @@ -128,6 +148,14 @@ int wxJoystick::GetButtonState() const return 0; } +bool wxJoystick::GetButtonState(unsigned id) const +{ + if (id > sizeof(int) * 8) + return false; + + return (GetButtonState() & (1 << id)) != 0; +} + /** JLI 2002-08-20: Returns -1 to signify error. --- src/unix/joystick.cpp.orig 2007-03-07 01:21:56.000000000 -0500 +++ src/unix/joystick.cpp 2007-03-07 11:40:43.000000000 -0500 @@ -42,7 +42,9 @@ enum { wxJS_AXIS_V, wxJS_AXIS_MAX = 32767, - wxJS_AXIS_MIN = -32767 + wxJS_AXIS_MIN = -32767, + wxJS_MAX_AXES = 15, + wxJS_MAX_BUTTONS = sizeof(int) * 8 }; @@ -60,13 +62,15 @@ public: void* Entry(); private: + void SendEvent(wxEventType type, long ts, int change = 0); int m_device; int m_joystick; wxPoint m_lastposition; - int m_axe[15]; + int m_axe[wxJS_MAX_AXES]; int m_buttons; wxWindow* m_catchwin; int m_polling; + int m_threshold; friend class wxJoystick; }; @@ -78,12 +82,24 @@ wxJoystickThread::wxJoystickThread(int d m_lastposition(wxDefaultPosition), m_buttons(0), m_catchwin(NULL), - m_polling(0) + m_polling(0), + m_threshold(0) { - for (int i=0; i<15; i++) - m_axe[i] = 0; + memset(m_axe, 0, sizeof(m_axe)); } +void wxJoystickThread::SendEvent(wxEventType type, long ts, int change) +{ + wxJoystickEvent jwx_event(type, m_buttons, m_joystick, change); + + jwx_event.SetTimestamp(ts); + jwx_event.SetPosition(m_lastposition); + jwx_event.SetZPosition(m_axe[wxJS_AXIS_Z]); + jwx_event.SetEventObject(m_catchwin); + + if (m_catchwin) + m_catchwin->AddPendingEvent(jwx_event); +} void* wxJoystickThread::Entry() { @@ -114,9 +130,10 @@ void* wxJoystickThread::Entry() //printf("time: %d\t value: %d\t type: %d\t number: %d\n", // j_evt.time, j_evt.value, j_evt.type, j_evt.number); - wxJoystickEvent jwx_event; - - if (j_evt.type & JS_EVENT_AXIS) + if ((j_evt.type & JS_EVENT_AXIS) && (j_evt.number < wxJS_MAX_AXES)) + { + if ( (m_axe[j_evt.number] + m_threshold < j_evt.value) + || (m_axe[j_evt.number] - m_threshold > j_evt.value) ) { m_axe[j_evt.number] = j_evt.value; @@ -124,47 +141,36 @@ void* wxJoystickThread::Entry() { case wxJS_AXIS_X: m_lastposition.x = j_evt.value; - jwx_event.SetEventType(wxEVT_JOY_MOVE); + SendEvent(wxEVT_JOY_MOVE, j_evt.time); break; case wxJS_AXIS_Y: m_lastposition.y = j_evt.value; - jwx_event.SetEventType(wxEVT_JOY_MOVE); + SendEvent(wxEVT_JOY_MOVE, j_evt.time); break; case wxJS_AXIS_Z: - jwx_event.SetEventType(wxEVT_JOY_ZMOVE); + SendEvent(wxEVT_JOY_ZMOVE, j_evt.time); break; default: - jwx_event.SetEventType(wxEVT_JOY_MOVE); + SendEvent(wxEVT_JOY_MOVE, j_evt.time); // TODO: There should be a way to indicate that the event // is for some other axes. break; } } + } - if (j_evt.type & JS_EVENT_BUTTON) + if ( (j_evt.type & JS_EVENT_BUTTON) && (j_evt.number < wxJS_MAX_BUTTONS) ) { if (j_evt.value) { m_buttons |= (1 << j_evt.number); - jwx_event.SetEventType(wxEVT_JOY_BUTTON_DOWN); + SendEvent(wxEVT_JOY_BUTTON_DOWN, j_evt.time, j_evt.number); } else { m_buttons &= ~(1 << j_evt.number); - jwx_event.SetEventType(wxEVT_JOY_BUTTON_UP); + SendEvent(wxEVT_JOY_BUTTON_UP, j_evt.time, j_evt.number); } - - jwx_event.SetButtonChange(j_evt.number); - - jwx_event.SetTimestamp(j_evt.time); - jwx_event.SetJoystick(m_joystick); - jwx_event.SetButtonState(m_buttons); - jwx_event.SetPosition(m_lastposition); - jwx_event.SetZPosition(m_axe[3]); - jwx_event.SetEventObject(m_catchwin); - - if (m_catchwin) - m_catchwin->AddPendingEvent(jwx_event); } } } @@ -223,6 +229,13 @@ wxPoint wxJoystick::GetPosition() const return pos; } +int wxJoystick::GetPosition(unsigned axis) const +{ + if (m_thread && (axis < wxJS_MAX_AXES)) + return m_thread->m_axe[axis]; + return 0; +} + int wxJoystick::GetZPosition() const { if (m_thread) @@ -237,6 +250,13 @@ int wxJoystick::GetButtonState() const return 0; } +bool wxJoystick::GetButtonState(unsigned id) const +{ + if (m_thread && (id < wxJS_MAX_BUTTONS)) + return (m_thread->m_buttons & (1 << id)) != 0; + return false; +} + int wxJoystick::GetPOVPosition() const { return -1; @@ -270,11 +290,15 @@ int wxJoystick::GetVPosition() const int wxJoystick::GetMovementThreshold() const { + if (m_thread) + return m_thread->m_threshold; return 0; } void wxJoystick::SetMovementThreshold(int threshold) { + if (m_thread) + m_thread->m_threshold = threshold; } //////////////////////////////////////////////////////////////////////////// @@ -368,6 +392,9 @@ int wxJoystick::GetNumberButtons() const if (m_device != -1) ioctl(m_device, JSIOCGBUTTONS, &nb); + if (nb > wxJS_MAX_BUTTONS) + nb = wxJS_MAX_BUTTONS; + return nb; } @@ -378,17 +405,20 @@ int wxJoystick::GetNumberAxes() const if (m_device != -1) ioctl(m_device, JSIOCGAXES, &nb); + if (nb > wxJS_MAX_AXES) + nb = wxJS_MAX_AXES; + return nb; } int wxJoystick::GetMaxButtons() const { - return 15; // internal + return wxJS_MAX_BUTTONS; // internal } int wxJoystick::GetMaxAxes() const { - return 15; // internal + return wxJS_MAX_AXES; // internal } int wxJoystick::GetPollingMin() const --- src/palmos/joystick.cpp.orig 2007-03-07 12:24:58.000000000 -0500 +++ src/palmos/joystick.cpp 2007-03-07 12:28:52.000000000 -0500 @@ -38,6 +38,18 @@ wxPoint wxJoystick::GetPosition() const return wxPoint(0, 0); } +int wxJoystick::GetPosition(unsigned axis) const +{ + // TODO + return 0; +} + +bool wxJoystick::GetButtonState(unsigned id) const +{ + // TODO + return false; +} + int wxJoystick::GetZPosition() const { return 0;