]> git.saurik.com Git - wxWidgets.git/blame - src/osx/core/hid.cpp
Forgot header with OSX prefix
[wxWidgets.git] / src / osx / core / hid.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/corefoundation/hid.cpp
489468fe
SC
3// Purpose: DARWIN HID layer for WX Implementation
4// Author: Ryan Norton
5// Modified by:
6// Created: 11/11/2003
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27//DARWIN _ONLY_
28#ifdef __DARWIN__
29
c8ef3d55 30#include "wx/osx/core/hid.h"
489468fe
SC
31
32#ifndef WX_PRECOMP
33 #include "wx/dynarray.h"
34 #include "wx/string.h"
35 #include "wx/log.h"
36 #include "wx/utils.h"
37 #include "wx/module.h"
38#endif
39
c8ef3d55 40#include "wx/osx/core/cfstring.h"
489468fe
SC
41
42// ============================================================================
43// implementation
44// ============================================================================
45
46// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
47//
48// wxHIDDevice
49//
50// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
51
52// ----------------------------------------------------------------------------
53// wxHIDDevice::Create
54//
55// nClass is the HID Page such as
56// kHIDPage_GenericDesktop
57// nType is the HID Usage such as
58// kHIDUsage_GD_Joystick,kHIDUsage_GD_Mouse,kHIDUsage_GD_Keyboard
59// nDev is the device number to use
60//
61// ----------------------------------------------------------------------------
62bool wxHIDDevice::Create (int nClass, int nType, int nDev)
63{
64 //Create the mach port
65 if(IOMasterPort(bootstrap_port, &m_pPort) != kIOReturnSuccess)
66 {
67 wxLogSysError(wxT("Could not create mach port"));
68 return false;
69 }
70
71 //Dictionary that will hold first
72 //the matching dictionary for determining which kind of devices we want,
73 //then later some registry properties from an iterator (see below)
74 //
75 //The call to IOServiceMatching filters down the
76 //the services we want to hid services (and also eats the
77 //dictionary up for us (consumes one reference))
78 CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
79 if(pDictionary == NULL)
80 {
81 wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
82 return false;
83 }
84
85 //Here we'll filter down the services to what we want
86 if (nType != -1)
87 {
88 CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
89 kCFNumberIntType, &nType);
90 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
91 CFRelease(pType);
92 }
93 if (nClass != -1)
94 {
95 CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
96 kCFNumberIntType, &nClass);
97 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
98 CFRelease(pClass);
99 }
100
101 //Now get the maching services
102 io_iterator_t pIterator;
103 if( IOServiceGetMatchingServices(m_pPort,
104 pDictionary, &pIterator) != kIOReturnSuccess )
105 {
106 wxLogSysError(_T("No Matching HID Services"));
107 return false;
108 }
109
110 //Were there any devices matched?
111 if(pIterator == 0)
112 return false; // No devices found
113
114 //Now we iterate through them
115 io_object_t pObject;
116 while ( (pObject = IOIteratorNext(pIterator)) != 0)
117 {
118 if(--nDev != 0)
119 {
120 IOObjectRelease(pObject);
121 continue;
122 }
123
124 if ( IORegistryEntryCreateCFProperties
125 (
126 pObject,
127 &pDictionary,
128 kCFAllocatorDefault,
129 kNilOptions
130 ) != KERN_SUCCESS )
131 {
132 wxLogDebug(_T("IORegistryEntryCreateCFProperties failed"));
133 }
134
135 //
136 // Now we get the attributes of each "product" in the iterator
137 //
138
139 //Get [product] name
140 CFStringRef cfsProduct = (CFStringRef)
141 CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductKey));
142 m_szProductName =
143 wxCFStringRef( wxCFRetain(cfsProduct)
144 ).AsString();
145
146 //Get the Product ID Key
147 CFNumberRef cfnProductId = (CFNumberRef)
148 CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDProductIDKey));
149 if (cfnProductId)
150 {
151 CFNumberGetValue(cfnProductId, kCFNumberIntType, &m_nProductId);
152 }
153
154 //Get the Vendor ID Key
155 CFNumberRef cfnVendorId = (CFNumberRef)
156 CFDictionaryGetValue(pDictionary, CFSTR(kIOHIDVendorIDKey));
157 if (cfnVendorId)
158 {
159 CFNumberGetValue(cfnVendorId, kCFNumberIntType, &m_nManufacturerId);
160 }
161
162 //
163 // End attribute getting
164 //
165
166 //Create the interface (good grief - long function names!)
167 SInt32 nScore;
168 IOCFPlugInInterface** ppPlugin;
169 if(IOCreatePlugInInterfaceForService(pObject,
170 kIOHIDDeviceUserClientTypeID,
171 kIOCFPlugInInterfaceID, &ppPlugin,
172 &nScore) != kIOReturnSuccess)
173 {
174 wxLogSysError(wxT("Could not create HID Interface for product"));
175 return false;
176 }
177
178 //Now, the final thing we can check before we fall back to asserts
179 //(because the dtor only checks if the device is ok, so if anything
180 //fails from now on the dtor will delete the device anyway, so we can't break from this).
181
182 //Get the HID interface from the plugin to the mach port
183 if((*ppPlugin)->QueryInterface(ppPlugin,
184 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
185 (void**) &m_ppDevice) != S_OK)
186 {
187 wxLogSysError(wxT("Could not get device interface from HID interface"));
188 return false;
189 }
190
191 //release the plugin
192 (*ppPlugin)->Release(ppPlugin);
193
194 //open the HID interface...
195 if ( (*m_ppDevice)->open(m_ppDevice, 0) != S_OK )
196 wxLogDebug(_T("HID device: open failed"));
197
198 //
199 //Now the hard part - in order to scan things we need "cookies"
200 //
201 CFArrayRef cfaCookies = (CFArrayRef)CFDictionaryGetValue(pDictionary,
202 CFSTR(kIOHIDElementKey));
203 BuildCookies(cfaCookies);
204
205 //cleanup
206 CFRelease(pDictionary);
207 IOObjectRelease(pObject);
208
209 //iterator cleanup
210 IOObjectRelease(pIterator);
211
212 return true;
213 }
214
215 //iterator cleanup
216 IOObjectRelease(pIterator);
217
218 return false; //no device
219}//end Create()
220
221// ----------------------------------------------------------------------------
222// wxHIDDevice::GetCount [static]
223//
224// Obtains the number of devices on a system for a given HID Page (nClass)
225// and HID Usage (nType).
226// ----------------------------------------------------------------------------
227size_t wxHIDDevice::GetCount (int nClass, int nType)
228{
229 //Create the mach port
230 mach_port_t pPort;
231 if(IOMasterPort(bootstrap_port, &pPort) != kIOReturnSuccess)
232 {
233 wxLogSysError(wxT("Could not create mach port"));
234 return false;
235 }
236
237 //Dictionary that will hold first
238 //the matching dictionary for determining which kind of devices we want,
239 //then later some registry properties from an iterator (see below)
240 CFMutableDictionaryRef pDictionary = IOServiceMatching(kIOHIDDeviceKey);
241 if(pDictionary == NULL)
242 {
243 wxLogSysError( _T("IOServiceMatching(kIOHIDDeviceKey) failed") );
244 return false;
245 }
246
247 //Here we'll filter down the services to what we want
248 if (nType != -1)
249 {
250 CFNumberRef pType = CFNumberCreate(kCFAllocatorDefault,
251 kCFNumberIntType, &nType);
252 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsageKey), pType);
253 CFRelease(pType);
254 }
255 if (nClass != -1)
256 {
257 CFNumberRef pClass = CFNumberCreate(kCFAllocatorDefault,
258 kCFNumberIntType, &nClass);
259 CFDictionarySetValue(pDictionary, CFSTR(kIOHIDPrimaryUsagePageKey), pClass);
260 CFRelease(pClass);
261 }
262
263 //Now get the maching services
264 io_iterator_t pIterator;
265 if( IOServiceGetMatchingServices(pPort,
266 pDictionary, &pIterator) != kIOReturnSuccess )
267 {
268 wxLogSysError(_T("No Matching HID Services"));
269 return false;
270 }
271
272 //If the iterator doesn't exist there are no devices :)
273 if ( !pIterator )
274 return 0;
275
276 //Now we iterate through them
277 size_t nCount = 0;
278 io_object_t pObject;
279 while ( (pObject = IOIteratorNext(pIterator)) != 0)
280 {
281 ++nCount;
282 IOObjectRelease(pObject);
283 }
284
285 //cleanup
286 IOObjectRelease(pIterator);
287 mach_port_deallocate(mach_task_self(), pPort);
288
289 return nCount;
290}//end Create()
291
292// ----------------------------------------------------------------------------
293// wxHIDDevice::AddCookie
294//
295// Adds a cookie to the internal cookie array from a CFType
296// ----------------------------------------------------------------------------
297void wxHIDDevice::AddCookie(CFTypeRef Data, int i)
298{
299 CFNumberGetValue(
300 (CFNumberRef) CFDictionaryGetValue ( (CFDictionaryRef) Data
301 , CFSTR(kIOHIDElementCookieKey)
302 ),
303 kCFNumberIntType,
304 &m_pCookies[i]
305 );
306}
307
308// ----------------------------------------------------------------------------
309// wxHIDDevice::AddCookieInQueue
310//
311// Adds a cookie to the internal cookie array from a CFType and additionally
312// adds it to the internal HID Queue
313// ----------------------------------------------------------------------------
314void wxHIDDevice::AddCookieInQueue(CFTypeRef Data, int i)
315{
316 //3rd Param flags (none yet)
317 AddCookie(Data, i);
318 if ( (*m_ppQueue)->addElement(m_ppQueue, m_pCookies[i], 0) != S_OK )
319 wxLogDebug(_T("HID device: adding element failed"));
320}
321
322// ----------------------------------------------------------------------------
323// wxHIDDevice::InitCookies
324//
325// Create the internal cookie array, optionally creating a HID Queue
326// ----------------------------------------------------------------------------
327void wxHIDDevice::InitCookies(size_t dwSize, bool bQueue)
328{
329 m_pCookies = new IOHIDElementCookie[dwSize];
330 if (bQueue)
331 {
332 wxASSERT( m_ppQueue == NULL);
333 m_ppQueue = (*m_ppDevice)->allocQueue(m_ppDevice);
334 if ( !m_ppQueue )
335 {
336 wxLogDebug(_T("HID device: allocQueue failed"));
337 return;
338 }
339
340 //Param 2, flags, none yet
341 if ( (*m_ppQueue)->create(m_ppQueue, 0, 512) != S_OK )
342 {
343 wxLogDebug(_T("HID device: create failed"));
344 }
345 }
346
347 //make sure that cookie array is clear
348 memset(m_pCookies, 0, sizeof(*m_pCookies) * dwSize);
349}
350
351// ----------------------------------------------------------------------------
352// wxHIDDevice::IsActive
353//
354// Returns true if a cookie of the device is active - for example if a key is
355// held down, joystick button pressed, caps lock active, etc..
356// ----------------------------------------------------------------------------
357bool wxHIDDevice::IsActive(int nIndex)
358{
359 if(!HasElement(nIndex))
360 {
361 //cookie at index does not exist - getElementValue
362 //could return true which would be incorrect so we
363 //check here
364 return false;
365 }
366
367 IOHIDEventStruct Event;
368 (*m_ppDevice)->getElementValue(m_ppDevice, m_pCookies[nIndex], &Event);
369 return !!Event.value;
370}
371
372// ----------------------------------------------------------------------------
373// wxHIDDevice::HasElement
374//
375// Returns true if the element in the internal cookie array exists
376// ----------------------------------------------------------------------------
377bool wxHIDDevice::HasElement(int nIndex)
378{
379 return m_pCookies[nIndex] != NULL;
380}
381
382// ----------------------------------------------------------------------------
383// wxHIDDevice Destructor
384//
385// Frees all memory and objects from the structure
386// ----------------------------------------------------------------------------
387wxHIDDevice::~wxHIDDevice()
388{
389 if (m_ppDevice != NULL)
390 {
391 if (m_ppQueue != NULL)
392 {
393 (*m_ppQueue)->stop(m_ppQueue);
394 (*m_ppQueue)->dispose(m_ppQueue);
395 (*m_ppQueue)->Release(m_ppQueue);
396 }
397 (*m_ppDevice)->close(m_ppDevice);
398 (*m_ppDevice)->Release(m_ppDevice);
399 mach_port_deallocate(mach_task_self(), m_pPort);
400 }
401
402 if (m_pCookies != NULL)
403 {
404 delete [] m_pCookies;
405 }
406}
407
408// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
409//
410// wxHIDKeyboard
411//
412// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
413
414//There are no right shift, alt etc. in the wx headers yet so just sort
415//of "define our own" for now
416enum
417{
418 WXK_RSHIFT = 400,
419 WXK_RALT,
420 WXK_RCONTROL,
421 WXK_RMENU
422};
423
424// ----------------------------------------------------------------------------
425// wxHIDKeyboard::GetCount [static]
426//
427// Get number of HID keyboards available
428// ----------------------------------------------------------------------------
429int wxHIDKeyboard::GetCount()
430{
431 return wxHIDDevice::GetCount(kHIDPage_GenericDesktop,
432 kHIDUsage_GD_Keyboard);
433}
434
435// ----------------------------------------------------------------------------
436// wxHIDKeyboard::Create
437//
438// Create the HID Keyboard
439// ----------------------------------------------------------------------------
440bool wxHIDKeyboard::Create(int nDev /* = 1*/)
441{
442 return wxHIDDevice::Create(kHIDPage_GenericDesktop,
443 kHIDUsage_GD_Keyboard,
444 nDev);
445}
446
447// ----------------------------------------------------------------------------
448// wxHIDKeyboard::AddCookie
449//
450// Overloaded version of wxHIDDevice::AddCookie that simply does not
451// add a cookie if a duplicate is found
452// ----------------------------------------------------------------------------
453void wxHIDKeyboard::AddCookie(CFTypeRef Data, int i)
454{
455 if(!HasElement(i))
456 wxHIDDevice::AddCookie(Data, i);
457}
458
459// ----------------------------------------------------------------------------
460// wxHIDKeyboard::BuildCookies
461//
462// Callback from Create() to build the HID cookies for the internal cookie
463// array
464// ----------------------------------------------------------------------------
465void wxHIDKeyboard::BuildCookies(CFArrayRef Array)
466{
467 //Create internal cookie array
468 InitCookies(500);
469
470 //Begin recursing in array
471 DoBuildCookies(Array);
472}
473
474void wxHIDKeyboard::DoBuildCookies(CFArrayRef Array)
475{
476 //Now go through each possible cookie
477 int i,
478 nUsage;
479// bool bEOTriggered = false;
480 for (i = 0; i < CFArrayGetCount(Array); ++i)
481 {
482 const void* ref = CFDictionaryGetValue(
483 (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
484 CFSTR(kIOHIDElementKey)
485 );
486
487 if (ref != NULL)
488 {
489 DoBuildCookies((CFArrayRef) ref);
490 }
491 else
492 {
493
494 //
495 // Get the usage #
496 //
497 CFNumberGetValue(
498 (CFNumberRef)
499 CFDictionaryGetValue((CFDictionaryRef)
500 CFArrayGetValueAtIndex(Array, i),
501 CFSTR(kIOHIDElementUsageKey)
502 ),
503 kCFNumberLongType,
504 &nUsage);
505
506 //
507 // Now translate the usage # into a wx keycode
508 //
509
510 //
511 // OK, this is strange - basically this kind of strange -
512 // Starting from 0xEO these elements (like shift) appear twice in
513 // the array! The ones at the end are bogus I guess - the funny part
514 // is that besides the fact that the ones at the front have a Unit
515 // and UnitExponent key with a value of 0 and a different cookie value,
516 // there is no discernable difference between the two...
517 //
518 // Will the real shift please stand up?
519 //
520 // Something to spend a support request on, if I had one, LOL.
521 //
522 //if(nUsage == 0xE0)
523 //{
524 // if(bEOTriggered)
525 // break;
526 // bEOTriggered = true;
527 //}
528 //Instead of that though we now just don't add duplicate keys
529
530 if (nUsage >= kHIDUsage_KeyboardA && nUsage <= kHIDUsage_KeyboardZ)
531 AddCookie(CFArrayGetValueAtIndex(Array, i), 'A' + (nUsage - kHIDUsage_KeyboardA) );
532 else if (nUsage >= kHIDUsage_Keyboard1 && nUsage <= kHIDUsage_Keyboard9)
533 AddCookie(CFArrayGetValueAtIndex(Array, i), '1' + (nUsage - kHIDUsage_Keyboard1) );
534 else if (nUsage >= kHIDUsage_KeyboardF1 && nUsage <= kHIDUsage_KeyboardF12)
535 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F1 + (nUsage - kHIDUsage_KeyboardF1) );
536 else if (nUsage >= kHIDUsage_KeyboardF13 && nUsage <= kHIDUsage_KeyboardF24)
537 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_F13 + (nUsage - kHIDUsage_KeyboardF13) );
538 else if (nUsage >= kHIDUsage_Keypad1 && nUsage <= kHIDUsage_Keypad9)
539 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD1 + (nUsage - kHIDUsage_Keypad1) );
540 else switch (nUsage)
541 {
542 //0's (wx & ascii go 0-9, but HID goes 1-0)
543 case kHIDUsage_Keyboard0:
544 AddCookie(CFArrayGetValueAtIndex(Array, i), '0');
545 break;
546 case kHIDUsage_Keypad0:
547 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_NUMPAD0);
548 break;
549
550 //Basic
551 case kHIDUsage_KeyboardReturnOrEnter:
552 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RETURN);
553 break;
554 case kHIDUsage_KeyboardEscape:
555 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_ESCAPE);
556 break;
557 case kHIDUsage_KeyboardDeleteOrBackspace:
558 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_BACK);
559 break;
560 case kHIDUsage_KeyboardTab:
561 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_TAB);
562 break;
563 case kHIDUsage_KeyboardSpacebar:
564 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_SPACE);
565 break;
566 case kHIDUsage_KeyboardPageUp:
567 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEUP);
568 break;
569 case kHIDUsage_KeyboardEnd:
570 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_END);
571 break;
572 case kHIDUsage_KeyboardPageDown:
573 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_PAGEDOWN);
574 break;
575 case kHIDUsage_KeyboardRightArrow:
576 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_RIGHT);
577 break;
578 case kHIDUsage_KeyboardLeftArrow:
579 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_LEFT);
580 break;
581 case kHIDUsage_KeyboardDownArrow:
582 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_DOWN);
583 break;
584 case kHIDUsage_KeyboardUpArrow:
585 AddCookie(CFArrayGetValueAtIndex(Array, i), WXK_UP);
586 break;
587
588 //LEDS
589 case kHIDUsage_KeyboardCapsLock:
590 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CAPITAL);
591 break;
592 case kHIDUsage_KeypadNumLock:
593 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_NUMLOCK);
594 break;
595 case kHIDUsage_KeyboardScrollLock:
596 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SCROLL);
597 break;
598
599 //Menu keys, Shift, other specials
600 case kHIDUsage_KeyboardLeftControl:
601 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_CONTROL);
602 break;
603 case kHIDUsage_KeyboardLeftShift:
604 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_SHIFT);
605 break;
606 case kHIDUsage_KeyboardLeftAlt:
607 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_ALT);
608 break;
609 case kHIDUsage_KeyboardLeftGUI:
610 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_MENU);
611 break;
612 case kHIDUsage_KeyboardRightControl:
613 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RCONTROL);
614 break;
615 case kHIDUsage_KeyboardRightShift:
616 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RSHIFT);
617 break;
618 case kHIDUsage_KeyboardRightAlt:
619 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RALT);
620 break;
621 case kHIDUsage_KeyboardRightGUI:
622 AddCookie(CFArrayGetValueAtIndex(Array, i),WXK_RMENU);
623 break;
624
625 //Default
626 default:
627 //not in wx keycodes - do nothing....
628 break;
629 } //end mightly long switch
630 } //end if the current element is not an array...
631 } //end for loop for Array
632}//end buildcookies
633
634// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
635//
636// wxHIDModule
637//
638// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
639
640class wxHIDModule : public wxModule
641{
642 DECLARE_DYNAMIC_CLASS(wxHIDModule)
643
644 public:
645 static wxArrayPtrVoid sm_keyboards;
646 virtual bool OnInit()
647 {
648 return true;
649 }
650 virtual void OnExit()
651 {
652 for(size_t i = 0; i < sm_keyboards.GetCount(); ++i)
653 delete (wxHIDKeyboard*) sm_keyboards[i];
654 }
655};
656
657IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule)
658
659wxArrayPtrVoid wxHIDModule::sm_keyboards;
660
661// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
662//
663// wxGetKeyState()
664//
665// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
666
667bool wxGetKeyState (wxKeyCode key)
668{
669 wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
670 WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
671
672 if (wxHIDModule::sm_keyboards.GetCount() == 0)
673 {
674 int nKeyboards = wxHIDKeyboard::GetCount();
675
676 for(int i = 1; i <= nKeyboards; ++i)
677 {
678 wxHIDKeyboard* keyboard = new wxHIDKeyboard();
679 if(keyboard->Create(i))
680 {
681 wxHIDModule::sm_keyboards.Add(keyboard);
682 }
683 else
684 {
685 delete keyboard;
686 break;
687 }
688 }
689
690 wxASSERT_MSG(wxHIDModule::sm_keyboards.GetCount() != 0,
691 wxT("No keyboards found!"));
692 }
693
694 for(size_t i = 0; i < wxHIDModule::sm_keyboards.GetCount(); ++i)
695 {
696 wxHIDKeyboard* keyboard = (wxHIDKeyboard*)
697 wxHIDModule::sm_keyboards[i];
698
699 switch(key)
700 {
701 case WXK_SHIFT:
702 if( keyboard->IsActive(WXK_SHIFT) ||
703 keyboard->IsActive(WXK_RSHIFT) )
704 {
705 return true;
706 }
707 break;
708 case WXK_ALT:
709 if( keyboard->IsActive(WXK_ALT) ||
710 keyboard->IsActive(WXK_RALT) )
711 {
712 return true;
713 }
714 break;
715 case WXK_CONTROL:
716 if( keyboard->IsActive(WXK_CONTROL) ||
717 keyboard->IsActive(WXK_RCONTROL) )
718 {
719 return true;
720 }
721 break;
722 case WXK_MENU:
723 if( keyboard->IsActive(WXK_MENU) ||
724 keyboard->IsActive(WXK_RMENU) )
725 {
726 return true;
727 }
728 break;
729 default:
730 if( keyboard->IsActive(key) )
731 {
732 return true;
733 }
734 break;
735 }
736 }
737
738 return false; //not down/error
739}
740
741#endif //__DARWIN__