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