]> git.saurik.com Git - wxWidgets.git/blob - src/mac/corefoundation/hid.cpp
more checks for non-scrolling windows, some code duplication cleanup
[wxWidgets.git] / src / mac / corefoundation / hid.cpp
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 // ----------------------------------------------------------------------------
62 bool 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 // ----------------------------------------------------------------------------
228 size_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 // ----------------------------------------------------------------------------
298 void 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 // ----------------------------------------------------------------------------
315 void 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 // ----------------------------------------------------------------------------
328 void 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 // ----------------------------------------------------------------------------
358 bool 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 // ----------------------------------------------------------------------------
378 bool 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 // ----------------------------------------------------------------------------
388 wxHIDDevice::~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
417 enum
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 // ----------------------------------------------------------------------------
430 int 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 // ----------------------------------------------------------------------------
441 bool 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 // ----------------------------------------------------------------------------
454 void 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 // ----------------------------------------------------------------------------
466 void wxHIDKeyboard::BuildCookies(CFArrayRef Array)
467 {
468 //Create internal cookie array
469 InitCookies(500);
470
471 //Begin recursing in array
472 DoBuildCookies(Array);
473 }
474
475 void 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
641 class 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
658 IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule)
659
660 wxArrayPtrVoid wxHIDModule::sm_keyboards;
661
662 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
663 //
664 // wxGetKeyState()
665 //
666 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
667
668 bool 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__