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