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