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