You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xvnc.c 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /* Copyright (c) 1993 X Consortium
  2. Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  3. Copyright 2009-2015 Pierre Ossman for Cendio AB
  4. Permission is hereby granted, free of charge, to any person obtaining
  5. a copy of this software and associated documentation files (the
  6. "Software"), to deal in the Software without restriction, including
  7. without limitation the rights to use, copy, modify, merge, publish,
  8. distribute, sublicense, and/or sell copies of the Software, and to
  9. permit persons to whom the Software is furnished to do so, subject to
  10. the following conditions:
  11. The above copyright notice and this permission notice shall be included
  12. in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  16. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
  17. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  18. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  19. OTHER DEALINGS IN THE SOFTWARE.
  20. Except as contained in this notice, the name of the X Consortium shall
  21. not be used in advertising or otherwise to promote the sale, use or
  22. other dealings in this Software without prior written authorization
  23. from the X Consortium.
  24. */
  25. #ifdef HAVE_DIX_CONFIG_H
  26. #include <dix-config.h>
  27. #endif
  28. #include "vncExtInit.h"
  29. #include "RFBGlue.h"
  30. #include "XorgGlue.h"
  31. #include "RandrGlue.h"
  32. #include "xorg-version.h"
  33. #include <stdio.h>
  34. #include <X11/X.h>
  35. #include <X11/Xproto.h>
  36. #include <X11/Xos.h>
  37. #include "scrnintstr.h"
  38. #include "servermd.h"
  39. #include "fb.h"
  40. #include "mi.h"
  41. #include "gcstruct.h"
  42. #include "input.h"
  43. #include "mipointer.h"
  44. #include "micmap.h"
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <errno.h>
  48. #include <sys/param.h>
  49. #include "dix.h"
  50. #include "os.h"
  51. #include "miline.h"
  52. #include "glx_extinit.h"
  53. #include "inputstr.h"
  54. #include "randrstr.h"
  55. #ifdef DPMSExtension
  56. #include "dpmsproc.h"
  57. #endif
  58. #include <X11/keysym.h>
  59. extern char buildtime[];
  60. #undef VENDOR_RELEASE
  61. #undef VENDOR_STRING
  62. #include "version-config.h"
  63. #include "site.h"
  64. #define XVNCVERSION "TigerVNC 1.11.80"
  65. #define XVNCCOPYRIGHT ("Copyright (C) 1999-2021 TigerVNC Team and many others (see README.rst)\n" \
  66. "See https://www.tigervnc.org for information on TigerVNC.\n")
  67. #define VNC_DEFAULT_WIDTH 1024
  68. #define VNC_DEFAULT_HEIGHT 768
  69. #define VNC_DEFAULT_DEPTH 24
  70. typedef struct {
  71. int width;
  72. int paddedBytesWidth;
  73. int paddedWidth;
  74. int height;
  75. int depth;
  76. int bitsPerPixel;
  77. void *pfbMemory;
  78. } VncFramebufferInfo, *VncFramebufferInfoPtr;
  79. typedef struct {
  80. VncFramebufferInfo fb;
  81. Bool pixelFormatDefined;
  82. Bool rgbNotBgr;
  83. int redBits, greenBits, blueBits;
  84. } VncScreenInfo, *VncScreenInfoPtr;
  85. static VncScreenInfo vncScreenInfo = {
  86. .fb.width = VNC_DEFAULT_WIDTH,
  87. .fb.height = VNC_DEFAULT_HEIGHT,
  88. .fb.depth = VNC_DEFAULT_DEPTH,
  89. .fb.pfbMemory = NULL,
  90. .pixelFormatDefined = FALSE,
  91. };
  92. static Bool vncPixmapDepths[33];
  93. static Bool Render = TRUE;
  94. static Bool displaySpecified = FALSE;
  95. static char displayNumStr[16];
  96. static int vncVerbose = DEFAULT_LOG_VERBOSITY;
  97. static void
  98. vncPrintBanner(void)
  99. {
  100. ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
  101. ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
  102. VENDOR_STRING);
  103. }
  104. static void
  105. vncInitializePixmapDepths(void)
  106. {
  107. int i;
  108. vncPixmapDepths[1] = TRUE; /* always need bitmaps */
  109. for (i = 2; i <= 32; i++)
  110. vncPixmapDepths[i] = FALSE;
  111. }
  112. static int
  113. vncBitsPerPixel(int depth)
  114. {
  115. if (depth == 1)
  116. return 1;
  117. else if (depth <= 8)
  118. return 8;
  119. else if (depth <= 16)
  120. return 16;
  121. else
  122. return 32;
  123. }
  124. static void vncFreeFramebufferMemory(VncFramebufferInfoPtr pfb);
  125. #ifdef DPMSExtension
  126. #if XORG_OLDER_THAN(1, 20, 0)
  127. /* Why support DPMS? Because stupid modern desktop environments
  128. such as Unity 2D on Ubuntu 11.10 crashes if DPMS is not
  129. available. (DPMSSet is called by dpms.c, but the return value
  130. is ignored.) */
  131. int
  132. DPMSSet(ClientPtr client, int level)
  133. {
  134. return Success;
  135. }
  136. Bool
  137. DPMSSupported(void)
  138. {
  139. /* Causes DPMSCapable to return false, meaning no devices are DPMS
  140. capable */
  141. return FALSE;
  142. }
  143. #endif
  144. #endif
  145. void
  146. ddxGiveUp(enum ExitCode error)
  147. {
  148. /* clean up the framebuffers */
  149. vncFreeFramebufferMemory(&vncScreenInfo.fb);
  150. }
  151. void
  152. AbortDDX(enum ExitCode error)
  153. {
  154. ddxGiveUp(error);
  155. }
  156. void
  157. OsVendorInit(void)
  158. {
  159. }
  160. void
  161. OsVendorFatalError(const char *f, va_list args)
  162. {
  163. }
  164. #ifdef DDXBEFORERESET
  165. void
  166. ddxBeforeReset(void)
  167. {
  168. return;
  169. }
  170. #endif
  171. #if INPUTTHREAD
  172. #if XORG_AT_LEAST(1, 20, 7)
  173. /** This function is called in Xserver/os/inputthread.c when starting
  174. the input thread. */
  175. void
  176. ddxInputThreadInit(void)
  177. {
  178. }
  179. #endif
  180. #endif
  181. void
  182. ddxUseMsg(void)
  183. {
  184. vncPrintBanner();
  185. ErrorF("-pixdepths list-of-int support given pixmap depths\n");
  186. ErrorF("+/-render turn on/off RENDER extension support"
  187. "(default on)\n");
  188. ErrorF("-geometry WxH set screen 0's width, height\n");
  189. ErrorF("-depth D set screen 0's depth\n");
  190. ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
  191. ErrorF("-inetd has been launched from inetd\n");
  192. ErrorF
  193. ("-noclipboard disable clipboard settings modification via vncconfig utility\n");
  194. ErrorF("-verbose [n] verbose startup messages\n");
  195. ErrorF("-quiet minimal startup messages\n");
  196. ErrorF("-version show the server version\n");
  197. ErrorF("\nVNC parameters:\n");
  198. fprintf(stderr, "\n"
  199. "Parameters can be turned on with -<param> or off with -<param>=0\n"
  200. "Parameters which take a value can be specified as "
  201. "-<param> <value>\n"
  202. "Other valid forms are <param>=<value> -<param>=<value> "
  203. "--<param>=<value>\n"
  204. "Parameter names are case-insensitive. The parameters are:\n\n");
  205. vncListParams(79, 14);
  206. }
  207. static Bool
  208. displayNumFree(int num)
  209. {
  210. char file[256];
  211. if (vncIsTCPPortUsed(6000 + num))
  212. return FALSE;
  213. sprintf(file, "/tmp/.X%d-lock", num);
  214. if (access(file, F_OK) == 0)
  215. return FALSE;
  216. sprintf(file, "/tmp/.X11-unix/X%d", num);
  217. if (access(file, F_OK) == 0)
  218. return FALSE;
  219. sprintf(file, "/usr/spool/sockets/X11/%d", num);
  220. if (access(file, F_OK) == 0)
  221. return FALSE;
  222. return TRUE;
  223. }
  224. int
  225. ddxProcessArgument(int argc, char *argv[], int i)
  226. {
  227. static Bool firstTime = TRUE;
  228. if (firstTime) {
  229. /* Force -noreset as default until we properly handle resets */
  230. dispatchExceptionAtReset = 0;
  231. vncInitializePixmapDepths();
  232. firstTime = FALSE;
  233. vncInitRFB();
  234. }
  235. if (argv[i][0] == ':')
  236. displaySpecified = TRUE;
  237. #define CHECK_FOR_REQUIRED_ARGUMENTS(num) \
  238. if (((i + num) >= argc) || (!argv[i + num])) { \
  239. ErrorF("Required argument to %s not specified\n", argv[i]); \
  240. UseMsg(); \
  241. FatalError("Required argument to %s not specified\n", argv[i]); \
  242. }
  243. if (strcmp(argv[i], "-pixdepths") == 0) { /* -pixdepths list-of-depth */
  244. int depth, ret = 1;
  245. CHECK_FOR_REQUIRED_ARGUMENTS(1);
  246. ++i;
  247. while ((i < argc) && (depth = atoi(argv[i++])) != 0) {
  248. if (depth < 0 || depth > 32) {
  249. ErrorF("Invalid pixmap depth %d\n", depth);
  250. UseMsg();
  251. FatalError("Invalid pixmap depth %d passed to -pixdepths\n",
  252. depth);
  253. }
  254. vncPixmapDepths[depth] = TRUE;
  255. ret++;
  256. }
  257. return ret;
  258. }
  259. if (strcmp(argv[i], "+render") == 0) { /* +render */
  260. Render = TRUE;
  261. return 1;
  262. }
  263. if (strcmp(argv[i], "-render") == 0) { /* -render */
  264. Render = FALSE;
  265. return 1;
  266. }
  267. if (strcmp(argv[i], "-geometry") == 0) {
  268. CHECK_FOR_REQUIRED_ARGUMENTS(1);
  269. ++i;
  270. if (sscanf(argv[i], "%dx%d", &vncScreenInfo.fb.width,
  271. &vncScreenInfo.fb.height) != 2) {
  272. ErrorF("Invalid geometry %s\n", argv[i]);
  273. UseMsg();
  274. FatalError("Invalid geometry %s passed to -geometry\n",
  275. argv[i]);
  276. }
  277. return 2;
  278. }
  279. if (strcmp(argv[i], "-depth") == 0) {
  280. CHECK_FOR_REQUIRED_ARGUMENTS(1);
  281. ++i;
  282. vncScreenInfo.fb.depth = atoi(argv[i]);
  283. return 2;
  284. }
  285. if (strcmp(argv[i], "-pixelformat") == 0) {
  286. char rgbbgr[4];
  287. int bits1, bits2, bits3;
  288. CHECK_FOR_REQUIRED_ARGUMENTS(1);
  289. ++i;
  290. if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr, &bits1, &bits2, &bits3) < 4) {
  291. ErrorF("Invalid pixel format %s\n", argv[i]);
  292. UseMsg();
  293. FatalError("Invalid pixel format %s passed to -pixelformat\n",
  294. argv[i]);
  295. }
  296. vncScreenInfo.pixelFormatDefined = TRUE;
  297. vncScreenInfo.fb.depth = bits1 + bits2 + bits3;
  298. vncScreenInfo.greenBits = bits2;
  299. if (strcasecmp(rgbbgr, "bgr") == 0) {
  300. vncScreenInfo.rgbNotBgr = FALSE;
  301. vncScreenInfo.redBits = bits3;
  302. vncScreenInfo.blueBits = bits1;
  303. } else if (strcasecmp(rgbbgr, "rgb") == 0) {
  304. vncScreenInfo.rgbNotBgr = TRUE;
  305. vncScreenInfo.redBits = bits1;
  306. vncScreenInfo.blueBits = bits3;
  307. } else {
  308. ErrorF("Invalid pixel format %s\n", argv[i]);
  309. UseMsg();
  310. FatalError("Invalid pixel format %s passed to -pixelformat\n",
  311. argv[i]);
  312. }
  313. return 2;
  314. }
  315. if (strcmp(argv[i], "-inetd") == 0) {
  316. int nullfd;
  317. dup2(0, 3);
  318. vncInetdSock = 3;
  319. /* Avoid xserver >= 1.19's epoll-fd becoming fd 2 / stderr only to be
  320. replaced by /dev/null by OsInit() because the pollfd is not
  321. writable, breaking ospoll_wait(). */
  322. nullfd = open("/dev/null", O_WRONLY);
  323. dup2(nullfd, 2);
  324. close(nullfd);
  325. if (!displaySpecified) {
  326. int port = vncGetSocketPort(vncInetdSock);
  327. int displayNum = port - 5900;
  328. if (displayNum < 0 || displayNum > 99 ||
  329. !displayNumFree(displayNum)) {
  330. for (displayNum = 1; displayNum < 100; displayNum++)
  331. if (displayNumFree(displayNum))
  332. break;
  333. if (displayNum == 100)
  334. FatalError
  335. ("Xvnc error: no free display number for -inetd\n");
  336. }
  337. display = displayNumStr;
  338. sprintf(displayNumStr, "%d", displayNum);
  339. }
  340. return 1;
  341. }
  342. if (strcmp(argv[i], "-noclipboard") == 0) {
  343. vncNoClipboard = 1;
  344. return 1;
  345. }
  346. if (!strcmp(argv[i], "-verbose")) {
  347. if (++i < argc && argv[i]) {
  348. char *end;
  349. long val;
  350. val = strtol(argv[i], &end, 0);
  351. if (*end == '\0') {
  352. vncVerbose = val;
  353. LogSetParameter(XLOG_VERBOSITY, vncVerbose);
  354. return 2;
  355. }
  356. }
  357. vncVerbose++;
  358. LogSetParameter(XLOG_VERBOSITY, vncVerbose);
  359. return 1;
  360. }
  361. if (!strcmp(argv[i], "-quiet")) {
  362. vncVerbose = -1;
  363. LogSetParameter(XLOG_VERBOSITY, vncVerbose);
  364. return 1;
  365. }
  366. if (!strcmp(argv[i], "-showconfig") || !strcmp(argv[i], "-version")) {
  367. vncPrintBanner();
  368. exit(0);
  369. }
  370. /* We need to resolve an ambiguity for booleans */
  371. if (argv[i][0] == '-' && i + 1 < argc && vncIsParamBool(&argv[i][1])) {
  372. if ((strcasecmp(argv[i + 1], "0") == 0) ||
  373. (strcasecmp(argv[i + 1], "1") == 0) ||
  374. (strcasecmp(argv[i + 1], "true") == 0) ||
  375. (strcasecmp(argv[i + 1], "false") == 0) ||
  376. (strcasecmp(argv[i + 1], "yes") == 0) ||
  377. (strcasecmp(argv[i + 1], "no") == 0)) {
  378. vncSetParam(&argv[i][1], argv[i + 1]);
  379. return 2;
  380. }
  381. }
  382. if (vncSetParamSimple(argv[i]))
  383. return 1;
  384. if (argv[i][0] == '-' && i + 1 < argc) {
  385. if (vncSetParam(&argv[i][1], argv[i + 1]))
  386. return 2;
  387. }
  388. return 0;
  389. }
  390. static Bool
  391. vncSaveScreen(ScreenPtr pScreen, int on)
  392. {
  393. return TRUE;
  394. }
  395. static void *
  396. vncAllocateFramebufferMemory(VncFramebufferInfoPtr pfb)
  397. {
  398. size_t sizeInBytes;
  399. if (pfb->pfbMemory != NULL)
  400. return pfb->pfbMemory; /* already done */
  401. /* Compute memory layout */
  402. pfb->paddedBytesWidth = PixmapBytePad(pfb->width, pfb->depth);
  403. pfb->bitsPerPixel = vncBitsPerPixel(pfb->depth);
  404. pfb->paddedWidth = pfb->paddedBytesWidth * 8 / pfb->bitsPerPixel;
  405. /* And allocate buffer */
  406. sizeInBytes = pfb->paddedBytesWidth * pfb->height;
  407. pfb->pfbMemory = malloc(sizeInBytes);
  408. /* This will be NULL if the above failed */
  409. return pfb->pfbMemory;
  410. }
  411. static void
  412. vncFreeFramebufferMemory(VncFramebufferInfoPtr pfb)
  413. {
  414. if ((pfb == NULL) || (pfb->pfbMemory == NULL))
  415. return;
  416. free(pfb->pfbMemory);
  417. pfb->pfbMemory = NULL;
  418. }
  419. static Bool
  420. vncCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
  421. {
  422. return FALSE;
  423. }
  424. static void
  425. vncCrossScreen(ScreenPtr pScreen, Bool entering)
  426. {
  427. }
  428. static Bool
  429. vncRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
  430. {
  431. return TRUE;
  432. }
  433. static Bool
  434. vncUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
  435. {
  436. return TRUE;
  437. }
  438. static void
  439. vncSetCursor(DeviceIntPtr pDev,
  440. ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
  441. {
  442. }
  443. static void
  444. vncMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
  445. {
  446. }
  447. static Bool
  448. vncDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
  449. {
  450. return TRUE;
  451. }
  452. static void
  453. vncDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
  454. {
  455. }
  456. static miPointerSpriteFuncRec vncPointerSpriteFuncs = {
  457. vncRealizeCursor,
  458. vncUnrealizeCursor,
  459. vncSetCursor,
  460. vncMoveCursor,
  461. vncDeviceCursorInitialize,
  462. vncDeviceCursorCleanup
  463. };
  464. static miPointerScreenFuncRec vncPointerCursorFuncs = {
  465. vncCursorOffScreen,
  466. vncCrossScreen,
  467. miPointerWarpCursor
  468. };
  469. static Bool
  470. vncRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
  471. {
  472. // We update all information right away, so there is nothing to
  473. // do here.
  474. return TRUE;
  475. }
  476. static Bool vncRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,
  477. int x, int y, Rotation rotation, int num_outputs,
  478. RROutputPtr * outputs);
  479. static RRModePtr vncRandRModeGet(int width, int height);
  480. static Bool
  481. vncRandRScreenSetSize(ScreenPtr pScreen,
  482. CARD16 width, CARD16 height,
  483. CARD32 mmWidth, CARD32 mmHeight)
  484. {
  485. VncFramebufferInfo fb;
  486. rrScrPrivPtr rp = rrGetScrPriv(pScreen);
  487. PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
  488. void *pbits;
  489. Bool ret;
  490. int oldwidth, oldheight, oldmmWidth, oldmmHeight;
  491. /* Prevent updates while we fiddle */
  492. SetRootClip(pScreen, ROOT_CLIP_NONE);
  493. /* Store current state in case we fail */
  494. oldwidth = pScreen->width;
  495. oldheight = pScreen->height;
  496. oldmmWidth = pScreen->mmWidth;
  497. oldmmHeight = pScreen->mmHeight;
  498. /* Then set the new dimensions */
  499. pScreen->width = width;
  500. pScreen->height = height;
  501. pScreen->mmWidth = mmWidth;
  502. pScreen->mmHeight = mmHeight;
  503. /* Allocate a new framebuffer */
  504. memset(&fb, 0, sizeof(VncFramebufferInfo));
  505. fb.width = pScreen->width;
  506. fb.height = pScreen->height;
  507. fb.depth = vncScreenInfo.fb.depth;
  508. pbits = vncAllocateFramebufferMemory(&fb);
  509. if (!pbits) {
  510. /* Allocation failed. Restore old state */
  511. pScreen->width = oldwidth;
  512. pScreen->height = oldheight;
  513. pScreen->mmWidth = oldmmWidth;
  514. pScreen->mmHeight = oldmmHeight;
  515. SetRootClip(pScreen, ROOT_CLIP_FULL);
  516. return FALSE;
  517. }
  518. /* Update root pixmap with the new dimensions and buffer */
  519. ret = pScreen->ModifyPixmapHeader(rootPixmap, fb.width, fb.height,
  520. -1, -1, fb.paddedBytesWidth, pbits);
  521. if (!ret) {
  522. /* Update failed. Free the new framebuffer and restore old state */
  523. vncFreeFramebufferMemory(&fb);
  524. pScreen->width = oldwidth;
  525. pScreen->height = oldheight;
  526. pScreen->mmWidth = oldmmWidth;
  527. pScreen->mmHeight = oldmmHeight;
  528. SetRootClip(pScreen, ROOT_CLIP_FULL);
  529. return FALSE;
  530. }
  531. /* Free the old framebuffer and keep the info about the new one */
  532. vncFreeFramebufferMemory(&vncScreenInfo.fb);
  533. vncScreenInfo.fb = fb;
  534. /* Let VNC get the new framebuffer (actual update is in vncHooks.cc) */
  535. vncFbptr[pScreen->myNum] = pbits;
  536. vncFbstride[pScreen->myNum] = fb.paddedWidth;
  537. /* Restore ability to update screen, now with new dimensions */
  538. SetRootClip(pScreen, ROOT_CLIP_FULL);
  539. /*
  540. * Let RandR know we changed something (it doesn't assume that
  541. * TRUE means something changed for some reason...).
  542. */
  543. RRScreenSizeNotify(pScreen);
  544. /* Crop all CRTCs to the new screen */
  545. for (int i = 0; i < rp->numCrtcs; i++) {
  546. RRCrtcPtr crtc;
  547. RRModePtr mode;
  548. crtc = rp->crtcs[i];
  549. /* Disabled? */
  550. if (crtc->mode == NULL)
  551. continue;
  552. /* Fully inside? */
  553. if ((crtc->x + crtc->mode->mode.width <= width) &&
  554. (crtc->y + crtc->mode->mode.height <= height))
  555. continue;
  556. /* Fully outside? */
  557. if ((crtc->x >= width) || (crtc->y >= height)) {
  558. /* Disable it */
  559. ret = vncRandRCrtcSet(pScreen, crtc, NULL,
  560. crtc->x, crtc->y, crtc->rotation, 0, NULL);
  561. if (!ret)
  562. ErrorF("Warning: Unable to disable CRTC that is outside of new screen dimensions");
  563. continue;
  564. }
  565. /* Just needs to be resized to a temporary mode */
  566. mode = vncRandRModeGet(width - crtc->x, height - crtc->y);
  567. if (mode == NULL) {
  568. ErrorF("Warning: Unable to create custom mode for %dx%d",
  569. width - crtc->x, height - crtc->y);
  570. continue;
  571. }
  572. ret = vncRandRCrtcSet(pScreen, crtc, mode,
  573. crtc->x, crtc->y, crtc->rotation,
  574. crtc->numOutputs, crtc->outputs);
  575. RRModeDestroy(mode);
  576. if (!ret)
  577. ErrorF("Warning: Unable to crop CRTC to new screen dimensions");
  578. }
  579. return TRUE;
  580. }
  581. static Bool
  582. vncRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,
  583. int x, int y, Rotation rotation, int num_outputs,
  584. RROutputPtr * outputs)
  585. {
  586. Bool ret;
  587. int i;
  588. /*
  589. * Some applications get confused by a connected output without a
  590. * mode or CRTC, so we need to fiddle with the connection state as well.
  591. */
  592. for (i = 0; i < crtc->numOutputs; i++)
  593. RROutputSetConnection(crtc->outputs[i], RR_Disconnected);
  594. for (i = 0; i < num_outputs; i++) {
  595. if (mode != NULL)
  596. RROutputSetConnection(outputs[i], RR_Connected);
  597. else
  598. RROutputSetConnection(outputs[i], RR_Disconnected);
  599. }
  600. /* Let RandR know we approve, and let it update its internal state */
  601. ret = RRCrtcNotify(crtc, mode, x, y, rotation, NULL, num_outputs, outputs);
  602. if (!ret)
  603. return FALSE;
  604. return TRUE;
  605. }
  606. static Bool
  607. vncRandROutputValidateMode(ScreenPtr pScreen,
  608. RROutputPtr output, RRModePtr mode)
  609. {
  610. /* We have no hardware so any mode works */
  611. return TRUE;
  612. }
  613. static void
  614. vncRandRModeDestroy(ScreenPtr pScreen, RRModePtr mode)
  615. {
  616. /* We haven't allocated anything so nothing to destroy */
  617. }
  618. static const int vncRandRWidths[] =
  619. { 1920, 1920, 1600, 1680, 1400, 1360, 1280, 1280, 1280, 1280, 1024, 800, 640 };
  620. static const int vncRandRHeights[] =
  621. { 1200, 1080, 1200, 1050, 1050, 768, 1024, 960, 800, 720, 768, 600, 480 };
  622. static int vncRandRIndex = 0;
  623. static RRModePtr
  624. vncRandRModeGet(int width, int height)
  625. {
  626. xRRModeInfo modeInfo;
  627. char name[100];
  628. RRModePtr mode;
  629. memset(&modeInfo, 0, sizeof(modeInfo));
  630. sprintf(name, "%dx%d", width, height);
  631. modeInfo.width = width;
  632. modeInfo.height = height;
  633. modeInfo.hTotal = width;
  634. modeInfo.vTotal = height;
  635. modeInfo.dotClock = ((CARD32) width * (CARD32) height * 60);
  636. modeInfo.nameLength = strlen(name);
  637. mode = RRModeGet(&modeInfo, name);
  638. if (mode == NULL)
  639. return NULL;
  640. return mode;
  641. }
  642. static void
  643. vncRandRSetModes(RROutputPtr output, int pref_width, int pref_height)
  644. {
  645. RRModePtr mode;
  646. RRModePtr *modes;
  647. int i, num_modes, num_pref;
  648. num_modes = sizeof(vncRandRWidths) / sizeof(*vncRandRWidths) + 1;
  649. modes = malloc(sizeof(RRModePtr) * num_modes);
  650. if (modes == NULL)
  651. return;
  652. num_modes = 0;
  653. num_pref = 0;
  654. if ((pref_width > 0) && (pref_height > 0)) {
  655. mode = vncRandRModeGet(pref_width, pref_height);
  656. if (mode != NULL) {
  657. modes[num_modes] = mode;
  658. num_modes++;
  659. num_pref++;
  660. }
  661. }
  662. for (i = 0; i < sizeof(vncRandRWidths) / sizeof(*vncRandRWidths); i++) {
  663. if ((vncRandRWidths[i] == pref_width) &&
  664. (vncRandRHeights[i] == pref_height))
  665. continue;
  666. mode = vncRandRModeGet(vncRandRWidths[i], vncRandRHeights[i]);
  667. if (mode != NULL) {
  668. modes[num_modes] = mode;
  669. num_modes++;
  670. }
  671. }
  672. RROutputSetModes(output, modes, num_modes, num_pref);
  673. free(modes);
  674. }
  675. static RRCrtcPtr
  676. vncRandRCrtcCreate(ScreenPtr pScreen)
  677. {
  678. RRCrtcPtr crtc;
  679. RROutputPtr output;
  680. char name[100];
  681. /* First we create the CRTC... */
  682. crtc = RRCrtcCreate(pScreen, NULL);
  683. /* We don't actually support gamma, but xrandr complains when it is missing */
  684. RRCrtcGammaSetSize(crtc, 256);
  685. /* Then we create a dummy output for it... */
  686. sprintf(name, "VNC-%d", vncRandRIndex);
  687. vncRandRIndex++;
  688. output = RROutputCreate(pScreen, name, strlen(name), NULL);
  689. RROutputSetCrtcs(output, &crtc, 1);
  690. RROutputSetConnection(output, RR_Disconnected);
  691. /* Make sure the CRTC has this output set */
  692. vncRandRCrtcSet(pScreen, crtc, NULL, 0, 0, RR_Rotate_0, 1, &output);
  693. /* Populate a list of default modes */
  694. vncRandRSetModes(output, -1, -1);
  695. return crtc;
  696. }
  697. /* Used from XserverDesktop when it needs more outputs... */
  698. int
  699. vncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs)
  700. {
  701. return 1;
  702. }
  703. int
  704. vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs)
  705. {
  706. RRCrtcPtr crtc;
  707. while (extraOutputs > 0) {
  708. crtc = vncRandRCrtcCreate(screenInfo.screens[scrIdx]);
  709. if (crtc == NULL)
  710. return 0;
  711. extraOutputs--;
  712. }
  713. return 1;
  714. }
  715. /* Creating and modifying modes, used by XserverDesktop and init here */
  716. int
  717. vncRandRCanCreateModes()
  718. {
  719. return 1;
  720. }
  721. void *
  722. vncRandRCreateMode(void *out, int width, int height)
  723. {
  724. RROutputPtr output;
  725. output = out;
  726. /* Do we already have the mode? */
  727. for (int i = 0; i < output->numModes; i++) {
  728. if ((output->modes[i]->mode.width == width) &&
  729. (output->modes[i]->mode.height == height))
  730. return output->modes[i];
  731. }
  732. /* Just recreate the entire list */
  733. vncRandRSetModes(output, width, height);
  734. /* Find the new mode */
  735. for (int i = 0; i < output->numModes; i++) {
  736. if ((output->modes[i]->mode.width == width) &&
  737. (output->modes[i]->mode.height == height))
  738. return output->modes[i];
  739. }
  740. /* Something went horribly wrong */
  741. return NULL;
  742. }
  743. void *
  744. vncRandRSetPreferredMode(void *out, void *m)
  745. {
  746. RRModePtr mode;
  747. RROutputPtr output;
  748. int width, height;
  749. mode = m;
  750. output = out;
  751. width = mode->mode.width;
  752. height = mode->mode.height;
  753. /* Already the preferred mode? */
  754. if ((output->numModes >= 1) && (output->numPreferred == 1) &&
  755. (output->modes[0] == mode))
  756. return mode;
  757. /* Recreate the list, with the mode we want as preferred */
  758. vncRandRSetModes(output, width, height);
  759. /* Sanity check */
  760. if ((output->numModes >= 1) && (output->numPreferred == 1) &&
  761. (output->modes[0]->mode.width == width) &&
  762. (output->modes[0]->mode.height == height))
  763. return output->modes[0];
  764. /* Something went horribly wrong */
  765. return NULL;
  766. }
  767. static Bool
  768. vncRandRInit(ScreenPtr pScreen)
  769. {
  770. rrScrPrivPtr pScrPriv;
  771. RRCrtcPtr crtc;
  772. RRModePtr mode;
  773. Bool ret;
  774. if (!RRScreenInit(pScreen))
  775. return FALSE;
  776. pScrPriv = rrGetScrPriv(pScreen);
  777. pScrPriv->rrGetInfo = vncRandRGetInfo;
  778. pScrPriv->rrSetConfig = NULL;
  779. pScrPriv->rrScreenSetSize = vncRandRScreenSetSize;
  780. pScrPriv->rrCrtcSet = vncRandRCrtcSet;
  781. pScrPriv->rrOutputValidateMode = vncRandROutputValidateMode;
  782. pScrPriv->rrModeDestroy = vncRandRModeDestroy;
  783. /* These are completely arbitrary */
  784. RRScreenSetSizeRange(pScreen, 32, 32, 32768, 32768);
  785. /*
  786. * Start with a single CRTC with a single output. More will be
  787. * allocated as needed...
  788. */
  789. crtc = vncRandRCrtcCreate(pScreen);
  790. /* Make sure the current screen size is the active mode */
  791. mode = vncRandRCreateMode(crtc->outputs[0],
  792. pScreen->width, pScreen->height);
  793. if (mode == NULL)
  794. return FALSE;
  795. mode = vncRandRSetPreferredMode(crtc->outputs[0], mode);
  796. if (mode == NULL)
  797. return FALSE;
  798. ret = vncRandRCrtcSet(pScreen, crtc, mode, 0, 0, RR_Rotate_0,
  799. crtc->numOutputs, crtc->outputs);
  800. if (!ret)
  801. return FALSE;
  802. return TRUE;
  803. }
  804. static Bool
  805. vncScreenInit(ScreenPtr pScreen, int argc, char **argv)
  806. {
  807. int dpi;
  808. int ret;
  809. void *pbits;
  810. /* 96 is the default used by most other systems */
  811. dpi = 96;
  812. if (monitorResolution)
  813. dpi = monitorResolution;
  814. pbits = vncAllocateFramebufferMemory(&vncScreenInfo.fb);
  815. if (!pbits)
  816. return FALSE;
  817. vncFbptr[0] = pbits;
  818. vncFbstride[0] = vncScreenInfo.fb.paddedWidth;
  819. miSetPixmapDepths();
  820. switch (vncScreenInfo.fb.depth) {
  821. case 16:
  822. miSetVisualTypesAndMasks(16,
  823. ((1 << TrueColor) |
  824. (1 << DirectColor)),
  825. 8, TrueColor, 0xf800, 0x07e0, 0x001f);
  826. break;
  827. case 24:
  828. miSetVisualTypesAndMasks(24,
  829. ((1 << TrueColor) |
  830. (1 << DirectColor)),
  831. 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);
  832. break;
  833. case 32:
  834. miSetVisualTypesAndMasks(32,
  835. ((1 << TrueColor) |
  836. (1 << DirectColor)),
  837. 8, TrueColor, 0xff000000, 0x00ff0000,
  838. 0x0000ff00);
  839. break;
  840. default:
  841. return FALSE;
  842. }
  843. ret = fbScreenInit(pScreen, pbits,
  844. vncScreenInfo.fb.width, vncScreenInfo.fb.height,
  845. dpi, dpi, vncScreenInfo.fb.paddedWidth,
  846. vncScreenInfo.fb.bitsPerPixel);
  847. if (ret && Render)
  848. ret = fbPictureInit(pScreen, 0, 0);
  849. if (!ret)
  850. return FALSE;
  851. ret = vncRandRInit(pScreen);
  852. if (!ret)
  853. return FALSE;
  854. pScreen->SaveScreen = vncSaveScreen;
  855. miPointerInitialize(pScreen, &vncPointerSpriteFuncs, &vncPointerCursorFuncs,
  856. FALSE);
  857. if (!vncScreenInfo.pixelFormatDefined) {
  858. switch (vncScreenInfo.fb.depth) {
  859. case 16:
  860. vncScreenInfo.pixelFormatDefined = TRUE;
  861. vncScreenInfo.rgbNotBgr = TRUE;
  862. vncScreenInfo.blueBits = vncScreenInfo.redBits = 5;
  863. vncScreenInfo.greenBits = 6;
  864. break;
  865. case 24:
  866. case 32:
  867. vncScreenInfo.pixelFormatDefined = TRUE;
  868. vncScreenInfo.rgbNotBgr = TRUE;
  869. vncScreenInfo.blueBits = vncScreenInfo.redBits = vncScreenInfo.greenBits = 8;
  870. break;
  871. }
  872. }
  873. if (vncScreenInfo.pixelFormatDefined) {
  874. VisualPtr vis = pScreen->visuals;
  875. for (int i = 0; i < pScreen->numVisuals; i++) {
  876. if (vncScreenInfo.rgbNotBgr) {
  877. vis->offsetBlue = 0;
  878. vis->blueMask = (1 << vncScreenInfo.blueBits) - 1;
  879. vis->offsetGreen = vncScreenInfo.blueBits;
  880. vis->greenMask =
  881. ((1 << vncScreenInfo.greenBits) - 1) << vis->offsetGreen;
  882. vis->offsetRed = vis->offsetGreen + vncScreenInfo.greenBits;
  883. vis->redMask = ((1 << vncScreenInfo.redBits) - 1) << vis->offsetRed;
  884. }
  885. else {
  886. vis->offsetRed = 0;
  887. vis->redMask = (1 << vncScreenInfo.redBits) - 1;
  888. vis->offsetGreen = vncScreenInfo.redBits;
  889. vis->greenMask =
  890. ((1 << vncScreenInfo.greenBits) - 1) << vis->offsetGreen;
  891. vis->offsetBlue = vis->offsetGreen + vncScreenInfo.greenBits;
  892. vis->blueMask = ((1 << vncScreenInfo.blueBits) - 1) << vis->offsetBlue;
  893. }
  894. vis++;
  895. }
  896. }
  897. ret = fbCreateDefColormap(pScreen);
  898. if (!ret)
  899. return FALSE;
  900. return TRUE;
  901. } /* end vncScreenInit */
  902. static void
  903. vncClientStateChange(CallbackListPtr *a, void *b, void *c)
  904. {
  905. if (dispatchException & DE_RESET) {
  906. ErrorF("Warning: VNC extension does not support -reset, terminating instead. Use -noreset to prevent termination.\n");
  907. dispatchException |= DE_TERMINATE;
  908. dispatchException &= ~DE_RESET;
  909. }
  910. }
  911. #ifdef GLXEXT
  912. #if XORG_OLDER_THAN(1, 20, 0)
  913. extern void GlxExtensionInit(void);
  914. static ExtensionModule glxExt = {
  915. GlxExtensionInit,
  916. "GLX",
  917. &noGlxExtension
  918. };
  919. #endif
  920. #endif
  921. void
  922. InitOutput(ScreenInfo * scrInfo, int argc, char **argv)
  923. {
  924. int i;
  925. int NumFormats = 0;
  926. vncPrintBanner();
  927. #if XORG_AT_LEAST(1, 20, 0)
  928. xorgGlxCreateVendor();
  929. #else
  930. #ifdef GLXEXT
  931. if (serverGeneration == 1)
  932. LoadExtensionList(&glxExt, 1, TRUE);
  933. #endif
  934. #endif
  935. /* initialize pixmap formats */
  936. /* must have a pixmap depth to match every screen depth */
  937. vncPixmapDepths[vncScreenInfo.fb.depth] = TRUE;
  938. /* RENDER needs a good set of pixmaps. */
  939. if (Render) {
  940. vncPixmapDepths[1] = TRUE;
  941. vncPixmapDepths[4] = TRUE;
  942. vncPixmapDepths[8] = TRUE;
  943. /* vncPixmapDepths[15] = TRUE; */
  944. vncPixmapDepths[16] = TRUE;
  945. vncPixmapDepths[24] = TRUE;
  946. vncPixmapDepths[32] = TRUE;
  947. }
  948. for (i = 1; i <= 32; i++) {
  949. if (vncPixmapDepths[i]) {
  950. if (NumFormats >= MAXFORMATS)
  951. FatalError("MAXFORMATS is too small for this server\n");
  952. scrInfo->formats[NumFormats].depth = i;
  953. scrInfo->formats[NumFormats].bitsPerPixel = vncBitsPerPixel(i);
  954. scrInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
  955. NumFormats++;
  956. }
  957. }
  958. scrInfo->imageByteOrder = IMAGE_BYTE_ORDER;
  959. scrInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
  960. scrInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
  961. scrInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
  962. scrInfo->numPixmapFormats = NumFormats;
  963. /* initialize screen */
  964. if (AddScreen(vncScreenInit, argc, argv) == -1) {
  965. FatalError("Couldn't add screen\n");
  966. }
  967. if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
  968. FatalError("AddCallback failed\n");
  969. }
  970. } /* end InitOutput */
  971. void
  972. DDXRingBell(int percent, int pitch, int duration)
  973. {
  974. if (percent > 0)
  975. vncBell();
  976. }
  977. Bool
  978. LegalModifier(unsigned int key, DeviceIntPtr pDev)
  979. {
  980. return TRUE;
  981. }
  982. void
  983. ProcessInputEvents(void)
  984. {
  985. mieqProcessInputEvents();
  986. }
  987. void
  988. InitInput(int argc, char *argv[])
  989. {
  990. mieqInit();
  991. }
  992. void
  993. CloseInput(void)
  994. {
  995. }
  996. void
  997. vncClientGone(int fd)
  998. {
  999. if (fd == vncInetdSock) {
  1000. ErrorF("inetdSock client gone\n");
  1001. GiveUp(0);
  1002. }
  1003. }