]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOHIDSystem / IOHIKeyboardMapper.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
23 *
24 * KeyMap.m - Generic keymap string parser and keycode translator.
25 *
26 * HISTORY
27 * 19 June 1992 Mike Paquette at NeXT
28 * Created.
29 * 5 Aug 1993 Erik Kay at NeXT
30 * minor API cleanup
31 * 11 Nov 1993 Erik Kay at NeXT
32 * fix to allow prevent long sequences from overflowing the event queue
33 * 12 Nov 1998 Dan Markarian at Apple
34 * major cleanup of public API's; converted to C++
35 */
36
37 #include <IOKit/assert.h>
38 #include <IOKit/IOLib.h>
39 #include <IOKit/hidsystem/IOLLEvent.h>
40 #include <IOKit/hidsystem/IOHIKeyboard.h>
41 #include <IOKit/hidsystem/IOHIKeyboardMapper.h>
42
43 #define super OSObject
44 OSDefineMetaClassAndStructors(IOHIKeyboardMapper, OSObject);
45
46 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47
48 IOHIKeyboardMapper * IOHIKeyboardMapper::keyboardMapper(
49 IOHIKeyboard * delegate,
50 const UInt8 * mapping,
51 UInt32 mappingLength,
52 bool mappingShouldBeFreed )
53 {
54 IOHIKeyboardMapper * me = new IOHIKeyboardMapper;
55
56 if (me && !me->init(delegate, mapping, mappingLength, mappingShouldBeFreed))
57 {
58 me->free();
59 return 0;
60 }
61
62 return me;
63 }
64
65 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66
67 /*
68 * Common KeyMap initialization
69 */
70 bool IOHIKeyboardMapper::init( IOHIKeyboard * delegate,
71 const UInt8 * mapping,
72 UInt32 mappingLength,
73 bool mappingShouldBeFreed )
74 {
75 if (!super::init()) return false;
76
77 _delegate = delegate;
78
79 if (!parseKeyMapping(mapping, mappingLength, &_parsedMapping)) return false;
80
81 _mappingShouldBeFreed = mappingShouldBeFreed;
82 _parsedMapping.mapping = mapping;
83 _parsedMapping.mappingLen = mappingLength;
84
85 return true;
86 }
87
88 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89
90 void IOHIKeyboardMapper::free()
91 {
92 if (_mappingShouldBeFreed && _parsedMapping.mapping)
93 IOFree((void *)_parsedMapping.mapping, _parsedMapping.mappingLen);
94
95 super::free();
96 }
97
98 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
99
100 const UInt8 * IOHIKeyboardMapper::mapping()
101 {
102 return (const UInt8 *)_parsedMapping.mapping;
103 }
104
105 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
106
107 UInt32 IOHIKeyboardMapper::mappingLength()
108 {
109 return _parsedMapping.mappingLen;
110 }
111
112 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
113
114 bool IOHIKeyboardMapper::serialize(OSSerialize *s) const
115 {
116 OSData * data;
117 bool ok;
118
119 if (s->previouslySerialized(this)) return true;
120
121 data = OSData::withBytesNoCopy( (void *) _parsedMapping.mapping, _parsedMapping.mappingLen );
122 if (data) {
123 ok = data->serialize(s);
124 data->release();
125 } else
126 ok = false;
127
128 return( ok );
129 }
130
131 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132
133 //
134 // Perform the mapping of 'key' moving in the specified direction
135 // into events.
136 //
137
138 void IOHIKeyboardMapper::translateKeyCode(UInt8 key,
139 bool keyDown,
140 kbdBitVector keyBits)
141 {
142 unsigned char thisBits = _parsedMapping.keyBits[key];
143 unsigned char * bp;
144
145 /* do mod bit update and char generation in useful order */
146 if (keyDown)
147 {
148 EVK_KEYDOWN(key, keyBits);
149
150 if (thisBits & NX_MODMASK) doModCalc(key, keyBits);
151 if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown);
152 }
153 else
154 {
155 EVK_KEYUP(key, keyBits);
156 if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown);
157 if (thisBits & NX_MODMASK) doModCalc(key, keyBits);
158 }
159
160 //Fix JIS localization. We are here because the JIS keys Yen, Ro, Eisu,
161 // Kana, and "," are not matched in _parsedMapping.keyBits[] above even
162 // though the keyboard drivers are sending the correct scan codes.
163 // The check for interfaceID() below makes sure both ADB and USB works.
164 // This fix has been tested with AppKit and Carbon for Kodiak 1H
165 if( 0 == (thisBits & (NX_MODMASK | NX_CHARGENMASK)))
166 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
167 {
168 unsigned charCode=0;
169
170 switch (key) {
171 case 0x5F: // numpad ',' using raw ADB scan code
172 charCode = ',';
173 break;
174 case 0x5E: //ro
175 charCode = '_';
176 break;
177 case 0x5d: //Yen
178 charCode = '\\';
179 break;
180 case 0x0a:
181 charCode = 0xa7;
182 break;
183 case 0x66: // eisu
184 case 0x68: // kana
185 default:
186 // do nothing. AppKit has fix in 1H
187 break;
188 }
189 /* Post the keyboard event */
190 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
191 /* flags */ _delegate->eventFlags(),
192 /* keyCode */ key,
193 /* charCode */ charCode,
194 /* charSet */ 0, //0 is adequate for JIS
195 /* originalCharCode */ 0,
196 /* originalCharSet */ 0);
197 }
198
199 #ifdef OMITPENDINGKEYCAPS
200 //Make KeyCaps.app see the caps lock
201 if (key == _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK]) //ADB caps lock 0x39
202 {
203 if (_delegate->alphaLock() == keyDown)
204 //This logic is needed for non-locking USB caps lock
205 {
206 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
207 _delegate->eventFlags(), key, 0, 0, 0, 0);
208 }
209 }
210
211 //Find scan code corresponding to PowerBook fn key (0x3f in ADB)
212 bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry
213 if (bp)
214 {
215 bp++; //now points to actual ADB scan code
216 if (key == *bp ) //ADB fn key should be 0x3f here
217 {
218 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
219 _delegate->eventFlags(), key, 0, 0, 0, 0);
220 }
221 }
222 #endif
223 }
224
225 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
226
227 //
228 // Support goop for parseKeyMapping. These routines are
229 // used to walk through the keymapping string. The string
230 // may be composed of bytes or shorts. If using shorts, it
231 // MUST always be aligned to use short boundries.
232 //
233 typedef struct {
234 unsigned const char *bp;
235 unsigned const char *endPtr;
236 int shorts;
237 } NewMappingData;
238
239 static inline unsigned int NextNum(NewMappingData *nmd)
240 {
241 if (nmd->bp >= nmd->endPtr)
242 return(0);
243 if (nmd->shorts)
244 return(*((unsigned short *)nmd->bp)++);
245 else
246 return(*((unsigned char *)nmd->bp)++);
247 }
248
249 //
250 // Perform the actual parsing operation on a keymap. Returns false on failure.
251 //
252
253 bool IOHIKeyboardMapper::parseKeyMapping(const UInt8 * mapping,
254 UInt32 mappingLength,
255 NXParsedKeyMapping * parsedMapping) const
256 {
257 NewMappingData nmd;
258 int i, j, k, l, n;
259 unsigned int m;
260 int keyMask, numMods;
261 int maxSeqNum = -1;
262 unsigned char * bp;
263
264
265 /* Initialize the new map. */
266 bzero( parsedMapping, sizeof (NXParsedKeyMapping) );
267 parsedMapping->maxMod = -1;
268 parsedMapping->numDefs = -1;
269 parsedMapping->numSeqs = -1;
270
271 nmd.endPtr = mapping + mappingLength;
272 nmd.bp = mapping;
273 nmd.shorts = 1; // First value, the size, is always a short
274
275 /* Start filling it in with the new data */
276 parsedMapping->mapping = (unsigned char *)mapping;
277 parsedMapping->mappingLen = mappingLength;
278 parsedMapping->shorts = nmd.shorts = NextNum(&nmd);
279
280 /* Walk through the modifier definitions */
281 numMods = NextNum(&nmd);
282 for(i=0; i<numMods; i++)
283 {
284 /* Get bit number */
285 if ((j = NextNum(&nmd)) >= NX_NUMMODIFIERS)
286 return false;
287
288 /* Check maxMod */
289 if (j > parsedMapping->maxMod)
290 parsedMapping->maxMod = j;
291
292 /* record position of this def */
293 parsedMapping->modDefs[j] = (unsigned char *)nmd.bp;
294
295 /* Loop through each key assigned to this bit */
296 for(k=0,n = NextNum(&nmd);k<n;k++)
297 {
298 /* Check that key code is valid */
299 if ((l = NextNum(&nmd)) >= NX_NUMKEYCODES)
300 return false;
301 /* Make sure the key's not already assigned */
302 if (parsedMapping->keyBits[l] & NX_MODMASK)
303 return false;
304 /* Set bit for modifier and which one */
305
306 //The "if" here is to patch the keymapping file. That file has nothing
307 // for num lock, so no change is required here for num lock.
308 // Also, laptop Macs have num lock handled by Buttons driver
309 if ((j != NX_MODIFIERKEY_ALPHALOCK) || (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) )
310 {
311 parsedMapping->keyBits[l] |=NX_MODMASK | (j & NX_WHICHMODMASK);
312 }
313
314 }
315 }
316
317 //This is here because keymapping file has an entry for caps lock, but in
318 // order to trigger special code (line 646-), the entry needs to be zero
319 if (!_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK))
320 parsedMapping->modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0;
321
322 //This section is here to force keymapping to include the PowerBook's secondary
323 // fn key as a new modifier key. This code can be removed once the keymapping
324 // file has the fn key (ADB=0x3f) in the modifiers section.
325 // NX_MODIFIERKEY_SECONDARYFN = 8 in ev_keymap.h
326 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
327 {
328 parsedMapping->keyBits[0x3f] |=NX_MODMASK | (NX_MODIFIERKEY_SECONDARYFN & NX_WHICHMODMASK);
329 }
330
331 /* Walk through each key definition */
332 parsedMapping->numDefs = NextNum(&nmd);
333 n = parsedMapping->numDefs;
334 for( i=0; i < NX_NUMKEYCODES; i++)
335 {
336 if (i < n)
337 {
338 parsedMapping->keyDefs[i] = (unsigned char *)nmd.bp;
339 if ((keyMask = NextNum(&nmd)) != (nmd.shorts ? 0xFFFF: 0x00FF))
340 {
341 /* Set char gen bit for this guy: not a no-op */
342 parsedMapping->keyBits[i] |= NX_CHARGENMASK;
343 /* Check key defs to find max sequence number */
344 for(j=0, k=1; j<=parsedMapping->maxMod; j++, keyMask>>=1)
345 {
346 if (keyMask & 0x01)
347 k*= 2;
348 }
349 for(j=0; j<k; j++)
350 {
351 m = NextNum(&nmd);
352 l = NextNum(&nmd);
353 if (m == (unsigned)(nmd.shorts ? 0xFFFF: 0x00FF))
354 if (((int)l) > maxSeqNum)
355 maxSeqNum = l; /* Update expected # of seqs */
356 }
357 }
358 else /* unused code within active range */
359 parsedMapping->keyDefs[i] = NULL;
360 }
361 else /* Unused code past active range */
362 {
363 parsedMapping->keyDefs[i] = NULL;
364 }
365 }
366 /* Walk through sequence defs */
367 parsedMapping->numSeqs = NextNum(&nmd);
368 /* If the map calls more sequences than are declared, bail out */
369 if (parsedMapping->numSeqs <= maxSeqNum)
370 return false;
371
372 /* Walk past all sequences */
373 for(i = 0; i < parsedMapping->numSeqs; i++)
374 {
375 parsedMapping->seqDefs[i] = (unsigned char *)nmd.bp;
376 /* Walk thru entries in a seq. */
377 for(j=0, l=NextNum(&nmd); j<l; j++)
378 {
379 NextNum(&nmd);
380 NextNum(&nmd);
381 }
382 }
383 /* Install Special device keys. These override default values. */
384 numMods = NextNum(&nmd); /* Zero on old style keymaps */
385 if ( numMods > NX_NUMSPECIALKEYS )
386 return false;
387 if ( numMods )
388 {
389 for ( i = 0; i < NX_NUMSPECIALKEYS; ++i )
390 parsedMapping->specialKeys[i] = NX_NOSPECIALKEY;
391
392 //This "if" will cover both ADB and USB keyboards. This code does not
393 // have to be here if the keymaps include these two entries. Keyboard
394 // drivers already have these entries, but keymapping file does not
395 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
396 {
397 //ADB capslock:
398 parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] = 0x39;
399
400 //ADB numlock for external keyboards, not PowerBook keyboards:
401 parsedMapping->specialKeys[NX_KEYTYPE_NUM_LOCK] = 0x47;
402
403 //HELP key needs to be visible
404 parsedMapping->keyDefs[0x72] = parsedMapping->keyDefs[0x47];
405 }
406
407 //Keymapping file can override caps and num lock above now:
408 for ( i = 0; i < numMods; ++i )
409 {
410 j = NextNum(&nmd); /* Which modifier key? */
411 l = NextNum(&nmd); /* Scancode for modifier key */
412 if ( j >= NX_NUMSPECIALKEYS )
413 return false;
414 parsedMapping->specialKeys[j] = l;
415 }
416 }
417 else /* No special keys defs implies an old style keymap */
418 {
419 return false; /* Old style keymaps are guaranteed to do */
420 /* the wrong thing on ADB keyboards */
421 }
422 /* Install bits for Special device keys */
423 for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++)
424 {
425 if ( parsedMapping->specialKeys[i] != NX_NOSPECIALKEY )
426 {
427 parsedMapping->keyBits[parsedMapping->specialKeys[i]] |=
428 (NX_CHARGENMASK | NX_SPECIALKEYMASK);
429 }
430 }
431
432 //caps lock keys should not generate characters.
433 if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK))
434 {
435 parsedMapping->keyBits[ parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] ]
436 &= ~NX_CHARGENMASK;
437 }
438
439 //Find scan code corresponding to PowerBook fn key (0x3f in ADB)
440 // and then make sure it does not generate a character
441 bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry
442 if (bp)
443 {
444 bp++; //now points to actual ADB scan code
445 parsedMapping->keyBits[ *bp ] &= ~NX_CHARGENMASK;
446 }
447
448 return true;
449 }
450
451
452 //Retrieve a key from mapping above. Useful for IOHIKeyboard
453 UInt8 IOHIKeyboardMapper::getParsedSpecialKey(UInt8 logical)
454 {
455 UInt8 retval;
456
457 if ( logical < NX_NUMSPECIALKEYS)
458 retval = _parsedMapping.specialKeys[logical];
459 else
460 retval = 0xff; //careful, 0 is mapped already
461 return retval;
462 }
463
464
465 static inline int NEXTNUM(unsigned char ** mapping, short shorts)
466 {
467 int returnValue;
468
469 if (shorts)
470 {
471 returnValue = *((unsigned short *)*mapping);
472 *mapping += sizeof(unsigned short);
473 }
474 else
475 {
476 returnValue = **((unsigned char **)mapping);
477 *mapping += sizeof(unsigned char);
478 }
479
480 return returnValue;
481 }
482
483 //
484 // Look up in the keymapping each key associated with the modifier bit.
485 // Look in the device state to see if that key is down.
486 // Return 1 if a key for modifier 'bit' is down. Return 0 if none is down
487 //
488 static inline int IsModifierDown(NXParsedKeyMapping *parsedMapping,
489 kbdBitVector keyBits,
490 int bit )
491 {
492 int i, n;
493 unsigned char *mapping;
494 unsigned key;
495 short shorts = parsedMapping->shorts;
496
497 if ( (mapping = parsedMapping->modDefs[bit]) != 0 ) {
498 for(i=0, n=NEXTNUM(&mapping, shorts); i<n; i++)
499 {
500 key = NEXTNUM(&mapping, shorts);
501 if ( EVK_IS_KEYDOWN(key, keyBits) )
502 return 1;
503 }
504 }
505 return 0;
506 }
507
508 void IOHIKeyboardMapper::calcModBit(int bit, kbdBitVector keyBits)
509 {
510 int bitMask;
511 unsigned myFlags;
512
513 bitMask = 1<<(bit+16);
514
515 /* Initially clear bit, as if key-up */
516 myFlags = _delegate->deviceFlags() & (~bitMask);
517 /* Set bit if any associated keys are down */
518 if ( IsModifierDown( &_parsedMapping, keyBits, bit ) )
519 myFlags |= bitMask;
520
521 if ( bit == NX_MODIFIERKEY_ALPHALOCK ) /* Caps Lock key */
522 _delegate->setAlphaLock((myFlags & NX_ALPHASHIFTMASK) ? true : false);
523 else if ( bit == NX_MODIFIERKEY_NUMLOCK ) /* Num Lock key */
524 _delegate->setNumLock((myFlags & NX_NUMERICPADMASK) ? true : false);
525
526 _delegate->setDeviceFlags(myFlags);
527
528 }
529
530
531 //
532 // Perform flag state update and generate flags changed events for this key.
533 //
534 void IOHIKeyboardMapper::doModCalc(int key, kbdBitVector keyBits)
535 {
536 int thisBits;
537 thisBits = _parsedMapping.keyBits[key];
538 if (thisBits & NX_MODMASK)
539 {
540 calcModBit((thisBits & NX_WHICHMODMASK), keyBits);
541 /* The driver generates flags-changed events only when there is
542 no key-down or key-up event generated */
543 if (!(thisBits & NX_CHARGENMASK))
544 {
545 /* Post the flags-changed event */
546 _delegate->keyboardEvent(NX_FLAGSCHANGED,
547 /* flags */ _delegate->eventFlags(),
548 /* keyCode */ key,
549 /* charCode */ 0,
550 /* charSet */ 0,
551 /* originalCharCode */ 0,
552 /* originalCharSet */ 0);
553 }
554 else /* Update, but don't generate an event */
555 _delegate->updateEventFlags(_delegate->eventFlags());
556 }
557 }
558
559 //
560 // Perform character event generation for this key
561 //
562 void IOHIKeyboardMapper::doCharGen(int keyCode, bool down)
563 {
564 int i, n, eventType, adjust, thisMask, modifiers, saveModifiers;
565 short shorts;
566 unsigned charSet, origCharSet;
567 unsigned charCode, origCharCode;
568 unsigned char *mapping;
569 unsigned eventFlags, origflags;
570
571 _delegate->setCharKeyActive(true); // a character generating key is active
572
573 eventType = (down == true) ? NX_KEYDOWN : NX_KEYUP;
574 eventFlags = _delegate->eventFlags();
575 saveModifiers = eventFlags >> 16; // machine independent mod bits
576 /* Set NX_ALPHASHIFTMASK based on alphaLock OR shift active */
577 if( saveModifiers & (NX_SHIFTMASK >> 16))
578 saveModifiers |= (NX_ALPHASHIFTMASK >> 16);
579
580
581 /* Get this key's key mapping */
582 shorts = _parsedMapping.shorts;
583 mapping = _parsedMapping.keyDefs[keyCode];
584 modifiers = saveModifiers;
585 if ( mapping )
586 {
587
588
589 /* Build offset for this key */
590 thisMask = NEXTNUM(&mapping, shorts);
591 if (thisMask && modifiers)
592 {
593 adjust = (shorts ? sizeof(short) : sizeof(char))*2;
594 for( i = 0; i <= _parsedMapping.maxMod; ++i)
595 {
596 if (thisMask & 0x01)
597 {
598 if (modifiers & 0x01)
599 mapping += adjust;
600 adjust *= 2;
601 }
602 thisMask >>= 1;
603 modifiers >>= 1;
604 }
605 }
606 charSet = NEXTNUM(&mapping, shorts);
607 charCode = NEXTNUM(&mapping, shorts);
608
609 /* construct "unmodified" character */
610 mapping = _parsedMapping.keyDefs[keyCode];
611 modifiers = saveModifiers & ((NX_ALPHASHIFTMASK | NX_SHIFTMASK) >> 16);
612
613 thisMask = NEXTNUM(&mapping, shorts);
614 if (thisMask && modifiers)
615 {
616 adjust = (shorts ? sizeof(short) : sizeof(char)) * 2;
617 for ( i = 0; i <= _parsedMapping.maxMod; ++i)
618 {
619 if (thisMask & 0x01)
620 {
621 if (modifiers & 0x01)
622 mapping += adjust;
623 adjust *= 2;
624 }
625 thisMask >>= 1;
626 modifiers >>= 1;
627 }
628 }
629 origCharSet = NEXTNUM(&mapping, shorts);
630 origCharCode = NEXTNUM(&mapping, shorts);
631
632 if (charSet == (unsigned)(shorts ? 0xFFFF : 0x00FF))
633 {
634 // Process as a character sequence
635 // charCode holds the sequence number
636 mapping = _parsedMapping.seqDefs[charCode];
637
638 origflags = eventFlags;
639 for(i=0,n=NEXTNUM(&mapping, shorts);i<n;i++)
640 {
641 if ( (charSet = NEXTNUM(&mapping, shorts)) == 0xFF ) /* metakey */
642 {
643 if ( down == true ) /* down or repeat */
644 {
645 eventFlags |= (1 << (NEXTNUM(&mapping, shorts) + 16));
646 _delegate->keyboardEvent(NX_FLAGSCHANGED,
647 /* flags */ _delegate->deviceFlags(),
648 /* keyCode */ keyCode,
649 /* charCode */ 0,
650 /* charSet */ 0,
651 /* originalCharCode */ 0,
652 /* originalCharSet */ 0);
653 }
654 else
655 NEXTNUM(&mapping, shorts); /* Skip over value */
656 }
657 else
658 {
659 charCode = NEXTNUM(&mapping, shorts);
660 _delegate->keyboardEvent(eventType,
661 /* flags */ eventFlags,
662 /* keyCode */ keyCode,
663 /* charCode */ charCode,
664 /* charSet */ charSet,
665 /* originalCharCode */ charCode,
666 /* originalCharSet */ charSet);
667 }
668 }
669 /* Done with macro. Restore the flags if needed. */
670 if ( eventFlags != origflags )
671 {
672 _delegate->keyboardEvent(NX_FLAGSCHANGED,
673 /* flags */ _delegate->deviceFlags(),
674 /* keyCode */ keyCode,
675 /* charCode */ 0,
676 /* charSet */ 0,
677 /* originalCharCode */ 0,
678 /* originalCharSet */ 0);
679 eventFlags = origflags;
680 }
681 }
682 else /* A simple character generating key */
683 {
684 _delegate->keyboardEvent(eventType,
685 /* flags */ eventFlags,
686 /* keyCode */ keyCode,
687 /* charCode */ charCode,
688 /* charSet */ charSet,
689 /* originalCharCode */ origCharCode,
690 /* originalCharSet */ origCharSet);
691 }
692 } /* if (mapping) */
693
694 /*
695 * Check for a device control key: note that they always have CHARGEN
696 * bit set
697 */
698 if (_parsedMapping.keyBits[keyCode] & NX_SPECIALKEYMASK)
699 {
700 for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++)
701 {
702 if ( keyCode == _parsedMapping.specialKeys[i] )
703 {
704 _delegate->keyboardSpecialEvent(eventType,
705 /* flags */ eventFlags,
706 /* keyCode */ keyCode,
707 /* specialty */ i);
708 /*
709 * Special keys hack for letting an arbitrary (non-locking)
710 * key act as a CAPS-LOCK key. If a special CAPS LOCK key
711 * is designated, and there is no key designated for the
712 * AlphaLock function, then we'll let the special key toggle
713 * the AlphaLock state.
714 */
715 if (i == NX_KEYTYPE_CAPS_LOCK
716 && down == true
717 && !_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] )
718 {
719 unsigned myFlags = _delegate->deviceFlags();
720 bool alphaLock = (_delegate->alphaLock() == false);
721
722 // Set delegate's alphaLock state
723 _delegate->setAlphaLock(alphaLock);
724 // Update the delegate's flags
725 if ( alphaLock )
726 myFlags |= NX_ALPHASHIFTMASK;
727 else
728 myFlags &= ~NX_ALPHASHIFTMASK;
729
730 _delegate->setDeviceFlags(myFlags);
731
732 _delegate->keyboardEvent(NX_FLAGSCHANGED,
733 /* flags */ myFlags,
734 /* keyCode */ keyCode,
735 /* charCode */ 0,
736 /* charSet */ 0,
737 /* originalCharCode */ 0,
738 /* originalCharSet */ 0);
739 }
740 else if (i == NX_KEYTYPE_NUM_LOCK
741 && down == true
742 && !_parsedMapping.modDefs[NX_MODIFIERKEY_NUMLOCK] )
743 {
744 unsigned myFlags = _delegate->deviceFlags();
745 bool numLock = (_delegate->numLock() == false);
746
747 // Set delegate's alphaLock state
748 _delegate->setNumLock(numLock);
749 if ( numLock )
750 myFlags |= NX_NUMERICPADMASK;
751 else
752 myFlags &= ~NX_NUMERICPADMASK;
753
754 _delegate->setDeviceFlags(myFlags);
755 _delegate->keyboardEvent(NX_FLAGSCHANGED,
756 /* flags */ myFlags,
757 /* keyCode */ keyCode,
758 /* charCode */ 0,
759 /* charSet */ 0,
760 /* originalCharCode */ 0,
761 /* originalCharSet */ 0);
762 }
763
764 break;
765 }
766 }
767 }
768 }