forked from steve680/OSXVnc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVNCBundle.m
173 lines (149 loc) · 7.58 KB
/
VNCBundle.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// VNCBundle.m
// OSXvnc
//
// Created by Jonathan Gillaspie on 3/6/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "VNCBundle.h"
#import "keysymdef.h"
#import "kbdptr.h"
@implementation VNCBundle
+ (void) initialize {
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObjects:[NSNumber numberWithInt:kUCKeyActionAutoKey],[NSNumber numberWithInt:kUCKeyActionDisplay],[NSNumber numberWithInt:kUCKeyActionDown], [NSNumber numberWithInt:kUCKeyActionUp], nil], @"KeyStates", // Key States to review to find KeyCodes
nil]];
}
// Here are the resources we can think about using for Int'l keyboard support
// http://developer.apple.com/documentation/Carbon/Reference/KeyboardLayoutServices/
// This will let us determine the current keyboard
// KLGetCurrentKeyboardLayout
// This will set the current keyboard
// KLSetCurrentKeyboardLayout
// This will get the Properties of a keyboard (like the key code to char tables) but...
// KLGetKeyboardLayoutProperty
// UCKeyTranslate - This is the opposite of what we need, if you give it a table and some keyCode (key input) it will tell you what Unicode char (or string) you get
// we need the opposite - we want to know what keys to hit to get a given key (or string)
// This will use the KeyboardLayoutRef to produce a static table of lookups
// By iterating through all possible KeyCodes
+ (void) loadKeyboard: (KeyboardLayoutRef) keyboardLayoutRef forServer: (rfbserver *) theServer{
int i, j;
UCKeyboardLayout *uchrHandle = NULL;
const void *kchrHandle = NULL;
CFStringRef keyboardName;
KeyboardLayoutKind layoutKind;
static UInt32 modifierKeyStates[] = {0, shiftKey, optionKey, controlKey, optionKey | shiftKey, optionKey | controlKey, controlKey | shiftKey, optionKey | shiftKey | controlKey};
UInt32 modifierKeyState = 0;
NSArray *keyStates = [[NSUserDefaults standardUserDefaults] arrayForKey:@"KeyStates"];
/* modifiers */
//cmdKey = 1 << cmdKeyBit,
//shiftKey = 1 << shiftKeyBit,
//alphaLock = 1 << alphaLockBit,
//optionKey = 1 << optionKeyBit,
//controlKey = 1 << controlKeyBit,
// KLGetKeyboardLayoutProperty is 10.2 only how do I access these resources in early versions?
if (keyboardLayoutRef) {
KLGetKeyboardLayoutProperty(keyboardLayoutRef, kKLName, (const void **) &keyboardName);
KLGetKeyboardLayoutProperty(keyboardLayoutRef, kKLKind, (const void **) &layoutKind);
NSLog(@"Keyboard Detected: %@ (Type:%ld) - Loading Keys\n", keyboardName, layoutKind);
if (layoutKind == kKLKCHRuchrKind || layoutKind == kKLuchrKind)
KLGetKeyboardLayoutProperty(keyboardLayoutRef, kKLuchrData, (const void **) &uchrHandle);
else
KLGetKeyboardLayoutProperty(keyboardLayoutRef, kKLKCHRData, (const void **) &kchrHandle);
}
// Initialize them all to 0xFFFF
memset(theServer->keyTable, 0xFF, keyTableSize * sizeof(CGKeyCode));
memset(theServer->keyTableMods, 0xFF, keyTableSize * sizeof(unsigned char));
if (uchrHandle) {
// Ok - we could get the LIST of Modifier Key States out of the Keyboard Layout
// some of them are duplicates so we need to compare them, then we'll iterate through them in reverse order
// UCKeyModifiersToTableNum = ; EventRecord
// This layout gets a little harry
UInt16 keyCode;
UInt32 keyboardType = LMGetKbdType();
UInt32 deadKeyState = 0;
UniCharCount actualStringLength;
UniChar unicodeChar[255];
// Iterate Over Each Modifier Keyset
for (i=0; i < (sizeof(modifierKeyStates) / sizeof(UInt32)); i++) {
modifierKeyState = (modifierKeyStates[i] >> 8) & 0xFF;
//NSLog(@"Loading Keys For Modifer State: %#04x", modifierKeyState);
// Iterate Over Each Key Code
for (keyCode = 0; keyCode < 255; keyCode++) {
for (j=0; j < [keyStates count]; j++) {
int keyActionState = [[keyStates objectAtIndex:j] intValue];
OSStatus resultCode = UCKeyTranslate (uchrHandle,
keyCode,
keyActionState,
modifierKeyState,
keyboardType,
kUCKeyTranslateNoDeadKeysBit,
&deadKeyState,
255, // Only 1 key allowed due to VNC behavior
&actualStringLength,
unicodeChar);
if (resultCode == noErr) {
if (actualStringLength > 1) {
NSLog(@"Multiple Characters For %d (%04lx): %S", keyCode, modifierKeyState, (int*)unicodeChar);
//unicodeChar[0] = unicodeChar[actualStringLength-1];
}
else {
// We'll use the FIRST keyCode that we find for that UNICODE character
if (theServer->keyTable[unicodeChar[0]] == 0xFFFF) {
theServer->keyTable[unicodeChar[0]] = keyCode;
theServer->keyTableMods[unicodeChar[0]] = modifierKeyState;
}
}
}
else {
NSLog(@"Error Translating %d (%04lx): %ld", keyCode, modifierKeyState, resultCode);
}
}
}
}
}
else if (kchrHandle) {
UInt16 keyCode;
UInt32 state=0;
UInt32 kchrCharacters;
// Ok - we need to get the LIST of Modifier Key States out of the Keyboard Layout
// some of them are duplicates so we need to compare them, then we'll iterate through them in reverse order
//UCKeyModifiersToTableNum = ;
for (i=0; i < (sizeof(modifierKeyStates) / sizeof(UInt32)); i++) {
modifierKeyState = (modifierKeyStates[i] >> 8) & 0xFF;
//NSLog(@"Loading Keys For Modifer State:%#04x", modifierKeyState);
// Iterate Over Each Key Code
for (keyCode = 0; keyCode < 255; keyCode++) {
// We pass the modifierKeys as the top 8 bits of keycode
kchrCharacters = KeyTranslate(kchrHandle, (modifierKeyState<<8 | keyCode), &state);
if (kchrCharacters & 0xFFFF0000) {
NSLog(@"Unable To Convert KeyCode, Multiple Characters (%04lx) (%04lx) For: %d (%04lx)",
kchrCharacters>>16 & 0xFFFF, kchrCharacters & 0xFFFF, keyCode, modifierKeyState);
}
else {
// We'll use the FIRST keyCode that we find for that UNICODE character
if (theServer->keyTable[kchrCharacters & 0xFFFF] == 0xFFFF) {
//NSLog(@"KeyCode:%d UniCode:%d", keyCode, kchrCharacters & 0xFFFF);
theServer->keyTable[kchrCharacters & 0xFFFF] = keyCode;
theServer->keyTableMods[kchrCharacters & 0xFFFF] = modifierKeyState;
}
}
}
}
}
else {
// This is the old US only keyboard mapping
// Map the above key table into a static array so we can just look them up directly
NSLog(@"Unable To Determine Key Map - Reverting to US Mapping\n");
for (i = 0; i < (sizeof(USKeyCodes) / sizeof(int)); i += 2)
theServer->keyTable[(unsigned short)USKeyCodes[i]] = (CGKeyCode) USKeyCodes[i+1];
}
// This is the old SpecialKeyCodes keyboard mapping
// Map the above key table into a static array so we can just look them up directly
NSLog(@"Loading %lu XKeysym Special Keys\n", (sizeof(SpecialKeyCodes) / sizeof(int))/2);
for (i = 0; i < (sizeof(SpecialKeyCodes) / sizeof(int)); i += 2) {
theServer->keyTable[(unsigned short)SpecialKeyCodes[i]] = (CGKeyCode) SpecialKeyCodes[i+1];
}
}
@end