blob: 3ef17fd4473356cf6d516f894ba9cf101ddd5561 [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19/*
20
21Copyright (c) 1993 X Consortium
22
23Permission is hereby granted, free of charge, to any person obtaining
24a copy of this software and associated documentation files (the
25"Software"), to deal in the Software without restriction, including
26without limitation the rights to use, copy, modify, merge, publish,
27distribute, sublicense, and/or sell copies of the Software, and to
28permit persons to whom the Software is furnished to do so, subject to
29the following conditions:
30
31The above copyright notice and this permission notice shall be included
32in all copies or substantial portions of the Software.
33
34THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
35OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
38OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
39ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
40OTHER DEALINGS IN THE SOFTWARE.
41
42Except as contained in this notice, the name of the X Consortium shall
43not be used in advertising or otherwise to promote the sale, use or
44other dealings in this Software without prior written authorization
45from the X Consortium.
46
47*/
48
49#include <rfb/Configuration.h>
50#include <rfb/Logger_stdio.h>
51#include <rfb/LogWriter.h>
52#include <network/TcpSocket.h>
53#include "vncExtInit.h"
54
55extern "C" {
56#define class c_class
57#define public c_public
58#define xor c_xor
59#define and c_and
60#ifdef WIN32
61#include <X11/Xwinsock.h>
62#endif
63#include <stdio.h>
64#include "X11/X.h"
65#define NEED_EVENTS
66#include "X11/Xproto.h"
67#include "X11/Xos.h"
68#include "scrnintstr.h"
69#include "servermd.h"
Peter Åstrand1bdab802005-02-14 14:03:35 +000070#include "fb.h"
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000071#include "mi.h"
72#include "mibstore.h"
73#include "colormapst.h"
74#include "gcstruct.h"
75#include "input.h"
76#include "mipointer.h"
Peter Åstrand200c31c2005-02-23 13:21:09 +000077#define new New
Peter Åstrand1d742b42005-02-22 21:33:20 +000078#include "micmap.h"
Peter Åstrand200c31c2005-02-23 13:21:09 +000079#undef new
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000080#include <sys/types.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000081#ifdef HAS_MMAP
82#include <sys/mman.h>
83#ifndef MAP_FILE
84#define MAP_FILE 0
85#endif
86#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000087#include <sys/stat.h>
88#include <errno.h>
89#ifndef WIN32
90#include <sys/param.h>
91#endif
92#include <X11/XWDFile.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000093#ifdef HAS_SHM
94#include <sys/ipc.h>
95#include <sys/shm.h>
96#endif /* HAS_SHM */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000097#include "dix.h"
98#include "miline.h"
99#include "inputstr.h"
100#include "keysym.h"
101 extern int defaultColorVisualClass;
102 extern char buildtime[];
103#undef class
104#undef public
105#undef xor
106#undef and
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000107}
108
109#define XVNCVERSION "4.0"
110
111extern char *display;
112extern int monitorResolution;
113
114#define VFB_DEFAULT_WIDTH 1024
115#define VFB_DEFAULT_HEIGHT 768
116#define VFB_DEFAULT_DEPTH 16
117#define VFB_DEFAULT_WHITEPIXEL 0xffff
118#define VFB_DEFAULT_BLACKPIXEL 0
119#define VFB_DEFAULT_LINEBIAS 0
120#define XWD_WINDOW_NAME_LEN 60
121
122typedef struct
123{
Peter Åstrand60870912005-02-22 21:27:51 +0000124 int scrnum;
125 int width;
126 int paddedBytesWidth;
127 int paddedWidth;
128 int height;
129 int depth;
130 int bitsPerPixel;
131 int sizeInBytes;
132 int ncolors;
133 char *pfbMemory;
134 XWDColor *pXWDCmap;
135 XWDFileHeader *pXWDHeader;
136 Pixel blackPixel;
137 Pixel whitePixel;
138 unsigned int lineBias;
139 CloseScreenProcPtr closeScreen;
140
141#ifdef HAS_MMAP
142 int mmap_fd;
143 char mmap_file[MAXPATHLEN];
144#endif
145
146#ifdef HAS_SHM
147 int shmid;
148#endif
149
150 Bool pixelFormatDefined;
151 Bool rgbNotBgr;
152 int redBits, greenBits, blueBits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000153
154} vfbScreenInfo, *vfbScreenInfoPtr;
155
156static int vfbNumScreens;
157static vfbScreenInfo vfbScreens[MAXSCREENS];
158static Bool vfbPixmapDepths[33];
Peter Åstrand00c759d2005-02-22 20:11:47 +0000159#ifdef HAS_MMAP
160static char *pfbdir = NULL;
161#endif
162typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
163static fbMemType fbmemtype = NORMAL_MEMORY_FB;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000164static char needswap = 0;
165static int lastScreen = -1;
Peter Åstrandc5421b22005-02-14 20:25:49 +0000166static Bool Render = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000167
168static bool displaySpecified = false;
169static bool wellKnownSocketsCreated = false;
170static char displayNumStr[16];
171
172#define swapcopy16(_dst, _src) \
173 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
174 else _dst = _src;
175
176#define swapcopy32(_dst, _src) \
177 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
178 else _dst = _src;
179
180
Peter Åstrandf960f042005-02-22 20:07:55 +0000181static void
182vfbInitializePixmapDepths(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000183{
Peter Åstrandf960f042005-02-22 20:07:55 +0000184 int i;
185 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
186 for (i = 2; i <= 32; i++)
187 vfbPixmapDepths[i] = FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000188}
189
Peter Åstrandf960f042005-02-22 20:07:55 +0000190static void
191vfbInitializeDefaultScreens(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000192{
Peter Åstrandf960f042005-02-22 20:07:55 +0000193 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000194
Peter Åstrandf960f042005-02-22 20:07:55 +0000195 for (i = 0; i < MAXSCREENS; i++)
196 {
197 vfbScreens[i].scrnum = i;
198 vfbScreens[i].width = VFB_DEFAULT_WIDTH;
199 vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
200 vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
201 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
202 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
203 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
204 vfbScreens[i].pixelFormatDefined = FALSE;
205 vfbScreens[i].pfbMemory = NULL;
206 }
207 vfbNumScreens = 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000208}
209
Peter Åstrand00c759d2005-02-22 20:11:47 +0000210static int
211vfbBitsPerPixel(int depth)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000212{
Peter Åstrand00c759d2005-02-22 20:11:47 +0000213 if (depth == 1) return 1;
214 else if (depth <= 8) return 8;
215 else if (depth <= 16) return 16;
216 else return 32;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000217}
218
219extern "C" {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000220void
221ddxGiveUp()
222{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000223 int i;
224
225 /* clean up the framebuffers */
226
Peter Åstrand00c759d2005-02-22 20:11:47 +0000227 switch (fbmemtype)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000228 {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000229#ifdef HAS_MMAP
230 case MMAPPED_FILE_FB:
231 for (i = 0; i < vfbNumScreens; i++)
232 {
233 if (-1 == unlink(vfbScreens[i].mmap_file))
234 {
235 perror("unlink");
236 ErrorF("unlink %s failed, errno %d",
237 vfbScreens[i].mmap_file, errno);
238 }
239 }
240 break;
241#else /* HAS_MMAP */
242 case MMAPPED_FILE_FB:
243 break;
244#endif /* HAS_MMAP */
245
246#ifdef HAS_SHM
247 case SHARED_MEMORY_FB:
248 for (i = 0; i < vfbNumScreens; i++)
249 {
250 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
251 {
252 perror("shmdt");
253 ErrorF("shmdt failed, errno %d", errno);
254 }
255 }
256 break;
257#else /* HAS_SHM */
258 case SHARED_MEMORY_FB:
259 break;
260#endif /* HAS_SHM */
261
262 case NORMAL_MEMORY_FB:
263 for (i = 0; i < vfbNumScreens; i++)
264 {
265 Xfree(vfbScreens[i].pXWDHeader);
266 }
267 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000268 }
Peter Åstrand00c759d2005-02-22 20:11:47 +0000269}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000270
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000271void
272AbortDDX()
273{
274 ddxGiveUp();
275}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000276
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000277#ifdef __DARWIN__
278void
279DarwinHandleGUI(int argc, char *argv[])
280{
281}
282
283void GlxExtensionInit();
284void GlxWrapInitVisuals(void *procPtr);
285
286void
287DarwinGlxExtensionInit()
288{
289 GlxExtensionInit();
290}
291
292void
293DarwinGlxWrapInitVisuals(
294 void *procPtr)
295{
296 GlxWrapInitVisuals(procPtr);
297}
298#endif
299
300void
301OsVendorInit()
302{
303}
304
305void
306OsVendorFatalError()
307{
308}
309
310void ddxBeforeReset(void)
311{
312 return;
313}
314
315void
316ddxUseMsg()
317{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000318 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
319 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
320 VENDOR_STRING);
321 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
322 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
Peter Åstrandc5421b22005-02-14 20:25:49 +0000323#ifdef RENDER
324 ErrorF("+/-render turn on/off RENDER extension support"
325 "(default on)\n");
326#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000327 ErrorF("-linebias n adjust thin line pixelization\n");
328 ErrorF("-blackpixel n pixel value for black\n");
329 ErrorF("-whitepixel n pixel value for white\n");
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000330
331#ifdef HAS_MMAP
332 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
333#endif
334
335#ifdef HAS_SHM
336 ErrorF("-shmem put framebuffers in shared memory\n");
337#endif
338
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000339 ErrorF("-geometry WxH set screen 0's width, height\n");
340 ErrorF("-depth D set screen 0's depth\n");
341 ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
342 ErrorF("-inetd has been launched from inetd\n");
343 ErrorF("\nVNC parameters:\n");
344
345 fprintf(stderr,"\n"
346 "Parameters can be turned on with -<param> or off with -<param>=0\n"
347 "Parameters which take a value can be specified as "
348 "-<param> <value>\n"
349 "Other valid forms are <param>=<value> -<param>=<value> "
350 "--<param>=<value>\n"
351 "Parameter names are case-insensitive. The parameters are:\n\n");
352 rfb::Configuration::listParams(79, 14);
353 }
354}
355
Peter Åstrandfc41a212005-02-22 20:29:40 +0000356/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
357void ddxInitGlobals(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000358{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000359}
360
Peter Åstrandfc41a212005-02-22 20:29:40 +0000361static
362bool displayNumFree(int num)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000363{
Peter Åstrandfc41a212005-02-22 20:29:40 +0000364 try {
365 network::TcpListener l(6000+num);
366 } catch (rdr::Exception& e) {
367 return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000368 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000369 char file[256];
370 sprintf(file, "/tmp/.X%d-lock", num);
371 if (access(file, F_OK) == 0) return false;
372 sprintf(file, "/tmp/.X11-unix/X%d", num);
373 if (access(file, F_OK) == 0) return false;
374 sprintf(file, "/usr/spool/sockets/X11/%d", num);
375 if (access(file, F_OK) == 0) return false;
376 return true;
377}
378
379int
380ddxProcessArgument(int argc, char *argv[], int i)
381{
382 static Bool firstTime = TRUE;
383
384 if (firstTime)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000385 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000386 vfbInitializeDefaultScreens();
387 vfbInitializePixmapDepths();
388 firstTime = FALSE;
389 rfb::initStdIOLoggers();
390 rfb::LogWriter::setLogParams("*:stderr:30");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000391 }
392
Peter Åstrandfc41a212005-02-22 20:29:40 +0000393 if (argv[i][0] == ':')
394 displaySpecified = true;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000395
Peter Åstrandfc41a212005-02-22 20:29:40 +0000396 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000397 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000398 int screenNum;
399 if (i + 2 >= argc) UseMsg();
400 screenNum = atoi(argv[i+1]);
401 if (screenNum < 0 || screenNum >= MAXSCREENS)
402 {
403 ErrorF("Invalid screen number %d\n", screenNum);
404 UseMsg();
405 }
406 if (3 != sscanf(argv[i+2], "%dx%dx%d",
407 &vfbScreens[screenNum].width,
408 &vfbScreens[screenNum].height,
409 &vfbScreens[screenNum].depth))
410 {
411 ErrorF("Invalid screen configuration %s\n", argv[i+2]);
412 UseMsg();
413 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000414
Peter Åstrandfc41a212005-02-22 20:29:40 +0000415 if (screenNum >= vfbNumScreens)
416 vfbNumScreens = screenNum + 1;
417 lastScreen = screenNum;
418 return 3;
419 }
420
421 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
422 {
423 int depth, ret = 1;
424
425 if (++i >= argc) UseMsg();
426 while ((i < argc) && (depth = atoi(argv[i++])) != 0)
427 {
428 if (depth < 0 || depth > 32)
429 {
430 ErrorF("Invalid pixmap depth %d\n", depth);
431 UseMsg();
432 }
433 vfbPixmapDepths[depth] = TRUE;
434 ret++;
435 }
436 return ret;
437 }
438
439 if (strcmp (argv[i], "+render") == 0) /* +render */
440 {
441 Render = TRUE;
442 return 1;
443 }
Peter Åstrandc5421b22005-02-14 20:25:49 +0000444
Peter Åstrandfc41a212005-02-22 20:29:40 +0000445 if (strcmp (argv[i], "-render") == 0) /* -render */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000446 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000447 Render = FALSE;
448 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000449 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000450
Peter Åstrandfc41a212005-02-22 20:29:40 +0000451 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000452 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000453 Pixel pix;
454 if (++i >= argc) UseMsg();
455 pix = atoi(argv[i]);
456 if (-1 == lastScreen)
457 {
458 int i;
459 for (i = 0; i < MAXSCREENS; i++)
460 {
461 vfbScreens[i].blackPixel = pix;
462 }
463 }
464 else
465 {
466 vfbScreens[lastScreen].blackPixel = pix;
467 }
468 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000469 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000470
471 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000472 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000473 Pixel pix;
474 if (++i >= argc) UseMsg();
475 pix = atoi(argv[i]);
476 if (-1 == lastScreen)
477 {
478 int i;
479 for (i = 0; i < MAXSCREENS; i++)
480 {
481 vfbScreens[i].whitePixel = pix;
482 }
483 }
484 else
485 {
486 vfbScreens[lastScreen].whitePixel = pix;
487 }
488 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000489 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000490
491 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000492 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000493 unsigned int linebias;
494 if (++i >= argc) UseMsg();
495 linebias = atoi(argv[i]);
496 if (-1 == lastScreen)
497 {
498 int i;
499 for (i = 0; i < MAXSCREENS; i++)
500 {
501 vfbScreens[i].lineBias = linebias;
502 }
503 }
504 else
505 {
506 vfbScreens[lastScreen].lineBias = linebias;
507 }
508 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000509 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000510
511#ifdef HAS_MMAP
512 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000513 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000514 if (++i >= argc) UseMsg();
515 pfbdir = argv[i];
516 fbmemtype = MMAPPED_FILE_FB;
517 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000518 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000519#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000520
Peter Åstrandfc41a212005-02-22 20:29:40 +0000521#ifdef HAS_SHM
522 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
523 {
524 fbmemtype = SHARED_MEMORY_FB;
525 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000526 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000527#endif
528
529 if (strcmp(argv[i], "-geometry") == 0)
530 {
531 if (++i >= argc) UseMsg();
532 if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
533 &vfbScreens[0].height) != 2) {
534 ErrorF("Invalid geometry %s\n", argv[i]);
535 UseMsg();
536 }
537 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000538 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000539
540 if (strcmp(argv[i], "-depth") == 0)
541 {
542 if (++i >= argc) UseMsg();
543 vfbScreens[0].depth = atoi(argv[i]);
544 return 2;
545 }
546
547 if (strcmp(argv[i], "-pixelformat") == 0)
548 {
549 char rgbbgr[4];
550 int bits1, bits2, bits3;
551 if (++i >= argc) UseMsg();
552 if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
553 ErrorF("Invalid pixel format %s\n", argv[i]);
554 UseMsg();
555 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000556
557#define SET_PIXEL_FORMAT(vfbScreen) \
558 (vfbScreen).pixelFormatDefined = TRUE; \
559 (vfbScreen).depth = bits1 + bits2 + bits3; \
560 (vfbScreen).greenBits = bits2; \
561 if (strcasecmp(rgbbgr, "bgr") == 0) { \
562 (vfbScreen).rgbNotBgr = FALSE; \
563 (vfbScreen).redBits = bits3; \
564 (vfbScreen).blueBits = bits1; \
565 } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
566 (vfbScreen).rgbNotBgr = TRUE; \
567 (vfbScreen).redBits = bits1; \
568 (vfbScreen).blueBits = bits3; \
569 } else { \
570 ErrorF("Invalid pixel format %s\n", argv[i]); \
571 UseMsg(); \
572 }
573
Peter Åstrandfc41a212005-02-22 20:29:40 +0000574 if (-1 == lastScreen)
575 {
576 int i;
577 for (i = 0; i < MAXSCREENS; i++)
578 {
579 SET_PIXEL_FORMAT(vfbScreens[i]);
580 }
581 }
582 else
583 {
584 SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
585 }
586
587 return 2;
588 }
589
590 if (strcmp(argv[i], "-inetd") == 0)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000591 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000592 dup2(0,3);
593 vncInetdSock = 3;
594 close(2);
595
596 if (!displaySpecified) {
597 int port = network::TcpSocket::getSockPort(vncInetdSock);
598 int displayNum = port - 5900;
599 if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
600 for (displayNum = 1; displayNum < 100; displayNum++)
601 if (displayNumFree(displayNum)) break;
602
603 if (displayNum == 100)
604 FatalError("Xvnc error: no free display number for -inetd");
605 }
606
607 display = displayNumStr;
608 sprintf(displayNumStr, "%d", displayNum);
609 }
610
611 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000612 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000613
614 if (rfb::Configuration::setParam(argv[i]))
615 return 1;
616
617 if (argv[i][0] == '-' && i+1 < argc) {
618 if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
619 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000620 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000621
622 return 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000623}
624
625#ifdef DDXTIME /* from ServerOSDefines */
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000626CARD32
627GetTimeInMillis()
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000628{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000629 struct timeval tp;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000630
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000631 X_GETTIMEOFDAY(&tp);
632 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000633}
634#endif
635
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000636static ColormapPtr InstalledMaps[MAXSCREENS];
637
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000638static int
639vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000640{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000641 /* By the time we are processing requests, we can guarantee that there
642 * is always a colormap installed */
643 *pmaps = InstalledMaps[pScreen->myNum]->mid;
644 return (1);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000645}
646
647
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000648static void
649vfbInstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000650{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000651 int index = pmap->pScreen->myNum;
652 ColormapPtr oldpmap = InstalledMaps[index];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000653
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000654 if (pmap != oldpmap)
655 {
656 int entries;
657 XWDFileHeader *pXWDHeader;
658 XWDColor *pXWDCmap;
659 VisualPtr pVisual;
660 Pixel * ppix;
661 xrgb * prgb;
662 xColorItem *defs;
663 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000664
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000665 if(oldpmap != (ColormapPtr)None)
666 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
667 /* Install pmap */
668 InstalledMaps[index] = pmap;
669 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000670
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000671 entries = pmap->pVisual->ColormapEntries;
672 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
673 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
674 pVisual = pmap->pVisual;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000675
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000676 swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
677 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
678 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
679 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
680 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
681 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000682
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000683 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
684 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
685 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000686
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000687 for (i = 0; i < entries; i++) ppix[i] = i;
688 /* XXX truecolor */
689 QueryColors(pmap, entries, ppix, prgb);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000690
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000691 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
692 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
693 defs[i].red = prgb[i].red;
694 defs[i].green = prgb[i].green;
695 defs[i].blue = prgb[i].blue;
696 defs[i].flags = DoRed|DoGreen|DoBlue;
697 }
698 (*pmap->pScreen->StoreColors)(pmap, entries, defs);
699
700 DEALLOCATE_LOCAL(ppix);
701 DEALLOCATE_LOCAL(prgb);
702 DEALLOCATE_LOCAL(defs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000703 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000704}
705
Peter Åstrand853287d2005-02-22 20:46:58 +0000706static void
707vfbUninstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000708{
Peter Åstrand853287d2005-02-22 20:46:58 +0000709 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000710
Peter Åstrand853287d2005-02-22 20:46:58 +0000711 if(pmap == curpmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000712 {
Peter Åstrand853287d2005-02-22 20:46:58 +0000713 if (pmap->mid != pmap->pScreen->defColormap)
714 {
715 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
716 RT_COLORMAP);
717 (*pmap->pScreen->InstallColormap)(curpmap);
718 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000719 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000720}
721
Peter Åstrand853287d2005-02-22 20:46:58 +0000722static void
723vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000724{
Peter Åstrand853287d2005-02-22 20:46:58 +0000725 XWDColor *pXWDCmap;
726 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000727
Peter Åstrand853287d2005-02-22 20:46:58 +0000728 if (pmap != InstalledMaps[pmap->pScreen->myNum])
729 {
730 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000731 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000732
733 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
734
Peter Åstrandbe228572005-02-22 20:48:29 +0000735 if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
Peter Åstrand853287d2005-02-22 20:46:58 +0000736 {
737 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000738 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000739
740 for (i = 0; i < ndef; i++)
741 {
742 if (pdefs[i].flags & DoRed)
743 {
744 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
745 }
746 if (pdefs[i].flags & DoGreen)
747 {
748 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
749 }
750 if (pdefs[i].flags & DoBlue)
751 {
752 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
753 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000754 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000755}
756
Peter Åstrand853287d2005-02-22 20:46:58 +0000757static Bool
758vfbSaveScreen(ScreenPtr pScreen, int on)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000759{
Peter Åstrand853287d2005-02-22 20:46:58 +0000760 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000761}
762
Peter Åstrand1402f8c2005-02-23 08:22:10 +0000763#ifdef HAS_MMAP
764
765/* this flushes any changes to the screens out to the mmapped file */
766static void
767vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
768{
769 int i;
770
771 for (i = 0; i < vfbNumScreens; i++)
772 {
773#ifdef MS_ASYNC
774 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
775 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
776#else
777 /* silly NetBSD and who else? */
778 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
779 (size_t)vfbScreens[i].sizeInBytes))
780#endif
781 {
782 perror("msync");
783 ErrorF("msync failed, errno %d", errno);
784 }
785 }
786}
787
788
789static void
790vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
791{
792}
793
794
795static void
796vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
797{
798#define DUMMY_BUFFER_SIZE 65536
799 char dummyBuffer[DUMMY_BUFFER_SIZE];
800 int currentFileSize, writeThisTime;
801
802 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
803 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
804 {
805 perror("open");
806 ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
807 return;
808 }
809
810 /* Extend the file to be the proper size */
811
812 bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
813 for (currentFileSize = 0;
814 currentFileSize < pvfb->sizeInBytes;
815 currentFileSize += writeThisTime)
816 {
817 writeThisTime = min(DUMMY_BUFFER_SIZE,
818 pvfb->sizeInBytes - currentFileSize);
819 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
820 {
821 perror("write");
822 ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
823 return;
824 }
825 }
826
827 /* try to mmap the file */
828
829 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
830 PROT_READ|PROT_WRITE,
831 MAP_FILE|MAP_SHARED,
832 pvfb->mmap_fd, 0);
833 if (-1 == (long)pvfb->pXWDHeader)
834 {
835 perror("mmap");
836 ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
837 pvfb->pXWDHeader = NULL;
838 return;
839 }
840
841 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
842 NULL))
843 {
844 pvfb->pXWDHeader = NULL;
845 }
846}
847#endif /* HAS_MMAP */
848
849
850#ifdef HAS_SHM
851static void
852vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
853{
854 /* create the shared memory segment */
855
856 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
857 if (pvfb->shmid < 0)
858 {
859 perror("shmget");
860 ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
861 return;
862 }
863
864 /* try to attach it */
865
866 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
867 if (-1 == (long)pvfb->pXWDHeader)
868 {
869 perror("shmat");
870 ErrorF("shmat failed, errno %d", errno);
871 pvfb->pXWDHeader = NULL;
872 return;
873 }
874
875 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
876}
877#endif /* HAS_SHM */
878
879
Peter Åstrand8de329f2005-02-22 21:05:16 +0000880static char *
881vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000882{
Peter Åstrand8de329f2005-02-22 21:05:16 +0000883 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000884
Peter Åstrand8de329f2005-02-22 21:05:16 +0000885 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000886
Peter Åstrand8de329f2005-02-22 21:05:16 +0000887 /* Calculate how many entries in colormap. This is rather bogus, because
888 * the visuals haven't even been set up yet, but we need to know because we
889 * have to allocate space in the file for the colormap. The number 10
890 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
891 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000892
Peter Åstrand8de329f2005-02-22 21:05:16 +0000893 if (pvfb->depth <= 10)
894 { /* single index colormaps */
895 pvfb->ncolors = 1 << pvfb->depth;
896 }
897 else
898 { /* decomposed colormaps */
899 int nplanes_per_color_component = pvfb->depth / 3;
900 if (pvfb->depth % 3) nplanes_per_color_component++;
901 pvfb->ncolors = 1 << nplanes_per_color_component;
902 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000903
Peter Åstrand8de329f2005-02-22 21:05:16 +0000904 /* add extra bytes for XWDFileHeader, window name, and colormap */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000905
Peter Åstrand8de329f2005-02-22 21:05:16 +0000906 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
907 pvfb->ncolors * SIZEOF(XWDColor);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000908
Peter Åstrand8de329f2005-02-22 21:05:16 +0000909 pvfb->pXWDHeader = NULL;
910 switch (fbmemtype)
911 {
912#ifdef HAS_MMAP
913 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
914#else
915 case MMAPPED_FILE_FB: break;
916#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000917
Peter Åstrand8de329f2005-02-22 21:05:16 +0000918#ifdef HAS_SHM
919 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
920#else
921 case SHARED_MEMORY_FB: break;
922#endif
923
924 case NORMAL_MEMORY_FB:
925 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
926 break;
927 }
928
929 if (pvfb->pXWDHeader)
930 {
931 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
932 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
933 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
934
935 return pvfb->pfbMemory;
936 }
937 else
938 return NULL;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000939}
940
Peter Åstrandf9357f52005-02-22 21:08:02 +0000941static void
942vfbWriteXWDFileHeader(ScreenPtr pScreen)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000943{
Peter Åstrandf9357f52005-02-22 21:08:02 +0000944 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
945 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
946 char hostname[XWD_WINDOW_NAME_LEN];
947 unsigned long swaptest = 1;
948 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000949
Peter Åstrandf9357f52005-02-22 21:08:02 +0000950 needswap = *(char *) &swaptest;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000951
Peter Åstrandf9357f52005-02-22 21:08:02 +0000952 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
953 pXWDHeader->file_version = XWD_FILE_VERSION;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000954
Peter Åstrandf9357f52005-02-22 21:08:02 +0000955 pXWDHeader->pixmap_format = ZPixmap;
956 pXWDHeader->pixmap_depth = pvfb->depth;
957 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
958 pXWDHeader->xoffset = 0;
959 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
960 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000961#ifndef INTERNAL_VS_EXTERNAL_PADDING
Peter Åstrandf9357f52005-02-22 21:08:02 +0000962 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
963 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
964 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000965#else
Peter Åstrandf9357f52005-02-22 21:08:02 +0000966 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
967 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
968 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000969#endif
Peter Åstrandf9357f52005-02-22 21:08:02 +0000970 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
971 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
972 pXWDHeader->ncolors = pvfb->ncolors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000973
Peter Åstrandf9357f52005-02-22 21:08:02 +0000974 /* visual related fields are written when colormap is installed */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000975
Peter Åstrandf9357f52005-02-22 21:08:02 +0000976 pXWDHeader->window_x = pXWDHeader->window_y = 0;
977 pXWDHeader->window_bdrwidth = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000978
Peter Åstrandf9357f52005-02-22 21:08:02 +0000979 /* write xwd "window" name: Xvfb hostname:server.screen */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000980
Peter Åstrandf9357f52005-02-22 21:08:02 +0000981 if (-1 == gethostname(hostname, sizeof(hostname)))
982 hostname[0] = 0;
983 else
984 hostname[XWD_WINDOW_NAME_LEN-1] = 0;
985 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
986 pScreen->myNum);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000987
Peter Åstrandf9357f52005-02-22 21:08:02 +0000988 /* write colormap pixel slot values */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000989
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000990 for (i = 0; i < pvfb->ncolors; i++)
991 {
Peter Åstrandf9357f52005-02-22 21:08:02 +0000992 pvfb->pXWDCmap[i].pixel = i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000993 }
Peter Åstrandf9357f52005-02-22 21:08:02 +0000994
995 /* byte swap to most significant byte first */
996
997 if (needswap)
998 {
999 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
1000 for (i = 0; i < pvfb->ncolors; i++)
1001 {
1002 register char n;
1003 swapl(&pvfb->pXWDCmap[i].pixel, n);
1004 }
1005 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001006}
1007
1008
Peter Åstrandf9357f52005-02-22 21:08:02 +00001009static Bool
1010vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
1011{
1012 return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001013}
Peter Åstrandf9357f52005-02-22 21:08:02 +00001014
1015static void
1016vfbCrossScreen (ScreenPtr pScreen, Bool entering)
1017{
1018}
1019
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001020static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001021 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001022}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001023
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001024static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001025 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001026}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001027
1028static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
1029{
1030}
1031
1032static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
1033{
1034}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001035
1036static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001037 vfbRealizeCursor,
1038 vfbUnrealizeCursor,
1039 vfbSetCursor,
1040 vfbMoveCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001041};
1042
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001043static miPointerScreenFuncRec vfbPointerCursorFuncs = {
1044 vfbCursorOffScreen,
1045 vfbCrossScreen,
1046 miPointerWarpCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001047};
1048
Peter Åstrand60870912005-02-22 21:27:51 +00001049static Bool
1050vfbCloseScreen(int index, ScreenPtr pScreen)
1051{
1052 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1053 int i;
1054
1055 pScreen->CloseScreen = pvfb->closeScreen;
1056
1057 /*
1058 * XXX probably lots of stuff to clean. For now,
1059 * clear InstalledMaps[] so that server reset works correctly.
1060 */
1061 for (i = 0; i < MAXSCREENS; i++)
1062 InstalledMaps[i] = NULL;
1063
1064 return pScreen->CloseScreen(index, pScreen);
1065}
1066
Peter Åstrand1d742b42005-02-22 21:33:20 +00001067static Bool
1068vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001069{
Peter Åstrand1d742b42005-02-22 21:33:20 +00001070 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1071 int dpix = 100, dpiy = 100;
1072 int ret;
1073 char *pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001074
Peter Åstrand1d742b42005-02-22 21:33:20 +00001075 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
1076 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
1077 if (pvfb->bitsPerPixel >= 8 )
1078 pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8);
1079 else
1080 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8;
1081 pbits = vfbAllocateFramebufferMemory(pvfb);
1082 if (!pbits) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001083
Peter Åstrand1d742b42005-02-22 21:33:20 +00001084 miSetPixmapDepths ();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001085
Peter Åstrand1d742b42005-02-22 21:33:20 +00001086 switch (pvfb->depth) {
1087 case 8:
1088 miSetVisualTypesAndMasks (8,
1089 ((1 << StaticGray) |
1090 (1 << GrayScale) |
1091 (1 << StaticColor) |
1092 (1 << PseudoColor) |
1093 (1 << TrueColor) |
1094 (1 << DirectColor)),
1095 8, PseudoColor, 0x07, 0x38, 0xc0);
1096 break;
1097 case 15:
1098 miSetVisualTypesAndMasks (15,
1099 ((1 << TrueColor) |
1100 (1 << DirectColor)),
1101 8, TrueColor, 0x7c00, 0x03e0, 0x001f);
1102 break;
1103 case 16:
1104 miSetVisualTypesAndMasks (16,
1105 ((1 << TrueColor) |
1106 (1 << DirectColor)),
1107 8, TrueColor, 0xf800, 0x07e0, 0x001f);
1108 break;
1109 case 24:
1110 miSetVisualTypesAndMasks (24,
1111 ((1 << TrueColor) |
1112 (1 << DirectColor)),
1113 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);
1114 break;
1115 }
1116
1117 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
1118 dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001119#ifdef RENDER
Peter Åstrand1d742b42005-02-22 21:33:20 +00001120 if (ret && Render)
1121 fbPictureInit (pScreen, 0, 0);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001122#endif
1123
Peter Åstrand1d742b42005-02-22 21:33:20 +00001124 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001125
Peter Åstrand1d742b42005-02-22 21:33:20 +00001126 /* miInitializeBackingStore(pScreen); */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001127
Peter Åstrand1d742b42005-02-22 21:33:20 +00001128 /*
1129 * Circumvent the backing store that was just initialised. This amounts
1130 * to a truely bizarre way of initialising SaveDoomedAreas and friends.
1131 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001132
Peter Åstrand1d742b42005-02-22 21:33:20 +00001133 pScreen->InstallColormap = vfbInstallColormap;
1134 pScreen->UninstallColormap = vfbUninstallColormap;
1135 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001136
Peter Åstrand1d742b42005-02-22 21:33:20 +00001137 pScreen->SaveScreen = vfbSaveScreen;
1138 pScreen->StoreColors = vfbStoreColors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001139
Peter Åstrand1d742b42005-02-22 21:33:20 +00001140 miDCInitialize(pScreen, &vfbPointerCursorFuncs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001141
Peter Åstrand1d742b42005-02-22 21:33:20 +00001142 vfbWriteXWDFileHeader(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001143
Peter Åstrand1d742b42005-02-22 21:33:20 +00001144 pScreen->blackPixel = pvfb->blackPixel;
1145 pScreen->whitePixel = pvfb->whitePixel;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001146
Peter Åstrand1d742b42005-02-22 21:33:20 +00001147 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001148
Peter Åstrand1d742b42005-02-22 21:33:20 +00001149 miSetZeroLineBias(pScreen, pvfb->lineBias);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001150
Peter Åstrand1d742b42005-02-22 21:33:20 +00001151 pvfb->closeScreen = pScreen->CloseScreen;
1152 pScreen->CloseScreen = vfbCloseScreen;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001153
Peter Åstrand1d742b42005-02-22 21:33:20 +00001154 return ret;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001155
1156} /* end vfbScreenInit */
1157
1158
1159static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
1160 dispatchException &= ~DE_RESET;
1161}
1162
Peter Åstrand321a9922005-02-22 21:37:32 +00001163void
1164InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001165{
Peter Åstrand321a9922005-02-22 21:37:32 +00001166 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
1167 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
1168 VENDOR_STRING);
1169 int i;
1170 int NumFormats = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001171
Peter Åstrand321a9922005-02-22 21:37:32 +00001172 /* initialize pixmap formats */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001173
Peter Åstrand321a9922005-02-22 21:37:32 +00001174 /* must have a pixmap depth to match every screen depth */
1175 for (i = 0; i < vfbNumScreens; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001176 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001177 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001178 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001179
Peter Åstrand321a9922005-02-22 21:37:32 +00001180 /* RENDER needs a good set of pixmaps. */
1181 if (Render) {
1182 vfbPixmapDepths[1] = TRUE;
1183 vfbPixmapDepths[4] = TRUE;
1184 vfbPixmapDepths[8] = TRUE;
1185/* vfbPixmapDepths[15] = TRUE; */
1186 vfbPixmapDepths[16] = TRUE;
1187 vfbPixmapDepths[24] = TRUE;
1188 vfbPixmapDepths[32] = TRUE;
1189 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001190
Peter Åstrand321a9922005-02-22 21:37:32 +00001191 for (i = 1; i <= 32; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001192 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001193 if (vfbPixmapDepths[i])
1194 {
1195 if (NumFormats >= MAXFORMATS)
1196 FatalError ("MAXFORMATS is too small for this server\n");
1197 screenInfo->formats[NumFormats].depth = i;
1198 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1199 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1200 NumFormats++;
1201 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001202 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001203
Peter Åstrand321a9922005-02-22 21:37:32 +00001204 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
1205 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1206 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1207 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
1208 screenInfo->numPixmapFormats = NumFormats;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001209
Peter Åstrand321a9922005-02-22 21:37:32 +00001210 /* initialize screens */
1211
1212 for (i = 0; i < vfbNumScreens; i++)
1213 {
1214 if (-1 == AddScreen(vfbScreenInit, argc, argv))
1215 {
1216 FatalError("Couldn't add screen %d", i);
1217 }
1218 }
1219
1220 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
1221 FatalError("AddCallback failed\n");
1222 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001223} /* end InitOutput */
1224
1225#ifdef DPMSExtension
1226extern "C" {
1227#if NeedFunctionPrototypes
1228 void DPMSSet(CARD16 level)
1229#else
1230 void DPMSSet(level)
1231 CARD16 level;
1232#endif
1233 {
1234 return;
1235 }
1236
1237 Bool DPMSSupported()
1238 {
1239 return FALSE;
1240 }
1241}
1242#endif
1243
1244/* this is just to get the server to link on AIX */
1245#ifdef AIXV3
1246int SelectWaitTime = 10000; /* usec */
1247#endif
1248
1249Bool LegalModifier(unsigned int key, DevicePtr pDev)
1250{
1251 return TRUE;
1252}
1253
1254void ProcessInputEvents()
1255{
1256 mieqProcessInputEvents();
1257 miPointerUpdate();
1258}
1259
1260/* Fairly standard US PC Keyboard */
1261
1262#define VFB_MIN_KEY 8
1263#define VFB_MAX_KEY 255
1264#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1265#define KEYSYMS_PER_KEY 2
1266KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1267 NoSymbol, NoSymbol,
1268 XK_Escape, NoSymbol,
1269 XK_1, XK_exclam,
1270 XK_2, XK_at,
1271 XK_3, XK_numbersign,
1272 XK_4, XK_dollar,
1273 XK_5, XK_percent,
1274 XK_6, XK_asciicircum,
1275 XK_7, XK_ampersand,
1276 XK_8, XK_asterisk,
1277 XK_9, XK_parenleft,
1278 XK_0, XK_parenright,
1279 XK_minus, XK_underscore,
1280 XK_equal, XK_plus,
1281 XK_BackSpace, NoSymbol,
1282 XK_Tab, NoSymbol,
1283 XK_q, XK_Q,
1284 XK_w, XK_W,
1285 XK_e, XK_E,
1286 XK_r, XK_R,
1287 XK_t, XK_T,
1288 XK_y, XK_Y,
1289 XK_u, XK_U,
1290 XK_i, XK_I,
1291 XK_o, XK_O,
1292 XK_p, XK_P,
1293 XK_bracketleft, XK_braceleft,
1294 XK_bracketright, XK_braceright,
1295 XK_Return, NoSymbol,
1296 XK_Control_L, NoSymbol,
1297 XK_a, XK_A,
1298 XK_s, XK_S,
1299 XK_d, XK_D,
1300 XK_f, XK_F,
1301 XK_g, XK_G,
1302 XK_h, XK_H,
1303 XK_j, XK_J,
1304 XK_k, XK_K,
1305 XK_l, XK_L,
1306 XK_semicolon, XK_colon,
1307 XK_apostrophe, XK_quotedbl,
1308 XK_grave, XK_asciitilde,
1309 XK_Shift_L, NoSymbol,
1310 XK_backslash, XK_bar,
1311 XK_z, XK_Z,
1312 XK_x, XK_X,
1313 XK_c, XK_C,
1314 XK_v, XK_V,
1315 XK_b, XK_B,
1316 XK_n, XK_N,
1317 XK_m, XK_M,
1318 XK_comma, XK_less,
1319 XK_period, XK_greater,
1320 XK_slash, XK_question,
1321 XK_Shift_R, NoSymbol,
1322 XK_KP_Multiply, NoSymbol,
1323 XK_Alt_L, XK_Meta_L,
1324 XK_space, NoSymbol,
1325 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1326 XK_F1, NoSymbol,
1327 XK_F2, NoSymbol,
1328 XK_F3, NoSymbol,
1329 XK_F4, NoSymbol,
1330 XK_F5, NoSymbol,
1331 XK_F6, NoSymbol,
1332 XK_F7, NoSymbol,
1333 XK_F8, NoSymbol,
1334 XK_F9, NoSymbol,
1335 XK_F10, NoSymbol,
1336 XK_Num_Lock, XK_Pointer_EnableKeys,
1337 XK_Scroll_Lock, NoSymbol,
1338 XK_KP_Home, XK_KP_7,
1339 XK_KP_Up, XK_KP_8,
1340 XK_KP_Prior, XK_KP_9,
1341 XK_KP_Subtract, NoSymbol,
1342 XK_KP_Left, XK_KP_4,
1343 XK_KP_Begin, XK_KP_5,
1344 XK_KP_Right, XK_KP_6,
1345 XK_KP_Add, NoSymbol,
1346 XK_KP_End, XK_KP_1,
1347 XK_KP_Down, XK_KP_2,
1348 XK_KP_Next, XK_KP_3,
1349 XK_KP_Insert, XK_KP_0,
1350 XK_KP_Delete, XK_KP_Decimal,
1351 NoSymbol, NoSymbol,
1352 NoSymbol, NoSymbol,
1353 NoSymbol, NoSymbol,
1354 XK_F11, NoSymbol,
1355 XK_F12, NoSymbol,
1356 XK_Home, NoSymbol,
1357 XK_Up, NoSymbol,
1358 XK_Prior, NoSymbol,
1359 XK_Left, NoSymbol,
1360 NoSymbol, NoSymbol,
1361 XK_Right, NoSymbol,
1362 XK_End, NoSymbol,
1363 XK_Down, NoSymbol,
1364 XK_Next, NoSymbol,
1365 XK_Insert, NoSymbol,
1366 XK_Delete, NoSymbol,
1367 XK_KP_Enter, NoSymbol,
1368 XK_Control_R, NoSymbol,
1369 XK_Pause, XK_Break,
1370 XK_Print, XK_Execute,
1371 XK_KP_Divide, NoSymbol,
1372 XK_Alt_R, XK_Meta_R,
1373};
1374
1375static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1376{
1377 int i;
1378
1379 for (i = 0; i < MAP_LENGTH; i++)
1380 pModMap[i] = NoSymbol;
1381
1382 for (i = 0; i < VFB_MAP_LEN; i++) {
1383 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1384 pModMap[i + VFB_MIN_KEY] = LockMask;
1385 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1386 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1387 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1388 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1389 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1390 pModMap[i + VFB_MIN_KEY] = ControlMask;
1391 }
1392 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1393 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1394 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1395 }
1396
1397 pKeySyms->minKeyCode = VFB_MIN_KEY;
1398 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1399 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1400 pKeySyms->map = keyboardMap;
1401
1402 return TRUE;
1403}
1404
1405static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1406{
1407 if (percent > 0)
1408 vncBell();
1409}
1410
1411static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1412{
1413 KeySymsRec keySyms;
1414 CARD8 modMap[MAP_LENGTH];
1415 DevicePtr pDev = (DevicePtr)pDevice;
1416
1417 switch (onoff)
1418 {
1419 case DEVICE_INIT:
1420 GetMappings(&keySyms, modMap);
1421 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1422 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1423 break;
1424 case DEVICE_ON:
1425 pDev->on = TRUE;
1426 break;
1427 case DEVICE_OFF:
1428 pDev->on = FALSE;
1429 break;
1430 case DEVICE_CLOSE:
1431 break;
1432 }
1433 return Success;
1434}
1435
1436static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1437{
1438 BYTE map[6];
1439 DevicePtr pDev = (DevicePtr)pDevice;
1440
1441 switch (onoff)
1442 {
1443 case DEVICE_INIT:
1444 map[1] = 1;
1445 map[2] = 2;
1446 map[3] = 3;
1447 map[4] = 4;
1448 map[5] = 5;
1449 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1450 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1451 break;
1452
1453 case DEVICE_ON:
1454 pDev->on = TRUE;
1455 break;
1456
1457 case DEVICE_OFF:
1458 pDev->on = FALSE;
1459 break;
1460
1461 case DEVICE_CLOSE:
1462 break;
1463 }
1464 return Success;
1465}
1466
1467// InitInput is called after InitExtensions, so we're guaranteed that
1468// vncExtensionInit() has already been called.
1469
1470void InitInput(int argc, char *argv[])
1471{
1472 DeviceIntPtr p, k;
1473 p = AddInputDevice(vfbMouseProc, TRUE);
1474 k = AddInputDevice(vfbKeybdProc, TRUE);
1475 RegisterPointerDevice(p);
1476 RegisterKeyboardDevice(k);
1477 miRegisterPointerDevice(screenInfo.screens[0], p);
1478 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1479}