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