blob: 5daf663de444bab2c5bcd9cda4740ba198105886 [file] [log] [blame]
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +00001/* Copyright (c) 1993 X Consortium
2 Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00003
4Permission is hereby granted, free of charge, to any person obtaining
5a copy of this software and associated documentation files (the
6"Software"), to deal in the Software without restriction, including
7without limitation the rights to use, copy, modify, merge, publish,
8distribute, sublicense, and/or sell copies of the Software, and to
9permit persons to whom the Software is furnished to do so, subject to
10the following conditions:
11
12The above copyright notice and this permission notice shall be included
13in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of the X Consortium shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from the X Consortium.
27
28*/
29
30#include <rfb/Configuration.h>
31#include <rfb/Logger_stdio.h>
32#include <rfb/LogWriter.h>
33#include <network/TcpSocket.h>
34#include "vncExtInit.h"
35
36extern "C" {
37#define class c_class
38#define public c_public
39#define xor c_xor
40#define and c_and
41#ifdef WIN32
42#include <X11/Xwinsock.h>
43#endif
44#include <stdio.h>
45#include "X11/X.h"
46#define NEED_EVENTS
47#include "X11/Xproto.h"
48#include "X11/Xos.h"
49#include "scrnintstr.h"
50#include "servermd.h"
Peter Åstrand1bdab802005-02-14 14:03:35 +000051#include "fb.h"
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000052#include "mi.h"
53#include "mibstore.h"
54#include "colormapst.h"
55#include "gcstruct.h"
56#include "input.h"
57#include "mipointer.h"
Peter Åstrand200c31c2005-02-23 13:21:09 +000058#define new New
Peter Åstrand1d742b42005-02-22 21:33:20 +000059#include "micmap.h"
Peter Åstrand200c31c2005-02-23 13:21:09 +000060#undef new
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000061#include <sys/types.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000062#ifdef HAS_MMAP
63#include <sys/mman.h>
64#ifndef MAP_FILE
65#define MAP_FILE 0
66#endif
67#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000068#include <sys/stat.h>
69#include <errno.h>
70#ifndef WIN32
71#include <sys/param.h>
72#endif
73#include <X11/XWDFile.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000074#ifdef HAS_SHM
75#include <sys/ipc.h>
76#include <sys/shm.h>
77#endif /* HAS_SHM */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000078#include "dix.h"
79#include "miline.h"
80#include "inputstr.h"
81#include "keysym.h"
82 extern int defaultColorVisualClass;
83 extern char buildtime[];
84#undef class
85#undef public
86#undef xor
87#undef and
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000088}
89
Peter Åstrand601eb612006-05-24 11:04:28 +000090#define XVNCVERSION "TightVNC 1.5 series"
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +000091#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
Peter Åstrand601eb612006-05-24 11:04:28 +000092 "Copyright (C) 2000-2006 Constantin Kaplinsky\n" \
93 "Copyright (C) 2004-2006 Peter Astrand, Cendio AB\n" \
94 "See http://www.tightvnc.com for information on TightVNC.\n")
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +000095
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000096
97extern char *display;
98extern int monitorResolution;
99
100#define VFB_DEFAULT_WIDTH 1024
101#define VFB_DEFAULT_HEIGHT 768
102#define VFB_DEFAULT_DEPTH 16
103#define VFB_DEFAULT_WHITEPIXEL 0xffff
104#define VFB_DEFAULT_BLACKPIXEL 0
105#define VFB_DEFAULT_LINEBIAS 0
106#define XWD_WINDOW_NAME_LEN 60
107
108typedef struct
109{
Peter Åstrand60870912005-02-22 21:27:51 +0000110 int scrnum;
111 int width;
112 int paddedBytesWidth;
113 int paddedWidth;
114 int height;
115 int depth;
116 int bitsPerPixel;
117 int sizeInBytes;
118 int ncolors;
119 char *pfbMemory;
120 XWDColor *pXWDCmap;
121 XWDFileHeader *pXWDHeader;
122 Pixel blackPixel;
123 Pixel whitePixel;
124 unsigned int lineBias;
125 CloseScreenProcPtr closeScreen;
126
127#ifdef HAS_MMAP
128 int mmap_fd;
129 char mmap_file[MAXPATHLEN];
130#endif
131
132#ifdef HAS_SHM
133 int shmid;
134#endif
135
136 Bool pixelFormatDefined;
137 Bool rgbNotBgr;
138 int redBits, greenBits, blueBits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000139
140} vfbScreenInfo, *vfbScreenInfoPtr;
141
142static int vfbNumScreens;
143static vfbScreenInfo vfbScreens[MAXSCREENS];
144static Bool vfbPixmapDepths[33];
Peter Åstrand00c759d2005-02-22 20:11:47 +0000145#ifdef HAS_MMAP
146static char *pfbdir = NULL;
147#endif
148typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
149static fbMemType fbmemtype = NORMAL_MEMORY_FB;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000150static char needswap = 0;
151static int lastScreen = -1;
Peter Åstrandc5421b22005-02-14 20:25:49 +0000152static Bool Render = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000153
154static bool displaySpecified = false;
155static bool wellKnownSocketsCreated = false;
156static char displayNumStr[16];
157
158#define swapcopy16(_dst, _src) \
159 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
160 else _dst = _src;
161
162#define swapcopy32(_dst, _src) \
163 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
164 else _dst = _src;
165
166
Peter Åstrandf960f042005-02-22 20:07:55 +0000167static void
168vfbInitializePixmapDepths(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000169{
Peter Åstrandf960f042005-02-22 20:07:55 +0000170 int i;
171 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
172 for (i = 2; i <= 32; i++)
173 vfbPixmapDepths[i] = FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000174}
175
Peter Åstrandf960f042005-02-22 20:07:55 +0000176static void
177vfbInitializeDefaultScreens(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000178{
Peter Åstrandf960f042005-02-22 20:07:55 +0000179 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000180
Peter Åstrandf960f042005-02-22 20:07:55 +0000181 for (i = 0; i < MAXSCREENS; i++)
182 {
183 vfbScreens[i].scrnum = i;
184 vfbScreens[i].width = VFB_DEFAULT_WIDTH;
185 vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
186 vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
187 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
188 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
189 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
190 vfbScreens[i].pixelFormatDefined = FALSE;
191 vfbScreens[i].pfbMemory = NULL;
192 }
193 vfbNumScreens = 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000194}
195
Peter Åstrand00c759d2005-02-22 20:11:47 +0000196static int
197vfbBitsPerPixel(int depth)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000198{
Peter Åstrand00c759d2005-02-22 20:11:47 +0000199 if (depth == 1) return 1;
200 else if (depth <= 8) return 8;
201 else if (depth <= 16) return 16;
202 else return 32;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000203}
204
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000205
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000206extern "C" {
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000207
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000208 void ddxGiveUp()
209 {
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000210 int i;
211
212 /* clean up the framebuffers */
213
Peter Åstrand00c759d2005-02-22 20:11:47 +0000214 switch (fbmemtype)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000215 {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000216#ifdef HAS_MMAP
217 case MMAPPED_FILE_FB:
218 for (i = 0; i < vfbNumScreens; i++)
219 {
220 if (-1 == unlink(vfbScreens[i].mmap_file))
221 {
222 perror("unlink");
223 ErrorF("unlink %s failed, errno %d",
224 vfbScreens[i].mmap_file, errno);
225 }
226 }
227 break;
228#else /* HAS_MMAP */
229 case MMAPPED_FILE_FB:
230 break;
231#endif /* HAS_MMAP */
232
233#ifdef HAS_SHM
234 case SHARED_MEMORY_FB:
235 for (i = 0; i < vfbNumScreens; i++)
236 {
237 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
238 {
239 perror("shmdt");
240 ErrorF("shmdt failed, errno %d", errno);
241 }
242 }
243 break;
244#else /* HAS_SHM */
245 case SHARED_MEMORY_FB:
246 break;
247#endif /* HAS_SHM */
248
249 case NORMAL_MEMORY_FB:
250 for (i = 0; i < vfbNumScreens; i++)
251 {
252 Xfree(vfbScreens[i].pXWDHeader);
253 }
254 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000255 }
Peter Åstrand00c759d2005-02-22 20:11:47 +0000256}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000257
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000258void
259AbortDDX()
260{
261 ddxGiveUp();
262}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000263
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000264#ifdef __DARWIN__
265void
266DarwinHandleGUI(int argc, char *argv[])
267{
268}
269
270void GlxExtensionInit();
271void GlxWrapInitVisuals(void *procPtr);
272
273void
274DarwinGlxExtensionInit()
275{
276 GlxExtensionInit();
277}
278
279void
280DarwinGlxWrapInitVisuals(
281 void *procPtr)
282{
283 GlxWrapInitVisuals(procPtr);
284}
285#endif
286
287void
288OsVendorInit()
289{
290}
291
292void
293OsVendorFatalError()
294{
295}
296
297void ddxBeforeReset(void)
298{
299 return;
300}
301
302void
303ddxUseMsg()
304{
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000305 ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000306 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
307 VENDOR_STRING);
308 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
309 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
Peter Åstrandc5421b22005-02-14 20:25:49 +0000310#ifdef RENDER
311 ErrorF("+/-render turn on/off RENDER extension support"
312 "(default on)\n");
313#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000314 ErrorF("-linebias n adjust thin line pixelization\n");
315 ErrorF("-blackpixel n pixel value for black\n");
316 ErrorF("-whitepixel n pixel value for white\n");
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000317
318#ifdef HAS_MMAP
319 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
320#endif
321
322#ifdef HAS_SHM
323 ErrorF("-shmem put framebuffers in shared memory\n");
324#endif
325
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000326 ErrorF("-geometry WxH set screen 0's width, height\n");
327 ErrorF("-depth D set screen 0's depth\n");
328 ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
329 ErrorF("-inetd has been launched from inetd\n");
330 ErrorF("\nVNC parameters:\n");
331
332 fprintf(stderr,"\n"
333 "Parameters can be turned on with -<param> or off with -<param>=0\n"
334 "Parameters which take a value can be specified as "
335 "-<param> <value>\n"
336 "Other valid forms are <param>=<value> -<param>=<value> "
337 "--<param>=<value>\n"
338 "Parameter names are case-insensitive. The parameters are:\n\n");
339 rfb::Configuration::listParams(79, 14);
340 }
341}
342
Peter Åstrandfc41a212005-02-22 20:29:40 +0000343/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
344void ddxInitGlobals(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000345{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000346}
347
Peter Åstrandfc41a212005-02-22 20:29:40 +0000348static
349bool displayNumFree(int num)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000350{
Peter Åstrandfc41a212005-02-22 20:29:40 +0000351 try {
352 network::TcpListener l(6000+num);
353 } catch (rdr::Exception& e) {
354 return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000355 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000356 char file[256];
357 sprintf(file, "/tmp/.X%d-lock", num);
358 if (access(file, F_OK) == 0) return false;
359 sprintf(file, "/tmp/.X11-unix/X%d", num);
360 if (access(file, F_OK) == 0) return false;
361 sprintf(file, "/usr/spool/sockets/X11/%d", num);
362 if (access(file, F_OK) == 0) return false;
363 return true;
364}
365
366int
367ddxProcessArgument(int argc, char *argv[], int i)
368{
369 static Bool firstTime = TRUE;
370
371 if (firstTime)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000372 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000373 vfbInitializeDefaultScreens();
374 vfbInitializePixmapDepths();
375 firstTime = FALSE;
376 rfb::initStdIOLoggers();
377 rfb::LogWriter::setLogParams("*:stderr:30");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000378 }
379
Peter Åstrandfc41a212005-02-22 20:29:40 +0000380 if (argv[i][0] == ':')
381 displaySpecified = true;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000382
Peter Åstrandfc41a212005-02-22 20:29:40 +0000383 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000384 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000385 int screenNum;
386 if (i + 2 >= argc) UseMsg();
387 screenNum = atoi(argv[i+1]);
388 if (screenNum < 0 || screenNum >= MAXSCREENS)
389 {
390 ErrorF("Invalid screen number %d\n", screenNum);
391 UseMsg();
392 }
393 if (3 != sscanf(argv[i+2], "%dx%dx%d",
394 &vfbScreens[screenNum].width,
395 &vfbScreens[screenNum].height,
396 &vfbScreens[screenNum].depth))
397 {
398 ErrorF("Invalid screen configuration %s\n", argv[i+2]);
399 UseMsg();
400 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000401
Peter Åstrandfc41a212005-02-22 20:29:40 +0000402 if (screenNum >= vfbNumScreens)
403 vfbNumScreens = screenNum + 1;
404 lastScreen = screenNum;
405 return 3;
406 }
407
408 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
409 {
410 int depth, ret = 1;
411
412 if (++i >= argc) UseMsg();
413 while ((i < argc) && (depth = atoi(argv[i++])) != 0)
414 {
415 if (depth < 0 || depth > 32)
416 {
417 ErrorF("Invalid pixmap depth %d\n", depth);
418 UseMsg();
419 }
420 vfbPixmapDepths[depth] = TRUE;
421 ret++;
422 }
423 return ret;
424 }
425
426 if (strcmp (argv[i], "+render") == 0) /* +render */
427 {
428 Render = TRUE;
429 return 1;
430 }
Peter Åstrandc5421b22005-02-14 20:25:49 +0000431
Peter Åstrandfc41a212005-02-22 20:29:40 +0000432 if (strcmp (argv[i], "-render") == 0) /* -render */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000433 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000434 Render = FALSE;
435 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000436 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000437
Peter Åstrandfc41a212005-02-22 20:29:40 +0000438 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000439 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000440 Pixel pix;
441 if (++i >= argc) UseMsg();
442 pix = atoi(argv[i]);
443 if (-1 == lastScreen)
444 {
445 int i;
446 for (i = 0; i < MAXSCREENS; i++)
447 {
448 vfbScreens[i].blackPixel = pix;
449 }
450 }
451 else
452 {
453 vfbScreens[lastScreen].blackPixel = pix;
454 }
455 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000456 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000457
458 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000459 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000460 Pixel pix;
461 if (++i >= argc) UseMsg();
462 pix = atoi(argv[i]);
463 if (-1 == lastScreen)
464 {
465 int i;
466 for (i = 0; i < MAXSCREENS; i++)
467 {
468 vfbScreens[i].whitePixel = pix;
469 }
470 }
471 else
472 {
473 vfbScreens[lastScreen].whitePixel = pix;
474 }
475 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000476 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000477
478 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000479 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000480 unsigned int linebias;
481 if (++i >= argc) UseMsg();
482 linebias = atoi(argv[i]);
483 if (-1 == lastScreen)
484 {
485 int i;
486 for (i = 0; i < MAXSCREENS; i++)
487 {
488 vfbScreens[i].lineBias = linebias;
489 }
490 }
491 else
492 {
493 vfbScreens[lastScreen].lineBias = linebias;
494 }
495 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000496 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000497
498#ifdef HAS_MMAP
499 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000500 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000501 if (++i >= argc) UseMsg();
502 pfbdir = argv[i];
503 fbmemtype = MMAPPED_FILE_FB;
504 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000505 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000506#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000507
Peter Åstrandfc41a212005-02-22 20:29:40 +0000508#ifdef HAS_SHM
509 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
510 {
511 fbmemtype = SHARED_MEMORY_FB;
512 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000513 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000514#endif
515
516 if (strcmp(argv[i], "-geometry") == 0)
517 {
518 if (++i >= argc) UseMsg();
519 if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
520 &vfbScreens[0].height) != 2) {
521 ErrorF("Invalid geometry %s\n", argv[i]);
522 UseMsg();
523 }
524 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000525 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000526
527 if (strcmp(argv[i], "-depth") == 0)
528 {
529 if (++i >= argc) UseMsg();
530 vfbScreens[0].depth = atoi(argv[i]);
531 return 2;
532 }
533
534 if (strcmp(argv[i], "-pixelformat") == 0)
535 {
536 char rgbbgr[4];
537 int bits1, bits2, bits3;
538 if (++i >= argc) UseMsg();
539 if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
540 ErrorF("Invalid pixel format %s\n", argv[i]);
541 UseMsg();
542 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000543
544#define SET_PIXEL_FORMAT(vfbScreen) \
545 (vfbScreen).pixelFormatDefined = TRUE; \
546 (vfbScreen).depth = bits1 + bits2 + bits3; \
547 (vfbScreen).greenBits = bits2; \
548 if (strcasecmp(rgbbgr, "bgr") == 0) { \
549 (vfbScreen).rgbNotBgr = FALSE; \
550 (vfbScreen).redBits = bits3; \
551 (vfbScreen).blueBits = bits1; \
552 } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
553 (vfbScreen).rgbNotBgr = TRUE; \
554 (vfbScreen).redBits = bits1; \
555 (vfbScreen).blueBits = bits3; \
556 } else { \
557 ErrorF("Invalid pixel format %s\n", argv[i]); \
558 UseMsg(); \
559 }
560
Peter Åstrandfc41a212005-02-22 20:29:40 +0000561 if (-1 == lastScreen)
562 {
563 int i;
564 for (i = 0; i < MAXSCREENS; i++)
565 {
566 SET_PIXEL_FORMAT(vfbScreens[i]);
567 }
568 }
569 else
570 {
571 SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
572 }
573
574 return 2;
575 }
576
577 if (strcmp(argv[i], "-inetd") == 0)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000578 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000579 dup2(0,3);
580 vncInetdSock = 3;
581 close(2);
582
583 if (!displaySpecified) {
584 int port = network::TcpSocket::getSockPort(vncInetdSock);
585 int displayNum = port - 5900;
586 if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
587 for (displayNum = 1; displayNum < 100; displayNum++)
588 if (displayNumFree(displayNum)) break;
589
590 if (displayNum == 100)
591 FatalError("Xvnc error: no free display number for -inetd");
592 }
593
594 display = displayNumStr;
595 sprintf(displayNumStr, "%d", displayNum);
596 }
597
598 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000599 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000600
601 if (rfb::Configuration::setParam(argv[i]))
602 return 1;
603
604 if (argv[i][0] == '-' && i+1 < argc) {
605 if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
606 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000607 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000608
609 return 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000610}
611
612#ifdef DDXTIME /* from ServerOSDefines */
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000613CARD32
614GetTimeInMillis()
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000615{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000616 struct timeval tp;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000617
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000618 X_GETTIMEOFDAY(&tp);
619 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000620}
621#endif
622
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000623static ColormapPtr InstalledMaps[MAXSCREENS];
624
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000625static int
626vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000627{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000628 /* By the time we are processing requests, we can guarantee that there
629 * is always a colormap installed */
630 *pmaps = InstalledMaps[pScreen->myNum]->mid;
631 return (1);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000632}
633
634
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000635static void
636vfbInstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000637{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000638 int index = pmap->pScreen->myNum;
639 ColormapPtr oldpmap = InstalledMaps[index];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000640
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000641 if (pmap != oldpmap)
642 {
643 int entries;
644 XWDFileHeader *pXWDHeader;
645 XWDColor *pXWDCmap;
646 VisualPtr pVisual;
647 Pixel * ppix;
648 xrgb * prgb;
649 xColorItem *defs;
650 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000651
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000652 if(oldpmap != (ColormapPtr)None)
653 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
654 /* Install pmap */
655 InstalledMaps[index] = pmap;
656 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000657
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000658 entries = pmap->pVisual->ColormapEntries;
659 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
660 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
661 pVisual = pmap->pVisual;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000662
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000663 swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
664 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
665 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
666 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
667 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
668 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000669
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000670 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
671 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
672 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000673
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000674 for (i = 0; i < entries; i++) ppix[i] = i;
675 /* XXX truecolor */
676 QueryColors(pmap, entries, ppix, prgb);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000677
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000678 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
679 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
680 defs[i].red = prgb[i].red;
681 defs[i].green = prgb[i].green;
682 defs[i].blue = prgb[i].blue;
683 defs[i].flags = DoRed|DoGreen|DoBlue;
684 }
685 (*pmap->pScreen->StoreColors)(pmap, entries, defs);
686
687 DEALLOCATE_LOCAL(ppix);
688 DEALLOCATE_LOCAL(prgb);
689 DEALLOCATE_LOCAL(defs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000690 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000691}
692
Peter Åstrand853287d2005-02-22 20:46:58 +0000693static void
694vfbUninstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000695{
Peter Åstrand853287d2005-02-22 20:46:58 +0000696 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000697
Peter Åstrand853287d2005-02-22 20:46:58 +0000698 if(pmap == curpmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000699 {
Peter Åstrand853287d2005-02-22 20:46:58 +0000700 if (pmap->mid != pmap->pScreen->defColormap)
701 {
702 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
703 RT_COLORMAP);
704 (*pmap->pScreen->InstallColormap)(curpmap);
705 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000706 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000707}
708
Peter Åstrand853287d2005-02-22 20:46:58 +0000709static void
710vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000711{
Peter Åstrand853287d2005-02-22 20:46:58 +0000712 XWDColor *pXWDCmap;
713 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000714
Peter Åstrand853287d2005-02-22 20:46:58 +0000715 if (pmap != InstalledMaps[pmap->pScreen->myNum])
716 {
717 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000718 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000719
720 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
721
Peter Åstrandbe228572005-02-22 20:48:29 +0000722 if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
Peter Åstrand853287d2005-02-22 20:46:58 +0000723 {
724 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000725 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000726
727 for (i = 0; i < ndef; i++)
728 {
729 if (pdefs[i].flags & DoRed)
730 {
731 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
732 }
733 if (pdefs[i].flags & DoGreen)
734 {
735 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
736 }
737 if (pdefs[i].flags & DoBlue)
738 {
739 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
740 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000741 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000742}
743
Peter Åstrand853287d2005-02-22 20:46:58 +0000744static Bool
745vfbSaveScreen(ScreenPtr pScreen, int on)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000746{
Peter Åstrand853287d2005-02-22 20:46:58 +0000747 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000748}
749
Peter Åstrand1402f8c2005-02-23 08:22:10 +0000750#ifdef HAS_MMAP
751
752/* this flushes any changes to the screens out to the mmapped file */
753static void
754vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
755{
756 int i;
757
758 for (i = 0; i < vfbNumScreens; i++)
759 {
760#ifdef MS_ASYNC
761 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
762 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
763#else
764 /* silly NetBSD and who else? */
765 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
766 (size_t)vfbScreens[i].sizeInBytes))
767#endif
768 {
769 perror("msync");
770 ErrorF("msync failed, errno %d", errno);
771 }
772 }
773}
774
775
776static void
777vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
778{
779}
780
781
782static void
783vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
784{
785#define DUMMY_BUFFER_SIZE 65536
786 char dummyBuffer[DUMMY_BUFFER_SIZE];
787 int currentFileSize, writeThisTime;
788
789 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
790 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
791 {
792 perror("open");
793 ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
794 return;
795 }
796
797 /* Extend the file to be the proper size */
798
799 bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
800 for (currentFileSize = 0;
801 currentFileSize < pvfb->sizeInBytes;
802 currentFileSize += writeThisTime)
803 {
804 writeThisTime = min(DUMMY_BUFFER_SIZE,
805 pvfb->sizeInBytes - currentFileSize);
806 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
807 {
808 perror("write");
809 ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
810 return;
811 }
812 }
813
814 /* try to mmap the file */
815
816 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
817 PROT_READ|PROT_WRITE,
818 MAP_FILE|MAP_SHARED,
819 pvfb->mmap_fd, 0);
820 if (-1 == (long)pvfb->pXWDHeader)
821 {
822 perror("mmap");
823 ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
824 pvfb->pXWDHeader = NULL;
825 return;
826 }
827
828 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
829 NULL))
830 {
831 pvfb->pXWDHeader = NULL;
832 }
833}
834#endif /* HAS_MMAP */
835
836
837#ifdef HAS_SHM
838static void
839vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
840{
841 /* create the shared memory segment */
842
843 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
844 if (pvfb->shmid < 0)
845 {
846 perror("shmget");
847 ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
848 return;
849 }
850
851 /* try to attach it */
852
853 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
854 if (-1 == (long)pvfb->pXWDHeader)
855 {
856 perror("shmat");
857 ErrorF("shmat failed, errno %d", errno);
858 pvfb->pXWDHeader = NULL;
859 return;
860 }
861
862 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
863}
864#endif /* HAS_SHM */
865
866
Peter Åstrand8de329f2005-02-22 21:05:16 +0000867static char *
868vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000869{
Peter Åstrand8de329f2005-02-22 21:05:16 +0000870 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000871
Peter Åstrand8de329f2005-02-22 21:05:16 +0000872 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000873
Peter Åstrand8de329f2005-02-22 21:05:16 +0000874 /* Calculate how many entries in colormap. This is rather bogus, because
875 * the visuals haven't even been set up yet, but we need to know because we
876 * have to allocate space in the file for the colormap. The number 10
877 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
878 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000879
Peter Åstrand8de329f2005-02-22 21:05:16 +0000880 if (pvfb->depth <= 10)
881 { /* single index colormaps */
882 pvfb->ncolors = 1 << pvfb->depth;
883 }
884 else
885 { /* decomposed colormaps */
886 int nplanes_per_color_component = pvfb->depth / 3;
887 if (pvfb->depth % 3) nplanes_per_color_component++;
888 pvfb->ncolors = 1 << nplanes_per_color_component;
889 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000890
Peter Åstrand8de329f2005-02-22 21:05:16 +0000891 /* add extra bytes for XWDFileHeader, window name, and colormap */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000892
Peter Åstrand8de329f2005-02-22 21:05:16 +0000893 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
894 pvfb->ncolors * SIZEOF(XWDColor);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000895
Peter Åstrand8de329f2005-02-22 21:05:16 +0000896 pvfb->pXWDHeader = NULL;
897 switch (fbmemtype)
898 {
899#ifdef HAS_MMAP
900 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
901#else
902 case MMAPPED_FILE_FB: break;
903#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000904
Peter Åstrand8de329f2005-02-22 21:05:16 +0000905#ifdef HAS_SHM
906 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
907#else
908 case SHARED_MEMORY_FB: break;
909#endif
910
911 case NORMAL_MEMORY_FB:
912 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
913 break;
914 }
915
916 if (pvfb->pXWDHeader)
917 {
918 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
919 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
920 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
921
922 return pvfb->pfbMemory;
923 }
924 else
925 return NULL;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000926}
927
Peter Åstrandf9357f52005-02-22 21:08:02 +0000928static void
929vfbWriteXWDFileHeader(ScreenPtr pScreen)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000930{
Peter Åstrandf9357f52005-02-22 21:08:02 +0000931 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
932 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
933 char hostname[XWD_WINDOW_NAME_LEN];
934 unsigned long swaptest = 1;
935 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000936
Peter Åstrandf9357f52005-02-22 21:08:02 +0000937 needswap = *(char *) &swaptest;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000938
Peter Åstrandf9357f52005-02-22 21:08:02 +0000939 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
940 pXWDHeader->file_version = XWD_FILE_VERSION;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000941
Peter Åstrandf9357f52005-02-22 21:08:02 +0000942 pXWDHeader->pixmap_format = ZPixmap;
943 pXWDHeader->pixmap_depth = pvfb->depth;
944 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
945 pXWDHeader->xoffset = 0;
946 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
947 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000948#ifndef INTERNAL_VS_EXTERNAL_PADDING
Peter Åstrandf9357f52005-02-22 21:08:02 +0000949 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
950 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
951 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000952#else
Peter Åstrandf9357f52005-02-22 21:08:02 +0000953 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
954 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
955 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000956#endif
Peter Åstrandf9357f52005-02-22 21:08:02 +0000957 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
958 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
959 pXWDHeader->ncolors = pvfb->ncolors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000960
Peter Åstrandf9357f52005-02-22 21:08:02 +0000961 /* visual related fields are written when colormap is installed */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000962
Peter Åstrandf9357f52005-02-22 21:08:02 +0000963 pXWDHeader->window_x = pXWDHeader->window_y = 0;
964 pXWDHeader->window_bdrwidth = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000965
Peter Åstrandf9357f52005-02-22 21:08:02 +0000966 /* write xwd "window" name: Xvfb hostname:server.screen */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000967
Peter Åstrandf9357f52005-02-22 21:08:02 +0000968 if (-1 == gethostname(hostname, sizeof(hostname)))
969 hostname[0] = 0;
970 else
971 hostname[XWD_WINDOW_NAME_LEN-1] = 0;
972 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
973 pScreen->myNum);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000974
Peter Åstrandf9357f52005-02-22 21:08:02 +0000975 /* write colormap pixel slot values */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000976
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000977 for (i = 0; i < pvfb->ncolors; i++)
978 {
Peter Åstrandf9357f52005-02-22 21:08:02 +0000979 pvfb->pXWDCmap[i].pixel = i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000980 }
Peter Åstrandf9357f52005-02-22 21:08:02 +0000981
982 /* byte swap to most significant byte first */
983
984 if (needswap)
985 {
986 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
987 for (i = 0; i < pvfb->ncolors; i++)
988 {
989 register char n;
990 swapl(&pvfb->pXWDCmap[i].pixel, n);
991 }
992 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000993}
994
995
Peter Åstrandf9357f52005-02-22 21:08:02 +0000996static Bool
997vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
998{
999 return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001000}
Peter Åstrandf9357f52005-02-22 21:08:02 +00001001
1002static void
1003vfbCrossScreen (ScreenPtr pScreen, Bool entering)
1004{
1005}
1006
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001007static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001008 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001009}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001010
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001011static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001012 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001013}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001014
1015static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
1016{
1017}
1018
1019static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
1020{
1021}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001022
1023static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001024 vfbRealizeCursor,
1025 vfbUnrealizeCursor,
1026 vfbSetCursor,
1027 vfbMoveCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001028};
1029
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001030static miPointerScreenFuncRec vfbPointerCursorFuncs = {
1031 vfbCursorOffScreen,
1032 vfbCrossScreen,
1033 miPointerWarpCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001034};
1035
Peter Åstrand60870912005-02-22 21:27:51 +00001036static Bool
1037vfbCloseScreen(int index, ScreenPtr pScreen)
1038{
1039 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1040 int i;
1041
1042 pScreen->CloseScreen = pvfb->closeScreen;
1043
1044 /*
1045 * XXX probably lots of stuff to clean. For now,
1046 * clear InstalledMaps[] so that server reset works correctly.
1047 */
1048 for (i = 0; i < MAXSCREENS; i++)
1049 InstalledMaps[i] = NULL;
1050
1051 return pScreen->CloseScreen(index, pScreen);
1052}
1053
Peter Åstrand1d742b42005-02-22 21:33:20 +00001054static Bool
1055vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001056{
Peter Åstrand1d742b42005-02-22 21:33:20 +00001057 vfbScreenInfoPtr pvfb = &vfbScreens[index];
Peter Åstrandd6a29142005-02-23 15:22:34 +00001058 int dpi = 100;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001059 int ret;
1060 char *pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001061
Peter Åstrandd6a29142005-02-23 15:22:34 +00001062 if (monitorResolution) dpi = monitorResolution;
1063
Peter Åstrand1d742b42005-02-22 21:33:20 +00001064 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
1065 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
Peter Åstrandd6a29142005-02-23 15:22:34 +00001066 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001067 pbits = vfbAllocateFramebufferMemory(pvfb);
1068 if (!pbits) return FALSE;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001069 vncFbptr[index] = pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001070
Peter Åstrandd6a29142005-02-23 15:22:34 +00001071 defaultColorVisualClass
1072 = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001073
Peter Åstrand1d742b42005-02-22 21:33:20 +00001074 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
Peter Åstrandd6a29142005-02-23 15:22:34 +00001075 dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
1076
Peter Åstrandc5421b22005-02-14 20:25:49 +00001077#ifdef RENDER
Peter Åstrand1d742b42005-02-22 21:33:20 +00001078 if (ret && Render)
1079 fbPictureInit (pScreen, 0, 0);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001080#endif
1081
Peter Åstrand1d742b42005-02-22 21:33:20 +00001082 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001083
Peter Åstrand1d742b42005-02-22 21:33:20 +00001084 /* miInitializeBackingStore(pScreen); */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001085
Peter Åstrand1d742b42005-02-22 21:33:20 +00001086 /*
1087 * Circumvent the backing store that was just initialised. This amounts
1088 * to a truely bizarre way of initialising SaveDoomedAreas and friends.
1089 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001090
Peter Åstrand1d742b42005-02-22 21:33:20 +00001091 pScreen->InstallColormap = vfbInstallColormap;
1092 pScreen->UninstallColormap = vfbUninstallColormap;
1093 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001094
Peter Åstrand1d742b42005-02-22 21:33:20 +00001095 pScreen->SaveScreen = vfbSaveScreen;
1096 pScreen->StoreColors = vfbStoreColors;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001097
1098 miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
1099 FALSE);
1100
Peter Åstrand1d742b42005-02-22 21:33:20 +00001101 vfbWriteXWDFileHeader(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001102
Peter Åstrand1d742b42005-02-22 21:33:20 +00001103 pScreen->blackPixel = pvfb->blackPixel;
1104 pScreen->whitePixel = pvfb->whitePixel;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001105
Peter Åstrandd6a29142005-02-23 15:22:34 +00001106 if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
1107 pvfb->pixelFormatDefined = TRUE;
1108 pvfb->rgbNotBgr = TRUE;
1109 pvfb->blueBits = pvfb->redBits = 5;
1110 pvfb->greenBits = 6;
1111 }
1112
1113 if (pvfb->pixelFormatDefined) {
Peter Åstrand2e387492005-06-21 14:04:43 +00001114 VisualPtr vis = pScreen->visuals;
1115 for (int i = 0; i < pScreen->numVisuals; i++) {
1116 if (pvfb->rgbNotBgr) {
1117 vis->offsetBlue = 0;
1118 vis->blueMask = (1 << pvfb->blueBits) - 1;
1119 vis->offsetGreen = pvfb->blueBits;
1120 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1121 vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
1122 vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
1123 } else {
1124 vis->offsetRed = 0;
1125 vis->redMask = (1 << pvfb->redBits) - 1;
1126 vis->offsetGreen = pvfb->redBits;
1127 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1128 vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
1129 vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
1130 }
1131 vis++;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001132 }
1133 }
1134
Peter Åstrand1d742b42005-02-22 21:33:20 +00001135 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001136
Peter Åstrand1d742b42005-02-22 21:33:20 +00001137 miSetZeroLineBias(pScreen, pvfb->lineBias);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001138
Peter Åstrand1d742b42005-02-22 21:33:20 +00001139 pvfb->closeScreen = pScreen->CloseScreen;
1140 pScreen->CloseScreen = vfbCloseScreen;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001141
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +00001142#ifndef NO_INIT_BACKING_STORE
1143 miInitializeBackingStore(pScreen);
1144 pScreen->backingStoreSupport = Always;
1145#endif
1146
1147 return ret;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001148
1149} /* end vfbScreenInit */
1150
1151
1152static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
1153 dispatchException &= ~DE_RESET;
1154}
1155
Peter Åstrand321a9922005-02-22 21:37:32 +00001156void
1157InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001158{
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +00001159 ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
1160 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
1161 VENDOR_STRING);
Peter Åstrand321a9922005-02-22 21:37:32 +00001162 int i;
1163 int NumFormats = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001164
Peter Åstrand321a9922005-02-22 21:37:32 +00001165 /* initialize pixmap formats */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001166
Peter Åstrand321a9922005-02-22 21:37:32 +00001167 /* must have a pixmap depth to match every screen depth */
1168 for (i = 0; i < vfbNumScreens; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001169 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001170 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001171 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001172
Peter Åstrand321a9922005-02-22 21:37:32 +00001173 /* RENDER needs a good set of pixmaps. */
1174 if (Render) {
1175 vfbPixmapDepths[1] = TRUE;
1176 vfbPixmapDepths[4] = TRUE;
1177 vfbPixmapDepths[8] = TRUE;
1178/* vfbPixmapDepths[15] = TRUE; */
1179 vfbPixmapDepths[16] = TRUE;
1180 vfbPixmapDepths[24] = TRUE;
1181 vfbPixmapDepths[32] = TRUE;
1182 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001183
Peter Åstrand321a9922005-02-22 21:37:32 +00001184 for (i = 1; i <= 32; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001185 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001186 if (vfbPixmapDepths[i])
1187 {
1188 if (NumFormats >= MAXFORMATS)
1189 FatalError ("MAXFORMATS is too small for this server\n");
1190 screenInfo->formats[NumFormats].depth = i;
1191 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1192 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1193 NumFormats++;
1194 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001195 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001196
Peter Åstrand321a9922005-02-22 21:37:32 +00001197 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
1198 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1199 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1200 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
1201 screenInfo->numPixmapFormats = NumFormats;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001202
Peter Åstrand321a9922005-02-22 21:37:32 +00001203 /* initialize screens */
1204
1205 for (i = 0; i < vfbNumScreens; i++)
1206 {
1207 if (-1 == AddScreen(vfbScreenInit, argc, argv))
1208 {
1209 FatalError("Couldn't add screen %d", i);
1210 }
1211 }
1212
1213 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
1214 FatalError("AddCallback failed\n");
1215 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001216} /* end InitOutput */
1217
1218#ifdef DPMSExtension
1219extern "C" {
1220#if NeedFunctionPrototypes
1221 void DPMSSet(CARD16 level)
1222#else
1223 void DPMSSet(level)
1224 CARD16 level;
1225#endif
1226 {
1227 return;
1228 }
1229
1230 Bool DPMSSupported()
1231 {
1232 return FALSE;
1233 }
1234}
1235#endif
1236
1237/* this is just to get the server to link on AIX */
1238#ifdef AIXV3
1239int SelectWaitTime = 10000; /* usec */
1240#endif
1241
1242Bool LegalModifier(unsigned int key, DevicePtr pDev)
1243{
1244 return TRUE;
1245}
1246
1247void ProcessInputEvents()
1248{
1249 mieqProcessInputEvents();
1250 miPointerUpdate();
1251}
1252
1253/* Fairly standard US PC Keyboard */
1254
1255#define VFB_MIN_KEY 8
1256#define VFB_MAX_KEY 255
1257#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1258#define KEYSYMS_PER_KEY 2
1259KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1260 NoSymbol, NoSymbol,
1261 XK_Escape, NoSymbol,
1262 XK_1, XK_exclam,
1263 XK_2, XK_at,
1264 XK_3, XK_numbersign,
1265 XK_4, XK_dollar,
1266 XK_5, XK_percent,
1267 XK_6, XK_asciicircum,
1268 XK_7, XK_ampersand,
1269 XK_8, XK_asterisk,
1270 XK_9, XK_parenleft,
1271 XK_0, XK_parenright,
1272 XK_minus, XK_underscore,
1273 XK_equal, XK_plus,
1274 XK_BackSpace, NoSymbol,
1275 XK_Tab, NoSymbol,
1276 XK_q, XK_Q,
1277 XK_w, XK_W,
1278 XK_e, XK_E,
1279 XK_r, XK_R,
1280 XK_t, XK_T,
1281 XK_y, XK_Y,
1282 XK_u, XK_U,
1283 XK_i, XK_I,
1284 XK_o, XK_O,
1285 XK_p, XK_P,
1286 XK_bracketleft, XK_braceleft,
1287 XK_bracketright, XK_braceright,
1288 XK_Return, NoSymbol,
1289 XK_Control_L, NoSymbol,
1290 XK_a, XK_A,
1291 XK_s, XK_S,
1292 XK_d, XK_D,
1293 XK_f, XK_F,
1294 XK_g, XK_G,
1295 XK_h, XK_H,
1296 XK_j, XK_J,
1297 XK_k, XK_K,
1298 XK_l, XK_L,
1299 XK_semicolon, XK_colon,
1300 XK_apostrophe, XK_quotedbl,
1301 XK_grave, XK_asciitilde,
1302 XK_Shift_L, NoSymbol,
1303 XK_backslash, XK_bar,
1304 XK_z, XK_Z,
1305 XK_x, XK_X,
1306 XK_c, XK_C,
1307 XK_v, XK_V,
1308 XK_b, XK_B,
1309 XK_n, XK_N,
1310 XK_m, XK_M,
1311 XK_comma, XK_less,
1312 XK_period, XK_greater,
1313 XK_slash, XK_question,
1314 XK_Shift_R, NoSymbol,
1315 XK_KP_Multiply, NoSymbol,
1316 XK_Alt_L, XK_Meta_L,
1317 XK_space, NoSymbol,
1318 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1319 XK_F1, NoSymbol,
1320 XK_F2, NoSymbol,
1321 XK_F3, NoSymbol,
1322 XK_F4, NoSymbol,
1323 XK_F5, NoSymbol,
1324 XK_F6, NoSymbol,
1325 XK_F7, NoSymbol,
1326 XK_F8, NoSymbol,
1327 XK_F9, NoSymbol,
1328 XK_F10, NoSymbol,
1329 XK_Num_Lock, XK_Pointer_EnableKeys,
1330 XK_Scroll_Lock, NoSymbol,
1331 XK_KP_Home, XK_KP_7,
1332 XK_KP_Up, XK_KP_8,
1333 XK_KP_Prior, XK_KP_9,
1334 XK_KP_Subtract, NoSymbol,
1335 XK_KP_Left, XK_KP_4,
1336 XK_KP_Begin, XK_KP_5,
1337 XK_KP_Right, XK_KP_6,
1338 XK_KP_Add, NoSymbol,
1339 XK_KP_End, XK_KP_1,
1340 XK_KP_Down, XK_KP_2,
1341 XK_KP_Next, XK_KP_3,
1342 XK_KP_Insert, XK_KP_0,
1343 XK_KP_Delete, XK_KP_Decimal,
1344 NoSymbol, NoSymbol,
1345 NoSymbol, NoSymbol,
1346 NoSymbol, NoSymbol,
1347 XK_F11, NoSymbol,
1348 XK_F12, NoSymbol,
1349 XK_Home, NoSymbol,
1350 XK_Up, NoSymbol,
1351 XK_Prior, NoSymbol,
1352 XK_Left, NoSymbol,
1353 NoSymbol, NoSymbol,
1354 XK_Right, NoSymbol,
1355 XK_End, NoSymbol,
1356 XK_Down, NoSymbol,
1357 XK_Next, NoSymbol,
1358 XK_Insert, NoSymbol,
1359 XK_Delete, NoSymbol,
1360 XK_KP_Enter, NoSymbol,
1361 XK_Control_R, NoSymbol,
1362 XK_Pause, XK_Break,
1363 XK_Print, XK_Execute,
1364 XK_KP_Divide, NoSymbol,
1365 XK_Alt_R, XK_Meta_R,
1366};
1367
1368static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1369{
1370 int i;
1371
1372 for (i = 0; i < MAP_LENGTH; i++)
1373 pModMap[i] = NoSymbol;
1374
1375 for (i = 0; i < VFB_MAP_LEN; i++) {
1376 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1377 pModMap[i + VFB_MIN_KEY] = LockMask;
1378 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1379 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1380 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1381 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1382 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1383 pModMap[i + VFB_MIN_KEY] = ControlMask;
1384 }
1385 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1386 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1387 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1388 }
1389
1390 pKeySyms->minKeyCode = VFB_MIN_KEY;
1391 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1392 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1393 pKeySyms->map = keyboardMap;
1394
1395 return TRUE;
1396}
1397
1398static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1399{
1400 if (percent > 0)
1401 vncBell();
1402}
1403
1404static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1405{
1406 KeySymsRec keySyms;
1407 CARD8 modMap[MAP_LENGTH];
1408 DevicePtr pDev = (DevicePtr)pDevice;
1409
1410 switch (onoff)
1411 {
1412 case DEVICE_INIT:
1413 GetMappings(&keySyms, modMap);
1414 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1415 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1416 break;
1417 case DEVICE_ON:
1418 pDev->on = TRUE;
1419 break;
1420 case DEVICE_OFF:
1421 pDev->on = FALSE;
1422 break;
1423 case DEVICE_CLOSE:
1424 break;
1425 }
1426 return Success;
1427}
1428
1429static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1430{
1431 BYTE map[6];
1432 DevicePtr pDev = (DevicePtr)pDevice;
1433
1434 switch (onoff)
1435 {
1436 case DEVICE_INIT:
1437 map[1] = 1;
1438 map[2] = 2;
1439 map[3] = 3;
1440 map[4] = 4;
1441 map[5] = 5;
1442 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1443 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1444 break;
1445
1446 case DEVICE_ON:
1447 pDev->on = TRUE;
1448 break;
1449
1450 case DEVICE_OFF:
1451 pDev->on = FALSE;
1452 break;
1453
1454 case DEVICE_CLOSE:
1455 break;
1456 }
1457 return Success;
1458}
1459
1460// InitInput is called after InitExtensions, so we're guaranteed that
1461// vncExtensionInit() has already been called.
1462
1463void InitInput(int argc, char *argv[])
1464{
1465 DeviceIntPtr p, k;
1466 p = AddInputDevice(vfbMouseProc, TRUE);
1467 k = AddInputDevice(vfbKeybdProc, TRUE);
1468 RegisterPointerDevice(p);
1469 RegisterKeyboardDevice(k);
1470 miRegisterPointerDevice(screenInfo.screens[0], p);
1471 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1472}