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