]> git.saurik.com Git - wxWidgets.git/blame - src/osx/core/hid.cpp
Fix handling of the *.* extension case, before this fix it was being passed as a...
[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 {
9a83f860 81 wxLogSysError( wxT("IOServiceMatching(kIOHIDDeviceKey) failed") );
489468fe
SC
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 {
9a83f860 106 wxLogSysError(wxT("No Matching HID Services"));
489468fe
SC
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 {
9a83f860 132 wxLogDebug(wxT("IORegistryEntryCreateCFProperties failed"));
489468fe
SC
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 )
43b2d5e7 196 {
9a83f860 197 wxLogDebug(wxT("HID device: open failed"));
43b2d5e7 198 }
489468fe
SC
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// ----------------------------------------------------------------------------
229size_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 {
9a83f860 245 wxLogSysError( wxT("IOServiceMatching(kIOHIDDeviceKey) failed") );
489468fe
SC
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 {
9a83f860 270 wxLogSysError(wxT("No Matching HID Services"));
489468fe
SC
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// ----------------------------------------------------------------------------
299void 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// ----------------------------------------------------------------------------
316void 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 )
43b2d5e7 321 {
9a83f860 322 wxLogDebug(wxT("HID device: adding element failed"));
43b2d5e7 323 }
489468fe
SC
324}
325
326// ----------------------------------------------------------------------------
327// wxHIDDevice::InitCookies
328//
329// Create the internal cookie array, optionally creating a HID Queue
330// ----------------------------------------------------------------------------
331void 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 {
9a83f860 340 wxLogDebug(wxT("HID device: allocQueue failed"));
489468fe
SC
341 return;
342 }
343
344 //Param 2, flags, none yet
345 if ( (*m_ppQueue)->create(m_ppQueue, 0, 512) != S_OK )
346 {
9a83f860 347 wxLogDebug(wxT("HID device: create failed"));
489468fe
SC
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// ----------------------------------------------------------------------------
361bool 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// ----------------------------------------------------------------------------
381bool wxHIDDevice::HasElement(int nIndex)
382{
728447a0 383 return (void*) m_pCookies[nIndex] != NULL;
489468fe
SC
384}
385
386// ----------------------------------------------------------------------------
387// wxHIDDevice Destructor
388//
389// Frees all memory and objects from the structure
390// ----------------------------------------------------------------------------
391wxHIDDevice::~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
420enum
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// ----------------------------------------------------------------------------
433int 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// ----------------------------------------------------------------------------
444bool 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// ----------------------------------------------------------------------------
457void 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// ----------------------------------------------------------------------------
469void wxHIDKeyboard::BuildCookies(CFArrayRef Array)
470{
471 //Create internal cookie array
472 InitCookies(500);
473
474 //Begin recursing in array
475 DoBuildCookies(Array);
476}
477
478void wxHIDKeyboard::DoBuildCookies(CFArrayRef Array)
479{
480 //Now go through each possible cookie
43201491
SC
481 int i;
482 long nUsage;
489468fe
SC
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
644class 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];
03647350 658 sm_keyboards.Clear();
489468fe
SC
659 }
660};
661
662IMPLEMENT_DYNAMIC_CLASS(wxHIDModule, wxModule)
663
664wxArrayPtrVoid wxHIDModule::sm_keyboards;
665
666// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
667//
668// wxGetKeyState()
669//
670// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
671
672bool 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__