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