tangled
alpha
login
or
join now
jcs.org
/
shadowebkit
0
fork
atom
an experiment in making a cocoa webkit browser manageable under X11
0
fork
atom
overview
issues
pulls
pipelines
more key handling
jcs.org
14 years ago
5a49de9c
a1f3f0b1
+75
-20
2 changed files
expand all
collapse all
unified
split
X11Window.h
X11Window.m
+1
-1
X11Window.h
···
11
11
12
12
- (void)updateWKWindowPosition;
13
13
- (void)mainLoopWithWKWindow: (id)wkwobj;
14
14
-
- (void)sendKeyFromXEvent:(XKeyEvent)e;
14
14
+
- (void)sendKeyFromXEvent:(XEvent)e;
15
15
16
16
@end
+74
-19
X11Window.m
···
62
62
XSync(display, False);
63
63
64
64
if (e.type == KeyPress || e.type == KeyRelease)
65
65
-
[self sendKeyFromXEvent:e.xkey];
65
65
+
[self sendKeyFromXEvent:e];
66
66
else
67
67
[self updateWKWindowPosition];
68
68
}
···
87
87
waitUntilDone:true];
88
88
}
89
89
90
90
-
- (void)sendKeyFromXEvent:(XKeyEvent)e
90
90
+
/* translate an x11 key event into an equivalent keycode or string and send
91
91
+
* the NSEvent to the app, which will handle sending it to webkit or the url
92
92
+
* bar */
93
93
+
- (void)sendKeyFromXEvent:(XEvent)e
91
94
{
92
92
-
char str[257];
95
95
+
char str[256+1];
96
96
+
char strNoMod[2] = { '\0' };
93
97
char *ksname;
94
98
KeySym ks;
95
99
int keycode = 0;
100
100
+
int repeating = 0;
101
101
+
int modifier = 0;
96
102
97
97
-
XLookupString(&e, str, 256, &ks, NULL);
103
103
+
XLookupString(&e.xkey, str, 256, &ks, NULL);
98
104
99
99
-
if (!(ksname = XKeysymToString(ks)))
100
100
-
ksname = "no name";
105
105
+
/* X11 keysyms in /usr/X11/include/X11/keysymdef.h, carbon key codes
106
106
+
* in /System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/Headers/Events.h */
101
107
102
108
switch (ks) {
103
103
-
case 0x20: keycode = kVK_Space; break;
104
104
-
105
109
case XK_Control_L: keycode = kVK_Control; break;
106
110
case XK_Control_R: keycode = kVK_RightControl; break;
107
111
case XK_Delete: keycode = kVK_ForwardDelete; break;
···
110
114
case XK_Escape: keycode = kVK_Escape; break;
111
115
case XK_Home: keycode = kVK_Home; break;
112
116
case XK_Left: keycode = kVK_LeftArrow; break;
117
117
+
case XK_Meta_L: keycode = kVK_Command; break;
118
118
+
case XK_Meta_R: keycode = kVK_Command; break;
119
119
+
case XK_Mode_switch: keycode = kVK_Option; break;
113
120
case XK_Next: keycode = kVK_PageDown; break;
114
121
case XK_Prior: keycode = kVK_PageUp; break;
115
122
case XK_Return: keycode = kVK_Return; break;
···
119
126
case XK_Up: keycode = kVK_UpArrow; break;
120
127
121
128
default:
122
122
-
if (!strcasecmp(ksname, "backspace")) { keycode = kVK_Delete; break; }
129
129
+
/* translate keys that don't have XK_* equivalents */
130
130
+
131
131
+
if (!(ksname = XKeysymToString(ks)))
132
132
+
ksname = "no name";
133
133
+
134
134
+
if (!strcasecmp(ksname, "backspace")) {
135
135
+
keycode = kVK_Delete;
136
136
+
break;
137
137
+
}
138
138
+
else if (!strcasecmp(ksname, "space")) {
139
139
+
keycode = kVK_Space;
140
140
+
break;
141
141
+
}
142
142
+
else if (strlen(ksname) == 1) {
143
143
+
strlcpy(str, ksname, sizeof(str));
144
144
+
strlcpy(strNoMod, ksname, sizeof(strNoMod));
145
145
+
}
146
146
+
else if (strlen(ksname) > 1)
147
147
+
/* probably a named key */
148
148
+
fprintf(stderr, "should probably translate \"%s\"\n",
149
149
+
ksname);
123
150
124
151
/* otherwise, assume it's just an ascii letter or number we
125
152
* can pass through as 'characters' param and a 0 keyCode */
153
153
+
if (debug)
154
154
+
printf("key %s 0x%x (X11 \"%s\") -> key \"%s\"\n",
155
155
+
(e.type == KeyPress ? "press" : "release"),
156
156
+
e.xkey.keycode,
157
157
+
ksname,
158
158
+
str);
126
159
}
127
160
128
128
-
if (debug)
129
129
-
printf("key %s %d (X11 \"%s\") -> keycode %d %s\n",
130
130
-
(e.type == KeyPress ? "press" : "release"),
131
131
-
e.keycode,
132
132
-
ksname,
133
133
-
keycode,
134
134
-
(keycode == 0 ? str : ""));
161
161
+
/* if we are looking at a keyrelease event and there's a pending
162
162
+
* keypress event with the same timestamp, we're holding a key down */
163
163
+
if (e.type == KeyRelease && XEventsQueued(display,
164
164
+
QueuedAfterReading)) {
165
165
+
XEvent nev;
166
166
+
XPeekEvent(display, &nev);
167
167
+
168
168
+
if (nev.type == KeyPress && nev.xkey.time == e.xkey.time &&
169
169
+
nev.xkey.keycode == e.xkey.keycode)
170
170
+
repeating = 1;
171
171
+
}
172
172
+
173
173
+
if (e.xkey.state) {
174
174
+
if (e.xkey.state & ShiftMask)
175
175
+
modifier |= NSShiftKeyMask;
176
176
+
if (e.xkey.state & LockMask)
177
177
+
modifier |= NSAlphaShiftKeyMask;
178
178
+
if (e.xkey.state & ControlMask)
179
179
+
modifier |= NSControlKeyMask;
180
180
+
if (e.xkey.state & Mod2Mask)
181
181
+
modifier |= NSCommandKeyMask;
182
182
+
if (e.xkey.state & 0x2000)
183
183
+
modifier |= NSAlternateKeyMask;
184
184
+
185
185
+
/* TODO: what do mod1, mod3, mod4, and mod5 map to? */
186
186
+
}
135
187
136
188
NSEvent *fakeEvent = [NSEvent
137
189
keyEventWithType:(e.type == KeyPress ? NSKeyDown : NSKeyUp)
138
190
location:[NSEvent mouseLocation]
139
139
-
modifierFlags:0
191
191
+
modifierFlags:modifier
140
192
timestamp:0
141
193
windowNumber:[[NSApp mainWindow] windowNumber]
142
194
context:nil
143
195
characters:[NSString stringWithFormat:@"%s", str]
144
144
-
charactersIgnoringModifiers:[NSString stringWithFormat:@"%s", str]
145
145
-
isARepeat:NO
196
196
+
charactersIgnoringModifiers:[NSString stringWithFormat:@"%s", strNoMod]
197
197
+
isARepeat:(BOOL)repeating
146
198
keyCode:keycode];
199
199
+
200
200
+
if (debug)
201
201
+
NSLog(@"%@", fakeEvent);
147
202
148
203
[NSApp postEvent:fakeEvent atStart:NO];
149
204
}