Make wxJoystick::GetNumberJoystick a static method, as the number of
[wxWidgets.git] / src / mac / corefoundation / hidjoystick.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: joystick.cpp
3 // Purpose: wxJoystick class
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 2/13/2005
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 //===========================================================================
13 // DECLARATIONS
14 //===========================================================================
15
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 //---------------------------------------------------------------------------
24 // Guard
25 //---------------------------------------------------------------------------
26
27 //we only support HID on OSX (DARWIN), since it requires DARWIN...
28 #if wxUSE_JOYSTICK && defined(__DARWIN__)
29
30 //---------------------------------------------------------------------------
31 // Includes
32 //---------------------------------------------------------------------------
33 #include "wx/event.h" //joystick wxEvents
34 #include "wx/log.h" //logging...
35 #include "wx/joystick.h" //...
36 #include "wx/thread.h" //wxThread for polling thread/ wxCriticalSection
37 #include "wx/window.h" //for wxWindow to "capture" joystick
38
39 //private headers
40 #include "wx/mac/corefoundation/hid.h" //private mac hid stuff
41
42 //mac headers
43 #include <CoreServices/CoreServices.h>
44 #include <mach/mach.h>
45 #include <mach/mach_time.h>
46 #include <unistd.h>
47
48 //---------------------------------------------------------------------------
49 // Definitions/Enumerations
50 //---------------------------------------------------------------------------
51
52 #define wxJS_MAX_AXES 10 /*max number of axes*/
53 #define wxJS_MAX_BUTTONS 40 /*max number of buttons*/
54
55 enum
56 {
57 //These are positions within the cookie array
58 //in wxHIDJoystick that the cookies that store the axis' are
59 wxJS_AXIS_X = 40,
60 wxJS_AXIS_Y,
61 wxJS_AXIS_Z,
62 wxJS_AXIS_RUDDER,
63 wxJS_AXIS_U,
64 wxJS_AXIS_V,
65
66 //For the Get[XXX](Min/Max) functions
67 wxJS_AXIS_MAX = 255, //32767,
68 wxJS_AXIS_MIN = 0, //-32767
69 };
70
71 //---------------------------------------------------------------------------
72 // wxHIDJoystick
73 //---------------------------------------------------------------------------
74 class wxHIDJoystick : public wxHIDDevice
75 {
76 public:
77 bool Create(int nWhich);
78 virtual void BuildCookies(wxCFArray& Array);
79 void MakeCookies(wxCFArray& Array);
80 IOHIDElementCookie* GetCookies();
81 IOHIDQueueInterface** GetQueue();
82
83 friend class wxJoystick;
84 };
85
86 //---------------------------------------------------------------------------
87 // wxJoystickThread
88 //---------------------------------------------------------------------------
89 class wxJoystickThread : public wxThread
90 {
91 public:
92 wxJoystickThread(wxHIDJoystick* hid, int joystick);
93 void* Entry();
94 static void HIDCallback(void* target, IOReturn res, void* context, void* sender);
95
96 private:
97 wxHIDJoystick* m_hid;
98 int m_joystick;
99 wxPoint m_lastposition;
100 int m_axe[wxJS_MAX_AXES];
101 int m_buttons;
102 wxWindow* m_catchwin;
103 int m_polling;
104
105 friend class wxJoystick;
106 };
107
108 //===========================================================================
109 // IMPLEMENTATION
110 //===========================================================================
111
112 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
113 //
114 // wxJoystick
115 //
116 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
117
118 IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
119
120 //---------------------------------------------------------------------------
121 // wxJoystick Constructor
122 //
123 // 1) Initializes member variables
124 // 2) Attempts to create the native HID joystick implementation - if none
125 // could be found (no joysticks, etc.) then it sets it to NULL
126 //---------------------------------------------------------------------------
127 wxJoystick::wxJoystick(int joystick)
128 : m_joystick(joystick),
129 m_thread(NULL)
130 {
131 m_hid = new wxHIDJoystick();
132
133 if (m_hid->Create(m_joystick))
134 {
135 m_thread = new wxJoystickThread(m_hid, m_joystick);
136 m_thread->Create();
137 m_thread->Run();
138 }
139 else
140 {
141 delete m_hid;
142 m_hid = NULL;
143 }
144 }
145
146 //---------------------------------------------------------------------------
147 // wxJoystick Destructor
148 //
149 // Releases the capture of the thread, deletes it, and deletes
150 // the native implementation.
151 //---------------------------------------------------------------------------
152 wxJoystick::~wxJoystick()
153 {
154 ReleaseCapture();
155 if (m_thread)
156 m_thread->Delete(); // It's detached so it will delete itself
157
158 if (m_hid)
159 delete m_hid;
160 }
161
162 //---------------------------------------------------------------------------
163 // wxJoystick::Get[XXX]Position
164 //
165 // Returns the value of an axis that was polled from the thread. In the
166 // case of GetPosition returns the X and Y values in a wxPoint
167 //---------------------------------------------------------------------------
168 wxPoint wxJoystick::GetPosition() const
169 {
170 wxPoint pos(wxDefaultPosition);
171 if (m_thread) pos = m_thread->m_lastposition;
172 return pos;
173 }
174 int wxJoystick::GetZPosition() const
175 {
176 if (m_thread)
177 return m_thread->m_axe[wxJS_AXIS_Z];
178 return 0;
179 }
180 int wxJoystick::GetRudderPosition() const
181 {
182 if (m_thread)
183 return m_thread->m_axe[wxJS_AXIS_RUDDER];
184 return 0;
185 }
186 int wxJoystick::GetUPosition() const
187 {
188 if (m_thread)
189 return m_thread->m_axe[wxJS_AXIS_U];
190 return 0;
191 }
192 int wxJoystick::GetVPosition() const
193 {
194 if (m_thread)
195 return m_thread->m_axe[wxJS_AXIS_V];
196 return 0;
197 }
198
199 //---------------------------------------------------------------------------
200 // wxJoystick::GetButtonState
201 //
202 // Returns the state of the buttons in a bitmask as dictated by the
203 // wx manual (the real work takes place in the thread, as always)
204 //---------------------------------------------------------------------------
205 int wxJoystick::GetButtonState() const
206 {
207 if (m_thread)
208 return m_thread->m_buttons;
209 return 0;
210 }
211
212 //---------------------------------------------------------------------------
213 // wxJoystick::IsOk
214 //
215 // Returns whether the joystick initialized successfully - in this case
216 // if the native implementation doesn't exist (in constructor)
217 //---------------------------------------------------------------------------
218 bool wxJoystick::IsOk() const
219 {
220 return m_hid != NULL;
221 }
222
223 //---------------------------------------------------------------------------
224 // wxJoystick::Get[XXX](Id/Name)
225 //
226 // Simple accessors to the native HID implementation
227 //---------------------------------------------------------------------------
228 int wxJoystick::GetManufacturerId() const
229 { return m_hid->m_nManufacturerId; }
230 int wxJoystick::GetProductId() const
231 { return m_hid->m_nProductId; }
232 wxString wxJoystick::GetProductName() const
233 { return m_hid->m_szProductName; }
234
235 //---------------------------------------------------------------------------
236 // wxJoystick::GetNumberButtons
237 // wxJoystick::GetNumberAxes
238 //
239 // Queries the joystick for an active number of buttons/axes.
240 //
241 // In the native HID implementation, the cookies:
242 // 0-40 are the buttons of the joystick
243 // 40-50 are the axes of the joystick
244 //
245 // These just query the native HID implementation as above.
246 //---------------------------------------------------------------------------
247 int wxJoystick::GetNumberButtons() const
248 {
249 int nCount = 0;
250
251 for(int nIndex = 0; nIndex < 40; ++nIndex)
252 {
253 if(m_hid->HasElement(nIndex))
254 ++nCount;
255 }
256
257 return nCount;
258 }
259 int wxJoystick::GetNumberAxes() const
260 {
261 int nCount = 0;
262
263 for(int nIndex = 40; nIndex < 50; ++nIndex)
264 {
265 if(m_hid->HasElement(nIndex))
266 ++nCount;
267 }
268
269 return nCount;
270 }
271
272 //---------------------------------------------------------------------------
273 // wxJoystick::GetNumberJoysticks
274 //
275 // Gets the number of joysticks on the system. In HID that
276 // is all devices with the kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad
277 // identifiers.
278 //---------------------------------------------------------------------------
279 int wxJoystick::GetNumberJoysticks()
280 {
281 return
282 wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) +
283 wxHIDDevice::GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
284 }
285
286 //---------------------------------------------------------------------------
287 // wxJoystick::SetCapture
288 //
289 // Stops sending events from the thread to the window set in
290 // SetCapture and stops polling the joystick
291 //---------------------------------------------------------------------------
292 bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
293 {
294 if (m_thread)
295 {
296 m_thread->m_catchwin = win;
297 m_thread->m_polling = pollingFreq;
298 return true;
299 }
300 return false;
301 }
302
303 //---------------------------------------------------------------------------
304 // wxJoystick::ReleaseCapture
305 //
306 // Stops sending events from the thread to the window set in
307 // SetCapture and stops polling the joystick
308 //---------------------------------------------------------------------------
309 bool wxJoystick::ReleaseCapture()
310 {
311 if (m_thread)
312 {
313 m_thread->m_catchwin = NULL;
314 m_thread->m_polling = 0;
315 return true;
316 }
317 return false;
318 }
319
320 //---------------------------------------------------------------------------
321 // wxJoystick::Get[XXX]
322 //
323 // All values in hid range from 0 to 255, making these all kind of
324 // superflous. These are mainly here due to the msw-centric api
325 // that wxJoystick has... it should REALLY do its own scaling... oh well :)
326 //---------------------------------------------------------------------------
327 int wxJoystick::GetXMin() const
328 { return wxJS_AXIS_MIN; }
329 int wxJoystick::GetYMin() const
330 { return wxJS_AXIS_MIN; }
331 int wxJoystick::GetZMin() const
332 { return wxJS_AXIS_MIN; }
333 int wxJoystick::GetUMin() const
334 { return wxJS_AXIS_MIN; }
335 int wxJoystick::GetVMin() const
336 { return wxJS_AXIS_MIN; }
337 int wxJoystick::GetRudderMin() const
338 { return wxJS_AXIS_MIN; }
339
340 int wxJoystick::GetXMax() const
341 { return wxJS_AXIS_MAX; }
342 int wxJoystick::GetYMax() const
343 { return wxJS_AXIS_MAX; }
344 int wxJoystick::GetZMax() const
345 { return wxJS_AXIS_MAX; }
346 int wxJoystick::GetUMax() const
347 { return wxJS_AXIS_MAX; }
348 int wxJoystick::GetVMax() const
349 { return wxJS_AXIS_MAX; }
350 int wxJoystick::GetRudderMax() const
351 { return wxJS_AXIS_MAX; }
352
353 //---------------------------------------------------------------------------
354 // wxJoystick::Get[XXX]
355 //
356 // Min/Max values for buttons, axes, etc.. Polling in this case is just
357 // what the linux port has.
358 //---------------------------------------------------------------------------
359 int wxJoystick::GetMaxButtons() const
360 { return wxJS_MAX_BUTTONS; }
361 int wxJoystick::GetMaxAxes() const
362 { return wxJS_MAX_AXES; }
363 int wxJoystick::GetPollingMin() const
364 { return 10; }
365 int wxJoystick::GetPollingMax() const
366 { return 1000; }
367
368 //---------------------------------------------------------------------------
369 // wxJoystick::Has[XXX]
370 //
371 // Just queries the native hid implementation if the cookie was found
372 // when enumerating the cookies of the joystick device
373 //---------------------------------------------------------------------------
374 bool wxJoystick::HasRudder() const
375 { return m_hid->HasElement(wxJS_AXIS_RUDDER); }
376 bool wxJoystick::HasZ() const
377 { return m_hid->HasElement(wxJS_AXIS_Z); }
378 bool wxJoystick::HasU() const
379 { return m_hid->HasElement(wxJS_AXIS_U); }
380 bool wxJoystick::HasV() const
381 { return m_hid->HasElement(wxJS_AXIS_V); }
382
383 //---------------------------------------------------------------------------
384 // UNSUPPORTED
385 //---------------------------------------------------------------------------
386 int wxJoystick::GetPOVPosition() const
387 { return -1; }
388 int wxJoystick::GetPOVCTSPosition() const
389 { return -1; }
390 int wxJoystick::GetMovementThreshold() const
391 { return 0; }
392 void wxJoystick::SetMovementThreshold(int threshold)
393 { }
394 bool wxJoystick::HasPOV() const
395 { return false; }
396 bool wxJoystick::HasPOV4Dir() const
397 { return false; }
398 bool wxJoystick::HasPOVCTS() const
399 { return false; }
400
401 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
402 //
403 // wxHIDJoystick
404 //
405 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
406
407 //---------------------------------------------------------------------------
408 // wxHIDJoystick::Create
409 //
410 // Creates the native HID device (joysticks are of either
411 // kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
412 //---------------------------------------------------------------------------
413 bool wxHIDJoystick::Create(int nWhich)
414 {
415 int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
416
417 if (nWhich <= nJoysticks)
418 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
419 else
420 nWhich -= nJoysticks;
421
422 int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
423
424 if (nWhich <= nGamePads)
425 return wxHIDDevice::Create(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
426 else
427 return false;
428 }
429
430 //---------------------------------------------------------------------------
431 // wxHIDJoystick::BuildCookies
432 // wxHIDJoystick::MakeCookies
433 //
434 // Sets up the cookies for the HID device (called from Create) - as
435 // mentioned 0-40 are the buttons and 40-50 are the axes.
436 //
437 // MakeCookies is just a recursive function for each array within
438 // BuildCookies.
439 //---------------------------------------------------------------------------
440 void wxHIDJoystick::BuildCookies(wxCFArray& Array)
441 {
442 Array = CFDictionaryGetValue((CFDictionaryRef)Array[0], CFSTR(kIOHIDElementKey));
443 InitCookies(50, true);
444
445 memset(m_pCookies, 0, sizeof(*m_pCookies) * 50);
446
447 //
448 // I wasted two hours of my life on this line :(
449 // accidently removed it during some source cleaning...
450 //
451 MakeCookies(Array);
452
453 //paranoid debugging stuff
454 #if 0
455 for(int i = 0; i < 50; ++i)
456 wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);
457 #endif
458 }//end buildcookies
459
460 void wxHIDJoystick::MakeCookies(wxCFArray& Array)
461 {
462 int i, nUsage, nPage;
463
464 for (i = 0; i < Array.Count(); ++i)
465 {
466 const void* ref = CFDictionaryGetValue((CFDictionaryRef)Array[i], CFSTR(kIOHIDElementKey));
467
468 if (ref != NULL)
469 {
470 wxCFArray newarray(ref);
471 MakeCookies(newarray);
472 }
473 else
474 {
475 CFNumberGetValue(
476 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)),
477 kCFNumberLongType, &nUsage);
478
479 CFNumberGetValue(
480 (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsagePageKey)),
481 kCFNumberLongType, &nPage);
482
483 #if 0
484 wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);
485 #endif
486 if (nPage == kHIDPage_Button && nUsage <= 40)
487 AddCookieInQueue(Array[i], nUsage-1 );
488 else if (nPage == kHIDPage_GenericDesktop)
489 {
490 switch(nUsage)
491 {
492 case kHIDUsage_GD_X:
493 AddCookieInQueue(Array[i], wxJS_AXIS_X);
494 break;
495 case kHIDUsage_GD_Y:
496 AddCookieInQueue(Array[i], wxJS_AXIS_Y);
497 break;
498 case kHIDUsage_GD_Z:
499 AddCookieInQueue(Array[i], wxJS_AXIS_Z);
500 break;
501 default:
502 break;
503 }
504 }
505 else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder)
506 AddCookieInQueue(Array[i], wxJS_AXIS_RUDDER );
507 }
508 }
509 }
510
511 //---------------------------------------------------------------------------
512 // wxHIDJoystick::Get[XXX]
513 //
514 // Simple accessors so that the HID callback and the thread procedure
515 // can access members from wxHIDDevice (our parent here).
516 //---------------------------------------------------------------------------
517 IOHIDElementCookie* wxHIDJoystick::GetCookies()
518 { return m_pCookies; }
519 IOHIDQueueInterface** wxHIDJoystick::GetQueue()
520 { return m_ppQueue; }
521
522 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
523 //
524 // wxJoystickThread
525 //
526 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
527
528 //---------------------------------------------------------------------------
529 // wxJoystickThread Constructor
530 //
531 // Just initializes members
532 //---------------------------------------------------------------------------
533 wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick)
534 : m_hid(hid),
535 m_joystick(joystick),
536 m_lastposition(127,127),
537 m_buttons(0),
538 m_catchwin(NULL),
539 m_polling(0)
540 {
541 memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);
542 }
543
544 //---------------------------------------------------------------------------
545 // wxJoystickThread::Entry
546 //
547 // Thread procedure
548 //
549 // Runs a CFRunLoop for polling. Basically, it sets the HID queue to
550 // call wxJoystickThread::HIDCallback in the context of this thread
551 // when something changes on the device. It polls as long as the user
552 // wants, or a certain amount if the user wants to "block". Note that
553 // we don't actually block here since this is in a secondary thread.
554 //---------------------------------------------------------------------------
555 void* wxJoystickThread::Entry()
556 {
557 CFRunLoopSourceRef pRLSource = NULL;
558
559 if ((*m_hid->GetQueue())->createAsyncEventSource(
560 m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess )
561 {
562 wxLogSysError(wxT("Couldn't create async event source"));
563 return NULL;
564 }
565
566 wxASSERT(pRLSource != NULL);
567
568 //attach runloop source to main run loop in thread
569 CFRunLoopRef pRL = CFRunLoopGetCurrent();
570 CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode);
571 wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
572
573
574 if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(),
575 wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess )
576 {
577 wxLogSysError(wxT("Could not set event callout for queue"));
578 return NULL;
579 }
580
581 if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess )
582 {
583 wxLogSysError(wxT("Could not start queue"));
584 return NULL;
585 }
586
587 double dTime;
588
589 while(true)
590 {
591 if (TestDestroy())
592 break;
593
594 if (m_polling)
595 dTime = 0.0001 * m_polling;
596 else
597 dTime = 0.0001 * 10; // check at least every 10 msec in "blocking" case
598
599 //true just "handles and returns" - false forces it to stay the time
600 //amount
601 #if 1
602 CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);
603 #else
604 IOReturn ret = NULL;
605 HIDCallback(this, ret, this, this);
606 Sleep(3000);
607 #endif
608 }
609
610 wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );
611
612 CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode);
613 CFRelease(pRLSource);
614
615 return NULL;
616 }
617
618 //---------------------------------------------------------------------------
619 // wxJoystickThread::HIDCallback (static)
620 //
621 // Callback for the native HID device when it recieves input.
622 //
623 // This is where the REAL dirty work gets done.
624 //
625 // 1) Loops through each event the queue has recieved
626 // 2) First, checks if the thread that is running the loop for
627 // the polling has ended - if so it breaks out
628 // 3) Next, it checks if there was an error getting this event from
629 // the HID queue, if there was, it logs an error and returns
630 // 4) Now it does the real dirty work by getting the button states
631 // from cookies 0-40 and axes positions/states from cookies 40-50
632 // in the native HID device by quering cookie values.
633 // 5) Sends the event to the polling window (if any)
634 // 6) Gets the next event and goes back to (1)
635 //---------------------------------------------------------------------------
636 /*static*/ void wxJoystickThread::HIDCallback(void* target, IOReturn res,
637 void* context, void* sender)
638 {
639 IOHIDEventStruct hidevent;
640 AbsoluteTime bogustime = {0,0};
641 IOReturn ret;
642 wxJoystickThread* pThis = (wxJoystickThread*) context;
643 wxHIDJoystick* m_hid = pThis->m_hid;
644
645 //Get the "first" event from the queue
646 //bogustime tells it we don't care at what time to start
647 //where it gets the next from
648 ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
649 &hidevent, bogustime, 0);
650
651 while (ret != kIOReturnUnderrun)
652 {
653 if (pThis->TestDestroy())
654 break;
655
656 if(ret != kIOReturnSuccess)
657 {
658 wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret));
659 return;
660 }
661
662 wxJoystickEvent wxevent;
663
664 //Find the cookie that changed
665 int nIndex = 0;
666 IOHIDElementCookie* pCookies = m_hid->GetCookies();
667 while(nIndex < 50)
668 {
669 if(hidevent.elementCookie == pCookies[nIndex])
670 break;
671
672 ++nIndex;
673 }
674
675 //debugging stuff
676 #if 0
677 if(nIndex == 50)
678 {
679 wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
680 break;
681 }
682 #endif
683
684 //is the cookie a button?
685 if (nIndex < 40)
686 {
687 if (hidevent.value)
688 {
689 pThis->m_buttons |= (1 << nIndex);
690 wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN);
691 }
692 else
693 {
694 pThis->m_buttons &= ~(1 << nIndex);
695 wxevent.SetEventType(wxEVT_JOY_BUTTON_UP);
696 }
697
698 wxevent.SetButtonChange(nIndex+1);
699 }
700 else if (nIndex == wxJS_AXIS_X)
701 {
702 pThis->m_lastposition.x = hidevent.value;
703 wxevent.SetEventType(wxEVT_JOY_MOVE);
704 pThis->m_axe[0] = hidevent.value;
705 }
706 else if (nIndex == wxJS_AXIS_Y)
707 {
708 pThis->m_lastposition.y = hidevent.value;
709 wxevent.SetEventType(wxEVT_JOY_MOVE);
710 pThis->m_axe[1] = hidevent.value;
711 }
712 else if (nIndex == wxJS_AXIS_Z)
713 {
714 wxevent.SetEventType(wxEVT_JOY_ZMOVE);
715 pThis->m_axe[2] = hidevent.value;
716 }
717 else
718 wxevent.SetEventType(wxEVT_JOY_MOVE);
719
720 Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp);
721
722 wxULongLong llTime(timestamp.hi, timestamp.lo);
723
724 llTime /= 1000000;
725
726 wxevent.SetTimestamp(llTime.GetValue());
727 wxevent.SetJoystick(pThis->m_joystick);
728 wxevent.SetButtonState(pThis->m_buttons);
729 wxevent.SetPosition(pThis->m_lastposition);
730 wxevent.SetZPosition(pThis->m_axe[2]);
731 wxevent.SetEventObject(pThis->m_catchwin);
732
733 if (pThis->m_catchwin)
734 pThis->m_catchwin->AddPendingEvent(wxevent);
735
736 ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
737 &hidevent, bogustime, 0);
738 }
739 }
740
741 #endif // wxUSE_JOYSTICK && defined(__DARWIN__)
742