1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/joystick.cpp
3 // Purpose: wxJoystick class
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 //===========================================================================
14 //===========================================================================
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 //---------------------------------------------------------------------------
25 //---------------------------------------------------------------------------
27 //we only support HID on OSX (DARWIN), since it requires DARWIN...
28 #if wxUSE_JOYSTICK && wxUSE_THREADS
30 //---------------------------------------------------------------------------
32 //---------------------------------------------------------------------------
36 #include "wx/event.h" //joystick wxEvents
37 #include "wx/window.h" //for wxWindow to "capture" joystick
40 #include "wx/joystick.h" //...
41 #include "wx/thread.h" //wxThread for polling thread/ wxCriticalSection
44 #include "wx/osx/core/hid.h" //private mac hid stuff
47 #include <CoreServices/CoreServices.h>
48 #include <mach/mach.h>
49 #include <mach/mach_time.h>
52 //---------------------------------------------------------------------------
53 // Definitions/Enumerations
54 //---------------------------------------------------------------------------
56 #define wxJS_MAX_AXES 10 /*max number of axes*/
57 #define wxJS_MAX_BUTTONS 40 /*max number of buttons*/
61 //These are positions within the cookie array
62 //in wxHIDJoystick that the cookies that store the axis' are
71 //---------------------------------------------------------------------------
73 //---------------------------------------------------------------------------
74 class wxHIDJoystick
: public wxHIDDevice
78 virtual ~wxHIDJoystick();
80 bool Create(int nWhich
);
81 virtual void BuildCookies(CFArrayRef Array
);
82 void MakeCookies(CFArrayRef Array
);
83 IOHIDElementCookie
* GetCookies();
84 IOHIDQueueInterface
** GetQueue();
86 int m_nXMax
, m_nYMax
, m_nZMax
, m_nRudderMax
, m_nUMax
, m_nVMax
,
87 m_nXMin
, m_nYMin
, m_nZMin
, m_nRudderMin
, m_nUMin
, m_nVMin
;
89 friend class wxJoystick
;
92 //---------------------------------------------------------------------------
94 //---------------------------------------------------------------------------
95 class wxJoystickThread
: public wxThread
98 wxJoystickThread(wxHIDJoystick
* hid
, int joystick
);
100 static void HIDCallback(void* target
, IOReturn res
, void* context
, void* sender
);
103 wxHIDJoystick
* m_hid
;
105 wxPoint m_lastposition
;
106 int m_axe
[wxJS_MAX_AXES
];
108 wxWindow
* m_catchwin
;
111 friend class wxJoystick
;
114 //===========================================================================
116 //===========================================================================
118 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 // wxGetIntFromCFDictionary
121 // Helper function that gets a integer from a dictionary key
122 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 void wxGetIntFromCFDictionary(CFTypeRef cfDict
, CFStringRef key
, int* pOut
)
126 (CFNumberRef
) CFDictionaryGetValue((CFDictionaryRef
) cfDict
,
128 kCFNumberIntType
, pOut
);
131 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
135 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
137 IMPLEMENT_DYNAMIC_CLASS(wxJoystick
, wxObject
)
139 //---------------------------------------------------------------------------
140 // wxJoystick Constructor
142 // 1) Initializes member variables
143 // 2) Attempts to create the native HID joystick implementation - if none
144 // could be found (no joysticks, etc.) then it sets it to NULL
145 //---------------------------------------------------------------------------
146 wxJoystick::wxJoystick(int joystick
)
147 : m_joystick(joystick
),
150 m_hid
= new wxHIDJoystick();
152 if (m_hid
->Create(m_joystick
+1)) //wxHIDDevice is 1-based while this is 0
154 m_thread
= new wxJoystickThread(m_hid
, m_joystick
);
164 //---------------------------------------------------------------------------
165 // wxJoystick Destructor
167 // Releases the capture of the thread, deletes it, and deletes
168 // the native implementation.
169 //---------------------------------------------------------------------------
170 wxJoystick::~wxJoystick()
174 m_thread
->Delete(); // It's detached so it will delete itself
179 //---------------------------------------------------------------------------
180 // wxJoystick::Get[XXX]Position
182 // Returns the value of an axis that was polled from the thread. In the
183 // case of GetPosition returns the X and Y values in a wxPoint
184 //---------------------------------------------------------------------------
185 wxPoint
wxJoystick::GetPosition() const
187 wxPoint
pos(wxDefaultPosition
);
188 if (m_thread
) pos
= m_thread
->m_lastposition
;
191 int wxJoystick::GetZPosition() const
194 return m_thread
->m_axe
[wxJS_AXIS_Z
-wxJS_AXIS_X
];
197 int wxJoystick::GetRudderPosition() const
200 return m_thread
->m_axe
[wxJS_AXIS_RUDDER
-wxJS_AXIS_X
];
203 int wxJoystick::GetUPosition() const
206 return m_thread
->m_axe
[wxJS_AXIS_U
-wxJS_AXIS_X
];
209 int wxJoystick::GetVPosition() const
212 return m_thread
->m_axe
[wxJS_AXIS_V
-wxJS_AXIS_X
];
216 //---------------------------------------------------------------------------
217 // wxJoystick::GetButtonState
219 // Returns the state of the buttons in a bitmask as dictated by the
220 // wx manual (the real work takes place in the thread, as always)
221 //---------------------------------------------------------------------------
222 int wxJoystick::GetButtonState() const
225 return m_thread
->m_buttons
;
229 //---------------------------------------------------------------------------
232 // Returns whether the joystick initialized successfully - in this case
233 // if the native implementation doesn't exist (in constructor)
234 //---------------------------------------------------------------------------
235 bool wxJoystick::IsOk() const
237 return m_hid
!= NULL
;
240 //---------------------------------------------------------------------------
241 // wxJoystick::Get[XXX](Id/Name)
243 // Simple accessors to the native HID implementation
244 //---------------------------------------------------------------------------
245 int wxJoystick::GetManufacturerId() const
247 return m_hid
->m_nManufacturerId
;
250 int wxJoystick::GetProductId() const
252 return m_hid
->m_nProductId
;
255 wxString
wxJoystick::GetProductName() const
257 return m_hid
->m_szProductName
;
260 //---------------------------------------------------------------------------
261 // wxJoystick::GetNumberButtons
262 // wxJoystick::GetNumberAxes
264 // Queries the joystick for an active number of buttons/axes.
266 // In the native HID implementation, the cookies:
267 // 0-40 are the buttons of the joystick
268 // 40-50 are the axes of the joystick
270 // These just query the native HID implementation as above.
271 //---------------------------------------------------------------------------
272 int wxJoystick::GetNumberButtons() const
276 for(int nIndex
= 0; nIndex
< 40; ++nIndex
)
278 if(m_hid
->HasElement(nIndex
))
284 int wxJoystick::GetNumberAxes() const
288 for(int nIndex
= 40; nIndex
< 50; ++nIndex
)
290 if(m_hid
->HasElement(nIndex
))
297 //---------------------------------------------------------------------------
298 // wxJoystick::GetNumberJoysticks
300 // Gets the number of joysticks on the system. In HID that
301 // is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
303 //---------------------------------------------------------------------------
304 int wxJoystick::GetNumberJoysticks()
307 wxHIDDevice::GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_Joystick
) +
308 wxHIDDevice::GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_GamePad
);
311 //---------------------------------------------------------------------------
312 // wxJoystick::SetCapture
314 // Stops sending events from the thread to the window set in
315 // SetCapture and stops polling the joystick
316 //---------------------------------------------------------------------------
317 bool wxJoystick::SetCapture(wxWindow
* win
, int pollingFreq
)
321 m_thread
->m_catchwin
= win
;
322 m_thread
->m_polling
= pollingFreq
;
328 //---------------------------------------------------------------------------
329 // wxJoystick::ReleaseCapture
331 // Stops sending events from the thread to the window set in
332 // SetCapture and stops polling the joystick
333 //---------------------------------------------------------------------------
334 bool wxJoystick::ReleaseCapture()
338 m_thread
->m_catchwin
= NULL
;
339 m_thread
->m_polling
= 0;
345 //---------------------------------------------------------------------------
346 // wxJoystick::Get[XXX]
348 // Gets the minimum and maximum values for each axis, returning 0 if the
349 // axis doesn't exist.
350 //---------------------------------------------------------------------------
351 int wxJoystick::GetXMin() const
353 return m_hid
->m_nXMin
;
356 int wxJoystick::GetYMin() const
358 return m_hid
->m_nYMin
;
361 int wxJoystick::GetZMin() const
363 return m_hid
->m_nZMin
;
366 int wxJoystick::GetRudderMin() const
368 return m_hid
->m_nRudderMin
;
371 int wxJoystick::GetUMin() const
373 return m_hid
->m_nUMin
;
376 int wxJoystick::GetVMin() const
378 return m_hid
->m_nVMin
;
381 int wxJoystick::GetXMax() const
383 return m_hid
->m_nXMax
;
386 int wxJoystick::GetYMax() const
388 return m_hid
->m_nYMax
;
391 int wxJoystick::GetZMax() const
393 return m_hid
->m_nZMax
;
396 int wxJoystick::GetRudderMax() const
398 return m_hid
->m_nRudderMax
;
401 int wxJoystick::GetUMax() const
403 return m_hid
->m_nUMax
;
406 int wxJoystick::GetVMax() const
408 return m_hid
->m_nVMax
;
411 //---------------------------------------------------------------------------
412 // wxJoystick::Get[XXX]
414 // Min/Max values for buttons, axes, etc.. Polling in this case is just
415 // what the linux port has.
416 //---------------------------------------------------------------------------
417 int wxJoystick::GetMaxButtons() const
419 return wxJS_MAX_BUTTONS
;
422 int wxJoystick::GetMaxAxes() const
424 return wxJS_MAX_AXES
;
427 int wxJoystick::GetPollingMin() const
432 int wxJoystick::GetPollingMax() const
437 //---------------------------------------------------------------------------
438 // wxJoystick::Has[XXX]
440 // Just queries the native hid implementation if the cookie was found
441 // when enumerating the cookies of the joystick device
442 //---------------------------------------------------------------------------
443 bool wxJoystick::HasZ() const
445 return m_hid
->HasElement(wxJS_AXIS_Z
);
448 bool wxJoystick::HasRudder() const
450 return m_hid
->HasElement(wxJS_AXIS_RUDDER
);
453 bool wxJoystick::HasU() const
455 return m_hid
->HasElement(wxJS_AXIS_U
);
458 bool wxJoystick::HasV() const
460 return m_hid
->HasElement(wxJS_AXIS_V
);
463 //---------------------------------------------------------------------------
465 //---------------------------------------------------------------------------
466 int wxJoystick::GetPOVPosition() const
471 int wxJoystick::GetPOVCTSPosition() const
476 int wxJoystick::GetMovementThreshold() const
481 void wxJoystick::SetMovementThreshold(int WXUNUSED(threshold
))
485 bool wxJoystick::HasPOV() const
490 bool wxJoystick::HasPOV4Dir() const
495 bool wxJoystick::HasPOVCTS() const
500 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
504 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
506 //---------------------------------------------------------------------------
507 // wxHIDJoystick ctor
509 // Initializes the min/max members
510 //---------------------------------------------------------------------------
511 wxHIDJoystick::wxHIDJoystick() :
512 m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0),
513 m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0)
517 //---------------------------------------------------------------------------
518 // wxHIDJoystick dtor
521 //---------------------------------------------------------------------------
522 wxHIDJoystick::~wxHIDJoystick()
526 //---------------------------------------------------------------------------
527 // wxHIDJoystick::Create
529 // Creates the native HID device (joysticks are of either
530 // kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
531 //---------------------------------------------------------------------------
532 bool wxHIDJoystick::Create(int nWhich
)
534 int nJoysticks
= GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_Joystick
);
536 if (nWhich
<= nJoysticks
)
537 return wxHIDDevice::Create(kHIDPage_GenericDesktop
,
538 kHIDUsage_GD_Joystick
,
541 nWhich
-= nJoysticks
;
543 int nGamePads
= GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_GamePad
);
545 if (nWhich
<= nGamePads
)
546 return wxHIDDevice::Create(kHIDPage_GenericDesktop
,
547 kHIDUsage_GD_GamePad
,
553 //---------------------------------------------------------------------------
554 // wxHIDJoystick::BuildCookies
555 // wxHIDJoystick::MakeCookies
557 // Sets up the cookies for the HID device (called from Create) - as
558 // mentioned 0-40 are the buttons and 40-50 are the axes.
560 // MakeCookies is just a recursive function for each array within
562 //---------------------------------------------------------------------------
563 void wxHIDJoystick::BuildCookies(CFArrayRef Array
)
565 InitCookies(50, true);
568 // I wasted two hours of my life on this line :(
569 // accidently removed it during some source cleaning...
573 //paranoid debugging stuff
575 for(int i
= 0; i
< 50; ++i
)
576 wxPrintf(wxT("\nVAL #%i:[%i]"), i
, m_pCookies
[i
]);
580 void wxHIDJoystick::MakeCookies(CFArrayRef Array
)
582 int i
, nUsage
, nPage
;
584 for (i
= 0; i
< CFArrayGetCount(Array
); ++i
)
586 const void* ref
= CFDictionaryGetValue(
587 (CFDictionaryRef
)CFArrayGetValueAtIndex(Array
, i
),
588 CFSTR(kIOHIDElementKey
)
593 MakeCookies((CFArrayRef
) ref
);
599 CFDictionaryGetValue(
600 (CFDictionaryRef
) CFArrayGetValueAtIndex(Array
, i
),
601 CFSTR(kIOHIDElementUsageKey
)
608 CFDictionaryGetValue(
609 (CFDictionaryRef
) CFArrayGetValueAtIndex(Array
, i
),
610 CFSTR(kIOHIDElementUsagePageKey
)
616 wxLogSysError(wxT("[%i][%i]"), nUsage
, nPage
);
618 if (nPage
== kHIDPage_Button
&& nUsage
<= 40)
619 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), nUsage
-1 );
620 else if (nPage
== kHIDPage_GenericDesktop
)
626 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_X
);
627 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
628 CFSTR(kIOHIDElementMaxKey
),
630 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
631 CFSTR(kIOHIDElementMinKey
),
635 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_Y
);
636 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
637 CFSTR(kIOHIDElementMaxKey
),
639 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
640 CFSTR(kIOHIDElementMinKey
),
644 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_Z
);
645 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
646 CFSTR(kIOHIDElementMaxKey
),
648 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
649 CFSTR(kIOHIDElementMinKey
),
656 else if (nPage
== kHIDPage_Simulation
&& nUsage
== kHIDUsage_Sim_Rudder
)
659 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_RUDDER
);
660 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
661 CFSTR(kIOHIDElementMaxKey
),
663 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
664 CFSTR(kIOHIDElementMinKey
),
671 //---------------------------------------------------------------------------
672 // wxHIDJoystick::Get[XXX]
674 // Simple accessors so that the HID callback and the thread procedure
675 // can access members from wxHIDDevice (our parent here).
676 //---------------------------------------------------------------------------
677 IOHIDElementCookie
* wxHIDJoystick::GetCookies()
678 { return m_pCookies
; }
679 IOHIDQueueInterface
** wxHIDJoystick::GetQueue()
680 { return m_ppQueue
; }
682 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
686 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
688 //---------------------------------------------------------------------------
689 // wxJoystickThread Constructor
691 // Just initializes members
692 //---------------------------------------------------------------------------
693 wxJoystickThread::wxJoystickThread(wxHIDJoystick
* hid
, int joystick
)
695 m_joystick(joystick
),
696 m_lastposition(127,127),
701 memset(m_axe
, 0, sizeof(int) * wxJS_MAX_AXES
);
704 //---------------------------------------------------------------------------
705 // wxJoystickThread::Entry
709 // Runs a CFRunLoop for polling. Basically, it sets the HID queue to
710 // call wxJoystickThread::HIDCallback in the context of this thread
711 // when something changes on the device. It polls as long as the user
712 // wants, or a certain amount if the user wants to "block". Note that
713 // we don't actually block here since this is in a secondary thread.
714 //---------------------------------------------------------------------------
715 void* wxJoystickThread::Entry()
717 CFRunLoopSourceRef pRLSource
= NULL
;
719 if ((*m_hid
->GetQueue())->createAsyncEventSource(
720 m_hid
->GetQueue(), &pRLSource
) != kIOReturnSuccess
)
722 wxLogSysError(wxT("Couldn't create async event source"));
726 wxASSERT(pRLSource
!= NULL
);
728 //attach runloop source to main run loop in thread
729 CFRunLoopRef pRL
= CFRunLoopGetCurrent();
730 CFRunLoopAddSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
);
731 wxASSERT( CFRunLoopContainsSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
) );
734 if( (*m_hid
->GetQueue())->setEventCallout(m_hid
->GetQueue(),
735 wxJoystickThread::HIDCallback
, this, this) != kIOReturnSuccess
)
737 wxLogSysError(wxT("Could not set event callout for queue"));
741 if( (*m_hid
->GetQueue())->start(m_hid
->GetQueue()) != kIOReturnSuccess
)
743 wxLogSysError(wxT("Could not start queue"));
755 dTime
= 0.0001 * m_polling
;
757 dTime
= 0.0001 * 10; // check at least every 10 msec in "blocking" case
759 //true just "handles and returns" - false forces it to stay the time
762 CFRunLoopRunInMode(kCFRunLoopDefaultMode
, dTime
, true);
765 HIDCallback(this, ret
, this, this);
770 wxASSERT( CFRunLoopContainsSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
) );
772 CFRunLoopRemoveSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
);
773 CFRelease(pRLSource
);
778 //---------------------------------------------------------------------------
779 // wxJoystickThread::HIDCallback (static)
781 // Callback for the native HID device when it receives input.
783 // This is where the REAL dirty work gets done.
785 // 1) Loops through each event the queue has received
786 // 2) First, checks if the thread that is running the loop for
787 // the polling has ended - if so it breaks out
788 // 3) Next, it checks if there was an error getting this event from
789 // the HID queue, if there was, it logs an error and returns
790 // 4) Now it does the real dirty work by getting the button states
791 // from cookies 0-40 and axes positions/states from cookies 40-50
792 // in the native HID device by quering cookie values.
793 // 5) Sends the event to the polling window (if any)
794 // 6) Gets the next event and goes back to (1)
795 //---------------------------------------------------------------------------
796 /*static*/ void wxJoystickThread::HIDCallback(void* WXUNUSED(target
),
797 IOReturn
WXUNUSED(res
),
799 void* WXUNUSED(sender
))
801 IOHIDEventStruct hidevent
;
802 AbsoluteTime bogustime
= {0,0};
804 wxJoystickThread
* pThis
= (wxJoystickThread
*) context
;
805 wxHIDJoystick
* m_hid
= pThis
->m_hid
;
807 //Get the "first" event from the queue
808 //bogustime tells it we don't care at what time to start
809 //where it gets the next from
810 ret
= (*m_hid
->GetQueue())->getNextEvent(m_hid
->GetQueue(),
811 &hidevent
, bogustime
, 0);
813 while (ret
!= kIOReturnUnderrun
)
815 if (pThis
->TestDestroy())
818 if(ret
!= kIOReturnSuccess
)
820 wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret
));
824 wxJoystickEvent wxevent
;
826 //Find the cookie that changed
828 IOHIDElementCookie
* pCookies
= m_hid
->GetCookies();
831 if(hidevent
.elementCookie
== pCookies
[nIndex
])
841 wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
846 //is the cookie a button?
851 pThis
->m_buttons
|= (1 << nIndex
);
852 wxevent
.SetEventType(wxEVT_JOY_BUTTON_DOWN
);
856 pThis
->m_buttons
&= ~(1 << nIndex
);
857 wxevent
.SetEventType(wxEVT_JOY_BUTTON_UP
);
860 wxevent
.SetButtonChange(nIndex
+1);
862 else if (nIndex
== wxJS_AXIS_X
)
864 pThis
->m_lastposition
.x
= hidevent
.value
;
865 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
866 pThis
->m_axe
[0] = hidevent
.value
;
868 else if (nIndex
== wxJS_AXIS_Y
)
870 pThis
->m_lastposition
.y
= hidevent
.value
;
871 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
872 pThis
->m_axe
[1] = hidevent
.value
;
874 else if (nIndex
== wxJS_AXIS_Z
)
876 wxevent
.SetEventType(wxEVT_JOY_ZMOVE
);
877 pThis
->m_axe
[2] = hidevent
.value
;
880 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
882 Nanoseconds timestamp
= AbsoluteToNanoseconds(hidevent
.timestamp
);
884 wxULongLong
llTime(timestamp
.hi
, timestamp
.lo
);
888 wxevent
.SetTimestamp(llTime
.GetValue());
889 wxevent
.SetJoystick(pThis
->m_joystick
);
890 wxevent
.SetButtonState(pThis
->m_buttons
);
891 wxevent
.SetPosition(pThis
->m_lastposition
);
892 wxevent
.SetZPosition(pThis
->m_axe
[2]);
893 wxevent
.SetEventObject(pThis
->m_catchwin
);
895 if (pThis
->m_catchwin
)
896 pThis
->m_catchwin
->GetEventHandler()->AddPendingEvent(wxevent
);
898 ret
= (*m_hid
->GetQueue())->getNextEvent(m_hid
->GetQueue(),
899 &hidevent
, bogustime
, 0);
903 #endif // wxUSE_JOYSTICK