From e6733873f5bc5de9ef538533da786250de9dd9c7 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Fri, 16 Mar 2007 00:51:43 +0000
Subject: [PATCH] multiple fixes to wxJoystick under Unix and new index-based
 API for accessing joystick buttons and axes (patch 1678497)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44843 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt                         |  1 +
 docs/latex/wx/joystick.tex               | 16 +++++
 include/wx/mac/carbon/joystick.h         |  2 +
 include/wx/mac/corefoundation/joystick.h |  2 +
 include/wx/msw/joystick.h                |  2 +
 include/wx/palmos/joystick.h             |  2 +
 include/wx/unix/joystick.h               |  2 +
 src/mac/carbon/joystick.cpp              | 12 ++++
 src/msw/joystick.cpp                     | 28 ++++++++
 src/palmos/joystick.cpp                  | 12 ++++
 src/unix/joystick.cpp                    | 88 ++++++++++++++++--------
 11 files changed, 138 insertions(+), 29 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index 7e644bdaca..5546f5cc0e 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -39,6 +39,7 @@ All:
 - Fixed crashes in helpview when opening a file.
 - Added wxMutex::LockTimeout() (Aleksandr Napylov)
 - Set locale to the default in all ports, not just wxGTK
+- Added wxJoystick::GetButtonState/Position() (Frank C Szczerba)
 - Added wxGridUpdateLocker helper class (Evgeniy Tarassov)
 - Support wxGRID_AUTOSIZE in wxGrid::SetRow/ColLabelSize() (Evgeniy Tarassov)
 
diff --git a/docs/latex/wx/joystick.tex b/docs/latex/wx/joystick.tex
index 155b2f05fb..1f934e6993 100644
--- a/docs/latex/wx/joystick.tex
+++ b/docs/latex/wx/joystick.tex
@@ -39,6 +39,14 @@ significant bit, and so on.
 A bitlist of wxJOY\_BUTTONn identifiers, where n is 1, 2, 3 or 4 
 is available for historical reasons.
 
+\constfunc{bool}{GetButtonState}{\param{unsigned}{ id}}
+
+Returns the state of the specified joystick button.
+
+\wxheading{Parameters}
+
+\docparam{id}{The button id to report, from 0 to \helpref{GetNumberButtons()}{wxjoystickgetnumberbuttons} - 1}
+
 \membersection{wxJoystick::GetManufacturerId}\label{wxjoystickgetmanufacturerid}
 
 \constfunc{int}{GetManufacturerId}{\void}
@@ -100,6 +108,14 @@ Returns the product name for the joystick.
 
 Returns the x, y position of the joystick.
 
+\constfunc{int}{GetPosition}{\param{unsigned}{ axis}}
+
+Returns the position of the specified joystick axis.
+
+\wxheading{Parameters}
+
+\docparam{axis}{The joystick axis to report, from 0 to \helpref{GetNumberAxes()}{wxjoystickgetnumberaxes} - 1.}
+
 \membersection{wxJoystick::GetPOVPosition}\label{wxjoystickgetpovposition}
 
 \constfunc{int}{GetPOVPosition}{\void}
diff --git a/include/wx/mac/carbon/joystick.h b/include/wx/mac/carbon/joystick.h
index dce79f8a37..2aabceb8c3 100644
--- a/include/wx/mac/carbon/joystick.h
+++ b/include/wx/mac/carbon/joystick.h
@@ -28,6 +28,8 @@ class WXDLLEXPORT wxJoystick: public wxObject
   ////////////////////////////////////////////////////////////////////////////
 
   wxPoint GetPosition() const;
+  int GetPosition(unsigned axis) const;
+  bool GetButtonState(unsigned button) const;
   int GetZPosition() const;
   int GetButtonState() const;
   int GetPOVPosition() const;
diff --git a/include/wx/mac/corefoundation/joystick.h b/include/wx/mac/corefoundation/joystick.h
index 13024b2731..99f23c37f9 100644
--- a/include/wx/mac/corefoundation/joystick.h
+++ b/include/wx/mac/corefoundation/joystick.h
@@ -28,6 +28,8 @@ class WXDLLEXPORT wxJoystick: public wxObject
     ////////////////////////////////////////////////////////////////////////////
 
     wxPoint GetPosition() const;
+    int GetPosition(unsigned axis) const;
+    bool GetButtonState(unsigned button) const;
     int GetZPosition() const;
     int GetButtonState() const;
     int GetPOVPosition() const;
diff --git a/include/wx/msw/joystick.h b/include/wx/msw/joystick.h
index db039ee2ff..7a655137a9 100644
--- a/include/wx/msw/joystick.h
+++ b/include/wx/msw/joystick.h
@@ -28,6 +28,8 @@ class WXDLLIMPEXP_ADV wxJoystick: public wxObject
   ////////////////////////////////////////////////////////////////////////////
 
   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;
diff --git a/include/wx/palmos/joystick.h b/include/wx/palmos/joystick.h
index 57fcc7db23..d5f425761d 100644
--- a/include/wx/palmos/joystick.h
+++ b/include/wx/palmos/joystick.h
@@ -28,6 +28,8 @@ class WXDLLIMPEXP_ADV wxJoystick: public wxObject
   ////////////////////////////////////////////////////////////////////////////
 
   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;
diff --git a/include/wx/unix/joystick.h b/include/wx/unix/joystick.h
index 4ff41f134e..5145446311 100644
--- a/include/wx/unix/joystick.h
+++ b/include/wx/unix/joystick.h
@@ -32,6 +32,8 @@ class WXDLLEXPORT wxJoystick: public wxObject
     ////////////////////////////////////////////////////////////////////////////
 
     wxPoint GetPosition() const;
+    int GetPosition(unsigned axis) const;
+    bool GetButtonState(unsigned button) const;
     int GetZPosition() const;
     int GetButtonState() const;
     int GetPOVPosition() const;
diff --git a/src/mac/carbon/joystick.cpp b/src/mac/carbon/joystick.cpp
index c56cf2001a..3f1a5a9f5e 100644
--- a/src/mac/carbon/joystick.cpp
+++ b/src/mac/carbon/joystick.cpp
@@ -28,6 +28,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
diff --git a/src/msw/joystick.cpp b/src/msw/joystick.cpp
index 78e023fd73..1b9f8b04ce 100644
--- a/src/msw/joystick.cpp
+++ b/src/msw/joystick.cpp
@@ -86,6 +86,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;
@@ -127,6 +147,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.
diff --git a/src/palmos/joystick.cpp b/src/palmos/joystick.cpp
index 01a44cd3e3..528e6dc408 100644
--- a/src/palmos/joystick.cpp
+++ b/src/palmos/joystick.cpp
@@ -35,6 +35,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;
diff --git a/src/unix/joystick.cpp b/src/unix/joystick.cpp
index 64afa78cb9..f5ad718346 100644
--- a/src/unix/joystick.cpp
+++ b/src/unix/joystick.cpp
@@ -44,7 +44,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
 };
 
 
@@ -62,13 +64,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;
 };
@@ -80,12 +84,24 @@ wxJoystickThread::wxJoystickThread(int device, int joystick)
       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()
 {
@@ -116,9 +132,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;
 
@@ -126,47 +143,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);
             }
         }
     }
@@ -225,6 +231,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)
@@ -239,6 +252,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;
@@ -272,11 +292,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;
 }
 
 ////////////////////////////////////////////////////////////////////////////
@@ -370,6 +394,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;
 }
 
@@ -380,17 +407,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
-- 
2.50.0

