1 From 2f97d8a75e7371ac7f3a9a1338db55888754d7c0 Mon Sep 17 00:00:00 2001 |
|
2 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519> |
|
3 Date: Fri, 28 Aug 2009 12:03:11 +0000 |
|
4 Subject: [PATCH] Initialize eventq in all cases. |
|
5 |
|
6 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3885 3789f03b-4d11-0410-bbf8-ca57d06f2519 |
|
7 --- |
|
8 unix/xserver/hw/vnc/XserverDesktop.cc | 2 ++ |
|
9 1 files changed, 2 insertions(+), 0 deletions(-) |
|
10 |
|
11 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
12 index d6fe993..533f31b 100644 |
|
13 --- a/unix/xserver/hw/vnc/XserverDesktop.cc |
|
14 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
15 @@ -203,6 +203,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, |
|
16 eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum()); |
|
17 if (!eventq) |
|
18 FatalError("Couldn't allocate eventq\n"); |
|
19 +#else |
|
20 + GetEventList(&eventq); |
|
21 #endif |
|
22 |
|
23 /* |
|
24 -- |
|
25 1.5.6.5 |
|
26 |
|
27 From 1093aa3149c24b362781ab7f19c4c63a6eb19990 Mon Sep 17 00:00:00 2001 |
|
28 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519> |
|
29 Date: Fri, 28 Aug 2009 12:04:20 +0000 |
|
30 Subject: [PATCH] Add Input.h and Input.cc and move all mouse input related code there. |
|
31 |
|
32 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3886 3789f03b-4d11-0410-bbf8-ca57d06f2519 |
|
33 --- |
|
34 unix/xserver/hw/vnc/Input.cc | 167 +++++++++++++++++++++++++++++++++ |
|
35 unix/xserver/hw/vnc/Input.h | 61 ++++++++++++ |
|
36 unix/xserver/hw/vnc/Makefile.am | 6 +- |
|
37 unix/xserver/hw/vnc/XserverDesktop.cc | 142 +--------------------------- |
|
38 unix/xserver/hw/vnc/XserverDesktop.h | 5 +- |
|
39 5 files changed, 240 insertions(+), 141 deletions(-) |
|
40 create mode 100644 unix/xserver/hw/vnc/Input.cc |
|
41 create mode 100644 unix/xserver/hw/vnc/Input.h |
|
42 |
|
43 diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc |
|
44 new file mode 100644 |
|
45 index 0000000..ca279f0 |
|
46 --- /dev/null |
|
47 +++ b/unix/xserver/hw/vnc/Input.cc |
|
48 @@ -0,0 +1,167 @@ |
|
49 +/* Copyright (C) 2009 TightVNC Team |
|
50 + * Copyright (C) 2009 Red Hat, Inc. |
|
51 + * |
|
52 + * This is free software; you can redistribute it and/or modify |
|
53 + * it under the terms of the GNU General Public License as published by |
|
54 + * the Free Software Foundation; either version 2 of the License, or |
|
55 + * (at your option) any later version. |
|
56 + * |
|
57 + * This software is distributed in the hope that it will be useful, |
|
58 + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
59 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
60 + * GNU General Public License for more details. |
|
61 + * |
|
62 + * You should have received a copy of the GNU General Public License |
|
63 + * along with this software; if not, write to the Free Software |
|
64 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
|
65 + * USA. |
|
66 + */ |
|
67 + |
|
68 +#ifdef HAVE_DIX_CONFIG_H |
|
69 +#include <dix-config.h> |
|
70 +#endif |
|
71 + |
|
72 +#include "Input.h" |
|
73 +#include "xorg-version.h" |
|
74 + |
|
75 +extern "C" { |
|
76 +#include "mi.h" |
|
77 +} |
|
78 + |
|
79 +/* Event queue is shared between all devices. */ |
|
80 +#if XORG == 15 |
|
81 +static xEvent *eventq = NULL; |
|
82 +#else |
|
83 +static EventList *eventq = NULL; |
|
84 +#endif |
|
85 + |
|
86 +static void initEventq(void) |
|
87 +{ |
|
88 + /* eventq is never free()-ed because it exists during server life. */ |
|
89 + if (eventq == NULL) { |
|
90 +#if XORG == 15 |
|
91 + eventq = (xEvent *)xcalloc(sizeof(xEvent), |
|
92 + GetMaximumEventsNum()); |
|
93 + if (!eventq) |
|
94 + FatalError("Couldn't allocate eventq\n"); |
|
95 +#else |
|
96 + GetEventList(&eventq); |
|
97 +#endif |
|
98 + } |
|
99 +} |
|
100 + |
|
101 +static void enqueueEvents(DeviceIntPtr dev, int n) |
|
102 +{ |
|
103 + int i; |
|
104 + |
|
105 + for (i = 0; i < n; i++) { |
|
106 + /* |
|
107 + * Passing arguments in global variable eventq is probably not |
|
108 + * good programming practise but in this case it is safe and |
|
109 + * clear. |
|
110 + */ |
|
111 + mieqEnqueue(dev, |
|
112 +#if XORG == 15 |
|
113 + eventq + i |
|
114 +#else |
|
115 + (eventq + i)->event |
|
116 +#endif |
|
117 + ); |
|
118 + } |
|
119 +} |
|
120 + |
|
121 +/* Pointer device pre-declarations */ |
|
122 +#define BUTTONS 5 |
|
123 +static int pointerProc(DeviceIntPtr pDevice, int onoff); |
|
124 + |
|
125 +/* Pointer device methods */ |
|
126 + |
|
127 +PointerDevice::PointerDevice(rfb::VNCServerST *_server) |
|
128 + : server(_server), oldButtonMask(0) |
|
129 +{ |
|
130 + dev = AddInputDevice( |
|
131 +#if XORG >= 16 |
|
132 + serverClient, |
|
133 +#endif |
|
134 + pointerProc, TRUE); |
|
135 + RegisterPointerDevice(dev); |
|
136 + initEventq(); |
|
137 +} |
|
138 + |
|
139 +void PointerDevice::ButtonAction(int buttonMask) |
|
140 +{ |
|
141 + int i, n; |
|
142 + |
|
143 + for (i = 0; i < BUTTONS; i++) { |
|
144 + if ((buttonMask ^ oldButtonMask) & (1 << i)) { |
|
145 + int action = (buttonMask & (1<<i)) ? |
|
146 + ButtonPress : ButtonRelease; |
|
147 + n = GetPointerEvents(eventq, dev, action, i + 1, |
|
148 + POINTER_RELATIVE, 0, 0, NULL); |
|
149 + enqueueEvents(dev, n); |
|
150 + |
|
151 + } |
|
152 + } |
|
153 + |
|
154 + oldButtonMask = buttonMask; |
|
155 +} |
|
156 + |
|
157 +void PointerDevice::Move(const rfb::Point &pos) |
|
158 +{ |
|
159 + int n, valuators[2]; |
|
160 + |
|
161 + if (pos.equals(cursorPos)) |
|
162 + return; |
|
163 + |
|
164 + valuators[0] = pos.x; |
|
165 + valuators[1] = pos.y; |
|
166 + n = GetPointerEvents(eventq, dev, MotionNotify, 0, POINTER_ABSOLUTE, 0, |
|
167 + 2, valuators); |
|
168 + enqueueEvents(dev, n); |
|
169 + |
|
170 + cursorPos = pos; |
|
171 +} |
|
172 + |
|
173 +void PointerDevice::Sync(void) |
|
174 +{ |
|
175 + if (cursorPos.equals(oldCursorPos)) |
|
176 + return; |
|
177 + |
|
178 + oldCursorPos = cursorPos; |
|
179 + server->setCursorPos(cursorPos); |
|
180 + server->tryUpdate(); |
|
181 +} |
|
182 + |
|
183 +static int pointerProc(DeviceIntPtr pDevice, int onoff) |
|
184 +{ |
|
185 + BYTE map[BUTTONS + 1]; |
|
186 + DevicePtr pDev = (DevicePtr)pDevice; |
|
187 + int i; |
|
188 + |
|
189 + switch (onoff) { |
|
190 + case DEVICE_INIT: |
|
191 + for (i = 0; i < BUTTONS + 1; i++) |
|
192 + map[i] = i; |
|
193 + |
|
194 + InitPointerDeviceStruct(pDev, map, BUTTONS, |
|
195 +#if XORG == 15 |
|
196 + GetMotionHistory, |
|
197 +#endif |
|
198 + (PtrCtrlProcPtr)NoopDDA, |
|
199 + GetMotionHistorySize(), 2); |
|
200 + break; |
|
201 + case DEVICE_ON: |
|
202 + pDev->on = TRUE; |
|
203 + break; |
|
204 + case DEVICE_OFF: |
|
205 + pDev->on = FALSE; |
|
206 + break; |
|
207 +#if 0 |
|
208 + case DEVICE_CLOSE: |
|
209 + break; |
|
210 +#endif |
|
211 + } |
|
212 + |
|
213 + return Success; |
|
214 +} |
|
215 + |
|
216 diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h |
|
217 new file mode 100644 |
|
218 index 0000000..49cedf2 |
|
219 --- /dev/null |
|
220 +++ b/unix/xserver/hw/vnc/Input.h |
|
221 @@ -0,0 +1,61 @@ |
|
222 +/* Copyright (C) 2009 TightVNC Team |
|
223 + * Copyright (C) 2009 Red Hat, Inc. |
|
224 + * |
|
225 + * This is free software; you can redistribute it and/or modify |
|
226 + * it under the terms of the GNU General Public License as published by |
|
227 + * the Free Software Foundation; either version 2 of the License, or |
|
228 + * (at your option) any later version. |
|
229 + * |
|
230 + * This software is distributed in the hope that it will be useful, |
|
231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
233 + * GNU General Public License for more details. |
|
234 + * |
|
235 + * You should have received a copy of the GNU General Public License |
|
236 + * along with this software; if not, write to the Free Software |
|
237 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
|
238 + * USA. |
|
239 + */ |
|
240 + |
|
241 +/* Make sure macro doesn't conflict with macro in include/input.h. */ |
|
242 +#ifndef INPUT_H_ |
|
243 +#define INPUT_H_ |
|
244 + |
|
245 +#ifdef HAVE_DIX_CONFIG_H |
|
246 +#include <dix-config.h> |
|
247 +#endif |
|
248 + |
|
249 +#include <rfb/VNCServerST.h> |
|
250 + |
|
251 +extern "C" { |
|
252 +#include "input.h" |
|
253 +}; |
|
254 + |
|
255 +/* Represents pointer device. */ |
|
256 +class PointerDevice { |
|
257 +public: |
|
258 + /* Create new PointerDevice instance. */ |
|
259 + PointerDevice(rfb::VNCServerST *_server); |
|
260 + |
|
261 + /* |
|
262 + * Press or release buttons. Relationship between buttonMask and |
|
263 + * buttons is specified in RFB protocol. |
|
264 + */ |
|
265 + void ButtonAction(int buttonMask); |
|
266 + |
|
267 + /* Move pointer to target location (point coords are absolute). */ |
|
268 + void Move(const rfb::Point &point); |
|
269 + |
|
270 + /* |
|
271 + * Send pointer position to clients. If not called then Move() calls |
|
272 + * won't be visible to clients. |
|
273 + */ |
|
274 + void Sync(void); |
|
275 +private: |
|
276 + rfb::VNCServerST *server; |
|
277 + DeviceIntPtr dev; |
|
278 + int oldButtonMask; |
|
279 + rfb::Point cursorPos, oldCursorPos; |
|
280 +}; |
|
281 + |
|
282 +#endif |
|
283 diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am |
|
284 index a39a10d..c2e78df 100644 |
|
285 --- a/unix/xserver/hw/vnc/Makefile.am |
|
286 +++ b/unix/xserver/hw/vnc/Makefile.am |
|
287 @@ -9,9 +9,11 @@ COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB) |
|
288 |
|
289 noinst_LTLIBRARIES = libvnccommon.la |
|
290 |
|
291 -HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h |
|
292 +HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h \ |
|
293 + Input.h |
|
294 |
|
295 -libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc |
|
296 +libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \ |
|
297 + Input.cc |
|
298 |
|
299 libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \ |
|
300 -DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(LIB_DIR) \ |
|
301 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
302 index 533f31b..58f70d9 100644 |
|
303 --- a/unix/xserver/hw/vnc/XserverDesktop.cc |
|
304 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
305 @@ -42,6 +42,7 @@ |
|
306 #include "XserverDesktop.h" |
|
307 #include "vncExtInit.h" |
|
308 #include "xorg-version.h" |
|
309 +#include "Input.h" |
|
310 |
|
311 extern "C" { |
|
312 #define public c_public |
|
313 @@ -77,7 +78,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); |
|
314 } |
|
315 |
|
316 static DeviceIntPtr vncKeyboardDevice = NULL; |
|
317 -static DeviceIntPtr vncPointerDevice = NULL; |
|
318 #if XORG == 15 |
|
319 static xEvent *eventq = NULL; |
|
320 #else |
|
321 @@ -85,7 +85,6 @@ static EventList *eventq = NULL; |
|
322 #endif |
|
323 |
|
324 static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff); |
|
325 -static int vfbMouseProc(DeviceIntPtr pDevice, int onoff); |
|
326 |
|
327 using namespace rfb; |
|
328 using namespace network; |
|
329 @@ -180,7 +179,6 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, |
|
330 listener(listener_), httpListener(httpListener_), |
|
331 cmap(0), deferredUpdateTimerSet(false), |
|
332 grabbing(false), ignoreHooks_(false), directFbptr(true), |
|
333 - oldButtonMask(0), |
|
334 queryConnectId(0) |
|
335 { |
|
336 format = pf; |
|
337 @@ -221,14 +219,7 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, |
|
338 RegisterKeyboardDevice(vncKeyboardDevice); |
|
339 } |
|
340 |
|
341 - if (vncPointerDevice == NULL) { |
|
342 - vncPointerDevice = AddInputDevice( |
|
343 -#if XORG >= 16 |
|
344 - serverClient, |
|
345 -#endif |
|
346 - vfbMouseProc, TRUE); |
|
347 - RegisterPointerDevice(vncPointerDevice); |
|
348 - } |
|
349 + pointerDevice = new PointerDevice(server); |
|
350 } |
|
351 |
|
352 XserverDesktop::~XserverDesktop() |
|
353 @@ -237,6 +228,7 @@ XserverDesktop::~XserverDesktop() |
|
354 delete [] data; |
|
355 TimerFree(deferredUpdateTimer); |
|
356 TimerFree(dummyTimer); |
|
357 + delete pointerDevice; |
|
358 delete httpServer; |
|
359 delete server; |
|
360 } |
|
361 @@ -555,43 +547,9 @@ void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy) |
|
362 } |
|
363 } |
|
364 |
|
365 -void XserverDesktop::positionCursor() |
|
366 -{ |
|
367 - if (!cursorPos.equals(oldCursorPos)) { |
|
368 - oldCursorPos = cursorPos; |
|
369 - (*pScreen->SetCursorPosition) ( |
|
370 -#if XORG >= 16 |
|
371 - vncPointerDevice, |
|
372 -#endif |
|
373 - pScreen, cursorPos.x, cursorPos.y, FALSE); |
|
374 - server->setCursorPos(cursorPos); |
|
375 - server->tryUpdate(); |
|
376 - } |
|
377 -} |
|
378 - |
|
379 void XserverDesktop::blockHandler(fd_set* fds) |
|
380 { |
|
381 try { |
|
382 -#if XORG == 15 |
|
383 - ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen; |
|
384 -#else |
|
385 - ScreenPtr screenWithCursor = |
|
386 - GetCurrentRootWindow(vncPointerDevice)->drawable.pScreen; |
|
387 -#endif |
|
388 - if (screenWithCursor == pScreen) { |
|
389 - int x, y; |
|
390 - GetSpritePosition( |
|
391 -#if XORG >= 16 |
|
392 - vncPointerDevice, |
|
393 -#endif |
|
394 - &x, &y); |
|
395 - if (x != cursorPos.x || y != cursorPos.y) { |
|
396 - cursorPos = oldCursorPos = Point(x, y); |
|
397 - server->setCursorPos(cursorPos); |
|
398 - server->tryUpdate(); |
|
399 - } |
|
400 - } |
|
401 - |
|
402 if (listener) |
|
403 FD_SET(listener->getFd(), fds); |
|
404 if (httpListener) |
|
405 @@ -678,7 +636,7 @@ void XserverDesktop::wakeupHandler(fd_set* fds, int nfds) |
|
406 } |
|
407 } |
|
408 |
|
409 - positionCursor(); |
|
410 + pointerDevice->Sync(); |
|
411 } |
|
412 |
|
413 int timeout = server->checkTimeouts(); |
|
414 @@ -737,63 +695,8 @@ void XserverDesktop::approveConnection(void* opaqueId, bool accept, |
|
415 |
|
416 void XserverDesktop::pointerEvent(const Point& pos, int buttonMask) |
|
417 { |
|
418 - int i, j, n, valuators[2]; |
|
419 - |
|
420 - // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6 |
|
421 - // for S3), so we delay calling it until positionCursor() is called at the |
|
422 - // end of processing a load of RFB. |
|
423 - //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE); |
|
424 - |
|
425 - NewCurrentScreen( |
|
426 -#if XORG >= 16 |
|
427 - vncPointerDevice, |
|
428 -#endif |
|
429 - pScreen, pos.x, pos.y); |
|
430 - |
|
431 - if (!pos.equals(cursorPos)) { |
|
432 - valuators[0] = pos.x; |
|
433 - valuators[1] = pos.y; |
|
434 - |
|
435 -#if XORG >= 16 |
|
436 - GetEventList(&eventq); |
|
437 -#endif |
|
438 - n = GetPointerEvents (eventq, vncPointerDevice, MotionNotify, 0, |
|
439 - POINTER_ABSOLUTE, 0, 2, valuators); |
|
440 - |
|
441 - for (i = 0; i < n; i++) { |
|
442 - mieqEnqueue (vncPointerDevice, |
|
443 -#if XORG == 15 |
|
444 - eventq + i |
|
445 -#else |
|
446 - (eventq + i)->event |
|
447 -#endif |
|
448 - ); |
|
449 - } |
|
450 - } |
|
451 - |
|
452 - for (i = 0; i < 5; i++) { |
|
453 - if ((buttonMask ^ oldButtonMask) & (1<<i)) { |
|
454 - // Do not use the pointer mapping. Treat VNC buttons as logical |
|
455 - // buttons. |
|
456 - n = GetPointerEvents (eventq, vncPointerDevice, |
|
457 - (buttonMask & (1<<i)) ? |
|
458 - ButtonPress : ButtonRelease, |
|
459 - i + 1, POINTER_RELATIVE, 0, 0, NULL); |
|
460 - |
|
461 - for (j = 0; j < n; j++) { |
|
462 - mieqEnqueue (vncPointerDevice, |
|
463 -#if XORG == 15 |
|
464 - eventq + j |
|
465 -#else |
|
466 - (eventq + j)->event |
|
467 -#endif |
|
468 - ); |
|
469 - } |
|
470 - } |
|
471 - } |
|
472 - |
|
473 - cursorPos = pos; |
|
474 - oldButtonMask = buttonMask; |
|
475 + pointerDevice->Move(pos); |
|
476 + pointerDevice->ButtonAction(buttonMask); |
|
477 } |
|
478 |
|
479 void XserverDesktop::clientCutText(const char* str, int len) |
|
480 @@ -1481,36 +1384,3 @@ static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff) |
|
481 return Success; |
|
482 } |
|
483 |
|
484 -static int vfbMouseProc(DeviceIntPtr pDevice, int onoff) |
|
485 -{ |
|
486 - BYTE map[6]; |
|
487 - DevicePtr pDev = (DevicePtr)pDevice; |
|
488 - |
|
489 - switch (onoff) |
|
490 - { |
|
491 - case DEVICE_INIT: |
|
492 - map[1] = 1; |
|
493 - map[2] = 2; |
|
494 - map[3] = 3; |
|
495 - map[4] = 4; |
|
496 - map[5] = 5; |
|
497 - InitPointerDeviceStruct(pDev, map, 5, |
|
498 -#if XORG == 15 |
|
499 - GetMotionHistory, |
|
500 -#endif |
|
501 - (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2); |
|
502 - break; |
|
503 - |
|
504 - case DEVICE_ON: |
|
505 - pDev->on = TRUE; |
|
506 - break; |
|
507 - |
|
508 - case DEVICE_OFF: |
|
509 - pDev->on = FALSE; |
|
510 - break; |
|
511 - |
|
512 - case DEVICE_CLOSE: |
|
513 - break; |
|
514 - } |
|
515 - return Success; |
|
516 -} |
|
517 diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h |
|
518 index 7729d3f..9f300f5 100644 |
|
519 --- a/unix/xserver/hw/vnc/XserverDesktop.h |
|
520 +++ b/unix/xserver/hw/vnc/XserverDesktop.h |
|
521 @@ -32,6 +32,7 @@ |
|
522 #include <rfb/Configuration.h> |
|
523 #include <rfb/VNCServerST.h> |
|
524 #include <rdr/SubstitutingInStream.h> |
|
525 +#include "Input.h" |
|
526 |
|
527 extern "C" { |
|
528 #define class c_class |
|
529 @@ -68,7 +69,6 @@ public: |
|
530 void setCursor(CursorPtr cursor); |
|
531 void add_changed(RegionPtr reg); |
|
532 void add_copied(RegionPtr dst, int dx, int dy); |
|
533 - void positionCursor(); |
|
534 void ignoreHooks(bool b) { ignoreHooks_ = b; } |
|
535 void blockHandler(fd_set* fds); |
|
536 void wakeupHandler(fd_set* fds, int nfds); |
|
537 @@ -122,6 +122,7 @@ private: |
|
538 pointer arg); |
|
539 void deferUpdate(); |
|
540 ScreenPtr pScreen; |
|
541 + PointerDevice *pointerDevice; |
|
542 OsTimerPtr deferredUpdateTimer, dummyTimer; |
|
543 rfb::VNCServerST* server; |
|
544 rfb::HTTPServer* httpServer; |
|
545 @@ -133,8 +134,6 @@ private: |
|
546 bool grabbing; |
|
547 bool ignoreHooks_; |
|
548 bool directFbptr; |
|
549 - int oldButtonMask; |
|
550 - rfb::Point cursorPos, oldCursorPos; |
|
551 |
|
552 void* queryConnectId; |
|
553 rfb::CharArray queryConnectAddress; |
|
554 -- |
|
555 1.5.6.5 |
|
556 |
|
557 From 845dbbfbb6a2c0e1a4981920121935febe7c0a50 Mon Sep 17 00:00:00 2001 |
|
558 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519> |
|
559 Date: Fri, 28 Aug 2009 12:05:24 +0000 |
|
560 Subject: [PATCH] Move keyboard input related code to Input.h and Input.cc. |
|
561 |
|
562 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3887 3789f03b-4d11-0410-bbf8-ca57d06f2519 |
|
563 --- |
|
564 unix/xserver/hw/vnc/Input.cc | 606 ++++++++++++++++++++++++++++++++- |
|
565 unix/xserver/hw/vnc/Input.h | 13 + |
|
566 unix/xserver/hw/vnc/XserverDesktop.cc | 589 +------------------------------- |
|
567 unix/xserver/hw/vnc/XserverDesktop.h | 1 + |
|
568 4 files changed, 622 insertions(+), 587 deletions(-) |
|
569 |
|
570 diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc |
|
571 index ca279f0..478240c 100644 |
|
572 --- a/unix/xserver/hw/vnc/Input.cc |
|
573 +++ b/unix/xserver/hw/vnc/Input.cc |
|
574 @@ -21,13 +21,49 @@ |
|
575 #include <dix-config.h> |
|
576 #endif |
|
577 |
|
578 +#include <rfb/LogWriter.h> |
|
579 #include "Input.h" |
|
580 #include "xorg-version.h" |
|
581 +#include "vncExtInit.h" |
|
582 |
|
583 extern "C" { |
|
584 +#define public c_public |
|
585 +#define class c_class |
|
586 +#include "inputstr.h" |
|
587 #include "mi.h" |
|
588 +#ifndef XKB_IN_SERVER |
|
589 +#define XKB_IN_SERVER |
|
590 +#endif |
|
591 +#ifdef XKB |
|
592 +/* |
|
593 + * This include is needed to use XkbConvertCase instead of XConvertCase even if |
|
594 + * we don't use XKB extension. |
|
595 + */ |
|
596 +#include <xkbsrv.h> |
|
597 +#endif |
|
598 +#if XORG >= 16 |
|
599 +#include "exevents.h" |
|
600 +extern void |
|
601 +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); |
|
602 +#endif |
|
603 +#include <X11/keysym.h> |
|
604 +#include <X11/Xutil.h> |
|
605 +#undef public |
|
606 +#undef class |
|
607 } |
|
608 |
|
609 +using namespace rdr; |
|
610 +using namespace rfb; |
|
611 + |
|
612 +static LogWriter vlog("Input"); |
|
613 + |
|
614 +#define BUTTONS 5 |
|
615 +static int pointerProc(DeviceIntPtr pDevice, int onoff); |
|
616 + |
|
617 +static int keyboardProc(DeviceIntPtr pDevice, int onoff); |
|
618 +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col); |
|
619 +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); |
|
620 + |
|
621 /* Event queue is shared between all devices. */ |
|
622 #if XORG == 15 |
|
623 static xEvent *eventq = NULL; |
|
624 @@ -70,10 +106,6 @@ static void enqueueEvents(DeviceIntPtr dev, int n) |
|
625 } |
|
626 } |
|
627 |
|
628 -/* Pointer device pre-declarations */ |
|
629 -#define BUTTONS 5 |
|
630 -static int pointerProc(DeviceIntPtr pDevice, int onoff); |
|
631 - |
|
632 /* Pointer device methods */ |
|
633 |
|
634 PointerDevice::PointerDevice(rfb::VNCServerST *_server) |
|
635 @@ -165,3 +197,569 @@ static int pointerProc(DeviceIntPtr pDevice, int onoff) |
|
636 return Success; |
|
637 } |
|
638 |
|
639 +/* KeyboardDevice methods */ |
|
640 + |
|
641 +KeyboardDevice::KeyboardDevice(void) |
|
642 +{ |
|
643 + dev = AddInputDevice( |
|
644 +#if XORG >= 16 |
|
645 + serverClient, |
|
646 +#endif |
|
647 + keyboardProc, TRUE); |
|
648 + RegisterKeyboardDevice(dev); |
|
649 + initEventq(); |
|
650 +} |
|
651 + |
|
652 +#define IS_PRESSED(keyc, keycode) \ |
|
653 + ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) |
|
654 + |
|
655 +/* |
|
656 + * ModifierState is a class which helps simplify generating a "fake" press or |
|
657 + * release of shift, ctrl, alt, etc. An instance of the class is created for |
|
658 + * every modifier which may need to be pressed or released. Then either |
|
659 + * press() or release() may be called to make sure that the corresponding keys |
|
660 + * are in the right state. The destructor of the class automatically reverts |
|
661 + * to the previous state. Each modifier may have multiple keys associated with |
|
662 + * it, so in the case of a fake release, this may involve releasing more than |
|
663 + * one key. |
|
664 + */ |
|
665 + |
|
666 +class ModifierState { |
|
667 +public: |
|
668 + ModifierState(DeviceIntPtr _dev, int _modIndex) |
|
669 + : modIndex(_modIndex), nKeys(0), keys(0), pressed(false), |
|
670 + dev(_dev) {} |
|
671 + |
|
672 + ~ModifierState() |
|
673 + { |
|
674 + for (int i = 0; i < nKeys; i++) |
|
675 + generateXKeyEvent(keys[i], !pressed); |
|
676 + delete [] keys; |
|
677 + } |
|
678 + |
|
679 + void press() |
|
680 + { |
|
681 + KeyClassPtr keyc = dev->key; |
|
682 + if (!(keyc->state & (1 << modIndex))) { |
|
683 + int index = modIndex * keyc->maxKeysPerModifier; |
|
684 + tempKeyEvent(keyc->modifierKeyMap[index], true); |
|
685 + pressed = true; |
|
686 + } |
|
687 + } |
|
688 + |
|
689 + void release() |
|
690 + { |
|
691 + KeyClassPtr keyc = dev->key; |
|
692 + if ((keyc->state & (1 << modIndex)) == 0) |
|
693 + return; |
|
694 + |
|
695 + for (int k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
696 + int index = modIndex * keyc->maxKeysPerModifier + k; |
|
697 + int keycode = keyc->modifierKeyMap[index]; |
|
698 + if (keycode && IS_PRESSED(keyc, keycode)) |
|
699 + tempKeyEvent(keycode, false); |
|
700 + } |
|
701 + } |
|
702 + |
|
703 +private: |
|
704 + void tempKeyEvent(int keycode, bool down) |
|
705 + { |
|
706 + if (keycode) { |
|
707 + if (!keys) keys = new int[dev->key->maxKeysPerModifier]; |
|
708 + keys[nKeys++] = keycode; |
|
709 + generateXKeyEvent(keycode, down); |
|
710 + } |
|
711 + } |
|
712 + |
|
713 + void generateXKeyEvent(int keycode, bool down) |
|
714 + { |
|
715 + int n, action; |
|
716 + |
|
717 + action = down ? KeyPress : KeyRelease; |
|
718 + n = GetKeyboardEvents(eventq, dev, action, keycode); |
|
719 + enqueueEvents(dev, n); |
|
720 + |
|
721 + vlog.debug("fake keycode %d %s", keycode, |
|
722 + down ? "down" : "up"); |
|
723 + } |
|
724 + |
|
725 + int modIndex; |
|
726 + int nKeys; |
|
727 + int *keys; |
|
728 + bool pressed; |
|
729 + DeviceIntPtr dev; |
|
730 +}; |
|
731 + |
|
732 + |
|
733 +/* altKeysym is a table of alternative keysyms which have the same meaning. */ |
|
734 + |
|
735 +static struct altKeysym_t { |
|
736 + KeySym a, b; |
|
737 +} altKeysym[] = { |
|
738 + { XK_Shift_L, XK_Shift_R }, |
|
739 + { XK_Control_L, XK_Control_R }, |
|
740 + { XK_Meta_L, XK_Meta_R }, |
|
741 + { XK_Alt_L, XK_Alt_R }, |
|
742 + { XK_Super_L, XK_Super_R }, |
|
743 + { XK_Hyper_L, XK_Hyper_R }, |
|
744 + { XK_KP_Space, XK_space }, |
|
745 + { XK_KP_Tab, XK_Tab }, |
|
746 + { XK_KP_Enter, XK_Return }, |
|
747 + { XK_KP_F1, XK_F1 }, |
|
748 + { XK_KP_F2, XK_F2 }, |
|
749 + { XK_KP_F3, XK_F3 }, |
|
750 + { XK_KP_F4, XK_F4 }, |
|
751 + { XK_KP_Home, XK_Home }, |
|
752 + { XK_KP_Left, XK_Left }, |
|
753 + { XK_KP_Up, XK_Up }, |
|
754 + { XK_KP_Right, XK_Right }, |
|
755 + { XK_KP_Down, XK_Down }, |
|
756 + { XK_KP_Page_Up, XK_Page_Up }, |
|
757 + { XK_KP_Page_Down, XK_Page_Down }, |
|
758 + { XK_KP_End, XK_End }, |
|
759 + { XK_KP_Begin, XK_Begin }, |
|
760 + { XK_KP_Insert, XK_Insert }, |
|
761 + { XK_KP_Delete, XK_Delete }, |
|
762 + { XK_KP_Equal, XK_equal }, |
|
763 + { XK_KP_Multiply, XK_asterisk }, |
|
764 + { XK_KP_Add, XK_plus }, |
|
765 + { XK_KP_Separator, XK_comma }, |
|
766 + { XK_KP_Subtract, XK_minus }, |
|
767 + { XK_KP_Decimal, XK_period }, |
|
768 + { XK_KP_Divide, XK_slash }, |
|
769 + { XK_KP_0, XK_0 }, |
|
770 + { XK_KP_1, XK_1 }, |
|
771 + { XK_KP_2, XK_2 }, |
|
772 + { XK_KP_3, XK_3 }, |
|
773 + { XK_KP_4, XK_4 }, |
|
774 + { XK_KP_5, XK_5 }, |
|
775 + { XK_KP_6, XK_6 }, |
|
776 + { XK_KP_7, XK_7 }, |
|
777 + { XK_KP_8, XK_8 }, |
|
778 + { XK_KP_9, XK_9 }, |
|
779 +}; |
|
780 + |
|
781 +/* |
|
782 + * keyEvent() - work out the best keycode corresponding to the keysym sent by |
|
783 + * the viewer. This is non-trivial because we can't assume much about the |
|
784 + * local keyboard layout. We must also find out which column of the keyboard |
|
785 + * mapping the keysym is in, and alter the shift state appropriately. Column 0 |
|
786 + * means both shift and "mode_switch" (AltGr) must be released, column 1 means |
|
787 + * shift must be pressed and mode_switch released, column 2 means shift must be |
|
788 + * released and mode_switch pressed, and column 3 means both shift and |
|
789 + * mode_switch must be pressed. |
|
790 + * |
|
791 + * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org |
|
792 + * version. Quick explanation of that "magic": |
|
793 + * |
|
794 + * 1.5 |
|
795 + * - has only one core keyboard so we have to keep core keyboard mapping |
|
796 + * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard() |
|
797 + * |
|
798 + * 1.6 (aka MPX - Multi pointer X) |
|
799 + * - multiple master devices (= core devices) exists, keep vncKeyboardDevice |
|
800 + * synchronized with proper master device |
|
801 + */ |
|
802 + |
|
803 +void KeyboardDevice::keyEvent(rdr::U32 keysym, bool down) |
|
804 +{ |
|
805 + DeviceIntPtr master; |
|
806 + KeyClassPtr keyc = dev->key; |
|
807 + KeySymsPtr keymap = &keyc->curKeySyms; |
|
808 + KeySym *map = keymap->map; |
|
809 + KeyCode minKeyCode = keymap->minKeyCode; |
|
810 + KeyCode maxKeyCode = keymap->maxKeyCode; |
|
811 + int mapWidth = keymap->mapWidth; |
|
812 + unsigned int i, n; |
|
813 + int j, k, action; |
|
814 + |
|
815 + if (keysym == XK_Caps_Lock) { |
|
816 + vlog.debug("Ignoring caps lock"); |
|
817 + return; |
|
818 + } |
|
819 + |
|
820 + /* find which modifier Mode_switch is on. */ |
|
821 + int modeSwitchMapIndex = 0; |
|
822 + for (i = 3; i < 8; i++) { |
|
823 + for (k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
824 + int index = i * keyc->maxKeysPerModifier + k; |
|
825 + int keycode = keyc->modifierKeyMap[index]; |
|
826 + |
|
827 + if (keycode == 0) |
|
828 + continue; |
|
829 + |
|
830 + for (j = 0; j < mapWidth; j++) { |
|
831 + if (map[(keycode - minKeyCode) * mapWidth + j] |
|
832 + == XK_Mode_switch) { |
|
833 + modeSwitchMapIndex = i; |
|
834 + goto ModeSwitchFound; |
|
835 + } |
|
836 + } |
|
837 + } |
|
838 + } |
|
839 +ModeSwitchFound: |
|
840 + |
|
841 + int col = 0; |
|
842 + if ((keyc->state & (1 << ShiftMapIndex)) != 0) |
|
843 + col |= 1; |
|
844 + if (modeSwitchMapIndex != 0 && |
|
845 + ((keyc->state & (1 << modeSwitchMapIndex))) != 0) |
|
846 + col |= 2; |
|
847 + |
|
848 + int kc = KeysymToKeycode(keymap, keysym, &col); |
|
849 + |
|
850 + /* |
|
851 + * Sort out the "shifted Tab" mess. If we are sent a shifted Tab, |
|
852 + * generate a local shifted Tab regardless of what the "shifted Tab" |
|
853 + * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or |
|
854 + * HP's private BackTab keysym, and quite possibly some others too). |
|
855 + * We never get ISO_Left_Tab here because it's already been translated |
|
856 + * in VNCSConnectionST. |
|
857 + */ |
|
858 + if (keysym == XK_Tab && ((keyc->state & (1 << ShiftMapIndex))) != 0) |
|
859 + col |= 1; |
|
860 + |
|
861 + if (kc == 0) { |
|
862 + /* |
|
863 + * Not a direct match in the local keyboard mapping. Check for |
|
864 + * alternative keysyms with the same meaning. |
|
865 + */ |
|
866 + for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { |
|
867 + if (keysym == altKeysym[i].a) |
|
868 + kc = KeysymToKeycode(keymap, altKeysym[i].b, |
|
869 + &col); |
|
870 + else if (keysym == altKeysym[i].b) |
|
871 + kc = KeysymToKeycode(keymap, altKeysym[i].a, |
|
872 + &col); |
|
873 + if (kc) |
|
874 + break; |
|
875 + } |
|
876 + } |
|
877 + |
|
878 + if (kc == 0) { |
|
879 + /* Dynamically add a new key to the keyboard mapping. */ |
|
880 + for (kc = maxKeyCode; kc >= minKeyCode; kc--) { |
|
881 + if (map[(kc - minKeyCode) * mapWidth] != 0) |
|
882 + continue; |
|
883 + |
|
884 + map[(kc - minKeyCode) * mapWidth] = keysym; |
|
885 + col = 0; |
|
886 + |
|
887 + vlog.info("Added unknown keysym 0x%x to keycode %d", |
|
888 + keysym, kc); |
|
889 +#if XORG == 15 |
|
890 + master = inputInfo.keyboard; |
|
891 +#else |
|
892 + master = dev->u.master; |
|
893 +#endif |
|
894 + void *slave = dixLookupPrivate(&master->devPrivates, |
|
895 + CoreDevicePrivateKey); |
|
896 + if (dev == slave) { |
|
897 + dixSetPrivate(&master->devPrivates, |
|
898 + CoreDevicePrivateKey, NULL); |
|
899 +#if XORG == 15 |
|
900 + SwitchCoreKeyboard(dev); |
|
901 +#else |
|
902 + CopyKeyClass(dev, master); |
|
903 +#endif |
|
904 + } |
|
905 + break; |
|
906 + } |
|
907 + } |
|
908 + |
|
909 + if (kc < minKeyCode) { |
|
910 + vlog.info("Keyboard mapping full - ignoring unknown keysym " |
|
911 + "0x%x",keysym); |
|
912 + return; |
|
913 + } |
|
914 + |
|
915 + /* |
|
916 + * See if it's a modifier key. If so, then don't do any auto-repeat, |
|
917 + * because the X server will translate each press into a release |
|
918 + * followed by a press. |
|
919 + */ |
|
920 + for (i = 0; i < 8; i++) { |
|
921 + for (k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
922 + int index = i * keyc->maxKeysPerModifier + k; |
|
923 + if (kc == keyc->modifierKeyMap[index] && |
|
924 + IS_PRESSED(keyc,kc) && down) |
|
925 + return; |
|
926 + } |
|
927 + } |
|
928 + |
|
929 + ModifierState shift(dev, ShiftMapIndex); |
|
930 + ModifierState modeSwitch(dev, modeSwitchMapIndex); |
|
931 + if (down) { |
|
932 + if (col & 1) |
|
933 + shift.press(); |
|
934 + else |
|
935 + shift.release(); |
|
936 + if (modeSwitchMapIndex) { |
|
937 + if (col & 2) |
|
938 + modeSwitch.press(); |
|
939 + else |
|
940 + modeSwitch.release(); |
|
941 + } |
|
942 + } |
|
943 + |
|
944 + vlog.debug("keycode %d %s", kc, down ? "down" : "up"); |
|
945 + action = down ? KeyPress : KeyRelease; |
|
946 + n = GetKeyboardEvents(eventq, dev, action, kc); |
|
947 + enqueueEvents(dev, n); |
|
948 +} |
|
949 + |
|
950 +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) |
|
951 +{ |
|
952 + int per = keymap->mapWidth; |
|
953 + KeySym *syms; |
|
954 + KeySym lsym, usym; |
|
955 + |
|
956 + if ((col < 0) || ((col >= per) && (col > 3)) || |
|
957 + (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) |
|
958 + return NoSymbol; |
|
959 + |
|
960 + syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; |
|
961 + if (col >= 4) |
|
962 + return syms[col]; |
|
963 + |
|
964 + if (col > 1) { |
|
965 + while ((per > 2) && (syms[per - 1] == NoSymbol)) |
|
966 + per--; |
|
967 + if (per < 3) |
|
968 + col -= 2; |
|
969 + } |
|
970 + |
|
971 + if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { |
|
972 + XConvertCase(syms[col&~1], &lsym, &usym); |
|
973 + if (!(col & 1)) |
|
974 + return lsym; |
|
975 + /* |
|
976 + * I'm commenting out this logic because it's incorrect even |
|
977 + * though it was copied from the Xlib sources. The X protocol |
|
978 + * book quite clearly states that where a group consists of |
|
979 + * element 1 being a non-alphabetic keysym and element 2 being |
|
980 + * NoSymbol that you treat the second element as being the |
|
981 + * same as the first. This also tallies with the behaviour |
|
982 + * produced by the installed Xlib on my linux box (I believe |
|
983 + * this is because it uses some XKB code rather than the |
|
984 + * original Xlib code - compare XKBBind.c with KeyBind.c in |
|
985 + * lib/X11). |
|
986 + */ |
|
987 +#if 0 |
|
988 + else if (usym == lsym) |
|
989 + return NoSymbol; |
|
990 +#endif |
|
991 + else |
|
992 + return usym; |
|
993 + } |
|
994 + |
|
995 + return syms[col]; |
|
996 +} |
|
997 + |
|
998 +/* |
|
999 + * KeysymToKeycode() - find the keycode and column corresponding to the given |
|
1000 + * keysym. The value of col passed in should be the column determined from the |
|
1001 + * current shift state. If the keysym can be found in that column we prefer |
|
1002 + * that to finding it in a different column (which would require fake events to |
|
1003 + * alter the shift state). |
|
1004 + */ |
|
1005 +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) |
|
1006 +{ |
|
1007 + int i, j; |
|
1008 + |
|
1009 + j = *col; |
|
1010 + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { |
|
1011 + if (KeyCodetoKeySym(keymap, i, j) == ks) |
|
1012 + return i; |
|
1013 + } |
|
1014 + |
|
1015 + for (j = 0; j < keymap->mapWidth; j++) { |
|
1016 + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { |
|
1017 + if (KeyCodetoKeySym(keymap, i, j) == ks) { |
|
1018 + *col = j; |
|
1019 + return i; |
|
1020 + } |
|
1021 + } |
|
1022 + } |
|
1023 + |
|
1024 + return 0; |
|
1025 +} |
|
1026 + |
|
1027 +/* Fairly standard US PC Keyboard */ |
|
1028 + |
|
1029 +#define MIN_KEY 8 |
|
1030 +#define MAX_KEY 255 |
|
1031 +#define MAP_LEN (MAX_KEY - MIN_KEY + 1) |
|
1032 +#define KEYSYMS_PER_KEY 2 |
|
1033 +KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = { |
|
1034 + NoSymbol, NoSymbol, |
|
1035 + XK_Escape, NoSymbol, |
|
1036 + XK_1, XK_exclam, |
|
1037 + XK_2, XK_at, |
|
1038 + XK_3, XK_numbersign, |
|
1039 + XK_4, XK_dollar, |
|
1040 + XK_5, XK_percent, |
|
1041 + XK_6, XK_asciicircum, |
|
1042 + XK_7, XK_ampersand, |
|
1043 + XK_8, XK_asterisk, |
|
1044 + XK_9, XK_parenleft, |
|
1045 + XK_0, XK_parenright, |
|
1046 + XK_minus, XK_underscore, |
|
1047 + XK_equal, XK_plus, |
|
1048 + XK_BackSpace, NoSymbol, |
|
1049 + XK_Tab, NoSymbol, |
|
1050 + XK_q, XK_Q, |
|
1051 + XK_w, XK_W, |
|
1052 + XK_e, XK_E, |
|
1053 + XK_r, XK_R, |
|
1054 + XK_t, XK_T, |
|
1055 + XK_y, XK_Y, |
|
1056 + XK_u, XK_U, |
|
1057 + XK_i, XK_I, |
|
1058 + XK_o, XK_O, |
|
1059 + XK_p, XK_P, |
|
1060 + XK_bracketleft, XK_braceleft, |
|
1061 + XK_bracketright, XK_braceright, |
|
1062 + XK_Return, NoSymbol, |
|
1063 + XK_Control_L, NoSymbol, |
|
1064 + XK_a, XK_A, |
|
1065 + XK_s, XK_S, |
|
1066 + XK_d, XK_D, |
|
1067 + XK_f, XK_F, |
|
1068 + XK_g, XK_G, |
|
1069 + XK_h, XK_H, |
|
1070 + XK_j, XK_J, |
|
1071 + XK_k, XK_K, |
|
1072 + XK_l, XK_L, |
|
1073 + XK_semicolon, XK_colon, |
|
1074 + XK_apostrophe, XK_quotedbl, |
|
1075 + XK_grave, XK_asciitilde, |
|
1076 + XK_Shift_L, NoSymbol, |
|
1077 + XK_backslash, XK_bar, |
|
1078 + XK_z, XK_Z, |
|
1079 + XK_x, XK_X, |
|
1080 + XK_c, XK_C, |
|
1081 + XK_v, XK_V, |
|
1082 + XK_b, XK_B, |
|
1083 + XK_n, XK_N, |
|
1084 + XK_m, XK_M, |
|
1085 + XK_comma, XK_less, |
|
1086 + XK_period, XK_greater, |
|
1087 + XK_slash, XK_question, |
|
1088 + XK_Shift_R, NoSymbol, |
|
1089 + XK_KP_Multiply, NoSymbol, |
|
1090 + XK_Alt_L, XK_Meta_L, |
|
1091 + XK_space, NoSymbol, |
|
1092 + /* XK_Caps_Lock */ NoSymbol, NoSymbol, |
|
1093 + XK_F1, NoSymbol, |
|
1094 + XK_F2, NoSymbol, |
|
1095 + XK_F3, NoSymbol, |
|
1096 + XK_F4, NoSymbol, |
|
1097 + XK_F5, NoSymbol, |
|
1098 + XK_F6, NoSymbol, |
|
1099 + XK_F7, NoSymbol, |
|
1100 + XK_F8, NoSymbol, |
|
1101 + XK_F9, NoSymbol, |
|
1102 + XK_F10, NoSymbol, |
|
1103 + XK_Num_Lock, XK_Pointer_EnableKeys, |
|
1104 + XK_Scroll_Lock, NoSymbol, |
|
1105 + XK_KP_Home, XK_KP_7, |
|
1106 + XK_KP_Up, XK_KP_8, |
|
1107 + XK_KP_Prior, XK_KP_9, |
|
1108 + XK_KP_Subtract, NoSymbol, |
|
1109 + XK_KP_Left, XK_KP_4, |
|
1110 + XK_KP_Begin, XK_KP_5, |
|
1111 + XK_KP_Right, XK_KP_6, |
|
1112 + XK_KP_Add, NoSymbol, |
|
1113 + XK_KP_End, XK_KP_1, |
|
1114 + XK_KP_Down, XK_KP_2, |
|
1115 + XK_KP_Next, XK_KP_3, |
|
1116 + XK_KP_Insert, XK_KP_0, |
|
1117 + XK_KP_Delete, XK_KP_Decimal, |
|
1118 + NoSymbol, NoSymbol, |
|
1119 + NoSymbol, NoSymbol, |
|
1120 + NoSymbol, NoSymbol, |
|
1121 + XK_F11, NoSymbol, |
|
1122 + XK_F12, NoSymbol, |
|
1123 + XK_Home, NoSymbol, |
|
1124 + XK_Up, NoSymbol, |
|
1125 + XK_Prior, NoSymbol, |
|
1126 + XK_Left, NoSymbol, |
|
1127 + NoSymbol, NoSymbol, |
|
1128 + XK_Right, NoSymbol, |
|
1129 + XK_End, NoSymbol, |
|
1130 + XK_Down, NoSymbol, |
|
1131 + XK_Next, NoSymbol, |
|
1132 + XK_Insert, NoSymbol, |
|
1133 + XK_Delete, NoSymbol, |
|
1134 + XK_KP_Enter, NoSymbol, |
|
1135 + XK_Control_R, NoSymbol, |
|
1136 + XK_Pause, XK_Break, |
|
1137 + XK_Print, XK_Execute, |
|
1138 + XK_KP_Divide, NoSymbol, |
|
1139 + XK_Alt_R, XK_Meta_R, |
|
1140 +}; |
|
1141 + |
|
1142 +static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) |
|
1143 +{ |
|
1144 + int i; |
|
1145 + |
|
1146 + for (i = 0; i < MAP_LENGTH; i++) |
|
1147 + pModMap[i] = NoSymbol; |
|
1148 + |
|
1149 + for (i = 0; i < MAP_LEN; i++) { |
|
1150 + if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock) |
|
1151 + pModMap[i + MIN_KEY] = LockMask; |
|
1152 + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L || |
|
1153 + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R) |
|
1154 + pModMap[i + MIN_KEY] = ShiftMask; |
|
1155 + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L || |
|
1156 + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) |
|
1157 + pModMap[i + MIN_KEY] = ControlMask; |
|
1158 + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L || |
|
1159 + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R) |
|
1160 + pModMap[i + MIN_KEY] = Mod1Mask; |
|
1161 + } |
|
1162 + |
|
1163 + pKeySyms->minKeyCode = MIN_KEY; |
|
1164 + pKeySyms->maxKeyCode = MAX_KEY; |
|
1165 + pKeySyms->mapWidth = KEYSYMS_PER_KEY; |
|
1166 + pKeySyms->map = keyboardMap; |
|
1167 + |
|
1168 + return TRUE; |
|
1169 +} |
|
1170 + |
|
1171 +static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl, |
|
1172 + int class_) |
|
1173 +{ |
|
1174 + if (percent > 0) |
|
1175 + vncBell(); |
|
1176 +} |
|
1177 + |
|
1178 +static int keyboardProc(DeviceIntPtr pDevice, int onoff) |
|
1179 +{ |
|
1180 + KeySymsRec keySyms; |
|
1181 + CARD8 modMap[MAP_LENGTH]; |
|
1182 + DevicePtr pDev = (DevicePtr)pDevice; |
|
1183 + |
|
1184 + switch (onoff) { |
|
1185 + case DEVICE_INIT: |
|
1186 + GetMappings(&keySyms, modMap); |
|
1187 + InitKeyboardDeviceStruct(pDev, &keySyms, modMap, keyboardBell, |
|
1188 + (KbdCtrlProcPtr)NoopDDA); |
|
1189 + break; |
|
1190 + case DEVICE_ON: |
|
1191 + pDev->on = TRUE; |
|
1192 + break; |
|
1193 + case DEVICE_OFF: |
|
1194 + pDev->on = FALSE; |
|
1195 + break; |
|
1196 +#if 0 |
|
1197 + case DEVICE_CLOSE: |
|
1198 + break; |
|
1199 +#endif |
|
1200 + } |
|
1201 + |
|
1202 + return Success; |
|
1203 +} |
|
1204 + |
|
1205 diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h |
|
1206 index 49cedf2..1bfec92 100644 |
|
1207 --- a/unix/xserver/hw/vnc/Input.h |
|
1208 +++ b/unix/xserver/hw/vnc/Input.h |
|
1209 @@ -58,4 +58,17 @@ private: |
|
1210 rfb::Point cursorPos, oldCursorPos; |
|
1211 }; |
|
1212 |
|
1213 +/* Represents keyboard device. */ |
|
1214 +class KeyboardDevice { |
|
1215 +public: |
|
1216 + /* Create new Keyboard device instance. */ |
|
1217 + KeyboardDevice(void); |
|
1218 + |
|
1219 + void Press(rdr::U32 keysym) { keyEvent(keysym, true); } |
|
1220 + void Release(rdr::U32 keysym) { keyEvent(keysym, false); } |
|
1221 +private: |
|
1222 + void keyEvent(rdr::U32 keysym, bool down); |
|
1223 + DeviceIntPtr dev; |
|
1224 +}; |
|
1225 + |
|
1226 #endif |
|
1227 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
1228 index 58f70d9..66c92d2 100644 |
|
1229 --- a/unix/xserver/hw/vnc/XserverDesktop.cc |
|
1230 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc |
|
1231 @@ -50,26 +50,7 @@ extern "C" { |
|
1232 |
|
1233 extern char *display; |
|
1234 |
|
1235 -#include "inputstr.h" |
|
1236 -#include "servermd.h" |
|
1237 #include "colormapst.h" |
|
1238 -#include "resource.h" |
|
1239 -#include "cursorstr.h" |
|
1240 -#include "windowstr.h" |
|
1241 -#include "mi.h" |
|
1242 -#define XK_CYRILLIC |
|
1243 -#include <X11/keysym.h> |
|
1244 -#ifndef XKB_IN_SERVER |
|
1245 -#define XKB_IN_SERVER |
|
1246 -#endif |
|
1247 -#ifdef XKB |
|
1248 -#include <xkbsrv.h> |
|
1249 -#endif |
|
1250 -#if XORG >= 16 |
|
1251 -#include "exevents.h" |
|
1252 -extern void |
|
1253 -CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); |
|
1254 -#endif |
|
1255 #ifdef RANDR |
|
1256 #include "randrstr.h" |
|
1257 #endif |
|
1258 @@ -77,15 +58,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); |
|
1259 #undef class |
|
1260 } |
|
1261 |
|
1262 -static DeviceIntPtr vncKeyboardDevice = NULL; |
|
1263 -#if XORG == 15 |
|
1264 -static xEvent *eventq = NULL; |
|
1265 -#else |
|
1266 -static EventList *eventq = NULL; |
|
1267 -#endif |
|
1268 - |
|
1269 -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff); |
|
1270 - |
|
1271 using namespace rfb; |
|
1272 using namespace network; |
|
1273 |
|
1274 @@ -102,8 +74,6 @@ IntParameter queryConnectTimeout("QueryConnectTimeout", |
|
1275 "rejecting the connection", |
|
1276 10); |
|
1277 |
|
1278 -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); |
|
1279 - |
|
1280 static rdr::U8 reverseBits[] = { |
|
1281 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, |
|
1282 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, |
|
1283 @@ -193,33 +163,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, |
|
1284 if (httpListener) |
|
1285 httpServer = new FileHTTPServer(this); |
|
1286 |
|
1287 -#if XORG == 15 |
|
1288 - /* |
|
1289 - * XXX eventq is never free()-ed because it has to exist during server life |
|
1290 - * */ |
|
1291 - if (!eventq) |
|
1292 - eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum()); |
|
1293 - if (!eventq) |
|
1294 - FatalError("Couldn't allocate eventq\n"); |
|
1295 -#else |
|
1296 - GetEventList(&eventq); |
|
1297 -#endif |
|
1298 - |
|
1299 - /* |
|
1300 - * NOTE: |
|
1301 - * We _might_ have to call ActivateDevice function for both keyboard and |
|
1302 - * mouse. For Xvnc it's not needed but I have to check libvnc.so module. |
|
1303 - */ |
|
1304 - if (vncKeyboardDevice == NULL) { |
|
1305 - vncKeyboardDevice = AddInputDevice( |
|
1306 -#if XORG >= 16 |
|
1307 - serverClient, |
|
1308 -#endif |
|
1309 - vfbKeybdProc, TRUE); |
|
1310 - RegisterKeyboardDevice(vncKeyboardDevice); |
|
1311 - } |
|
1312 - |
|
1313 pointerDevice = new PointerDevice(server); |
|
1314 + keyboardDevice = new KeyboardDevice(); |
|
1315 } |
|
1316 |
|
1317 XserverDesktop::~XserverDesktop() |
|
1318 @@ -229,6 +174,7 @@ XserverDesktop::~XserverDesktop() |
|
1319 TimerFree(deferredUpdateTimer); |
|
1320 TimerFree(dummyTimer); |
|
1321 delete pointerDevice; |
|
1322 + delete keyboardDevice; |
|
1323 delete httpServer; |
|
1324 delete server; |
|
1325 } |
|
1326 @@ -854,550 +800,10 @@ |
|
1327 } |
|
1328 } |
|
1329 |
|
1330 -// |
|
1331 -// Keyboard handling |
|
1332 -// |
|
1333 - |
|
1334 -#define IS_PRESSED(keyc, keycode) \ |
|
1335 - ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) |
|
1336 - |
|
1337 -// ModifierState is a class which helps simplify generating a "fake" press |
|
1338 -// or release of shift, ctrl, alt, etc. An instance of the class is created |
|
1339 -// for every modifier which may need to be pressed or released. Then either |
|
1340 -// press() or release() may be called to make sure that the corresponding keys |
|
1341 -// are in the right state. The destructor of the class automatically reverts |
|
1342 -// to the previous state. Each modifier may have multiple keys associated with |
|
1343 -// it, so in the case of a fake release, this may involve releasing more than |
|
1344 -// one key. |
|
1345 - |
|
1346 -class ModifierState { |
|
1347 -public: |
|
1348 - ModifierState(int modIndex_) |
|
1349 - : modIndex(modIndex_), nKeys(0), keys(0), pressed(false) |
|
1350 - { |
|
1351 - } |
|
1352 - ~ModifierState() { |
|
1353 - for (int i = 0; i < nKeys; i++) |
|
1354 - generateXKeyEvent(keys[i], !pressed); |
|
1355 - delete [] keys; |
|
1356 - } |
|
1357 - void press() { |
|
1358 - KeyClassPtr keyc = vncKeyboardDevice->key; |
|
1359 - if (!(keyc->state & (1<<modIndex))) { |
|
1360 - tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier], |
|
1361 - true); |
|
1362 - pressed = true; |
|
1363 - } |
|
1364 - } |
|
1365 - void release() { |
|
1366 - KeyClassPtr keyc = vncKeyboardDevice->key; |
|
1367 - if (keyc->state & (1<<modIndex)) { |
|
1368 - for (int k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
1369 - int keycode |
|
1370 - = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k]; |
|
1371 - if (keycode && IS_PRESSED(keyc, keycode)) |
|
1372 - tempKeyEvent(keycode, false); |
|
1373 - } |
|
1374 - } |
|
1375 - } |
|
1376 -private: |
|
1377 - void tempKeyEvent(int keycode, bool down) { |
|
1378 - if (keycode) { |
|
1379 - if (!keys) keys = new int[vncKeyboardDevice->key->maxKeysPerModifier]; |
|
1380 - keys[nKeys++] = keycode; |
|
1381 - generateXKeyEvent(keycode, down); |
|
1382 - } |
|
1383 - } |
|
1384 - void generateXKeyEvent(int keycode, bool down) { |
|
1385 - int i, n; |
|
1386 - n = GetKeyboardEvents (eventq, vncKeyboardDevice, |
|
1387 - down ? KeyPress : KeyRelease, keycode); |
|
1388 - for (i = 0; i < n; i++) { |
|
1389 - mieqEnqueue (vncKeyboardDevice, |
|
1390 -#if XORG == 15 |
|
1391 - eventq + i |
|
1392 -#else |
|
1393 - (eventq + i)->event |
|
1394 -#endif |
|
1395 - ); |
|
1396 - } |
|
1397 - vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up"); |
|
1398 - } |
|
1399 - int modIndex; |
|
1400 - int nKeys; |
|
1401 - int* keys; |
|
1402 - bool pressed; |
|
1403 -}; |
|
1404 - |
|
1405 - |
|
1406 -// altKeysym is a table of alternative keysyms which have the same meaning. |
|
1407 - |
|
1408 -struct altKeysym_t { |
|
1409 - KeySym a, b; |
|
1410 -}; |
|
1411 - |
|
1412 -altKeysym_t altKeysym[] = { |
|
1413 - { XK_Shift_L, XK_Shift_R }, |
|
1414 - { XK_Control_L, XK_Control_R }, |
|
1415 - { XK_Meta_L, XK_Meta_R }, |
|
1416 - { XK_Alt_L, XK_Alt_R }, |
|
1417 - { XK_Super_L, XK_Super_R }, |
|
1418 - { XK_Hyper_L, XK_Hyper_R }, |
|
1419 - { XK_KP_Space, XK_space }, |
|
1420 - { XK_KP_Tab, XK_Tab }, |
|
1421 - { XK_KP_Enter, XK_Return }, |
|
1422 - { XK_KP_F1, XK_F1 }, |
|
1423 - { XK_KP_F2, XK_F2 }, |
|
1424 - { XK_KP_F3, XK_F3 }, |
|
1425 - { XK_KP_F4, XK_F4 }, |
|
1426 - { XK_KP_Home, XK_Home }, |
|
1427 - { XK_KP_Left, XK_Left }, |
|
1428 - { XK_KP_Up, XK_Up }, |
|
1429 - { XK_KP_Right, XK_Right }, |
|
1430 - { XK_KP_Down, XK_Down }, |
|
1431 - { XK_KP_Page_Up, XK_Page_Up }, |
|
1432 - { XK_KP_Page_Down, XK_Page_Down }, |
|
1433 - { XK_KP_End, XK_End }, |
|
1434 - { XK_KP_Begin, XK_Begin }, |
|
1435 - { XK_KP_Insert, XK_Insert }, |
|
1436 - { XK_KP_Delete, XK_Delete }, |
|
1437 - { XK_KP_Equal, XK_equal }, |
|
1438 - { XK_KP_Multiply, XK_asterisk }, |
|
1439 - { XK_KP_Add, XK_plus }, |
|
1440 - { XK_KP_Separator, XK_comma }, |
|
1441 - { XK_KP_Subtract, XK_minus }, |
|
1442 - { XK_KP_Decimal, XK_period }, |
|
1443 - { XK_KP_Divide, XK_slash }, |
|
1444 - { XK_KP_0, XK_0 }, |
|
1445 - { XK_KP_1, XK_1 }, |
|
1446 - { XK_KP_2, XK_2 }, |
|
1447 - { XK_KP_3, XK_3 }, |
|
1448 - { XK_KP_4, XK_4 }, |
|
1449 - { XK_KP_5, XK_5 }, |
|
1450 - { XK_KP_6, XK_6 }, |
|
1451 - { XK_KP_7, XK_7 }, |
|
1452 - { XK_KP_8, XK_8 }, |
|
1453 - { XK_KP_9, XK_9 }, |
|
1454 -}; |
|
1455 - |
|
1456 -/* |
|
1457 - * keyEvent() - work out the best keycode corresponding to the keysym sent by |
|
1458 - * the viewer. This is non-trivial because we can't assume much about the |
|
1459 - * local keyboard layout. We must also find out which column of the keyboard |
|
1460 - * mapping the keysym is in, and alter the shift state appropriately. Column 0 |
|
1461 - * means both shift and "mode_switch" (AltGr) must be released, column 1 means |
|
1462 - * shift must be pressed and mode_switch released, column 2 means shift must be |
|
1463 - * released and mode_switch pressed, and column 3 means both shift and |
|
1464 - * mode_switch must be pressed. |
|
1465 - * |
|
1466 - * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org |
|
1467 - * version. Quick explanation of that "magic": |
|
1468 - * |
|
1469 - * 1.5 |
|
1470 - * - has only one core keyboard so we have to keep core keyboard mapping |
|
1471 - * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard() |
|
1472 - * |
|
1473 - * 1.6 (aka MPX - Multi pointer X) |
|
1474 - * - multiple master devices (= core devices) exists, keep vncKeyboardDevice |
|
1475 - * synchronized with proper master device |
|
1476 - */ |
|
1477 - |
|
1478 void XserverDesktop::keyEvent(rdr::U32 keysym, bool down) |
|
1479 { |
|
1480 - DeviceIntPtr master; |
|
1481 - KeyClassPtr keyc = vncKeyboardDevice->key; |
|
1482 - KeySymsPtr keymap = &keyc->curKeySyms; |
|
1483 - unsigned int i, n; |
|
1484 - int j, k; |
|
1485 - |
|
1486 - /* |
|
1487 - * Since we are checking the current state to determine if we need |
|
1488 - * to fake modifiers, we must make sure that everything put on the |
|
1489 - * input queue is processed before we start. Otherwise, shift may be |
|
1490 - * stuck down. |
|
1491 - */ |
|
1492 - mieqProcessInputEvents(); |
|
1493 - |
|
1494 - if (keysym == XK_Caps_Lock) { |
|
1495 - vlog.debug("Ignoring caps lock"); |
|
1496 - return; |
|
1497 - } |
|
1498 - |
|
1499 - // find which modifier Mode_switch is on. |
|
1500 - int modeSwitchMapIndex = 0; |
|
1501 - for (i = 3; i < 8; i++) { |
|
1502 - for (k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
1503 - int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k]; |
|
1504 - for (j = 0; j < keymap->mapWidth; j++) { |
|
1505 - if (keycode != 0 && |
|
1506 - keymap->map[(keycode - keymap->minKeyCode) |
|
1507 - * keymap->mapWidth + j] == XK_Mode_switch) |
|
1508 - { |
|
1509 - modeSwitchMapIndex = i; |
|
1510 - break; |
|
1511 - } |
|
1512 - } |
|
1513 - } |
|
1514 - } |
|
1515 - |
|
1516 - int col = 0; |
|
1517 - if (keyc->state & (1<<ShiftMapIndex)) col |= 1; |
|
1518 - if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2; |
|
1519 - |
|
1520 - int kc = KeysymToKeycode(keymap, keysym, &col); |
|
1521 - |
|
1522 - // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a |
|
1523 - // local shifted Tab regardless of what the "shifted Tab" keysym is on the |
|
1524 - // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab |
|
1525 - // keysym, and quite possibly some others too). We never get ISO_Left_Tab |
|
1526 - // here because it's already been translated in VNCSConnectionST. |
|
1527 - if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex))) |
|
1528 - col |= 1; |
|
1529 - |
|
1530 - if (kc == 0) { |
|
1531 - // Not a direct match in the local keyboard mapping. Check for alternative |
|
1532 - // keysyms with the same meaning. |
|
1533 - for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { |
|
1534 - if (keysym == altKeysym[i].a) |
|
1535 - kc = KeysymToKeycode(keymap, altKeysym[i].b, &col); |
|
1536 - else if (keysym == altKeysym[i].b) |
|
1537 - kc = KeysymToKeycode(keymap, altKeysym[i].a, &col); |
|
1538 - if (kc) break; |
|
1539 - } |
|
1540 - } |
|
1541 - |
|
1542 - if (kc == 0) { |
|
1543 - // Last resort - dynamically add a new key to the keyboard mapping. |
|
1544 - for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) { |
|
1545 - if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) { |
|
1546 - keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym; |
|
1547 - col = 0; |
|
1548 - |
|
1549 - vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc); |
|
1550 - |
|
1551 -#if XORG == 15 |
|
1552 - master = inputInfo.keyboard; |
|
1553 -#else |
|
1554 - master = vncKeyboardDevice->u.master; |
|
1555 -#endif |
|
1556 - if (vncKeyboardDevice == |
|
1557 - dixLookupPrivate(&master->devPrivates, CoreDevicePrivateKey)) { |
|
1558 - dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, NULL); |
|
1559 -#if XORG == 15 |
|
1560 - SwitchCoreKeyboard(vncKeyboardDevice); |
|
1561 -#else |
|
1562 - CopyKeyClass(vncKeyboardDevice, master); |
|
1563 -#endif |
|
1564 - } |
|
1565 - break; |
|
1566 - } |
|
1567 - } |
|
1568 - if (kc < keymap->minKeyCode) { |
|
1569 - vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym); |
|
1570 - return; |
|
1571 - } |
|
1572 - } |
|
1573 - |
|
1574 - // See if it's a modifier key. If so, then don't do any auto-repeat, because |
|
1575 - // the X server will translate each press into a release followed by a press. |
|
1576 - for (i = 0; i < 8; i++) { |
|
1577 - for (k = 0; k < keyc->maxKeysPerModifier; k++) { |
|
1578 - if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] && |
|
1579 - IS_PRESSED(keyc,kc) && down) |
|
1580 - return; |
|
1581 - } |
|
1582 - } |
|
1583 - |
|
1584 - ModifierState shift(ShiftMapIndex); |
|
1585 - ModifierState modeSwitch(modeSwitchMapIndex); |
|
1586 - if (down) { |
|
1587 - if (col & 1) |
|
1588 - shift.press(); |
|
1589 - else |
|
1590 - shift.release(); |
|
1591 - if (modeSwitchMapIndex) { |
|
1592 - if (col & 2) |
|
1593 - modeSwitch.press(); |
|
1594 - else |
|
1595 - modeSwitch.release(); |
|
1596 - } |
|
1597 - } |
|
1598 - vlog.debug("keycode %d %s", kc, down ? "down" : "up"); |
|
1599 - n = GetKeyboardEvents (eventq, vncKeyboardDevice, down ? |
|
1600 - KeyPress : KeyRelease, kc); |
|
1601 - for (i = 0; i < n; i++) { |
|
1602 - mieqEnqueue (vncKeyboardDevice, |
|
1603 -#if XORG == 15 |
|
1604 - eventq + i |
|
1605 -#else |
|
1606 - (eventq + i)->event |
|
1607 -#endif |
|
1608 - ); |
|
1609 - } |
|
1610 - |
|
1611 - /* |
|
1612 - * When faking a modifier we are putting a keycode (which can |
|
1613 - * currently activate the desired modifier) on the input |
|
1614 - * queue. A future modmap change can change the mapping so |
|
1615 - * that this keycode means something else entirely. Guard |
|
1616 - * against this by processing the queue now. |
|
1617 - */ |
|
1618 - mieqProcessInputEvents(); |
|
1619 + if (down) |
|
1620 + keyboardDevice->Press(keysym); |
|
1621 + else |
|
1622 + keyboardDevice->Release(keysym); |
|
1623 } |
|
1624 - |
|
1625 -static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) |
|
1626 -{ |
|
1627 - register int per = keymap->mapWidth; |
|
1628 - register KeySym *syms; |
|
1629 - KeySym lsym, usym; |
|
1630 - |
|
1631 - if ((col < 0) || ((col >= per) && (col > 3)) || |
|
1632 - (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) |
|
1633 - return NoSymbol; |
|
1634 - |
|
1635 - syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; |
|
1636 - if (col < 4) { |
|
1637 - if (col > 1) { |
|
1638 - while ((per > 2) && (syms[per - 1] == NoSymbol)) |
|
1639 - per--; |
|
1640 - if (per < 3) |
|
1641 - col -= 2; |
|
1642 - } |
|
1643 - if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { |
|
1644 - XConvertCase(syms[col&~1], &lsym, &usym); |
|
1645 - if (!(col & 1)) |
|
1646 - return lsym; |
|
1647 - // I'm commenting out this logic because it's incorrect even though it |
|
1648 - // was copied from the Xlib sources. The X protocol book quite clearly |
|
1649 - // states that where a group consists of element 1 being a non-alphabetic |
|
1650 - // keysym and element 2 being NoSymbol that you treat the second element |
|
1651 - // as being the same as the first. This also tallies with the behaviour |
|
1652 - // produced by the installed Xlib on my linux box (I believe this is |
|
1653 - // because it uses some XKB code rather than the original Xlib code - |
|
1654 - // compare XKBBind.c with KeyBind.c in lib/X11). |
|
1655 - // else if (usym == lsym) |
|
1656 - // return NoSymbol; |
|
1657 - else |
|
1658 - return usym; |
|
1659 - } |
|
1660 - } |
|
1661 - return syms[col]; |
|
1662 -} |
|
1663 - |
|
1664 -// KeysymToKeycode() - find the keycode and column corresponding to the given |
|
1665 -// keysym. The value of col passed in should be the column determined from the |
|
1666 -// current shift state. If the keysym can be found in that column we prefer |
|
1667 -// that to finding it in a different column (which would require fake events to |
|
1668 -// alter the shift state). |
|
1669 - |
|
1670 -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) |
|
1671 -{ |
|
1672 - register int i, j; |
|
1673 - |
|
1674 - j = *col; |
|
1675 - for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { |
|
1676 - if (KeyCodetoKeySym(keymap, i, j) == ks) |
|
1677 - return i; |
|
1678 - } |
|
1679 - |
|
1680 - for (j = 0; j < keymap->mapWidth; j++) { |
|
1681 - for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { |
|
1682 - if (KeyCodetoKeySym(keymap, i, j) == ks) { |
|
1683 - *col = j; |
|
1684 - return i; |
|
1685 - } |
|
1686 - } |
|
1687 - } |
|
1688 - return 0; |
|
1689 -} |
|
1690 - |
|
1691 -/* Fairly standard US PC Keyboard */ |
|
1692 - |
|
1693 -#define VFB_MIN_KEY 8 |
|
1694 -#define VFB_MAX_KEY 255 |
|
1695 -#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1) |
|
1696 -#define KEYSYMS_PER_KEY 2 |
|
1697 -KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = { |
|
1698 - NoSymbol, NoSymbol, |
|
1699 - XK_Escape, NoSymbol, |
|
1700 - XK_1, XK_exclam, |
|
1701 - XK_2, XK_at, |
|
1702 - XK_3, XK_numbersign, |
|
1703 - XK_4, XK_dollar, |
|
1704 - XK_5, XK_percent, |
|
1705 - XK_6, XK_asciicircum, |
|
1706 - XK_7, XK_ampersand, |
|
1707 - XK_8, XK_asterisk, |
|
1708 - XK_9, XK_parenleft, |
|
1709 - XK_0, XK_parenright, |
|
1710 - XK_minus, XK_underscore, |
|
1711 - XK_equal, XK_plus, |
|
1712 - XK_BackSpace, NoSymbol, |
|
1713 - XK_Tab, NoSymbol, |
|
1714 - XK_q, XK_Q, |
|
1715 - XK_w, XK_W, |
|
1716 - XK_e, XK_E, |
|
1717 - XK_r, XK_R, |
|
1718 - XK_t, XK_T, |
|
1719 - XK_y, XK_Y, |
|
1720 - XK_u, XK_U, |
|
1721 - XK_i, XK_I, |
|
1722 - XK_o, XK_O, |
|
1723 - XK_p, XK_P, |
|
1724 - XK_bracketleft, XK_braceleft, |
|
1725 - XK_bracketright, XK_braceright, |
|
1726 - XK_Return, NoSymbol, |
|
1727 - XK_Control_L, NoSymbol, |
|
1728 - XK_a, XK_A, |
|
1729 - XK_s, XK_S, |
|
1730 - XK_d, XK_D, |
|
1731 - XK_f, XK_F, |
|
1732 - XK_g, XK_G, |
|
1733 - XK_h, XK_H, |
|
1734 - XK_j, XK_J, |
|
1735 - XK_k, XK_K, |
|
1736 - XK_l, XK_L, |
|
1737 - XK_semicolon, XK_colon, |
|
1738 - XK_apostrophe, XK_quotedbl, |
|
1739 - XK_grave, XK_asciitilde, |
|
1740 - XK_Shift_L, NoSymbol, |
|
1741 - XK_backslash, XK_bar, |
|
1742 - XK_z, XK_Z, |
|
1743 - XK_x, XK_X, |
|
1744 - XK_c, XK_C, |
|
1745 - XK_v, XK_V, |
|
1746 - XK_b, XK_B, |
|
1747 - XK_n, XK_N, |
|
1748 - XK_m, XK_M, |
|
1749 - XK_comma, XK_less, |
|
1750 - XK_period, XK_greater, |
|
1751 - XK_slash, XK_question, |
|
1752 - XK_Shift_R, NoSymbol, |
|
1753 - XK_KP_Multiply, NoSymbol, |
|
1754 - XK_Alt_L, XK_Meta_L, |
|
1755 - XK_space, NoSymbol, |
|
1756 - /*XK_Caps_Lock*/ NoSymbol, NoSymbol, |
|
1757 - XK_F1, NoSymbol, |
|
1758 - XK_F2, NoSymbol, |
|
1759 - XK_F3, NoSymbol, |
|
1760 - XK_F4, NoSymbol, |
|
1761 - XK_F5, NoSymbol, |
|
1762 - XK_F6, NoSymbol, |
|
1763 - XK_F7, NoSymbol, |
|
1764 - XK_F8, NoSymbol, |
|
1765 - XK_F9, NoSymbol, |
|
1766 - XK_F10, NoSymbol, |
|
1767 - XK_Num_Lock, XK_Pointer_EnableKeys, |
|
1768 - XK_Scroll_Lock, NoSymbol, |
|
1769 - XK_KP_Home, XK_KP_7, |
|
1770 - XK_KP_Up, XK_KP_8, |
|
1771 - XK_KP_Prior, XK_KP_9, |
|
1772 - XK_KP_Subtract, NoSymbol, |
|
1773 - XK_KP_Left, XK_KP_4, |
|
1774 - XK_KP_Begin, XK_KP_5, |
|
1775 - XK_KP_Right, XK_KP_6, |
|
1776 - XK_KP_Add, NoSymbol, |
|
1777 - XK_KP_End, XK_KP_1, |
|
1778 - XK_KP_Down, XK_KP_2, |
|
1779 - XK_KP_Next, XK_KP_3, |
|
1780 - XK_KP_Insert, XK_KP_0, |
|
1781 - XK_KP_Delete, XK_KP_Decimal, |
|
1782 - NoSymbol, NoSymbol, |
|
1783 - NoSymbol, NoSymbol, |
|
1784 - NoSymbol, NoSymbol, |
|
1785 - XK_F11, NoSymbol, |
|
1786 - XK_F12, NoSymbol, |
|
1787 - XK_Home, NoSymbol, |
|
1788 - XK_Up, NoSymbol, |
|
1789 - XK_Prior, NoSymbol, |
|
1790 - XK_Left, NoSymbol, |
|
1791 - NoSymbol, NoSymbol, |
|
1792 - XK_Right, NoSymbol, |
|
1793 - XK_End, NoSymbol, |
|
1794 - XK_Down, NoSymbol, |
|
1795 - XK_Next, NoSymbol, |
|
1796 - XK_Insert, NoSymbol, |
|
1797 - XK_Delete, NoSymbol, |
|
1798 - XK_KP_Enter, NoSymbol, |
|
1799 - XK_Control_R, NoSymbol, |
|
1800 - XK_Pause, XK_Break, |
|
1801 - XK_Print, XK_Execute, |
|
1802 - XK_KP_Divide, NoSymbol, |
|
1803 - XK_Alt_R, XK_Meta_R, |
|
1804 -}; |
|
1805 - |
|
1806 -static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) |
|
1807 -{ |
|
1808 - int i; |
|
1809 - |
|
1810 - for (i = 0; i < MAP_LENGTH; i++) |
|
1811 - pModMap[i] = NoSymbol; |
|
1812 - |
|
1813 - for (i = 0; i < VFB_MAP_LEN; i++) { |
|
1814 - if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock) |
|
1815 - pModMap[i + VFB_MIN_KEY] = LockMask; |
|
1816 - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L || |
|
1817 - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R) |
|
1818 - pModMap[i + VFB_MIN_KEY] = ShiftMask; |
|
1819 - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L || |
|
1820 - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) { |
|
1821 - pModMap[i + VFB_MIN_KEY] = ControlMask; |
|
1822 - } |
|
1823 - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L || |
|
1824 - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R) |
|
1825 - pModMap[i + VFB_MIN_KEY] = Mod1Mask; |
|
1826 - } |
|
1827 - |
|
1828 - pKeySyms->minKeyCode = VFB_MIN_KEY; |
|
1829 - pKeySyms->maxKeyCode = VFB_MAX_KEY; |
|
1830 - pKeySyms->mapWidth = KEYSYMS_PER_KEY; |
|
1831 - pKeySyms->map = keyboardMap; |
|
1832 - |
|
1833 - return TRUE; |
|
1834 -} |
|
1835 - |
|
1836 -static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_) |
|
1837 -{ |
|
1838 - if (percent > 0) |
|
1839 - vncBell(); |
|
1840 -} |
|
1841 - |
|
1842 -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff) |
|
1843 -{ |
|
1844 - KeySymsRec keySyms; |
|
1845 - CARD8 modMap[MAP_LENGTH]; |
|
1846 - DevicePtr pDev = (DevicePtr)pDevice; |
|
1847 -#ifdef XKB |
|
1848 - XkbComponentNamesRec names; |
|
1849 -#endif |
|
1850 - |
|
1851 - switch (onoff) |
|
1852 - { |
|
1853 - case DEVICE_INIT: |
|
1854 - GetMappings(&keySyms, modMap); |
|
1855 -#ifdef XKB |
|
1856 - if (!noXkbExtension) { |
|
1857 - memset(&names, 0, sizeof (names)); |
|
1858 - XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); |
|
1859 - XkbInitKeyboardDeviceStruct(pDevice, &names, &keySyms, modMap, |
|
1860 - (BellProcPtr)vfbBell, |
|
1861 - (KbdCtrlProcPtr)NoopDDA); |
|
1862 - } else |
|
1863 -#endif |
|
1864 - { |
|
1865 - InitKeyboardDeviceStruct(pDev, &keySyms, modMap, |
|
1866 - (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA); |
|
1867 - } |
|
1868 - break; |
|
1869 - case DEVICE_ON: |
|
1870 - pDev->on = TRUE; |
|
1871 - break; |
|
1872 - case DEVICE_OFF: |
|
1873 - pDev->on = FALSE; |
|
1874 - break; |
|
1875 - case DEVICE_CLOSE: |
|
1876 - break; |
|
1877 - } |
|
1878 - return Success; |
|
1879 -} |
|
1880 - |
|
1881 diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h |
|
1882 index 9f300f5..6e4f609 100644 |
|
1883 --- a/unix/xserver/hw/vnc/XserverDesktop.h |
|
1884 +++ b/unix/xserver/hw/vnc/XserverDesktop.h |
|
1885 @@ -123,6 +123,7 @@ private: |
|
1886 void deferUpdate(); |
|
1887 ScreenPtr pScreen; |
|
1888 PointerDevice *pointerDevice; |
|
1889 + KeyboardDevice *keyboardDevice; |
|
1890 OsTimerPtr deferredUpdateTimer, dummyTimer; |
|
1891 rfb::VNCServerST* server; |
|
1892 rfb::HTTPServer* httpServer; |
|
1893 |
|
1894 -- |
|
1895 1.5.6.5 |
|
1896 |
|