blob: a170e223c7746de2a080a1fc4319d47e953a643c [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 Åstrand1d742b42005-02-22 21:33:20 +000077#include "micmap.h"
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000078#include <sys/types.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000079#ifdef HAS_MMAP
80#include <sys/mman.h>
81#ifndef MAP_FILE
82#define MAP_FILE 0
83#endif
84#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000085#include <sys/stat.h>
86#include <errno.h>
87#ifndef WIN32
88#include <sys/param.h>
89#endif
90#include <X11/XWDFile.h>
Peter Åstrand1402f8c2005-02-23 08:22:10 +000091#ifdef HAS_SHM
92#include <sys/ipc.h>
93#include <sys/shm.h>
94#endif /* HAS_SHM */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000095#include "dix.h"
96#include "miline.h"
97#include "inputstr.h"
98#include "keysym.h"
99 extern int defaultColorVisualClass;
100 extern char buildtime[];
101#undef class
102#undef public
103#undef xor
104#undef and
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000105}
106
107#define XVNCVERSION "4.0"
108
109extern char *display;
110extern int monitorResolution;
111
112#define VFB_DEFAULT_WIDTH 1024
113#define VFB_DEFAULT_HEIGHT 768
114#define VFB_DEFAULT_DEPTH 16
115#define VFB_DEFAULT_WHITEPIXEL 0xffff
116#define VFB_DEFAULT_BLACKPIXEL 0
117#define VFB_DEFAULT_LINEBIAS 0
118#define XWD_WINDOW_NAME_LEN 60
119
120typedef struct
121{
Peter Åstrand60870912005-02-22 21:27:51 +0000122 int scrnum;
123 int width;
124 int paddedBytesWidth;
125 int paddedWidth;
126 int height;
127 int depth;
128 int bitsPerPixel;
129 int sizeInBytes;
130 int ncolors;
131 char *pfbMemory;
132 XWDColor *pXWDCmap;
133 XWDFileHeader *pXWDHeader;
134 Pixel blackPixel;
135 Pixel whitePixel;
136 unsigned int lineBias;
137 CloseScreenProcPtr closeScreen;
138
139#ifdef HAS_MMAP
140 int mmap_fd;
141 char mmap_file[MAXPATHLEN];
142#endif
143
144#ifdef HAS_SHM
145 int shmid;
146#endif
147
148 Bool pixelFormatDefined;
149 Bool rgbNotBgr;
150 int redBits, greenBits, blueBits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000151
152} vfbScreenInfo, *vfbScreenInfoPtr;
153
154static int vfbNumScreens;
155static vfbScreenInfo vfbScreens[MAXSCREENS];
156static Bool vfbPixmapDepths[33];
Peter Åstrand00c759d2005-02-22 20:11:47 +0000157#ifdef HAS_MMAP
158static char *pfbdir = NULL;
159#endif
160typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
161static fbMemType fbmemtype = NORMAL_MEMORY_FB;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000162static char needswap = 0;
163static int lastScreen = -1;
Peter Åstrandc5421b22005-02-14 20:25:49 +0000164static Bool Render = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000165
166static bool displaySpecified = false;
167static bool wellKnownSocketsCreated = false;
168static char displayNumStr[16];
169
170#define swapcopy16(_dst, _src) \
171 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
172 else _dst = _src;
173
174#define swapcopy32(_dst, _src) \
175 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
176 else _dst = _src;
177
178
Peter Åstrandf960f042005-02-22 20:07:55 +0000179static void
180vfbInitializePixmapDepths(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000181{
Peter Åstrandf960f042005-02-22 20:07:55 +0000182 int i;
183 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
184 for (i = 2; i <= 32; i++)
185 vfbPixmapDepths[i] = FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000186}
187
Peter Åstrandf960f042005-02-22 20:07:55 +0000188static void
189vfbInitializeDefaultScreens(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000190{
Peter Åstrandf960f042005-02-22 20:07:55 +0000191 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000192
Peter Åstrandf960f042005-02-22 20:07:55 +0000193 for (i = 0; i < MAXSCREENS; i++)
194 {
195 vfbScreens[i].scrnum = i;
196 vfbScreens[i].width = VFB_DEFAULT_WIDTH;
197 vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
198 vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
199 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
200 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
201 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
202 vfbScreens[i].pixelFormatDefined = FALSE;
203 vfbScreens[i].pfbMemory = NULL;
204 }
205 vfbNumScreens = 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000206}
207
Peter Åstrand00c759d2005-02-22 20:11:47 +0000208static int
209vfbBitsPerPixel(int depth)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000210{
Peter Åstrand00c759d2005-02-22 20:11:47 +0000211 if (depth == 1) return 1;
212 else if (depth <= 8) return 8;
213 else if (depth <= 16) return 16;
214 else return 32;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000215}
216
217extern "C" {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000218void
219ddxGiveUp()
220{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000221 int i;
222
223 /* clean up the framebuffers */
224
Peter Åstrand00c759d2005-02-22 20:11:47 +0000225 switch (fbmemtype)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000226 {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000227#ifdef HAS_MMAP
228 case MMAPPED_FILE_FB:
229 for (i = 0; i < vfbNumScreens; i++)
230 {
231 if (-1 == unlink(vfbScreens[i].mmap_file))
232 {
233 perror("unlink");
234 ErrorF("unlink %s failed, errno %d",
235 vfbScreens[i].mmap_file, errno);
236 }
237 }
238 break;
239#else /* HAS_MMAP */
240 case MMAPPED_FILE_FB:
241 break;
242#endif /* HAS_MMAP */
243
244#ifdef HAS_SHM
245 case SHARED_MEMORY_FB:
246 for (i = 0; i < vfbNumScreens; i++)
247 {
248 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
249 {
250 perror("shmdt");
251 ErrorF("shmdt failed, errno %d", errno);
252 }
253 }
254 break;
255#else /* HAS_SHM */
256 case SHARED_MEMORY_FB:
257 break;
258#endif /* HAS_SHM */
259
260 case NORMAL_MEMORY_FB:
261 for (i = 0; i < vfbNumScreens; i++)
262 {
263 Xfree(vfbScreens[i].pXWDHeader);
264 }
265 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000266 }
Peter Åstrand00c759d2005-02-22 20:11:47 +0000267}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000268
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000269void
270AbortDDX()
271{
272 ddxGiveUp();
273}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000274
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000275#ifdef __DARWIN__
276void
277DarwinHandleGUI(int argc, char *argv[])
278{
279}
280
281void GlxExtensionInit();
282void GlxWrapInitVisuals(void *procPtr);
283
284void
285DarwinGlxExtensionInit()
286{
287 GlxExtensionInit();
288}
289
290void
291DarwinGlxWrapInitVisuals(
292 void *procPtr)
293{
294 GlxWrapInitVisuals(procPtr);
295}
296#endif
297
298void
299OsVendorInit()
300{
301}
302
303void
304OsVendorFatalError()
305{
306}
307
308void ddxBeforeReset(void)
309{
310 return;
311}
312
313void
314ddxUseMsg()
315{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000316 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
317 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
318 VENDOR_STRING);
319 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
320 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
Peter Åstrandc5421b22005-02-14 20:25:49 +0000321#ifdef RENDER
322 ErrorF("+/-render turn on/off RENDER extension support"
323 "(default on)\n");
324#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000325 ErrorF("-linebias n adjust thin line pixelization\n");
326 ErrorF("-blackpixel n pixel value for black\n");
327 ErrorF("-whitepixel n pixel value for white\n");
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000328
329#ifdef HAS_MMAP
330 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
331#endif
332
333#ifdef HAS_SHM
334 ErrorF("-shmem put framebuffers in shared memory\n");
335#endif
336
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000337 ErrorF("-geometry WxH set screen 0's width, height\n");
338 ErrorF("-depth D set screen 0's depth\n");
339 ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
340 ErrorF("-inetd has been launched from inetd\n");
341 ErrorF("\nVNC parameters:\n");
342
343 fprintf(stderr,"\n"
344 "Parameters can be turned on with -<param> or off with -<param>=0\n"
345 "Parameters which take a value can be specified as "
346 "-<param> <value>\n"
347 "Other valid forms are <param>=<value> -<param>=<value> "
348 "--<param>=<value>\n"
349 "Parameter names are case-insensitive. The parameters are:\n\n");
350 rfb::Configuration::listParams(79, 14);
351 }
352}
353
Peter Åstrandfc41a212005-02-22 20:29:40 +0000354/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
355void ddxInitGlobals(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000356{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000357}
358
Peter Åstrandfc41a212005-02-22 20:29:40 +0000359static
360bool displayNumFree(int num)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000361{
Peter Åstrandfc41a212005-02-22 20:29:40 +0000362 try {
363 network::TcpListener l(6000+num);
364 } catch (rdr::Exception& e) {
365 return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000366 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000367 char file[256];
368 sprintf(file, "/tmp/.X%d-lock", num);
369 if (access(file, F_OK) == 0) return false;
370 sprintf(file, "/tmp/.X11-unix/X%d", num);
371 if (access(file, F_OK) == 0) return false;
372 sprintf(file, "/usr/spool/sockets/X11/%d", num);
373 if (access(file, F_OK) == 0) return false;
374 return true;
375}
376
377int
378ddxProcessArgument(int argc, char *argv[], int i)
379{
380 static Bool firstTime = TRUE;
381
382 if (firstTime)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000383 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000384 vfbInitializeDefaultScreens();
385 vfbInitializePixmapDepths();
386 firstTime = FALSE;
387 rfb::initStdIOLoggers();
388 rfb::LogWriter::setLogParams("*:stderr:30");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000389 }
390
Peter Åstrandfc41a212005-02-22 20:29:40 +0000391 if (argv[i][0] == ':')
392 displaySpecified = true;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000393
Peter Åstrandfc41a212005-02-22 20:29:40 +0000394 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000395 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000396 int screenNum;
397 if (i + 2 >= argc) UseMsg();
398 screenNum = atoi(argv[i+1]);
399 if (screenNum < 0 || screenNum >= MAXSCREENS)
400 {
401 ErrorF("Invalid screen number %d\n", screenNum);
402 UseMsg();
403 }
404 if (3 != sscanf(argv[i+2], "%dx%dx%d",
405 &vfbScreens[screenNum].width,
406 &vfbScreens[screenNum].height,
407 &vfbScreens[screenNum].depth))
408 {
409 ErrorF("Invalid screen configuration %s\n", argv[i+2]);
410 UseMsg();
411 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000412
Peter Åstrandfc41a212005-02-22 20:29:40 +0000413 if (screenNum >= vfbNumScreens)
414 vfbNumScreens = screenNum + 1;
415 lastScreen = screenNum;
416 return 3;
417 }
418
419 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
420 {
421 int depth, ret = 1;
422
423 if (++i >= argc) UseMsg();
424 while ((i < argc) && (depth = atoi(argv[i++])) != 0)
425 {
426 if (depth < 0 || depth > 32)
427 {
428 ErrorF("Invalid pixmap depth %d\n", depth);
429 UseMsg();
430 }
431 vfbPixmapDepths[depth] = TRUE;
432 ret++;
433 }
434 return ret;
435 }
436
437 if (strcmp (argv[i], "+render") == 0) /* +render */
438 {
439 Render = TRUE;
440 return 1;
441 }
Peter Åstrandc5421b22005-02-14 20:25:49 +0000442
Peter Åstrandfc41a212005-02-22 20:29:40 +0000443 if (strcmp (argv[i], "-render") == 0) /* -render */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000444 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000445 Render = FALSE;
446 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000447 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000448
Peter Åstrandfc41a212005-02-22 20:29:40 +0000449 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000450 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000451 Pixel pix;
452 if (++i >= argc) UseMsg();
453 pix = atoi(argv[i]);
454 if (-1 == lastScreen)
455 {
456 int i;
457 for (i = 0; i < MAXSCREENS; i++)
458 {
459 vfbScreens[i].blackPixel = pix;
460 }
461 }
462 else
463 {
464 vfbScreens[lastScreen].blackPixel = pix;
465 }
466 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000467 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000468
469 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000470 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000471 Pixel pix;
472 if (++i >= argc) UseMsg();
473 pix = atoi(argv[i]);
474 if (-1 == lastScreen)
475 {
476 int i;
477 for (i = 0; i < MAXSCREENS; i++)
478 {
479 vfbScreens[i].whitePixel = pix;
480 }
481 }
482 else
483 {
484 vfbScreens[lastScreen].whitePixel = pix;
485 }
486 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000487 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000488
489 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000490 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000491 unsigned int linebias;
492 if (++i >= argc) UseMsg();
493 linebias = atoi(argv[i]);
494 if (-1 == lastScreen)
495 {
496 int i;
497 for (i = 0; i < MAXSCREENS; i++)
498 {
499 vfbScreens[i].lineBias = linebias;
500 }
501 }
502 else
503 {
504 vfbScreens[lastScreen].lineBias = linebias;
505 }
506 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000507 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000508
509#ifdef HAS_MMAP
510 if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000511 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000512 if (++i >= argc) UseMsg();
513 pfbdir = argv[i];
514 fbmemtype = MMAPPED_FILE_FB;
515 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000516 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000517#endif /* HAS_MMAP */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000518
Peter Åstrandfc41a212005-02-22 20:29:40 +0000519#ifdef HAS_SHM
520 if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
521 {
522 fbmemtype = SHARED_MEMORY_FB;
523 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000524 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000525#endif
526
527 if (strcmp(argv[i], "-geometry") == 0)
528 {
529 if (++i >= argc) UseMsg();
530 if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
531 &vfbScreens[0].height) != 2) {
532 ErrorF("Invalid geometry %s\n", argv[i]);
533 UseMsg();
534 }
535 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000536 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000537
538 if (strcmp(argv[i], "-depth") == 0)
539 {
540 if (++i >= argc) UseMsg();
541 vfbScreens[0].depth = atoi(argv[i]);
542 return 2;
543 }
544
545 if (strcmp(argv[i], "-pixelformat") == 0)
546 {
547 char rgbbgr[4];
548 int bits1, bits2, bits3;
549 if (++i >= argc) UseMsg();
550 if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
551 ErrorF("Invalid pixel format %s\n", argv[i]);
552 UseMsg();
553 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000554
555#define SET_PIXEL_FORMAT(vfbScreen) \
556 (vfbScreen).pixelFormatDefined = TRUE; \
557 (vfbScreen).depth = bits1 + bits2 + bits3; \
558 (vfbScreen).greenBits = bits2; \
559 if (strcasecmp(rgbbgr, "bgr") == 0) { \
560 (vfbScreen).rgbNotBgr = FALSE; \
561 (vfbScreen).redBits = bits3; \
562 (vfbScreen).blueBits = bits1; \
563 } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
564 (vfbScreen).rgbNotBgr = TRUE; \
565 (vfbScreen).redBits = bits1; \
566 (vfbScreen).blueBits = bits3; \
567 } else { \
568 ErrorF("Invalid pixel format %s\n", argv[i]); \
569 UseMsg(); \
570 }
571
Peter Åstrandfc41a212005-02-22 20:29:40 +0000572 if (-1 == lastScreen)
573 {
574 int i;
575 for (i = 0; i < MAXSCREENS; i++)
576 {
577 SET_PIXEL_FORMAT(vfbScreens[i]);
578 }
579 }
580 else
581 {
582 SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
583 }
584
585 return 2;
586 }
587
588 if (strcmp(argv[i], "-inetd") == 0)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000589 {
Peter Åstrandfc41a212005-02-22 20:29:40 +0000590 dup2(0,3);
591 vncInetdSock = 3;
592 close(2);
593
594 if (!displaySpecified) {
595 int port = network::TcpSocket::getSockPort(vncInetdSock);
596 int displayNum = port - 5900;
597 if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
598 for (displayNum = 1; displayNum < 100; displayNum++)
599 if (displayNumFree(displayNum)) break;
600
601 if (displayNum == 100)
602 FatalError("Xvnc error: no free display number for -inetd");
603 }
604
605 display = displayNumStr;
606 sprintf(displayNumStr, "%d", displayNum);
607 }
608
609 return 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000610 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000611
612 if (rfb::Configuration::setParam(argv[i]))
613 return 1;
614
615 if (argv[i][0] == '-' && i+1 < argc) {
616 if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
617 return 2;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000618 }
Peter Åstrandfc41a212005-02-22 20:29:40 +0000619
620 return 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000621}
622
623#ifdef DDXTIME /* from ServerOSDefines */
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000624CARD32
625GetTimeInMillis()
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000626{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000627 struct timeval tp;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000628
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000629 X_GETTIMEOFDAY(&tp);
630 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000631}
632#endif
633
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000634static ColormapPtr InstalledMaps[MAXSCREENS];
635
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000636static int
637vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000638{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000639 /* By the time we are processing requests, we can guarantee that there
640 * is always a colormap installed */
641 *pmaps = InstalledMaps[pScreen->myNum]->mid;
642 return (1);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000643}
644
645
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000646static void
647vfbInstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000648{
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000649 int index = pmap->pScreen->myNum;
650 ColormapPtr oldpmap = InstalledMaps[index];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000651
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000652 if (pmap != oldpmap)
653 {
654 int entries;
655 XWDFileHeader *pXWDHeader;
656 XWDColor *pXWDCmap;
657 VisualPtr pVisual;
658 Pixel * ppix;
659 xrgb * prgb;
660 xColorItem *defs;
661 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000662
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000663 if(oldpmap != (ColormapPtr)None)
664 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
665 /* Install pmap */
666 InstalledMaps[index] = pmap;
667 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000668
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000669 entries = pmap->pVisual->ColormapEntries;
670 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
671 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
672 pVisual = pmap->pVisual;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000673
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000674 swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
675 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
676 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
677 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
678 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
679 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000680
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000681 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
682 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
683 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000684
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000685 for (i = 0; i < entries; i++) ppix[i] = i;
686 /* XXX truecolor */
687 QueryColors(pmap, entries, ppix, prgb);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000688
Peter Åstrand9d803ef2005-02-22 20:35:43 +0000689 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
690 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
691 defs[i].red = prgb[i].red;
692 defs[i].green = prgb[i].green;
693 defs[i].blue = prgb[i].blue;
694 defs[i].flags = DoRed|DoGreen|DoBlue;
695 }
696 (*pmap->pScreen->StoreColors)(pmap, entries, defs);
697
698 DEALLOCATE_LOCAL(ppix);
699 DEALLOCATE_LOCAL(prgb);
700 DEALLOCATE_LOCAL(defs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000701 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000702}
703
Peter Åstrand853287d2005-02-22 20:46:58 +0000704static void
705vfbUninstallColormap(ColormapPtr pmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000706{
Peter Åstrand853287d2005-02-22 20:46:58 +0000707 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000708
Peter Åstrand853287d2005-02-22 20:46:58 +0000709 if(pmap == curpmap)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000710 {
Peter Åstrand853287d2005-02-22 20:46:58 +0000711 if (pmap->mid != pmap->pScreen->defColormap)
712 {
713 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
714 RT_COLORMAP);
715 (*pmap->pScreen->InstallColormap)(curpmap);
716 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000717 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000718}
719
Peter Åstrand853287d2005-02-22 20:46:58 +0000720static void
721vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000722{
Peter Åstrand853287d2005-02-22 20:46:58 +0000723 XWDColor *pXWDCmap;
724 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000725
Peter Åstrand853287d2005-02-22 20:46:58 +0000726 if (pmap != InstalledMaps[pmap->pScreen->myNum])
727 {
728 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000729 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000730
731 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
732
Peter Åstrandbe228572005-02-22 20:48:29 +0000733 if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
Peter Åstrand853287d2005-02-22 20:46:58 +0000734 {
735 return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000736 }
Peter Åstrand853287d2005-02-22 20:46:58 +0000737
738 for (i = 0; i < ndef; i++)
739 {
740 if (pdefs[i].flags & DoRed)
741 {
742 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
743 }
744 if (pdefs[i].flags & DoGreen)
745 {
746 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
747 }
748 if (pdefs[i].flags & DoBlue)
749 {
750 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
751 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000752 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000753}
754
Peter Åstrand853287d2005-02-22 20:46:58 +0000755static Bool
756vfbSaveScreen(ScreenPtr pScreen, int on)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000757{
Peter Åstrand853287d2005-02-22 20:46:58 +0000758 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000759}
760
Peter Åstrand1402f8c2005-02-23 08:22:10 +0000761#ifdef HAS_MMAP
762
763/* this flushes any changes to the screens out to the mmapped file */
764static void
765vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
766{
767 int i;
768
769 for (i = 0; i < vfbNumScreens; i++)
770 {
771#ifdef MS_ASYNC
772 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
773 (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
774#else
775 /* silly NetBSD and who else? */
776 if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
777 (size_t)vfbScreens[i].sizeInBytes))
778#endif
779 {
780 perror("msync");
781 ErrorF("msync failed, errno %d", errno);
782 }
783 }
784}
785
786
787static void
788vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
789{
790}
791
792
793static void
794vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
795{
796#define DUMMY_BUFFER_SIZE 65536
797 char dummyBuffer[DUMMY_BUFFER_SIZE];
798 int currentFileSize, writeThisTime;
799
800 sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
801 if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
802 {
803 perror("open");
804 ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
805 return;
806 }
807
808 /* Extend the file to be the proper size */
809
810 bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
811 for (currentFileSize = 0;
812 currentFileSize < pvfb->sizeInBytes;
813 currentFileSize += writeThisTime)
814 {
815 writeThisTime = min(DUMMY_BUFFER_SIZE,
816 pvfb->sizeInBytes - currentFileSize);
817 if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
818 {
819 perror("write");
820 ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
821 return;
822 }
823 }
824
825 /* try to mmap the file */
826
827 pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
828 PROT_READ|PROT_WRITE,
829 MAP_FILE|MAP_SHARED,
830 pvfb->mmap_fd, 0);
831 if (-1 == (long)pvfb->pXWDHeader)
832 {
833 perror("mmap");
834 ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
835 pvfb->pXWDHeader = NULL;
836 return;
837 }
838
839 if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
840 NULL))
841 {
842 pvfb->pXWDHeader = NULL;
843 }
844}
845#endif /* HAS_MMAP */
846
847
848#ifdef HAS_SHM
849static void
850vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
851{
852 /* create the shared memory segment */
853
854 pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
855 if (pvfb->shmid < 0)
856 {
857 perror("shmget");
858 ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
859 return;
860 }
861
862 /* try to attach it */
863
864 pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
865 if (-1 == (long)pvfb->pXWDHeader)
866 {
867 perror("shmat");
868 ErrorF("shmat failed, errno %d", errno);
869 pvfb->pXWDHeader = NULL;
870 return;
871 }
872
873 ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
874}
875#endif /* HAS_SHM */
876
877
Peter Åstrand8de329f2005-02-22 21:05:16 +0000878static char *
879vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000880{
Peter Åstrand8de329f2005-02-22 21:05:16 +0000881 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000882
Peter Åstrand8de329f2005-02-22 21:05:16 +0000883 pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000884
Peter Åstrand8de329f2005-02-22 21:05:16 +0000885 /* Calculate how many entries in colormap. This is rather bogus, because
886 * the visuals haven't even been set up yet, but we need to know because we
887 * have to allocate space in the file for the colormap. The number 10
888 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
889 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000890
Peter Åstrand8de329f2005-02-22 21:05:16 +0000891 if (pvfb->depth <= 10)
892 { /* single index colormaps */
893 pvfb->ncolors = 1 << pvfb->depth;
894 }
895 else
896 { /* decomposed colormaps */
897 int nplanes_per_color_component = pvfb->depth / 3;
898 if (pvfb->depth % 3) nplanes_per_color_component++;
899 pvfb->ncolors = 1 << nplanes_per_color_component;
900 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000901
Peter Åstrand8de329f2005-02-22 21:05:16 +0000902 /* add extra bytes for XWDFileHeader, window name, and colormap */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000903
Peter Åstrand8de329f2005-02-22 21:05:16 +0000904 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
905 pvfb->ncolors * SIZEOF(XWDColor);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000906
Peter Åstrand8de329f2005-02-22 21:05:16 +0000907 pvfb->pXWDHeader = NULL;
908 switch (fbmemtype)
909 {
910#ifdef HAS_MMAP
911 case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
912#else
913 case MMAPPED_FILE_FB: break;
914#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000915
Peter Åstrand8de329f2005-02-22 21:05:16 +0000916#ifdef HAS_SHM
917 case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
918#else
919 case SHARED_MEMORY_FB: break;
920#endif
921
922 case NORMAL_MEMORY_FB:
923 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
924 break;
925 }
926
927 if (pvfb->pXWDHeader)
928 {
929 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
930 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
931 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
932
933 return pvfb->pfbMemory;
934 }
935 else
936 return NULL;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000937}
938
Peter Åstrandf9357f52005-02-22 21:08:02 +0000939static void
940vfbWriteXWDFileHeader(ScreenPtr pScreen)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000941{
Peter Åstrandf9357f52005-02-22 21:08:02 +0000942 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
943 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
944 char hostname[XWD_WINDOW_NAME_LEN];
945 unsigned long swaptest = 1;
946 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000947
Peter Åstrandf9357f52005-02-22 21:08:02 +0000948 needswap = *(char *) &swaptest;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000949
Peter Åstrandf9357f52005-02-22 21:08:02 +0000950 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
951 pXWDHeader->file_version = XWD_FILE_VERSION;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000952
Peter Åstrandf9357f52005-02-22 21:08:02 +0000953 pXWDHeader->pixmap_format = ZPixmap;
954 pXWDHeader->pixmap_depth = pvfb->depth;
955 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
956 pXWDHeader->xoffset = 0;
957 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
958 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000959#ifndef INTERNAL_VS_EXTERNAL_PADDING
Peter Åstrandf9357f52005-02-22 21:08:02 +0000960 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
961 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
962 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000963#else
Peter Åstrandf9357f52005-02-22 21:08:02 +0000964 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
965 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
966 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000967#endif
Peter Åstrandf9357f52005-02-22 21:08:02 +0000968 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
969 pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
970 pXWDHeader->ncolors = pvfb->ncolors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000971
Peter Åstrandf9357f52005-02-22 21:08:02 +0000972 /* visual related fields are written when colormap is installed */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000973
Peter Åstrandf9357f52005-02-22 21:08:02 +0000974 pXWDHeader->window_x = pXWDHeader->window_y = 0;
975 pXWDHeader->window_bdrwidth = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000976
Peter Åstrandf9357f52005-02-22 21:08:02 +0000977 /* write xwd "window" name: Xvfb hostname:server.screen */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000978
Peter Åstrandf9357f52005-02-22 21:08:02 +0000979 if (-1 == gethostname(hostname, sizeof(hostname)))
980 hostname[0] = 0;
981 else
982 hostname[XWD_WINDOW_NAME_LEN-1] = 0;
983 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
984 pScreen->myNum);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000985
Peter Åstrandf9357f52005-02-22 21:08:02 +0000986 /* write colormap pixel slot values */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000987
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000988 for (i = 0; i < pvfb->ncolors; i++)
989 {
Peter Åstrandf9357f52005-02-22 21:08:02 +0000990 pvfb->pXWDCmap[i].pixel = i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000991 }
Peter Åstrandf9357f52005-02-22 21:08:02 +0000992
993 /* byte swap to most significant byte first */
994
995 if (needswap)
996 {
997 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
998 for (i = 0; i < pvfb->ncolors; i++)
999 {
1000 register char n;
1001 swapl(&pvfb->pXWDCmap[i].pixel, n);
1002 }
1003 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001004}
1005
1006
Peter Åstrandf9357f52005-02-22 21:08:02 +00001007static Bool
1008vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
1009{
1010 return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001011}
Peter Åstrandf9357f52005-02-22 21:08:02 +00001012
1013static void
1014vfbCrossScreen (ScreenPtr pScreen, Bool entering)
1015{
1016}
1017
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001018static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001019 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001020}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001021
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001022static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001023 return TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001024}
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001025
1026static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
1027{
1028}
1029
1030static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
1031{
1032}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001033
1034static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001035 vfbRealizeCursor,
1036 vfbUnrealizeCursor,
1037 vfbSetCursor,
1038 vfbMoveCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001039};
1040
Peter Åstrand5eef5ee2005-02-22 21:13:14 +00001041static miPointerScreenFuncRec vfbPointerCursorFuncs = {
1042 vfbCursorOffScreen,
1043 vfbCrossScreen,
1044 miPointerWarpCursor
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001045};
1046
Peter Åstrand60870912005-02-22 21:27:51 +00001047static Bool
1048vfbCloseScreen(int index, ScreenPtr pScreen)
1049{
1050 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1051 int i;
1052
1053 pScreen->CloseScreen = pvfb->closeScreen;
1054
1055 /*
1056 * XXX probably lots of stuff to clean. For now,
1057 * clear InstalledMaps[] so that server reset works correctly.
1058 */
1059 for (i = 0; i < MAXSCREENS; i++)
1060 InstalledMaps[i] = NULL;
1061
1062 return pScreen->CloseScreen(index, pScreen);
1063}
1064
Peter Åstrand1d742b42005-02-22 21:33:20 +00001065static Bool
1066vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001067{
Peter Åstrand1d742b42005-02-22 21:33:20 +00001068 vfbScreenInfoPtr pvfb = &vfbScreens[index];
1069 int dpix = 100, dpiy = 100;
1070 int ret;
1071 char *pbits;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001072
Peter Åstrand1d742b42005-02-22 21:33:20 +00001073 pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
1074 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
1075 if (pvfb->bitsPerPixel >= 8 )
1076 pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8);
1077 else
1078 pvfb->paddedWidth = pvfb->paddedBytesWidth * 8;
1079 pbits = vfbAllocateFramebufferMemory(pvfb);
1080 if (!pbits) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001081
Peter Åstrand1d742b42005-02-22 21:33:20 +00001082 miSetPixmapDepths ();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001083
Peter Åstrand1d742b42005-02-22 21:33:20 +00001084 switch (pvfb->depth) {
1085 case 8:
1086 miSetVisualTypesAndMasks (8,
1087 ((1 << StaticGray) |
1088 (1 << GrayScale) |
1089 (1 << StaticColor) |
1090 (1 << PseudoColor) |
1091 (1 << TrueColor) |
1092 (1 << DirectColor)),
1093 8, PseudoColor, 0x07, 0x38, 0xc0);
1094 break;
1095 case 15:
1096 miSetVisualTypesAndMasks (15,
1097 ((1 << TrueColor) |
1098 (1 << DirectColor)),
1099 8, TrueColor, 0x7c00, 0x03e0, 0x001f);
1100 break;
1101 case 16:
1102 miSetVisualTypesAndMasks (16,
1103 ((1 << TrueColor) |
1104 (1 << DirectColor)),
1105 8, TrueColor, 0xf800, 0x07e0, 0x001f);
1106 break;
1107 case 24:
1108 miSetVisualTypesAndMasks (24,
1109 ((1 << TrueColor) |
1110 (1 << DirectColor)),
1111 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);
1112 break;
1113 }
1114
1115 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
1116 dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001117#ifdef RENDER
Peter Åstrand1d742b42005-02-22 21:33:20 +00001118 if (ret && Render)
1119 fbPictureInit (pScreen, 0, 0);
Peter Åstrandc5421b22005-02-14 20:25:49 +00001120#endif
1121
Peter Åstrand1d742b42005-02-22 21:33:20 +00001122 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001123
Peter Åstrand1d742b42005-02-22 21:33:20 +00001124 /* miInitializeBackingStore(pScreen); */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001125
Peter Åstrand1d742b42005-02-22 21:33:20 +00001126 /*
1127 * Circumvent the backing store that was just initialised. This amounts
1128 * to a truely bizarre way of initialising SaveDoomedAreas and friends.
1129 */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001130
Peter Åstrand1d742b42005-02-22 21:33:20 +00001131 pScreen->InstallColormap = vfbInstallColormap;
1132 pScreen->UninstallColormap = vfbUninstallColormap;
1133 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001134
Peter Åstrand1d742b42005-02-22 21:33:20 +00001135 pScreen->SaveScreen = vfbSaveScreen;
1136 pScreen->StoreColors = vfbStoreColors;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001137
Peter Åstrand1d742b42005-02-22 21:33:20 +00001138 miDCInitialize(pScreen, &vfbPointerCursorFuncs);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001139
Peter Åstrand1d742b42005-02-22 21:33:20 +00001140 vfbWriteXWDFileHeader(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001141
Peter Åstrand1d742b42005-02-22 21:33:20 +00001142 pScreen->blackPixel = pvfb->blackPixel;
1143 pScreen->whitePixel = pvfb->whitePixel;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001144
Peter Åstrand1d742b42005-02-22 21:33:20 +00001145 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001146
Peter Åstrand1d742b42005-02-22 21:33:20 +00001147 miSetZeroLineBias(pScreen, pvfb->lineBias);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001148
Peter Åstrand1d742b42005-02-22 21:33:20 +00001149 pvfb->closeScreen = pScreen->CloseScreen;
1150 pScreen->CloseScreen = vfbCloseScreen;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001151
Peter Åstrand1d742b42005-02-22 21:33:20 +00001152 return ret;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001153
1154} /* end vfbScreenInit */
1155
1156
1157static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
1158 dispatchException &= ~DE_RESET;
1159}
1160
Peter Åstrand321a9922005-02-22 21:37:32 +00001161void
1162InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001163{
Peter Åstrand321a9922005-02-22 21:37:32 +00001164 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
1165 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
1166 VENDOR_STRING);
1167 int i;
1168 int NumFormats = 0;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001169
Peter Åstrand321a9922005-02-22 21:37:32 +00001170 /* initialize pixmap formats */
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001171
Peter Åstrand321a9922005-02-22 21:37:32 +00001172 /* must have a pixmap depth to match every screen depth */
1173 for (i = 0; i < vfbNumScreens; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001174 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001175 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001176 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001177
Peter Åstrand321a9922005-02-22 21:37:32 +00001178 /* RENDER needs a good set of pixmaps. */
1179 if (Render) {
1180 vfbPixmapDepths[1] = TRUE;
1181 vfbPixmapDepths[4] = TRUE;
1182 vfbPixmapDepths[8] = TRUE;
1183/* vfbPixmapDepths[15] = TRUE; */
1184 vfbPixmapDepths[16] = TRUE;
1185 vfbPixmapDepths[24] = TRUE;
1186 vfbPixmapDepths[32] = TRUE;
1187 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001188
Peter Åstrand321a9922005-02-22 21:37:32 +00001189 for (i = 1; i <= 32; i++)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001190 {
Peter Åstrand321a9922005-02-22 21:37:32 +00001191 if (vfbPixmapDepths[i])
1192 {
1193 if (NumFormats >= MAXFORMATS)
1194 FatalError ("MAXFORMATS is too small for this server\n");
1195 screenInfo->formats[NumFormats].depth = i;
1196 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
1197 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
1198 NumFormats++;
1199 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001200 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001201
Peter Åstrand321a9922005-02-22 21:37:32 +00001202 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
1203 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1204 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1205 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
1206 screenInfo->numPixmapFormats = NumFormats;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001207
Peter Åstrand321a9922005-02-22 21:37:32 +00001208 /* initialize screens */
1209
1210 for (i = 0; i < vfbNumScreens; i++)
1211 {
1212 if (-1 == AddScreen(vfbScreenInit, argc, argv))
1213 {
1214 FatalError("Couldn't add screen %d", i);
1215 }
1216 }
1217
1218 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
1219 FatalError("AddCallback failed\n");
1220 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001221} /* end InitOutput */
1222
1223#ifdef DPMSExtension
1224extern "C" {
1225#if NeedFunctionPrototypes
1226 void DPMSSet(CARD16 level)
1227#else
1228 void DPMSSet(level)
1229 CARD16 level;
1230#endif
1231 {
1232 return;
1233 }
1234
1235 Bool DPMSSupported()
1236 {
1237 return FALSE;
1238 }
1239}
1240#endif
1241
1242/* this is just to get the server to link on AIX */
1243#ifdef AIXV3
1244int SelectWaitTime = 10000; /* usec */
1245#endif
1246
1247Bool LegalModifier(unsigned int key, DevicePtr pDev)
1248{
1249 return TRUE;
1250}
1251
1252void ProcessInputEvents()
1253{
1254 mieqProcessInputEvents();
1255 miPointerUpdate();
1256}
1257
1258/* Fairly standard US PC Keyboard */
1259
1260#define VFB_MIN_KEY 8
1261#define VFB_MAX_KEY 255
1262#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1263#define KEYSYMS_PER_KEY 2
1264KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1265 NoSymbol, NoSymbol,
1266 XK_Escape, NoSymbol,
1267 XK_1, XK_exclam,
1268 XK_2, XK_at,
1269 XK_3, XK_numbersign,
1270 XK_4, XK_dollar,
1271 XK_5, XK_percent,
1272 XK_6, XK_asciicircum,
1273 XK_7, XK_ampersand,
1274 XK_8, XK_asterisk,
1275 XK_9, XK_parenleft,
1276 XK_0, XK_parenright,
1277 XK_minus, XK_underscore,
1278 XK_equal, XK_plus,
1279 XK_BackSpace, NoSymbol,
1280 XK_Tab, NoSymbol,
1281 XK_q, XK_Q,
1282 XK_w, XK_W,
1283 XK_e, XK_E,
1284 XK_r, XK_R,
1285 XK_t, XK_T,
1286 XK_y, XK_Y,
1287 XK_u, XK_U,
1288 XK_i, XK_I,
1289 XK_o, XK_O,
1290 XK_p, XK_P,
1291 XK_bracketleft, XK_braceleft,
1292 XK_bracketright, XK_braceright,
1293 XK_Return, NoSymbol,
1294 XK_Control_L, NoSymbol,
1295 XK_a, XK_A,
1296 XK_s, XK_S,
1297 XK_d, XK_D,
1298 XK_f, XK_F,
1299 XK_g, XK_G,
1300 XK_h, XK_H,
1301 XK_j, XK_J,
1302 XK_k, XK_K,
1303 XK_l, XK_L,
1304 XK_semicolon, XK_colon,
1305 XK_apostrophe, XK_quotedbl,
1306 XK_grave, XK_asciitilde,
1307 XK_Shift_L, NoSymbol,
1308 XK_backslash, XK_bar,
1309 XK_z, XK_Z,
1310 XK_x, XK_X,
1311 XK_c, XK_C,
1312 XK_v, XK_V,
1313 XK_b, XK_B,
1314 XK_n, XK_N,
1315 XK_m, XK_M,
1316 XK_comma, XK_less,
1317 XK_period, XK_greater,
1318 XK_slash, XK_question,
1319 XK_Shift_R, NoSymbol,
1320 XK_KP_Multiply, NoSymbol,
1321 XK_Alt_L, XK_Meta_L,
1322 XK_space, NoSymbol,
1323 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1324 XK_F1, NoSymbol,
1325 XK_F2, NoSymbol,
1326 XK_F3, NoSymbol,
1327 XK_F4, NoSymbol,
1328 XK_F5, NoSymbol,
1329 XK_F6, NoSymbol,
1330 XK_F7, NoSymbol,
1331 XK_F8, NoSymbol,
1332 XK_F9, NoSymbol,
1333 XK_F10, NoSymbol,
1334 XK_Num_Lock, XK_Pointer_EnableKeys,
1335 XK_Scroll_Lock, NoSymbol,
1336 XK_KP_Home, XK_KP_7,
1337 XK_KP_Up, XK_KP_8,
1338 XK_KP_Prior, XK_KP_9,
1339 XK_KP_Subtract, NoSymbol,
1340 XK_KP_Left, XK_KP_4,
1341 XK_KP_Begin, XK_KP_5,
1342 XK_KP_Right, XK_KP_6,
1343 XK_KP_Add, NoSymbol,
1344 XK_KP_End, XK_KP_1,
1345 XK_KP_Down, XK_KP_2,
1346 XK_KP_Next, XK_KP_3,
1347 XK_KP_Insert, XK_KP_0,
1348 XK_KP_Delete, XK_KP_Decimal,
1349 NoSymbol, NoSymbol,
1350 NoSymbol, NoSymbol,
1351 NoSymbol, NoSymbol,
1352 XK_F11, NoSymbol,
1353 XK_F12, NoSymbol,
1354 XK_Home, NoSymbol,
1355 XK_Up, NoSymbol,
1356 XK_Prior, NoSymbol,
1357 XK_Left, NoSymbol,
1358 NoSymbol, NoSymbol,
1359 XK_Right, NoSymbol,
1360 XK_End, NoSymbol,
1361 XK_Down, NoSymbol,
1362 XK_Next, NoSymbol,
1363 XK_Insert, NoSymbol,
1364 XK_Delete, NoSymbol,
1365 XK_KP_Enter, NoSymbol,
1366 XK_Control_R, NoSymbol,
1367 XK_Pause, XK_Break,
1368 XK_Print, XK_Execute,
1369 XK_KP_Divide, NoSymbol,
1370 XK_Alt_R, XK_Meta_R,
1371};
1372
1373static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1374{
1375 int i;
1376
1377 for (i = 0; i < MAP_LENGTH; i++)
1378 pModMap[i] = NoSymbol;
1379
1380 for (i = 0; i < VFB_MAP_LEN; i++) {
1381 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1382 pModMap[i + VFB_MIN_KEY] = LockMask;
1383 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1384 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1385 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1386 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1387 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1388 pModMap[i + VFB_MIN_KEY] = ControlMask;
1389 }
1390 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1391 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1392 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1393 }
1394
1395 pKeySyms->minKeyCode = VFB_MIN_KEY;
1396 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1397 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1398 pKeySyms->map = keyboardMap;
1399
1400 return TRUE;
1401}
1402
1403static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1404{
1405 if (percent > 0)
1406 vncBell();
1407}
1408
1409static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1410{
1411 KeySymsRec keySyms;
1412 CARD8 modMap[MAP_LENGTH];
1413 DevicePtr pDev = (DevicePtr)pDevice;
1414
1415 switch (onoff)
1416 {
1417 case DEVICE_INIT:
1418 GetMappings(&keySyms, modMap);
1419 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1420 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1421 break;
1422 case DEVICE_ON:
1423 pDev->on = TRUE;
1424 break;
1425 case DEVICE_OFF:
1426 pDev->on = FALSE;
1427 break;
1428 case DEVICE_CLOSE:
1429 break;
1430 }
1431 return Success;
1432}
1433
1434static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1435{
1436 BYTE map[6];
1437 DevicePtr pDev = (DevicePtr)pDevice;
1438
1439 switch (onoff)
1440 {
1441 case DEVICE_INIT:
1442 map[1] = 1;
1443 map[2] = 2;
1444 map[3] = 3;
1445 map[4] = 4;
1446 map[5] = 5;
1447 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1448 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1449 break;
1450
1451 case DEVICE_ON:
1452 pDev->on = TRUE;
1453 break;
1454
1455 case DEVICE_OFF:
1456 pDev->on = FALSE;
1457 break;
1458
1459 case DEVICE_CLOSE:
1460 break;
1461 }
1462 return Success;
1463}
1464
1465// InitInput is called after InitExtensions, so we're guaranteed that
1466// vncExtensionInit() has already been called.
1467
1468void InitInput(int argc, char *argv[])
1469{
1470 DeviceIntPtr p, k;
1471 p = AddInputDevice(vfbMouseProc, TRUE);
1472 k = AddInputDevice(vfbKeybdProc, TRUE);
1473 RegisterPointerDevice(p);
1474 RegisterKeyboardDevice(k);
1475 miRegisterPointerDevice(screenInfo.screens[0], p);
1476 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1477}