2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
24 * KeyMap.m - Generic keymap string parser and keycode translator.
27 * 19 June 1992 Mike Paquette at NeXT
29 * 5 Aug 1993 Erik Kay at NeXT
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++
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>
43 #define super OSObject
44 OSDefineMetaClassAndStructors(IOHIKeyboardMapper
, OSObject
);
46 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
48 IOHIKeyboardMapper
* IOHIKeyboardMapper::keyboardMapper(
49 IOHIKeyboard
* delegate
,
50 const UInt8
* mapping
,
52 bool mappingShouldBeFreed
)
54 IOHIKeyboardMapper
* me
= new IOHIKeyboardMapper
;
56 if (me
&& !me
->init(delegate
, mapping
, mappingLength
, mappingShouldBeFreed
))
65 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68 * Common KeyMap initialization
70 bool IOHIKeyboardMapper::init( IOHIKeyboard
* delegate
,
71 const UInt8
* mapping
,
73 bool mappingShouldBeFreed
)
75 if (!super::init()) return false;
79 if (!parseKeyMapping(mapping
, mappingLength
, &_parsedMapping
)) return false;
81 _mappingShouldBeFreed
= mappingShouldBeFreed
;
82 _parsedMapping
.mapping
= mapping
;
83 _parsedMapping
.mappingLen
= mappingLength
;
88 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90 void IOHIKeyboardMapper::free()
92 if (_mappingShouldBeFreed
&& _parsedMapping
.mapping
)
93 IOFree((void *)_parsedMapping
.mapping
, _parsedMapping
.mappingLen
);
98 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100 const UInt8
* IOHIKeyboardMapper::mapping()
102 return (const UInt8
*)_parsedMapping
.mapping
;
105 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107 UInt32
IOHIKeyboardMapper::mappingLength()
109 return _parsedMapping
.mappingLen
;
112 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114 bool IOHIKeyboardMapper::serialize(OSSerialize
*s
) const
119 if (s
->previouslySerialized(this)) return true;
121 data
= OSData::withBytesNoCopy( (void *) _parsedMapping
.mapping
, _parsedMapping
.mappingLen
);
123 ok
= data
->serialize(s
);
131 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134 // Perform the mapping of 'key' moving in the specified direction
138 void IOHIKeyboardMapper::translateKeyCode(UInt8 key
,
140 kbdBitVector keyBits
)
142 unsigned char thisBits
= _parsedMapping
.keyBits
[key
];
145 /* do mod bit update and char generation in useful order */
148 EVK_KEYDOWN(key
, keyBits
);
150 if (thisBits
& NX_MODMASK
) doModCalc(key
, keyBits
);
151 if (thisBits
& NX_CHARGENMASK
) doCharGen(key
, keyDown
);
155 EVK_KEYUP(key
, keyBits
);
156 if (thisBits
& NX_CHARGENMASK
) doCharGen(key
, keyDown
);
157 if (thisBits
& NX_MODMASK
) doModCalc(key
, keyBits
);
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
)
171 case 0x5F: // numpad ',' using raw ADB scan code
186 // do nothing. AppKit has fix in 1H
189 /* Post the keyboard event */
190 _delegate
->keyboardEvent(keyDown
? NX_KEYDOWN
: NX_KEYUP
,
191 /* flags */ _delegate
->eventFlags(),
193 /* charCode */ charCode
,
194 /* charSet */ 0, //0 is adequate for JIS
195 /* originalCharCode */ 0,
196 /* originalCharSet */ 0);
199 #ifdef OMITPENDINGKEYCAPS
200 //Make KeyCaps.app see the caps lock
201 if (key
== _parsedMapping
.specialKeys
[NX_KEYTYPE_CAPS_LOCK
]) //ADB caps lock 0x39
203 if (_delegate
->alphaLock() == keyDown
)
204 //This logic is needed for non-locking USB caps lock
206 _delegate
->keyboardEvent(keyDown
? NX_KEYDOWN
: NX_KEYUP
,
207 _delegate
->eventFlags(), key
, 0, 0, 0, 0);
211 //Find scan code corresponding to PowerBook fn key (0x3f in ADB)
212 bp
= _parsedMapping
.modDefs
[NX_MODIFIERKEY_SECONDARYFN
]; //7th array entry
215 bp
++; //now points to actual ADB scan code
216 if (key
== *bp
) //ADB fn key should be 0x3f here
218 _delegate
->keyboardEvent(keyDown
? NX_KEYDOWN
: NX_KEYUP
,
219 _delegate
->eventFlags(), key
, 0, 0, 0, 0);
225 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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.
234 unsigned const char *bp
;
235 unsigned const char *endPtr
;
239 static inline unsigned int NextNum(NewMappingData
*nmd
)
241 if (nmd
->bp
>= nmd
->endPtr
)
244 return(*((unsigned short *)nmd
->bp
)++);
246 return(*((unsigned char *)nmd
->bp
)++);
250 // Perform the actual parsing operation on a keymap. Returns false on failure.
253 bool IOHIKeyboardMapper::parseKeyMapping(const UInt8
* mapping
,
254 UInt32 mappingLength
,
255 NXParsedKeyMapping
* parsedMapping
) const
260 int keyMask
, numMods
;
265 /* Initialize the new map. */
266 bzero( parsedMapping
, sizeof (NXParsedKeyMapping
) );
267 parsedMapping
->maxMod
= -1;
268 parsedMapping
->numDefs
= -1;
269 parsedMapping
->numSeqs
= -1;
271 nmd
.endPtr
= mapping
+ mappingLength
;
273 nmd
.shorts
= 1; // First value, the size, is always a short
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
);
280 /* Walk through the modifier definitions */
281 numMods
= NextNum(&nmd
);
282 for(i
=0; i
<numMods
; i
++)
285 if ((j
= NextNum(&nmd
)) >= NX_NUMMODIFIERS
)
289 if (j
> parsedMapping
->maxMod
)
290 parsedMapping
->maxMod
= j
;
292 /* record position of this def */
293 parsedMapping
->modDefs
[j
] = (unsigned char *)nmd
.bp
;
295 /* Loop through each key assigned to this bit */
296 for(k
=0,n
= NextNum(&nmd
);k
<n
;k
++)
298 /* Check that key code is valid */
299 if ((l
= NextNum(&nmd
)) >= NX_NUMKEYCODES
)
301 /* Make sure the key's not already assigned */
302 if (parsedMapping
->keyBits
[l
] & NX_MODMASK
)
304 /* Set bit for modifier and which one */
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
)) )
311 parsedMapping
->keyBits
[l
] |=NX_MODMASK
| (j
& NX_WHICHMODMASK
);
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;
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
)
328 parsedMapping
->keyBits
[0x3f] |=NX_MODMASK
| (NX_MODIFIERKEY_SECONDARYFN
& NX_WHICHMODMASK
);
331 /* Walk through each key definition */
332 parsedMapping
->numDefs
= NextNum(&nmd
);
333 n
= parsedMapping
->numDefs
;
334 for( i
=0; i
< NX_NUMKEYCODES
; i
++)
338 parsedMapping
->keyDefs
[i
] = (unsigned char *)nmd
.bp
;
339 if ((keyMask
= NextNum(&nmd
)) != (nmd
.shorts
? 0xFFFF: 0x00FF))
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)
353 if (m
== (unsigned)(nmd
.shorts
? 0xFFFF: 0x00FF))
354 if (((int)l
) > maxSeqNum
)
355 maxSeqNum
= l
; /* Update expected # of seqs */
358 else /* unused code within active range */
359 parsedMapping
->keyDefs
[i
] = NULL
;
361 else /* Unused code past active range */
363 parsedMapping
->keyDefs
[i
] = NULL
;
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
)
372 /* Walk past all sequences */
373 for(i
= 0; i
< parsedMapping
->numSeqs
; i
++)
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
++)
383 /* Install Special device keys. These override default values. */
384 numMods
= NextNum(&nmd
); /* Zero on old style keymaps */
385 if ( numMods
> NX_NUMSPECIALKEYS
)
389 for ( i
= 0; i
< NX_NUMSPECIALKEYS
; ++i
)
390 parsedMapping
->specialKeys
[i
] = NX_NOSPECIALKEY
;
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
)
398 parsedMapping
->specialKeys
[NX_KEYTYPE_CAPS_LOCK
] = 0x39;
400 //ADB numlock for external keyboards, not PowerBook keyboards:
401 parsedMapping
->specialKeys
[NX_KEYTYPE_NUM_LOCK
] = 0x47;
403 //HELP key needs to be visible
404 parsedMapping
->keyDefs
[0x72] = parsedMapping
->keyDefs
[0x47];
407 //Keymapping file can override caps and num lock above now:
408 for ( i
= 0; i
< numMods
; ++i
)
410 j
= NextNum(&nmd
); /* Which modifier key? */
411 l
= NextNum(&nmd
); /* Scancode for modifier key */
412 if ( j
>= NX_NUMSPECIALKEYS
)
414 parsedMapping
->specialKeys
[j
] = l
;
417 else /* No special keys defs implies an old style keymap */
419 return false; /* Old style keymaps are guaranteed to do */
420 /* the wrong thing on ADB keyboards */
422 /* Install bits for Special device keys */
423 for(i
=0; i
<NX_NUM_SCANNED_SPECIALKEYS
; i
++)
425 if ( parsedMapping
->specialKeys
[i
] != NX_NOSPECIALKEY
)
427 parsedMapping
->keyBits
[parsedMapping
->specialKeys
[i
]] |=
428 (NX_CHARGENMASK
| NX_SPECIALKEYMASK
);
432 //caps lock keys should not generate characters.
433 if (_delegate
->doesKeyLock(NX_KEYTYPE_CAPS_LOCK
))
435 parsedMapping
->keyBits
[ parsedMapping
->specialKeys
[NX_KEYTYPE_CAPS_LOCK
] ]
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
444 bp
++; //now points to actual ADB scan code
445 parsedMapping
->keyBits
[ *bp
] &= ~NX_CHARGENMASK
;
452 //Retrieve a key from mapping above. Useful for IOHIKeyboard
453 UInt8
IOHIKeyboardMapper::getParsedSpecialKey(UInt8 logical
)
457 if ( logical
< NX_NUMSPECIALKEYS
)
458 retval
= _parsedMapping
.specialKeys
[logical
];
460 retval
= 0xff; //careful, 0 is mapped already
465 static inline int NEXTNUM(unsigned char ** mapping
, short shorts
)
471 returnValue
= *((unsigned short *)*mapping
);
472 *mapping
+= sizeof(unsigned short);
476 returnValue
= **((unsigned char **)mapping
);
477 *mapping
+= sizeof(unsigned char);
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
488 static inline int IsModifierDown(NXParsedKeyMapping
*parsedMapping
,
489 kbdBitVector keyBits
,
493 unsigned char *mapping
;
495 short shorts
= parsedMapping
->shorts
;
497 if ( (mapping
= parsedMapping
->modDefs
[bit
]) != 0 ) {
498 for(i
=0, n
=NEXTNUM(&mapping
, shorts
); i
<n
; i
++)
500 key
= NEXTNUM(&mapping
, shorts
);
501 if ( EVK_IS_KEYDOWN(key
, keyBits
) )
508 void IOHIKeyboardMapper::calcModBit(int bit
, kbdBitVector keyBits
)
513 bitMask
= 1<<(bit
+16);
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
) )
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);
526 _delegate
->setDeviceFlags(myFlags
);
532 // Perform flag state update and generate flags changed events for this key.
534 void IOHIKeyboardMapper::doModCalc(int key
, kbdBitVector keyBits
)
537 thisBits
= _parsedMapping
.keyBits
[key
];
538 if (thisBits
& NX_MODMASK
)
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
))
545 /* Post the flags-changed event */
546 _delegate
->keyboardEvent(NX_FLAGSCHANGED
,
547 /* flags */ _delegate
->eventFlags(),
551 /* originalCharCode */ 0,
552 /* originalCharSet */ 0);
554 else /* Update, but don't generate an event */
555 _delegate
->updateEventFlags(_delegate
->eventFlags());
560 // Perform character event generation for this key
562 void IOHIKeyboardMapper::doCharGen(int keyCode
, bool down
)
564 int i
, n
, eventType
, adjust
, thisMask
, modifiers
, saveModifiers
;
566 unsigned charSet
, origCharSet
;
567 unsigned charCode
, origCharCode
;
568 unsigned char *mapping
;
569 unsigned eventFlags
, origflags
;
571 _delegate
->setCharKeyActive(true); // a character generating key is active
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);
581 /* Get this key's key mapping */
582 shorts
= _parsedMapping
.shorts
;
583 mapping
= _parsedMapping
.keyDefs
[keyCode
];
584 modifiers
= saveModifiers
;
589 /* Build offset for this key */
590 thisMask
= NEXTNUM(&mapping
, shorts
);
591 if (thisMask
&& modifiers
)
593 adjust
= (shorts
? sizeof(short) : sizeof(char))*2;
594 for( i
= 0; i
<= _parsedMapping
.maxMod
; ++i
)
598 if (modifiers
& 0x01)
606 charSet
= NEXTNUM(&mapping
, shorts
);
607 charCode
= NEXTNUM(&mapping
, shorts
);
609 /* construct "unmodified" character */
610 mapping
= _parsedMapping
.keyDefs
[keyCode
];
611 modifiers
= saveModifiers
& ((NX_ALPHASHIFTMASK
| NX_SHIFTMASK
) >> 16);
613 thisMask
= NEXTNUM(&mapping
, shorts
);
614 if (thisMask
&& modifiers
)
616 adjust
= (shorts
? sizeof(short) : sizeof(char)) * 2;
617 for ( i
= 0; i
<= _parsedMapping
.maxMod
; ++i
)
621 if (modifiers
& 0x01)
629 origCharSet
= NEXTNUM(&mapping
, shorts
);
630 origCharCode
= NEXTNUM(&mapping
, shorts
);
632 if (charSet
== (unsigned)(shorts
? 0xFFFF : 0x00FF))
634 // Process as a character sequence
635 // charCode holds the sequence number
636 mapping
= _parsedMapping
.seqDefs
[charCode
];
638 origflags
= eventFlags
;
639 for(i
=0,n
=NEXTNUM(&mapping
, shorts
);i
<n
;i
++)
641 if ( (charSet
= NEXTNUM(&mapping
, shorts
)) == 0xFF ) /* metakey */
643 if ( down
== true ) /* down or repeat */
645 eventFlags
|= (1 << (NEXTNUM(&mapping
, shorts
) + 16));
646 _delegate
->keyboardEvent(NX_FLAGSCHANGED
,
647 /* flags */ _delegate
->deviceFlags(),
648 /* keyCode */ keyCode
,
651 /* originalCharCode */ 0,
652 /* originalCharSet */ 0);
655 NEXTNUM(&mapping
, shorts
); /* Skip over value */
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
);
669 /* Done with macro. Restore the flags if needed. */
670 if ( eventFlags
!= origflags
)
672 _delegate
->keyboardEvent(NX_FLAGSCHANGED
,
673 /* flags */ _delegate
->deviceFlags(),
674 /* keyCode */ keyCode
,
677 /* originalCharCode */ 0,
678 /* originalCharSet */ 0);
679 eventFlags
= origflags
;
682 else /* A simple character generating key */
684 _delegate
->keyboardEvent(eventType
,
685 /* flags */ eventFlags
,
686 /* keyCode */ keyCode
,
687 /* charCode */ charCode
,
688 /* charSet */ charSet
,
689 /* originalCharCode */ origCharCode
,
690 /* originalCharSet */ origCharSet
);
695 * Check for a device control key: note that they always have CHARGEN
698 if (_parsedMapping
.keyBits
[keyCode
] & NX_SPECIALKEYMASK
)
700 for(i
=0; i
<NX_NUM_SCANNED_SPECIALKEYS
; i
++)
702 if ( keyCode
== _parsedMapping
.specialKeys
[i
] )
704 _delegate
->keyboardSpecialEvent(eventType
,
705 /* flags */ eventFlags
,
706 /* keyCode */ keyCode
,
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.
715 if (i
== NX_KEYTYPE_CAPS_LOCK
717 && !_parsedMapping
.modDefs
[NX_MODIFIERKEY_ALPHALOCK
] )
719 unsigned myFlags
= _delegate
->deviceFlags();
720 bool alphaLock
= (_delegate
->alphaLock() == false);
722 // Set delegate's alphaLock state
723 _delegate
->setAlphaLock(alphaLock
);
724 // Update the delegate's flags
726 myFlags
|= NX_ALPHASHIFTMASK
;
728 myFlags
&= ~NX_ALPHASHIFTMASK
;
730 _delegate
->setDeviceFlags(myFlags
);
732 _delegate
->keyboardEvent(NX_FLAGSCHANGED
,
734 /* keyCode */ keyCode
,
737 /* originalCharCode */ 0,
738 /* originalCharSet */ 0);
740 else if (i
== NX_KEYTYPE_NUM_LOCK
742 && !_parsedMapping
.modDefs
[NX_MODIFIERKEY_NUMLOCK
] )
744 unsigned myFlags
= _delegate
->deviceFlags();
745 bool numLock
= (_delegate
->numLock() == false);
747 // Set delegate's alphaLock state
748 _delegate
->setNumLock(numLock
);
750 myFlags
|= NX_NUMERICPADMASK
;
752 myFlags
&= ~NX_NUMERICPADMASK
;
754 _delegate
->setDeviceFlags(myFlags
);
755 _delegate
->keyboardEvent(NX_FLAGSCHANGED
,
757 /* keyCode */ keyCode
,
760 /* originalCharCode */ 0,
761 /* originalCharSet */ 0);