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