blob: fcb73e65c0a98f0e32f436b3c43994557e5d5dc3 [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
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +000090#define XVNCVERSION "Free Edition 4.1.1"
91#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
92 "See http://www.realvnc.com for information on VNC.\n")
93
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000094
95extern char *display;
96extern int monitorResolution;
97
98#define VFB_DEFAULT_WIDTH 1024
99#define VFB_DEFAULT_HEIGHT 768
100#define VFB_DEFAULT_DEPTH 16
101#define VFB_DEFAULT_WHITEPIXEL 0xffff
102#define VFB_DEFAULT_BLACKPIXEL 0
103#define VFB_DEFAULT_LINEBIAS 0
104#define XWD_WINDOW_NAME_LEN 60
105
106typedef struct
107{
Peter Åstrand60870912005-02-22 21:27:51 +0000108 int scrnum;
109 int width;
110 int paddedBytesWidth;
111 int paddedWidth;
112 int height;
113 int depth;
114 int bitsPerPixel;
115 int sizeInBytes;
116 int ncolors;
117 char *pfbMemory;
118 XWDColor *pXWDCmap;
119 XWDFileHeader *pXWDHeader;
120 Pixel blackPixel;
121 Pixel whitePixel;
122 unsigned int lineBias;
123 CloseScreenProcPtr closeScreen;
124
125#ifdef HAS_MMAP
126 int mmap_fd;
127 char mmap_file[MAXPATHLEN];
128#endif
129
130#ifdef HAS_SHM
131 int shmid;
132#endif
133
134 Bool pixelFormatDefined;
135 Bool rgbNotBgr;
136 int redBits, greenBits, blueBits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000137
138} vfbScreenInfo, *vfbScreenInfoPtr;
139
140static int vfbNumScreens;
141static vfbScreenInfo vfbScreens[MAXSCREENS];
142static Bool vfbPixmapDepths[33];
Peter Åstrand00c759d2005-02-22 20:11:47 +0000143#ifdef HAS_MMAP
144static char *pfbdir = NULL;
145#endif
146typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
147static fbMemType fbmemtype = NORMAL_MEMORY_FB;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000148static char needswap = 0;
149static int lastScreen = -1;
Peter Åstrandc5421b22005-02-14 20:25:49 +0000150static Bool Render = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000151
152static bool displaySpecified = false;
153static bool wellKnownSocketsCreated = false;
154static char displayNumStr[16];
155
156#define swapcopy16(_dst, _src) \
157 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
158 else _dst = _src;
159
160#define swapcopy32(_dst, _src) \
161 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
162 else _dst = _src;
163
164
Peter Åstrandf960f042005-02-22 20:07:55 +0000165static void
166vfbInitializePixmapDepths(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000167{
Peter Åstrandf960f042005-02-22 20:07:55 +0000168 int i;
169 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
170 for (i = 2; i <= 32; i++)
171 vfbPixmapDepths[i] = FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000172}
173
Peter Åstrandf960f042005-02-22 20:07:55 +0000174static void
175vfbInitializeDefaultScreens(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000176{
Peter Åstrandf960f042005-02-22 20:07:55 +0000177 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000178
Peter Åstrandf960f042005-02-22 20:07:55 +0000179 for (i = 0; i < MAXSCREENS; i++)
180 {
181 vfbScreens[i].scrnum = i;
182 vfbScreens[i].width = VFB_DEFAULT_WIDTH;
183 vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
184 vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
185 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
186 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
187 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
188 vfbScreens[i].pixelFormatDefined = FALSE;
189 vfbScreens[i].pfbMemory = NULL;
190 }
191 vfbNumScreens = 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000192}
193
Peter Åstrand00c759d2005-02-22 20:11:47 +0000194static int
195vfbBitsPerPixel(int depth)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000196{
Peter Åstrand00c759d2005-02-22 20:11:47 +0000197 if (depth == 1) return 1;
198 else if (depth <= 8) return 8;
199 else if (depth <= 16) return 16;
200 else return 32;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000201}
202
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000203
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000204extern "C" {
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000205
206 /* ddxInitGlobals - called by |InitGlobals| from os/util.c in XOrg */
207 void ddxInitGlobals(void)
208 {
209 }
210
211 void ddxGiveUp()
212 {
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000213 int i;
214
215 /* clean up the framebuffers */
216
Peter Åstrand00c759d2005-02-22 20:11:47 +0000217 switch (fbmemtype)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000218 {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000219#ifdef HAS_MMAP
220 case MMAPPED_FILE_FB:
221 for (i = 0; i < vfbNumScreens; i++)
222 {
223 if (-1 == unlink(vfbScreens[i].mmap_file))
224 {
225 perror("unlink");
226 ErrorF("unlink %s failed, errno %d",
227 vfbScreens[i].mmap_file, errno);
228 }
229 }
230 break;
231#else /* HAS_MMAP */
232 case MMAPPED_FILE_FB:
233 break;
234#endif /* HAS_MMAP */
235
236#ifdef HAS_SHM
237 case SHARED_MEMORY_FB:
238 for (i = 0; i < vfbNumScreens; i++)
239 {
240 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
241 {
242 perror("shmdt");
243 ErrorF("shmdt failed, errno %d", errno);
244 }
245 }
246 break;
247#else /* HAS_SHM */
248 case SHARED_MEMORY_FB:
249 break;
250#endif /* HAS_SHM */
251
252 case NORMAL_MEMORY_FB:
253 for (i = 0; i < vfbNumScreens; i++)
254 {
255 Xfree(vfbScreens[i].pXWDHeader);
256 }
257 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000258 }
Peter Åstrand00c759d2005-02-22 20:11:47 +0000259}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000260
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000261void
262AbortDDX()
263{
264 ddxGiveUp();
265}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000266
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000267#ifdef __DARWIN__
268void
269DarwinHandleGUI(int argc, char *argv[])
270{
271}
272
273void GlxExtensionInit();
274void GlxWrapInitVisuals(void *procPtr);
275
276void
277DarwinGlxExtensionInit()
278{
279 GlxExtensionInit();
280}
281
282void
283DarwinGlxWrapInitVisuals(
284 void *procPtr)
285{
286 GlxWrapInitVisuals(procPtr);
287}
288#endif
289
290void
291OsVendorInit()
292{
293}
294
295void
296OsVendorFatalError()
297{
298}
299
300void ddxBeforeReset(void)
301{
302 return;
303}
304
305void
306ddxUseMsg()
307{
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +0000308 ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000309 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
310 VENDOR_STRING);
311 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
312 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
Peter Åstrandc5421b22005-02-14 20:25:49 +0000313#ifdef RENDER
314 ErrorF("+/-render turn on/off RENDER extension support"
315 "(default on)\n");
316#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000317 ErrorF("-linebias n adjust thin line pixelization\n");
318 ErrorF("-blackpixel n pixel value for black\n");
319 ErrorF("-whitepixel n pixel value for white\n");
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000320
321#ifdef HAS_MMAP
322 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
323#endif
324
325#ifdef HAS_SHM
326 ErrorF("-shmem put framebuffers in shared memory\n");
327#endif
328
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000329 ErrorF("-geometry WxH set screen 0's width, height\n");
330 ErrorF("-depth D set screen 0's depth\n");
331 ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
332 ErrorF("-inetd has been launched from inetd\n");
333 ErrorF("\nVNC parameters:\n");
334
335 fprintf(stderr,"\n"
336 "Parameters can be turned on with -<param> or off with -<param>=0\n"
337 "Parameters which take a value can be specified as "
338 "-<param> <value>\n"
339 "Other valid forms are <param>=<value> -<param>=<value> "
340 "--<param>=<value>\n"
341 "Parameter names are case-insensitive. The parameters are:\n\n");
342 rfb::Configuration::listParams(79, 14);
343 }
344}
345
Peter Åstrandfc41a212005-02-22 20:29:40 +0000346/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
347void ddxInitGlobals(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000348{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000349}
350
Peter Åstrandfc41a212005-02-22 20:29:40 +0000351static
352bool displayNumFree(int num)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000353{
Peter Åstrandfc41a212005-02-22 20:29:40 +0000354 try {
355 network::TcpListener l(6000+num);
356 } catch (rdr::Exception& e) {
357 return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000358 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000359 char file[256];
360 sprintf(file, "/tmp/.X%d-lock", num);
361 if (access(file, F_OK) == 0) return false;
362 sprintf(file, "/tmp/.X11-unix/X%d", num);
363 if (access(file, F_OK) == 0) return false;
364 sprintf(file, "/usr/spool/sockets/X11/%d", num);
365 if (access(file, F_OK) == 0) return false;
366 return true;
367}
368
369int
370ddxProcessArgument(int argc, char *argv[], int i)
371{
372 static Bool firstTime = TRUE;
373
374 if (firstTime)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000375 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000376 vfbInitializeDefaultScreens();
377 vfbInitializePixmapDepths();
378 firstTime = FALSE;
379 rfb::initStdIOLoggers();
380 rfb::LogWriter::setLogParams("*:stderr:30");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000381 }
382
Peter Åstrandfc41a212005-02-22 20:29:40 +0000383 if (argv[i][0] == ':')
384 displaySpecified = true;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000385
Peter Åstrandfc41a212005-02-22 20:29:40 +0000386 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000387 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000388 int screenNum;
389 if (i + 2 >= argc) UseMsg();
390 screenNum = atoi(argv[i+1]);
391 if (screenNum < 0 || screenNum >= MAXSCREENS)
392 {
393 ErrorF("Invalid screen number %d\n", screenNum);
394 UseMsg();
395 }
396 if (3 != sscanf(argv[i+2], "%dx%dx%d",
397 &vfbScreens[screenNum].width,
398 &vfbScreens[screenNum].height,
399 &vfbScreens[screenNum].depth))
400 {
401 ErrorF("Invalid screen configuration %s\n", argv[i+2]);
402 UseMsg();
403 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000404
Peter Åstrandfc41a212005-02-22 20:29:40 +0000405 if (screenNum >= vfbNumScreens)
406 vfbNumScreens = screenNum + 1;
407 lastScreen = screenNum;
408 return 3;
409 }
410
411 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
412 {
413 int depth, ret = 1;
414
415 if (++i >= argc) UseMsg();
416 while ((i < argc) && (depth = atoi(argv[i++])) != 0)
417 {
418 if (depth < 0 || depth > 32)
419 {
420 ErrorF("Invalid pixmap depth %d\n", depth);
421 UseMsg();
422 }
423 vfbPixmapDepths[depth] = TRUE;
424 ret++;
425 }
426 return ret;
427 }
428
429 if (strcmp (argv[i], "+render") == 0) /* +render */
430 {
431 Render = TRUE;
432 return 1;
433 }
Peter Åstrandc5421b22005-02-14 20:25:49 +0000434
Peter Åstrandfc41a212005-02-22 20:29:40 +0000435 if (strcmp (argv[i], "-render") == 0) /* -render */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000436 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000437 Render = FALSE;
438 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000439 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000440
Peter Åstrandfc41a212005-02-22 20:29:40 +0000441 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000442 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000443 Pixel pix;
444 if (++i >= argc) UseMsg();
445 pix = atoi(argv[i]);
446 if (-1 == lastScreen)
447 {
448 int i;
449 for (i = 0; i < MAXSCREENS; i++)
450 {
451 vfbScreens[i].blackPixel = pix;
452 }
453 }
454 else
455 {
456 vfbScreens[lastScreen].blackPixel = pix;
457 }
458 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000459 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000460
461 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000462 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000463 Pixel pix;
464 if (++i >= argc) UseMsg();
465 pix = atoi(argv[i]);
466 if (-1 == lastScreen)
467 {
468 int i;
469 for (i = 0; i < MAXSCREENS; i++)
470 {
471 vfbScreens[i].whitePixel = pix;
472 }
473 }
474 else
475 {
476 vfbScreens[lastScreen].whitePixel = pix;
477 }
478 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000479 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000480
481 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000482 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000483 unsigned int linebias;
484 if (++i >= argc) UseMsg();
485 linebias = atoi(argv[i]);
486 if (-1 == lastScreen)
487 {
488 int i;
489 for (i = 0; i < MAXSCREENS; i++)
490 {
491 vfbScreens[i].lineBias = linebias;
492 }
493 }
494 else
495 {
496 vfbScreens[lastScreen].lineBias = linebias;
497 }
498 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000499 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000500
501#ifdef HAS_MMAP
502 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000503 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000504 if (++i >= argc) UseMsg();
505 pfbdir = argv[i];
506 fbmemtype = MMAPPED_FILE_FB;
507 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000508 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000509#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000510
Peter Åstrandfc41a212005-02-22 20:29:40 +0000511#ifdef HAS_SHM
512 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
513 {
514 fbmemtype = SHARED_MEMORY_FB;
515 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000516 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000517#endif
518
519 if (strcmp(argv[i], "-geometry") == 0)
520 {
521 if (++i >= argc) UseMsg();
522 if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
523 &vfbScreens[0].height) != 2) {
524 ErrorF("Invalid geometry %s\n", argv[i]);
525 UseMsg();
526 }
527 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000528 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000529
530 if (strcmp(argv[i], "-depth") == 0)
531 {
532 if (++i >= argc) UseMsg();
533 vfbScreens[0].depth = atoi(argv[i]);
534 return 2;
535 }
536
537 if (strcmp(argv[i], "-pixelformat") == 0)
538 {
539 char rgbbgr[4];
540 int bits1, bits2, bits3;
541 if (++i >= argc) UseMsg();
542 if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
543 ErrorF("Invalid pixel format %s\n", argv[i]);
544 UseMsg();
545 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000546
547#define SET_PIXEL_FORMAT(vfbScreen) \
548 (vfbScreen).pixelFormatDefined = TRUE; \
549 (vfbScreen).depth = bits1 + bits2 + bits3; \
550 (vfbScreen).greenBits = bits2; \
551 if (strcasecmp(rgbbgr, "bgr") == 0) { \
552 (vfbScreen).rgbNotBgr = FALSE; \
553 (vfbScreen).redBits = bits3; \
554 (vfbScreen).blueBits = bits1; \
555 } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
556 (vfbScreen).rgbNotBgr = TRUE; \
557 (vfbScreen).redBits = bits1; \
558 (vfbScreen).blueBits = bits3; \
559 } else { \
560 ErrorF("Invalid pixel format %s\n", argv[i]); \
561 UseMsg(); \
562 }
563
Peter Åstrandfc41a212005-02-22 20:29:40 +0000564 if (-1 == lastScreen)
565 {
566 int i;
567 for (i = 0; i < MAXSCREENS; i++)
568 {
569 SET_PIXEL_FORMAT(vfbScreens[i]);
570 }
571 }
572 else
573 {
574 SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
575 }
576
577 return 2;
578 }
579
580 if (strcmp(argv[i], "-inetd") == 0)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000581 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000582 dup2(0,3);
583 vncInetdSock = 3;
584 close(2);
585
586 if (!displaySpecified) {
587 int port = network::TcpSocket::getSockPort(vncInetdSock);
588 int displayNum = port - 5900;
589 if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
590 for (displayNum = 1; displayNum < 100; displayNum++)
591 if (displayNumFree(displayNum)) break;
592
593 if (displayNum == 100)
594 FatalError("Xvnc error: no free display number for -inetd");
595 }
596
597 display = displayNumStr;
598 sprintf(displayNumStr, "%d", displayNum);
599 }
600
601 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000602 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000603
604 if (rfb::Configuration::setParam(argv[i]))
605 return 1;
606
607 if (argv[i][0] == '-' && i+1 < argc) {
608 if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
609 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000610 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000611
612 return 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000613}
614
615#ifdef DDXTIME /* from ServerOSDefines */
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000616CARD32
617GetTimeInMillis()
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000618{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000619 struct timeval tp;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000620
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000621 X_GETTIMEOFDAY(&tp);
622 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000623}
624#endif
625
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000626static ColormapPtr InstalledMaps[MAXSCREENS];
627
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000628static int
629vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000630{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000631 /* By the time we are processing requests, we can guarantee that there
632 * is always a colormap installed */
633 *pmaps = InstalledMaps[pScreen->myNum]->mid;
634 return (1);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000635}
636
637
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000638static void
639vfbInstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000640{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000641 int index = pmap->pScreen->myNum;
642 ColormapPtr oldpmap = InstalledMaps[index];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000643
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000644 if (pmap != oldpmap)
645 {
646 int entries;
647 XWDFileHeader *pXWDHeader;
648 XWDColor *pXWDCmap;
649 VisualPtr pVisual;
650 Pixel * ppix;
651 xrgb * prgb;
652 xColorItem *defs;
653 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000654
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000655 if(oldpmap != (ColormapPtr)None)
656 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
657 /* Install pmap */
658 InstalledMaps[index] = pmap;
659 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000660
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000661 entries = pmap->pVisual->ColormapEntries;
662 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
663 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
664 pVisual = pmap->pVisual;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000665
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000666 swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
667 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
668 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
669 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
670 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
671 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000672
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000673 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
674 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
675 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000676
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000677 for (i = 0; i < entries; i++) ppix[i] = i;
678 /* XXX truecolor */
679 QueryColors(pmap, entries, ppix, prgb);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000680
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000681 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
682 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
683 defs[i].red = prgb[i].red;
684 defs[i].green = prgb[i].green;
685 defs[i].blue = prgb[i].blue;
686 defs[i].flags = DoRed|DoGreen|DoBlue;
687 }
688 (*pmap->pScreen->StoreColors)(pmap, entries, defs);
689
690 DEALLOCATE_LOCAL(ppix);
691 DEALLOCATE_LOCAL(prgb);
692 DEALLOCATE_LOCAL(defs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000693 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000694}
695
Peter Åstrand853287d2005-02-22 20:46:58 +0000696static void
697vfbUninstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000698{
Peter Åstrand853287d2005-02-22 20:46:58 +0000699 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000700
Peter Åstrand853287d2005-02-22 20:46:58 +0000701 if(pmap == curpmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000702 {
Peter Åstrand853287d2005-02-22 20:46:58 +0000703 if (pmap->mid != pmap->pScreen->defColormap)
704 {
705 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
706 RT_COLORMAP);
707 (*pmap->pScreen->InstallColormap)(curpmap);
708 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000709 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000710}
711
Peter Åstrand853287d2005-02-22 20:46:58 +0000712static void
713vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000714{
Peter Åstrand853287d2005-02-22 20:46:58 +0000715 XWDColor *pXWDCmap;
716 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000717
Peter Åstrand853287d2005-02-22 20:46:58 +0000718 if (pmap != InstalledMaps[pmap->pScreen->myNum])
719 {
720 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000721 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000722
723 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
724
Peter Åstrandbe228572005-02-22 20:48:29 +0000725 if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
Peter Åstrand853287d2005-02-22 20:46:58 +0000726 {
727 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000728 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000729
730 for (i = 0; i < ndef; i++)
731 {
732 if (pdefs[i].flags & DoRed)
733 {
734 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
735 }
736 if (pdefs[i].flags & DoGreen)
737 {
738 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
739 }
740 if (pdefs[i].flags & DoBlue)
741 {
742 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
743 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000744 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000745}
746
Peter Åstrand853287d2005-02-22 20:46:58 +0000747static Bool
748vfbSaveScreen(ScreenPtr pScreen, int on)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000749{
Peter Åstrand853287d2005-02-22 20:46:58 +0000750 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000751}
752
Peter Åstrand1402f8c2005-02-23 08:22:10 +0000753#ifdef HAS_MMAP
754
755/* this flushes any changes to the screens out to the mmapped file */
756static void
757vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
758{
759 int i;
760
761 for (i = 0; i < vfbNumScreens; i++)
762 {
763#ifdef MS_ASYNC
764 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
765 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
766#else
767 /* silly NetBSD and who else? */
768 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
769 (size_t)vfbScreens[i].sizeInBytes))
770#endif
771 {
772 perror("msync");
773 ErrorF("msync failed, errno %d", errno);
774 }
775 }
776}
777
778
779static void
780vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
781{
782}
783
784
785static void
786vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
787{
788#define DUMMY_BUFFER_SIZE 65536
789 char dummyBuffer[DUMMY_BUFFER_SIZE];
790 int currentFileSize, writeThisTime;
791
792 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
793 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
794 {
795 perror("open");
796 ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
797 return;
798 }
799
800 /* Extend the file to be the proper size */
801
802 bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
803 for (currentFileSize = 0;
804 currentFileSize < pvfb->sizeInBytes;
805 currentFileSize += writeThisTime)
806 {
807 writeThisTime = min(DUMMY_BUFFER_SIZE,
808 pvfb->sizeInBytes - currentFileSize);
809 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
810 {
811 perror("write");
812 ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
813 return;
814 }
815 }
816
817 /* try to mmap the file */
818
819 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
820 PROT_READ|PROT_WRITE,
821 MAP_FILE|MAP_SHARED,
822 pvfb->mmap_fd, 0);
823 if (-1 == (long)pvfb->pXWDHeader)
824 {
825 perror("mmap");
826 ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
827 pvfb->pXWDHeader = NULL;
828 return;
829 }
830
831 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
832 NULL))
833 {
834 pvfb->pXWDHeader = NULL;
835 }
836}
837#endif /* HAS_MMAP */
838
839
840#ifdef HAS_SHM
841static void
842vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
843{
844 /* create the shared memory segment */
845
846 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
847 if (pvfb->shmid < 0)
848 {
849 perror("shmget");
850 ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
851 return;
852 }
853
854 /* try to attach it */
855
856 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
857 if (-1 == (long)pvfb->pXWDHeader)
858 {
859 perror("shmat");
860 ErrorF("shmat failed, errno %d", errno);
861 pvfb->pXWDHeader = NULL;
862 return;
863 }
864
865 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
866}
867#endif /* HAS_SHM */
868
869
Peter Åstrand8de329f2005-02-22 21:05:16 +0000870static char *
871vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000872{
Peter Åstrand8de329f2005-02-22 21:05:16 +0000873 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000874
Peter Åstrand8de329f2005-02-22 21:05:16 +0000875 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000876
Peter Åstrand8de329f2005-02-22 21:05:16 +0000877 /* Calculate how many entries in colormap. This is rather bogus, because
878 * the visuals haven't even been set up yet, but we need to know because we
879 * have to allocate space in the file for the colormap. The number 10
880 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
881 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000882
Peter Åstrand8de329f2005-02-22 21:05:16 +0000883 if (pvfb->depth <= 10)
884 { /* single index colormaps */
885 pvfb->ncolors = 1 << pvfb->depth;
886 }
887 else
888 { /* decomposed colormaps */
889 int nplanes_per_color_component = pvfb->depth / 3;
890 if (pvfb->depth % 3) nplanes_per_color_component++;
891 pvfb->ncolors = 1 << nplanes_per_color_component;
892 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000893
Peter Åstrand8de329f2005-02-22 21:05:16 +0000894 /* add extra bytes for XWDFileHeader, window name, and colormap */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000895
Peter Åstrand8de329f2005-02-22 21:05:16 +0000896 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
897 pvfb->ncolors * SIZEOF(XWDColor);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000898
Peter Åstrand8de329f2005-02-22 21:05:16 +0000899 pvfb->pXWDHeader = NULL;
900 switch (fbmemtype)
901 {
902#ifdef HAS_MMAP
903 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
904#else
905 case MMAPPED_FILE_FB: break;
906#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000907
Peter Åstrand8de329f2005-02-22 21:05:16 +0000908#ifdef HAS_SHM
909 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
910#else
911 case SHARED_MEMORY_FB: break;
912#endif
913
914 case NORMAL_MEMORY_FB:
915 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
916 break;
917 }
918
919 if (pvfb->pXWDHeader)
920 {
921 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
922 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
923 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
924
925 return pvfb->pfbMemory;
926 }
927 else
928 return NULL;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000929}
930
Peter Åstrandf9357f52005-02-22 21:08:02 +0000931static void
932vfbWriteXWDFileHeader(ScreenPtr pScreen)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000933{
Peter Åstrandf9357f52005-02-22 21:08:02 +0000934 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
935 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
936 char hostname[XWD_WINDOW_NAME_LEN];
937 unsigned long swaptest = 1;
938 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000939
Peter Åstrandf9357f52005-02-22 21:08:02 +0000940 needswap = *(char *) &swaptest;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000941
Peter Åstrandf9357f52005-02-22 21:08:02 +0000942 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
943 pXWDHeader->file_version = XWD_FILE_VERSION;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000944
Peter Åstrandf9357f52005-02-22 21:08:02 +0000945 pXWDHeader->pixmap_format = ZPixmap;
946 pXWDHeader->pixmap_depth = pvfb->depth;
947 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
948 pXWDHeader->xoffset = 0;
949 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
950 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000951#ifndef INTERNAL_VS_EXTERNAL_PADDING
Peter Åstrandf9357f52005-02-22 21:08:02 +0000952 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
953 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
954 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000955#else
Peter Åstrandf9357f52005-02-22 21:08:02 +0000956 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
957 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
958 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000959#endif
Peter Åstrandf9357f52005-02-22 21:08:02 +0000960 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
961 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
962 pXWDHeader->ncolors = pvfb->ncolors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000963
Peter Åstrandf9357f52005-02-22 21:08:02 +0000964 /* visual related fields are written when colormap is installed */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000965
Peter Åstrandf9357f52005-02-22 21:08:02 +0000966 pXWDHeader->window_x = pXWDHeader->window_y = 0;
967 pXWDHeader->window_bdrwidth = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000968
Peter Åstrandf9357f52005-02-22 21:08:02 +0000969 /* write xwd "window" name: Xvfb hostname:server.screen */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000970
Peter Åstrandf9357f52005-02-22 21:08:02 +0000971 if (-1 == gethostname(hostname, sizeof(hostname)))
972 hostname[0] = 0;
973 else
974 hostname[XWD_WINDOW_NAME_LEN-1] = 0;
975 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
976 pScreen->myNum);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000977
Peter Åstrandf9357f52005-02-22 21:08:02 +0000978 /* write colormap pixel slot values */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000979
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000980 for (i = 0; i < pvfb->ncolors; i++)
981 {
Peter Åstrandf9357f52005-02-22 21:08:02 +0000982 pvfb->pXWDCmap[i].pixel = i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000983 }
Peter Åstrandf9357f52005-02-22 21:08:02 +0000984
985 /* byte swap to most significant byte first */
986
987 if (needswap)
988 {
989 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
990 for (i = 0; i < pvfb->ncolors; i++)
991 {
992 register char n;
993 swapl(&pvfb->pXWDCmap[i].pixel, n);
994 }
995 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000996}
997
998
Peter Åstrandf9357f52005-02-22 21:08:02 +0000999static Bool
1000vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
1001{
1002 return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001003}
Peter Åstrandf9357f52005-02-22 21:08:02 +00001004
1005static void
1006vfbCrossScreen (ScreenPtr pScreen, Bool entering)
1007{
1008}
1009
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001010static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001011 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001012}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001013
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001014static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001015 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001016}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001017
1018static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
1019{
1020}
1021
1022static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
1023{
1024}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001025
1026static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001027 vfbRealizeCursor,
1028 vfbUnrealizeCursor,
1029 vfbSetCursor,
1030 vfbMoveCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001031};
1032
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001033static miPointerScreenFuncRec vfbPointerCursorFuncs = {
1034 vfbCursorOffScreen,
1035 vfbCrossScreen,
1036 miPointerWarpCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001037};
1038
Peter Åstrand60870912005-02-22 21:27:51 +00001039static Bool
1040vfbCloseScreen(int index, ScreenPtr pScreen)
1041{
1042 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1043 int i;
1044
1045 pScreen->CloseScreen = pvfb->closeScreen;
1046
1047 /*
1048 * XXX probably lots of stuff to clean. For now,
1049 * clear InstalledMaps[] so that server reset works correctly.
1050 */
1051 for (i = 0; i < MAXSCREENS; i++)
1052 InstalledMaps[i] = NULL;
1053
1054 return pScreen->CloseScreen(index, pScreen);
1055}
1056
Peter Åstrand1d742b42005-02-22 21:33:20 +00001057static Bool
1058vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001059{
Peter Åstrand1d742b42005-02-22 21:33:20 +00001060 vfbScreenInfoPtr pvfb = &vfbScreens[index];
Peter Åstrandd6a29142005-02-23 15:22:34 +00001061 int dpi = 100;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001062 int ret;
1063 char *pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001064
Peter Åstrandd6a29142005-02-23 15:22:34 +00001065 if (monitorResolution) dpi = monitorResolution;
1066
Peter Åstrand1d742b42005-02-22 21:33:20 +00001067 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
1068 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
Peter Åstrandd6a29142005-02-23 15:22:34 +00001069 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001070 pbits = vfbAllocateFramebufferMemory(pvfb);
1071 if (!pbits) return FALSE;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001072 vncFbptr[index] = pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001073
Peter Åstrandd6a29142005-02-23 15:22:34 +00001074 defaultColorVisualClass
1075 = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001076
Peter Åstrand1d742b42005-02-22 21:33:20 +00001077 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
Peter Åstrandd6a29142005-02-23 15:22:34 +00001078 dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
1079
Peter Åstrandc5421b22005-02-14 20:25:49 +00001080#ifdef RENDER
Peter Åstrand1d742b42005-02-22 21:33:20 +00001081 if (ret && Render)
1082 fbPictureInit (pScreen, 0, 0);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001083#endif
1084
Peter Åstrand1d742b42005-02-22 21:33:20 +00001085 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001086
Peter Åstrand1d742b42005-02-22 21:33:20 +00001087 /* miInitializeBackingStore(pScreen); */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001088
Peter Åstrand1d742b42005-02-22 21:33:20 +00001089 /*
1090 * Circumvent the backing store that was just initialised. This amounts
1091 * to a truely bizarre way of initialising SaveDoomedAreas and friends.
1092 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001093
Peter Åstrand1d742b42005-02-22 21:33:20 +00001094 pScreen->InstallColormap = vfbInstallColormap;
1095 pScreen->UninstallColormap = vfbUninstallColormap;
1096 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001097
Peter Åstrand1d742b42005-02-22 21:33:20 +00001098 pScreen->SaveScreen = vfbSaveScreen;
1099 pScreen->StoreColors = vfbStoreColors;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001100
1101 miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
1102 FALSE);
1103
Peter Åstrand1d742b42005-02-22 21:33:20 +00001104 vfbWriteXWDFileHeader(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001105
Peter Åstrand1d742b42005-02-22 21:33:20 +00001106 pScreen->blackPixel = pvfb->blackPixel;
1107 pScreen->whitePixel = pvfb->whitePixel;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001108
Peter Åstrandd6a29142005-02-23 15:22:34 +00001109 if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
1110 pvfb->pixelFormatDefined = TRUE;
1111 pvfb->rgbNotBgr = TRUE;
1112 pvfb->blueBits = pvfb->redBits = 5;
1113 pvfb->greenBits = 6;
1114 }
1115
1116 if (pvfb->pixelFormatDefined) {
Peter Åstrand2e387492005-06-21 14:04:43 +00001117 VisualPtr vis = pScreen->visuals;
1118 for (int i = 0; i < pScreen->numVisuals; i++) {
1119 if (pvfb->rgbNotBgr) {
1120 vis->offsetBlue = 0;
1121 vis->blueMask = (1 << pvfb->blueBits) - 1;
1122 vis->offsetGreen = pvfb->blueBits;
1123 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1124 vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
1125 vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
1126 } else {
1127 vis->offsetRed = 0;
1128 vis->redMask = (1 << pvfb->redBits) - 1;
1129 vis->offsetGreen = pvfb->redBits;
1130 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1131 vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
1132 vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
1133 }
1134 vis++;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001135 }
1136 }
1137
Peter Åstrand1d742b42005-02-22 21:33:20 +00001138 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001139
Peter Åstrand1d742b42005-02-22 21:33:20 +00001140 miSetZeroLineBias(pScreen, pvfb->lineBias);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001141
Peter Åstrand1d742b42005-02-22 21:33:20 +00001142 pvfb->closeScreen = pScreen->CloseScreen;
1143 pScreen->CloseScreen = vfbCloseScreen;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001144
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +00001145#ifndef NO_INIT_BACKING_STORE
1146 miInitializeBackingStore(pScreen);
1147 pScreen->backingStoreSupport = Always;
1148#endif
1149
1150 return ret;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001151
1152} /* end vfbScreenInit */
1153
1154
1155static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
1156 dispatchException &= ~DE_RESET;
1157}
1158
Peter Åstrand321a9922005-02-22 21:37:32 +00001159void
1160InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001161{
Constantin Kaplinsky95f6f7a2006-04-17 04:17:23 +00001162 ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
1163 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
1164 VENDOR_STRING);
Peter Åstrand321a9922005-02-22 21:37:32 +00001165 int i;
1166 int NumFormats = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001167
Peter Åstrand321a9922005-02-22 21:37:32 +00001168 /* initialize pixmap formats */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001169
Peter Åstrand321a9922005-02-22 21:37:32 +00001170 /* must have a pixmap depth to match every screen depth */
1171 for (i = 0; i < vfbNumScreens; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001172 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001173 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001174 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001175
Peter Åstrand321a9922005-02-22 21:37:32 +00001176 /* RENDER needs a good set of pixmaps. */
1177 if (Render) {
1178 vfbPixmapDepths[1] = TRUE;
1179 vfbPixmapDepths[4] = TRUE;
1180 vfbPixmapDepths[8] = TRUE;
1181/* vfbPixmapDepths[15] = TRUE; */
1182 vfbPixmapDepths[16] = TRUE;
1183 vfbPixmapDepths[24] = TRUE;
1184 vfbPixmapDepths[32] = TRUE;
1185 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001186
Peter Åstrand321a9922005-02-22 21:37:32 +00001187 for (i = 1; i <= 32; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001188 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001189 if (vfbPixmapDepths[i])
1190 {
1191 if (NumFormats >= MAXFORMATS)
1192 FatalError ("MAXFORMATS is too small for this server\n");
1193 screenInfo->formats[NumFormats].depth = i;
1194 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1195 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1196 NumFormats++;
1197 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001198 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001199
Peter Åstrand321a9922005-02-22 21:37:32 +00001200 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
1201 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1202 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1203 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
1204 screenInfo->numPixmapFormats = NumFormats;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001205
Peter Åstrand321a9922005-02-22 21:37:32 +00001206 /* initialize screens */
1207
1208 for (i = 0; i < vfbNumScreens; i++)
1209 {
1210 if (-1 == AddScreen(vfbScreenInit, argc, argv))
1211 {
1212 FatalError("Couldn't add screen %d", i);
1213 }
1214 }
1215
1216 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
1217 FatalError("AddCallback failed\n");
1218 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001219} /* end InitOutput */
1220
1221#ifdef DPMSExtension
1222extern "C" {
1223#if NeedFunctionPrototypes
1224 void DPMSSet(CARD16 level)
1225#else
1226 void DPMSSet(level)
1227 CARD16 level;
1228#endif
1229 {
1230 return;
1231 }
1232
1233 Bool DPMSSupported()
1234 {
1235 return FALSE;
1236 }
1237}
1238#endif
1239
1240/* this is just to get the server to link on AIX */
1241#ifdef AIXV3
1242int SelectWaitTime = 10000; /* usec */
1243#endif
1244
1245Bool LegalModifier(unsigned int key, DevicePtr pDev)
1246{
1247 return TRUE;
1248}
1249
1250void ProcessInputEvents()
1251{
1252 mieqProcessInputEvents();
1253 miPointerUpdate();
1254}
1255
1256/* Fairly standard US PC Keyboard */
1257
1258#define VFB_MIN_KEY 8
1259#define VFB_MAX_KEY 255
1260#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1261#define KEYSYMS_PER_KEY 2
1262KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1263 NoSymbol, NoSymbol,
1264 XK_Escape, NoSymbol,
1265 XK_1, XK_exclam,
1266 XK_2, XK_at,
1267 XK_3, XK_numbersign,
1268 XK_4, XK_dollar,
1269 XK_5, XK_percent,
1270 XK_6, XK_asciicircum,
1271 XK_7, XK_ampersand,
1272 XK_8, XK_asterisk,
1273 XK_9, XK_parenleft,
1274 XK_0, XK_parenright,
1275 XK_minus, XK_underscore,
1276 XK_equal, XK_plus,
1277 XK_BackSpace, NoSymbol,
1278 XK_Tab, NoSymbol,
1279 XK_q, XK_Q,
1280 XK_w, XK_W,
1281 XK_e, XK_E,
1282 XK_r, XK_R,
1283 XK_t, XK_T,
1284 XK_y, XK_Y,
1285 XK_u, XK_U,
1286 XK_i, XK_I,
1287 XK_o, XK_O,
1288 XK_p, XK_P,
1289 XK_bracketleft, XK_braceleft,
1290 XK_bracketright, XK_braceright,
1291 XK_Return, NoSymbol,
1292 XK_Control_L, NoSymbol,
1293 XK_a, XK_A,
1294 XK_s, XK_S,
1295 XK_d, XK_D,
1296 XK_f, XK_F,
1297 XK_g, XK_G,
1298 XK_h, XK_H,
1299 XK_j, XK_J,
1300 XK_k, XK_K,
1301 XK_l, XK_L,
1302 XK_semicolon, XK_colon,
1303 XK_apostrophe, XK_quotedbl,
1304 XK_grave, XK_asciitilde,
1305 XK_Shift_L, NoSymbol,
1306 XK_backslash, XK_bar,
1307 XK_z, XK_Z,
1308 XK_x, XK_X,
1309 XK_c, XK_C,
1310 XK_v, XK_V,
1311 XK_b, XK_B,
1312 XK_n, XK_N,
1313 XK_m, XK_M,
1314 XK_comma, XK_less,
1315 XK_period, XK_greater,
1316 XK_slash, XK_question,
1317 XK_Shift_R, NoSymbol,
1318 XK_KP_Multiply, NoSymbol,
1319 XK_Alt_L, XK_Meta_L,
1320 XK_space, NoSymbol,
1321 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1322 XK_F1, NoSymbol,
1323 XK_F2, NoSymbol,
1324 XK_F3, NoSymbol,
1325 XK_F4, NoSymbol,
1326 XK_F5, NoSymbol,
1327 XK_F6, NoSymbol,
1328 XK_F7, NoSymbol,
1329 XK_F8, NoSymbol,
1330 XK_F9, NoSymbol,
1331 XK_F10, NoSymbol,
1332 XK_Num_Lock, XK_Pointer_EnableKeys,
1333 XK_Scroll_Lock, NoSymbol,
1334 XK_KP_Home, XK_KP_7,
1335 XK_KP_Up, XK_KP_8,
1336 XK_KP_Prior, XK_KP_9,
1337 XK_KP_Subtract, NoSymbol,
1338 XK_KP_Left, XK_KP_4,
1339 XK_KP_Begin, XK_KP_5,
1340 XK_KP_Right, XK_KP_6,
1341 XK_KP_Add, NoSymbol,
1342 XK_KP_End, XK_KP_1,
1343 XK_KP_Down, XK_KP_2,
1344 XK_KP_Next, XK_KP_3,
1345 XK_KP_Insert, XK_KP_0,
1346 XK_KP_Delete, XK_KP_Decimal,
1347 NoSymbol, NoSymbol,
1348 NoSymbol, NoSymbol,
1349 NoSymbol, NoSymbol,
1350 XK_F11, NoSymbol,
1351 XK_F12, NoSymbol,
1352 XK_Home, NoSymbol,
1353 XK_Up, NoSymbol,
1354 XK_Prior, NoSymbol,
1355 XK_Left, NoSymbol,
1356 NoSymbol, NoSymbol,
1357 XK_Right, NoSymbol,
1358 XK_End, NoSymbol,
1359 XK_Down, NoSymbol,
1360 XK_Next, NoSymbol,
1361 XK_Insert, NoSymbol,
1362 XK_Delete, NoSymbol,
1363 XK_KP_Enter, NoSymbol,
1364 XK_Control_R, NoSymbol,
1365 XK_Pause, XK_Break,
1366 XK_Print, XK_Execute,
1367 XK_KP_Divide, NoSymbol,
1368 XK_Alt_R, XK_Meta_R,
1369};
1370
1371static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1372{
1373 int i;
1374
1375 for (i = 0; i < MAP_LENGTH; i++)
1376 pModMap[i] = NoSymbol;
1377
1378 for (i = 0; i < VFB_MAP_LEN; i++) {
1379 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1380 pModMap[i + VFB_MIN_KEY] = LockMask;
1381 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1382 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1383 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1384 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1385 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1386 pModMap[i + VFB_MIN_KEY] = ControlMask;
1387 }
1388 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1389 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1390 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1391 }
1392
1393 pKeySyms->minKeyCode = VFB_MIN_KEY;
1394 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1395 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1396 pKeySyms->map = keyboardMap;
1397
1398 return TRUE;
1399}
1400
1401static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1402{
1403 if (percent > 0)
1404 vncBell();
1405}
1406
1407static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1408{
1409 KeySymsRec keySyms;
1410 CARD8 modMap[MAP_LENGTH];
1411 DevicePtr pDev = (DevicePtr)pDevice;
1412
1413 switch (onoff)
1414 {
1415 case DEVICE_INIT:
1416 GetMappings(&keySyms, modMap);
1417 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1418 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1419 break;
1420 case DEVICE_ON:
1421 pDev->on = TRUE;
1422 break;
1423 case DEVICE_OFF:
1424 pDev->on = FALSE;
1425 break;
1426 case DEVICE_CLOSE:
1427 break;
1428 }
1429 return Success;
1430}
1431
1432static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1433{
1434 BYTE map[6];
1435 DevicePtr pDev = (DevicePtr)pDevice;
1436
1437 switch (onoff)
1438 {
1439 case DEVICE_INIT:
1440 map[1] = 1;
1441 map[2] = 2;
1442 map[3] = 3;
1443 map[4] = 4;
1444 map[5] = 5;
1445 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1446 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1447 break;
1448
1449 case DEVICE_ON:
1450 pDev->on = TRUE;
1451 break;
1452
1453 case DEVICE_OFF:
1454 pDev->on = FALSE;
1455 break;
1456
1457 case DEVICE_CLOSE:
1458 break;
1459 }
1460 return Success;
1461}
1462
1463// InitInput is called after InitExtensions, so we're guaranteed that
1464// vncExtensionInit() has already been called.
1465
1466void InitInput(int argc, char *argv[])
1467{
1468 DeviceIntPtr p, k;
1469 p = AddInputDevice(vfbMouseProc, TRUE);
1470 k = AddInputDevice(vfbKeybdProc, TRUE);
1471 RegisterPointerDevice(p);
1472 RegisterKeyboardDevice(k);
1473 miRegisterPointerDevice(screenInfo.screens[0], p);
1474 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1475}