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.

XserverDesktop.cc 42KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. /* Copyright (C) 2002-2005 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. // XserverDesktop.cxx
  20. //
  21. #ifdef HAVE_DIX_CONFIG_H
  22. #include <dix-config.h>
  23. #endif
  24. #include <assert.h>
  25. #include <stdio.h>
  26. #include <strings.h>
  27. #include <unistd.h>
  28. #include <pwd.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <fcntl.h>
  32. #include <sys/utsname.h>
  33. #include <network/TcpSocket.h>
  34. #include <rfb/Exception.h>
  35. #include <rfb/VNCServerST.h>
  36. #include <rfb/HTTPServer.h>
  37. #include <rfb/LogWriter.h>
  38. #include <rfb/Configuration.h>
  39. #include "XserverDesktop.h"
  40. #include "vncExtInit.h"
  41. extern "C" {
  42. #define public c_public
  43. #define class c_class
  44. extern char *display;
  45. #include "inputstr.h"
  46. #include "servermd.h"
  47. #include "colormapst.h"
  48. #include "resource.h"
  49. #include "cursorstr.h"
  50. #include "windowstr.h"
  51. #include "mi.h"
  52. #define XK_CYRILLIC
  53. #include <X11/keysym.h>
  54. #undef public
  55. #undef class
  56. }
  57. static DeviceIntPtr vncKeyboardDevice = NULL;
  58. static DeviceIntPtr vncPointerDevice = NULL;
  59. #ifdef XORG_15
  60. static xEvent *eventq = NULL;
  61. #else
  62. static EventList *eventq = NULL;
  63. #endif
  64. static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
  65. static int vfbMouseProc(DeviceIntPtr pDevice, int onoff);
  66. using namespace rfb;
  67. using namespace network;
  68. static LogWriter vlog("XserverDesktop");
  69. rfb::IntParameter deferUpdateTime("DeferUpdate",
  70. "Time in milliseconds to defer updates",40);
  71. rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
  72. "Always reset the defer update timer on every change",false);
  73. IntParameter queryConnectTimeout("QueryConnectTimeout",
  74. "Number of seconds to show the Accept Connection dialog before "
  75. "rejecting the connection",
  76. 10);
  77. static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
  78. static rdr::U8 reverseBits[] = {
  79. 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
  80. 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  81. 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
  82. 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  83. 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
  84. 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  85. 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
  86. 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  87. 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
  88. 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  89. 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
  90. 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  91. 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
  92. 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  93. 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
  94. 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  95. 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
  96. 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  97. 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
  98. 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  99. 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
  100. 0x3f, 0xbf, 0x7f, 0xff
  101. };
  102. class FileHTTPServer : public rfb::HTTPServer {
  103. public:
  104. FileHTTPServer(XserverDesktop* d) : desktop(d) {}
  105. virtual ~FileHTTPServer() {}
  106. virtual rdr::InStream* getFile(const char* name, const char** contentType,
  107. int* contentLength, time_t* lastModified)
  108. {
  109. if (name[0] != '/' || strstr(name, "..") != 0) {
  110. vlog.info("http request was for invalid file name");
  111. return 0;
  112. }
  113. if (strcmp(name, "/") == 0) name = "/index.vnc";
  114. CharArray httpDirStr(httpDir.getData());
  115. CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
  116. sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
  117. int fd = open(fname.buf, O_RDONLY);
  118. if (fd < 0) return 0;
  119. rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
  120. *contentType = guessContentType(name, *contentType);
  121. if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
  122. is = new rdr::SubstitutingInStream(is, desktop, 20);
  123. *contentType = "text/html";
  124. } else {
  125. struct stat st;
  126. if (fstat(fd, &st) == 0) {
  127. *contentLength = st.st_size;
  128. *lastModified = st.st_mtime;
  129. }
  130. }
  131. return is;
  132. }
  133. XserverDesktop* desktop;
  134. };
  135. XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
  136. network::TcpListener* listener_,
  137. network::TcpListener* httpListener_,
  138. const char* name, void* fbptr)
  139. : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0),
  140. server(0), httpServer(0),
  141. listener(listener_), httpListener(httpListener_),
  142. cmap(0), deferredUpdateTimerSet(false),
  143. grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
  144. oldButtonMask(0),
  145. queryConnectId(0)
  146. {
  147. int i;
  148. format.depth = pScreen->rootDepth;
  149. for (i = 0; i < screenInfo.numPixmapFormats; i++) {
  150. if (screenInfo.formats[i].depth == format.depth) {
  151. format.bpp = screenInfo.formats[i].bitsPerPixel;
  152. break;
  153. }
  154. }
  155. if (i == screenInfo.numPixmapFormats) {
  156. fprintf(stderr,"no pixmap format for root depth???\n");
  157. abort();
  158. }
  159. format.bigEndian = (screenInfo.imageByteOrder == MSBFirst);
  160. VisualPtr vis;
  161. for (i = 0; i < pScreen->numVisuals; i++) {
  162. if (pScreen->visuals[i].vid == pScreen->rootVisual) {
  163. vis = &pScreen->visuals[i];
  164. break;
  165. }
  166. }
  167. if (i == pScreen->numVisuals) {
  168. fprintf(stderr,"no visual rec for root visual???\n");
  169. abort();
  170. }
  171. format.trueColour = (vis->c_class == TrueColor);
  172. if (!format.trueColour && format.bpp != 8)
  173. throw rfb::Exception("X server uses unsupported visual");
  174. format.redShift = ffs(vis->redMask) - 1;
  175. format.greenShift = ffs(vis->greenMask) - 1;
  176. format.blueShift = ffs(vis->blueMask) - 1;
  177. format.redMax = vis->redMask >> format.redShift;
  178. format.greenMax = vis->greenMask >> format.greenShift;
  179. format.blueMax = vis->blueMask >> format.blueShift;
  180. width_ = pScreen->width;
  181. height_ = pScreen->height;
  182. if (fbptr)
  183. data = (rdr::U8*)fbptr;
  184. else
  185. data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)];
  186. colourmap = this;
  187. serverReset(pScreen);
  188. server = new VNCServerST(name, this);
  189. server->setPixelBuffer(this);
  190. server->setQueryConnectionHandler(this);
  191. if (httpListener)
  192. httpServer = new FileHTTPServer(this);
  193. #ifdef XORG_15
  194. /*
  195. * XXX eventq is never free()-ed because it has to exist during server life
  196. * */
  197. if (!eventq)
  198. eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
  199. if (!eventq)
  200. FatalError("Couldn't allocate eventq\n");
  201. #endif
  202. if (vncKeyboardDevice == NULL) {
  203. vncKeyboardDevice = AddInputDevice(
  204. #ifdef XORG_16
  205. serverClient,
  206. #endif
  207. vfbKeybdProc, TRUE);
  208. RegisterKeyboardDevice(vncKeyboardDevice);
  209. }
  210. if (vncPointerDevice == NULL) {
  211. vncPointerDevice = AddInputDevice(
  212. #ifdef XORG_16
  213. serverClient,
  214. #endif
  215. vfbMouseProc, TRUE);
  216. RegisterPointerDevice(vncPointerDevice);
  217. }
  218. }
  219. XserverDesktop::~XserverDesktop()
  220. {
  221. if (!directFbptr)
  222. delete [] data;
  223. TimerFree(deferredUpdateTimer);
  224. TimerFree(dummyTimer);
  225. delete httpServer;
  226. delete server;
  227. }
  228. void XserverDesktop::serverReset(ScreenPtr pScreen_)
  229. {
  230. pScreen = pScreen_;
  231. int i;
  232. pointer retval;
  233. i = dixLookupResource(&retval, pScreen->defColormap, RT_COLORMAP, NullClient,
  234. DixReadAccess);
  235. /* Handle suspicious conditions */
  236. assert(i == Success);
  237. cmap = (ColormapPtr) retval;
  238. }
  239. char* XserverDesktop::substitute(const char* varName)
  240. {
  241. if (strcmp(varName, "$$") == 0) {
  242. return rfb::strDup("$");
  243. }
  244. if (strcmp(varName, "$PORT") == 0) {
  245. char* str = new char[10];
  246. sprintf(str, "%d", listener ? listener->getMyPort() : 0);
  247. return str;
  248. }
  249. if (strcmp(varName, "$WIDTH") == 0) {
  250. char* str = new char[10];
  251. sprintf(str, "%d", width());
  252. return str;
  253. }
  254. if (strcmp(varName, "$HEIGHT") == 0) {
  255. char* str = new char[10];
  256. sprintf(str, "%d", height());
  257. return str;
  258. }
  259. if (strcmp(varName, "$APPLETWIDTH") == 0) {
  260. char* str = new char[10];
  261. sprintf(str, "%d", width());
  262. return str;
  263. }
  264. if (strcmp(varName, "$APPLETHEIGHT") == 0) {
  265. char* str = new char[10];
  266. sprintf(str, "%d", height() + 32);
  267. return str;
  268. }
  269. if (strcmp(varName, "$DESKTOP") == 0) {
  270. return rfb::strDup(server->getName());
  271. }
  272. if (strcmp(varName, "$DISPLAY") == 0) {
  273. struct utsname uts;
  274. uname(&uts);
  275. char* str = new char[256];
  276. strncat(str, uts.nodename, 240);
  277. strcat(str, ":");
  278. strncat(str, display, 10);
  279. return str;
  280. }
  281. if (strcmp(varName, "$USER") == 0) {
  282. struct passwd* user = getpwuid(getuid());
  283. return rfb::strDup(user ? user->pw_name : "?");
  284. }
  285. return 0;
  286. }
  287. rfb::VNCServerST::queryResult
  288. XserverDesktop::queryConnection(network::Socket* sock,
  289. const char* userName,
  290. char** reason) {
  291. if (queryConnectId) {
  292. *reason = strDup("Another connection is currently being queried.");
  293. return rfb::VNCServerST::REJECT;
  294. }
  295. queryConnectAddress.replaceBuf(sock->getPeerAddress());
  296. if (!userName)
  297. userName = "(anonymous)";
  298. queryConnectUsername.replaceBuf(strDup(userName));
  299. queryConnectId = sock;
  300. vncQueryConnect(this, sock);
  301. return rfb::VNCServerST::PENDING;
  302. }
  303. void XserverDesktop::setColormap(ColormapPtr cmap_)
  304. {
  305. if (cmap != cmap_) {
  306. cmap = cmap_;
  307. setColourMapEntries(0, 0);
  308. }
  309. }
  310. void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
  311. xColorItem* pdef)
  312. {
  313. if (cmap != pColormap || ndef <= 0) return;
  314. int first = pdef[0].pixel;
  315. int n = 1;
  316. for (int i = 1; i < ndef; i++) {
  317. if (first + n == pdef[i].pixel) {
  318. n++;
  319. } else {
  320. setColourMapEntries(first, n);
  321. first = pdef[i].pixel;
  322. n = 1;
  323. }
  324. }
  325. setColourMapEntries(first, n);
  326. }
  327. void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
  328. {
  329. try {
  330. server->setColourMapEntries(firstColour, nColours);
  331. } catch (rdr::Exception& e) {
  332. vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
  333. }
  334. }
  335. void XserverDesktop::bell()
  336. {
  337. server->bell();
  338. }
  339. void XserverDesktop::serverCutText(const char* str, int len)
  340. {
  341. try {
  342. server->serverCutText(str, len);
  343. } catch (rdr::Exception& e) {
  344. vlog.error("XserverDesktop::serverCutText: %s",e.str());
  345. }
  346. }
  347. void XserverDesktop::setDesktopName(const char* name)
  348. {
  349. try {
  350. server->setName(name);
  351. } catch (rdr::Exception& e) {
  352. vlog.error("XserverDesktop::setDesktopName: %s",e.str());
  353. }
  354. }
  355. void XserverDesktop::setCursor(CursorPtr cursor)
  356. {
  357. try {
  358. int w = cursor->bits->width;
  359. int h = cursor->bits->height;
  360. rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)];
  361. xColorItem fg, bg;
  362. fg.red = cursor->foreRed;
  363. fg.green = cursor->foreGreen;
  364. fg.blue = cursor->foreBlue;
  365. FakeAllocColor(cmap, &fg);
  366. bg.red = cursor->backRed;
  367. bg.green = cursor->backGreen;
  368. bg.blue = cursor->backBlue;
  369. FakeAllocColor(cmap, &bg);
  370. FakeFreeColor(cmap, fg.pixel);
  371. FakeFreeColor(cmap, bg.pixel);
  372. int xMaskBytesPerRow = BitmapBytePad(w);
  373. for (int y = 0; y < h; y++) {
  374. for (int x = 0; x < w; x++) {
  375. int byte = y * xMaskBytesPerRow + x / 8;
  376. #if (BITMAP_BIT_ORDER == MSBFirst)
  377. int bit = 7 - x % 8;
  378. #else
  379. int bit = x % 8;
  380. #endif
  381. switch (getPF().bpp) {
  382. case 8:
  383. ((rdr::U8*)cursorData)[y * w + x]
  384. = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
  385. break;
  386. case 16:
  387. ((rdr::U16*)cursorData)[y * w + x]
  388. = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
  389. break;
  390. case 32:
  391. ((rdr::U32*)cursorData)[y * w + x]
  392. = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
  393. break;
  394. }
  395. }
  396. }
  397. int rfbMaskBytesPerRow = (w + 7) / 8;
  398. rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h];
  399. for (int j = 0; j < h; j++) {
  400. for (int i = 0; i < rfbMaskBytesPerRow; i++)
  401. #if (BITMAP_BIT_ORDER == MSBFirst)
  402. cursorMask[j * rfbMaskBytesPerRow + i]
  403. = cursor->bits->mask[j * xMaskBytesPerRow + i];
  404. #else
  405. cursorMask[j * rfbMaskBytesPerRow + i]
  406. = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]];
  407. #endif
  408. }
  409. server->setCursor(cursor->bits->width, cursor->bits->height,
  410. Point(cursor->bits->xhot, cursor->bits->yhot),
  411. cursorData, cursorMask);
  412. server->tryUpdate();
  413. delete [] cursorData;
  414. delete [] cursorMask;
  415. } catch (rdr::Exception& e) {
  416. vlog.error("XserverDesktop::setCursor: %s",e.str());
  417. }
  418. }
  419. static void printRegion(RegionPtr reg)
  420. {
  421. int nrects = REGION_NUM_RECTS(reg);
  422. fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects,
  423. (REGION_EXTENTS(pScreen,reg))->x1,
  424. (REGION_EXTENTS(pScreen,reg))->y1,
  425. (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1,
  426. (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1);
  427. for (int i = 0; i < nrects; i++) {
  428. fprintf(stderr," rect %3d,%3d %3dx%3d\n",
  429. REGION_RECTS(reg)[i].x1,
  430. REGION_RECTS(reg)[i].y1,
  431. REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1,
  432. REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1);
  433. }
  434. }
  435. CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
  436. CARD32 now, pointer arg)
  437. {
  438. XserverDesktop* desktop = (XserverDesktop*)arg;
  439. desktop->deferredUpdateTimerSet = false;
  440. try {
  441. desktop->server->tryUpdate();
  442. } catch (rdr::Exception& e) {
  443. vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
  444. }
  445. return 0;
  446. }
  447. void XserverDesktop::deferUpdate()
  448. {
  449. if (deferUpdateTime != 0) {
  450. if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
  451. deferredUpdateTimerSet = true;
  452. deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
  453. deferUpdateTime,
  454. deferredUpdateTimerCallback, this);
  455. }
  456. } else {
  457. server->tryUpdate();
  458. }
  459. }
  460. void XserverDesktop::add_changed(RegionPtr reg)
  461. {
  462. if (ignoreHooks_) return;
  463. if (grabbing) return;
  464. try {
  465. rfb::Region rfbReg;
  466. rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg),
  467. REGION_NUM_RECTS(reg),
  468. (ShortRect*)REGION_RECTS(reg));
  469. server->add_changed(rfbReg);
  470. deferUpdate();
  471. } catch (rdr::Exception& e) {
  472. vlog.error("XserverDesktop::add_changed: %s",e.str());
  473. }
  474. }
  475. void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
  476. {
  477. if (ignoreHooks_) return;
  478. if (grabbing) return;
  479. try {
  480. rfb::Region rfbReg;
  481. rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst),
  482. REGION_NUM_RECTS(dst),
  483. (ShortRect*)REGION_RECTS(dst));
  484. server->add_copied(rfbReg, rfb::Point(dx, dy));
  485. deferUpdate();
  486. } catch (rdr::Exception& e) {
  487. vlog.error("XserverDesktop::add_copied: %s",e.str());
  488. }
  489. }
  490. void XserverDesktop::positionCursor()
  491. {
  492. if (!cursorPos.equals(oldCursorPos)) {
  493. oldCursorPos = cursorPos;
  494. (*pScreen->SetCursorPosition) (
  495. #ifdef XORG_16
  496. vncPointerDevice,
  497. #endif
  498. pScreen, cursorPos.x, cursorPos.y, FALSE);
  499. server->setCursorPos(cursorPos);
  500. server->tryUpdate();
  501. }
  502. }
  503. void XserverDesktop::blockHandler(fd_set* fds)
  504. {
  505. try {
  506. #ifdef XORG_15
  507. ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
  508. #else
  509. ScreenPtr screenWithCursor =
  510. GetCurrentRootWindow(vncPointerDevice)->drawable.pScreen;
  511. #endif
  512. if (screenWithCursor == pScreen) {
  513. int x, y;
  514. GetSpritePosition(
  515. #ifdef XORG_16
  516. vncPointerDevice,
  517. #endif
  518. &x, &y);
  519. if (x != cursorPos.x || y != cursorPos.y) {
  520. cursorPos = oldCursorPos = Point(x, y);
  521. server->setCursorPos(cursorPos);
  522. server->tryUpdate();
  523. }
  524. }
  525. if (listener)
  526. FD_SET(listener->getFd(), fds);
  527. if (httpListener)
  528. FD_SET(httpListener->getFd(), fds);
  529. std::list<Socket*> sockets;
  530. server->getSockets(&sockets);
  531. std::list<Socket*>::iterator i;
  532. for (i = sockets.begin(); i != sockets.end(); i++) {
  533. int fd = (*i)->getFd();
  534. if ((*i)->isShutdown()) {
  535. vlog.debug("client gone, sock %d",fd);
  536. server->removeSocket(*i);
  537. vncClientGone(fd);
  538. delete (*i);
  539. } else {
  540. FD_SET(fd, fds);
  541. }
  542. }
  543. if (httpServer) {
  544. httpServer->getSockets(&sockets);
  545. for (i = sockets.begin(); i != sockets.end(); i++) {
  546. int fd = (*i)->getFd();
  547. if ((*i)->isShutdown()) {
  548. vlog.debug("http client gone, sock %d",fd);
  549. httpServer->removeSocket(*i);
  550. delete (*i);
  551. } else {
  552. FD_SET(fd, fds);
  553. }
  554. }
  555. }
  556. } catch (rdr::Exception& e) {
  557. vlog.error("XserverDesktop::blockHandler: %s",e.str());
  558. }
  559. }
  560. static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) {
  561. return 0;
  562. }
  563. void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
  564. {
  565. try {
  566. if (nfds >= 1) {
  567. if (listener) {
  568. if (FD_ISSET(listener->getFd(), fds)) {
  569. FD_CLR(listener->getFd(), fds);
  570. Socket* sock = listener->accept();
  571. server->addSocket(sock);
  572. vlog.debug("new client, sock %d",sock->getFd());
  573. }
  574. }
  575. if (httpListener) {
  576. if (FD_ISSET(httpListener->getFd(), fds)) {
  577. FD_CLR(httpListener->getFd(), fds);
  578. Socket* sock = httpListener->accept();
  579. httpServer->addSocket(sock);
  580. vlog.debug("new http client, sock %d",sock->getFd());
  581. }
  582. }
  583. std::list<Socket*> sockets;
  584. server->getSockets(&sockets);
  585. std::list<Socket*>::iterator i;
  586. for (i = sockets.begin(); i != sockets.end(); i++) {
  587. int fd = (*i)->getFd();
  588. if (FD_ISSET(fd, fds)) {
  589. FD_CLR(fd, fds);
  590. server->processSocketEvent(*i);
  591. }
  592. }
  593. if (httpServer) {
  594. httpServer->getSockets(&sockets);
  595. for (i = sockets.begin(); i != sockets.end(); i++) {
  596. int fd = (*i)->getFd();
  597. if (FD_ISSET(fd, fds)) {
  598. FD_CLR(fd, fds);
  599. httpServer->processSocketEvent(*i);
  600. }
  601. }
  602. }
  603. positionCursor();
  604. }
  605. int timeout = server->checkTimeouts();
  606. if (timeout > 0) {
  607. // set a dummy timer just so we are guaranteed be called again next time.
  608. dummyTimer = TimerSet(dummyTimer, 0, timeout,
  609. dummyTimerCallback, 0);
  610. }
  611. } catch (rdr::Exception& e) {
  612. vlog.error("XserverDesktop::wakeupHandler: %s",e.str());
  613. }
  614. }
  615. void XserverDesktop::addClient(Socket* sock, bool reverse)
  616. {
  617. vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
  618. server->addSocket(sock, reverse);
  619. }
  620. void XserverDesktop::disconnectClients()
  621. {
  622. vlog.debug("disconnecting all clients");
  623. return server->closeClients("Disconnection from server end");
  624. }
  625. int XserverDesktop::getQueryTimeout(void* opaqueId,
  626. const char** address,
  627. const char** username)
  628. {
  629. if (opaqueId && queryConnectId == opaqueId) {
  630. vlog.info("address=%s, username=%s, timeout=%d",
  631. queryConnectAddress.buf, queryConnectUsername.buf,
  632. (int)queryConnectTimeout);
  633. if (address) *address = queryConnectAddress.buf;
  634. if (username) *username = queryConnectUsername.buf;
  635. return queryConnectTimeout;
  636. }
  637. return 0;
  638. }
  639. void XserverDesktop::approveConnection(void* opaqueId, bool accept,
  640. const char* rejectMsg)
  641. {
  642. if (queryConnectId == opaqueId) {
  643. server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
  644. queryConnectId = 0;
  645. }
  646. }
  647. ///////////////////////////////////////////////////////////////////////////
  648. //
  649. // SDesktop callbacks
  650. void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
  651. {
  652. int i, j, n, valuators[2];
  653. // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
  654. // for S3), so we delay calling it until positionCursor() is called at the
  655. // end of processing a load of RFB.
  656. //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
  657. NewCurrentScreen(
  658. #ifdef XORG_16
  659. vncPointerDevice,
  660. #endif
  661. pScreen, pos.x, pos.y);
  662. if (!pos.equals(cursorPos)) {
  663. valuators[0] = pos.x;
  664. valuators[1] = pos.y;
  665. #ifdef XORG_16
  666. GetEventList(&eventq);
  667. #endif
  668. n = GetPointerEvents (eventq, vncPointerDevice, MotionNotify, 0,
  669. POINTER_ABSOLUTE, 0, 2, valuators);
  670. for (i = 0; i < n; i++) {
  671. mieqEnqueue (vncPointerDevice,
  672. #ifdef XORG_15
  673. eventq + i
  674. #else
  675. (eventq + i)->event
  676. #endif
  677. );
  678. }
  679. }
  680. for (i = 0; i < 5; i++) {
  681. if ((buttonMask ^ oldButtonMask) & (1<<i)) {
  682. // Do not use the pointer mapping. Treat VNC buttons as logical
  683. // buttons.
  684. n = GetPointerEvents (eventq, vncPointerDevice,
  685. (buttonMask & (1<<i)) ?
  686. ButtonPress : ButtonRelease,
  687. i + 1, POINTER_RELATIVE, 0, 0, NULL);
  688. for (j = 0; j < n; j++) {
  689. mieqEnqueue (vncPointerDevice,
  690. #ifdef XORG_15
  691. eventq + j
  692. #else
  693. (eventq + j)->event
  694. #endif
  695. );
  696. }
  697. }
  698. }
  699. cursorPos = pos;
  700. oldButtonMask = buttonMask;
  701. }
  702. void XserverDesktop::clientCutText(const char* str, int len)
  703. {
  704. vncClientCutText(str, len);
  705. }
  706. void XserverDesktop::grabRegion(const rfb::Region& region)
  707. {
  708. if (directFbptr) return;
  709. if (!pScreen->GetImage) {
  710. vlog.error("VNC error: pScreen->GetImage == 0");
  711. return;
  712. }
  713. grabbing = true;
  714. int bytesPerPixel = format.bpp/8;
  715. int bytesPerRow = pScreen->width * bytesPerPixel;
  716. std::vector<rfb::Rect> rects;
  717. std::vector<rfb::Rect>::iterator i;
  718. region.get_rects(&rects);
  719. for (i = rects.begin(); i != rects.end(); i++) {
  720. for (int y = i->tl.y; y < i->br.y; y++) {
  721. (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum],
  722. i->tl.x, y, i->width(), 1,
  723. ZPixmap, (unsigned long)~0L,
  724. ((char*)data
  725. + y * bytesPerRow + i->tl.x * bytesPerPixel));
  726. }
  727. }
  728. grabbing = false;
  729. }
  730. void XserverDesktop::lookup(int index, int* r, int* g, int* b)
  731. {
  732. if ((cmap->c_class | DynamicClass) == DirectColor) {
  733. VisualPtr v = cmap->pVisual;
  734. *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red;
  735. *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
  736. *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
  737. } else {
  738. EntryPtr pent;
  739. pent = (EntryPtr)&cmap->red[index];
  740. if (pent->fShared) {
  741. *r = pent->co.shco.red->color;
  742. *g = pent->co.shco.green->color;
  743. *b = pent->co.shco.blue->color;
  744. } else {
  745. *r = pent->co.local.red;
  746. *g = pent->co.local.green;
  747. *b = pent->co.local.blue;
  748. }
  749. }
  750. }
  751. //
  752. // Keyboard handling
  753. //
  754. #define IS_PRESSED(keyc, keycode) \
  755. ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
  756. // ModifierState is a class which helps simplify generating a "fake" press
  757. // or release of shift, ctrl, alt, etc. An instance of the class is created
  758. // for every modifier which may need to be pressed or released. Then either
  759. // press() or release() may be called to make sure that the corresponding keys
  760. // are in the right state. The destructor of the class automatically reverts
  761. // to the previous state. Each modifier may have multiple keys associated with
  762. // it, so in the case of a fake release, this may involve releasing more than
  763. // one key.
  764. class ModifierState {
  765. public:
  766. ModifierState(int modIndex_)
  767. : modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
  768. {
  769. }
  770. ~ModifierState() {
  771. for (int i = 0; i < nKeys; i++)
  772. generateXKeyEvent(keys[i], !pressed);
  773. delete [] keys;
  774. }
  775. void press() {
  776. KeyClassPtr keyc = vncKeyboardDevice->key;
  777. if (!(keyc->state & (1<<modIndex))) {
  778. tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
  779. true);
  780. pressed = true;
  781. }
  782. }
  783. void release() {
  784. KeyClassPtr keyc = vncKeyboardDevice->key;
  785. if (keyc->state & (1<<modIndex)) {
  786. for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
  787. int keycode
  788. = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
  789. if (keycode && IS_PRESSED(keyc, keycode))
  790. tempKeyEvent(keycode, false);
  791. }
  792. }
  793. }
  794. private:
  795. void tempKeyEvent(int keycode, bool down) {
  796. if (keycode) {
  797. if (!keys) keys = new int[vncKeyboardDevice->key->maxKeysPerModifier];
  798. keys[nKeys++] = keycode;
  799. generateXKeyEvent(keycode, down);
  800. }
  801. }
  802. void generateXKeyEvent(int keycode, bool down) {
  803. int i, n;
  804. n = GetKeyboardEvents (eventq, vncKeyboardDevice,
  805. down ? KeyPress : KeyRelease, keycode);
  806. for (i = 0; i < n; i++) {
  807. mieqEnqueue (vncKeyboardDevice,
  808. #ifdef XORG_15
  809. eventq + i
  810. #else
  811. (eventq + i)->event
  812. #endif
  813. );
  814. }
  815. vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
  816. }
  817. int modIndex;
  818. int nKeys;
  819. int* keys;
  820. bool pressed;
  821. };
  822. // altKeysym is a table of alternative keysyms which have the same meaning.
  823. struct altKeysym_t {
  824. KeySym a, b;
  825. };
  826. altKeysym_t altKeysym[] = {
  827. { XK_Shift_L, XK_Shift_R },
  828. { XK_Control_L, XK_Control_R },
  829. { XK_Meta_L, XK_Meta_R },
  830. { XK_Alt_L, XK_Alt_R },
  831. { XK_Super_L, XK_Super_R },
  832. { XK_Hyper_L, XK_Hyper_R },
  833. { XK_KP_Space, XK_space },
  834. { XK_KP_Tab, XK_Tab },
  835. { XK_KP_Enter, XK_Return },
  836. { XK_KP_F1, XK_F1 },
  837. { XK_KP_F2, XK_F2 },
  838. { XK_KP_F3, XK_F3 },
  839. { XK_KP_F4, XK_F4 },
  840. { XK_KP_Home, XK_Home },
  841. { XK_KP_Left, XK_Left },
  842. { XK_KP_Up, XK_Up },
  843. { XK_KP_Right, XK_Right },
  844. { XK_KP_Down, XK_Down },
  845. { XK_KP_Page_Up, XK_Page_Up },
  846. { XK_KP_Page_Down, XK_Page_Down },
  847. { XK_KP_End, XK_End },
  848. { XK_KP_Begin, XK_Begin },
  849. { XK_KP_Insert, XK_Insert },
  850. { XK_KP_Delete, XK_Delete },
  851. { XK_KP_Equal, XK_equal },
  852. { XK_KP_Multiply, XK_asterisk },
  853. { XK_KP_Add, XK_plus },
  854. { XK_KP_Separator, XK_comma },
  855. { XK_KP_Subtract, XK_minus },
  856. { XK_KP_Decimal, XK_period },
  857. { XK_KP_Divide, XK_slash },
  858. { XK_KP_0, XK_0 },
  859. { XK_KP_1, XK_1 },
  860. { XK_KP_2, XK_2 },
  861. { XK_KP_3, XK_3 },
  862. { XK_KP_4, XK_4 },
  863. { XK_KP_5, XK_5 },
  864. { XK_KP_6, XK_6 },
  865. { XK_KP_7, XK_7 },
  866. { XK_KP_8, XK_8 },
  867. { XK_KP_9, XK_9 },
  868. };
  869. // keyEvent() - work out the best keycode corresponding to the keysym sent by
  870. // the viewer. This is non-trivial because we can't assume much about the
  871. // local keyboard layout. We must also find out which column of the keyboard
  872. // mapping the keysym is in, and alter the shift state appropriately. Column 0
  873. // means both shift and "mode_switch" (AltGr) must be released, column 1 means
  874. // shift must be pressed and mode_switch released, column 2 means shift must be
  875. // released and mode_switch pressed, and column 3 means both shift and
  876. // mode_switch must be pressed.
  877. void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
  878. {
  879. KeyClassPtr keyc = vncKeyboardDevice->key;
  880. KeySymsPtr keymap = &keyc->curKeySyms;
  881. int i, j, k, n;
  882. if (keysym == XK_Caps_Lock) {
  883. vlog.debug("Ignoring caps lock");
  884. return;
  885. }
  886. // find which modifier Mode_switch is on.
  887. int modeSwitchMapIndex = 0;
  888. for (i = 3; i < 8; i++) {
  889. for (k = 0; k < keyc->maxKeysPerModifier; k++) {
  890. int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
  891. for (j = 0; j < keymap->mapWidth; j++) {
  892. if (keycode != 0 &&
  893. keymap->map[(keycode - keymap->minKeyCode)
  894. * keymap->mapWidth + j] == XK_Mode_switch)
  895. {
  896. modeSwitchMapIndex = i;
  897. break;
  898. }
  899. }
  900. }
  901. }
  902. int col = 0;
  903. if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
  904. if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
  905. int kc = KeysymToKeycode(keymap, keysym, &col);
  906. // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a
  907. // local shifted Tab regardless of what the "shifted Tab" keysym is on the
  908. // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
  909. // keysym, and quite possibly some others too). We never get ISO_Left_Tab
  910. // here because it's already been translated in VNCSConnectionST.
  911. if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
  912. col |= 1;
  913. if (kc == 0) {
  914. // Not a direct match in the local keyboard mapping. Check for alternative
  915. // keysyms with the same meaning.
  916. for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
  917. if (keysym == altKeysym[i].a)
  918. kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
  919. else if (keysym == altKeysym[i].b)
  920. kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
  921. if (kc) break;
  922. }
  923. }
  924. if (kc == 0) {
  925. // Last resort - dynamically add a new key to the keyboard mapping.
  926. for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
  927. if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
  928. keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
  929. col = 0;
  930. SendMappingNotify(
  931. #ifdef XORG_16
  932. vncKeyboardDevice,
  933. #endif
  934. MappingKeyboard, kc, 1, serverClient);
  935. vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
  936. break;
  937. }
  938. }
  939. if (kc < keymap->minKeyCode) {
  940. vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
  941. return;
  942. }
  943. }
  944. // See if it's a modifier key. If so, then don't do any auto-repeat, because
  945. // the X server will translate each press into a release followed by a press.
  946. for (i = 0; i < 8; i++) {
  947. for (k = 0; k < keyc->maxKeysPerModifier; k++) {
  948. if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
  949. IS_PRESSED(keyc,kc) && down)
  950. return;
  951. }
  952. }
  953. ModifierState shift(ShiftMapIndex);
  954. ModifierState modeSwitch(modeSwitchMapIndex);
  955. if (down) {
  956. if (col & 1)
  957. shift.press();
  958. else
  959. shift.release();
  960. if (modeSwitchMapIndex) {
  961. if (col & 2)
  962. modeSwitch.press();
  963. else
  964. modeSwitch.release();
  965. }
  966. }
  967. vlog.debug("keycode %d %s", kc, down ? "down" : "up");
  968. n = GetKeyboardEvents (eventq, vncKeyboardDevice, down ?
  969. KeyPress : KeyRelease, kc);
  970. for (i = 0; i < n; i++) {
  971. mieqEnqueue (vncKeyboardDevice,
  972. #ifdef XORG_15
  973. eventq + i
  974. #else
  975. (eventq + i)->event
  976. #endif
  977. );
  978. }
  979. }
  980. void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
  981. {
  982. *lower = sym;
  983. *upper = sym;
  984. switch(sym >> 8) {
  985. case 0: /* Latin 1 */
  986. if ((sym >= XK_A) && (sym <= XK_Z))
  987. *lower += (XK_a - XK_A);
  988. else if ((sym >= XK_a) && (sym <= XK_z))
  989. *upper -= (XK_a - XK_A);
  990. else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
  991. *lower += (XK_agrave - XK_Agrave);
  992. else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
  993. *upper -= (XK_agrave - XK_Agrave);
  994. else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
  995. *lower += (XK_oslash - XK_Ooblique);
  996. else if ((sym >= XK_oslash) && (sym <= XK_thorn))
  997. *upper -= (XK_oslash - XK_Ooblique);
  998. break;
  999. case 1: /* Latin 2 */
  1000. /* Assume the KeySym is a legal value (ignore discontinuities) */
  1001. if (sym == XK_Aogonek)
  1002. *lower = XK_aogonek;
  1003. else if (sym >= XK_Lstroke && sym <= XK_Sacute)
  1004. *lower += (XK_lstroke - XK_Lstroke);
  1005. else if (sym >= XK_Scaron && sym <= XK_Zacute)
  1006. *lower += (XK_scaron - XK_Scaron);
  1007. else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
  1008. *lower += (XK_zcaron - XK_Zcaron);
  1009. else if (sym == XK_aogonek)
  1010. *upper = XK_Aogonek;
  1011. else if (sym >= XK_lstroke && sym <= XK_sacute)
  1012. *upper -= (XK_lstroke - XK_Lstroke);
  1013. else if (sym >= XK_scaron && sym <= XK_zacute)
  1014. *upper -= (XK_scaron - XK_Scaron);
  1015. else if (sym >= XK_zcaron && sym <= XK_zabovedot)
  1016. *upper -= (XK_zcaron - XK_Zcaron);
  1017. else if (sym >= XK_Racute && sym <= XK_Tcedilla)
  1018. *lower += (XK_racute - XK_Racute);
  1019. else if (sym >= XK_racute && sym <= XK_tcedilla)
  1020. *upper -= (XK_racute - XK_Racute);
  1021. break;
  1022. case 2: /* Latin 3 */
  1023. /* Assume the KeySym is a legal value (ignore discontinuities) */
  1024. if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
  1025. *lower += (XK_hstroke - XK_Hstroke);
  1026. else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
  1027. *lower += (XK_gbreve - XK_Gbreve);
  1028. else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
  1029. *upper -= (XK_hstroke - XK_Hstroke);
  1030. else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
  1031. *upper -= (XK_gbreve - XK_Gbreve);
  1032. else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
  1033. *lower += (XK_cabovedot - XK_Cabovedot);
  1034. else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
  1035. *upper -= (XK_cabovedot - XK_Cabovedot);
  1036. break;
  1037. case 3: /* Latin 4 */
  1038. /* Assume the KeySym is a legal value (ignore discontinuities) */
  1039. if (sym >= XK_Rcedilla && sym <= XK_Tslash)
  1040. *lower += (XK_rcedilla - XK_Rcedilla);
  1041. else if (sym >= XK_rcedilla && sym <= XK_tslash)
  1042. *upper -= (XK_rcedilla - XK_Rcedilla);
  1043. else if (sym == XK_ENG)
  1044. *lower = XK_eng;
  1045. else if (sym == XK_eng)
  1046. *upper = XK_ENG;
  1047. else if (sym >= XK_Amacron && sym <= XK_Umacron)
  1048. *lower += (XK_amacron - XK_Amacron);
  1049. else if (sym >= XK_amacron && sym <= XK_umacron)
  1050. *upper -= (XK_amacron - XK_Amacron);
  1051. break;
  1052. case 6: /* Cyrillic */
  1053. /* Assume the KeySym is a legal value (ignore discontinuities) */
  1054. if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
  1055. *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
  1056. else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
  1057. *upper += (XK_Serbian_DJE - XK_Serbian_dje);
  1058. else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
  1059. *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
  1060. else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
  1061. *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
  1062. break;
  1063. case 7: /* Greek */
  1064. /* Assume the KeySym is a legal value (ignore discontinuities) */
  1065. if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
  1066. *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
  1067. else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
  1068. sym != XK_Greek_iotaaccentdieresis &&
  1069. sym != XK_Greek_upsilonaccentdieresis)
  1070. *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
  1071. else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
  1072. *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
  1073. else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
  1074. sym != XK_Greek_finalsmallsigma)
  1075. *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
  1076. break;
  1077. }
  1078. }
  1079. static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
  1080. {
  1081. register int per = keymap->mapWidth;
  1082. register KeySym *syms;
  1083. KeySym lsym, usym;
  1084. if ((col < 0) || ((col >= per) && (col > 3)) ||
  1085. (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
  1086. return NoSymbol;
  1087. syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
  1088. if (col < 4) {
  1089. if (col > 1) {
  1090. while ((per > 2) && (syms[per - 1] == NoSymbol))
  1091. per--;
  1092. if (per < 3)
  1093. col -= 2;
  1094. }
  1095. if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
  1096. XConvertCase(syms[col&~1], &lsym, &usym);
  1097. if (!(col & 1))
  1098. return lsym;
  1099. // I'm commenting out this logic because it's incorrect even though it
  1100. // was copied from the Xlib sources. The X protocol book quite clearly
  1101. // states that where a group consists of element 1 being a non-alphabetic
  1102. // keysym and element 2 being NoSymbol that you treat the second element
  1103. // as being the same as the first. This also tallies with the behaviour
  1104. // produced by the installed Xlib on my linux box (I believe this is
  1105. // because it uses some XKB code rather than the original Xlib code -
  1106. // compare XKBBind.c with KeyBind.c in lib/X11).
  1107. // else if (usym == lsym)
  1108. // return NoSymbol;
  1109. else
  1110. return usym;
  1111. }
  1112. }
  1113. return syms[col];
  1114. }
  1115. // KeysymToKeycode() - find the keycode and column corresponding to the given
  1116. // keysym. The value of col passed in should be the column determined from the
  1117. // current shift state. If the keysym can be found in that column we prefer
  1118. // that to finding it in a different column (which would require fake events to
  1119. // alter the shift state).
  1120. static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
  1121. {
  1122. register int i, j;
  1123. j = *col;
  1124. for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
  1125. if (KeyCodetoKeySym(keymap, i, j) == ks)
  1126. return i;
  1127. }
  1128. for (j = 0; j < keymap->mapWidth; j++) {
  1129. for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
  1130. if (KeyCodetoKeySym(keymap, i, j) == ks) {
  1131. *col = j;
  1132. return i;
  1133. }
  1134. }
  1135. }
  1136. return 0;
  1137. }
  1138. /* Fairly standard US PC Keyboard */
  1139. #define VFB_MIN_KEY 8
  1140. #define VFB_MAX_KEY 255
  1141. #define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
  1142. #define KEYSYMS_PER_KEY 2
  1143. KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
  1144. NoSymbol, NoSymbol,
  1145. XK_Escape, NoSymbol,
  1146. XK_1, XK_exclam,
  1147. XK_2, XK_at,
  1148. XK_3, XK_numbersign,
  1149. XK_4, XK_dollar,
  1150. XK_5, XK_percent,
  1151. XK_6, XK_asciicircum,
  1152. XK_7, XK_ampersand,
  1153. XK_8, XK_asterisk,
  1154. XK_9, XK_parenleft,
  1155. XK_0, XK_parenright,
  1156. XK_minus, XK_underscore,
  1157. XK_equal, XK_plus,
  1158. XK_BackSpace, NoSymbol,
  1159. XK_Tab, NoSymbol,
  1160. XK_q, XK_Q,
  1161. XK_w, XK_W,
  1162. XK_e, XK_E,
  1163. XK_r, XK_R,
  1164. XK_t, XK_T,
  1165. XK_y, XK_Y,
  1166. XK_u, XK_U,
  1167. XK_i, XK_I,
  1168. XK_o, XK_O,
  1169. XK_p, XK_P,
  1170. XK_bracketleft, XK_braceleft,
  1171. XK_bracketright, XK_braceright,
  1172. XK_Return, NoSymbol,
  1173. XK_Control_L, NoSymbol,
  1174. XK_a, XK_A,
  1175. XK_s, XK_S,
  1176. XK_d, XK_D,
  1177. XK_f, XK_F,
  1178. XK_g, XK_G,
  1179. XK_h, XK_H,
  1180. XK_j, XK_J,
  1181. XK_k, XK_K,
  1182. XK_l, XK_L,
  1183. XK_semicolon, XK_colon,
  1184. XK_apostrophe, XK_quotedbl,
  1185. XK_grave, XK_asciitilde,
  1186. XK_Shift_L, NoSymbol,
  1187. XK_backslash, XK_bar,
  1188. XK_z, XK_Z,
  1189. XK_x, XK_X,
  1190. XK_c, XK_C,
  1191. XK_v, XK_V,
  1192. XK_b, XK_B,
  1193. XK_n, XK_N,
  1194. XK_m, XK_M,
  1195. XK_comma, XK_less,
  1196. XK_period, XK_greater,
  1197. XK_slash, XK_question,
  1198. XK_Shift_R, NoSymbol,
  1199. XK_KP_Multiply, NoSymbol,
  1200. XK_Alt_L, XK_Meta_L,
  1201. XK_space, NoSymbol,
  1202. /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
  1203. XK_F1, NoSymbol,
  1204. XK_F2, NoSymbol,
  1205. XK_F3, NoSymbol,
  1206. XK_F4, NoSymbol,
  1207. XK_F5, NoSymbol,
  1208. XK_F6, NoSymbol,
  1209. XK_F7, NoSymbol,
  1210. XK_F8, NoSymbol,
  1211. XK_F9, NoSymbol,
  1212. XK_F10, NoSymbol,
  1213. XK_Num_Lock, XK_Pointer_EnableKeys,
  1214. XK_Scroll_Lock, NoSymbol,
  1215. XK_KP_Home, XK_KP_7,
  1216. XK_KP_Up, XK_KP_8,
  1217. XK_KP_Prior, XK_KP_9,
  1218. XK_KP_Subtract, NoSymbol,
  1219. XK_KP_Left, XK_KP_4,
  1220. XK_KP_Begin, XK_KP_5,
  1221. XK_KP_Right, XK_KP_6,
  1222. XK_KP_Add, NoSymbol,
  1223. XK_KP_End, XK_KP_1,
  1224. XK_KP_Down, XK_KP_2,
  1225. XK_KP_Next, XK_KP_3,
  1226. XK_KP_Insert, XK_KP_0,
  1227. XK_KP_Delete, XK_KP_Decimal,
  1228. NoSymbol, NoSymbol,
  1229. NoSymbol, NoSymbol,
  1230. NoSymbol, NoSymbol,
  1231. XK_F11, NoSymbol,
  1232. XK_F12, NoSymbol,
  1233. XK_Home, NoSymbol,
  1234. XK_Up, NoSymbol,
  1235. XK_Prior, NoSymbol,
  1236. XK_Left, NoSymbol,
  1237. NoSymbol, NoSymbol,
  1238. XK_Right, NoSymbol,
  1239. XK_End, NoSymbol,
  1240. XK_Down, NoSymbol,
  1241. XK_Next, NoSymbol,
  1242. XK_Insert, NoSymbol,
  1243. XK_Delete, NoSymbol,
  1244. XK_KP_Enter, NoSymbol,
  1245. XK_Control_R, NoSymbol,
  1246. XK_Pause, XK_Break,
  1247. XK_Print, XK_Execute,
  1248. XK_KP_Divide, NoSymbol,
  1249. XK_Alt_R, XK_Meta_R,
  1250. };
  1251. static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
  1252. {
  1253. int i;
  1254. for (i = 0; i < MAP_LENGTH; i++)
  1255. pModMap[i] = NoSymbol;
  1256. for (i = 0; i < VFB_MAP_LEN; i++) {
  1257. if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
  1258. pModMap[i + VFB_MIN_KEY] = LockMask;
  1259. else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
  1260. keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
  1261. pModMap[i + VFB_MIN_KEY] = ShiftMask;
  1262. else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
  1263. keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
  1264. pModMap[i + VFB_MIN_KEY] = ControlMask;
  1265. }
  1266. else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
  1267. keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
  1268. pModMap[i + VFB_MIN_KEY] = Mod1Mask;
  1269. }
  1270. pKeySyms->minKeyCode = VFB_MIN_KEY;
  1271. pKeySyms->maxKeyCode = VFB_MAX_KEY;
  1272. pKeySyms->mapWidth = KEYSYMS_PER_KEY;
  1273. pKeySyms->map = keyboardMap;
  1274. return TRUE;
  1275. }
  1276. static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
  1277. {
  1278. if (percent > 0)
  1279. vncBell();
  1280. }
  1281. static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
  1282. {
  1283. KeySymsRec keySyms;
  1284. CARD8 modMap[MAP_LENGTH];
  1285. DevicePtr pDev = (DevicePtr)pDevice;
  1286. switch (onoff)
  1287. {
  1288. case DEVICE_INIT:
  1289. GetMappings(&keySyms, modMap);
  1290. InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
  1291. (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
  1292. break;
  1293. case DEVICE_ON:
  1294. pDev->on = TRUE;
  1295. break;
  1296. case DEVICE_OFF:
  1297. pDev->on = FALSE;
  1298. break;
  1299. case DEVICE_CLOSE:
  1300. break;
  1301. }
  1302. return Success;
  1303. }
  1304. static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
  1305. {
  1306. BYTE map[6];
  1307. DevicePtr pDev = (DevicePtr)pDevice;
  1308. switch (onoff)
  1309. {
  1310. case DEVICE_INIT:
  1311. map[1] = 1;
  1312. map[2] = 2;
  1313. map[3] = 3;
  1314. map[4] = 4;
  1315. map[5] = 5;
  1316. InitPointerDeviceStruct(pDev, map, 5,
  1317. #ifdef XORG_15
  1318. GetMotionHistory,
  1319. #endif
  1320. (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2);
  1321. break;
  1322. case DEVICE_ON:
  1323. pDev->on = TRUE;
  1324. break;
  1325. case DEVICE_OFF:
  1326. pDev->on = FALSE;
  1327. break;
  1328. case DEVICE_CLOSE:
  1329. break;
  1330. }
  1331. return Success;
  1332. }