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