blob: e5e92904710f7488f974e740757531bf24ebf3ab [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];
Peter Åstrandd6a29142005-02-23 15:22:34 +00001071 int dpi = 100;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001072 int ret;
1073 char *pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001074
Peter Åstrandd6a29142005-02-23 15:22:34 +00001075 if (monitorResolution) dpi = monitorResolution;
1076
Peter Åstrand1d742b42005-02-22 21:33:20 +00001077 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
1078 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
Peter Åstrandd6a29142005-02-23 15:22:34 +00001079 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
Peter Åstrand1d742b42005-02-22 21:33:20 +00001080 pbits = vfbAllocateFramebufferMemory(pvfb);
1081 if (!pbits) return FALSE;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001082 vncFbptr[index] = pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001083
Peter Åstrandd6a29142005-02-23 15:22:34 +00001084 defaultColorVisualClass
1085 = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001086
Peter Åstrand1d742b42005-02-22 21:33:20 +00001087 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
Peter Åstrandd6a29142005-02-23 15:22:34 +00001088 dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
1089
Peter Åstrandc5421b22005-02-14 20:25:49 +00001090#ifdef RENDER
Peter Åstrand1d742b42005-02-22 21:33:20 +00001091 if (ret && Render)
1092 fbPictureInit (pScreen, 0, 0);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001093#endif
1094
Peter Åstrand1d742b42005-02-22 21:33:20 +00001095 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001096
Peter Åstrand1d742b42005-02-22 21:33:20 +00001097 /* miInitializeBackingStore(pScreen); */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001098
Peter Åstrand1d742b42005-02-22 21:33:20 +00001099 /*
1100 * Circumvent the backing store that was just initialised. This amounts
1101 * to a truely bizarre way of initialising SaveDoomedAreas and friends.
1102 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001103
Peter Åstrand1d742b42005-02-22 21:33:20 +00001104 pScreen->InstallColormap = vfbInstallColormap;
1105 pScreen->UninstallColormap = vfbUninstallColormap;
1106 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001107
Peter Åstrand1d742b42005-02-22 21:33:20 +00001108 pScreen->SaveScreen = vfbSaveScreen;
1109 pScreen->StoreColors = vfbStoreColors;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001110
1111 miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
1112 FALSE);
1113
Peter Åstrand1d742b42005-02-22 21:33:20 +00001114 vfbWriteXWDFileHeader(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001115
Peter Åstrand1d742b42005-02-22 21:33:20 +00001116 pScreen->blackPixel = pvfb->blackPixel;
1117 pScreen->whitePixel = pvfb->whitePixel;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001118
Peter Åstrandd6a29142005-02-23 15:22:34 +00001119 if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
1120 pvfb->pixelFormatDefined = TRUE;
1121 pvfb->rgbNotBgr = TRUE;
1122 pvfb->blueBits = pvfb->redBits = 5;
1123 pvfb->greenBits = 6;
1124 }
1125
1126 if (pvfb->pixelFormatDefined) {
Peter Åstrand2e387492005-06-21 14:04:43 +00001127 VisualPtr vis = pScreen->visuals;
1128 for (int i = 0; i < pScreen->numVisuals; i++) {
1129 if (pvfb->rgbNotBgr) {
1130 vis->offsetBlue = 0;
1131 vis->blueMask = (1 << pvfb->blueBits) - 1;
1132 vis->offsetGreen = pvfb->blueBits;
1133 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1134 vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
1135 vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
1136 } else {
1137 vis->offsetRed = 0;
1138 vis->redMask = (1 << pvfb->redBits) - 1;
1139 vis->offsetGreen = pvfb->redBits;
1140 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
1141 vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
1142 vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
1143 }
1144 vis++;
Peter Åstrandd6a29142005-02-23 15:22:34 +00001145 }
1146 }
1147
Peter Åstrand1d742b42005-02-22 21:33:20 +00001148 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001149
Peter Åstrand1d742b42005-02-22 21:33:20 +00001150 miSetZeroLineBias(pScreen, pvfb->lineBias);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001151
Peter Åstrand1d742b42005-02-22 21:33:20 +00001152 pvfb->closeScreen = pScreen->CloseScreen;
1153 pScreen->CloseScreen = vfbCloseScreen;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001154
Peter Åstrand1d742b42005-02-22 21:33:20 +00001155 return ret;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001156
1157} /* end vfbScreenInit */
1158
1159
1160static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
1161 dispatchException &= ~DE_RESET;
1162}
1163
Peter Åstrand321a9922005-02-22 21:37:32 +00001164void
1165InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001166{
Peter Åstrand321a9922005-02-22 21:37:32 +00001167 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
1168 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
1169 VENDOR_STRING);
1170 int i;
1171 int NumFormats = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001172
Peter Åstrand321a9922005-02-22 21:37:32 +00001173 /* initialize pixmap formats */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001174
Peter Åstrand321a9922005-02-22 21:37:32 +00001175 /* must have a pixmap depth to match every screen depth */
1176 for (i = 0; i < vfbNumScreens; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001177 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001178 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001179 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001180
Peter Åstrand321a9922005-02-22 21:37:32 +00001181 /* RENDER needs a good set of pixmaps. */
1182 if (Render) {
1183 vfbPixmapDepths[1] = TRUE;
1184 vfbPixmapDepths[4] = TRUE;
1185 vfbPixmapDepths[8] = TRUE;
1186/* vfbPixmapDepths[15] = TRUE; */
1187 vfbPixmapDepths[16] = TRUE;
1188 vfbPixmapDepths[24] = TRUE;
1189 vfbPixmapDepths[32] = TRUE;
1190 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001191
Peter Åstrand321a9922005-02-22 21:37:32 +00001192 for (i = 1; i <= 32; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001193 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001194 if (vfbPixmapDepths[i])
1195 {
1196 if (NumFormats >= MAXFORMATS)
1197 FatalError ("MAXFORMATS is too small for this server\n");
1198 screenInfo->formats[NumFormats].depth = i;
1199 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1200 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1201 NumFormats++;
1202 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001203 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001204
Peter Åstrand321a9922005-02-22 21:37:32 +00001205 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
1206 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1207 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1208 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
1209 screenInfo->numPixmapFormats = NumFormats;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001210
Peter Åstrand321a9922005-02-22 21:37:32 +00001211 /* initialize screens */
1212
1213 for (i = 0; i < vfbNumScreens; i++)
1214 {
1215 if (-1 == AddScreen(vfbScreenInit, argc, argv))
1216 {
1217 FatalError("Couldn't add screen %d", i);
1218 }
1219 }
1220
1221 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
1222 FatalError("AddCallback failed\n");
1223 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001224} /* end InitOutput */
1225
1226#ifdef DPMSExtension
1227extern "C" {
1228#if NeedFunctionPrototypes
1229 void DPMSSet(CARD16 level)
1230#else
1231 void DPMSSet(level)
1232 CARD16 level;
1233#endif
1234 {
1235 return;
1236 }
1237
1238 Bool DPMSSupported()
1239 {
1240 return FALSE;
1241 }
1242}
1243#endif
1244
1245/* this is just to get the server to link on AIX */
1246#ifdef AIXV3
1247int SelectWaitTime = 10000; /* usec */
1248#endif
1249
1250Bool LegalModifier(unsigned int key, DevicePtr pDev)
1251{
1252 return TRUE;
1253}
1254
1255void ProcessInputEvents()
1256{
1257 mieqProcessInputEvents();
1258 miPointerUpdate();
1259}
1260
1261/* Fairly standard US PC Keyboard */
1262
1263#define VFB_MIN_KEY 8
1264#define VFB_MAX_KEY 255
1265#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1266#define KEYSYMS_PER_KEY 2
1267KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1268 NoSymbol, NoSymbol,
1269 XK_Escape, NoSymbol,
1270 XK_1, XK_exclam,
1271 XK_2, XK_at,
1272 XK_3, XK_numbersign,
1273 XK_4, XK_dollar,
1274 XK_5, XK_percent,
1275 XK_6, XK_asciicircum,
1276 XK_7, XK_ampersand,
1277 XK_8, XK_asterisk,
1278 XK_9, XK_parenleft,
1279 XK_0, XK_parenright,
1280 XK_minus, XK_underscore,
1281 XK_equal, XK_plus,
1282 XK_BackSpace, NoSymbol,
1283 XK_Tab, NoSymbol,
1284 XK_q, XK_Q,
1285 XK_w, XK_W,
1286 XK_e, XK_E,
1287 XK_r, XK_R,
1288 XK_t, XK_T,
1289 XK_y, XK_Y,
1290 XK_u, XK_U,
1291 XK_i, XK_I,
1292 XK_o, XK_O,
1293 XK_p, XK_P,
1294 XK_bracketleft, XK_braceleft,
1295 XK_bracketright, XK_braceright,
1296 XK_Return, NoSymbol,
1297 XK_Control_L, NoSymbol,
1298 XK_a, XK_A,
1299 XK_s, XK_S,
1300 XK_d, XK_D,
1301 XK_f, XK_F,
1302 XK_g, XK_G,
1303 XK_h, XK_H,
1304 XK_j, XK_J,
1305 XK_k, XK_K,
1306 XK_l, XK_L,
1307 XK_semicolon, XK_colon,
1308 XK_apostrophe, XK_quotedbl,
1309 XK_grave, XK_asciitilde,
1310 XK_Shift_L, NoSymbol,
1311 XK_backslash, XK_bar,
1312 XK_z, XK_Z,
1313 XK_x, XK_X,
1314 XK_c, XK_C,
1315 XK_v, XK_V,
1316 XK_b, XK_B,
1317 XK_n, XK_N,
1318 XK_m, XK_M,
1319 XK_comma, XK_less,
1320 XK_period, XK_greater,
1321 XK_slash, XK_question,
1322 XK_Shift_R, NoSymbol,
1323 XK_KP_Multiply, NoSymbol,
1324 XK_Alt_L, XK_Meta_L,
1325 XK_space, NoSymbol,
1326 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1327 XK_F1, NoSymbol,
1328 XK_F2, NoSymbol,
1329 XK_F3, NoSymbol,
1330 XK_F4, NoSymbol,
1331 XK_F5, NoSymbol,
1332 XK_F6, NoSymbol,
1333 XK_F7, NoSymbol,
1334 XK_F8, NoSymbol,
1335 XK_F9, NoSymbol,
1336 XK_F10, NoSymbol,
1337 XK_Num_Lock, XK_Pointer_EnableKeys,
1338 XK_Scroll_Lock, NoSymbol,
1339 XK_KP_Home, XK_KP_7,
1340 XK_KP_Up, XK_KP_8,
1341 XK_KP_Prior, XK_KP_9,
1342 XK_KP_Subtract, NoSymbol,
1343 XK_KP_Left, XK_KP_4,
1344 XK_KP_Begin, XK_KP_5,
1345 XK_KP_Right, XK_KP_6,
1346 XK_KP_Add, NoSymbol,
1347 XK_KP_End, XK_KP_1,
1348 XK_KP_Down, XK_KP_2,
1349 XK_KP_Next, XK_KP_3,
1350 XK_KP_Insert, XK_KP_0,
1351 XK_KP_Delete, XK_KP_Decimal,
1352 NoSymbol, NoSymbol,
1353 NoSymbol, NoSymbol,
1354 NoSymbol, NoSymbol,
1355 XK_F11, NoSymbol,
1356 XK_F12, NoSymbol,
1357 XK_Home, NoSymbol,
1358 XK_Up, NoSymbol,
1359 XK_Prior, NoSymbol,
1360 XK_Left, NoSymbol,
1361 NoSymbol, NoSymbol,
1362 XK_Right, NoSymbol,
1363 XK_End, NoSymbol,
1364 XK_Down, NoSymbol,
1365 XK_Next, NoSymbol,
1366 XK_Insert, NoSymbol,
1367 XK_Delete, NoSymbol,
1368 XK_KP_Enter, NoSymbol,
1369 XK_Control_R, NoSymbol,
1370 XK_Pause, XK_Break,
1371 XK_Print, XK_Execute,
1372 XK_KP_Divide, NoSymbol,
1373 XK_Alt_R, XK_Meta_R,
1374};
1375
1376static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1377{
1378 int i;
1379
1380 for (i = 0; i < MAP_LENGTH; i++)
1381 pModMap[i] = NoSymbol;
1382
1383 for (i = 0; i < VFB_MAP_LEN; i++) {
1384 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1385 pModMap[i + VFB_MIN_KEY] = LockMask;
1386 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1387 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1388 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1389 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1390 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1391 pModMap[i + VFB_MIN_KEY] = ControlMask;
1392 }
1393 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1394 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1395 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1396 }
1397
1398 pKeySyms->minKeyCode = VFB_MIN_KEY;
1399 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1400 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1401 pKeySyms->map = keyboardMap;
1402
1403 return TRUE;
1404}
1405
1406static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1407{
1408 if (percent > 0)
1409 vncBell();
1410}
1411
1412static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1413{
1414 KeySymsRec keySyms;
1415 CARD8 modMap[MAP_LENGTH];
1416 DevicePtr pDev = (DevicePtr)pDevice;
1417
1418 switch (onoff)
1419 {
1420 case DEVICE_INIT:
1421 GetMappings(&keySyms, modMap);
1422 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1423 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1424 break;
1425 case DEVICE_ON:
1426 pDev->on = TRUE;
1427 break;
1428 case DEVICE_OFF:
1429 pDev->on = FALSE;
1430 break;
1431 case DEVICE_CLOSE:
1432 break;
1433 }
1434 return Success;
1435}
1436
1437static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1438{
1439 BYTE map[6];
1440 DevicePtr pDev = (DevicePtr)pDevice;
1441
1442 switch (onoff)
1443 {
1444 case DEVICE_INIT:
1445 map[1] = 1;
1446 map[2] = 2;
1447 map[3] = 3;
1448 map[4] = 4;
1449 map[5] = 5;
1450 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1451 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1452 break;
1453
1454 case DEVICE_ON:
1455 pDev->on = TRUE;
1456 break;
1457
1458 case DEVICE_OFF:
1459 pDev->on = FALSE;
1460 break;
1461
1462 case DEVICE_CLOSE:
1463 break;
1464 }
1465 return Success;
1466}
1467
1468// InitInput is called after InitExtensions, so we're guaranteed that
1469// vncExtensionInit() has already been called.
1470
1471void InitInput(int argc, char *argv[])
1472{
1473 DeviceIntPtr p, k;
1474 p = AddInputDevice(vfbMouseProc, TRUE);
1475 k = AddInputDevice(vfbKeybdProc, TRUE);
1476 RegisterPointerDevice(p);
1477 RegisterKeyboardDevice(k);
1478 miRegisterPointerDevice(screenInfo.screens[0], p);
1479 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1480}