blob: 7ad34f25b7947b68af45943f4169ee20574cb2ea [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"
77#include <sys/types.h>
78#include <sys/stat.h>
79#include <errno.h>
80#ifndef WIN32
81#include <sys/param.h>
82#endif
83#include <X11/XWDFile.h>
84#include "dix.h"
85#include "miline.h"
86#include "inputstr.h"
87#include "keysym.h"
88 extern int defaultColorVisualClass;
89 extern char buildtime[];
90#undef class
91#undef public
92#undef xor
93#undef and
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000094}
95
96#define XVNCVERSION "4.0"
97
98extern char *display;
99extern int monitorResolution;
100
101#define VFB_DEFAULT_WIDTH 1024
102#define VFB_DEFAULT_HEIGHT 768
103#define VFB_DEFAULT_DEPTH 16
104#define VFB_DEFAULT_WHITEPIXEL 0xffff
105#define VFB_DEFAULT_BLACKPIXEL 0
106#define VFB_DEFAULT_LINEBIAS 0
107#define XWD_WINDOW_NAME_LEN 60
108
109typedef struct
110{
111 int scrnum;
112 int width;
113 int paddedWidth;
114 int paddedWidthInBytes;
115 int height;
116 int depth;
117 int bitsPerPixel;
118 int sizeInBytes;
119 int ncolors;
120 char *pfbMemory;
121 XWDColor *pXWDCmap;
122 XWDFileHeader *pXWDHeader;
123 Pixel blackPixel;
124 Pixel whitePixel;
125 unsigned int lineBias;
126 Bool pixelFormatDefined;
127 Bool rgbNotBgr;
128 int redBits, greenBits, blueBits;
129
130} vfbScreenInfo, *vfbScreenInfoPtr;
131
132static int vfbNumScreens;
133static vfbScreenInfo vfbScreens[MAXSCREENS];
134static Bool vfbPixmapDepths[33];
Peter Åstrand00c759d2005-02-22 20:11:47 +0000135#ifdef HAS_MMAP
136static char *pfbdir = NULL;
137#endif
138typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
139static fbMemType fbmemtype = NORMAL_MEMORY_FB;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000140static char needswap = 0;
141static int lastScreen = -1;
Peter Åstrandc5421b22005-02-14 20:25:49 +0000142static Bool Render = TRUE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000143
144static bool displaySpecified = false;
145static bool wellKnownSocketsCreated = false;
146static char displayNumStr[16];
147
148#define swapcopy16(_dst, _src) \
149 if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
150 else _dst = _src;
151
152#define swapcopy32(_dst, _src) \
153 if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
154 else _dst = _src;
155
156
Peter Åstrandf960f042005-02-22 20:07:55 +0000157static void
158vfbInitializePixmapDepths(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000159{
Peter Åstrandf960f042005-02-22 20:07:55 +0000160 int i;
161 vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
162 for (i = 2; i <= 32; i++)
163 vfbPixmapDepths[i] = FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000164}
165
Peter Åstrandf960f042005-02-22 20:07:55 +0000166static void
167vfbInitializeDefaultScreens(void)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000168{
Peter Åstrandf960f042005-02-22 20:07:55 +0000169 int i;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000170
Peter Åstrandf960f042005-02-22 20:07:55 +0000171 for (i = 0; i < MAXSCREENS; i++)
172 {
173 vfbScreens[i].scrnum = i;
174 vfbScreens[i].width = VFB_DEFAULT_WIDTH;
175 vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
176 vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
177 vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
178 vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
179 vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
180 vfbScreens[i].pixelFormatDefined = FALSE;
181 vfbScreens[i].pfbMemory = NULL;
182 }
183 vfbNumScreens = 1;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000184}
185
Peter Åstrand00c759d2005-02-22 20:11:47 +0000186static int
187vfbBitsPerPixel(int depth)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000188{
Peter Åstrand00c759d2005-02-22 20:11:47 +0000189 if (depth == 1) return 1;
190 else if (depth <= 8) return 8;
191 else if (depth <= 16) return 16;
192 else return 32;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000193}
194
195extern "C" {
Peter Åstrand5b99ba52005-02-11 14:05:28 +0000196 void ddxInitGlobals() {}
Peter Åstrand00c759d2005-02-22 20:11:47 +0000197
198void
199ddxGiveUp()
200{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000201 int i;
202
203 /* clean up the framebuffers */
204
Peter Åstrand00c759d2005-02-22 20:11:47 +0000205 switch (fbmemtype)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000206 {
Peter Åstrand00c759d2005-02-22 20:11:47 +0000207#ifdef HAS_MMAP
208 case MMAPPED_FILE_FB:
209 for (i = 0; i < vfbNumScreens; i++)
210 {
211 if (-1 == unlink(vfbScreens[i].mmap_file))
212 {
213 perror("unlink");
214 ErrorF("unlink %s failed, errno %d",
215 vfbScreens[i].mmap_file, errno);
216 }
217 }
218 break;
219#else /* HAS_MMAP */
220 case MMAPPED_FILE_FB:
221 break;
222#endif /* HAS_MMAP */
223
224#ifdef HAS_SHM
225 case SHARED_MEMORY_FB:
226 for (i = 0; i < vfbNumScreens; i++)
227 {
228 if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
229 {
230 perror("shmdt");
231 ErrorF("shmdt failed, errno %d", errno);
232 }
233 }
234 break;
235#else /* HAS_SHM */
236 case SHARED_MEMORY_FB:
237 break;
238#endif /* HAS_SHM */
239
240 case NORMAL_MEMORY_FB:
241 for (i = 0; i < vfbNumScreens; i++)
242 {
243 Xfree(vfbScreens[i].pXWDHeader);
244 }
245 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000246 }
Peter Åstrand00c759d2005-02-22 20:11:47 +0000247}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000248
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000249void
250AbortDDX()
251{
252 ddxGiveUp();
253}
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000254
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000255#ifdef __DARWIN__
256void
257DarwinHandleGUI(int argc, char *argv[])
258{
259}
260
261void GlxExtensionInit();
262void GlxWrapInitVisuals(void *procPtr);
263
264void
265DarwinGlxExtensionInit()
266{
267 GlxExtensionInit();
268}
269
270void
271DarwinGlxWrapInitVisuals(
272 void *procPtr)
273{
274 GlxWrapInitVisuals(procPtr);
275}
276#endif
277
278void
279OsVendorInit()
280{
281}
282
283void
284OsVendorFatalError()
285{
286}
287
288void ddxBeforeReset(void)
289{
290 return;
291}
292
293void
294ddxUseMsg()
295{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000296 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
297 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
298 VENDOR_STRING);
299 ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
300 ErrorF("-pixdepths list-of-int support given pixmap depths\n");
Peter Åstrandc5421b22005-02-14 20:25:49 +0000301#ifdef RENDER
302 ErrorF("+/-render turn on/off RENDER extension support"
303 "(default on)\n");
304#endif
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000305 ErrorF("-linebias n adjust thin line pixelization\n");
306 ErrorF("-blackpixel n pixel value for black\n");
307 ErrorF("-whitepixel n pixel value for white\n");
Peter Åstrand5b1d7a22005-02-22 20:18:24 +0000308
309#ifdef HAS_MMAP
310 ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
311#endif
312
313#ifdef HAS_SHM
314 ErrorF("-shmem put framebuffers in shared memory\n");
315#endif
316
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000317 ErrorF("-geometry WxH set screen 0's width, height\n");
318 ErrorF("-depth D set screen 0's depth\n");
319 ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
320 ErrorF("-inetd has been launched from inetd\n");
321 ErrorF("\nVNC parameters:\n");
322
323 fprintf(stderr,"\n"
324 "Parameters can be turned on with -<param> or off with -<param>=0\n"
325 "Parameters which take a value can be specified as "
326 "-<param> <value>\n"
327 "Other valid forms are <param>=<value> -<param>=<value> "
328 "--<param>=<value>\n"
329 "Parameter names are case-insensitive. The parameters are:\n\n");
330 rfb::Configuration::listParams(79, 14);
331 }
332}
333
334static bool displayNumFree(int num)
335{
336 try {
337 network::TcpListener l(6000+num);
338 } catch (rdr::Exception& e) {
339 return false;
340 }
341 char file[256];
342 sprintf(file, "/tmp/.X%d-lock", num);
343 if (access(file, F_OK) == 0) return false;
344 sprintf(file, "/tmp/.X11-unix/X%d", num);
345 if (access(file, F_OK) == 0) return false;
346 sprintf(file, "/usr/spool/sockets/X11/%d", num);
347 if (access(file, F_OK) == 0) return false;
348 return true;
349}
350
351int ddxProcessArgument(int argc, char *argv[], int i)
352{
353 static Bool firstTime = TRUE;
354
355 if (firstTime)
356 {
357 vfbInitializeDefaultScreens();
358 vfbInitializePixmapDepths();
359 firstTime = FALSE;
360 rfb::initStdIOLoggers();
361 rfb::LogWriter::setLogParams("*:stderr:30");
362 }
363
364 if (argv[i][0] == ':')
365 displaySpecified = true;
366
367 if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
368 {
369 int screenNum;
370 if (i + 2 >= argc) UseMsg();
371 screenNum = atoi(argv[i+1]);
372 if (screenNum < 0 || screenNum >= MAXSCREENS)
373 {
374 ErrorF("Invalid screen number %d\n", screenNum);
375 UseMsg();
376 }
377 if (3 != sscanf(argv[i+2], "%dx%dx%d",
378 &vfbScreens[screenNum].width,
379 &vfbScreens[screenNum].height,
380 &vfbScreens[screenNum].depth))
381 {
382 ErrorF("Invalid screen configuration %s\n", argv[i+2]);
383 UseMsg();
384 }
385
386 if (screenNum >= vfbNumScreens)
387 vfbNumScreens = screenNum + 1;
388 lastScreen = screenNum;
389 return 3;
390 }
391
392 if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
393 {
394 int depth, ret = 1;
395
396 if (++i >= argc) UseMsg();
397 while ((i < argc) && (depth = atoi(argv[i++])) != 0)
398 {
399 if (depth < 0 || depth > 32)
400 {
401 ErrorF("Invalid pixmap depth %d\n", depth);
402 UseMsg();
403 }
404 vfbPixmapDepths[depth] = TRUE;
405 ret++;
406 }
407 return ret;
408 }
409
Peter Åstrandc5421b22005-02-14 20:25:49 +0000410 if (strcmp (argv[i], "+render") == 0) /* +render */
411 {
412 Render = TRUE;
413 return 1;
414 }
415
416 if (strcmp (argv[i], "-render") == 0) /* -render */
417 {
418 Render = FALSE;
419 return 1;
420 }
421
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000422 if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
423 {
424 Pixel pix;
425 if (++i >= argc) UseMsg();
426 pix = atoi(argv[i]);
427 if (-1 == lastScreen)
428 {
429 int i;
430 for (i = 0; i < MAXSCREENS; i++)
431 {
432 vfbScreens[i].blackPixel = pix;
433 }
434 }
435 else
436 {
437 vfbScreens[lastScreen].blackPixel = pix;
438 }
439 return 2;
440 }
441
442 if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
443 {
444 Pixel pix;
445 if (++i >= argc) UseMsg();
446 pix = atoi(argv[i]);
447 if (-1 == lastScreen)
448 {
449 int i;
450 for (i = 0; i < MAXSCREENS; i++)
451 {
452 vfbScreens[i].whitePixel = pix;
453 }
454 }
455 else
456 {
457 vfbScreens[lastScreen].whitePixel = pix;
458 }
459 return 2;
460 }
461
462 if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
463 {
464 unsigned int linebias;
465 if (++i >= argc) UseMsg();
466 linebias = atoi(argv[i]);
467 if (-1 == lastScreen)
468 {
469 int i;
470 for (i = 0; i < MAXSCREENS; i++)
471 {
472 vfbScreens[i].lineBias = linebias;
473 }
474 }
475 else
476 {
477 vfbScreens[lastScreen].lineBias = linebias;
478 }
479 return 2;
480 }
481
482 if (strcmp(argv[i], "-geometry") == 0)
483 {
484 if (++i >= argc) UseMsg();
485 if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
486 &vfbScreens[0].height) != 2) {
487 ErrorF("Invalid geometry %s\n", argv[i]);
488 UseMsg();
489 }
490 return 2;
491 }
492
493 if (strcmp(argv[i], "-depth") == 0)
494 {
495 if (++i >= argc) UseMsg();
496 vfbScreens[0].depth = atoi(argv[i]);
497 return 2;
498 }
499
500 if (strcmp(argv[i], "-pixelformat") == 0)
501 {
502 char rgbbgr[4];
503 int bits1, bits2, bits3;
504 if (++i >= argc) UseMsg();
505 if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
506 ErrorF("Invalid pixel format %s\n", argv[i]);
507 UseMsg();
508 }
509
510#define SET_PIXEL_FORMAT(vfbScreen) \
511 (vfbScreen).pixelFormatDefined = TRUE; \
512 (vfbScreen).depth = bits1 + bits2 + bits3; \
513 (vfbScreen).greenBits = bits2; \
514 if (strcasecmp(rgbbgr, "bgr") == 0) { \
515 (vfbScreen).rgbNotBgr = FALSE; \
516 (vfbScreen).redBits = bits3; \
517 (vfbScreen).blueBits = bits1; \
518 } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
519 (vfbScreen).rgbNotBgr = TRUE; \
520 (vfbScreen).redBits = bits1; \
521 (vfbScreen).blueBits = bits3; \
522 } else { \
523 ErrorF("Invalid pixel format %s\n", argv[i]); \
524 UseMsg(); \
525 }
526
527 if (-1 == lastScreen)
528 {
529 int i;
530 for (i = 0; i < MAXSCREENS; i++)
531 {
532 SET_PIXEL_FORMAT(vfbScreens[i]);
533 }
534 }
535 else
536 {
537 SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
538 }
539
540 return 2;
541 }
542
543 if (strcmp(argv[i], "-inetd") == 0)
544 {
545 dup2(0,3);
546 vncInetdSock = 3;
547 close(2);
548
549 if (!displaySpecified) {
550 int port = network::TcpSocket::getSockPort(vncInetdSock);
551 int displayNum = port - 5900;
552 if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
553 for (displayNum = 1; displayNum < 100; displayNum++)
554 if (displayNumFree(displayNum)) break;
555
556 if (displayNum == 100)
557 FatalError("Xvnc error: no free display number for -inetd");
558 }
559
560 display = displayNumStr;
561 sprintf(displayNumStr, "%d", displayNum);
562 }
563
564 return 1;
565 }
566
567 if (rfb::Configuration::setParam(argv[i]))
568 return 1;
569
570 if (argv[i][0] == '-' && i+1 < argc) {
571 if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
572 return 2;
573 }
574
575 return 0;
576}
577
578#ifdef DDXTIME /* from ServerOSDefines */
579CARD32 GetTimeInMillis()
580{
581 struct timeval tp;
582
583 X_GETTIMEOFDAY(&tp);
584 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
585}
586#endif
587
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000588static ColormapPtr InstalledMaps[MAXSCREENS];
589
590static int vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
591{
592 /* By the time we are processing requests, we can guarantee that there
593 * is always a colormap installed */
594 *pmaps = InstalledMaps[pScreen->myNum]->mid;
595 return (1);
596}
597
598
599static void vfbInstallColormap(ColormapPtr pmap)
600{
601 int index = pmap->pScreen->myNum;
602 ColormapPtr oldpmap = InstalledMaps[index];
603
604 if (pmap != oldpmap)
605 {
606 int entries;
607 XWDFileHeader *pXWDHeader;
608 XWDColor *pXWDCmap;
609 VisualPtr pVisual;
610 Pixel * ppix;
611 xrgb * prgb;
612 xColorItem *defs;
613 int i;
614
615 if(oldpmap != (ColormapPtr)None)
616 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
617 /* Install pmap */
618 InstalledMaps[index] = pmap;
619 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
620
621 entries = pmap->pVisual->ColormapEntries;
622 pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
623 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
624 pVisual = pmap->pVisual;
625
626 swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
627 swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
628 swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
629 swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
630 swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
631 swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
632
633 ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
634 prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
635 defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
636
637 for (i = 0; i < entries; i++) ppix[i] = i;
638 /* XXX truecolor */
639 QueryColors(pmap, entries, ppix, prgb);
640
641 for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
642 defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
643 defs[i].red = prgb[i].red;
644 defs[i].green = prgb[i].green;
645 defs[i].blue = prgb[i].blue;
646 defs[i].flags = DoRed|DoGreen|DoBlue;
647 }
648 (*pmap->pScreen->StoreColors)(pmap, entries, defs);
649
650 DEALLOCATE_LOCAL(ppix);
651 DEALLOCATE_LOCAL(prgb);
652 DEALLOCATE_LOCAL(defs);
653 }
654}
655
656static void vfbUninstallColormap(ColormapPtr pmap)
657{
658 ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
659
660 if(pmap == curpmap)
661 {
662 if (pmap->mid != pmap->pScreen->defColormap)
663 {
664 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
665 RT_COLORMAP);
666 (*pmap->pScreen->InstallColormap)(curpmap);
667 }
668 }
669}
670
671static void vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
672{
673 XWDColor *pXWDCmap;
674 int i;
675
676 if (pmap != InstalledMaps[pmap->pScreen->myNum]) return;
677
678 pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
679
680 if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
681 return;
682
683 for (i = 0; i < ndef; i++)
684 {
685 if (pdefs[i].flags & DoRed) {
686 swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
687 }
688 if (pdefs[i].flags & DoGreen) {
689 swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
690 }
691 if (pdefs[i].flags & DoBlue) {
692 swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
693 }
694 }
695}
696
697static Bool vfbSaveScreen(ScreenPtr pScreen, int on)
698{
699 return TRUE;
700}
701
702static char* vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
703{
704 if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
705
706 pvfb->sizeInBytes = pvfb->paddedWidthInBytes * pvfb->height;
707
708 /* Calculate how many entries in colormap. This is rather bogus, because
709 * the visuals haven't even been set up yet, but we need to know because we
710 * have to allocate space in the file for the colormap. The number 10
711 * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
712 */
713
714 if (pvfb->depth <= 10)
715 { /* single index colormaps */
716 pvfb->ncolors = 1 << pvfb->depth;
717 }
718 else
719 { /* decomposed colormaps */
720 int nplanes_per_color_component = pvfb->depth / 3;
721 if (pvfb->depth % 3) nplanes_per_color_component++;
722 pvfb->ncolors = 1 << nplanes_per_color_component;
723 }
724
725 /* add extra bytes for XWDFileHeader, window name, and colormap */
726
727 pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
728 pvfb->ncolors * SIZEOF(XWDColor);
729
730 pvfb->pXWDHeader = NULL;
731 pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
732
733 if (pvfb->pXWDHeader)
734 {
735 pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
736 + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
737 pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
738 memset(pvfb->pfbMemory, 0, pvfb->paddedWidthInBytes * pvfb->height);
739 return pvfb->pfbMemory;
740 }
741 else
742 return NULL;
743}
744
745
746static void vfbWriteXWDFileHeader(ScreenPtr pScreen)
747{
748 vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
749 XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
750 char hostname[XWD_WINDOW_NAME_LEN];
751 VisualPtr pVisual;
752 unsigned long swaptest = 1;
753 int i;
754
755 needswap = *(char *) &swaptest;
756
757 pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
758 pXWDHeader->file_version = XWD_FILE_VERSION;
759
760 pXWDHeader->pixmap_format = ZPixmap;
761 pXWDHeader->pixmap_depth = pvfb->depth;
762 pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
763 pXWDHeader->xoffset = 0;
764 pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
765 pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
766#ifndef INTERNAL_VS_EXTERNAL_PADDING
767 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
768 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
769 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
770#else
771 pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
772 pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
773 pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
774#endif
775 pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
776 pXWDHeader->bytes_per_line = pvfb->paddedWidthInBytes;
777 pXWDHeader->ncolors = pvfb->ncolors;
778
779 /* visual related fields are written when colormap is installed */
780
781 pXWDHeader->window_x = pXWDHeader->window_y = 0;
782 pXWDHeader->window_bdrwidth = 0;
783
784 /* write xwd "window" name: Xvfb hostname:server.screen */
785
786 hostname[0] = 0;
787 sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
788 pScreen->myNum);
789
790 /* write colormap pixel slot values */
791
792 for (i = 0; i < pvfb->ncolors; i++)
793 {
794 pvfb->pXWDCmap[i].pixel = i;
795 }
796
797 /* byte swap to most significant byte first */
798
799 if (needswap)
800 {
801 SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
802 for (i = 0; i < pvfb->ncolors; i++)
803 {
804 register char n;
805 swapl(&pvfb->pXWDCmap[i].pixel, n);
806 }
807 }
808}
809
810
811static Bool vfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) {
812 return FALSE;
813}
814static void vfbCrossScreen (ScreenPtr pScreen, Bool entering) {}
815static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
816 return TRUE;
817}
818static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
819 return TRUE;
820}
821static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
822 int x, int y) {}
823static void vfbMoveCursor(ScreenPtr pScreen, int x, int y) {}
824
825static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
826 vfbRealizeCursor,
827 vfbUnrealizeCursor,
828 vfbSetCursor,
829 vfbMoveCursor
830};
831
832static miPointerScreenFuncRec vfbPointerScreenFuncs = {
833 vfbCursorOffScreen,
834 vfbCrossScreen,
835 miPointerWarpCursor
836};
837
838static Bool vfbScreenInit(int index, ScreenPtr pScreen, int argc, char** argv)
839{
840 vfbScreenInfoPtr pvfb = &vfbScreens[index];
841 int dpi = 100;
842 int ret;
843 char *pbits;
844
845 if (monitorResolution) dpi = monitorResolution;
846
847 pvfb->paddedWidthInBytes = PixmapBytePad(pvfb->width, pvfb->depth);
848 pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
849 pvfb->paddedWidth = pvfb->paddedWidthInBytes * 8 / pvfb->bitsPerPixel;
850 pbits = vfbAllocateFramebufferMemory(pvfb);
851 if (!pbits) return FALSE;
852 vncFbptr[index] = pbits;
853
854 defaultColorVisualClass
855 = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
856
Peter Åstrandc5421b22005-02-14 20:25:49 +0000857 ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
858 dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
859
860#ifdef RENDER
861 if (ret && Render)
862 fbPictureInit(pScreen, 0, 0);
863#endif
864
865 if (!ret) return FALSE;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000866
867 pScreen->InstallColormap = vfbInstallColormap;
868 pScreen->UninstallColormap = vfbUninstallColormap;
869 pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
870
871 pScreen->SaveScreen = vfbSaveScreen;
872 pScreen->StoreColors = vfbStoreColors;
873
874 miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerScreenFuncs,
875 FALSE);
876
877 vfbWriteXWDFileHeader(pScreen);
878
879 pScreen->blackPixel = pvfb->blackPixel;
880 pScreen->whitePixel = pvfb->whitePixel;
881
882 if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
883 pvfb->pixelFormatDefined = TRUE;
884 pvfb->rgbNotBgr = TRUE;
885 pvfb->blueBits = pvfb->redBits = 5;
886 pvfb->greenBits = 6;
887 }
888
889 if (pvfb->pixelFormatDefined) {
890 VisualPtr vis;
891 for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
892 ;
893
894 if (pvfb->rgbNotBgr) {
895 vis->offsetBlue = 0;
896 vis->blueMask = (1 << pvfb->blueBits) - 1;
897 vis->offsetGreen = pvfb->blueBits;
898 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
899 vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
900 vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
901 } else {
902 vis->offsetRed = 0;
903 vis->redMask = (1 << pvfb->redBits) - 1;
904 vis->offsetGreen = pvfb->redBits;
905 vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
906 vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
907 vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
908 }
909 }
910
Peter Åstrand1bdab802005-02-14 14:03:35 +0000911 ret = fbCreateDefColormap(pScreen);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000912
913 miSetZeroLineBias(pScreen, pvfb->lineBias);
914
915 return ret;
916
917} /* end vfbScreenInit */
918
919
920static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
921 dispatchException &= ~DE_RESET;
922}
923
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000924void InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
925{
926 ErrorF("\nXvnc version %s - built %s\n", XVNCVERSION, buildtime);
927 ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
928 VENDOR_STRING);
929 wellKnownSocketsCreated = true;
930
931 int i;
932 int NumFormats = 0;
933
934 /* initialize pixmap formats */
935
936 /* must have a pixmap depth to match every screen depth */
937 for (i = 0; i < vfbNumScreens; i++)
938 {
939 vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
940 }
941
Peter Åstrandc5421b22005-02-14 20:25:49 +0000942 /* RENDER needs a good set of pixmaps. */
943 if (Render) {
944 vfbPixmapDepths[1] = TRUE;
945 vfbPixmapDepths[4] = TRUE;
946 vfbPixmapDepths[8] = TRUE;
947/* vfbPixmapDepths[15] = TRUE; */
948 vfbPixmapDepths[16] = TRUE;
949 vfbPixmapDepths[24] = TRUE;
950 vfbPixmapDepths[32] = TRUE;
951 }
952
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000953 for (i = 1; i <= 32; i++)
954 {
955 if (vfbPixmapDepths[i])
956 {
957 if (NumFormats >= MAXFORMATS)
958 FatalError ("MAXFORMATS is too small for this server\n");
959 screenInfo->formats[NumFormats].depth = i;
960 screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
961 screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
962 NumFormats++;
963 }
964 }
965
966 screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
967 screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
968 screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
969 screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
970 screenInfo->numPixmapFormats = NumFormats;
971
972 /* initialize screens */
973
974 for (i = 0; i < vfbNumScreens; i++)
975 {
976 if (-1 == AddScreen(vfbScreenInit, argc, argv))
977 {
978 FatalError("Couldn't add screen %d", i);
979 }
980 }
981
982 if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
983 FatalError("AddCallback failed\n");
984 }
985
986} /* end InitOutput */
987
988#ifdef DPMSExtension
989extern "C" {
990#if NeedFunctionPrototypes
991 void DPMSSet(CARD16 level)
992#else
993 void DPMSSet(level)
994 CARD16 level;
995#endif
996 {
997 return;
998 }
999
1000 Bool DPMSSupported()
1001 {
1002 return FALSE;
1003 }
1004}
1005#endif
1006
1007/* this is just to get the server to link on AIX */
1008#ifdef AIXV3
1009int SelectWaitTime = 10000; /* usec */
1010#endif
1011
1012Bool LegalModifier(unsigned int key, DevicePtr pDev)
1013{
1014 return TRUE;
1015}
1016
1017void ProcessInputEvents()
1018{
1019 mieqProcessInputEvents();
1020 miPointerUpdate();
1021}
1022
1023/* Fairly standard US PC Keyboard */
1024
1025#define VFB_MIN_KEY 8
1026#define VFB_MAX_KEY 255
1027#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
1028#define KEYSYMS_PER_KEY 2
1029KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
1030 NoSymbol, NoSymbol,
1031 XK_Escape, NoSymbol,
1032 XK_1, XK_exclam,
1033 XK_2, XK_at,
1034 XK_3, XK_numbersign,
1035 XK_4, XK_dollar,
1036 XK_5, XK_percent,
1037 XK_6, XK_asciicircum,
1038 XK_7, XK_ampersand,
1039 XK_8, XK_asterisk,
1040 XK_9, XK_parenleft,
1041 XK_0, XK_parenright,
1042 XK_minus, XK_underscore,
1043 XK_equal, XK_plus,
1044 XK_BackSpace, NoSymbol,
1045 XK_Tab, NoSymbol,
1046 XK_q, XK_Q,
1047 XK_w, XK_W,
1048 XK_e, XK_E,
1049 XK_r, XK_R,
1050 XK_t, XK_T,
1051 XK_y, XK_Y,
1052 XK_u, XK_U,
1053 XK_i, XK_I,
1054 XK_o, XK_O,
1055 XK_p, XK_P,
1056 XK_bracketleft, XK_braceleft,
1057 XK_bracketright, XK_braceright,
1058 XK_Return, NoSymbol,
1059 XK_Control_L, NoSymbol,
1060 XK_a, XK_A,
1061 XK_s, XK_S,
1062 XK_d, XK_D,
1063 XK_f, XK_F,
1064 XK_g, XK_G,
1065 XK_h, XK_H,
1066 XK_j, XK_J,
1067 XK_k, XK_K,
1068 XK_l, XK_L,
1069 XK_semicolon, XK_colon,
1070 XK_apostrophe, XK_quotedbl,
1071 XK_grave, XK_asciitilde,
1072 XK_Shift_L, NoSymbol,
1073 XK_backslash, XK_bar,
1074 XK_z, XK_Z,
1075 XK_x, XK_X,
1076 XK_c, XK_C,
1077 XK_v, XK_V,
1078 XK_b, XK_B,
1079 XK_n, XK_N,
1080 XK_m, XK_M,
1081 XK_comma, XK_less,
1082 XK_period, XK_greater,
1083 XK_slash, XK_question,
1084 XK_Shift_R, NoSymbol,
1085 XK_KP_Multiply, NoSymbol,
1086 XK_Alt_L, XK_Meta_L,
1087 XK_space, NoSymbol,
1088 /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
1089 XK_F1, NoSymbol,
1090 XK_F2, NoSymbol,
1091 XK_F3, NoSymbol,
1092 XK_F4, NoSymbol,
1093 XK_F5, NoSymbol,
1094 XK_F6, NoSymbol,
1095 XK_F7, NoSymbol,
1096 XK_F8, NoSymbol,
1097 XK_F9, NoSymbol,
1098 XK_F10, NoSymbol,
1099 XK_Num_Lock, XK_Pointer_EnableKeys,
1100 XK_Scroll_Lock, NoSymbol,
1101 XK_KP_Home, XK_KP_7,
1102 XK_KP_Up, XK_KP_8,
1103 XK_KP_Prior, XK_KP_9,
1104 XK_KP_Subtract, NoSymbol,
1105 XK_KP_Left, XK_KP_4,
1106 XK_KP_Begin, XK_KP_5,
1107 XK_KP_Right, XK_KP_6,
1108 XK_KP_Add, NoSymbol,
1109 XK_KP_End, XK_KP_1,
1110 XK_KP_Down, XK_KP_2,
1111 XK_KP_Next, XK_KP_3,
1112 XK_KP_Insert, XK_KP_0,
1113 XK_KP_Delete, XK_KP_Decimal,
1114 NoSymbol, NoSymbol,
1115 NoSymbol, NoSymbol,
1116 NoSymbol, NoSymbol,
1117 XK_F11, NoSymbol,
1118 XK_F12, NoSymbol,
1119 XK_Home, NoSymbol,
1120 XK_Up, NoSymbol,
1121 XK_Prior, NoSymbol,
1122 XK_Left, NoSymbol,
1123 NoSymbol, NoSymbol,
1124 XK_Right, NoSymbol,
1125 XK_End, NoSymbol,
1126 XK_Down, NoSymbol,
1127 XK_Next, NoSymbol,
1128 XK_Insert, NoSymbol,
1129 XK_Delete, NoSymbol,
1130 XK_KP_Enter, NoSymbol,
1131 XK_Control_R, NoSymbol,
1132 XK_Pause, XK_Break,
1133 XK_Print, XK_Execute,
1134 XK_KP_Divide, NoSymbol,
1135 XK_Alt_R, XK_Meta_R,
1136};
1137
1138static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
1139{
1140 int i;
1141
1142 for (i = 0; i < MAP_LENGTH; i++)
1143 pModMap[i] = NoSymbol;
1144
1145 for (i = 0; i < VFB_MAP_LEN; i++) {
1146 if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
1147 pModMap[i + VFB_MIN_KEY] = LockMask;
1148 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
1149 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
1150 pModMap[i + VFB_MIN_KEY] = ShiftMask;
1151 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
1152 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
1153 pModMap[i + VFB_MIN_KEY] = ControlMask;
1154 }
1155 else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
1156 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
1157 pModMap[i + VFB_MIN_KEY] = Mod1Mask;
1158 }
1159
1160 pKeySyms->minKeyCode = VFB_MIN_KEY;
1161 pKeySyms->maxKeyCode = VFB_MAX_KEY;
1162 pKeySyms->mapWidth = KEYSYMS_PER_KEY;
1163 pKeySyms->map = keyboardMap;
1164
1165 return TRUE;
1166}
1167
1168static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
1169{
1170 if (percent > 0)
1171 vncBell();
1172}
1173
1174static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
1175{
1176 KeySymsRec keySyms;
1177 CARD8 modMap[MAP_LENGTH];
1178 DevicePtr pDev = (DevicePtr)pDevice;
1179
1180 switch (onoff)
1181 {
1182 case DEVICE_INIT:
1183 GetMappings(&keySyms, modMap);
1184 InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
1185 (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
1186 break;
1187 case DEVICE_ON:
1188 pDev->on = TRUE;
1189 break;
1190 case DEVICE_OFF:
1191 pDev->on = FALSE;
1192 break;
1193 case DEVICE_CLOSE:
1194 break;
1195 }
1196 return Success;
1197}
1198
1199static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
1200{
1201 BYTE map[6];
1202 DevicePtr pDev = (DevicePtr)pDevice;
1203
1204 switch (onoff)
1205 {
1206 case DEVICE_INIT:
1207 map[1] = 1;
1208 map[2] = 2;
1209 map[3] = 3;
1210 map[4] = 4;
1211 map[5] = 5;
1212 InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
1213 (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
1214 break;
1215
1216 case DEVICE_ON:
1217 pDev->on = TRUE;
1218 break;
1219
1220 case DEVICE_OFF:
1221 pDev->on = FALSE;
1222 break;
1223
1224 case DEVICE_CLOSE:
1225 break;
1226 }
1227 return Success;
1228}
1229
1230// InitInput is called after InitExtensions, so we're guaranteed that
1231// vncExtensionInit() has already been called.
1232
1233void InitInput(int argc, char *argv[])
1234{
1235 DeviceIntPtr p, k;
1236 p = AddInputDevice(vfbMouseProc, TRUE);
1237 k = AddInputDevice(vfbKeybdProc, TRUE);
1238 RegisterPointerDevice(p);
1239 RegisterKeyboardDevice(k);
1240 miRegisterPointerDevice(screenInfo.screens[0], p);
1241 (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
1242}