-void *wxJoystick::Entry(void)
-{
- struct js_event j_evt;
- wxJoystickEvent jwx_event;
- fd_set read_fds;
- struct timeval time_out = {0, 0};
-
- FD_ZERO(&read_fds);
- while (1) {
- TestDestroy();
-
- if (m_polling) {
- FD_SET(m_joystick, &read_fds);
- select(m_joystick+1, &read_fds, NULL, NULL, &time_out);
- if (FD_ISSET(m_joystick, &read_fds))
- read(m_joystick, &j_evt, sizeof(j_evt));
- else
- j_evt.type = 0;
- } else {
- read(m_joystick, &j_evt, sizeof(j_evt));
+
+class wxJoystickThread : public wxThread
+{
+public:
+ wxJoystickThread(int device, int joystick);
+ void* Entry();
+
+private:
+ void SendEvent(wxEventType type, long ts, int change = 0);
+ int m_device;
+ int m_joystick;
+ wxPoint m_lastposition;
+ int m_axe[wxJS_MAX_AXES];
+ int m_buttons;
+ wxWindow* m_catchwin;
+ int m_polling;
+ int m_threshold;
+
+ friend class wxJoystick;
+};
+
+
+wxJoystickThread::wxJoystickThread(int device, int joystick)
+ : m_device(device),
+ m_joystick(joystick),
+ m_lastposition(wxDefaultPosition),
+ m_buttons(0),
+ m_catchwin(NULL),
+ m_polling(0),
+ m_threshold(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()
+{
+ struct js_event j_evt;
+ fd_set read_fds;
+ struct timeval time_out = {0, 0};
+
+ wxFD_ZERO(&read_fds);
+ while (true)
+ {
+ if (TestDestroy())
+ break;
+
+ // We use select when either polling or 'blocking' as even in the
+ // blocking case we need to check TestDestroy periodically
+ if (m_polling)
+ time_out.tv_usec = m_polling * 1000;
+ else
+ time_out.tv_usec = 10 * 1000; // check at least every 10 msec in blocking case
+
+ wxFD_SET(m_device, &read_fds);
+ select(m_device+1, &read_fds, NULL, NULL, &time_out);
+ if (wxFD_ISSET(m_device, &read_fds))
+ {
+ memset(&j_evt, 0, sizeof(j_evt));
+ read(m_device, &j_evt, sizeof(j_evt));
+
+ //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);
+
+ 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;
+
+ switch (j_evt.number)
+ {
+ case wxJS_AXIS_X:
+ m_lastposition.x = j_evt.value;
+ SendEvent(wxEVT_JOY_MOVE, j_evt.time);
+ break;
+ case wxJS_AXIS_Y:
+ m_lastposition.y = j_evt.value;
+ SendEvent(wxEVT_JOY_MOVE, j_evt.time);
+ break;
+ case wxJS_AXIS_Z:
+ SendEvent(wxEVT_JOY_ZMOVE, j_evt.time);
+ break;
+ default:
+ 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) && (j_evt.number < wxJS_MAX_BUTTONS) )
+ {
+ if (j_evt.value)
+ {
+ m_buttons |= (1 << j_evt.number);
+ SendEvent(wxEVT_JOY_BUTTON_DOWN, j_evt.time, j_evt.number);
+ }
+ else
+ {
+ m_buttons &= ~(1 << j_evt.number);
+ SendEvent(wxEVT_JOY_BUTTON_UP, j_evt.time, j_evt.number);
+ }
+ }
+ }