1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/joystick.cpp
3 // Purpose: wxJoystick class
7 // Copyright: (c) Ryan Norton
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 //===========================================================================
13 //===========================================================================
15 //---------------------------------------------------------------------------
16 // Pre-compiled header stuff
17 //---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 //---------------------------------------------------------------------------
24 //---------------------------------------------------------------------------
26 //we only support HID on OSX (DARWIN), since it requires DARWIN...
27 #if wxUSE_JOYSTICK && wxUSE_THREADS
29 //---------------------------------------------------------------------------
31 //---------------------------------------------------------------------------
35 #include "wx/event.h" //joystick wxEvents
36 #include "wx/window.h" //for wxWindow to "capture" joystick
39 #include "wx/joystick.h" //...
40 #include "wx/thread.h" //wxThread for polling thread/ wxCriticalSection
43 #include "wx/osx/core/hid.h" //private mac hid stuff
46 #include <CoreServices/CoreServices.h>
47 #include <mach/mach.h>
48 #include <mach/mach_time.h>
51 //---------------------------------------------------------------------------
52 // Definitions/Enumerations
53 //---------------------------------------------------------------------------
55 #define wxJS_MAX_AXES 10 /*max number of axes*/
56 #define wxJS_MAX_BUTTONS 40 /*max number of buttons*/
60 //These are positions within the cookie array
61 //in wxHIDJoystick that the cookies that store the axis' are
70 //---------------------------------------------------------------------------
72 //---------------------------------------------------------------------------
73 class wxHIDJoystick
: public wxHIDDevice
77 virtual ~wxHIDJoystick();
79 bool Create(int nWhich
);
80 virtual void BuildCookies(CFArrayRef Array
);
81 void MakeCookies(CFArrayRef Array
);
82 IOHIDElementCookie
* GetCookies();
83 IOHIDQueueInterface
** GetQueue();
85 int m_nXMax
, m_nYMax
, m_nZMax
, m_nRudderMax
, m_nUMax
, m_nVMax
,
86 m_nXMin
, m_nYMin
, m_nZMin
, m_nRudderMin
, m_nUMin
, m_nVMin
;
88 friend class wxJoystick
;
91 //---------------------------------------------------------------------------
93 //---------------------------------------------------------------------------
94 class wxJoystickThread
: public wxThread
97 wxJoystickThread(wxHIDJoystick
* hid
, int joystick
);
99 static void HIDCallback(void* target
, IOReturn res
, void* context
, void* sender
);
102 wxHIDJoystick
* m_hid
;
104 wxPoint m_lastposition
;
105 int m_axe
[wxJS_MAX_AXES
];
107 wxWindow
* m_catchwin
;
110 friend class wxJoystick
;
113 //===========================================================================
115 //===========================================================================
117 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 // wxGetIntFromCFDictionary
120 // Helper function that gets a integer from a dictionary key
121 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 void wxGetIntFromCFDictionary(CFTypeRef cfDict
, CFStringRef key
, int* pOut
)
125 (CFNumberRef
) CFDictionaryGetValue((CFDictionaryRef
) cfDict
,
127 kCFNumberIntType
, pOut
);
130 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
134 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
136 IMPLEMENT_DYNAMIC_CLASS(wxJoystick
, wxObject
)
138 //---------------------------------------------------------------------------
139 // wxJoystick Constructor
141 // 1) Initializes member variables
142 // 2) Attempts to create the native HID joystick implementation - if none
143 // could be found (no joysticks, etc.) then it sets it to NULL
144 //---------------------------------------------------------------------------
145 wxJoystick::wxJoystick(int joystick
)
146 : m_joystick(joystick
),
149 m_hid
= new wxHIDJoystick();
151 if (m_hid
->Create(m_joystick
+1)) //wxHIDDevice is 1-based while this is 0
153 m_thread
= new wxJoystickThread(m_hid
, m_joystick
);
163 //---------------------------------------------------------------------------
164 // wxJoystick Destructor
166 // Releases the capture of the thread, deletes it, and deletes
167 // the native implementation.
168 //---------------------------------------------------------------------------
169 wxJoystick::~wxJoystick()
173 m_thread
->Delete(); // It's detached so it will delete itself
178 //---------------------------------------------------------------------------
179 // wxJoystick::Get[XXX]Position
181 // Returns the value of an axis that was polled from the thread. In the
182 // case of GetPosition returns the X and Y values in a wxPoint
183 //---------------------------------------------------------------------------
184 wxPoint
wxJoystick::GetPosition() const
186 wxPoint
pos(wxDefaultPosition
);
187 if (m_thread
) pos
= m_thread
->m_lastposition
;
190 int wxJoystick::GetZPosition() const
193 return m_thread
->m_axe
[wxJS_AXIS_Z
-wxJS_AXIS_X
];
196 int wxJoystick::GetRudderPosition() const
199 return m_thread
->m_axe
[wxJS_AXIS_RUDDER
-wxJS_AXIS_X
];
202 int wxJoystick::GetUPosition() const
205 return m_thread
->m_axe
[wxJS_AXIS_U
-wxJS_AXIS_X
];
208 int wxJoystick::GetVPosition() const
211 return m_thread
->m_axe
[wxJS_AXIS_V
-wxJS_AXIS_X
];
215 //---------------------------------------------------------------------------
216 // wxJoystick::GetButtonState
218 // Returns the state of the buttons in a bitmask as dictated by the
219 // wx manual (the real work takes place in the thread, as always)
220 //---------------------------------------------------------------------------
221 int wxJoystick::GetButtonState() const
224 return m_thread
->m_buttons
;
228 //---------------------------------------------------------------------------
231 // Returns whether the joystick initialized successfully - in this case
232 // if the native implementation doesn't exist (in constructor)
233 //---------------------------------------------------------------------------
234 bool wxJoystick::IsOk() const
236 return m_hid
!= NULL
;
239 //---------------------------------------------------------------------------
240 // wxJoystick::Get[XXX](Id/Name)
242 // Simple accessors to the native HID implementation
243 //---------------------------------------------------------------------------
244 int wxJoystick::GetManufacturerId() const
246 return m_hid
->m_nManufacturerId
;
249 int wxJoystick::GetProductId() const
251 return m_hid
->m_nProductId
;
254 wxString
wxJoystick::GetProductName() const
256 return m_hid
->m_szProductName
;
259 //---------------------------------------------------------------------------
260 // wxJoystick::GetNumberButtons
261 // wxJoystick::GetNumberAxes
263 // Queries the joystick for an active number of buttons/axes.
265 // In the native HID implementation, the cookies:
266 // 0-40 are the buttons of the joystick
267 // 40-50 are the axes of the joystick
269 // These just query the native HID implementation as above.
270 //---------------------------------------------------------------------------
271 int wxJoystick::GetNumberButtons() const
275 for(int nIndex
= 0; nIndex
< 40; ++nIndex
)
277 if(m_hid
->HasElement(nIndex
))
283 int wxJoystick::GetNumberAxes() const
287 for(int nIndex
= 40; nIndex
< 50; ++nIndex
)
289 if(m_hid
->HasElement(nIndex
))
296 //---------------------------------------------------------------------------
297 // wxJoystick::GetNumberJoysticks
299 // Gets the number of joysticks on the system. In HID that
300 // is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
302 //---------------------------------------------------------------------------
303 int wxJoystick::GetNumberJoysticks()
306 wxHIDDevice::GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_Joystick
) +
307 wxHIDDevice::GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_GamePad
);
310 //---------------------------------------------------------------------------
311 // wxJoystick::SetCapture
313 // Stops sending events from the thread to the window set in
314 // SetCapture and stops polling the joystick
315 //---------------------------------------------------------------------------
316 bool wxJoystick::SetCapture(wxWindow
* win
, int pollingFreq
)
320 m_thread
->m_catchwin
= win
;
321 m_thread
->m_polling
= pollingFreq
;
327 //---------------------------------------------------------------------------
328 // wxJoystick::ReleaseCapture
330 // Stops sending events from the thread to the window set in
331 // SetCapture and stops polling the joystick
332 //---------------------------------------------------------------------------
333 bool wxJoystick::ReleaseCapture()
337 m_thread
->m_catchwin
= NULL
;
338 m_thread
->m_polling
= 0;
344 //---------------------------------------------------------------------------
345 // wxJoystick::Get[XXX]
347 // Gets the minimum and maximum values for each axis, returning 0 if the
348 // axis doesn't exist.
349 //---------------------------------------------------------------------------
350 int wxJoystick::GetXMin() const
352 return m_hid
->m_nXMin
;
355 int wxJoystick::GetYMin() const
357 return m_hid
->m_nYMin
;
360 int wxJoystick::GetZMin() const
362 return m_hid
->m_nZMin
;
365 int wxJoystick::GetRudderMin() const
367 return m_hid
->m_nRudderMin
;
370 int wxJoystick::GetUMin() const
372 return m_hid
->m_nUMin
;
375 int wxJoystick::GetVMin() const
377 return m_hid
->m_nVMin
;
380 int wxJoystick::GetXMax() const
382 return m_hid
->m_nXMax
;
385 int wxJoystick::GetYMax() const
387 return m_hid
->m_nYMax
;
390 int wxJoystick::GetZMax() const
392 return m_hid
->m_nZMax
;
395 int wxJoystick::GetRudderMax() const
397 return m_hid
->m_nRudderMax
;
400 int wxJoystick::GetUMax() const
402 return m_hid
->m_nUMax
;
405 int wxJoystick::GetVMax() const
407 return m_hid
->m_nVMax
;
410 //---------------------------------------------------------------------------
411 // wxJoystick::Get[XXX]
413 // Min/Max values for buttons, axes, etc.. Polling in this case is just
414 // what the linux port has.
415 //---------------------------------------------------------------------------
416 int wxJoystick::GetMaxButtons() const
418 return wxJS_MAX_BUTTONS
;
421 int wxJoystick::GetMaxAxes() const
423 return wxJS_MAX_AXES
;
426 int wxJoystick::GetPollingMin() const
431 int wxJoystick::GetPollingMax() const
436 //---------------------------------------------------------------------------
437 // wxJoystick::Has[XXX]
439 // Just queries the native hid implementation if the cookie was found
440 // when enumerating the cookies of the joystick device
441 //---------------------------------------------------------------------------
442 bool wxJoystick::HasZ() const
444 return m_hid
->HasElement(wxJS_AXIS_Z
);
447 bool wxJoystick::HasRudder() const
449 return m_hid
->HasElement(wxJS_AXIS_RUDDER
);
452 bool wxJoystick::HasU() const
454 return m_hid
->HasElement(wxJS_AXIS_U
);
457 bool wxJoystick::HasV() const
459 return m_hid
->HasElement(wxJS_AXIS_V
);
462 //---------------------------------------------------------------------------
464 //---------------------------------------------------------------------------
465 int wxJoystick::GetPOVPosition() const
470 int wxJoystick::GetPOVCTSPosition() const
475 int wxJoystick::GetMovementThreshold() const
480 void wxJoystick::SetMovementThreshold(int WXUNUSED(threshold
))
484 bool wxJoystick::HasPOV() const
489 bool wxJoystick::HasPOV4Dir() const
494 bool wxJoystick::HasPOVCTS() const
499 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
503 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
505 //---------------------------------------------------------------------------
506 // wxHIDJoystick ctor
508 // Initializes the min/max members
509 //---------------------------------------------------------------------------
510 wxHIDJoystick::wxHIDJoystick() :
511 m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0),
512 m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0)
516 //---------------------------------------------------------------------------
517 // wxHIDJoystick dtor
520 //---------------------------------------------------------------------------
521 wxHIDJoystick::~wxHIDJoystick()
525 //---------------------------------------------------------------------------
526 // wxHIDJoystick::Create
528 // Creates the native HID device (joysticks are of either
529 // kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
530 //---------------------------------------------------------------------------
531 bool wxHIDJoystick::Create(int nWhich
)
533 int nJoysticks
= GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_Joystick
);
535 if (nWhich
<= nJoysticks
)
536 return wxHIDDevice::Create(kHIDPage_GenericDesktop
,
537 kHIDUsage_GD_Joystick
,
540 nWhich
-= nJoysticks
;
542 int nGamePads
= GetCount(kHIDPage_GenericDesktop
, kHIDUsage_GD_GamePad
);
544 if (nWhich
<= nGamePads
)
545 return wxHIDDevice::Create(kHIDPage_GenericDesktop
,
546 kHIDUsage_GD_GamePad
,
552 //---------------------------------------------------------------------------
553 // wxHIDJoystick::BuildCookies
554 // wxHIDJoystick::MakeCookies
556 // Sets up the cookies for the HID device (called from Create) - as
557 // mentioned 0-40 are the buttons and 40-50 are the axes.
559 // MakeCookies is just a recursive function for each array within
561 //---------------------------------------------------------------------------
562 void wxHIDJoystick::BuildCookies(CFArrayRef Array
)
564 InitCookies(50, true);
567 // I wasted two hours of my life on this line :(
568 // accidentally removed it during some source cleaning...
572 //paranoid debugging stuff
574 for(int i
= 0; i
< 50; ++i
)
575 wxPrintf(wxT("\nVAL #%i:[%i]"), i
, m_pCookies
[i
]);
579 void wxHIDJoystick::MakeCookies(CFArrayRef Array
)
581 int i
, nUsage
, nPage
;
583 for (i
= 0; i
< CFArrayGetCount(Array
); ++i
)
585 const void* ref
= CFDictionaryGetValue(
586 (CFDictionaryRef
)CFArrayGetValueAtIndex(Array
, i
),
587 CFSTR(kIOHIDElementKey
)
592 MakeCookies((CFArrayRef
) ref
);
598 CFDictionaryGetValue(
599 (CFDictionaryRef
) CFArrayGetValueAtIndex(Array
, i
),
600 CFSTR(kIOHIDElementUsageKey
)
607 CFDictionaryGetValue(
608 (CFDictionaryRef
) CFArrayGetValueAtIndex(Array
, i
),
609 CFSTR(kIOHIDElementUsagePageKey
)
615 wxLogSysError(wxT("[%i][%i]"), nUsage
, nPage
);
617 if (nPage
== kHIDPage_Button
&& nUsage
<= 40)
618 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), nUsage
-1 );
619 else if (nPage
== kHIDPage_GenericDesktop
)
625 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_X
);
626 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
627 CFSTR(kIOHIDElementMaxKey
),
629 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
630 CFSTR(kIOHIDElementMinKey
),
634 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_Y
);
635 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
636 CFSTR(kIOHIDElementMaxKey
),
638 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
639 CFSTR(kIOHIDElementMinKey
),
643 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_Z
);
644 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
645 CFSTR(kIOHIDElementMaxKey
),
647 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
648 CFSTR(kIOHIDElementMinKey
),
655 else if (nPage
== kHIDPage_Simulation
&& nUsage
== kHIDUsage_Sim_Rudder
)
658 AddCookieInQueue(CFArrayGetValueAtIndex(Array
, i
), wxJS_AXIS_RUDDER
);
659 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
660 CFSTR(kIOHIDElementMaxKey
),
662 wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array
, i
),
663 CFSTR(kIOHIDElementMinKey
),
670 //---------------------------------------------------------------------------
671 // wxHIDJoystick::Get[XXX]
673 // Simple accessors so that the HID callback and the thread procedure
674 // can access members from wxHIDDevice (our parent here).
675 //---------------------------------------------------------------------------
676 IOHIDElementCookie
* wxHIDJoystick::GetCookies()
677 { return m_pCookies
; }
678 IOHIDQueueInterface
** wxHIDJoystick::GetQueue()
679 { return m_ppQueue
; }
681 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
685 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
687 //---------------------------------------------------------------------------
688 // wxJoystickThread Constructor
690 // Just initializes members
691 //---------------------------------------------------------------------------
692 wxJoystickThread::wxJoystickThread(wxHIDJoystick
* hid
, int joystick
)
694 m_joystick(joystick
),
695 m_lastposition(127,127),
700 memset(m_axe
, 0, sizeof(int) * wxJS_MAX_AXES
);
703 //---------------------------------------------------------------------------
704 // wxJoystickThread::Entry
708 // Runs a CFRunLoop for polling. Basically, it sets the HID queue to
709 // call wxJoystickThread::HIDCallback in the context of this thread
710 // when something changes on the device. It polls as long as the user
711 // wants, or a certain amount if the user wants to "block". Note that
712 // we don't actually block here since this is in a secondary thread.
713 //---------------------------------------------------------------------------
714 void* wxJoystickThread::Entry()
716 CFRunLoopSourceRef pRLSource
= NULL
;
718 if ((*m_hid
->GetQueue())->createAsyncEventSource(
719 m_hid
->GetQueue(), &pRLSource
) != kIOReturnSuccess
)
721 wxLogSysError(wxT("Couldn't create async event source"));
725 wxASSERT(pRLSource
!= NULL
);
727 //attach runloop source to main run loop in thread
728 CFRunLoopRef pRL
= CFRunLoopGetCurrent();
729 CFRunLoopAddSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
);
730 wxASSERT( CFRunLoopContainsSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
) );
733 if( (*m_hid
->GetQueue())->setEventCallout(m_hid
->GetQueue(),
734 wxJoystickThread::HIDCallback
, this, this) != kIOReturnSuccess
)
736 wxLogSysError(wxT("Could not set event callout for queue"));
740 if( (*m_hid
->GetQueue())->start(m_hid
->GetQueue()) != kIOReturnSuccess
)
742 wxLogSysError(wxT("Could not start queue"));
754 dTime
= 0.0001 * m_polling
;
756 dTime
= 0.0001 * 10; // check at least every 10 msec in "blocking" case
758 //true just "handles and returns" - false forces it to stay the time
761 CFRunLoopRunInMode(kCFRunLoopDefaultMode
, dTime
, true);
764 HIDCallback(this, ret
, this, this);
769 wxASSERT( CFRunLoopContainsSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
) );
771 CFRunLoopRemoveSource(pRL
, pRLSource
, kCFRunLoopDefaultMode
);
772 CFRelease(pRLSource
);
777 //---------------------------------------------------------------------------
778 // wxJoystickThread::HIDCallback (static)
780 // Callback for the native HID device when it receives input.
782 // This is where the REAL dirty work gets done.
784 // 1) Loops through each event the queue has received
785 // 2) First, checks if the thread that is running the loop for
786 // the polling has ended - if so it breaks out
787 // 3) Next, it checks if there was an error getting this event from
788 // the HID queue, if there was, it logs an error and returns
789 // 4) Now it does the real dirty work by getting the button states
790 // from cookies 0-40 and axes positions/states from cookies 40-50
791 // in the native HID device by quering cookie values.
792 // 5) Sends the event to the polling window (if any)
793 // 6) Gets the next event and goes back to (1)
794 //---------------------------------------------------------------------------
795 /*static*/ void wxJoystickThread::HIDCallback(void* WXUNUSED(target
),
796 IOReturn
WXUNUSED(res
),
798 void* WXUNUSED(sender
))
800 IOHIDEventStruct hidevent
;
801 AbsoluteTime bogustime
= {0,0};
803 wxJoystickThread
* pThis
= (wxJoystickThread
*) context
;
804 wxHIDJoystick
* m_hid
= pThis
->m_hid
;
806 //Get the "first" event from the queue
807 //bogustime tells it we don't care at what time to start
808 //where it gets the next from
809 ret
= (*m_hid
->GetQueue())->getNextEvent(m_hid
->GetQueue(),
810 &hidevent
, bogustime
, 0);
812 while (ret
!= kIOReturnUnderrun
)
814 if (pThis
->TestDestroy())
817 if(ret
!= kIOReturnSuccess
)
819 wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret
));
823 wxJoystickEvent wxevent
;
825 //Find the cookie that changed
827 IOHIDElementCookie
* pCookies
= m_hid
->GetCookies();
830 if(hidevent
.elementCookie
== pCookies
[nIndex
])
840 wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
845 //is the cookie a button?
850 pThis
->m_buttons
|= (1 << nIndex
);
851 wxevent
.SetEventType(wxEVT_JOY_BUTTON_DOWN
);
855 pThis
->m_buttons
&= ~(1 << nIndex
);
856 wxevent
.SetEventType(wxEVT_JOY_BUTTON_UP
);
859 wxevent
.SetButtonChange(nIndex
+1);
861 else if (nIndex
== wxJS_AXIS_X
)
863 pThis
->m_lastposition
.x
= hidevent
.value
;
864 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
865 pThis
->m_axe
[0] = hidevent
.value
;
867 else if (nIndex
== wxJS_AXIS_Y
)
869 pThis
->m_lastposition
.y
= hidevent
.value
;
870 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
871 pThis
->m_axe
[1] = hidevent
.value
;
873 else if (nIndex
== wxJS_AXIS_Z
)
875 wxevent
.SetEventType(wxEVT_JOY_ZMOVE
);
876 pThis
->m_axe
[2] = hidevent
.value
;
879 wxevent
.SetEventType(wxEVT_JOY_MOVE
);
881 Nanoseconds timestamp
= AbsoluteToNanoseconds(hidevent
.timestamp
);
883 wxULongLong
llTime(timestamp
.hi
, timestamp
.lo
);
887 wxevent
.SetTimestamp(llTime
.GetValue());
888 wxevent
.SetJoystick(pThis
->m_joystick
);
889 wxevent
.SetButtonState(pThis
->m_buttons
);
890 wxevent
.SetPosition(pThis
->m_lastposition
);
891 wxevent
.SetZPosition(pThis
->m_axe
[2]);
892 wxevent
.SetEventObject(pThis
->m_catchwin
);
894 if (pThis
->m_catchwin
)
895 pThis
->m_catchwin
->GetEventHandler()->AddPendingEvent(wxevent
);
897 ret
= (*m_hid
->GetQueue())->getNextEvent(m_hid
->GetQueue(),
898 &hidevent
, bogustime
, 0);
902 #endif // wxUSE_JOYSTICK