Guest User

Untitled

a guest
Sep 20th, 2018
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 474.07 KB | None | 0 0
  1. (function() {
  2. "use strict";
  3. // Edit by Modules Factory for novnc-remote support
  4. // Start
  5.  
  6. function createCookie(name,value,days) {
  7. if (days) {
  8. var date = new Date();
  9. date.setTime(date.getTime()+(days*24*60*60*1000));
  10. var expires = "; expires="+date.toGMTString();
  11. }
  12. else var expires = "";
  13. document.cookie = name+"="+value+expires+"; path=/";
  14. }
  15.  
  16.  
  17. var $_GET = {},
  18. args = location.search.substr(1).split(/&/);
  19. for (var i=0; i<args.length; ++i) {
  20. var tmp = args[i].split(/=/);
  21. if (tmp[0] != "") {
  22. $_GET[decodeURIComponent(tmp[0])] = decodeURIComponent(tmp.slice(1).join("").replace("+", " "));
  23. }
  24. }
  25.  
  26. if($_GET['oticket']) {
  27. createCookie("PVEAuthCookie","",-1);
  28.  
  29. createCookie("PVEAuthCookie", $_GET['oticket']);
  30.  
  31. if($_GET['UserName']) {
  32. PVE = {};
  33. PVE.UserName = $_GET['UserName'];
  34. PVE.CSRFPreventionToken = $_GET['CSRFPreventionToken'];
  35. }
  36. }
  37. // End
  38. // Edit by Modules Factory for novnc-remote support
  39. var $$$core$util$logging$$ = {
  40. get init_logging() {
  41. return $$$core$util$logging$$init_logging;
  42. },
  43.  
  44. get get_logging() {
  45. return $$$core$util$logging$$get_logging;
  46. },
  47.  
  48. get Debug() {
  49. return $$$core$util$logging$$Debug;
  50. },
  51.  
  52. get Info() {
  53. return $$$core$util$logging$$Info;
  54. },
  55.  
  56. get Warn() {
  57. return $$$core$util$logging$$Warn;
  58. },
  59.  
  60. get Error() {
  61. return $$$core$util$logging$$Error;
  62. }
  63. },
  64. $$util$$ = {
  65. get getKeycode() {
  66. return $$util$$getKeycode;
  67. },
  68.  
  69. get getKey() {
  70. return $$util$$getKey;
  71. },
  72.  
  73. get getKeysym() {
  74. return $$util$$getKeysym;
  75. }
  76. },
  77. $$$utils$common$$ = {
  78. get shrinkBuf() {
  79. return $$$utils$common$$shrinkBuf;
  80. },
  81.  
  82. get arraySet() {
  83. return $$$utils$common$$arraySet;
  84. },
  85.  
  86. get flattenChunks() {
  87. return $$$utils$common$$flattenChunks;
  88. },
  89.  
  90. get Buf8() {
  91. return $$$utils$common$$Buf8;
  92. },
  93.  
  94. get Buf16() {
  95. return $$$utils$common$$Buf16;
  96. },
  97.  
  98. get Buf32() {
  99. return $$$utils$common$$Buf32;
  100. }
  101. },
  102. $$webutil$$ = {
  103. get init_logging() {
  104. return $$webutil$$init_logging;
  105. },
  106.  
  107. get getQueryVar() {
  108. return $$webutil$$getQueryVar;
  109. },
  110.  
  111. get getHashVar() {
  112. return $$webutil$$getHashVar;
  113. },
  114.  
  115. get getConfigVar() {
  116. return $$webutil$$getConfigVar;
  117. },
  118.  
  119. get createCookie() {
  120. return $$webutil$$createCookie;
  121. },
  122.  
  123. get readCookie() {
  124. return $$webutil$$readCookie;
  125. },
  126.  
  127. get eraseCookie() {
  128. return $$webutil$$eraseCookie;
  129. },
  130.  
  131. get initSettings() {
  132. return $$webutil$$initSettings;
  133. },
  134.  
  135. get writeSetting() {
  136. return $$webutil$$writeSetting;
  137. },
  138.  
  139. get readSetting() {
  140. return $$webutil$$readSetting;
  141. },
  142.  
  143. get eraseSetting() {
  144. return $$webutil$$eraseSetting;
  145. },
  146.  
  147. get injectParamIfMissing() {
  148. return $$webutil$$injectParamIfMissing;
  149. },
  150.  
  151. get fetchJSON() {
  152. return $$webutil$$fetchJSON;
  153. }
  154. };
  155.  
  156. /*
  157. * noVNC: HTML5 VNC client
  158. * Copyright (C) 2012 Joel Martin
  159. * Licensed under MPL 2.0 (see LICENSE.txt)
  160. *
  161. * See README.md for usage and integration instructions.
  162. */
  163.  
  164. /*
  165. * Logging/debug routines
  166. */
  167.  
  168. var $$$core$util$logging$$_log_level = 'warn';
  169.  
  170. var $$$core$util$logging$$Debug = function (msg) {};
  171. var $$$core$util$logging$$Info = function (msg) {};
  172. var $$$core$util$logging$$Warn = function (msg) {};
  173. var $$$core$util$logging$$Error = function (msg) {};
  174.  
  175. function $$$core$util$logging$$init_logging(level) {
  176. if (typeof level === 'undefined') {
  177. level = $$$core$util$logging$$_log_level;
  178. } else {
  179. $$$core$util$logging$$_log_level = level;
  180. }
  181.  
  182. $$$core$util$logging$$Debug = $$$core$util$logging$$Info = $$$core$util$logging$$Warn = $$$core$util$logging$$Error = function (msg) {};
  183. if (typeof window.console !== "undefined") {
  184. /* jshint -W086 */
  185. switch (level) {
  186. case 'debug':
  187. $$$core$util$logging$$Debug = console.debug.bind(window.console);
  188. case 'info':
  189. $$$core$util$logging$$Info = console.info.bind(window.console);
  190. case 'warn':
  191. $$$core$util$logging$$Warn = console.warn.bind(window.console);
  192. case 'error':
  193. $$$core$util$logging$$Error = console.error.bind(window.console);
  194. case 'none':
  195. break;
  196. default:
  197. throw new $$$core$util$logging$$Error("invalid logging type '" + level + "'");
  198. }
  199. /* jshint +W086 */
  200. }
  201. }
  202.  
  203. function $$$core$util$logging$$get_logging() {
  204. return $$$core$util$logging$$_log_level;
  205. }
  206.  
  207. // Initialize logging level
  208. $$$core$util$logging$$init_logging();
  209.  
  210. function $$$core$util$localization$$Localizer() {
  211. // Currently configured language
  212. this.language = 'en';
  213.  
  214. // Current dictionary of translations
  215. this.dictionary = undefined;
  216. }
  217.  
  218. $$$core$util$localization$$Localizer.prototype = {
  219. // Configure suitable language based on user preferences
  220. setup: function (supportedLanguages) {
  221. var userLanguages;
  222.  
  223. this.language = 'en'; // Default: US English
  224.  
  225. /*
  226. * Navigator.languages only available in Chrome (32+) and FireFox (32+)
  227. * Fall back to navigator.language for other browsers
  228. */
  229. if (typeof window.navigator.languages == 'object') {
  230. userLanguages = window.navigator.languages;
  231. } else {
  232. userLanguages = [navigator.language || navigator.userLanguage];
  233. }
  234.  
  235. for (var i = 0;i < userLanguages.length;i++) {
  236. var userLang = userLanguages[i];
  237. userLang = userLang.toLowerCase();
  238. userLang = userLang.replace("_", "-");
  239. userLang = userLang.split("-");
  240.  
  241. // Built-in default?
  242. if ((userLang[0] === 'en') &&
  243. ((userLang[1] === undefined) || (userLang[1] === 'us'))) {
  244. return;
  245. }
  246.  
  247. // First pass: perfect match
  248. for (var j = 0;j < supportedLanguages.length;j++) {
  249. var supLang = supportedLanguages[j];
  250. supLang = supLang.toLowerCase();
  251. supLang = supLang.replace("_", "-");
  252. supLang = supLang.split("-");
  253.  
  254. if (userLang[0] !== supLang[0])
  255. continue;
  256. if (userLang[1] !== supLang[1])
  257. continue;
  258.  
  259. this.language = supportedLanguages[j];
  260. return;
  261. }
  262.  
  263. // Second pass: fallback
  264. for (var j = 0;j < supportedLanguages.length;j++) {
  265. supLang = supportedLanguages[j];
  266. supLang = supLang.toLowerCase();
  267. supLang = supLang.replace("_", "-");
  268. supLang = supLang.split("-");
  269.  
  270. if (userLang[0] !== supLang[0])
  271. continue;
  272. if (supLang[1] !== undefined)
  273. continue;
  274.  
  275. this.language = supportedLanguages[j];
  276. return;
  277. }
  278. }
  279. },
  280.  
  281. // Retrieve localised text
  282. get: function (id) {
  283. if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) {
  284. return this.dictionary[id];
  285. } else {
  286. return id;
  287. }
  288. },
  289.  
  290. // Traverses the DOM and translates relevant fields
  291. // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
  292. translateDOM: function () {
  293. var self = this;
  294. function process(elem, enabled) {
  295. function isAnyOf(searchElement, items) {
  296. return items.indexOf(searchElement) !== -1;
  297. }
  298.  
  299. function translateAttribute(elem, attr) {
  300. var str = elem.getAttribute(attr);
  301. str = self.get(str);
  302. elem.setAttribute(attr, str);
  303. }
  304.  
  305. function translateTextNode(node) {
  306. var str = node.data.trim();
  307. str = self.get(str);
  308. node.data = str;
  309. }
  310.  
  311. if (elem.hasAttribute("translate")) {
  312. if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) {
  313. enabled = true;
  314. } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) {
  315. enabled = false;
  316. }
  317. }
  318.  
  319. if (enabled) {
  320. if (elem.hasAttribute("abbr") &&
  321. elem.tagName === "TH") {
  322. translateAttribute(elem, "abbr");
  323. }
  324. if (elem.hasAttribute("alt") &&
  325. isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) {
  326. translateAttribute(elem, "alt");
  327. }
  328. if (elem.hasAttribute("download") &&
  329. isAnyOf(elem.tagName, ["A", "AREA"])) {
  330. translateAttribute(elem, "download");
  331. }
  332. if (elem.hasAttribute("label") &&
  333. isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP",
  334. "OPTION", "TRACK"])) {
  335. translateAttribute(elem, "label");
  336. }
  337. // FIXME: Should update "lang"
  338. if (elem.hasAttribute("placeholder") &&
  339. isAnyOf(elem.tagName, ["INPUT", "TEXTAREA"])) {
  340. translateAttribute(elem, "placeholder");
  341. }
  342. if (elem.hasAttribute("title")) {
  343. translateAttribute(elem, "title");
  344. }
  345. if (elem.hasAttribute("value") &&
  346. elem.tagName === "INPUT" &&
  347. isAnyOf(elem.getAttribute("type"), ["reset", "button"])) {
  348. translateAttribute(elem, "value");
  349. }
  350. }
  351.  
  352. for (var i = 0;i < elem.childNodes.length;i++) {
  353. let node = elem.childNodes[i];
  354. if (node.nodeType === node.ELEMENT_NODE) {
  355. process(node, enabled);
  356. } else if (node.nodeType === node.TEXT_NODE && enabled) {
  357. translateTextNode(node);
  358. }
  359. }
  360. }
  361.  
  362. process(document.body, true);
  363. },
  364. }
  365.  
  366. const $$$core$util$localization$$l10n = new $$$core$util$localization$$Localizer();
  367. var $$$core$util$localization$$default = $$$core$util$localization$$l10n.get.bind($$$core$util$localization$$l10n);
  368.  
  369. var $$$core$util$browsers$$isTouchDevice = ('ontouchstart' in document.documentElement) ||
  370. // requried for Chrome debugger
  371. (document.ontouchstart !== undefined) ||
  372. // required for MS Surface
  373. (navigator.maxTouchPoints > 0) ||
  374. (navigator.msMaxTouchPoints > 0);
  375.  
  376. window.addEventListener('touchstart', function onFirstTouch() {
  377. $$$core$util$browsers$$isTouchDevice = true;
  378. window.removeEventListener('touchstart', onFirstTouch, false);
  379. }, false);
  380.  
  381. var $$$core$util$browsers$$_cursor_uris_supported = null;
  382.  
  383. function $$$core$util$browsers$$browserSupportsCursorURIs() {
  384. if ($$$core$util$browsers$$_cursor_uris_supported === null) {
  385. try {
  386. var target = document.createElement('canvas');
  387. target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
  388.  
  389. if (target.style.cursor) {
  390. $$$core$util$logging$$.Info("Data URI scheme cursor supported");
  391. $$$core$util$browsers$$_cursor_uris_supported = true;
  392. } else {
  393. $$$core$util$logging$$.Warn("Data URI scheme cursor not supported");
  394. $$$core$util$browsers$$_cursor_uris_supported = false;
  395. }
  396. } catch (exc) {
  397. $$$core$util$logging$$.Error("Data URI scheme cursor test exception: " + exc);
  398. $$$core$util$browsers$$_cursor_uris_supported = false;
  399. }
  400. }
  401.  
  402. return $$$core$util$browsers$$_cursor_uris_supported;
  403. }
  404.  
  405. function $$$core$util$browsers$$_forceCursorURIs(enabled) {
  406. if (enabled === undefined || enabled) {
  407. $$$core$util$browsers$$_cursor_uris_supported = true;
  408. } else {
  409. $$$core$util$browsers$$_cursor_uris_supported = false;
  410. }
  411. }
  412.  
  413. function $$$core$util$events$$getPointerEvent(e) {
  414. return e.changedTouches ? e.changedTouches[0] : e.touches ? e.touches[0] : e;
  415. }
  416.  
  417. function $$$core$util$events$$stopEvent(e) {
  418. e.stopPropagation();
  419. e.preventDefault();
  420. }
  421.  
  422. // Emulate Element.setCapture() when not supported
  423. var $$$core$util$events$$_captureRecursion = false;
  424. var $$$core$util$events$$_captureElem = null;
  425. const $$$core$util$events$$_captureProxy = function (e) {
  426. // Recursion protection as we'll see our own event
  427. if ($$$core$util$events$$_captureRecursion) return;
  428.  
  429. // Clone the event as we cannot dispatch an already dispatched event
  430. var newEv = new e.constructor(e.type, e);
  431.  
  432. $$$core$util$events$$_captureRecursion = true;
  433. $$$core$util$events$$_captureElem.dispatchEvent(newEv);
  434. $$$core$util$events$$_captureRecursion = false;
  435.  
  436. // Avoid double events
  437. e.stopPropagation();
  438.  
  439. // Respect the wishes of the redirected event handlers
  440. if (newEv.defaultPrevented) {
  441. e.preventDefault();
  442. }
  443.  
  444. // Implicitly release the capture on button release
  445. if (e.type === "mouseup") {
  446. $$$core$util$events$$releaseCapture();
  447. }
  448. };
  449.  
  450. // Follow cursor style of target element
  451. const $$$core$util$events$$_captureElemChanged = function() {
  452. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  453. captureElem.style.cursor = window.getComputedStyle($$$core$util$events$$_captureElem).cursor;
  454. };
  455. const $$$core$util$events$$_captureObserver = new MutationObserver($$$core$util$events$$_captureElemChanged);
  456.  
  457. var $$$core$util$events$$_captureIndex = 0;
  458.  
  459. function $$$core$util$events$$setCapture(elem) {
  460. if (elem.setCapture) {
  461.  
  462. elem.setCapture();
  463.  
  464. // IE releases capture on 'click' events which might not trigger
  465. elem.addEventListener('mouseup', $$$core$util$events$$releaseCapture);
  466.  
  467. } else {
  468. // Release any existing capture in case this method is
  469. // called multiple times without coordination
  470. $$$core$util$events$$releaseCapture();
  471.  
  472. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  473.  
  474. if (captureElem === null) {
  475. captureElem = document.createElement("div");
  476. captureElem.id = "noVNC_mouse_capture_elem";
  477. captureElem.style.position = "fixed";
  478. captureElem.style.top = "0px";
  479. captureElem.style.left = "0px";
  480. captureElem.style.width = "100%";
  481. captureElem.style.height = "100%";
  482. captureElem.style.zIndex = 10000;
  483. captureElem.style.display = "none";
  484. document.body.appendChild(captureElem);
  485.  
  486. // This is to make sure callers don't get confused by having
  487. // our blocking element as the target
  488. captureElem.addEventListener('contextmenu', $$$core$util$events$$_captureProxy);
  489.  
  490. captureElem.addEventListener('mousemove', $$$core$util$events$$_captureProxy);
  491. captureElem.addEventListener('mouseup', $$$core$util$events$$_captureProxy);
  492. }
  493.  
  494. $$$core$util$events$$_captureElem = elem;
  495. $$$core$util$events$$_captureIndex++;
  496.  
  497. // Track cursor and get initial cursor
  498. $$$core$util$events$$_captureObserver.observe(elem, {attributes:true});
  499. $$$core$util$events$$_captureElemChanged();
  500.  
  501. captureElem.style.display = "";
  502.  
  503. // We listen to events on window in order to keep tracking if it
  504. // happens to leave the viewport
  505. window.addEventListener('mousemove', $$$core$util$events$$_captureProxy);
  506. window.addEventListener('mouseup', $$$core$util$events$$_captureProxy);
  507. }
  508. }
  509.  
  510. function $$$core$util$events$$releaseCapture() {
  511. if (document.releaseCapture) {
  512.  
  513. document.releaseCapture();
  514.  
  515. } else {
  516. if (!$$$core$util$events$$_captureElem) {
  517. return;
  518. }
  519.  
  520. // There might be events already queued, so we need to wait for
  521. // them to flush. E.g. contextmenu in Microsoft Edge
  522. window.setTimeout(function(expected) {
  523. // Only clear it if it's the expected grab (i.e. no one
  524. // else has initiated a new grab)
  525. if ($$$core$util$events$$_captureIndex === expected) {
  526. $$$core$util$events$$_captureElem = null;
  527. }
  528. }, 0, $$$core$util$events$$_captureIndex);
  529.  
  530. $$$core$util$events$$_captureObserver.disconnect();
  531.  
  532. var captureElem = document.getElementById("noVNC_mouse_capture_elem");
  533. captureElem.style.display = "none";
  534.  
  535. window.removeEventListener('mousemove', $$$core$util$events$$_captureProxy);
  536. window.removeEventListener('mouseup', $$$core$util$events$$_captureProxy);
  537. }
  538. }
  539.  
  540. var $$$core$input$keysym$$default = {
  541. XK_VoidSymbol: 0xffffff,
  542.  
  543. /* Void symbol */
  544.  
  545. XK_BackSpace: 0xff08,
  546.  
  547. /* Back space, back char */
  548. XK_Tab: 0xff09,
  549.  
  550. XK_Linefeed: 0xff0a,
  551.  
  552. /* Linefeed, LF */
  553. XK_Clear: 0xff0b,
  554.  
  555. XK_Return: 0xff0d,
  556.  
  557. /* Return, enter */
  558. XK_Pause: 0xff13,
  559.  
  560. /* Pause, hold */
  561. XK_Scroll_Lock: 0xff14,
  562.  
  563. XK_Sys_Req: 0xff15,
  564. XK_Escape: 0xff1b,
  565. XK_Delete: 0xffff,
  566.  
  567. /* Delete, rubout */
  568.  
  569. /* International & multi-key character composition */
  570.  
  571. XK_Multi_key: 0xff20,
  572.  
  573. /* Multi-key character compose */
  574. XK_Codeinput: 0xff37,
  575.  
  576. XK_SingleCandidate: 0xff3c,
  577. XK_MultipleCandidate: 0xff3d,
  578. XK_PreviousCandidate: 0xff3e,
  579.  
  580. /* Japanese keyboard support */
  581.  
  582. XK_Kanji: 0xff21,
  583.  
  584. /* Kanji, Kanji convert */
  585. XK_Muhenkan: 0xff22,
  586.  
  587. /* Cancel Conversion */
  588. XK_Henkan_Mode: 0xff23,
  589.  
  590. /* Start/Stop Conversion */
  591. XK_Henkan: 0xff23,
  592.  
  593. /* Alias for Henkan_Mode */
  594. XK_Romaji: 0xff24,
  595.  
  596. /* to Romaji */
  597. XK_Hiragana: 0xff25,
  598.  
  599. /* to Hiragana */
  600. XK_Katakana: 0xff26,
  601.  
  602. /* to Katakana */
  603. XK_Hiragana_Katakana: 0xff27,
  604.  
  605. /* Hiragana/Katakana toggle */
  606. XK_Zenkaku: 0xff28,
  607.  
  608. /* to Zenkaku */
  609. XK_Hankaku: 0xff29,
  610.  
  611. /* to Hankaku */
  612. XK_Zenkaku_Hankaku: 0xff2a,
  613.  
  614. /* Zenkaku/Hankaku toggle */
  615. XK_Touroku: 0xff2b,
  616.  
  617. /* Add to Dictionary */
  618. XK_Massyo: 0xff2c,
  619.  
  620. /* Delete from Dictionary */
  621. XK_Kana_Lock: 0xff2d,
  622.  
  623. /* Kana Lock */
  624. XK_Kana_Shift: 0xff2e,
  625.  
  626. /* Kana Shift */
  627. XK_Eisu_Shift: 0xff2f,
  628.  
  629. /* Alphanumeric Shift */
  630. XK_Eisu_toggle: 0xff30,
  631.  
  632. /* Alphanumeric toggle */
  633. XK_Kanji_Bangou: 0xff37,
  634.  
  635. /* Codeinput */
  636. XK_Zen_Koho: 0xff3d,
  637.  
  638. /* Multiple/All Candidate(s) */
  639. XK_Mae_Koho: 0xff3e,
  640.  
  641. /* Previous Candidate */
  642.  
  643. /* Cursor control & motion */
  644.  
  645. XK_Home: 0xff50,
  646.  
  647. XK_Left: 0xff51,
  648.  
  649. /* Move left, left arrow */
  650. XK_Up: 0xff52,
  651.  
  652. /* Move up, up arrow */
  653. XK_Right: 0xff53,
  654.  
  655. /* Move right, right arrow */
  656. XK_Down: 0xff54,
  657.  
  658. /* Move down, down arrow */
  659. XK_Prior: 0xff55,
  660.  
  661. /* Prior, previous */
  662. XK_Page_Up: 0xff55,
  663.  
  664. XK_Next: 0xff56,
  665.  
  666. /* Next */
  667. XK_Page_Down: 0xff56,
  668.  
  669. XK_End: 0xff57,
  670.  
  671. /* EOL */
  672. XK_Begin: 0xff58,
  673.  
  674. /* BOL */
  675.  
  676.  
  677. /* Misc functions */
  678.  
  679. XK_Select: 0xff60,
  680.  
  681. /* Select, mark */
  682. XK_Print: 0xff61,
  683.  
  684. XK_Execute: 0xff62,
  685.  
  686. /* Execute, run, do */
  687. XK_Insert: 0xff63,
  688.  
  689. /* Insert, insert here */
  690. XK_Undo: 0xff65,
  691.  
  692. XK_Redo: 0xff66,
  693.  
  694. /* Redo, again */
  695. XK_Menu: 0xff67,
  696.  
  697. XK_Find: 0xff68,
  698.  
  699. /* Find, search */
  700. XK_Cancel: 0xff69,
  701.  
  702. /* Cancel, stop, abort, exit */
  703. XK_Help: 0xff6a,
  704.  
  705. /* Help */
  706. XK_Break: 0xff6b,
  707.  
  708. XK_Mode_switch: 0xff7e,
  709.  
  710. /* Character set switch */
  711. XK_script_switch: 0xff7e,
  712.  
  713. /* Alias for mode_switch */
  714. XK_Num_Lock: 0xff7f,
  715.  
  716. /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
  717.  
  718. XK_KP_Space: 0xff80,
  719.  
  720. /* Space */
  721. XK_KP_Tab: 0xff89,
  722.  
  723. XK_KP_Enter: 0xff8d,
  724.  
  725. /* Enter */
  726. XK_KP_F1: 0xff91,
  727.  
  728. /* PF1, KP_A, ... */
  729. XK_KP_F2: 0xff92,
  730.  
  731. XK_KP_F3: 0xff93,
  732. XK_KP_F4: 0xff94,
  733. XK_KP_Home: 0xff95,
  734. XK_KP_Left: 0xff96,
  735. XK_KP_Up: 0xff97,
  736. XK_KP_Right: 0xff98,
  737. XK_KP_Down: 0xff99,
  738. XK_KP_Prior: 0xff9a,
  739. XK_KP_Page_Up: 0xff9a,
  740. XK_KP_Next: 0xff9b,
  741. XK_KP_Page_Down: 0xff9b,
  742. XK_KP_End: 0xff9c,
  743. XK_KP_Begin: 0xff9d,
  744. XK_KP_Insert: 0xff9e,
  745. XK_KP_Delete: 0xff9f,
  746. XK_KP_Equal: 0xffbd,
  747.  
  748. /* Equals */
  749. XK_KP_Multiply: 0xffaa,
  750.  
  751. XK_KP_Add: 0xffab,
  752. XK_KP_Separator: 0xffac,
  753.  
  754. /* Separator, often comma */
  755. XK_KP_Subtract: 0xffad,
  756.  
  757. XK_KP_Decimal: 0xffae,
  758. XK_KP_Divide: 0xffaf,
  759. XK_KP_0: 0xffb0,
  760. XK_KP_1: 0xffb1,
  761. XK_KP_2: 0xffb2,
  762. XK_KP_3: 0xffb3,
  763. XK_KP_4: 0xffb4,
  764. XK_KP_5: 0xffb5,
  765. XK_KP_6: 0xffb6,
  766. XK_KP_7: 0xffb7,
  767. XK_KP_8: 0xffb8,
  768. XK_KP_9: 0xffb9,
  769.  
  770. /*
  771. * Auxiliary functions; note the duplicate definitions for left and right
  772. * function keys; Sun keyboards and a few other manufacturers have such
  773. * function key groups on the left and/or right sides of the keyboard.
  774. * We've not found a keyboard with more than 35 function keys total.
  775. */
  776.  
  777. XK_F1: 0xffbe,
  778.  
  779. XK_F2: 0xffbf,
  780. XK_F3: 0xffc0,
  781. XK_F4: 0xffc1,
  782. XK_F5: 0xffc2,
  783. XK_F6: 0xffc3,
  784. XK_F7: 0xffc4,
  785. XK_F8: 0xffc5,
  786. XK_F9: 0xffc6,
  787. XK_F10: 0xffc7,
  788. XK_F11: 0xffc8,
  789. XK_L1: 0xffc8,
  790. XK_F12: 0xffc9,
  791. XK_L2: 0xffc9,
  792. XK_F13: 0xffca,
  793. XK_L3: 0xffca,
  794. XK_F14: 0xffcb,
  795. XK_L4: 0xffcb,
  796. XK_F15: 0xffcc,
  797. XK_L5: 0xffcc,
  798. XK_F16: 0xffcd,
  799. XK_L6: 0xffcd,
  800. XK_F17: 0xffce,
  801. XK_L7: 0xffce,
  802. XK_F18: 0xffcf,
  803. XK_L8: 0xffcf,
  804. XK_F19: 0xffd0,
  805. XK_L9: 0xffd0,
  806. XK_F20: 0xffd1,
  807. XK_L10: 0xffd1,
  808. XK_F21: 0xffd2,
  809. XK_R1: 0xffd2,
  810. XK_F22: 0xffd3,
  811. XK_R2: 0xffd3,
  812. XK_F23: 0xffd4,
  813. XK_R3: 0xffd4,
  814. XK_F24: 0xffd5,
  815. XK_R4: 0xffd5,
  816. XK_F25: 0xffd6,
  817. XK_R5: 0xffd6,
  818. XK_F26: 0xffd7,
  819. XK_R6: 0xffd7,
  820. XK_F27: 0xffd8,
  821. XK_R7: 0xffd8,
  822. XK_F28: 0xffd9,
  823. XK_R8: 0xffd9,
  824. XK_F29: 0xffda,
  825. XK_R9: 0xffda,
  826. XK_F30: 0xffdb,
  827. XK_R10: 0xffdb,
  828. XK_F31: 0xffdc,
  829. XK_R11: 0xffdc,
  830. XK_F32: 0xffdd,
  831. XK_R12: 0xffdd,
  832. XK_F33: 0xffde,
  833. XK_R13: 0xffde,
  834. XK_F34: 0xffdf,
  835. XK_R14: 0xffdf,
  836. XK_F35: 0xffe0,
  837. XK_R15: 0xffe0,
  838.  
  839. /* Modifiers */
  840.  
  841. XK_Shift_L: 0xffe1,
  842.  
  843. /* Left shift */
  844. XK_Shift_R: 0xffe2,
  845.  
  846. /* Right shift */
  847. XK_Control_L: 0xffe3,
  848.  
  849. /* Left control */
  850. XK_Control_R: 0xffe4,
  851.  
  852. /* Right control */
  853. XK_Caps_Lock: 0xffe5,
  854.  
  855. /* Caps lock */
  856. XK_Shift_Lock: 0xffe6,
  857.  
  858. /* Shift lock */
  859.  
  860. XK_Meta_L: 0xffe7,
  861.  
  862. /* Left meta */
  863. XK_Meta_R: 0xffe8,
  864.  
  865. /* Right meta */
  866. XK_Alt_L: 0xffe9,
  867.  
  868. /* Left alt */
  869. XK_Alt_R: 0xffea,
  870.  
  871. /* Right alt */
  872. XK_Super_L: 0xffeb,
  873.  
  874. /* Left super */
  875. XK_Super_R: 0xffec,
  876.  
  877. /* Right super */
  878. XK_Hyper_L: 0xffed,
  879.  
  880. /* Left hyper */
  881. XK_Hyper_R: 0xffee,
  882.  
  883. /* Right hyper */
  884.  
  885. /*
  886. * Keyboard (XKB) Extension function and modifier keys
  887. * (from Appendix C of "The X Keyboard Extension: Protocol Specification")
  888. * Byte 3 = 0xfe
  889. */
  890.  
  891. XK_ISO_Level3_Shift: 0xfe03,
  892.  
  893. /* AltGr */
  894. XK_ISO_Next_Group: 0xfe08,
  895.  
  896. XK_ISO_Prev_Group: 0xfe0a,
  897. XK_ISO_First_Group: 0xfe0c,
  898. XK_ISO_Last_Group: 0xfe0e,
  899.  
  900. /*
  901. * Latin 1
  902. * (ISO/IEC 8859-1: Unicode U+0020..U+00FF)
  903. * Byte 3: 0
  904. */
  905.  
  906. XK_space: 0x0020,
  907.  
  908. /* U+0020 SPACE */
  909. XK_exclam: 0x0021,
  910.  
  911. /* U+0021 EXCLAMATION MARK */
  912. XK_quotedbl: 0x0022,
  913.  
  914. /* U+0022 QUOTATION MARK */
  915. XK_numbersign: 0x0023,
  916.  
  917. /* U+0023 NUMBER SIGN */
  918. XK_dollar: 0x0024,
  919.  
  920. /* U+0024 DOLLAR SIGN */
  921. XK_percent: 0x0025,
  922.  
  923. /* U+0025 PERCENT SIGN */
  924. XK_ampersand: 0x0026,
  925.  
  926. /* U+0026 AMPERSAND */
  927. XK_apostrophe: 0x0027,
  928.  
  929. /* U+0027 APOSTROPHE */
  930. XK_quoteright: 0x0027,
  931.  
  932. /* deprecated */
  933. XK_parenleft: 0x0028,
  934.  
  935. /* U+0028 LEFT PARENTHESIS */
  936. XK_parenright: 0x0029,
  937.  
  938. /* U+0029 RIGHT PARENTHESIS */
  939. XK_asterisk: 0x002a,
  940.  
  941. /* U+002A ASTERISK */
  942. XK_plus: 0x002b,
  943.  
  944. /* U+002B PLUS SIGN */
  945. XK_comma: 0x002c,
  946.  
  947. /* U+002C COMMA */
  948. XK_minus: 0x002d,
  949.  
  950. /* U+002D HYPHEN-MINUS */
  951. XK_period: 0x002e,
  952.  
  953. /* U+002E FULL STOP */
  954. XK_slash: 0x002f,
  955.  
  956. /* U+002F SOLIDUS */
  957. XK_0: 0x0030,
  958.  
  959. /* U+0030 DIGIT ZERO */
  960. XK_1: 0x0031,
  961.  
  962. /* U+0031 DIGIT ONE */
  963. XK_2: 0x0032,
  964.  
  965. /* U+0032 DIGIT TWO */
  966. XK_3: 0x0033,
  967.  
  968. /* U+0033 DIGIT THREE */
  969. XK_4: 0x0034,
  970.  
  971. /* U+0034 DIGIT FOUR */
  972. XK_5: 0x0035,
  973.  
  974. /* U+0035 DIGIT FIVE */
  975. XK_6: 0x0036,
  976.  
  977. /* U+0036 DIGIT SIX */
  978. XK_7: 0x0037,
  979.  
  980. /* U+0037 DIGIT SEVEN */
  981. XK_8: 0x0038,
  982.  
  983. /* U+0038 DIGIT EIGHT */
  984. XK_9: 0x0039,
  985.  
  986. /* U+0039 DIGIT NINE */
  987. XK_colon: 0x003a,
  988.  
  989. /* U+003A COLON */
  990. XK_semicolon: 0x003b,
  991.  
  992. /* U+003B SEMICOLON */
  993. XK_less: 0x003c,
  994.  
  995. /* U+003C LESS-THAN SIGN */
  996. XK_equal: 0x003d,
  997.  
  998. /* U+003D EQUALS SIGN */
  999. XK_greater: 0x003e,
  1000.  
  1001. /* U+003E GREATER-THAN SIGN */
  1002. XK_question: 0x003f,
  1003.  
  1004. /* U+003F QUESTION MARK */
  1005. XK_at: 0x0040,
  1006.  
  1007. /* U+0040 COMMERCIAL AT */
  1008. XK_A: 0x0041,
  1009.  
  1010. /* U+0041 LATIN CAPITAL LETTER A */
  1011. XK_B: 0x0042,
  1012.  
  1013. /* U+0042 LATIN CAPITAL LETTER B */
  1014. XK_C: 0x0043,
  1015.  
  1016. /* U+0043 LATIN CAPITAL LETTER C */
  1017. XK_D: 0x0044,
  1018.  
  1019. /* U+0044 LATIN CAPITAL LETTER D */
  1020. XK_E: 0x0045,
  1021.  
  1022. /* U+0045 LATIN CAPITAL LETTER E */
  1023. XK_F: 0x0046,
  1024.  
  1025. /* U+0046 LATIN CAPITAL LETTER F */
  1026. XK_G: 0x0047,
  1027.  
  1028. /* U+0047 LATIN CAPITAL LETTER G */
  1029. XK_H: 0x0048,
  1030.  
  1031. /* U+0048 LATIN CAPITAL LETTER H */
  1032. XK_I: 0x0049,
  1033.  
  1034. /* U+0049 LATIN CAPITAL LETTER I */
  1035. XK_J: 0x004a,
  1036.  
  1037. /* U+004A LATIN CAPITAL LETTER J */
  1038. XK_K: 0x004b,
  1039.  
  1040. /* U+004B LATIN CAPITAL LETTER K */
  1041. XK_L: 0x004c,
  1042.  
  1043. /* U+004C LATIN CAPITAL LETTER L */
  1044. XK_M: 0x004d,
  1045.  
  1046. /* U+004D LATIN CAPITAL LETTER M */
  1047. XK_N: 0x004e,
  1048.  
  1049. /* U+004E LATIN CAPITAL LETTER N */
  1050. XK_O: 0x004f,
  1051.  
  1052. /* U+004F LATIN CAPITAL LETTER O */
  1053. XK_P: 0x0050,
  1054.  
  1055. /* U+0050 LATIN CAPITAL LETTER P */
  1056. XK_Q: 0x0051,
  1057.  
  1058. /* U+0051 LATIN CAPITAL LETTER Q */
  1059. XK_R: 0x0052,
  1060.  
  1061. /* U+0052 LATIN CAPITAL LETTER R */
  1062. XK_S: 0x0053,
  1063.  
  1064. /* U+0053 LATIN CAPITAL LETTER S */
  1065. XK_T: 0x0054,
  1066.  
  1067. /* U+0054 LATIN CAPITAL LETTER T */
  1068. XK_U: 0x0055,
  1069.  
  1070. /* U+0055 LATIN CAPITAL LETTER U */
  1071. XK_V: 0x0056,
  1072.  
  1073. /* U+0056 LATIN CAPITAL LETTER V */
  1074. XK_W: 0x0057,
  1075.  
  1076. /* U+0057 LATIN CAPITAL LETTER W */
  1077. XK_X: 0x0058,
  1078.  
  1079. /* U+0058 LATIN CAPITAL LETTER X */
  1080. XK_Y: 0x0059,
  1081.  
  1082. /* U+0059 LATIN CAPITAL LETTER Y */
  1083. XK_Z: 0x005a,
  1084.  
  1085. /* U+005A LATIN CAPITAL LETTER Z */
  1086. XK_bracketleft: 0x005b,
  1087.  
  1088. /* U+005B LEFT SQUARE BRACKET */
  1089. XK_backslash: 0x005c,
  1090.  
  1091. /* U+005C REVERSE SOLIDUS */
  1092. XK_bracketright: 0x005d,
  1093.  
  1094. /* U+005D RIGHT SQUARE BRACKET */
  1095. XK_asciicircum: 0x005e,
  1096.  
  1097. /* U+005E CIRCUMFLEX ACCENT */
  1098. XK_underscore: 0x005f,
  1099.  
  1100. /* U+005F LOW LINE */
  1101. XK_grave: 0x0060,
  1102.  
  1103. /* U+0060 GRAVE ACCENT */
  1104. XK_quoteleft: 0x0060,
  1105.  
  1106. /* deprecated */
  1107. XK_a: 0x0061,
  1108.  
  1109. /* U+0061 LATIN SMALL LETTER A */
  1110. XK_b: 0x0062,
  1111.  
  1112. /* U+0062 LATIN SMALL LETTER B */
  1113. XK_c: 0x0063,
  1114.  
  1115. /* U+0063 LATIN SMALL LETTER C */
  1116. XK_d: 0x0064,
  1117.  
  1118. /* U+0064 LATIN SMALL LETTER D */
  1119. XK_e: 0x0065,
  1120.  
  1121. /* U+0065 LATIN SMALL LETTER E */
  1122. XK_f: 0x0066,
  1123.  
  1124. /* U+0066 LATIN SMALL LETTER F */
  1125. XK_g: 0x0067,
  1126.  
  1127. /* U+0067 LATIN SMALL LETTER G */
  1128. XK_h: 0x0068,
  1129.  
  1130. /* U+0068 LATIN SMALL LETTER H */
  1131. XK_i: 0x0069,
  1132.  
  1133. /* U+0069 LATIN SMALL LETTER I */
  1134. XK_j: 0x006a,
  1135.  
  1136. /* U+006A LATIN SMALL LETTER J */
  1137. XK_k: 0x006b,
  1138.  
  1139. /* U+006B LATIN SMALL LETTER K */
  1140. XK_l: 0x006c,
  1141.  
  1142. /* U+006C LATIN SMALL LETTER L */
  1143. XK_m: 0x006d,
  1144.  
  1145. /* U+006D LATIN SMALL LETTER M */
  1146. XK_n: 0x006e,
  1147.  
  1148. /* U+006E LATIN SMALL LETTER N */
  1149. XK_o: 0x006f,
  1150.  
  1151. /* U+006F LATIN SMALL LETTER O */
  1152. XK_p: 0x0070,
  1153.  
  1154. /* U+0070 LATIN SMALL LETTER P */
  1155. XK_q: 0x0071,
  1156.  
  1157. /* U+0071 LATIN SMALL LETTER Q */
  1158. XK_r: 0x0072,
  1159.  
  1160. /* U+0072 LATIN SMALL LETTER R */
  1161. XK_s: 0x0073,
  1162.  
  1163. /* U+0073 LATIN SMALL LETTER S */
  1164. XK_t: 0x0074,
  1165.  
  1166. /* U+0074 LATIN SMALL LETTER T */
  1167. XK_u: 0x0075,
  1168.  
  1169. /* U+0075 LATIN SMALL LETTER U */
  1170. XK_v: 0x0076,
  1171.  
  1172. /* U+0076 LATIN SMALL LETTER V */
  1173. XK_w: 0x0077,
  1174.  
  1175. /* U+0077 LATIN SMALL LETTER W */
  1176. XK_x: 0x0078,
  1177.  
  1178. /* U+0078 LATIN SMALL LETTER X */
  1179. XK_y: 0x0079,
  1180.  
  1181. /* U+0079 LATIN SMALL LETTER Y */
  1182. XK_z: 0x007a,
  1183.  
  1184. /* U+007A LATIN SMALL LETTER Z */
  1185. XK_braceleft: 0x007b,
  1186.  
  1187. /* U+007B LEFT CURLY BRACKET */
  1188. XK_bar: 0x007c,
  1189.  
  1190. /* U+007C VERTICAL LINE */
  1191. XK_braceright: 0x007d,
  1192.  
  1193. /* U+007D RIGHT CURLY BRACKET */
  1194. XK_asciitilde: 0x007e,
  1195.  
  1196. /* U+007E TILDE */
  1197.  
  1198. XK_nobreakspace: 0x00a0,
  1199.  
  1200. /* U+00A0 NO-BREAK SPACE */
  1201. XK_exclamdown: 0x00a1,
  1202.  
  1203. /* U+00A1 INVERTED EXCLAMATION MARK */
  1204. XK_cent: 0x00a2,
  1205.  
  1206. /* U+00A2 CENT SIGN */
  1207. XK_sterling: 0x00a3,
  1208.  
  1209. /* U+00A3 POUND SIGN */
  1210. XK_currency: 0x00a4,
  1211.  
  1212. /* U+00A4 CURRENCY SIGN */
  1213. XK_yen: 0x00a5,
  1214.  
  1215. /* U+00A5 YEN SIGN */
  1216. XK_brokenbar: 0x00a6,
  1217.  
  1218. /* U+00A6 BROKEN BAR */
  1219. XK_section: 0x00a7,
  1220.  
  1221. /* U+00A7 SECTION SIGN */
  1222. XK_diaeresis: 0x00a8,
  1223.  
  1224. /* U+00A8 DIAERESIS */
  1225. XK_copyright: 0x00a9,
  1226.  
  1227. /* U+00A9 COPYRIGHT SIGN */
  1228. XK_ordfeminine: 0x00aa,
  1229.  
  1230. /* U+00AA FEMININE ORDINAL INDICATOR */
  1231. XK_guillemotleft: 0x00ab,
  1232.  
  1233. /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
  1234. XK_notsign: 0x00ac,
  1235.  
  1236. /* U+00AC NOT SIGN */
  1237. XK_hyphen: 0x00ad,
  1238.  
  1239. /* U+00AD SOFT HYPHEN */
  1240. XK_registered: 0x00ae,
  1241.  
  1242. /* U+00AE REGISTERED SIGN */
  1243. XK_macron: 0x00af,
  1244.  
  1245. /* U+00AF MACRON */
  1246. XK_degree: 0x00b0,
  1247.  
  1248. /* U+00B0 DEGREE SIGN */
  1249. XK_plusminus: 0x00b1,
  1250.  
  1251. /* U+00B1 PLUS-MINUS SIGN */
  1252. XK_twosuperior: 0x00b2,
  1253.  
  1254. /* U+00B2 SUPERSCRIPT TWO */
  1255. XK_threesuperior: 0x00b3,
  1256.  
  1257. /* U+00B3 SUPERSCRIPT THREE */
  1258. XK_acute: 0x00b4,
  1259.  
  1260. /* U+00B4 ACUTE ACCENT */
  1261. XK_mu: 0x00b5,
  1262.  
  1263. /* U+00B5 MICRO SIGN */
  1264. XK_paragraph: 0x00b6,
  1265.  
  1266. /* U+00B6 PILCROW SIGN */
  1267. XK_periodcentered: 0x00b7,
  1268.  
  1269. /* U+00B7 MIDDLE DOT */
  1270. XK_cedilla: 0x00b8,
  1271.  
  1272. /* U+00B8 CEDILLA */
  1273. XK_onesuperior: 0x00b9,
  1274.  
  1275. /* U+00B9 SUPERSCRIPT ONE */
  1276. XK_masculine: 0x00ba,
  1277.  
  1278. /* U+00BA MASCULINE ORDINAL INDICATOR */
  1279. XK_guillemotright: 0x00bb,
  1280.  
  1281. /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
  1282. XK_onequarter: 0x00bc,
  1283.  
  1284. /* U+00BC VULGAR FRACTION ONE QUARTER */
  1285. XK_onehalf: 0x00bd,
  1286.  
  1287. /* U+00BD VULGAR FRACTION ONE HALF */
  1288. XK_threequarters: 0x00be,
  1289.  
  1290. /* U+00BE VULGAR FRACTION THREE QUARTERS */
  1291. XK_questiondown: 0x00bf,
  1292.  
  1293. /* U+00BF INVERTED QUESTION MARK */
  1294. XK_Agrave: 0x00c0,
  1295.  
  1296. /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */
  1297. XK_Aacute: 0x00c1,
  1298.  
  1299. /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */
  1300. XK_Acircumflex: 0x00c2,
  1301.  
  1302. /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
  1303. XK_Atilde: 0x00c3,
  1304.  
  1305. /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */
  1306. XK_Adiaeresis: 0x00c4,
  1307.  
  1308. /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */
  1309. XK_Aring: 0x00c5,
  1310.  
  1311. /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */
  1312. XK_AE: 0x00c6,
  1313.  
  1314. /* U+00C6 LATIN CAPITAL LETTER AE */
  1315. XK_Ccedilla: 0x00c7,
  1316.  
  1317. /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */
  1318. XK_Egrave: 0x00c8,
  1319.  
  1320. /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */
  1321. XK_Eacute: 0x00c9,
  1322.  
  1323. /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
  1324. XK_Ecircumflex: 0x00ca,
  1325.  
  1326. /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
  1327. XK_Ediaeresis: 0x00cb,
  1328.  
  1329. /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */
  1330. XK_Igrave: 0x00cc,
  1331.  
  1332. /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */
  1333. XK_Iacute: 0x00cd,
  1334.  
  1335. /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */
  1336. XK_Icircumflex: 0x00ce,
  1337.  
  1338. /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
  1339. XK_Idiaeresis: 0x00cf,
  1340.  
  1341. /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */
  1342. XK_ETH: 0x00d0,
  1343.  
  1344. /* U+00D0 LATIN CAPITAL LETTER ETH */
  1345. XK_Eth: 0x00d0,
  1346.  
  1347. /* deprecated */
  1348. XK_Ntilde: 0x00d1,
  1349.  
  1350. /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */
  1351. XK_Ograve: 0x00d2,
  1352.  
  1353. /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */
  1354. XK_Oacute: 0x00d3,
  1355.  
  1356. /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */
  1357. XK_Ocircumflex: 0x00d4,
  1358.  
  1359. /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
  1360. XK_Otilde: 0x00d5,
  1361.  
  1362. /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */
  1363. XK_Odiaeresis: 0x00d6,
  1364.  
  1365. /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */
  1366. XK_multiply: 0x00d7,
  1367.  
  1368. /* U+00D7 MULTIPLICATION SIGN */
  1369. XK_Oslash: 0x00d8,
  1370.  
  1371. /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
  1372. XK_Ooblique: 0x00d8,
  1373.  
  1374. /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
  1375. XK_Ugrave: 0x00d9,
  1376.  
  1377. /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */
  1378. XK_Uacute: 0x00da,
  1379.  
  1380. /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */
  1381. XK_Ucircumflex: 0x00db,
  1382.  
  1383. /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
  1384. XK_Udiaeresis: 0x00dc,
  1385.  
  1386. /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */
  1387. XK_Yacute: 0x00dd,
  1388.  
  1389. /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */
  1390. XK_THORN: 0x00de,
  1391.  
  1392. /* U+00DE LATIN CAPITAL LETTER THORN */
  1393. XK_Thorn: 0x00de,
  1394.  
  1395. /* deprecated */
  1396. XK_ssharp: 0x00df,
  1397.  
  1398. /* U+00DF LATIN SMALL LETTER SHARP S */
  1399. XK_agrave: 0x00e0,
  1400.  
  1401. /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */
  1402. XK_aacute: 0x00e1,
  1403.  
  1404. /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */
  1405. XK_acircumflex: 0x00e2,
  1406.  
  1407. /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */
  1408. XK_atilde: 0x00e3,
  1409.  
  1410. /* U+00E3 LATIN SMALL LETTER A WITH TILDE */
  1411. XK_adiaeresis: 0x00e4,
  1412.  
  1413. /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */
  1414. XK_aring: 0x00e5,
  1415.  
  1416. /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */
  1417. XK_ae: 0x00e6,
  1418.  
  1419. /* U+00E6 LATIN SMALL LETTER AE */
  1420. XK_ccedilla: 0x00e7,
  1421.  
  1422. /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */
  1423. XK_egrave: 0x00e8,
  1424.  
  1425. /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */
  1426. XK_eacute: 0x00e9,
  1427.  
  1428. /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
  1429. XK_ecircumflex: 0x00ea,
  1430.  
  1431. /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */
  1432. XK_ediaeresis: 0x00eb,
  1433.  
  1434. /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */
  1435. XK_igrave: 0x00ec,
  1436.  
  1437. /* U+00EC LATIN SMALL LETTER I WITH GRAVE */
  1438. XK_iacute: 0x00ed,
  1439.  
  1440. /* U+00ED LATIN SMALL LETTER I WITH ACUTE */
  1441. XK_icircumflex: 0x00ee,
  1442.  
  1443. /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */
  1444. XK_idiaeresis: 0x00ef,
  1445.  
  1446. /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */
  1447. XK_eth: 0x00f0,
  1448.  
  1449. /* U+00F0 LATIN SMALL LETTER ETH */
  1450. XK_ntilde: 0x00f1,
  1451.  
  1452. /* U+00F1 LATIN SMALL LETTER N WITH TILDE */
  1453. XK_ograve: 0x00f2,
  1454.  
  1455. /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */
  1456. XK_oacute: 0x00f3,
  1457.  
  1458. /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */
  1459. XK_ocircumflex: 0x00f4,
  1460.  
  1461. /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */
  1462. XK_otilde: 0x00f5,
  1463.  
  1464. /* U+00F5 LATIN SMALL LETTER O WITH TILDE */
  1465. XK_odiaeresis: 0x00f6,
  1466.  
  1467. /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */
  1468. XK_division: 0x00f7,
  1469.  
  1470. /* U+00F7 DIVISION SIGN */
  1471. XK_oslash: 0x00f8,
  1472.  
  1473. /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
  1474. XK_ooblique: 0x00f8,
  1475.  
  1476. /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
  1477. XK_ugrave: 0x00f9,
  1478.  
  1479. /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */
  1480. XK_uacute: 0x00fa,
  1481.  
  1482. /* U+00FA LATIN SMALL LETTER U WITH ACUTE */
  1483. XK_ucircumflex: 0x00fb,
  1484.  
  1485. /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */
  1486. XK_udiaeresis: 0x00fc,
  1487.  
  1488. /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */
  1489. XK_yacute: 0x00fd,
  1490.  
  1491. /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */
  1492. XK_thorn: 0x00fe,
  1493.  
  1494. /* U+00FE LATIN SMALL LETTER THORN */
  1495. XK_ydiaeresis: 0x00ff,
  1496.  
  1497. /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
  1498.  
  1499. /*
  1500. * Korean
  1501. * Byte 3 = 0x0e
  1502. */
  1503.  
  1504. XK_Hangul: 0xff31,
  1505.  
  1506. /* Hangul start/stop(toggle) */
  1507. XK_Hangul_Hanja: 0xff34,
  1508.  
  1509. /* Start Hangul->Hanja Conversion */
  1510. XK_Hangul_Jeonja: 0xff38,
  1511.  
  1512. /* Jeonja mode */
  1513.  
  1514. /*
  1515. * XFree86 vendor specific keysyms.
  1516. *
  1517. * The XFree86 keysym range is 0x10080001 - 0x1008FFFF.
  1518. */
  1519.  
  1520. XF86XK_ModeLock: 0x1008FF01,
  1521.  
  1522. XF86XK_MonBrightnessUp: 0x1008FF02,
  1523. XF86XK_MonBrightnessDown: 0x1008FF03,
  1524. XF86XK_KbdLightOnOff: 0x1008FF04,
  1525. XF86XK_KbdBrightnessUp: 0x1008FF05,
  1526. XF86XK_KbdBrightnessDown: 0x1008FF06,
  1527. XF86XK_Standby: 0x1008FF10,
  1528. XF86XK_AudioLowerVolume: 0x1008FF11,
  1529. XF86XK_AudioMute: 0x1008FF12,
  1530. XF86XK_AudioRaiseVolume: 0x1008FF13,
  1531. XF86XK_AudioPlay: 0x1008FF14,
  1532. XF86XK_AudioStop: 0x1008FF15,
  1533. XF86XK_AudioPrev: 0x1008FF16,
  1534. XF86XK_AudioNext: 0x1008FF17,
  1535. XF86XK_HomePage: 0x1008FF18,
  1536. XF86XK_Mail: 0x1008FF19,
  1537. XF86XK_Start: 0x1008FF1A,
  1538. XF86XK_Search: 0x1008FF1B,
  1539. XF86XK_AudioRecord: 0x1008FF1C,
  1540. XF86XK_Calculator: 0x1008FF1D,
  1541. XF86XK_Memo: 0x1008FF1E,
  1542. XF86XK_ToDoList: 0x1008FF1F,
  1543. XF86XK_Calendar: 0x1008FF20,
  1544. XF86XK_PowerDown: 0x1008FF21,
  1545. XF86XK_ContrastAdjust: 0x1008FF22,
  1546. XF86XK_RockerUp: 0x1008FF23,
  1547. XF86XK_RockerDown: 0x1008FF24,
  1548. XF86XK_RockerEnter: 0x1008FF25,
  1549. XF86XK_Back: 0x1008FF26,
  1550. XF86XK_Forward: 0x1008FF27,
  1551. XF86XK_Stop: 0x1008FF28,
  1552. XF86XK_Refresh: 0x1008FF29,
  1553. XF86XK_PowerOff: 0x1008FF2A,
  1554. XF86XK_WakeUp: 0x1008FF2B,
  1555. XF86XK_Eject: 0x1008FF2C,
  1556. XF86XK_ScreenSaver: 0x1008FF2D,
  1557. XF86XK_WWW: 0x1008FF2E,
  1558. XF86XK_Sleep: 0x1008FF2F,
  1559. XF86XK_Favorites: 0x1008FF30,
  1560. XF86XK_AudioPause: 0x1008FF31,
  1561. XF86XK_AudioMedia: 0x1008FF32,
  1562. XF86XK_MyComputer: 0x1008FF33,
  1563. XF86XK_VendorHome: 0x1008FF34,
  1564. XF86XK_LightBulb: 0x1008FF35,
  1565. XF86XK_Shop: 0x1008FF36,
  1566. XF86XK_History: 0x1008FF37,
  1567. XF86XK_OpenURL: 0x1008FF38,
  1568. XF86XK_AddFavorite: 0x1008FF39,
  1569. XF86XK_HotLinks: 0x1008FF3A,
  1570. XF86XK_BrightnessAdjust: 0x1008FF3B,
  1571. XF86XK_Finance: 0x1008FF3C,
  1572. XF86XK_Community: 0x1008FF3D,
  1573. XF86XK_AudioRewind: 0x1008FF3E,
  1574. XF86XK_BackForward: 0x1008FF3F,
  1575. XF86XK_Launch0: 0x1008FF40,
  1576. XF86XK_Launch1: 0x1008FF41,
  1577. XF86XK_Launch2: 0x1008FF42,
  1578. XF86XK_Launch3: 0x1008FF43,
  1579. XF86XK_Launch4: 0x1008FF44,
  1580. XF86XK_Launch5: 0x1008FF45,
  1581. XF86XK_Launch6: 0x1008FF46,
  1582. XF86XK_Launch7: 0x1008FF47,
  1583. XF86XK_Launch8: 0x1008FF48,
  1584. XF86XK_Launch9: 0x1008FF49,
  1585. XF86XK_LaunchA: 0x1008FF4A,
  1586. XF86XK_LaunchB: 0x1008FF4B,
  1587. XF86XK_LaunchC: 0x1008FF4C,
  1588. XF86XK_LaunchD: 0x1008FF4D,
  1589. XF86XK_LaunchE: 0x1008FF4E,
  1590. XF86XK_LaunchF: 0x1008FF4F,
  1591. XF86XK_ApplicationLeft: 0x1008FF50,
  1592. XF86XK_ApplicationRight: 0x1008FF51,
  1593. XF86XK_Book: 0x1008FF52,
  1594. XF86XK_CD: 0x1008FF53,
  1595. XF86XK_Calculater: 0x1008FF54,
  1596. XF86XK_Clear: 0x1008FF55,
  1597. XF86XK_Close: 0x1008FF56,
  1598. XF86XK_Copy: 0x1008FF57,
  1599. XF86XK_Cut: 0x1008FF58,
  1600. XF86XK_Display: 0x1008FF59,
  1601. XF86XK_DOS: 0x1008FF5A,
  1602. XF86XK_Documents: 0x1008FF5B,
  1603. XF86XK_Excel: 0x1008FF5C,
  1604. XF86XK_Explorer: 0x1008FF5D,
  1605. XF86XK_Game: 0x1008FF5E,
  1606. XF86XK_Go: 0x1008FF5F,
  1607. XF86XK_iTouch: 0x1008FF60,
  1608. XF86XK_LogOff: 0x1008FF61,
  1609. XF86XK_Market: 0x1008FF62,
  1610. XF86XK_Meeting: 0x1008FF63,
  1611. XF86XK_MenuKB: 0x1008FF65,
  1612. XF86XK_MenuPB: 0x1008FF66,
  1613. XF86XK_MySites: 0x1008FF67,
  1614. XF86XK_New: 0x1008FF68,
  1615. XF86XK_News: 0x1008FF69,
  1616. XF86XK_OfficeHome: 0x1008FF6A,
  1617. XF86XK_Open: 0x1008FF6B,
  1618. XF86XK_Option: 0x1008FF6C,
  1619. XF86XK_Paste: 0x1008FF6D,
  1620. XF86XK_Phone: 0x1008FF6E,
  1621. XF86XK_Q: 0x1008FF70,
  1622. XF86XK_Reply: 0x1008FF72,
  1623. XF86XK_Reload: 0x1008FF73,
  1624. XF86XK_RotateWindows: 0x1008FF74,
  1625. XF86XK_RotationPB: 0x1008FF75,
  1626. XF86XK_RotationKB: 0x1008FF76,
  1627. XF86XK_Save: 0x1008FF77,
  1628. XF86XK_ScrollUp: 0x1008FF78,
  1629. XF86XK_ScrollDown: 0x1008FF79,
  1630. XF86XK_ScrollClick: 0x1008FF7A,
  1631. XF86XK_Send: 0x1008FF7B,
  1632. XF86XK_Spell: 0x1008FF7C,
  1633. XF86XK_SplitScreen: 0x1008FF7D,
  1634. XF86XK_Support: 0x1008FF7E,
  1635. XF86XK_TaskPane: 0x1008FF7F,
  1636. XF86XK_Terminal: 0x1008FF80,
  1637. XF86XK_Tools: 0x1008FF81,
  1638. XF86XK_Travel: 0x1008FF82,
  1639. XF86XK_UserPB: 0x1008FF84,
  1640. XF86XK_User1KB: 0x1008FF85,
  1641. XF86XK_User2KB: 0x1008FF86,
  1642. XF86XK_Video: 0x1008FF87,
  1643. XF86XK_WheelButton: 0x1008FF88,
  1644. XF86XK_Word: 0x1008FF89,
  1645. XF86XK_Xfer: 0x1008FF8A,
  1646. XF86XK_ZoomIn: 0x1008FF8B,
  1647. XF86XK_ZoomOut: 0x1008FF8C,
  1648. XF86XK_Away: 0x1008FF8D,
  1649. XF86XK_Messenger: 0x1008FF8E,
  1650. XF86XK_WebCam: 0x1008FF8F,
  1651. XF86XK_MailForward: 0x1008FF90,
  1652. XF86XK_Pictures: 0x1008FF91,
  1653. XF86XK_Music: 0x1008FF92,
  1654. XF86XK_Battery: 0x1008FF93,
  1655. XF86XK_Bluetooth: 0x1008FF94,
  1656. XF86XK_WLAN: 0x1008FF95,
  1657. XF86XK_UWB: 0x1008FF96,
  1658. XF86XK_AudioForward: 0x1008FF97,
  1659. XF86XK_AudioRepeat: 0x1008FF98,
  1660. XF86XK_AudioRandomPlay: 0x1008FF99,
  1661. XF86XK_Subtitle: 0x1008FF9A,
  1662. XF86XK_AudioCycleTrack: 0x1008FF9B,
  1663. XF86XK_CycleAngle: 0x1008FF9C,
  1664. XF86XK_FrameBack: 0x1008FF9D,
  1665. XF86XK_FrameForward: 0x1008FF9E,
  1666. XF86XK_Time: 0x1008FF9F,
  1667. XF86XK_Select: 0x1008FFA0,
  1668. XF86XK_View: 0x1008FFA1,
  1669. XF86XK_TopMenu: 0x1008FFA2,
  1670. XF86XK_Red: 0x1008FFA3,
  1671. XF86XK_Green: 0x1008FFA4,
  1672. XF86XK_Yellow: 0x1008FFA5,
  1673. XF86XK_Blue: 0x1008FFA6,
  1674. XF86XK_Suspend: 0x1008FFA7,
  1675. XF86XK_Hibernate: 0x1008FFA8,
  1676. XF86XK_TouchpadToggle: 0x1008FFA9,
  1677. XF86XK_TouchpadOn: 0x1008FFB0,
  1678. XF86XK_TouchpadOff: 0x1008FFB1,
  1679. XF86XK_AudioMicMute: 0x1008FFB2,
  1680. XF86XK_Switch_VT_1: 0x1008FE01,
  1681. XF86XK_Switch_VT_2: 0x1008FE02,
  1682. XF86XK_Switch_VT_3: 0x1008FE03,
  1683. XF86XK_Switch_VT_4: 0x1008FE04,
  1684. XF86XK_Switch_VT_5: 0x1008FE05,
  1685. XF86XK_Switch_VT_6: 0x1008FE06,
  1686. XF86XK_Switch_VT_7: 0x1008FE07,
  1687. XF86XK_Switch_VT_8: 0x1008FE08,
  1688. XF86XK_Switch_VT_9: 0x1008FE09,
  1689. XF86XK_Switch_VT_10: 0x1008FE0A,
  1690. XF86XK_Switch_VT_11: 0x1008FE0B,
  1691. XF86XK_Switch_VT_12: 0x1008FE0C,
  1692. XF86XK_Ungrab: 0x1008FE20,
  1693. XF86XK_ClearGrab: 0x1008FE21,
  1694. XF86XK_Next_VMode: 0x1008FE22,
  1695. XF86XK_Prev_VMode: 0x1008FE23,
  1696. XF86XK_LogWindowTree: 0x1008FE24,
  1697. XF86XK_LogGrabInfo: 0x1008FE25
  1698. };
  1699.  
  1700. /*
  1701. * Mapping from Unicode codepoints to X11/RFB keysyms
  1702. *
  1703. * This file was automatically generated from keysymdef.h
  1704. * DO NOT EDIT!
  1705. */
  1706.  
  1707. /* Functions at the bottom */
  1708.  
  1709. var $$$core$input$keysymdef$$codepoints = {
  1710. 0x0100: 0x03c0, // XK_Amacron
  1711. 0x0101: 0x03e0, // XK_amacron
  1712. 0x0102: 0x01c3, // XK_Abreve
  1713. 0x0103: 0x01e3, // XK_abreve
  1714. 0x0104: 0x01a1, // XK_Aogonek
  1715. 0x0105: 0x01b1, // XK_aogonek
  1716. 0x0106: 0x01c6, // XK_Cacute
  1717. 0x0107: 0x01e6, // XK_cacute
  1718. 0x0108: 0x02c6, // XK_Ccircumflex
  1719. 0x0109: 0x02e6, // XK_ccircumflex
  1720. 0x010a: 0x02c5, // XK_Cabovedot
  1721. 0x010b: 0x02e5, // XK_cabovedot
  1722. 0x010c: 0x01c8, // XK_Ccaron
  1723. 0x010d: 0x01e8, // XK_ccaron
  1724. 0x010e: 0x01cf, // XK_Dcaron
  1725. 0x010f: 0x01ef, // XK_dcaron
  1726. 0x0110: 0x01d0, // XK_Dstroke
  1727. 0x0111: 0x01f0, // XK_dstroke
  1728. 0x0112: 0x03aa, // XK_Emacron
  1729. 0x0113: 0x03ba, // XK_emacron
  1730. 0x0116: 0x03cc, // XK_Eabovedot
  1731. 0x0117: 0x03ec, // XK_eabovedot
  1732. 0x0118: 0x01ca, // XK_Eogonek
  1733. 0x0119: 0x01ea, // XK_eogonek
  1734. 0x011a: 0x01cc, // XK_Ecaron
  1735. 0x011b: 0x01ec, // XK_ecaron
  1736. 0x011c: 0x02d8, // XK_Gcircumflex
  1737. 0x011d: 0x02f8, // XK_gcircumflex
  1738. 0x011e: 0x02ab, // XK_Gbreve
  1739. 0x011f: 0x02bb, // XK_gbreve
  1740. 0x0120: 0x02d5, // XK_Gabovedot
  1741. 0x0121: 0x02f5, // XK_gabovedot
  1742. 0x0122: 0x03ab, // XK_Gcedilla
  1743. 0x0123: 0x03bb, // XK_gcedilla
  1744. 0x0124: 0x02a6, // XK_Hcircumflex
  1745. 0x0125: 0x02b6, // XK_hcircumflex
  1746. 0x0126: 0x02a1, // XK_Hstroke
  1747. 0x0127: 0x02b1, // XK_hstroke
  1748. 0x0128: 0x03a5, // XK_Itilde
  1749. 0x0129: 0x03b5, // XK_itilde
  1750. 0x012a: 0x03cf, // XK_Imacron
  1751. 0x012b: 0x03ef, // XK_imacron
  1752. 0x012e: 0x03c7, // XK_Iogonek
  1753. 0x012f: 0x03e7, // XK_iogonek
  1754. 0x0130: 0x02a9, // XK_Iabovedot
  1755. 0x0131: 0x02b9, // XK_idotless
  1756. 0x0134: 0x02ac, // XK_Jcircumflex
  1757. 0x0135: 0x02bc, // XK_jcircumflex
  1758. 0x0136: 0x03d3, // XK_Kcedilla
  1759. 0x0137: 0x03f3, // XK_kcedilla
  1760. 0x0138: 0x03a2, // XK_kra
  1761. 0x0139: 0x01c5, // XK_Lacute
  1762. 0x013a: 0x01e5, // XK_lacute
  1763. 0x013b: 0x03a6, // XK_Lcedilla
  1764. 0x013c: 0x03b6, // XK_lcedilla
  1765. 0x013d: 0x01a5, // XK_Lcaron
  1766. 0x013e: 0x01b5, // XK_lcaron
  1767. 0x0141: 0x01a3, // XK_Lstroke
  1768. 0x0142: 0x01b3, // XK_lstroke
  1769. 0x0143: 0x01d1, // XK_Nacute
  1770. 0x0144: 0x01f1, // XK_nacute
  1771. 0x0145: 0x03d1, // XK_Ncedilla
  1772. 0x0146: 0x03f1, // XK_ncedilla
  1773. 0x0147: 0x01d2, // XK_Ncaron
  1774. 0x0148: 0x01f2, // XK_ncaron
  1775. 0x014a: 0x03bd, // XK_ENG
  1776. 0x014b: 0x03bf, // XK_eng
  1777. 0x014c: 0x03d2, // XK_Omacron
  1778. 0x014d: 0x03f2, // XK_omacron
  1779. 0x0150: 0x01d5, // XK_Odoubleacute
  1780. 0x0151: 0x01f5, // XK_odoubleacute
  1781. 0x0152: 0x13bc, // XK_OE
  1782. 0x0153: 0x13bd, // XK_oe
  1783. 0x0154: 0x01c0, // XK_Racute
  1784. 0x0155: 0x01e0, // XK_racute
  1785. 0x0156: 0x03a3, // XK_Rcedilla
  1786. 0x0157: 0x03b3, // XK_rcedilla
  1787. 0x0158: 0x01d8, // XK_Rcaron
  1788. 0x0159: 0x01f8, // XK_rcaron
  1789. 0x015a: 0x01a6, // XK_Sacute
  1790. 0x015b: 0x01b6, // XK_sacute
  1791. 0x015c: 0x02de, // XK_Scircumflex
  1792. 0x015d: 0x02fe, // XK_scircumflex
  1793. 0x015e: 0x01aa, // XK_Scedilla
  1794. 0x015f: 0x01ba, // XK_scedilla
  1795. 0x0160: 0x01a9, // XK_Scaron
  1796. 0x0161: 0x01b9, // XK_scaron
  1797. 0x0162: 0x01de, // XK_Tcedilla
  1798. 0x0163: 0x01fe, // XK_tcedilla
  1799. 0x0164: 0x01ab, // XK_Tcaron
  1800. 0x0165: 0x01bb, // XK_tcaron
  1801. 0x0166: 0x03ac, // XK_Tslash
  1802. 0x0167: 0x03bc, // XK_tslash
  1803. 0x0168: 0x03dd, // XK_Utilde
  1804. 0x0169: 0x03fd, // XK_utilde
  1805. 0x016a: 0x03de, // XK_Umacron
  1806. 0x016b: 0x03fe, // XK_umacron
  1807. 0x016c: 0x02dd, // XK_Ubreve
  1808. 0x016d: 0x02fd, // XK_ubreve
  1809. 0x016e: 0x01d9, // XK_Uring
  1810. 0x016f: 0x01f9, // XK_uring
  1811. 0x0170: 0x01db, // XK_Udoubleacute
  1812. 0x0171: 0x01fb, // XK_udoubleacute
  1813. 0x0172: 0x03d9, // XK_Uogonek
  1814. 0x0173: 0x03f9, // XK_uogonek
  1815. 0x0178: 0x13be, // XK_Ydiaeresis
  1816. 0x0179: 0x01ac, // XK_Zacute
  1817. 0x017a: 0x01bc, // XK_zacute
  1818. 0x017b: 0x01af, // XK_Zabovedot
  1819. 0x017c: 0x01bf, // XK_zabovedot
  1820. 0x017d: 0x01ae, // XK_Zcaron
  1821. 0x017e: 0x01be, // XK_zcaron
  1822. 0x0192: 0x08f6, // XK_function
  1823. 0x01d2: 0x10001d1, // XK_Ocaron
  1824. 0x02c7: 0x01b7, // XK_caron
  1825. 0x02d8: 0x01a2, // XK_breve
  1826. 0x02d9: 0x01ff, // XK_abovedot
  1827. 0x02db: 0x01b2, // XK_ogonek
  1828. 0x02dd: 0x01bd, // XK_doubleacute
  1829. 0x0385: 0x07ae, // XK_Greek_accentdieresis
  1830. 0x0386: 0x07a1, // XK_Greek_ALPHAaccent
  1831. 0x0388: 0x07a2, // XK_Greek_EPSILONaccent
  1832. 0x0389: 0x07a3, // XK_Greek_ETAaccent
  1833. 0x038a: 0x07a4, // XK_Greek_IOTAaccent
  1834. 0x038c: 0x07a7, // XK_Greek_OMICRONaccent
  1835. 0x038e: 0x07a8, // XK_Greek_UPSILONaccent
  1836. 0x038f: 0x07ab, // XK_Greek_OMEGAaccent
  1837. 0x0390: 0x07b6, // XK_Greek_iotaaccentdieresis
  1838. 0x0391: 0x07c1, // XK_Greek_ALPHA
  1839. 0x0392: 0x07c2, // XK_Greek_BETA
  1840. 0x0393: 0x07c3, // XK_Greek_GAMMA
  1841. 0x0394: 0x07c4, // XK_Greek_DELTA
  1842. 0x0395: 0x07c5, // XK_Greek_EPSILON
  1843. 0x0396: 0x07c6, // XK_Greek_ZETA
  1844. 0x0397: 0x07c7, // XK_Greek_ETA
  1845. 0x0398: 0x07c8, // XK_Greek_THETA
  1846. 0x0399: 0x07c9, // XK_Greek_IOTA
  1847. 0x039a: 0x07ca, // XK_Greek_KAPPA
  1848. 0x039b: 0x07cb, // XK_Greek_LAMDA
  1849. 0x039c: 0x07cc, // XK_Greek_MU
  1850. 0x039d: 0x07cd, // XK_Greek_NU
  1851. 0x039e: 0x07ce, // XK_Greek_XI
  1852. 0x039f: 0x07cf, // XK_Greek_OMICRON
  1853. 0x03a0: 0x07d0, // XK_Greek_PI
  1854. 0x03a1: 0x07d1, // XK_Greek_RHO
  1855. 0x03a3: 0x07d2, // XK_Greek_SIGMA
  1856. 0x03a4: 0x07d4, // XK_Greek_TAU
  1857. 0x03a5: 0x07d5, // XK_Greek_UPSILON
  1858. 0x03a6: 0x07d6, // XK_Greek_PHI
  1859. 0x03a7: 0x07d7, // XK_Greek_CHI
  1860. 0x03a8: 0x07d8, // XK_Greek_PSI
  1861. 0x03a9: 0x07d9, // XK_Greek_OMEGA
  1862. 0x03aa: 0x07a5, // XK_Greek_IOTAdieresis
  1863. 0x03ab: 0x07a9, // XK_Greek_UPSILONdieresis
  1864. 0x03ac: 0x07b1, // XK_Greek_alphaaccent
  1865. 0x03ad: 0x07b2, // XK_Greek_epsilonaccent
  1866. 0x03ae: 0x07b3, // XK_Greek_etaaccent
  1867. 0x03af: 0x07b4, // XK_Greek_iotaaccent
  1868. 0x03b0: 0x07ba, // XK_Greek_upsilonaccentdieresis
  1869. 0x03b1: 0x07e1, // XK_Greek_alpha
  1870. 0x03b2: 0x07e2, // XK_Greek_beta
  1871. 0x03b3: 0x07e3, // XK_Greek_gamma
  1872. 0x03b4: 0x07e4, // XK_Greek_delta
  1873. 0x03b5: 0x07e5, // XK_Greek_epsilon
  1874. 0x03b6: 0x07e6, // XK_Greek_zeta
  1875. 0x03b7: 0x07e7, // XK_Greek_eta
  1876. 0x03b8: 0x07e8, // XK_Greek_theta
  1877. 0x03b9: 0x07e9, // XK_Greek_iota
  1878. 0x03ba: 0x07ea, // XK_Greek_kappa
  1879. 0x03bb: 0x07eb, // XK_Greek_lamda
  1880. 0x03bc: 0x07ec, // XK_Greek_mu
  1881. 0x03bd: 0x07ed, // XK_Greek_nu
  1882. 0x03be: 0x07ee, // XK_Greek_xi
  1883. 0x03bf: 0x07ef, // XK_Greek_omicron
  1884. 0x03c0: 0x07f0, // XK_Greek_pi
  1885. 0x03c1: 0x07f1, // XK_Greek_rho
  1886. 0x03c2: 0x07f3, // XK_Greek_finalsmallsigma
  1887. 0x03c3: 0x07f2, // XK_Greek_sigma
  1888. 0x03c4: 0x07f4, // XK_Greek_tau
  1889. 0x03c5: 0x07f5, // XK_Greek_upsilon
  1890. 0x03c6: 0x07f6, // XK_Greek_phi
  1891. 0x03c7: 0x07f7, // XK_Greek_chi
  1892. 0x03c8: 0x07f8, // XK_Greek_psi
  1893. 0x03c9: 0x07f9, // XK_Greek_omega
  1894. 0x03ca: 0x07b5, // XK_Greek_iotadieresis
  1895. 0x03cb: 0x07b9, // XK_Greek_upsilondieresis
  1896. 0x03cc: 0x07b7, // XK_Greek_omicronaccent
  1897. 0x03cd: 0x07b8, // XK_Greek_upsilonaccent
  1898. 0x03ce: 0x07bb, // XK_Greek_omegaaccent
  1899. 0x0401: 0x06b3, // XK_Cyrillic_IO
  1900. 0x0402: 0x06b1, // XK_Serbian_DJE
  1901. 0x0403: 0x06b2, // XK_Macedonia_GJE
  1902. 0x0404: 0x06b4, // XK_Ukrainian_IE
  1903. 0x0405: 0x06b5, // XK_Macedonia_DSE
  1904. 0x0406: 0x06b6, // XK_Ukrainian_I
  1905. 0x0407: 0x06b7, // XK_Ukrainian_YI
  1906. 0x0408: 0x06b8, // XK_Cyrillic_JE
  1907. 0x0409: 0x06b9, // XK_Cyrillic_LJE
  1908. 0x040a: 0x06ba, // XK_Cyrillic_NJE
  1909. 0x040b: 0x06bb, // XK_Serbian_TSHE
  1910. 0x040c: 0x06bc, // XK_Macedonia_KJE
  1911. 0x040e: 0x06be, // XK_Byelorussian_SHORTU
  1912. 0x040f: 0x06bf, // XK_Cyrillic_DZHE
  1913. 0x0410: 0x06e1, // XK_Cyrillic_A
  1914. 0x0411: 0x06e2, // XK_Cyrillic_BE
  1915. 0x0412: 0x06f7, // XK_Cyrillic_VE
  1916. 0x0413: 0x06e7, // XK_Cyrillic_GHE
  1917. 0x0414: 0x06e4, // XK_Cyrillic_DE
  1918. 0x0415: 0x06e5, // XK_Cyrillic_IE
  1919. 0x0416: 0x06f6, // XK_Cyrillic_ZHE
  1920. 0x0417: 0x06fa, // XK_Cyrillic_ZE
  1921. 0x0418: 0x06e9, // XK_Cyrillic_I
  1922. 0x0419: 0x06ea, // XK_Cyrillic_SHORTI
  1923. 0x041a: 0x06eb, // XK_Cyrillic_KA
  1924. 0x041b: 0x06ec, // XK_Cyrillic_EL
  1925. 0x041c: 0x06ed, // XK_Cyrillic_EM
  1926. 0x041d: 0x06ee, // XK_Cyrillic_EN
  1927. 0x041e: 0x06ef, // XK_Cyrillic_O
  1928. 0x041f: 0x06f0, // XK_Cyrillic_PE
  1929. 0x0420: 0x06f2, // XK_Cyrillic_ER
  1930. 0x0421: 0x06f3, // XK_Cyrillic_ES
  1931. 0x0422: 0x06f4, // XK_Cyrillic_TE
  1932. 0x0423: 0x06f5, // XK_Cyrillic_U
  1933. 0x0424: 0x06e6, // XK_Cyrillic_EF
  1934. 0x0425: 0x06e8, // XK_Cyrillic_HA
  1935. 0x0426: 0x06e3, // XK_Cyrillic_TSE
  1936. 0x0427: 0x06fe, // XK_Cyrillic_CHE
  1937. 0x0428: 0x06fb, // XK_Cyrillic_SHA
  1938. 0x0429: 0x06fd, // XK_Cyrillic_SHCHA
  1939. 0x042a: 0x06ff, // XK_Cyrillic_HARDSIGN
  1940. 0x042b: 0x06f9, // XK_Cyrillic_YERU
  1941. 0x042c: 0x06f8, // XK_Cyrillic_SOFTSIGN
  1942. 0x042d: 0x06fc, // XK_Cyrillic_E
  1943. 0x042e: 0x06e0, // XK_Cyrillic_YU
  1944. 0x042f: 0x06f1, // XK_Cyrillic_YA
  1945. 0x0430: 0x06c1, // XK_Cyrillic_a
  1946. 0x0431: 0x06c2, // XK_Cyrillic_be
  1947. 0x0432: 0x06d7, // XK_Cyrillic_ve
  1948. 0x0433: 0x06c7, // XK_Cyrillic_ghe
  1949. 0x0434: 0x06c4, // XK_Cyrillic_de
  1950. 0x0435: 0x06c5, // XK_Cyrillic_ie
  1951. 0x0436: 0x06d6, // XK_Cyrillic_zhe
  1952. 0x0437: 0x06da, // XK_Cyrillic_ze
  1953. 0x0438: 0x06c9, // XK_Cyrillic_i
  1954. 0x0439: 0x06ca, // XK_Cyrillic_shorti
  1955. 0x043a: 0x06cb, // XK_Cyrillic_ka
  1956. 0x043b: 0x06cc, // XK_Cyrillic_el
  1957. 0x043c: 0x06cd, // XK_Cyrillic_em
  1958. 0x043d: 0x06ce, // XK_Cyrillic_en
  1959. 0x043e: 0x06cf, // XK_Cyrillic_o
  1960. 0x043f: 0x06d0, // XK_Cyrillic_pe
  1961. 0x0440: 0x06d2, // XK_Cyrillic_er
  1962. 0x0441: 0x06d3, // XK_Cyrillic_es
  1963. 0x0442: 0x06d4, // XK_Cyrillic_te
  1964. 0x0443: 0x06d5, // XK_Cyrillic_u
  1965. 0x0444: 0x06c6, // XK_Cyrillic_ef
  1966. 0x0445: 0x06c8, // XK_Cyrillic_ha
  1967. 0x0446: 0x06c3, // XK_Cyrillic_tse
  1968. 0x0447: 0x06de, // XK_Cyrillic_che
  1969. 0x0448: 0x06db, // XK_Cyrillic_sha
  1970. 0x0449: 0x06dd, // XK_Cyrillic_shcha
  1971. 0x044a: 0x06df, // XK_Cyrillic_hardsign
  1972. 0x044b: 0x06d9, // XK_Cyrillic_yeru
  1973. 0x044c: 0x06d8, // XK_Cyrillic_softsign
  1974. 0x044d: 0x06dc, // XK_Cyrillic_e
  1975. 0x044e: 0x06c0, // XK_Cyrillic_yu
  1976. 0x044f: 0x06d1, // XK_Cyrillic_ya
  1977. 0x0451: 0x06a3, // XK_Cyrillic_io
  1978. 0x0452: 0x06a1, // XK_Serbian_dje
  1979. 0x0453: 0x06a2, // XK_Macedonia_gje
  1980. 0x0454: 0x06a4, // XK_Ukrainian_ie
  1981. 0x0455: 0x06a5, // XK_Macedonia_dse
  1982. 0x0456: 0x06a6, // XK_Ukrainian_i
  1983. 0x0457: 0x06a7, // XK_Ukrainian_yi
  1984. 0x0458: 0x06a8, // XK_Cyrillic_je
  1985. 0x0459: 0x06a9, // XK_Cyrillic_lje
  1986. 0x045a: 0x06aa, // XK_Cyrillic_nje
  1987. 0x045b: 0x06ab, // XK_Serbian_tshe
  1988. 0x045c: 0x06ac, // XK_Macedonia_kje
  1989. 0x045e: 0x06ae, // XK_Byelorussian_shortu
  1990. 0x045f: 0x06af, // XK_Cyrillic_dzhe
  1991. 0x0490: 0x06bd, // XK_Ukrainian_GHE_WITH_UPTURN
  1992. 0x0491: 0x06ad, // XK_Ukrainian_ghe_with_upturn
  1993. 0x05d0: 0x0ce0, // XK_hebrew_aleph
  1994. 0x05d1: 0x0ce1, // XK_hebrew_bet
  1995. 0x05d2: 0x0ce2, // XK_hebrew_gimel
  1996. 0x05d3: 0x0ce3, // XK_hebrew_dalet
  1997. 0x05d4: 0x0ce4, // XK_hebrew_he
  1998. 0x05d5: 0x0ce5, // XK_hebrew_waw
  1999. 0x05d6: 0x0ce6, // XK_hebrew_zain
  2000. 0x05d7: 0x0ce7, // XK_hebrew_chet
  2001. 0x05d8: 0x0ce8, // XK_hebrew_tet
  2002. 0x05d9: 0x0ce9, // XK_hebrew_yod
  2003. 0x05da: 0x0cea, // XK_hebrew_finalkaph
  2004. 0x05db: 0x0ceb, // XK_hebrew_kaph
  2005. 0x05dc: 0x0cec, // XK_hebrew_lamed
  2006. 0x05dd: 0x0ced, // XK_hebrew_finalmem
  2007. 0x05de: 0x0cee, // XK_hebrew_mem
  2008. 0x05df: 0x0cef, // XK_hebrew_finalnun
  2009. 0x05e0: 0x0cf0, // XK_hebrew_nun
  2010. 0x05e1: 0x0cf1, // XK_hebrew_samech
  2011. 0x05e2: 0x0cf2, // XK_hebrew_ayin
  2012. 0x05e3: 0x0cf3, // XK_hebrew_finalpe
  2013. 0x05e4: 0x0cf4, // XK_hebrew_pe
  2014. 0x05e5: 0x0cf5, // XK_hebrew_finalzade
  2015. 0x05e6: 0x0cf6, // XK_hebrew_zade
  2016. 0x05e7: 0x0cf7, // XK_hebrew_qoph
  2017. 0x05e8: 0x0cf8, // XK_hebrew_resh
  2018. 0x05e9: 0x0cf9, // XK_hebrew_shin
  2019. 0x05ea: 0x0cfa, // XK_hebrew_taw
  2020. 0x060c: 0x05ac, // XK_Arabic_comma
  2021. 0x061b: 0x05bb, // XK_Arabic_semicolon
  2022. 0x061f: 0x05bf, // XK_Arabic_question_mark
  2023. 0x0621: 0x05c1, // XK_Arabic_hamza
  2024. 0x0622: 0x05c2, // XK_Arabic_maddaonalef
  2025. 0x0623: 0x05c3, // XK_Arabic_hamzaonalef
  2026. 0x0624: 0x05c4, // XK_Arabic_hamzaonwaw
  2027. 0x0625: 0x05c5, // XK_Arabic_hamzaunderalef
  2028. 0x0626: 0x05c6, // XK_Arabic_hamzaonyeh
  2029. 0x0627: 0x05c7, // XK_Arabic_alef
  2030. 0x0628: 0x05c8, // XK_Arabic_beh
  2031. 0x0629: 0x05c9, // XK_Arabic_tehmarbuta
  2032. 0x062a: 0x05ca, // XK_Arabic_teh
  2033. 0x062b: 0x05cb, // XK_Arabic_theh
  2034. 0x062c: 0x05cc, // XK_Arabic_jeem
  2035. 0x062d: 0x05cd, // XK_Arabic_hah
  2036. 0x062e: 0x05ce, // XK_Arabic_khah
  2037. 0x062f: 0x05cf, // XK_Arabic_dal
  2038. 0x0630: 0x05d0, // XK_Arabic_thal
  2039. 0x0631: 0x05d1, // XK_Arabic_ra
  2040. 0x0632: 0x05d2, // XK_Arabic_zain
  2041. 0x0633: 0x05d3, // XK_Arabic_seen
  2042. 0x0634: 0x05d4, // XK_Arabic_sheen
  2043. 0x0635: 0x05d5, // XK_Arabic_sad
  2044. 0x0636: 0x05d6, // XK_Arabic_dad
  2045. 0x0637: 0x05d7, // XK_Arabic_tah
  2046. 0x0638: 0x05d8, // XK_Arabic_zah
  2047. 0x0639: 0x05d9, // XK_Arabic_ain
  2048. 0x063a: 0x05da, // XK_Arabic_ghain
  2049. 0x0640: 0x05e0, // XK_Arabic_tatweel
  2050. 0x0641: 0x05e1, // XK_Arabic_feh
  2051. 0x0642: 0x05e2, // XK_Arabic_qaf
  2052. 0x0643: 0x05e3, // XK_Arabic_kaf
  2053. 0x0644: 0x05e4, // XK_Arabic_lam
  2054. 0x0645: 0x05e5, // XK_Arabic_meem
  2055. 0x0646: 0x05e6, // XK_Arabic_noon
  2056. 0x0647: 0x05e7, // XK_Arabic_ha
  2057. 0x0648: 0x05e8, // XK_Arabic_waw
  2058. 0x0649: 0x05e9, // XK_Arabic_alefmaksura
  2059. 0x064a: 0x05ea, // XK_Arabic_yeh
  2060. 0x064b: 0x05eb, // XK_Arabic_fathatan
  2061. 0x064c: 0x05ec, // XK_Arabic_dammatan
  2062. 0x064d: 0x05ed, // XK_Arabic_kasratan
  2063. 0x064e: 0x05ee, // XK_Arabic_fatha
  2064. 0x064f: 0x05ef, // XK_Arabic_damma
  2065. 0x0650: 0x05f0, // XK_Arabic_kasra
  2066. 0x0651: 0x05f1, // XK_Arabic_shadda
  2067. 0x0652: 0x05f2, // XK_Arabic_sukun
  2068. 0x0e01: 0x0da1, // XK_Thai_kokai
  2069. 0x0e02: 0x0da2, // XK_Thai_khokhai
  2070. 0x0e03: 0x0da3, // XK_Thai_khokhuat
  2071. 0x0e04: 0x0da4, // XK_Thai_khokhwai
  2072. 0x0e05: 0x0da5, // XK_Thai_khokhon
  2073. 0x0e06: 0x0da6, // XK_Thai_khorakhang
  2074. 0x0e07: 0x0da7, // XK_Thai_ngongu
  2075. 0x0e08: 0x0da8, // XK_Thai_chochan
  2076. 0x0e09: 0x0da9, // XK_Thai_choching
  2077. 0x0e0a: 0x0daa, // XK_Thai_chochang
  2078. 0x0e0b: 0x0dab, // XK_Thai_soso
  2079. 0x0e0c: 0x0dac, // XK_Thai_chochoe
  2080. 0x0e0d: 0x0dad, // XK_Thai_yoying
  2081. 0x0e0e: 0x0dae, // XK_Thai_dochada
  2082. 0x0e0f: 0x0daf, // XK_Thai_topatak
  2083. 0x0e10: 0x0db0, // XK_Thai_thothan
  2084. 0x0e11: 0x0db1, // XK_Thai_thonangmontho
  2085. 0x0e12: 0x0db2, // XK_Thai_thophuthao
  2086. 0x0e13: 0x0db3, // XK_Thai_nonen
  2087. 0x0e14: 0x0db4, // XK_Thai_dodek
  2088. 0x0e15: 0x0db5, // XK_Thai_totao
  2089. 0x0e16: 0x0db6, // XK_Thai_thothung
  2090. 0x0e17: 0x0db7, // XK_Thai_thothahan
  2091. 0x0e18: 0x0db8, // XK_Thai_thothong
  2092. 0x0e19: 0x0db9, // XK_Thai_nonu
  2093. 0x0e1a: 0x0dba, // XK_Thai_bobaimai
  2094. 0x0e1b: 0x0dbb, // XK_Thai_popla
  2095. 0x0e1c: 0x0dbc, // XK_Thai_phophung
  2096. 0x0e1d: 0x0dbd, // XK_Thai_fofa
  2097. 0x0e1e: 0x0dbe, // XK_Thai_phophan
  2098. 0x0e1f: 0x0dbf, // XK_Thai_fofan
  2099. 0x0e20: 0x0dc0, // XK_Thai_phosamphao
  2100. 0x0e21: 0x0dc1, // XK_Thai_moma
  2101. 0x0e22: 0x0dc2, // XK_Thai_yoyak
  2102. 0x0e23: 0x0dc3, // XK_Thai_rorua
  2103. 0x0e24: 0x0dc4, // XK_Thai_ru
  2104. 0x0e25: 0x0dc5, // XK_Thai_loling
  2105. 0x0e26: 0x0dc6, // XK_Thai_lu
  2106. 0x0e27: 0x0dc7, // XK_Thai_wowaen
  2107. 0x0e28: 0x0dc8, // XK_Thai_sosala
  2108. 0x0e29: 0x0dc9, // XK_Thai_sorusi
  2109. 0x0e2a: 0x0dca, // XK_Thai_sosua
  2110. 0x0e2b: 0x0dcb, // XK_Thai_hohip
  2111. 0x0e2c: 0x0dcc, // XK_Thai_lochula
  2112. 0x0e2d: 0x0dcd, // XK_Thai_oang
  2113. 0x0e2e: 0x0dce, // XK_Thai_honokhuk
  2114. 0x0e2f: 0x0dcf, // XK_Thai_paiyannoi
  2115. 0x0e30: 0x0dd0, // XK_Thai_saraa
  2116. 0x0e31: 0x0dd1, // XK_Thai_maihanakat
  2117. 0x0e32: 0x0dd2, // XK_Thai_saraaa
  2118. 0x0e33: 0x0dd3, // XK_Thai_saraam
  2119. 0x0e34: 0x0dd4, // XK_Thai_sarai
  2120. 0x0e35: 0x0dd5, // XK_Thai_saraii
  2121. 0x0e36: 0x0dd6, // XK_Thai_saraue
  2122. 0x0e37: 0x0dd7, // XK_Thai_sarauee
  2123. 0x0e38: 0x0dd8, // XK_Thai_sarau
  2124. 0x0e39: 0x0dd9, // XK_Thai_sarauu
  2125. 0x0e3a: 0x0dda, // XK_Thai_phinthu
  2126. 0x0e3f: 0x0ddf, // XK_Thai_baht
  2127. 0x0e40: 0x0de0, // XK_Thai_sarae
  2128. 0x0e41: 0x0de1, // XK_Thai_saraae
  2129. 0x0e42: 0x0de2, // XK_Thai_sarao
  2130. 0x0e43: 0x0de3, // XK_Thai_saraaimaimuan
  2131. 0x0e44: 0x0de4, // XK_Thai_saraaimaimalai
  2132. 0x0e45: 0x0de5, // XK_Thai_lakkhangyao
  2133. 0x0e46: 0x0de6, // XK_Thai_maiyamok
  2134. 0x0e47: 0x0de7, // XK_Thai_maitaikhu
  2135. 0x0e48: 0x0de8, // XK_Thai_maiek
  2136. 0x0e49: 0x0de9, // XK_Thai_maitho
  2137. 0x0e4a: 0x0dea, // XK_Thai_maitri
  2138. 0x0e4b: 0x0deb, // XK_Thai_maichattawa
  2139. 0x0e4c: 0x0dec, // XK_Thai_thanthakhat
  2140. 0x0e4d: 0x0ded, // XK_Thai_nikhahit
  2141. 0x0e50: 0x0df0, // XK_Thai_leksun
  2142. 0x0e51: 0x0df1, // XK_Thai_leknung
  2143. 0x0e52: 0x0df2, // XK_Thai_leksong
  2144. 0x0e53: 0x0df3, // XK_Thai_leksam
  2145. 0x0e54: 0x0df4, // XK_Thai_leksi
  2146. 0x0e55: 0x0df5, // XK_Thai_lekha
  2147. 0x0e56: 0x0df6, // XK_Thai_lekhok
  2148. 0x0e57: 0x0df7, // XK_Thai_lekchet
  2149. 0x0e58: 0x0df8, // XK_Thai_lekpaet
  2150. 0x0e59: 0x0df9, // XK_Thai_lekkao
  2151. 0x2002: 0x0aa2, // XK_enspace
  2152. 0x2003: 0x0aa1, // XK_emspace
  2153. 0x2004: 0x0aa3, // XK_em3space
  2154. 0x2005: 0x0aa4, // XK_em4space
  2155. 0x2007: 0x0aa5, // XK_digitspace
  2156. 0x2008: 0x0aa6, // XK_punctspace
  2157. 0x2009: 0x0aa7, // XK_thinspace
  2158. 0x200a: 0x0aa8, // XK_hairspace
  2159. 0x2012: 0x0abb, // XK_figdash
  2160. 0x2013: 0x0aaa, // XK_endash
  2161. 0x2014: 0x0aa9, // XK_emdash
  2162. 0x2015: 0x07af, // XK_Greek_horizbar
  2163. 0x2017: 0x0cdf, // XK_hebrew_doublelowline
  2164. 0x2018: 0x0ad0, // XK_leftsinglequotemark
  2165. 0x2019: 0x0ad1, // XK_rightsinglequotemark
  2166. 0x201a: 0x0afd, // XK_singlelowquotemark
  2167. 0x201c: 0x0ad2, // XK_leftdoublequotemark
  2168. 0x201d: 0x0ad3, // XK_rightdoublequotemark
  2169. 0x201e: 0x0afe, // XK_doublelowquotemark
  2170. 0x2020: 0x0af1, // XK_dagger
  2171. 0x2021: 0x0af2, // XK_doubledagger
  2172. 0x2022: 0x0ae6, // XK_enfilledcircbullet
  2173. 0x2025: 0x0aaf, // XK_doubbaselinedot
  2174. 0x2026: 0x0aae, // XK_ellipsis
  2175. 0x2030: 0x0ad5, // XK_permille
  2176. 0x2032: 0x0ad6, // XK_minutes
  2177. 0x2033: 0x0ad7, // XK_seconds
  2178. 0x2038: 0x0afc, // XK_caret
  2179. 0x203e: 0x047e, // XK_overline
  2180. 0x20a9: 0x0eff, // XK_Korean_Won
  2181. 0x20ac: 0x20ac, // XK_EuroSign
  2182. 0x2105: 0x0ab8, // XK_careof
  2183. 0x2116: 0x06b0, // XK_numerosign
  2184. 0x2117: 0x0afb, // XK_phonographcopyright
  2185. 0x211e: 0x0ad4, // XK_prescription
  2186. 0x2122: 0x0ac9, // XK_trademark
  2187. 0x2153: 0x0ab0, // XK_onethird
  2188. 0x2154: 0x0ab1, // XK_twothirds
  2189. 0x2155: 0x0ab2, // XK_onefifth
  2190. 0x2156: 0x0ab3, // XK_twofifths
  2191. 0x2157: 0x0ab4, // XK_threefifths
  2192. 0x2158: 0x0ab5, // XK_fourfifths
  2193. 0x2159: 0x0ab6, // XK_onesixth
  2194. 0x215a: 0x0ab7, // XK_fivesixths
  2195. 0x215b: 0x0ac3, // XK_oneeighth
  2196. 0x215c: 0x0ac4, // XK_threeeighths
  2197. 0x215d: 0x0ac5, // XK_fiveeighths
  2198. 0x215e: 0x0ac6, // XK_seveneighths
  2199. 0x2190: 0x08fb, // XK_leftarrow
  2200. 0x2191: 0x08fc, // XK_uparrow
  2201. 0x2192: 0x08fd, // XK_rightarrow
  2202. 0x2193: 0x08fe, // XK_downarrow
  2203. 0x21d2: 0x08ce, // XK_implies
  2204. 0x21d4: 0x08cd, // XK_ifonlyif
  2205. 0x2202: 0x08ef, // XK_partialderivative
  2206. 0x2207: 0x08c5, // XK_nabla
  2207. 0x2218: 0x0bca, // XK_jot
  2208. 0x221a: 0x08d6, // XK_radical
  2209. 0x221d: 0x08c1, // XK_variation
  2210. 0x221e: 0x08c2, // XK_infinity
  2211. 0x2227: 0x08de, // XK_logicaland
  2212. 0x2228: 0x08df, // XK_logicalor
  2213. 0x2229: 0x08dc, // XK_intersection
  2214. 0x222a: 0x08dd, // XK_union
  2215. 0x222b: 0x08bf, // XK_integral
  2216. 0x2234: 0x08c0, // XK_therefore
  2217. 0x223c: 0x08c8, // XK_approximate
  2218. 0x2243: 0x08c9, // XK_similarequal
  2219. 0x2245: 0x1002248, // XK_approxeq
  2220. 0x2260: 0x08bd, // XK_notequal
  2221. 0x2261: 0x08cf, // XK_identical
  2222. 0x2264: 0x08bc, // XK_lessthanequal
  2223. 0x2265: 0x08be, // XK_greaterthanequal
  2224. 0x2282: 0x08da, // XK_includedin
  2225. 0x2283: 0x08db, // XK_includes
  2226. 0x22a2: 0x0bfc, // XK_righttack
  2227. 0x22a3: 0x0bdc, // XK_lefttack
  2228. 0x22a4: 0x0bc2, // XK_downtack
  2229. 0x22a5: 0x0bce, // XK_uptack
  2230. 0x2308: 0x0bd3, // XK_upstile
  2231. 0x230a: 0x0bc4, // XK_downstile
  2232. 0x2315: 0x0afa, // XK_telephonerecorder
  2233. 0x2320: 0x08a4, // XK_topintegral
  2234. 0x2321: 0x08a5, // XK_botintegral
  2235. 0x2395: 0x0bcc, // XK_quad
  2236. 0x239b: 0x08ab, // XK_topleftparens
  2237. 0x239d: 0x08ac, // XK_botleftparens
  2238. 0x239e: 0x08ad, // XK_toprightparens
  2239. 0x23a0: 0x08ae, // XK_botrightparens
  2240. 0x23a1: 0x08a7, // XK_topleftsqbracket
  2241. 0x23a3: 0x08a8, // XK_botleftsqbracket
  2242. 0x23a4: 0x08a9, // XK_toprightsqbracket
  2243. 0x23a6: 0x08aa, // XK_botrightsqbracket
  2244. 0x23a8: 0x08af, // XK_leftmiddlecurlybrace
  2245. 0x23ac: 0x08b0, // XK_rightmiddlecurlybrace
  2246. 0x23b7: 0x08a1, // XK_leftradical
  2247. 0x23ba: 0x09ef, // XK_horizlinescan1
  2248. 0x23bb: 0x09f0, // XK_horizlinescan3
  2249. 0x23bc: 0x09f2, // XK_horizlinescan7
  2250. 0x23bd: 0x09f3, // XK_horizlinescan9
  2251. 0x2409: 0x09e2, // XK_ht
  2252. 0x240a: 0x09e5, // XK_lf
  2253. 0x240b: 0x09e9, // XK_vt
  2254. 0x240c: 0x09e3, // XK_ff
  2255. 0x240d: 0x09e4, // XK_cr
  2256. 0x2423: 0x0aac, // XK_signifblank
  2257. 0x2424: 0x09e8, // XK_nl
  2258. 0x2500: 0x08a3, // XK_horizconnector
  2259. 0x2502: 0x08a6, // XK_vertconnector
  2260. 0x250c: 0x08a2, // XK_topleftradical
  2261. 0x2510: 0x09eb, // XK_uprightcorner
  2262. 0x2514: 0x09ed, // XK_lowleftcorner
  2263. 0x2518: 0x09ea, // XK_lowrightcorner
  2264. 0x251c: 0x09f4, // XK_leftt
  2265. 0x2524: 0x09f5, // XK_rightt
  2266. 0x252c: 0x09f7, // XK_topt
  2267. 0x2534: 0x09f6, // XK_bott
  2268. 0x253c: 0x09ee, // XK_crossinglines
  2269. 0x2592: 0x09e1, // XK_checkerboard
  2270. 0x25aa: 0x0ae7, // XK_enfilledsqbullet
  2271. 0x25ab: 0x0ae1, // XK_enopensquarebullet
  2272. 0x25ac: 0x0adb, // XK_filledrectbullet
  2273. 0x25ad: 0x0ae2, // XK_openrectbullet
  2274. 0x25ae: 0x0adf, // XK_emfilledrect
  2275. 0x25af: 0x0acf, // XK_emopenrectangle
  2276. 0x25b2: 0x0ae8, // XK_filledtribulletup
  2277. 0x25b3: 0x0ae3, // XK_opentribulletup
  2278. 0x25b6: 0x0add, // XK_filledrighttribullet
  2279. 0x25b7: 0x0acd, // XK_rightopentriangle
  2280. 0x25bc: 0x0ae9, // XK_filledtribulletdown
  2281. 0x25bd: 0x0ae4, // XK_opentribulletdown
  2282. 0x25c0: 0x0adc, // XK_filledlefttribullet
  2283. 0x25c1: 0x0acc, // XK_leftopentriangle
  2284. 0x25c6: 0x09e0, // XK_soliddiamond
  2285. 0x25cb: 0x0ace, // XK_emopencircle
  2286. 0x25cf: 0x0ade, // XK_emfilledcircle
  2287. 0x25e6: 0x0ae0, // XK_enopencircbullet
  2288. 0x2606: 0x0ae5, // XK_openstar
  2289. 0x260e: 0x0af9, // XK_telephone
  2290. 0x2613: 0x0aca, // XK_signaturemark
  2291. 0x261c: 0x0aea, // XK_leftpointer
  2292. 0x261e: 0x0aeb, // XK_rightpointer
  2293. 0x2640: 0x0af8, // XK_femalesymbol
  2294. 0x2642: 0x0af7, // XK_malesymbol
  2295. 0x2663: 0x0aec, // XK_club
  2296. 0x2665: 0x0aee, // XK_heart
  2297. 0x2666: 0x0aed, // XK_diamond
  2298. 0x266d: 0x0af6, // XK_musicalflat
  2299. 0x266f: 0x0af5, // XK_musicalsharp
  2300. 0x2713: 0x0af3, // XK_checkmark
  2301. 0x2717: 0x0af4, // XK_ballotcross
  2302. 0x271d: 0x0ad9, // XK_latincross
  2303. 0x2720: 0x0af0, // XK_maltesecross
  2304. 0x27e8: 0x0abc, // XK_leftanglebracket
  2305. 0x27e9: 0x0abe, // XK_rightanglebracket
  2306. 0x3001: 0x04a4, // XK_kana_comma
  2307. 0x3002: 0x04a1, // XK_kana_fullstop
  2308. 0x300c: 0x04a2, // XK_kana_openingbracket
  2309. 0x300d: 0x04a3, // XK_kana_closingbracket
  2310. 0x309b: 0x04de, // XK_voicedsound
  2311. 0x309c: 0x04df, // XK_semivoicedsound
  2312. 0x30a1: 0x04a7, // XK_kana_a
  2313. 0x30a2: 0x04b1, // XK_kana_A
  2314. 0x30a3: 0x04a8, // XK_kana_i
  2315. 0x30a4: 0x04b2, // XK_kana_I
  2316. 0x30a5: 0x04a9, // XK_kana_u
  2317. 0x30a6: 0x04b3, // XK_kana_U
  2318. 0x30a7: 0x04aa, // XK_kana_e
  2319. 0x30a8: 0x04b4, // XK_kana_E
  2320. 0x30a9: 0x04ab, // XK_kana_o
  2321. 0x30aa: 0x04b5, // XK_kana_O
  2322. 0x30ab: 0x04b6, // XK_kana_KA
  2323. 0x30ad: 0x04b7, // XK_kana_KI
  2324. 0x30af: 0x04b8, // XK_kana_KU
  2325. 0x30b1: 0x04b9, // XK_kana_KE
  2326. 0x30b3: 0x04ba, // XK_kana_KO
  2327. 0x30b5: 0x04bb, // XK_kana_SA
  2328. 0x30b7: 0x04bc, // XK_kana_SHI
  2329. 0x30b9: 0x04bd, // XK_kana_SU
  2330. 0x30bb: 0x04be, // XK_kana_SE
  2331. 0x30bd: 0x04bf, // XK_kana_SO
  2332. 0x30bf: 0x04c0, // XK_kana_TA
  2333. 0x30c1: 0x04c1, // XK_kana_CHI
  2334. 0x30c3: 0x04af, // XK_kana_tsu
  2335. 0x30c4: 0x04c2, // XK_kana_TSU
  2336. 0x30c6: 0x04c3, // XK_kana_TE
  2337. 0x30c8: 0x04c4, // XK_kana_TO
  2338. 0x30ca: 0x04c5, // XK_kana_NA
  2339. 0x30cb: 0x04c6, // XK_kana_NI
  2340. 0x30cc: 0x04c7, // XK_kana_NU
  2341. 0x30cd: 0x04c8, // XK_kana_NE
  2342. 0x30ce: 0x04c9, // XK_kana_NO
  2343. 0x30cf: 0x04ca, // XK_kana_HA
  2344. 0x30d2: 0x04cb, // XK_kana_HI
  2345. 0x30d5: 0x04cc, // XK_kana_FU
  2346. 0x30d8: 0x04cd, // XK_kana_HE
  2347. 0x30db: 0x04ce, // XK_kana_HO
  2348. 0x30de: 0x04cf, // XK_kana_MA
  2349. 0x30df: 0x04d0, // XK_kana_MI
  2350. 0x30e0: 0x04d1, // XK_kana_MU
  2351. 0x30e1: 0x04d2, // XK_kana_ME
  2352. 0x30e2: 0x04d3, // XK_kana_MO
  2353. 0x30e3: 0x04ac, // XK_kana_ya
  2354. 0x30e4: 0x04d4, // XK_kana_YA
  2355. 0x30e5: 0x04ad, // XK_kana_yu
  2356. 0x30e6: 0x04d5, // XK_kana_YU
  2357. 0x30e7: 0x04ae, // XK_kana_yo
  2358. 0x30e8: 0x04d6, // XK_kana_YO
  2359. 0x30e9: 0x04d7, // XK_kana_RA
  2360. 0x30ea: 0x04d8, // XK_kana_RI
  2361. 0x30eb: 0x04d9, // XK_kana_RU
  2362. 0x30ec: 0x04da, // XK_kana_RE
  2363. 0x30ed: 0x04db, // XK_kana_RO
  2364. 0x30ef: 0x04dc, // XK_kana_WA
  2365. 0x30f2: 0x04a6, // XK_kana_WO
  2366. 0x30f3: 0x04dd, // XK_kana_N
  2367. 0x30fb: 0x04a5, // XK_kana_conjunctive
  2368. 0x30fc: 0x04b0, // XK_prolongedsound
  2369. };
  2370.  
  2371. var $$$core$input$keysymdef$$default = {
  2372. lookup : function(u) {
  2373. // Latin-1 is one-to-one mapping
  2374. if ((u >= 0x20) && (u <= 0xff)) {
  2375. return u;
  2376. }
  2377.  
  2378. // Lookup table (fairly random)
  2379. var keysym = $$$core$input$keysymdef$$codepoints[u];
  2380. if (keysym !== undefined) {
  2381. return keysym;
  2382. }
  2383.  
  2384. // General mapping as final fallback
  2385. return 0x01000000 | u;
  2386. }
  2387. };
  2388.  
  2389. function $$util$strings$$decodeUTF8(utf8string) {
  2390. "use strict";
  2391. return decodeURIComponent(escape(utf8string));
  2392. }
  2393.  
  2394. function $$util$properties$$make_property (proto, name, mode, type) {
  2395. "use strict";
  2396.  
  2397. var getter;
  2398. if (type === 'arr') {
  2399. getter = function (idx) {
  2400. if (typeof idx !== 'undefined') {
  2401. return this['_' + name][idx];
  2402. } else {
  2403. return this['_' + name];
  2404. }
  2405. };
  2406. } else {
  2407. getter = function () {
  2408. return this['_' + name];
  2409. };
  2410. }
  2411.  
  2412. var make_setter = function (process_val) {
  2413. if (process_val) {
  2414. return function (val, idx) {
  2415. if (typeof idx !== 'undefined') {
  2416. this['_' + name][idx] = process_val(val);
  2417. } else {
  2418. this['_' + name] = process_val(val);
  2419. }
  2420. };
  2421. } else {
  2422. return function (val, idx) {
  2423. if (typeof idx !== 'undefined') {
  2424. this['_' + name][idx] = val;
  2425. } else {
  2426. this['_' + name] = val;
  2427. }
  2428. };
  2429. }
  2430. };
  2431.  
  2432. var setter;
  2433. if (type === 'bool') {
  2434. setter = make_setter(function (val) {
  2435. if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) {
  2436. return false;
  2437. } else {
  2438. return true;
  2439. }
  2440. });
  2441. } else if (type === 'int') {
  2442. setter = make_setter(function (val) { return parseInt(val, 10); });
  2443. } else if (type === 'float') {
  2444. setter = make_setter(parseFloat);
  2445. } else if (type === 'str') {
  2446. setter = make_setter(String);
  2447. } else if (type === 'func') {
  2448. setter = make_setter(function (val) {
  2449. if (!val) {
  2450. return function () {};
  2451. } else {
  2452. return val;
  2453. }
  2454. });
  2455. } else if (type === 'arr' || type === 'dom' || type == 'raw') {
  2456. setter = make_setter();
  2457. } else {
  2458. throw new Error('Unknown property type ' + type); // some sanity checking
  2459. }
  2460.  
  2461. // set the getter
  2462. if (typeof proto['get_' + name] === 'undefined') {
  2463. proto['get_' + name] = getter;
  2464. }
  2465.  
  2466. // set the setter if needed
  2467. if (typeof proto['set_' + name] === 'undefined') {
  2468. if (mode === 'rw') {
  2469. proto['set_' + name] = setter;
  2470. } else if (mode === 'wo') {
  2471. proto['set_' + name] = function (val, idx) {
  2472. if (typeof this['_' + name] !== 'undefined') {
  2473. throw new Error(name + " can only be set once");
  2474. }
  2475. setter.call(this, val, idx);
  2476. };
  2477. }
  2478. }
  2479.  
  2480. // make a special setter that we can use in set defaults
  2481. proto['_raw_set_' + name] = function (val, idx) {
  2482. setter.call(this, val, idx);
  2483. //delete this['_init_set_' + name]; // remove it after use
  2484. };
  2485. }
  2486.  
  2487. function $$util$properties$$make_properties(constructor, arr) {
  2488. "use strict";
  2489. for (var i = 0; i < arr.length; i++) {
  2490. $$util$properties$$make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]);
  2491. }
  2492. }
  2493.  
  2494. function $$util$properties$$set_defaults(obj, conf, defaults) {
  2495. var defaults_keys = Object.keys(defaults);
  2496. var conf_keys = Object.keys(conf);
  2497. var keys_obj = {};
  2498. var i;
  2499. for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; }
  2500. for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; }
  2501. var keys = Object.keys(keys_obj);
  2502.  
  2503. for (i = 0; i < keys.length; i++) {
  2504. var setter = obj['_raw_set_' + keys[i]];
  2505. if (!setter) {
  2506. $$$core$util$logging$$.Warn('Invalid property ' + keys[i]);
  2507. continue;
  2508. }
  2509.  
  2510. if (keys[i] in conf) {
  2511. setter.call(obj, conf[keys[i]]);
  2512. } else {
  2513. setter.call(obj, defaults[keys[i]]);
  2514. }
  2515. }
  2516. }
  2517.  
  2518. var $$base64$$default = {
  2519. /* Convert data (an array of integers) to a Base64 string. */
  2520. toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
  2521.  
  2522. base64Pad : '=',
  2523.  
  2524. encode: function (data) {
  2525. "use strict";
  2526. var result = '';
  2527. var toBase64Table = this.toBase64Table;
  2528. var length = data.length;
  2529. var lengthpad = (length % 3);
  2530. // Convert every three bytes to 4 ascii characters.
  2531.  
  2532. for (var i = 0; i < (length - 2); i += 3) {
  2533. result += toBase64Table[data[i] >> 2];
  2534. result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
  2535. result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
  2536. result += toBase64Table[data[i + 2] & 0x3f];
  2537. }
  2538.  
  2539. // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
  2540. var j = 0;
  2541. if (lengthpad === 2) {
  2542. j = length - lengthpad;
  2543. result += toBase64Table[data[j] >> 2];
  2544. result += toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
  2545. result += toBase64Table[(data[j + 1] & 0x0f) << 2];
  2546. result += toBase64Table[64];
  2547. } else if (lengthpad === 1) {
  2548. j = length - lengthpad;
  2549. result += toBase64Table[data[j] >> 2];
  2550. result += toBase64Table[(data[j] & 0x03) << 4];
  2551. result += toBase64Table[64];
  2552. result += toBase64Table[64];
  2553. }
  2554.  
  2555. return result;
  2556. },
  2557.  
  2558. /* Convert Base64 data to a string */
  2559. /* jshint -W013 */
  2560. toBinaryTable : [
  2561. -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  2562. -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  2563. -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
  2564. 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
  2565. -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
  2566. 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
  2567. -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
  2568. 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
  2569. ],
  2570.  
  2571. /* jshint +W013 */
  2572.  
  2573. decode: function (data, offset) {
  2574. "use strict";
  2575. offset = typeof(offset) !== 'undefined' ? offset : 0;
  2576. var toBinaryTable = this.toBinaryTable;
  2577. var base64Pad = this.base64Pad;
  2578. var result, result_length;
  2579. var leftbits = 0; // number of bits decoded, but yet to be appended
  2580. var leftdata = 0; // bits decoded, but yet to be appended
  2581. var data_length = data.indexOf('=') - offset;
  2582.  
  2583. if (data_length < 0) { data_length = data.length - offset; }
  2584.  
  2585. /* Every four characters is 3 resulting numbers */
  2586. result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5);
  2587. result = new Array(result_length);
  2588.  
  2589. // Convert one by one.
  2590. for (var idx = 0, i = offset; i < data.length; i++) {
  2591. var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
  2592. var padding = (data.charAt(i) === base64Pad);
  2593. // Skip illegal characters and whitespace
  2594. if (c === -1) {
  2595. console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
  2596. continue;
  2597. }
  2598.  
  2599. // Collect data into leftdata, update bitcount
  2600. leftdata = (leftdata << 6) | c;
  2601. leftbits += 6;
  2602.  
  2603. // If we have 8 or more bits, append 8 bits to the result
  2604. if (leftbits >= 8) {
  2605. leftbits -= 8;
  2606. // Append if not padding.
  2607. if (!padding) {
  2608. result[idx++] = (leftdata >> leftbits) & 0xff;
  2609. }
  2610. leftdata &= (1 << leftbits) - 1;
  2611. }
  2612. }
  2613.  
  2614. // If there are any bits left, the base64 string was corrupted
  2615. if (leftbits) {
  2616. err = new Error('Corrupted base64 string');
  2617. err.name = 'Base64-Error';
  2618. throw err;
  2619. }
  2620.  
  2621. return result;
  2622. }
  2623. };
  2624.  
  2625. function $$$core$display$$Display(defaults) {
  2626. this._drawCtx = null;
  2627. this._c_forceCanvas = false;
  2628.  
  2629. this._renderQ = []; // queue drawing actions for in-oder rendering
  2630. this._flushing = false;
  2631.  
  2632. // the full frame buffer (logical canvas) size
  2633. this._fb_width = 0;
  2634. this._fb_height = 0;
  2635.  
  2636. this._prevDrawStyle = "";
  2637. this._tile = null;
  2638. this._tile16x16 = null;
  2639. this._tile_x = 0;
  2640. this._tile_y = 0;
  2641.  
  2642. $$util$properties$$set_defaults(this, defaults, {
  2643. 'scale': 1.0,
  2644. 'viewport': false,
  2645. 'render_mode': '',
  2646. "onFlush": function () {},
  2647. });
  2648.  
  2649. $$$core$util$logging$$.Debug(">> Display.constructor");
  2650.  
  2651. // The visible canvas
  2652. if (!this._target) {
  2653. throw new Error("Target must be set");
  2654. }
  2655.  
  2656. if (typeof this._target === 'string') {
  2657. throw new Error('target must be a DOM element');
  2658. }
  2659.  
  2660. if (!this._target.getContext) {
  2661. throw new Error("no getContext method");
  2662. }
  2663.  
  2664. this._targetCtx = this._target.getContext('2d');
  2665.  
  2666. // the visible canvas viewport (i.e. what actually gets seen)
  2667. this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
  2668.  
  2669. // The hidden canvas, where we do the actual rendering
  2670. this._backbuffer = document.createElement('canvas');
  2671. this._drawCtx = this._backbuffer.getContext('2d');
  2672.  
  2673. this._damageBounds = { left:0, top:0,
  2674. right: this._backbuffer.width,
  2675. bottom: this._backbuffer.height };
  2676.  
  2677. $$$core$util$logging$$.Debug("User Agent: " + navigator.userAgent);
  2678.  
  2679. this.clear();
  2680.  
  2681. // Check canvas features
  2682. if ('createImageData' in this._drawCtx) {
  2683. this._render_mode = 'canvas rendering';
  2684. } else {
  2685. throw new Error("Canvas does not support createImageData");
  2686. }
  2687.  
  2688. if (this._prefer_js === null) {
  2689. $$$core$util$logging$$.Info("Prefering javascript operations");
  2690. this._prefer_js = true;
  2691. }
  2692.  
  2693. // Determine browser support for setting the cursor via data URI scheme
  2694. if (this._cursor_uri || this._cursor_uri === null ||
  2695. this._cursor_uri === undefined) {
  2696. this._cursor_uri = $$$core$util$browsers$$browserSupportsCursorURIs();
  2697. }
  2698.  
  2699. $$$core$util$logging$$.Debug("<< Display.constructor");
  2700. }
  2701.  
  2702. var $$$core$display$$default = $$$core$display$$Display;
  2703.  
  2704. var $$$core$display$$SUPPORTS_IMAGEDATA_CONSTRUCTOR = false;
  2705. try {
  2706. new ImageData(new Uint8ClampedArray(4), 1, 1);
  2707. $$$core$display$$SUPPORTS_IMAGEDATA_CONSTRUCTOR = true;
  2708. } catch (ex) {
  2709. // ignore failure
  2710. }
  2711.  
  2712. $$$core$display$$Display.prototype = {
  2713. // Public methods
  2714. viewportChangePos: function (deltaX, deltaY) {
  2715. var vp = this._viewportLoc;
  2716. deltaX = Math.floor(deltaX);
  2717. deltaY = Math.floor(deltaY);
  2718.  
  2719. if (!this._viewport) {
  2720. deltaX = -vp.w; // clamped later of out of bounds
  2721. deltaY = -vp.h;
  2722. }
  2723.  
  2724. var vx2 = vp.x + vp.w - 1;
  2725. var vy2 = vp.y + vp.h - 1;
  2726.  
  2727. // Position change
  2728.  
  2729. if (deltaX < 0 && vp.x + deltaX < 0) {
  2730. deltaX = -vp.x;
  2731. }
  2732. if (vx2 + deltaX >= this._fb_width) {
  2733. deltaX -= vx2 + deltaX - this._fb_width + 1;
  2734. }
  2735.  
  2736. if (vp.y + deltaY < 0) {
  2737. deltaY = -vp.y;
  2738. }
  2739. if (vy2 + deltaY >= this._fb_height) {
  2740. deltaY -= (vy2 + deltaY - this._fb_height + 1);
  2741. }
  2742.  
  2743. if (deltaX === 0 && deltaY === 0) {
  2744. return;
  2745. }
  2746. $$$core$util$logging$$.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY);
  2747.  
  2748. vp.x += deltaX;
  2749. vp.y += deltaY;
  2750.  
  2751. this._damage(vp.x, vp.y, vp.w, vp.h);
  2752.  
  2753. this.flip();
  2754. },
  2755.  
  2756. viewportChangeSize: function(width, height) {
  2757.  
  2758. if (!this._viewport ||
  2759. typeof(width) === "undefined" ||
  2760. typeof(height) === "undefined") {
  2761.  
  2762. $$$core$util$logging$$.Debug("Setting viewport to full display region");
  2763. width = this._fb_width;
  2764. height = this._fb_height;
  2765. }
  2766.  
  2767. if (width > this._fb_width) {
  2768. width = this._fb_width;
  2769. }
  2770. if (height > this._fb_height) {
  2771. height = this._fb_height;
  2772. }
  2773.  
  2774. var vp = this._viewportLoc;
  2775. if (vp.w !== width || vp.h !== height) {
  2776. vp.w = width;
  2777. vp.h = height;
  2778.  
  2779. var canvas = this._target;
  2780. canvas.width = width;
  2781. canvas.height = height;
  2782.  
  2783. // The position might need to be updated if we've grown
  2784. this.viewportChangePos(0, 0);
  2785.  
  2786. this._damage(vp.x, vp.y, vp.w, vp.h);
  2787. this.flip();
  2788.  
  2789. // Update the visible size of the target canvas
  2790. this._rescale(this._scale);
  2791. }
  2792. },
  2793.  
  2794. absX: function (x) {
  2795. return x / this._scale + this._viewportLoc.x;
  2796. },
  2797.  
  2798. absY: function (y) {
  2799. return y / this._scale + this._viewportLoc.y;
  2800. },
  2801.  
  2802. resize: function (width, height) {
  2803. this._prevDrawStyle = "";
  2804.  
  2805. this._fb_width = width;
  2806. this._fb_height = height;
  2807.  
  2808. var canvas = this._backbuffer;
  2809. if (canvas.width !== width || canvas.height !== height) {
  2810.  
  2811. // We have to save the canvas data since changing the size will clear it
  2812. var saveImg = null;
  2813. if (canvas.width > 0 && canvas.height > 0) {
  2814. saveImg = this._drawCtx.getImageData(0, 0, canvas.width, canvas.height);
  2815. }
  2816.  
  2817. if (canvas.width !== width) {
  2818. canvas.width = width;
  2819. }
  2820. if (canvas.height !== height) {
  2821. canvas.height = height;
  2822. }
  2823.  
  2824. if (saveImg) {
  2825. this._drawCtx.putImageData(saveImg, 0, 0);
  2826. }
  2827. }
  2828.  
  2829. // Readjust the viewport as it may be incorrectly sized
  2830. // and positioned
  2831. var vp = this._viewportLoc;
  2832. this.viewportChangeSize(vp.w, vp.h);
  2833. this.viewportChangePos(0, 0);
  2834. },
  2835.  
  2836. // Track what parts of the visible canvas that need updating
  2837. _damage: function(x, y, w, h) {
  2838. if (x < this._damageBounds.left) {
  2839. this._damageBounds.left = x;
  2840. }
  2841. if (y < this._damageBounds.top) {
  2842. this._damageBounds.top = y;
  2843. }
  2844. if ((x + w) > this._damageBounds.right) {
  2845. this._damageBounds.right = x + w;
  2846. }
  2847. if ((y + h) > this._damageBounds.bottom) {
  2848. this._damageBounds.bottom = y + h;
  2849. }
  2850. },
  2851.  
  2852. // Update the visible canvas with the contents of the
  2853. // rendering canvas
  2854. flip: function(from_queue) {
  2855. if (this._renderQ.length !== 0 && !from_queue) {
  2856. this._renderQ_push({
  2857. 'type': 'flip'
  2858. });
  2859. } else {
  2860. var x, y, vx, vy, w, h;
  2861.  
  2862. x = this._damageBounds.left;
  2863. y = this._damageBounds.top;
  2864. w = this._damageBounds.right - x;
  2865. h = this._damageBounds.bottom - y;
  2866.  
  2867. vx = x - this._viewportLoc.x;
  2868. vy = y - this._viewportLoc.y;
  2869.  
  2870. if (vx < 0) {
  2871. w += vx;
  2872. x -= vx;
  2873. vx = 0;
  2874. }
  2875. if (vy < 0) {
  2876. h += vy;
  2877. y -= vy;
  2878. vy = 0;
  2879. }
  2880.  
  2881. if ((vx + w) > this._viewportLoc.w) {
  2882. w = this._viewportLoc.w - vx;
  2883. }
  2884. if ((vy + h) > this._viewportLoc.h) {
  2885. h = this._viewportLoc.h - vy;
  2886. }
  2887.  
  2888. if ((w > 0) && (h > 0)) {
  2889. // FIXME: We may need to disable image smoothing here
  2890. // as well (see copyImage()), but we haven't
  2891. // noticed any problem yet.
  2892. this._targetCtx.drawImage(this._backbuffer,
  2893. x, y, w, h,
  2894. vx, vy, w, h);
  2895. }
  2896.  
  2897. this._damageBounds.left = this._damageBounds.top = 65535;
  2898. this._damageBounds.right = this._damageBounds.bottom = 0;
  2899. }
  2900. },
  2901.  
  2902. clear: function () {
  2903. if (this._logo) {
  2904. this.resize(this._logo.width, this._logo.height);
  2905. this.imageRect(0, 0, this._logo.type, this._logo.data);
  2906. } else {
  2907. this.resize(240, 20);
  2908. this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height);
  2909. }
  2910. this.flip();
  2911. },
  2912.  
  2913. pending: function() {
  2914. return this._renderQ.length > 0;
  2915. },
  2916.  
  2917. flush: function() {
  2918. if (this._renderQ.length === 0) {
  2919. this._onFlush();
  2920. } else {
  2921. this._flushing = true;
  2922. }
  2923. },
  2924.  
  2925. fillRect: function (x, y, width, height, color, from_queue) {
  2926. if (this._renderQ.length !== 0 && !from_queue) {
  2927. this._renderQ_push({
  2928. 'type': 'fill',
  2929. 'x': x,
  2930. 'y': y,
  2931. 'width': width,
  2932. 'height': height,
  2933. 'color': color
  2934. });
  2935. } else {
  2936. this._setFillColor(color);
  2937. this._drawCtx.fillRect(x, y, width, height);
  2938. this._damage(x, y, width, height);
  2939. }
  2940. },
  2941.  
  2942. copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) {
  2943. if (this._renderQ.length !== 0 && !from_queue) {
  2944. this._renderQ_push({
  2945. 'type': 'copy',
  2946. 'old_x': old_x,
  2947. 'old_y': old_y,
  2948. 'x': new_x,
  2949. 'y': new_y,
  2950. 'width': w,
  2951. 'height': h,
  2952. });
  2953. } else {
  2954. // Due to this bug among others [1] we need to disable the image-smoothing to
  2955. // avoid getting a blur effect when copying data.
  2956. //
  2957. // 1. https://bugzilla.mozilla.org/show_bug.cgi?id=1194719
  2958. //
  2959. // We need to set these every time since all properties are reset
  2960. // when the the size is changed
  2961. this._drawCtx.mozImageSmoothingEnabled = false;
  2962. this._drawCtx.webkitImageSmoothingEnabled = false;
  2963. this._drawCtx.msImageSmoothingEnabled = false;
  2964. this._drawCtx.imageSmoothingEnabled = false;
  2965.  
  2966. this._drawCtx.drawImage(this._backbuffer,
  2967. old_x, old_y, w, h,
  2968. new_x, new_y, w, h);
  2969. this._damage(new_x, new_y, w, h);
  2970. }
  2971. },
  2972.  
  2973. imageRect: function(x, y, mime, arr) {
  2974. var img = new Image();
  2975. img.src = "data: " + mime + ";base64," + $$base64$$default.encode(arr);
  2976. this._renderQ_push({
  2977. 'type': 'img',
  2978. 'img': img,
  2979. 'x': x,
  2980. 'y': y
  2981. });
  2982. },
  2983.  
  2984. // start updating a tile
  2985. startTile: function (x, y, width, height, color) {
  2986. this._tile_x = x;
  2987. this._tile_y = y;
  2988. if (width === 16 && height === 16) {
  2989. this._tile = this._tile16x16;
  2990. } else {
  2991. this._tile = this._drawCtx.createImageData(width, height);
  2992. }
  2993.  
  2994. if (this._prefer_js) {
  2995. var red = color[2];
  2996. var green = color[1];
  2997. var blue = color[0];
  2998.  
  2999. var data = this._tile.data;
  3000. for (var i = 0; i < width * height * 4; i += 4) {
  3001. data[i] = red;
  3002. data[i + 1] = green;
  3003. data[i + 2] = blue;
  3004. data[i + 3] = 255;
  3005. }
  3006. } else {
  3007. this.fillRect(x, y, width, height, color, true);
  3008. }
  3009. },
  3010.  
  3011. // update sub-rectangle of the current tile
  3012. subTile: function (x, y, w, h, color) {
  3013. if (this._prefer_js) {
  3014. var red = color[2];
  3015. var green = color[1];
  3016. var blue = color[0];
  3017. var xend = x + w;
  3018. var yend = y + h;
  3019.  
  3020. var data = this._tile.data;
  3021. var width = this._tile.width;
  3022. for (var j = y; j < yend; j++) {
  3023. for (var i = x; i < xend; i++) {
  3024. var p = (i + (j * width)) * 4;
  3025. data[p] = red;
  3026. data[p + 1] = green;
  3027. data[p + 2] = blue;
  3028. data[p + 3] = 255;
  3029. }
  3030. }
  3031. } else {
  3032. this.fillRect(this._tile_x + x, this._tile_y + y, w, h, color, true);
  3033. }
  3034. },
  3035.  
  3036. // draw the current tile to the screen
  3037. finishTile: function () {
  3038. if (this._prefer_js) {
  3039. this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
  3040. this._damage(this._tile_x, this._tile_y,
  3041. this._tile.width, this._tile.height);
  3042. }
  3043. // else: No-op -- already done by setSubTile
  3044. },
  3045.  
  3046. blitImage: function (x, y, width, height, arr, offset, from_queue) {
  3047. if (this._renderQ.length !== 0 && !from_queue) {
  3048. // NB(directxman12): it's technically more performant here to use preallocated arrays,
  3049. // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
  3050. // this probably isn't getting called *nearly* as much
  3051. var new_arr = new Uint8Array(width * height * 4);
  3052. new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
  3053. this._renderQ_push({
  3054. 'type': 'blit',
  3055. 'data': new_arr,
  3056. 'x': x,
  3057. 'y': y,
  3058. 'width': width,
  3059. 'height': height,
  3060. });
  3061. } else {
  3062. this._bgrxImageData(x, y, width, height, arr, offset);
  3063. }
  3064. },
  3065.  
  3066. blitRgbImage: function (x, y , width, height, arr, offset, from_queue) {
  3067. if (this._renderQ.length !== 0 && !from_queue) {
  3068. // NB(directxman12): it's technically more performant here to use preallocated arrays,
  3069. // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
  3070. // this probably isn't getting called *nearly* as much
  3071. var new_arr = new Uint8Array(width * height * 3);
  3072. new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
  3073. this._renderQ_push({
  3074. 'type': 'blitRgb',
  3075. 'data': new_arr,
  3076. 'x': x,
  3077. 'y': y,
  3078. 'width': width,
  3079. 'height': height,
  3080. });
  3081. } else {
  3082. this._rgbImageData(x, y, width, height, arr, offset);
  3083. }
  3084. },
  3085.  
  3086. blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) {
  3087. if (this._renderQ.length !== 0 && !from_queue) {
  3088. // NB(directxman12): it's technically more performant here to use preallocated arrays,
  3089. // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
  3090. // this probably isn't getting called *nearly* as much
  3091. var new_arr = new Uint8Array(width * height * 4);
  3092. new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
  3093. this._renderQ_push({
  3094. 'type': 'blitRgbx',
  3095. 'data': new_arr,
  3096. 'x': x,
  3097. 'y': y,
  3098. 'width': width,
  3099. 'height': height,
  3100. });
  3101. } else {
  3102. this._rgbxImageData(x, y, width, height, arr, offset);
  3103. }
  3104. },
  3105.  
  3106. drawImage: function (img, x, y) {
  3107. this._drawCtx.drawImage(img, x, y);
  3108. this._damage(x, y, img.width, img.height);
  3109. },
  3110.  
  3111. changeCursor: function (pixels, mask, hotx, hoty, w, h) {
  3112. if (this._cursor_uri === false) {
  3113. $$$core$util$logging$$.Warn("changeCursor called but no cursor data URI support");
  3114. return;
  3115. }
  3116.  
  3117. $$$core$display$$Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h);
  3118. },
  3119.  
  3120. defaultCursor: function () {
  3121. this._target.style.cursor = "default";
  3122. },
  3123.  
  3124. disableLocalCursor: function () {
  3125. this._target.style.cursor = "none";
  3126. },
  3127.  
  3128. clippingDisplay: function () {
  3129. var vp = this._viewportLoc;
  3130. return this._fb_width > vp.w || this._fb_height > vp.h;
  3131. },
  3132.  
  3133. // Overridden getters/setters
  3134. set_scale: function (scale) {
  3135. this._rescale(scale);
  3136. },
  3137.  
  3138. set_viewport: function (viewport) {
  3139. this._viewport = viewport;
  3140. // May need to readjust the viewport dimensions
  3141. var vp = this._viewportLoc;
  3142. this.viewportChangeSize(vp.w, vp.h);
  3143. this.viewportChangePos(0, 0);
  3144. },
  3145.  
  3146. get_width: function () {
  3147. return this._fb_width;
  3148. },
  3149. get_height: function () {
  3150. return this._fb_height;
  3151. },
  3152.  
  3153. autoscale: function (containerWidth, containerHeight, downscaleOnly) {
  3154. var vp = this._viewportLoc;
  3155. var targetAspectRatio = containerWidth / containerHeight;
  3156. var fbAspectRatio = vp.w / vp.h;
  3157.  
  3158. var scaleRatio;
  3159. if (fbAspectRatio >= targetAspectRatio) {
  3160. scaleRatio = containerWidth / vp.w;
  3161. } else {
  3162. scaleRatio = containerHeight / vp.h;
  3163. }
  3164.  
  3165. if (scaleRatio > 1.0 && downscaleOnly) {
  3166. scaleRatio = 1.0;
  3167. }
  3168.  
  3169. this._rescale(scaleRatio);
  3170. },
  3171.  
  3172. // Private Methods
  3173. _rescale: function (factor) {
  3174. this._scale = factor;
  3175. var vp = this._viewportLoc;
  3176.  
  3177. // NB(directxman12): If you set the width directly, or set the
  3178. // style width to a number, the canvas is cleared.
  3179. // However, if you set the style width to a string
  3180. // ('NNNpx'), the canvas is scaled without clearing.
  3181. var width = Math.round(factor * vp.w) + 'px';
  3182. var height = Math.round(factor * vp.h) + 'px';
  3183.  
  3184. if ((this._target.style.width !== width) ||
  3185. (this._target.style.height !== height)) {
  3186. this._target.style.width = width;
  3187. this._target.style.height = height;
  3188. }
  3189. },
  3190.  
  3191. _setFillColor: function (color) {
  3192. var newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
  3193. if (newStyle !== this._prevDrawStyle) {
  3194. this._drawCtx.fillStyle = newStyle;
  3195. this._prevDrawStyle = newStyle;
  3196. }
  3197. },
  3198.  
  3199. _rgbImageData: function (x, y, width, height, arr, offset) {
  3200. var img = this._drawCtx.createImageData(width, height);
  3201. var data = img.data;
  3202. for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 3) {
  3203. data[i] = arr[j];
  3204. data[i + 1] = arr[j + 1];
  3205. data[i + 2] = arr[j + 2];
  3206. data[i + 3] = 255; // Alpha
  3207. }
  3208. this._drawCtx.putImageData(img, x, y);
  3209. this._damage(x, y, img.width, img.height);
  3210. },
  3211.  
  3212. _bgrxImageData: function (x, y, width, height, arr, offset) {
  3213. var img = this._drawCtx.createImageData(width, height);
  3214. var data = img.data;
  3215. for (var i = 0, j = offset; i < width * height * 4; i += 4, j += 4) {
  3216. data[i] = arr[j + 2];
  3217. data[i + 1] = arr[j + 1];
  3218. data[i + 2] = arr[j];
  3219. data[i + 3] = 255; // Alpha
  3220. }
  3221. this._drawCtx.putImageData(img, x, y);
  3222. this._damage(x, y, img.width, img.height);
  3223. },
  3224.  
  3225. _rgbxImageData: function (x, y, width, height, arr, offset) {
  3226. // NB(directxman12): arr must be an Type Array view
  3227. var img;
  3228. if ($$$core$display$$SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
  3229. img = new ImageData(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4), width, height);
  3230. } else {
  3231. img = this._drawCtx.createImageData(width, height);
  3232. img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4));
  3233. }
  3234. this._drawCtx.putImageData(img, x, y);
  3235. this._damage(x, y, img.width, img.height);
  3236. },
  3237.  
  3238. _renderQ_push: function (action) {
  3239. this._renderQ.push(action);
  3240. if (this._renderQ.length === 1) {
  3241. // If this can be rendered immediately it will be, otherwise
  3242. // the scanner will wait for the relevant event
  3243. this._scan_renderQ();
  3244. }
  3245. },
  3246.  
  3247. _resume_renderQ: function() {
  3248. // "this" is the object that is ready, not the
  3249. // display object
  3250. this.removeEventListener('load', this._noVNC_display._resume_renderQ);
  3251. this._noVNC_display._scan_renderQ();
  3252. },
  3253.  
  3254. _scan_renderQ: function () {
  3255. var ready = true;
  3256. while (ready && this._renderQ.length > 0) {
  3257. var a = this._renderQ[0];
  3258. switch (a.type) {
  3259. case 'flip':
  3260. this.flip(true);
  3261. break;
  3262. case 'copy':
  3263. this.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height, true);
  3264. break;
  3265. case 'fill':
  3266. this.fillRect(a.x, a.y, a.width, a.height, a.color, true);
  3267. break;
  3268. case 'blit':
  3269. this.blitImage(a.x, a.y, a.width, a.height, a.data, 0, true);
  3270. break;
  3271. case 'blitRgb':
  3272. this.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0, true);
  3273. break;
  3274. case 'blitRgbx':
  3275. this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0, true);
  3276. break;
  3277. case 'img':
  3278. if (a.img.complete) {
  3279. this.drawImage(a.img, a.x, a.y);
  3280. } else {
  3281. a.img._noVNC_display = this;
  3282. a.img.addEventListener('load', this._resume_renderQ);
  3283. // We need to wait for this image to 'load'
  3284. // to keep things in-order
  3285. ready = false;
  3286. }
  3287. break;
  3288. }
  3289.  
  3290. if (ready) {
  3291. this._renderQ.shift();
  3292. }
  3293. }
  3294.  
  3295. if (this._renderQ.length === 0 && this._flushing) {
  3296. this._flushing = false;
  3297. this._onFlush();
  3298. }
  3299. },
  3300. };
  3301.  
  3302. $$util$properties$$make_properties($$$core$display$$Display, [
  3303. ['target', 'wo', 'dom'], // Canvas element for rendering
  3304. ['context', 'ro', 'raw'], // Canvas 2D context for rendering (read-only)
  3305. ['logo', 'rw', 'raw'], // Logo to display when cleared: {"width": w, "height": h, "type": mime-type, "data": data}
  3306. ['scale', 'rw', 'float'], // Display area scale factor 0.0 - 1.0
  3307. ['viewport', 'rw', 'bool'], // Use viewport clipping
  3308. ['width', 'ro', 'int'], // Display area width
  3309. ['height', 'ro', 'int'], // Display area height
  3310.  
  3311. ['render_mode', 'ro', 'str'], // Canvas rendering mode (read-only)
  3312.  
  3313. ['prefer_js', 'rw', 'str'], // Prefer Javascript over canvas methods
  3314. ['cursor_uri', 'rw', 'raw'], // Can we render cursor using data URI
  3315.  
  3316. ['onFlush', 'rw', 'func'], // onFlush(): A flush request has finished
  3317. ]);
  3318.  
  3319. // Class Methods
  3320. $$$core$display$$Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) {
  3321. if ((w === 0) || (h === 0)) {
  3322. target.style.cursor = 'none';
  3323. return;
  3324. }
  3325.  
  3326. var cur = []
  3327. var y, x;
  3328. for (y = 0; y < h; y++) {
  3329. for (x = 0; x < w; x++) {
  3330. var idx = y * Math.ceil(w / 8) + Math.floor(x / 8);
  3331. var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
  3332. idx = ((w * y) + x) * 4;
  3333. cur.push(pixels[idx + 2]); // red
  3334. cur.push(pixels[idx + 1]); // green
  3335. cur.push(pixels[idx]); // blue
  3336. cur.push(alpha); // alpha
  3337. }
  3338. }
  3339.  
  3340. var canvas = document.createElement('canvas');
  3341. var ctx = canvas.getContext('2d');
  3342.  
  3343. canvas.width = w;
  3344. canvas.height = h;
  3345.  
  3346. var img;
  3347. if ($$$core$display$$SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
  3348. img = new ImageData(new Uint8ClampedArray(cur), w, h);
  3349. } else {
  3350. img = ctx.createImageData(w, h);
  3351. img.data.set(new Uint8ClampedArray(cur));
  3352. }
  3353. ctx.clearRect(0, 0, w, h);
  3354. ctx.putImageData(img, 0, 0);
  3355.  
  3356. var url = canvas.toDataURL();
  3357. target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default';
  3358. };
  3359.  
  3360. var $$vkeys$$default = {
  3361. 0x08: 'Backspace',
  3362. 0x09: 'Tab',
  3363. 0x0a: 'NumpadClear',
  3364. 0x0d: 'Enter',
  3365. 0x10: 'ShiftLeft',
  3366. 0x11: 'ControlLeft',
  3367. 0x12: 'AltLeft',
  3368. 0x13: 'Pause',
  3369. 0x14: 'CapsLock',
  3370. 0x15: 'Lang1',
  3371. 0x19: 'Lang2',
  3372. 0x1b: 'Escape',
  3373. 0x1c: 'Convert',
  3374. 0x1d: 'NonConvert',
  3375. 0x20: 'Space',
  3376. 0x21: 'PageUp',
  3377. 0x22: 'PageDown',
  3378. 0x23: 'End',
  3379. 0x24: 'Home',
  3380. 0x25: 'ArrowLeft',
  3381. 0x26: 'ArrowUp',
  3382. 0x27: 'ArrowRight',
  3383. 0x28: 'ArrowDown',
  3384. 0x29: 'Select',
  3385. 0x2c: 'PrintScreen',
  3386. 0x2d: 'Insert',
  3387. 0x2e: 'Delete',
  3388. 0x2f: 'Help',
  3389. 0x30: 'Digit0',
  3390. 0x31: 'Digit1',
  3391. 0x32: 'Digit2',
  3392. 0x33: 'Digit3',
  3393. 0x34: 'Digit4',
  3394. 0x35: 'Digit5',
  3395. 0x36: 'Digit6',
  3396. 0x37: 'Digit7',
  3397. 0x38: 'Digit8',
  3398. 0x39: 'Digit9',
  3399. 0x5b: 'MetaLeft',
  3400. 0x5c: 'MetaRight',
  3401. 0x5d: 'ContextMenu',
  3402. 0x5f: 'Sleep',
  3403. 0x60: 'Numpad0',
  3404. 0x61: 'Numpad1',
  3405. 0x62: 'Numpad2',
  3406. 0x63: 'Numpad3',
  3407. 0x64: 'Numpad4',
  3408. 0x65: 'Numpad5',
  3409. 0x66: 'Numpad6',
  3410. 0x67: 'Numpad7',
  3411. 0x68: 'Numpad8',
  3412. 0x69: 'Numpad9',
  3413. 0x6a: 'NumpadMultiply',
  3414. 0x6b: 'NumpadAdd',
  3415. 0x6c: 'NumpadDecimal',
  3416. 0x6d: 'NumpadSubtract',
  3417.  
  3418. // Duplicate, because buggy on Windows
  3419. 0x6e: 'NumpadDecimal',
  3420.  
  3421. 0x6f: 'NumpadDivide',
  3422. 0x70: 'F1',
  3423. 0x71: 'F2',
  3424. 0x72: 'F3',
  3425. 0x73: 'F4',
  3426. 0x74: 'F5',
  3427. 0x75: 'F6',
  3428. 0x76: 'F7',
  3429. 0x77: 'F8',
  3430. 0x78: 'F9',
  3431. 0x79: 'F10',
  3432. 0x7a: 'F11',
  3433. 0x7b: 'F12',
  3434. 0x7c: 'F13',
  3435. 0x7d: 'F14',
  3436. 0x7e: 'F15',
  3437. 0x7f: 'F16',
  3438. 0x80: 'F17',
  3439. 0x81: 'F18',
  3440. 0x82: 'F19',
  3441. 0x83: 'F20',
  3442. 0x84: 'F21',
  3443. 0x85: 'F22',
  3444. 0x86: 'F23',
  3445. 0x87: 'F24',
  3446. 0x90: 'NumLock',
  3447. 0x91: 'ScrollLock',
  3448. 0xa6: 'BrowserBack',
  3449. 0xa7: 'BrowserForward',
  3450. 0xa8: 'BrowserRefresh',
  3451. 0xa9: 'BrowserStop',
  3452. 0xaa: 'BrowserSearch',
  3453. 0xab: 'BrowserFavorites',
  3454. 0xac: 'BrowserHome',
  3455. 0xad: 'AudioVolumeMute',
  3456. 0xae: 'AudioVolumeDown',
  3457. 0xaf: 'AudioVolumeUp',
  3458. 0xb0: 'MediaTrackNext',
  3459. 0xb1: 'MediaTrackPrevious',
  3460. 0xb2: 'MediaStop',
  3461. 0xb3: 'MediaPlayPause',
  3462. 0xb4: 'LaunchMail',
  3463. 0xb5: 'MediaSelect',
  3464. 0xb6: 'LaunchApp1',
  3465. 0xb7: 'LaunchApp2',
  3466.  
  3467. // Only when it is AltGraph
  3468. 0xe1: 'AltRight'
  3469. };
  3470.  
  3471. var $$fixedkeys$$default = {
  3472. // 3.1.1.1. Writing System Keys
  3473.  
  3474. 'Backspace': 'Backspace',
  3475.  
  3476. // 3.1.1.2. Functional Keys
  3477.  
  3478. 'AltLeft': 'Alt',
  3479.  
  3480. // This could also be 'AltGraph'
  3481. 'AltRight': 'Alt',
  3482.  
  3483. 'CapsLock': 'CapsLock',
  3484. 'ContextMenu': 'ContextMenu',
  3485. 'ControlLeft': 'Control',
  3486. 'ControlRight': 'Control',
  3487. 'Enter': 'Enter',
  3488. 'MetaLeft': 'Meta',
  3489. 'MetaRight': 'Meta',
  3490. 'ShiftLeft': 'Shift',
  3491. 'ShiftRight': 'Shift',
  3492. 'Tab': 'Tab',
  3493.  
  3494. // FIXME: Japanese/Korean keys
  3495.  
  3496. // 3.1.2. Control Pad Section
  3497.  
  3498. 'Delete': 'Delete',
  3499.  
  3500. 'End': 'End',
  3501. 'Help': 'Help',
  3502. 'Home': 'Home',
  3503. 'Insert': 'Insert',
  3504. 'PageDown': 'PageDown',
  3505. 'PageUp': 'PageUp',
  3506.  
  3507. // 3.1.3. Arrow Pad Section
  3508.  
  3509. 'ArrowDown': 'ArrowDown',
  3510.  
  3511. 'ArrowLeft': 'ArrowLeft',
  3512. 'ArrowRight': 'ArrowRight',
  3513. 'ArrowUp': 'ArrowUp',
  3514.  
  3515. // 3.1.4. Numpad Section
  3516.  
  3517. 'NumLock': 'NumLock',
  3518.  
  3519. 'NumpadBackspace': 'Backspace',
  3520. 'NumpadClear': 'Clear',
  3521.  
  3522. // 3.1.5. Function Section
  3523.  
  3524. 'Escape': 'Escape',
  3525.  
  3526. 'F1': 'F1',
  3527. 'F2': 'F2',
  3528. 'F3': 'F3',
  3529. 'F4': 'F4',
  3530. 'F5': 'F5',
  3531. 'F6': 'F6',
  3532. 'F7': 'F7',
  3533. 'F8': 'F8',
  3534. 'F9': 'F9',
  3535. 'F10': 'F10',
  3536. 'F11': 'F11',
  3537. 'F12': 'F12',
  3538. 'F13': 'F13',
  3539. 'F14': 'F14',
  3540. 'F15': 'F15',
  3541. 'F16': 'F16',
  3542. 'F17': 'F17',
  3543. 'F18': 'F18',
  3544. 'F19': 'F19',
  3545. 'F20': 'F20',
  3546. 'F21': 'F21',
  3547. 'F22': 'F22',
  3548. 'F23': 'F23',
  3549. 'F24': 'F24',
  3550. 'F25': 'F25',
  3551. 'F26': 'F26',
  3552. 'F27': 'F27',
  3553. 'F28': 'F28',
  3554. 'F29': 'F29',
  3555. 'F30': 'F30',
  3556. 'F31': 'F31',
  3557. 'F32': 'F32',
  3558. 'F33': 'F33',
  3559. 'F34': 'F34',
  3560. 'F35': 'F35',
  3561. 'PrintScreen': 'PrintScreen',
  3562. 'ScrollLock': 'ScrollLock',
  3563. 'Pause': 'Pause',
  3564.  
  3565. // 3.1.6. Media Keys
  3566.  
  3567. 'BrowserBack': 'BrowserBack',
  3568.  
  3569. 'BrowserFavorites': 'BrowserFavorites',
  3570. 'BrowserForward': 'BrowserForward',
  3571. 'BrowserHome': 'BrowserHome',
  3572. 'BrowserRefresh': 'BrowserRefresh',
  3573. 'BrowserSearch': 'BrowserSearch',
  3574. 'BrowserStop': 'BrowserStop',
  3575. 'Eject': 'Eject',
  3576. 'LaunchApp1': 'LaunchMyComputer',
  3577. 'LaunchApp2': 'LaunchCalendar',
  3578. 'LaunchMail': 'LaunchMail',
  3579. 'MediaPlayPause': 'MediaPlay',
  3580. 'MediaStop': 'MediaStop',
  3581. 'MediaTrackNext': 'MediaTrackNext',
  3582. 'MediaTrackPrevious': 'MediaTrackPrevious',
  3583. 'Power': 'Power',
  3584. 'Sleep': 'Sleep',
  3585. 'AudioVolumeDown': 'AudioVolumeDown',
  3586. 'AudioVolumeMute': 'AudioVolumeMute',
  3587. 'AudioVolumeUp': 'AudioVolumeUp',
  3588. 'WakeUp': 'WakeUp'
  3589. };
  3590.  
  3591. /*
  3592. * Mapping between HTML key values and VNC/X11 keysyms for "special"
  3593. * keys that cannot be handled via their Unicode codepoint.
  3594. *
  3595. * See https://www.w3.org/TR/uievents-key/ for possible values.
  3596. */
  3597.  
  3598. var $$domkeytable$$DOMKeyTable = {};
  3599.  
  3600. function $$domkeytable$$addStandard(key, standard)
  3601. {
  3602. if (standard === undefined) throw "Undefined keysym for key \"" + key + "\"";
  3603. if (key in $$domkeytable$$DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
  3604. $$domkeytable$$DOMKeyTable[key] = [standard, standard, standard, standard];
  3605. }
  3606.  
  3607. function $$domkeytable$$addLeftRight(key, left, right)
  3608. {
  3609. if (left === undefined) throw "Undefined keysym for key \"" + key + "\"";
  3610. if (right === undefined) throw "Undefined keysym for key \"" + key + "\"";
  3611. if (key in $$domkeytable$$DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
  3612. $$domkeytable$$DOMKeyTable[key] = [left, left, right, left];
  3613. }
  3614.  
  3615. function $$domkeytable$$addNumpad(key, standard, numpad)
  3616. {
  3617. if (standard === undefined) throw "Undefined keysym for key \"" + key + "\"";
  3618. if (numpad === undefined) throw "Undefined keysym for key \"" + key + "\"";
  3619. if (key in $$domkeytable$$DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
  3620. $$domkeytable$$DOMKeyTable[key] = [standard, standard, standard, numpad];
  3621. }
  3622.  
  3623. // 2.2. Modifier Keys
  3624.  
  3625. $$domkeytable$$addLeftRight("Alt", $$$core$input$keysym$$default.XK_Alt_L, $$$core$input$keysym$$default.XK_Alt_R);
  3626. $$domkeytable$$addStandard("AltGraph", $$$core$input$keysym$$default.XK_ISO_Level3_Shift);
  3627. $$domkeytable$$addStandard("CapsLock", $$$core$input$keysym$$default.XK_Caps_Lock);
  3628. $$domkeytable$$addLeftRight("Control", $$$core$input$keysym$$default.XK_Control_L, $$$core$input$keysym$$default.XK_Control_R);
  3629. // - Fn
  3630. // - FnLock
  3631. $$domkeytable$$addLeftRight("Hyper", $$$core$input$keysym$$default.XK_Super_L, $$$core$input$keysym$$default.XK_Super_R);
  3632. $$domkeytable$$addLeftRight("Meta", $$$core$input$keysym$$default.XK_Super_L, $$$core$input$keysym$$default.XK_Super_R);
  3633. $$domkeytable$$addStandard("NumLock", $$$core$input$keysym$$default.XK_Num_Lock);
  3634. $$domkeytable$$addStandard("ScrollLock", $$$core$input$keysym$$default.XK_Scroll_Lock);
  3635. $$domkeytable$$addLeftRight("Shift", $$$core$input$keysym$$default.XK_Shift_L, $$$core$input$keysym$$default.XK_Shift_R);
  3636. $$domkeytable$$addLeftRight("Super", $$$core$input$keysym$$default.XK_Super_L, $$$core$input$keysym$$default.XK_Super_R);
  3637. // - Symbol
  3638. // - SymbolLock
  3639.  
  3640. // 2.3. Whitespace Keys
  3641.  
  3642. $$domkeytable$$addNumpad("Enter", $$$core$input$keysym$$default.XK_Return, $$$core$input$keysym$$default.XK_KP_Enter);
  3643. $$domkeytable$$addStandard("Tab", $$$core$input$keysym$$default.XK_Tab);
  3644. $$domkeytable$$addNumpad(" ", $$$core$input$keysym$$default.XK_space, $$$core$input$keysym$$default.XK_KP_Space);
  3645.  
  3646. // 2.4. Navigation Keys
  3647.  
  3648. $$domkeytable$$addNumpad("ArrowDown", $$$core$input$keysym$$default.XK_Down, $$$core$input$keysym$$default.XK_KP_Down);
  3649. $$domkeytable$$addNumpad("ArrowUp", $$$core$input$keysym$$default.XK_Up, $$$core$input$keysym$$default.XK_KP_Up);
  3650. $$domkeytable$$addNumpad("ArrowLeft", $$$core$input$keysym$$default.XK_Left, $$$core$input$keysym$$default.XK_KP_Left);
  3651. $$domkeytable$$addNumpad("ArrowRight", $$$core$input$keysym$$default.XK_Right, $$$core$input$keysym$$default.XK_KP_Right);
  3652. $$domkeytable$$addNumpad("End", $$$core$input$keysym$$default.XK_End, $$$core$input$keysym$$default.XK_KP_End);
  3653. $$domkeytable$$addNumpad("Home", $$$core$input$keysym$$default.XK_Home, $$$core$input$keysym$$default.XK_KP_Home);
  3654. $$domkeytable$$addNumpad("PageDown", $$$core$input$keysym$$default.XK_Next, $$$core$input$keysym$$default.XK_KP_Next);
  3655. $$domkeytable$$addNumpad("PageUp", $$$core$input$keysym$$default.XK_Prior, $$$core$input$keysym$$default.XK_KP_Prior);
  3656.  
  3657. // 2.5. Editing Keys
  3658.  
  3659. $$domkeytable$$addStandard("Backspace", $$$core$input$keysym$$default.XK_BackSpace);
  3660. $$domkeytable$$addStandard("Clear", $$$core$input$keysym$$default.XK_Clear);
  3661. $$domkeytable$$addStandard("Copy", $$$core$input$keysym$$default.XF86XK_Copy);
  3662. // - CrSel
  3663. $$domkeytable$$addStandard("Cut", $$$core$input$keysym$$default.XF86XK_Cut);
  3664. $$domkeytable$$addNumpad("Delete", $$$core$input$keysym$$default.XK_Delete, $$$core$input$keysym$$default.XK_KP_Delete);
  3665. // - EraseEof
  3666. // - ExSel
  3667. $$domkeytable$$addNumpad("Insert", $$$core$input$keysym$$default.XK_Insert, $$$core$input$keysym$$default.XK_KP_Insert);
  3668. $$domkeytable$$addStandard("Paste", $$$core$input$keysym$$default.XF86XK_Paste);
  3669. $$domkeytable$$addStandard("Redo", $$$core$input$keysym$$default.XK_Redo);
  3670. $$domkeytable$$addStandard("Undo", $$$core$input$keysym$$default.XK_Undo);
  3671.  
  3672. // 2.6. UI Keys
  3673.  
  3674. // - Accept
  3675. // - Again (could just be XK_Redo)
  3676. // - Attn
  3677. $$domkeytable$$addStandard("Cancel", $$$core$input$keysym$$default.XK_Cancel);
  3678. $$domkeytable$$addStandard("ContextMenu", $$$core$input$keysym$$default.XK_Menu);
  3679. $$domkeytable$$addStandard("Escape", $$$core$input$keysym$$default.XK_Escape);
  3680. $$domkeytable$$addStandard("Execute", $$$core$input$keysym$$default.XK_Execute);
  3681. $$domkeytable$$addStandard("Find", $$$core$input$keysym$$default.XK_Find);
  3682. $$domkeytable$$addStandard("Help", $$$core$input$keysym$$default.XK_Help);
  3683. $$domkeytable$$addStandard("Pause", $$$core$input$keysym$$default.XK_Pause);
  3684. // - Play
  3685. // - Props
  3686. $$domkeytable$$addStandard("Select", $$$core$input$keysym$$default.XK_Select);
  3687. $$domkeytable$$addStandard("ZoomIn", $$$core$input$keysym$$default.XF86XK_ZoomIn);
  3688. $$domkeytable$$addStandard("ZoomOut", $$$core$input$keysym$$default.XF86XK_ZoomOut);
  3689.  
  3690. // 2.7. Device Keys
  3691.  
  3692. $$domkeytable$$addStandard("BrightnessDown", $$$core$input$keysym$$default.XF86XK_MonBrightnessDown);
  3693. $$domkeytable$$addStandard("BrightnessUp", $$$core$input$keysym$$default.XF86XK_MonBrightnessUp);
  3694. $$domkeytable$$addStandard("Eject", $$$core$input$keysym$$default.XF86XK_Eject);
  3695. $$domkeytable$$addStandard("LogOff", $$$core$input$keysym$$default.XF86XK_LogOff);
  3696. $$domkeytable$$addStandard("Power", $$$core$input$keysym$$default.XF86XK_PowerOff);
  3697. $$domkeytable$$addStandard("PowerOff", $$$core$input$keysym$$default.XF86XK_PowerDown);
  3698. $$domkeytable$$addStandard("PrintScreen", $$$core$input$keysym$$default.XK_Print);
  3699. $$domkeytable$$addStandard("Hibernate", $$$core$input$keysym$$default.XF86XK_Hibernate);
  3700. $$domkeytable$$addStandard("Standby", $$$core$input$keysym$$default.XF86XK_Standby);
  3701. $$domkeytable$$addStandard("WakeUp", $$$core$input$keysym$$default.XF86XK_WakeUp);
  3702.  
  3703. // 2.8. IME and Composition Keys
  3704.  
  3705. $$domkeytable$$addStandard("AllCandidates", $$$core$input$keysym$$default.XK_MultipleCandidate);
  3706. $$domkeytable$$addStandard("Alphanumeric", $$$core$input$keysym$$default.XK_Eisu_Shift); // could also be _Eisu_Toggle
  3707. $$domkeytable$$addStandard("CodeInput", $$$core$input$keysym$$default.XK_Codeinput);
  3708. $$domkeytable$$addStandard("Compose", $$$core$input$keysym$$default.XK_Multi_key);
  3709. $$domkeytable$$addStandard("Convert", $$$core$input$keysym$$default.XK_Henkan);
  3710. // - Dead
  3711. // - FinalMode
  3712. $$domkeytable$$addStandard("GroupFirst", $$$core$input$keysym$$default.XK_ISO_First_Group);
  3713. $$domkeytable$$addStandard("GroupLast", $$$core$input$keysym$$default.XK_ISO_Last_Group);
  3714. $$domkeytable$$addStandard("GroupNext", $$$core$input$keysym$$default.XK_ISO_Next_Group);
  3715. $$domkeytable$$addStandard("GroupPrevious", $$$core$input$keysym$$default.XK_ISO_Prev_Group);
  3716. // - ModeChange (XK_Mode_switch is often used for AltGr)
  3717. // - NextCandidate
  3718. $$domkeytable$$addStandard("NonConvert", $$$core$input$keysym$$default.XK_Muhenkan);
  3719. $$domkeytable$$addStandard("PreviousCandidate", $$$core$input$keysym$$default.XK_PreviousCandidate);
  3720. // - Process
  3721. $$domkeytable$$addStandard("SingleCandidate", $$$core$input$keysym$$default.XK_SingleCandidate);
  3722. $$domkeytable$$addStandard("HangulMode", $$$core$input$keysym$$default.XK_Hangul);
  3723. $$domkeytable$$addStandard("HanjaMode", $$$core$input$keysym$$default.XK_Hangul_Hanja);
  3724. $$domkeytable$$addStandard("JunjuaMode", $$$core$input$keysym$$default.XK_Hangul_Jeonja);
  3725. $$domkeytable$$addStandard("Eisu", $$$core$input$keysym$$default.XK_Eisu_toggle);
  3726. $$domkeytable$$addStandard("Hankaku", $$$core$input$keysym$$default.XK_Hankaku);
  3727. $$domkeytable$$addStandard("Hiragana", $$$core$input$keysym$$default.XK_Hiragana);
  3728. $$domkeytable$$addStandard("HiraganaKatakana", $$$core$input$keysym$$default.XK_Hiragana_Katakana);
  3729. $$domkeytable$$addStandard("KanaMode", $$$core$input$keysym$$default.XK_Kana_Shift); // could also be _Kana_Lock
  3730. $$domkeytable$$addStandard("KanjiMode", $$$core$input$keysym$$default.XK_Kanji);
  3731. $$domkeytable$$addStandard("Katakana", $$$core$input$keysym$$default.XK_Katakana);
  3732. $$domkeytable$$addStandard("Romaji", $$$core$input$keysym$$default.XK_Romaji);
  3733. $$domkeytable$$addStandard("Zenkaku", $$$core$input$keysym$$default.XK_Zenkaku);
  3734. $$domkeytable$$addStandard("ZenkakuHanaku", $$$core$input$keysym$$default.XK_Zenkaku_Hankaku);
  3735.  
  3736. // 2.9. General-Purpose Function Keys
  3737.  
  3738. $$domkeytable$$addStandard("F1", $$$core$input$keysym$$default.XK_F1);
  3739. $$domkeytable$$addStandard("F2", $$$core$input$keysym$$default.XK_F2);
  3740. $$domkeytable$$addStandard("F3", $$$core$input$keysym$$default.XK_F3);
  3741. $$domkeytable$$addStandard("F4", $$$core$input$keysym$$default.XK_F4);
  3742. $$domkeytable$$addStandard("F5", $$$core$input$keysym$$default.XK_F5);
  3743. $$domkeytable$$addStandard("F6", $$$core$input$keysym$$default.XK_F6);
  3744. $$domkeytable$$addStandard("F7", $$$core$input$keysym$$default.XK_F7);
  3745. $$domkeytable$$addStandard("F8", $$$core$input$keysym$$default.XK_F8);
  3746. $$domkeytable$$addStandard("F9", $$$core$input$keysym$$default.XK_F9);
  3747. $$domkeytable$$addStandard("F10", $$$core$input$keysym$$default.XK_F10);
  3748. $$domkeytable$$addStandard("F11", $$$core$input$keysym$$default.XK_F11);
  3749. $$domkeytable$$addStandard("F12", $$$core$input$keysym$$default.XK_F12);
  3750. $$domkeytable$$addStandard("F13", $$$core$input$keysym$$default.XK_F13);
  3751. $$domkeytable$$addStandard("F14", $$$core$input$keysym$$default.XK_F14);
  3752. $$domkeytable$$addStandard("F15", $$$core$input$keysym$$default.XK_F15);
  3753. $$domkeytable$$addStandard("F16", $$$core$input$keysym$$default.XK_F16);
  3754. $$domkeytable$$addStandard("F17", $$$core$input$keysym$$default.XK_F17);
  3755. $$domkeytable$$addStandard("F18", $$$core$input$keysym$$default.XK_F18);
  3756. $$domkeytable$$addStandard("F19", $$$core$input$keysym$$default.XK_F19);
  3757. $$domkeytable$$addStandard("F20", $$$core$input$keysym$$default.XK_F20);
  3758. $$domkeytable$$addStandard("F21", $$$core$input$keysym$$default.XK_F21);
  3759. $$domkeytable$$addStandard("F22", $$$core$input$keysym$$default.XK_F22);
  3760. $$domkeytable$$addStandard("F23", $$$core$input$keysym$$default.XK_F23);
  3761. $$domkeytable$$addStandard("F24", $$$core$input$keysym$$default.XK_F24);
  3762. $$domkeytable$$addStandard("F25", $$$core$input$keysym$$default.XK_F25);
  3763. $$domkeytable$$addStandard("F26", $$$core$input$keysym$$default.XK_F26);
  3764. $$domkeytable$$addStandard("F27", $$$core$input$keysym$$default.XK_F27);
  3765. $$domkeytable$$addStandard("F28", $$$core$input$keysym$$default.XK_F28);
  3766. $$domkeytable$$addStandard("F29", $$$core$input$keysym$$default.XK_F29);
  3767. $$domkeytable$$addStandard("F30", $$$core$input$keysym$$default.XK_F30);
  3768. $$domkeytable$$addStandard("F31", $$$core$input$keysym$$default.XK_F31);
  3769. $$domkeytable$$addStandard("F32", $$$core$input$keysym$$default.XK_F32);
  3770. $$domkeytable$$addStandard("F33", $$$core$input$keysym$$default.XK_F33);
  3771. $$domkeytable$$addStandard("F34", $$$core$input$keysym$$default.XK_F34);
  3772. $$domkeytable$$addStandard("F35", $$$core$input$keysym$$default.XK_F35);
  3773. // - Soft1...
  3774.  
  3775. // 2.10. Multimedia Keys
  3776.  
  3777. // - ChannelDown
  3778. // - ChannelUp
  3779. $$domkeytable$$addStandard("Close", $$$core$input$keysym$$default.XF86XK_Close);
  3780. $$domkeytable$$addStandard("MailForward", $$$core$input$keysym$$default.XF86XK_MailForward);
  3781. $$domkeytable$$addStandard("MailReply", $$$core$input$keysym$$default.XF86XK_Reply);
  3782. $$domkeytable$$addStandard("MainSend", $$$core$input$keysym$$default.XF86XK_Send);
  3783. $$domkeytable$$addStandard("MediaFastForward", $$$core$input$keysym$$default.XF86XK_AudioForward);
  3784. $$domkeytable$$addStandard("MediaPause", $$$core$input$keysym$$default.XF86XK_AudioPause);
  3785. $$domkeytable$$addStandard("MediaPlay", $$$core$input$keysym$$default.XF86XK_AudioPlay);
  3786. $$domkeytable$$addStandard("MediaRecord", $$$core$input$keysym$$default.XF86XK_AudioRecord);
  3787. $$domkeytable$$addStandard("MediaRewind", $$$core$input$keysym$$default.XF86XK_AudioRewind);
  3788. $$domkeytable$$addStandard("MediaStop", $$$core$input$keysym$$default.XF86XK_AudioStop);
  3789. $$domkeytable$$addStandard("MediaTrackNext", $$$core$input$keysym$$default.XF86XK_AudioNext);
  3790. $$domkeytable$$addStandard("MediaTrackPrevious", $$$core$input$keysym$$default.XF86XK_AudioPrev);
  3791. $$domkeytable$$addStandard("New", $$$core$input$keysym$$default.XF86XK_New);
  3792. $$domkeytable$$addStandard("Open", $$$core$input$keysym$$default.XF86XK_Open);
  3793. $$domkeytable$$addStandard("Print", $$$core$input$keysym$$default.XK_Print);
  3794. $$domkeytable$$addStandard("Save", $$$core$input$keysym$$default.XF86XK_Save);
  3795. $$domkeytable$$addStandard("SpellCheck", $$$core$input$keysym$$default.XF86XK_Spell);
  3796.  
  3797. // 2.11. Multimedia Numpad Keys
  3798.  
  3799. // - Key11
  3800. // - Key12
  3801.  
  3802. // 2.12. Audio Keys
  3803.  
  3804. // - AudioBalanceLeft
  3805. // - AudioBalanceRight
  3806. // - AudioBassDown
  3807. // - AudioBassBoostDown
  3808. // - AudioBassBoostToggle
  3809. // - AudioBassBoostUp
  3810. // - AudioBassUp
  3811. // - AudioFaderFront
  3812. // - AudioFaderRear
  3813. // - AudioSurroundModeNext
  3814. // - AudioTrebleDown
  3815. // - AudioTrebleUp
  3816. $$domkeytable$$addStandard("AudioVolumeDown", $$$core$input$keysym$$default.XF86XK_AudioLowerVolume);
  3817. $$domkeytable$$addStandard("AudioVolumeUp", $$$core$input$keysym$$default.XF86XK_AudioRaiseVolume);
  3818. $$domkeytable$$addStandard("AudioVolumeMute", $$$core$input$keysym$$default.XF86XK_AudioMute);
  3819. // - MicrophoneToggle
  3820. // - MicrophoneVolumeDown
  3821. // - MicrophoneVolumeUp
  3822. $$domkeytable$$addStandard("MicrophoneVolumeMute", $$$core$input$keysym$$default.XF86XK_AudioMicMute);
  3823.  
  3824. // 2.13. Speech Keys
  3825.  
  3826. // - SpeechCorrectionList
  3827. // - SpeechInputToggle
  3828.  
  3829. // 2.14. Application Keys
  3830.  
  3831. $$domkeytable$$addStandard("LaunchCalculator", $$$core$input$keysym$$default.XF86XK_Calculator);
  3832. $$domkeytable$$addStandard("LaunchCalendar", $$$core$input$keysym$$default.XF86XK_Calendar);
  3833. $$domkeytable$$addStandard("LaunchMail", $$$core$input$keysym$$default.XF86XK_Mail);
  3834. $$domkeytable$$addStandard("LaunchMediaPlayer", $$$core$input$keysym$$default.XF86XK_AudioMedia);
  3835. $$domkeytable$$addStandard("LaunchMusicPlayer", $$$core$input$keysym$$default.XF86XK_Music);
  3836. $$domkeytable$$addStandard("LaunchMyComputer", $$$core$input$keysym$$default.XF86XK_MyComputer);
  3837. $$domkeytable$$addStandard("LaunchPhone", $$$core$input$keysym$$default.XF86XK_Phone);
  3838. $$domkeytable$$addStandard("LaunchScreenSaver", $$$core$input$keysym$$default.XF86XK_ScreenSaver);
  3839. $$domkeytable$$addStandard("LaunchSpreadsheet", $$$core$input$keysym$$default.XF86XK_Excel);
  3840. $$domkeytable$$addStandard("LaunchWebBrowser", $$$core$input$keysym$$default.XF86XK_WWW);
  3841. $$domkeytable$$addStandard("LaunchWebCam", $$$core$input$keysym$$default.XF86XK_WebCam);
  3842. $$domkeytable$$addStandard("LaunchWordProcessor", $$$core$input$keysym$$default.XF86XK_Word);
  3843.  
  3844. // 2.15. Browser Keys
  3845.  
  3846. $$domkeytable$$addStandard("BrowserBack", $$$core$input$keysym$$default.XF86XK_Back);
  3847. $$domkeytable$$addStandard("BrowserFavorites", $$$core$input$keysym$$default.XF86XK_Favorites);
  3848. $$domkeytable$$addStandard("BrowserForward", $$$core$input$keysym$$default.XF86XK_Forward);
  3849. $$domkeytable$$addStandard("BrowserHome", $$$core$input$keysym$$default.XF86XK_HomePage);
  3850. $$domkeytable$$addStandard("BrowserRefresh", $$$core$input$keysym$$default.XF86XK_Refresh);
  3851. $$domkeytable$$addStandard("BrowserSearch", $$$core$input$keysym$$default.XF86XK_Search);
  3852. $$domkeytable$$addStandard("BrowserStop", $$$core$input$keysym$$default.XF86XK_Stop);
  3853.  
  3854. // 2.16. Mobile Phone Keys
  3855.  
  3856. // - A whole bunch...
  3857.  
  3858. // 2.17. TV Keys
  3859.  
  3860. // - A whole bunch...
  3861.  
  3862. // 2.18. Media Controller Keys
  3863.  
  3864. // - A whole bunch...
  3865. $$domkeytable$$addStandard("Dimmer", $$$core$input$keysym$$default.XF86XK_BrightnessAdjust);
  3866. $$domkeytable$$addStandard("MediaAudioTrack", $$$core$input$keysym$$default.XF86XK_AudioCycleTrack);
  3867. $$domkeytable$$addStandard("RandomToggle", $$$core$input$keysym$$default.XF86XK_AudioRandomPlay);
  3868. $$domkeytable$$addStandard("SplitScreenToggle", $$$core$input$keysym$$default.XF86XK_SplitScreen);
  3869. $$domkeytable$$addStandard("Subtitle", $$$core$input$keysym$$default.XF86XK_Subtitle);
  3870. $$domkeytable$$addStandard("VideoModeNext", $$$core$input$keysym$$default.XF86XK_Next_VMode);
  3871.  
  3872. // Extra: Numpad
  3873.  
  3874. $$domkeytable$$addNumpad("=", $$$core$input$keysym$$default.XK_equal, $$$core$input$keysym$$default.XK_KP_Equal);
  3875. $$domkeytable$$addNumpad("+", $$$core$input$keysym$$default.XK_plus, $$$core$input$keysym$$default.XK_KP_Add);
  3876. $$domkeytable$$addNumpad("-", $$$core$input$keysym$$default.XK_minus, $$$core$input$keysym$$default.XK_KP_Subtract);
  3877. $$domkeytable$$addNumpad("*", $$$core$input$keysym$$default.XK_asterisk, $$$core$input$keysym$$default.XK_KP_Multiply);
  3878. $$domkeytable$$addNumpad("/", $$$core$input$keysym$$default.XK_slash, $$$core$input$keysym$$default.XK_KP_Divide);
  3879. $$domkeytable$$addNumpad(".", $$$core$input$keysym$$default.XK_period, $$$core$input$keysym$$default.XK_KP_Decimal);
  3880. $$domkeytable$$addNumpad(",", $$$core$input$keysym$$default.XK_comma, $$$core$input$keysym$$default.XK_KP_Separator);
  3881. $$domkeytable$$addNumpad("0", $$$core$input$keysym$$default.XK_0, $$$core$input$keysym$$default.XK_KP_0);
  3882. $$domkeytable$$addNumpad("1", $$$core$input$keysym$$default.XK_1, $$$core$input$keysym$$default.XK_KP_1);
  3883. $$domkeytable$$addNumpad("2", $$$core$input$keysym$$default.XK_2, $$$core$input$keysym$$default.XK_KP_2);
  3884. $$domkeytable$$addNumpad("3", $$$core$input$keysym$$default.XK_3, $$$core$input$keysym$$default.XK_KP_3);
  3885. $$domkeytable$$addNumpad("4", $$$core$input$keysym$$default.XK_4, $$$core$input$keysym$$default.XK_KP_4);
  3886. $$domkeytable$$addNumpad("5", $$$core$input$keysym$$default.XK_5, $$$core$input$keysym$$default.XK_KP_5);
  3887. $$domkeytable$$addNumpad("6", $$$core$input$keysym$$default.XK_6, $$$core$input$keysym$$default.XK_KP_6);
  3888. $$domkeytable$$addNumpad("7", $$$core$input$keysym$$default.XK_7, $$$core$input$keysym$$default.XK_KP_7);
  3889. $$domkeytable$$addNumpad("8", $$$core$input$keysym$$default.XK_8, $$$core$input$keysym$$default.XK_KP_8);
  3890. $$domkeytable$$addNumpad("9", $$$core$input$keysym$$default.XK_9, $$$core$input$keysym$$default.XK_KP_9);
  3891.  
  3892. var $$domkeytable$$default = $$domkeytable$$DOMKeyTable;
  3893.  
  3894. function $$util$$isMac() {
  3895. return navigator && !!(/mac/i).exec(navigator.platform);
  3896. }
  3897. function $$util$$isIE() {
  3898. return navigator && !!(/trident/i).exec(navigator.userAgent);
  3899. }
  3900. function $$util$$isEdge() {
  3901. return navigator && !!(/edge/i).exec(navigator.userAgent);
  3902. }
  3903.  
  3904. function $$util$$getKeycode(evt) {
  3905. // Are we getting proper key identifiers?
  3906. // (unfortunately Firefox and Chrome are crappy here and gives
  3907. // us an empty string on some platforms, rather than leaving it
  3908. // undefined)
  3909. if (evt.code) {
  3910. // Mozilla isn't fully in sync with the spec yet
  3911. switch (evt.code) {
  3912. case 'OSLeft': return 'MetaLeft';
  3913. case 'OSRight': return 'MetaRight';
  3914. }
  3915.  
  3916. return evt.code;
  3917. }
  3918.  
  3919. // The de-facto standard is to use Windows Virtual-Key codes
  3920. // in the 'keyCode' field for non-printable characters. However
  3921. // Webkit sets it to the same as charCode in 'keypress' events.
  3922. if ((evt.type !== 'keypress') && (evt.keyCode in $$vkeys$$default)) {
  3923. var code = $$vkeys$$default[evt.keyCode];
  3924.  
  3925. // macOS has messed up this code for some reason
  3926. if ($$util$$isMac() && (code === 'ContextMenu')) {
  3927. code = 'MetaRight';
  3928. }
  3929.  
  3930. // The keyCode doesn't distinguish between left and right
  3931. // for the standard modifiers
  3932. if (evt.location === 2) {
  3933. switch (code) {
  3934. case 'ShiftLeft': return 'ShiftRight';
  3935. case 'ControlLeft': return 'ControlRight';
  3936. case 'AltLeft': return 'AltRight';
  3937. }
  3938. }
  3939.  
  3940. // Nor a bunch of the numpad keys
  3941. if (evt.location === 3) {
  3942. switch (code) {
  3943. case 'Delete': return 'NumpadDecimal';
  3944. case 'Insert': return 'Numpad0';
  3945. case 'End': return 'Numpad1';
  3946. case 'ArrowDown': return 'Numpad2';
  3947. case 'PageDown': return 'Numpad3';
  3948. case 'ArrowLeft': return 'Numpad4';
  3949. case 'ArrowRight': return 'Numpad6';
  3950. case 'Home': return 'Numpad7';
  3951. case 'ArrowUp': return 'Numpad8';
  3952. case 'PageUp': return 'Numpad9';
  3953. case 'Enter': return 'NumpadEnter';
  3954. }
  3955. }
  3956.  
  3957. return code;
  3958. }
  3959.  
  3960. return 'Unidentified';
  3961. }
  3962.  
  3963. function $$util$$getKey(evt) {
  3964. // Are we getting a proper key value?
  3965. if (evt.key !== undefined) {
  3966. // IE and Edge use some ancient version of the spec
  3967. // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
  3968. switch (evt.key) {
  3969. case 'Spacebar': return ' ';
  3970. case 'Esc': return 'Escape';
  3971. case 'Scroll': return 'ScrollLock';
  3972. case 'Win': return 'Meta';
  3973. case 'Apps': return 'ContextMenu';
  3974. case 'Up': return 'ArrowUp';
  3975. case 'Left': return 'ArrowLeft';
  3976. case 'Right': return 'ArrowRight';
  3977. case 'Down': return 'ArrowDown';
  3978. case 'Del': return 'Delete';
  3979. case 'Divide': return '/';
  3980. case 'Multiply': return '*';
  3981. case 'Subtract': return '-';
  3982. case 'Add': return '+';
  3983. case 'Decimal': return evt.char;
  3984. }
  3985.  
  3986. // Mozilla isn't fully in sync with the spec yet
  3987. switch (evt.key) {
  3988. case 'OS': return 'Meta';
  3989. }
  3990.  
  3991. // IE and Edge have broken handling of AltGraph so we cannot
  3992. // trust them for printable characters
  3993. if ((evt.key.length !== 1) || (!$$util$$isIE() && !$$util$$isEdge())) {
  3994. return evt.key;
  3995. }
  3996. }
  3997.  
  3998. // Try to deduce it based on the physical key
  3999. var code = $$util$$getKeycode(evt);
  4000. if (code in $$fixedkeys$$default) {
  4001. return $$fixedkeys$$default[code];
  4002. }
  4003.  
  4004. // If that failed, then see if we have a printable character
  4005. if (evt.charCode) {
  4006. return String.fromCharCode(evt.charCode);
  4007. }
  4008.  
  4009. // At this point we have nothing left to go on
  4010. return 'Unidentified';
  4011. }
  4012.  
  4013. function $$util$$getKeysym(evt) {
  4014. var key = $$util$$getKey(evt);
  4015.  
  4016. if (key === 'Unidentified') {
  4017. return null;
  4018. }
  4019.  
  4020. // First look up special keys
  4021. if (key in $$domkeytable$$default) {
  4022. var location = evt.location;
  4023.  
  4024. // Safari screws up location for the right cmd key
  4025. if ((key === 'Meta') && (location === 0)) {
  4026. location = 2;
  4027. }
  4028.  
  4029. if ((location === undefined) || (location > 3)) {
  4030. location = 0;
  4031. }
  4032.  
  4033. return $$domkeytable$$default[key][location];
  4034. }
  4035.  
  4036. // Now we need to look at the Unicode symbol instead
  4037.  
  4038. var codepoint;
  4039.  
  4040. // Special key? (FIXME: Should have been caught earlier)
  4041. if (key.length !== 1) {
  4042. return null;
  4043. }
  4044.  
  4045. codepoint = key.charCodeAt();
  4046. if (codepoint) {
  4047. return $$$core$input$keysymdef$$default.lookup(codepoint);
  4048. }
  4049.  
  4050. return null;
  4051. }
  4052.  
  4053. //
  4054. // Keyboard event handler
  4055. //
  4056.  
  4057. const $$input$devices$$Keyboard = function (defaults) {
  4058. this._keyDownList = {}; // List of depressed keys
  4059. // (even if they are happy)
  4060. this._pendingKey = null; // Key waiting for keypress
  4061.  
  4062. $$util$properties$$set_defaults(this, defaults, {
  4063. 'target': document,
  4064. 'focused': true
  4065. });
  4066.  
  4067. // keep these here so we can refer to them later
  4068. this._eventHandlers = {
  4069. 'keyup': this._handleKeyUp.bind(this),
  4070. 'keydown': this._handleKeyDown.bind(this),
  4071. 'keypress': this._handleKeyPress.bind(this),
  4072. 'blur': this._allKeysUp.bind(this)
  4073. };
  4074. };
  4075.  
  4076. function $$input$devices$$isMac() {
  4077. return navigator && !!(/mac/i).exec(navigator.platform);
  4078. }
  4079. function $$input$devices$$isWindows() {
  4080. return navigator && !!(/win/i).exec(navigator.platform);
  4081. }
  4082.  
  4083. $$input$devices$$Keyboard.prototype = {
  4084. // private methods
  4085.  
  4086. _sendKeyEvent: function (keysym, code, down) {
  4087. if (!this._onKeyEvent) {
  4088. return;
  4089. }
  4090.  
  4091. $$$core$util$logging$$.Debug("onKeyEvent " + (down ? "down" : "up") +
  4092. ", keysym: " + keysym, ", code: " + code);
  4093.  
  4094. // Windows sends CtrlLeft+AltRight when you press
  4095. // AltGraph, which tends to confuse the hell out of
  4096. // remote systems. Fake a release of these keys until
  4097. // there is a way to detect AltGraph properly.
  4098. var fakeAltGraph = false;
  4099. if (down && $$input$devices$$isWindows()) {
  4100. if ((code !== 'ControlLeft') &&
  4101. (code !== 'AltRight') &&
  4102. ('ControlLeft' in this._keyDownList) &&
  4103. ('AltRight' in this._keyDownList)) {
  4104. fakeAltGraph = true;
  4105. this._onKeyEvent(this._keyDownList['AltRight'],
  4106. 'AltRight', false);
  4107. this._onKeyEvent(this._keyDownList['ControlLeft'],
  4108. 'ControlLeft', false);
  4109. }
  4110. }
  4111.  
  4112. this._onKeyEvent(keysym, code, down);
  4113.  
  4114. if (fakeAltGraph) {
  4115. this._onKeyEvent(this._keyDownList['ControlLeft'],
  4116. 'ControlLeft', true);
  4117. this._onKeyEvent(this._keyDownList['AltRight'],
  4118. 'AltRight', true);
  4119. }
  4120. },
  4121.  
  4122. _getKeyCode: function (e) {
  4123. var code = $$util$$.getKeycode(e);
  4124. if (code === 'Unidentified') {
  4125. // Unstable, but we don't have anything else to go on
  4126. // (don't use it for 'keypress' events thought since
  4127. // WebKit sets it to the same as charCode)
  4128. if (e.keyCode && (e.type !== 'keypress')) {
  4129. code = 'Platform' + e.keyCode;
  4130. }
  4131. }
  4132.  
  4133. return code;
  4134. },
  4135.  
  4136. _handleKeyDown: function (e) {
  4137. if (!this._focused) { return; }
  4138.  
  4139. var code = this._getKeyCode(e);
  4140. var keysym = $$util$$.getKeysym(e);
  4141.  
  4142. // We cannot handle keys we cannot track, but we also need
  4143. // to deal with virtual keyboards which omit key info
  4144. if (code === 'Unidentified') {
  4145. if (keysym) {
  4146. // If it's a virtual keyboard then it should be
  4147. // sufficient to just send press and release right
  4148. // after each other
  4149. this._sendKeyEvent(keysym, 'Unidentified', true);
  4150. this._sendKeyEvent(keysym, 'Unidentified', false);
  4151. }
  4152.  
  4153. $$$core$util$events$$stopEvent(e);
  4154. return;
  4155. }
  4156.  
  4157. // Alt behaves more like AltGraph on macOS, so shuffle the
  4158. // keys around a bit to make things more sane for the remote
  4159. // server. This method is used by RealVNC and TigerVNC (and
  4160. // possibly others).
  4161. if ($$input$devices$$isMac()) {
  4162. switch (keysym) {
  4163. case $$$core$input$keysym$$default.XK_Super_L:
  4164. keysym = $$$core$input$keysym$$default.XK_Alt_L;
  4165. break;
  4166. case $$$core$input$keysym$$default.XK_Super_R:
  4167. keysym = $$$core$input$keysym$$default.XK_Super_L;
  4168. break;
  4169. case $$$core$input$keysym$$default.XK_Alt_L:
  4170. keysym = $$$core$input$keysym$$default.XK_Mode_switch;
  4171. break;
  4172. case $$$core$input$keysym$$default.XK_Alt_R:
  4173. keysym = $$$core$input$keysym$$default.XK_ISO_Level3_Shift;
  4174. break;
  4175. }
  4176. }
  4177.  
  4178. // Is this key already pressed? If so, then we must use the
  4179. // same keysym or we'll confuse the server
  4180. if (code in this._keyDownList) {
  4181. keysym = this._keyDownList[code];
  4182. }
  4183.  
  4184. // macOS doesn't send proper key events for modifiers, only
  4185. // state change events. That gets extra confusing for CapsLock
  4186. // which toggles on each press, but not on release. So pretend
  4187. // it was a quick press and release of the button.
  4188. if ($$input$devices$$isMac() && (code === 'CapsLock')) {
  4189. this._sendKeyEvent($$$core$input$keysym$$default.XK_Caps_Lock, 'CapsLock', true);
  4190. this._sendKeyEvent($$$core$input$keysym$$default.XK_Caps_Lock, 'CapsLock', false);
  4191. $$$core$util$events$$stopEvent(e);
  4192. return;
  4193. }
  4194.  
  4195. // If this is a legacy browser then we'll need to wait for
  4196. // a keypress event as well
  4197. if (!keysym) {
  4198. this._pendingKey = code;
  4199. return;
  4200. }
  4201.  
  4202. this._pendingKey = null;
  4203. $$$core$util$events$$stopEvent(e);
  4204.  
  4205. this._keyDownList[code] = keysym;
  4206.  
  4207. this._sendKeyEvent(keysym, code, true);
  4208. },
  4209.  
  4210. // Legacy event for browsers without code/key
  4211. _handleKeyPress: function (e) {
  4212. if (!this._focused) { return; }
  4213.  
  4214. $$$core$util$events$$stopEvent(e);
  4215.  
  4216. // Are we expecting a keypress?
  4217. if (this._pendingKey === null) {
  4218. return;
  4219. }
  4220.  
  4221. var code = this._getKeyCode(e);
  4222. var keysym = $$util$$.getKeysym(e);
  4223.  
  4224. // The key we were waiting for?
  4225. if ((code !== 'Unidentified') && (code != this._pendingKey)) {
  4226. return;
  4227. }
  4228.  
  4229. code = this._pendingKey;
  4230. this._pendingKey = null;
  4231.  
  4232. if (!keysym) {
  4233. console.log('keypress with no keysym:', e);
  4234. return;
  4235. }
  4236.  
  4237. this._keyDownList[code] = keysym;
  4238.  
  4239. this._sendKeyEvent(keysym, code, true);
  4240. },
  4241.  
  4242. _handleKeyUp: function (e) {
  4243. if (!this._focused) { return; }
  4244.  
  4245. $$$core$util$events$$stopEvent(e);
  4246.  
  4247. var code = this._getKeyCode(e);
  4248.  
  4249. // See comment in _handleKeyDown()
  4250. if ($$input$devices$$isMac() && (code === 'CapsLock')) {
  4251. this._sendKeyEvent($$$core$input$keysym$$default.XK_Caps_Lock, 'CapsLock', true);
  4252. this._sendKeyEvent($$$core$input$keysym$$default.XK_Caps_Lock, 'CapsLock', false);
  4253. return;
  4254. }
  4255.  
  4256. // Do we really think this key is down?
  4257. if (!(code in this._keyDownList)) {
  4258. return;
  4259. }
  4260.  
  4261. this._sendKeyEvent(this._keyDownList[code], code, false);
  4262.  
  4263. delete this._keyDownList[code];
  4264. },
  4265.  
  4266. _allKeysUp: function () {
  4267. $$$core$util$logging$$.Debug(">> Keyboard.allKeysUp");
  4268. for (var code in this._keyDownList) {
  4269. this._sendKeyEvent(this._keyDownList[code], code, false);
  4270. };
  4271. this._keyDownList = {};
  4272. $$$core$util$logging$$.Debug("<< Keyboard.allKeysUp");
  4273. },
  4274.  
  4275. // Public methods
  4276.  
  4277. grab: function () {
  4278. //Log.Debug(">> Keyboard.grab");
  4279. var c = this._target;
  4280.  
  4281. c.addEventListener('keydown', this._eventHandlers.keydown);
  4282. c.addEventListener('keyup', this._eventHandlers.keyup);
  4283. c.addEventListener('keypress', this._eventHandlers.keypress);
  4284.  
  4285. // Release (key up) if window loses focus
  4286. window.addEventListener('blur', this._eventHandlers.blur);
  4287.  
  4288. //Log.Debug("<< Keyboard.grab");
  4289. },
  4290.  
  4291. ungrab: function () {
  4292. //Log.Debug(">> Keyboard.ungrab");
  4293. var c = this._target;
  4294.  
  4295. c.removeEventListener('keydown', this._eventHandlers.keydown);
  4296. c.removeEventListener('keyup', this._eventHandlers.keyup);
  4297. c.removeEventListener('keypress', this._eventHandlers.keypress);
  4298. window.removeEventListener('blur', this._eventHandlers.blur);
  4299.  
  4300. // Release (key up) all keys that are in a down state
  4301. this._allKeysUp();
  4302.  
  4303. //Log.Debug(">> Keyboard.ungrab");
  4304. },
  4305. };
  4306.  
  4307. $$util$properties$$make_properties($$input$devices$$Keyboard, [
  4308. ['target', 'wo', 'dom'], // DOM element that captures keyboard input
  4309. ['focused', 'rw', 'bool'], // Capture and send key events
  4310.  
  4311. ['onKeyEvent', 'rw', 'func'] // Handler for key press/release
  4312. ]);
  4313.  
  4314. const $$input$devices$$Mouse = function (defaults) {
  4315.  
  4316. this._doubleClickTimer = null;
  4317. this._lastTouchPos = null;
  4318.  
  4319. // Configuration attributes
  4320. $$util$properties$$set_defaults(this, defaults, {
  4321. 'target': document,
  4322. 'focused': true,
  4323. 'touchButton': 1
  4324. });
  4325.  
  4326. this._eventHandlers = {
  4327. 'mousedown': this._handleMouseDown.bind(this),
  4328. 'mouseup': this._handleMouseUp.bind(this),
  4329. 'mousemove': this._handleMouseMove.bind(this),
  4330. 'mousewheel': this._handleMouseWheel.bind(this),
  4331. 'mousedisable': this._handleMouseDisable.bind(this)
  4332. };
  4333. };
  4334.  
  4335. $$input$devices$$Mouse.prototype = {
  4336. // private methods
  4337.  
  4338. _resetDoubleClickTimer: function () {
  4339. this._doubleClickTimer = null;
  4340. },
  4341.  
  4342. _handleMouseButton: function (e, down) {
  4343. if (!this._focused) { return; }
  4344.  
  4345. var pos = this._getMousePosition(e);
  4346.  
  4347. var bmask;
  4348. if (e.touches || e.changedTouches) {
  4349. // Touch device
  4350.  
  4351. // When two touches occur within 500 ms of each other and are
  4352. // close enough together a double click is triggered.
  4353. if (down == 1) {
  4354. if (this._doubleClickTimer === null) {
  4355. this._lastTouchPos = pos;
  4356. } else {
  4357. clearTimeout(this._doubleClickTimer);
  4358.  
  4359. // When the distance between the two touches is small enough
  4360. // force the position of the latter touch to the position of
  4361. // the first.
  4362.  
  4363. var xs = this._lastTouchPos.x - pos.x;
  4364. var ys = this._lastTouchPos.y - pos.y;
  4365. var d = Math.sqrt((xs * xs) + (ys * ys));
  4366.  
  4367. // The goal is to trigger on a certain physical width, the
  4368. // devicePixelRatio brings us a bit closer but is not optimal.
  4369. var threshold = 20 * (window.devicePixelRatio || 1);
  4370. if (d < threshold) {
  4371. pos = this._lastTouchPos;
  4372. }
  4373. }
  4374. this._doubleClickTimer = setTimeout(this._resetDoubleClickTimer.bind(this), 500);
  4375. }
  4376. bmask = this._touchButton;
  4377. // If bmask is set
  4378. } else if (e.which) {
  4379. /* everything except IE */
  4380. bmask = 1 << e.button;
  4381. } else {
  4382. /* IE including 9 */
  4383. bmask = (e.button & 0x1) + // Left
  4384. (e.button & 0x2) * 2 + // Right
  4385. (e.button & 0x4) / 2; // Middle
  4386. }
  4387.  
  4388. if (this._onMouseButton) {
  4389. $$$core$util$logging$$.Debug("onMouseButton " + (down ? "down" : "up") +
  4390. ", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask);
  4391. this._onMouseButton(pos.x, pos.y, down, bmask);
  4392. }
  4393. $$$core$util$events$$stopEvent(e);
  4394. },
  4395.  
  4396. _handleMouseDown: function (e) {
  4397. // Touch events have implicit capture
  4398. if (e.type === "mousedown") {
  4399. $$$core$util$events$$setCapture(this._target);
  4400. }
  4401.  
  4402. this._handleMouseButton(e, 1);
  4403. },
  4404.  
  4405. _handleMouseUp: function (e) {
  4406. this._handleMouseButton(e, 0);
  4407. },
  4408.  
  4409. _handleMouseWheel: function (e) {
  4410. if (!this._focused) { return; }
  4411.  
  4412. var pos = this._getMousePosition(e);
  4413.  
  4414. if (this._onMouseButton) {
  4415. if (e.deltaX < 0) {
  4416. this._onMouseButton(pos.x, pos.y, 1, 1 << 5);
  4417. this._onMouseButton(pos.x, pos.y, 0, 1 << 5);
  4418. } else if (e.deltaX > 0) {
  4419. this._onMouseButton(pos.x, pos.y, 1, 1 << 6);
  4420. this._onMouseButton(pos.x, pos.y, 0, 1 << 6);
  4421. }
  4422.  
  4423. if (e.deltaY < 0) {
  4424. this._onMouseButton(pos.x, pos.y, 1, 1 << 3);
  4425. this._onMouseButton(pos.x, pos.y, 0, 1 << 3);
  4426. } else if (e.deltaY > 0) {
  4427. this._onMouseButton(pos.x, pos.y, 1, 1 << 4);
  4428. this._onMouseButton(pos.x, pos.y, 0, 1 << 4);
  4429. }
  4430. }
  4431.  
  4432. $$$core$util$events$$stopEvent(e);
  4433. },
  4434.  
  4435. _handleMouseMove: function (e) {
  4436. if (! this._focused) { return; }
  4437.  
  4438. var pos = this._getMousePosition(e);
  4439. if (this._onMouseMove) {
  4440. this._onMouseMove(pos.x, pos.y);
  4441. }
  4442. $$$core$util$events$$stopEvent(e);
  4443. },
  4444.  
  4445. _handleMouseDisable: function (e) {
  4446. if (!this._focused) { return; }
  4447.  
  4448. /*
  4449. * Stop propagation if inside canvas area
  4450. * Note: This is only needed for the 'click' event as it fails
  4451. * to fire properly for the target element so we have
  4452. * to listen on the document element instead.
  4453. */
  4454. if (e.target == this._target) {
  4455. $$$core$util$events$$stopEvent(e);
  4456. }
  4457. },
  4458.  
  4459. // Return coordinates relative to target
  4460. _getMousePosition: function(e) {
  4461. e = $$$core$util$events$$getPointerEvent(e);
  4462. var bounds = this._target.getBoundingClientRect();
  4463. var x, y;
  4464. // Clip to target bounds
  4465. if (e.clientX < bounds.left) {
  4466. x = 0;
  4467. } else if (e.clientX >= bounds.right) {
  4468. x = bounds.width - 1;
  4469. } else {
  4470. x = e.clientX - bounds.left;
  4471. }
  4472. if (e.clientY < bounds.top) {
  4473. y = 0;
  4474. } else if (e.clientY >= bounds.bottom) {
  4475. y = bounds.height - 1;
  4476. } else {
  4477. y = e.clientY - bounds.top;
  4478. }
  4479. return {x:x, y:y};
  4480. },
  4481.  
  4482. // Public methods
  4483. grab: function () {
  4484. var c = this._target;
  4485.  
  4486. if ($$$core$util$browsers$$isTouchDevice) {
  4487. c.addEventListener('touchstart', this._eventHandlers.mousedown);
  4488. c.addEventListener('touchend', this._eventHandlers.mouseup);
  4489. c.addEventListener('touchmove', this._eventHandlers.mousemove);
  4490. }
  4491. c.addEventListener('mousedown', this._eventHandlers.mousedown);
  4492. c.addEventListener('mouseup', this._eventHandlers.mouseup);
  4493. c.addEventListener('mousemove', this._eventHandlers.mousemove);
  4494. c.addEventListener('wheel', this._eventHandlers.mousewheel);
  4495.  
  4496. /* Prevent middle-click pasting (see above for why we bind to document) */
  4497. document.addEventListener('click', this._eventHandlers.mousedisable);
  4498.  
  4499. /* preventDefault() on mousedown doesn't stop this event for some
  4500. reason so we have to explicitly block it */
  4501. c.addEventListener('contextmenu', this._eventHandlers.mousedisable);
  4502. },
  4503.  
  4504. ungrab: function () {
  4505. var c = this._target;
  4506.  
  4507. if ($$$core$util$browsers$$isTouchDevice) {
  4508. c.removeEventListener('touchstart', this._eventHandlers.mousedown);
  4509. c.removeEventListener('touchend', this._eventHandlers.mouseup);
  4510. c.removeEventListener('touchmove', this._eventHandlers.mousemove);
  4511. }
  4512. c.removeEventListener('mousedown', this._eventHandlers.mousedown);
  4513. c.removeEventListener('mouseup', this._eventHandlers.mouseup);
  4514. c.removeEventListener('mousemove', this._eventHandlers.mousemove);
  4515. c.removeEventListener('wheel', this._eventHandlers.mousewheel);
  4516.  
  4517. document.removeEventListener('click', this._eventHandlers.mousedisable);
  4518.  
  4519. c.removeEventListener('contextmenu', this._eventHandlers.mousedisable);
  4520. }
  4521. };
  4522.  
  4523. $$util$properties$$make_properties($$input$devices$$Mouse, [
  4524. ['target', 'ro', 'dom'], // DOM element that captures mouse input
  4525. ['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement
  4526.  
  4527. ['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release
  4528. ['onMouseMove', 'rw', 'func'], // Handler for mouse movement
  4529. ['touchButton', 'rw', 'int'] // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
  4530. ]);
  4531.  
  4532. function $$websock$$Websock() {
  4533. "use strict";
  4534.  
  4535. this._websocket = null; // WebSocket object
  4536.  
  4537. this._rQi = 0; // Receive queue index
  4538. this._rQlen = 0; // Next write position in the receive queue
  4539. this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
  4540. this._rQmax = this._rQbufferSize / 8;
  4541. // called in init: this._rQ = new Uint8Array(this._rQbufferSize);
  4542. this._rQ = null; // Receive queue
  4543.  
  4544. this._sQbufferSize = 1024 * 10; // 10 KiB
  4545. // called in init: this._sQ = new Uint8Array(this._sQbufferSize);
  4546. this._sQlen = 0;
  4547. this._sQ = null; // Send queue
  4548.  
  4549. this._eventHandlers = {
  4550. 'message': function () {},
  4551. 'open': function () {},
  4552. 'close': function () {},
  4553. 'error': function () {}
  4554. };
  4555. }
  4556.  
  4557. var $$websock$$default = $$websock$$Websock;
  4558.  
  4559. // this has performance issues in some versions Chromium, and
  4560. // doesn't gain a tremendous amount of performance increase in Firefox
  4561. // at the moment. It may be valuable to turn it on in the future.
  4562. var $$websock$$ENABLE_COPYWITHIN = false;
  4563.  
  4564. var $$websock$$MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
  4565.  
  4566. var $$websock$$typedArrayToString = (function () {
  4567. // This is only for PhantomJS, which doesn't like apply-ing
  4568. // with Typed Arrays
  4569. try {
  4570. var arr = new Uint8Array([1, 2, 3]);
  4571. String.fromCharCode.apply(null, arr);
  4572. return function (a) { return String.fromCharCode.apply(null, a); };
  4573. } catch (ex) {
  4574. return function (a) {
  4575. return String.fromCharCode.apply(
  4576. null, Array.prototype.slice.call(a));
  4577. };
  4578. }
  4579. })();
  4580.  
  4581. $$websock$$Websock.prototype = {
  4582. // Getters and Setters
  4583. get_sQ: function () {
  4584. return this._sQ;
  4585. },
  4586.  
  4587. get_rQ: function () {
  4588. return this._rQ;
  4589. },
  4590.  
  4591. get_rQi: function () {
  4592. return this._rQi;
  4593. },
  4594.  
  4595. set_rQi: function (val) {
  4596. this._rQi = val;
  4597. },
  4598.  
  4599. // Receive Queue
  4600. rQlen: function () {
  4601. return this._rQlen - this._rQi;
  4602. },
  4603.  
  4604. rQpeek8: function () {
  4605. return this._rQ[this._rQi];
  4606. },
  4607.  
  4608. rQshift8: function () {
  4609. return this._rQ[this._rQi++];
  4610. },
  4611.  
  4612. rQskip8: function () {
  4613. this._rQi++;
  4614. },
  4615.  
  4616. rQskipBytes: function (num) {
  4617. this._rQi += num;
  4618. },
  4619.  
  4620. // TODO(directxman12): test performance with these vs a DataView
  4621. rQshift16: function () {
  4622. return (this._rQ[this._rQi++] << 8) +
  4623. this._rQ[this._rQi++];
  4624. },
  4625.  
  4626. rQshift32: function () {
  4627. return (this._rQ[this._rQi++] << 24) +
  4628. (this._rQ[this._rQi++] << 16) +
  4629. (this._rQ[this._rQi++] << 8) +
  4630. this._rQ[this._rQi++];
  4631. },
  4632.  
  4633. rQshiftStr: function (len) {
  4634. if (typeof(len) === 'undefined') { len = this.rQlen(); }
  4635. var arr = new Uint8Array(this._rQ.buffer, this._rQi, len);
  4636. this._rQi += len;
  4637. return $$websock$$typedArrayToString(arr);
  4638. },
  4639.  
  4640. rQshiftBytes: function (len) {
  4641. if (typeof(len) === 'undefined') { len = this.rQlen(); }
  4642. this._rQi += len;
  4643. return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
  4644. },
  4645.  
  4646. rQshiftTo: function (target, len) {
  4647. if (len === undefined) { len = this.rQlen(); }
  4648. // TODO: make this just use set with views when using a ArrayBuffer to store the rQ
  4649. target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
  4650. this._rQi += len;
  4651. },
  4652.  
  4653. rQwhole: function () {
  4654. return new Uint8Array(this._rQ.buffer, 0, this._rQlen);
  4655. },
  4656.  
  4657. rQslice: function (start, end) {
  4658. if (end) {
  4659. return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
  4660. } else {
  4661. return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start);
  4662. }
  4663. },
  4664.  
  4665. // Check to see if we must wait for 'num' bytes (default to FBU.bytes)
  4666. // to be available in the receive queue. Return true if we need to
  4667. // wait (and possibly print a debug message), otherwise false.
  4668. rQwait: function (msg, num, goback) {
  4669. var rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
  4670. if (rQlen < num) {
  4671. if (goback) {
  4672. if (this._rQi < goback) {
  4673. throw new Error("rQwait cannot backup " + goback + " bytes");
  4674. }
  4675. this._rQi -= goback;
  4676. }
  4677. return true; // true means need more data
  4678. }
  4679. return false;
  4680. },
  4681.  
  4682. // Send Queue
  4683.  
  4684. flush: function () {
  4685. if (this._websocket.bufferedAmount !== 0) {
  4686. $$$core$util$logging$$.Debug("bufferedAmount: " + this._websocket.bufferedAmount);
  4687. }
  4688.  
  4689. if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
  4690. this._websocket.send(this._encode_message());
  4691. this._sQlen = 0;
  4692. }
  4693. },
  4694.  
  4695. send: function (arr) {
  4696. this._sQ.set(arr, this._sQlen);
  4697. this._sQlen += arr.length;
  4698. this.flush();
  4699. },
  4700.  
  4701. send_string: function (str) {
  4702. this.send(str.split('').map(function (chr) {
  4703. return chr.charCodeAt(0);
  4704. }));
  4705. },
  4706.  
  4707. // Event Handlers
  4708. off: function (evt) {
  4709. this._eventHandlers[evt] = function () {};
  4710. },
  4711.  
  4712. on: function (evt, handler) {
  4713. this._eventHandlers[evt] = handler;
  4714. },
  4715.  
  4716. _allocate_buffers: function () {
  4717. this._rQ = new Uint8Array(this._rQbufferSize);
  4718. this._sQ = new Uint8Array(this._sQbufferSize);
  4719. },
  4720.  
  4721. init: function () {
  4722. this._allocate_buffers();
  4723. this._rQi = 0;
  4724. this._websocket = null;
  4725. },
  4726.  
  4727. open: function (uri, protocols) {
  4728. var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
  4729. this.init();
  4730.  
  4731. this._websocket = new WebSocket(uri, protocols);
  4732. this._websocket.binaryType = 'arraybuffer';
  4733.  
  4734. this._websocket.onmessage = this._recv_message.bind(this);
  4735. this._websocket.onopen = (function () {
  4736. $$$core$util$logging$$.Debug('>> WebSock.onopen');
  4737. if (this._websocket.protocol) {
  4738. $$$core$util$logging$$.Info("Server choose sub-protocol: " + this._websocket.protocol);
  4739. }
  4740.  
  4741. this._eventHandlers.open();
  4742. $$$core$util$logging$$.Debug("<< WebSock.onopen");
  4743. }).bind(this);
  4744. this._websocket.onclose = (function (e) {
  4745. $$$core$util$logging$$.Debug(">> WebSock.onclose");
  4746. this._eventHandlers.close(e);
  4747. $$$core$util$logging$$.Debug("<< WebSock.onclose");
  4748. }).bind(this);
  4749. this._websocket.onerror = (function (e) {
  4750. $$$core$util$logging$$.Debug(">> WebSock.onerror: " + e);
  4751. this._eventHandlers.error(e);
  4752. $$$core$util$logging$$.Debug("<< WebSock.onerror: " + e);
  4753. }).bind(this);
  4754. },
  4755.  
  4756. close: function () {
  4757. if (this._websocket) {
  4758. if ((this._websocket.readyState === WebSocket.OPEN) ||
  4759. (this._websocket.readyState === WebSocket.CONNECTING)) {
  4760. $$$core$util$logging$$.Info("Closing WebSocket connection");
  4761. this._websocket.close();
  4762. }
  4763.  
  4764. this._websocket.onmessage = function (e) { return; };
  4765. }
  4766. },
  4767.  
  4768. // private methods
  4769. _encode_message: function () {
  4770. // Put in a binary arraybuffer
  4771. // according to the spec, you can send ArrayBufferViews with the send method
  4772. return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
  4773. },
  4774.  
  4775. _expand_compact_rQ: function (min_fit) {
  4776. var resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
  4777. if (resizeNeeded) {
  4778. if (!min_fit) {
  4779. // just double the size if we need to do compaction
  4780. this._rQbufferSize *= 2;
  4781. } else {
  4782. // otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8
  4783. this._rQbufferSize = (this._rQlen - this._rQi + min_fit) * 8;
  4784. }
  4785. }
  4786.  
  4787. // we don't want to grow unboundedly
  4788. if (this._rQbufferSize > $$websock$$MAX_RQ_GROW_SIZE) {
  4789. this._rQbufferSize = $$websock$$MAX_RQ_GROW_SIZE;
  4790. if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) {
  4791. throw new Exception("Receive Queue buffer exceeded " + $$websock$$MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
  4792. }
  4793. }
  4794.  
  4795. if (resizeNeeded) {
  4796. var old_rQbuffer = this._rQ.buffer;
  4797. this._rQmax = this._rQbufferSize / 8;
  4798. this._rQ = new Uint8Array(this._rQbufferSize);
  4799. this._rQ.set(new Uint8Array(old_rQbuffer, this._rQi));
  4800. } else {
  4801. if ($$websock$$ENABLE_COPYWITHIN) {
  4802. this._rQ.copyWithin(0, this._rQi);
  4803. } else {
  4804. this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi));
  4805. }
  4806. }
  4807.  
  4808. this._rQlen = this._rQlen - this._rQi;
  4809. this._rQi = 0;
  4810. },
  4811.  
  4812. _decode_message: function (data) {
  4813. // push arraybuffer values onto the end
  4814. var u8 = new Uint8Array(data);
  4815. if (u8.length > this._rQbufferSize - this._rQlen) {
  4816. this._expand_compact_rQ(u8.length);
  4817. }
  4818. this._rQ.set(u8, this._rQlen);
  4819. this._rQlen += u8.length;
  4820. },
  4821.  
  4822. _recv_message: function (e) {
  4823. try {
  4824. this._decode_message(e.data);
  4825. if (this.rQlen() > 0) {
  4826. this._eventHandlers.message();
  4827. // Compact the receive queue
  4828. if (this._rQlen == this._rQi) {
  4829. this._rQlen = 0;
  4830. this._rQi = 0;
  4831. } else if (this._rQlen > this._rQmax) {
  4832. this._expand_compact_rQ();
  4833. }
  4834. } else {
  4835. $$$core$util$logging$$.Debug("Ignoring empty message");
  4836. }
  4837. } catch (exc) {
  4838. var exception_str = "";
  4839. if (exc.name) {
  4840. exception_str += "\n name: " + exc.name + "\n";
  4841. exception_str += " message: " + exc.message + "\n";
  4842. }
  4843.  
  4844. if (typeof exc.description !== 'undefined') {
  4845. exception_str += " description: " + exc.description + "\n";
  4846. }
  4847.  
  4848. if (typeof exc.stack !== 'undefined') {
  4849. exception_str += exc.stack;
  4850. }
  4851.  
  4852. if (exception_str.length > 0) {
  4853. $$$core$util$logging$$.Error("recv_message, caught exception: " + exception_str);
  4854. } else {
  4855. $$$core$util$logging$$.Error("recv_message, caught exception: " + exc);
  4856. }
  4857.  
  4858. if (typeof exc.name !== 'undefined') {
  4859. this._eventHandlers.error(exc.name + ": " + exc.message);
  4860. } else {
  4861. this._eventHandlers.error(exc);
  4862. }
  4863. }
  4864. }
  4865. };
  4866.  
  4867. function $$des$$DES(passwd) {
  4868. "use strict";
  4869.  
  4870. // Tables, permutations, S-boxes, etc.
  4871. // jshint -W013
  4872. var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
  4873. 25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39,
  4874. 50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ],
  4875. totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28],
  4876. z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,
  4877. keys = [];
  4878.  
  4879. // jshint -W015
  4880. a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e;
  4881. SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d,
  4882. z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z,
  4883. a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f,
  4884. c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d];
  4885. a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e;
  4886. SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d,
  4887. a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f,
  4888. z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z,
  4889. z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e];
  4890. a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e;
  4891. SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f,
  4892. b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z,
  4893. c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d,
  4894. b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e];
  4895. a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e;
  4896. SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d,
  4897. z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f,
  4898. b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e,
  4899. c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e];
  4900. a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e;
  4901. SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z,
  4902. a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f,
  4903. z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e,
  4904. c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d];
  4905. a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e;
  4906. SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f,
  4907. z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z,
  4908. b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z,
  4909. a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f];
  4910. a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e;
  4911. SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f,
  4912. b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e,
  4913. b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e,
  4914. z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d];
  4915. a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e;
  4916. SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d,
  4917. c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z,
  4918. a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f,
  4919. z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e];
  4920. // jshint +W013,+W015
  4921.  
  4922. // Set the key.
  4923. function setKeys(keyBlock) {
  4924. var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [],
  4925. raw0, raw1, rawi, KnLi;
  4926.  
  4927. for (j = 0, l = 56; j < 56; ++j, l -= 8) {
  4928. l += l < -5 ? 65 : l < -3 ? 31 : l < -1 ? 63 : l === 27 ? 35 : 0; // PC1
  4929. m = l & 0x7;
  4930. pc1m[j] = ((keyBlock[l >>> 3] & (1<<m)) !== 0) ? 1: 0;
  4931. }
  4932.  
  4933. for (i = 0; i < 16; ++i) {
  4934. m = i << 1;
  4935. n = m + 1;
  4936. kn[m] = kn[n] = 0;
  4937. for (o = 28; o < 59; o += 28) {
  4938. for (j = o - 28; j < o; ++j) {
  4939. l = j + totrot[i];
  4940. if (l < o) {
  4941. pcr[j] = pc1m[l];
  4942. } else {
  4943. pcr[j] = pc1m[l - 28];
  4944. }
  4945. }
  4946. }
  4947. for (j = 0; j < 24; ++j) {
  4948. if (pcr[PC2[j]] !== 0) {
  4949. kn[m] |= 1 << (23 - j);
  4950. }
  4951. if (pcr[PC2[j + 24]] !== 0) {
  4952. kn[n] |= 1 << (23 - j);
  4953. }
  4954. }
  4955. }
  4956.  
  4957. // cookey
  4958. for (i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
  4959. raw0 = kn[rawi++];
  4960. raw1 = kn[rawi++];
  4961. keys[KnLi] = (raw0 & 0x00fc0000) << 6;
  4962. keys[KnLi] |= (raw0 & 0x00000fc0) << 10;
  4963. keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
  4964. keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6;
  4965. ++KnLi;
  4966. keys[KnLi] = (raw0 & 0x0003f000) << 12;
  4967. keys[KnLi] |= (raw0 & 0x0000003f) << 16;
  4968. keys[KnLi] |= (raw1 & 0x0003f000) >>> 4;
  4969. keys[KnLi] |= (raw1 & 0x0000003f);
  4970. ++KnLi;
  4971. }
  4972. }
  4973.  
  4974. // Encrypt 8 bytes of text
  4975. function enc8(text) {
  4976. var i = 0, b = text.slice(), fval, keysi = 0,
  4977. l, r, x; // left, right, accumulator
  4978.  
  4979. // Squash 8 bytes to 2 ints
  4980. l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
  4981. r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
  4982.  
  4983. x = ((l >>> 4) ^ r) & 0x0f0f0f0f;
  4984. r ^= x;
  4985. l ^= (x << 4);
  4986. x = ((l >>> 16) ^ r) & 0x0000ffff;
  4987. r ^= x;
  4988. l ^= (x << 16);
  4989. x = ((r >>> 2) ^ l) & 0x33333333;
  4990. l ^= x;
  4991. r ^= (x << 2);
  4992. x = ((r >>> 8) ^ l) & 0x00ff00ff;
  4993. l ^= x;
  4994. r ^= (x << 8);
  4995. r = (r << 1) | ((r >>> 31) & 1);
  4996. x = (l ^ r) & 0xaaaaaaaa;
  4997. l ^= x;
  4998. r ^= x;
  4999. l = (l << 1) | ((l >>> 31) & 1);
  5000.  
  5001. for (i = 0; i < 8; ++i) {
  5002. x = (r << 28) | (r >>> 4);
  5003. x ^= keys[keysi++];
  5004. fval = SP7[x & 0x3f];
  5005. fval |= SP5[(x >>> 8) & 0x3f];
  5006. fval |= SP3[(x >>> 16) & 0x3f];
  5007. fval |= SP1[(x >>> 24) & 0x3f];
  5008. x = r ^ keys[keysi++];
  5009. fval |= SP8[x & 0x3f];
  5010. fval |= SP6[(x >>> 8) & 0x3f];
  5011. fval |= SP4[(x >>> 16) & 0x3f];
  5012. fval |= SP2[(x >>> 24) & 0x3f];
  5013. l ^= fval;
  5014. x = (l << 28) | (l >>> 4);
  5015. x ^= keys[keysi++];
  5016. fval = SP7[x & 0x3f];
  5017. fval |= SP5[(x >>> 8) & 0x3f];
  5018. fval |= SP3[(x >>> 16) & 0x3f];
  5019. fval |= SP1[(x >>> 24) & 0x3f];
  5020. x = l ^ keys[keysi++];
  5021. fval |= SP8[x & 0x0000003f];
  5022. fval |= SP6[(x >>> 8) & 0x3f];
  5023. fval |= SP4[(x >>> 16) & 0x3f];
  5024. fval |= SP2[(x >>> 24) & 0x3f];
  5025. r ^= fval;
  5026. }
  5027.  
  5028. r = (r << 31) | (r >>> 1);
  5029. x = (l ^ r) & 0xaaaaaaaa;
  5030. l ^= x;
  5031. r ^= x;
  5032. l = (l << 31) | (l >>> 1);
  5033. x = ((l >>> 8) ^ r) & 0x00ff00ff;
  5034. r ^= x;
  5035. l ^= (x << 8);
  5036. x = ((l >>> 2) ^ r) & 0x33333333;
  5037. r ^= x;
  5038. l ^= (x << 2);
  5039. x = ((r >>> 16) ^ l) & 0x0000ffff;
  5040. l ^= x;
  5041. r ^= (x << 16);
  5042. x = ((r >>> 4) ^ l) & 0x0f0f0f0f;
  5043. l ^= x;
  5044. r ^= (x << 4);
  5045.  
  5046. // Spread ints to bytes
  5047. x = [r, l];
  5048. for (i = 0; i < 8; i++) {
  5049. b[i] = (x[i>>>2] >>> (8 * (3 - (i % 4)))) % 256;
  5050. if (b[i] < 0) { b[i] += 256; } // unsigned
  5051. }
  5052. return b;
  5053. }
  5054.  
  5055. // Encrypt 16 bytes of text using passwd as key
  5056. function encrypt(t) {
  5057. return enc8(t.slice(0, 8)).concat(enc8(t.slice(8, 16)));
  5058. }
  5059.  
  5060. setKeys(passwd); // Setup keys
  5061. return {'encrypt': encrypt}; // Public interface
  5062.  
  5063. }
  5064.  
  5065. var $$des$$default = $$des$$DES;
  5066.  
  5067. var $$input$xtscancodes$$default = {
  5068. "Escape": 0x0001,
  5069. "Digit1": 0x0002,
  5070. "Digit2": 0x0003,
  5071. "Digit3": 0x0004,
  5072. "Digit4": 0x0005,
  5073. "Digit5": 0x0006,
  5074. "Digit6": 0x0007,
  5075. "Digit7": 0x0008,
  5076. "Digit8": 0x0009,
  5077. "Digit9": 0x000A,
  5078. "Digit0": 0x000B,
  5079. "Minus": 0x000C,
  5080. "Equal": 0x000D,
  5081. "Backspace": 0x000E,
  5082. "Tab": 0x000F,
  5083. "KeyQ": 0x0010,
  5084. "KeyW": 0x0011,
  5085. "KeyE": 0x0012,
  5086. "KeyR": 0x0013,
  5087. "KeyT": 0x0014,
  5088. "KeyY": 0x0015,
  5089. "KeyU": 0x0016,
  5090. "KeyI": 0x0017,
  5091. "KeyO": 0x0018,
  5092. "KeyP": 0x0019,
  5093. "BracketLeft": 0x001A,
  5094. "BracketRight": 0x001B,
  5095. "Enter": 0x001C,
  5096. "ControlLeft": 0x001D,
  5097. "KeyA": 0x001E,
  5098. "KeyS": 0x001F,
  5099. "KeyD": 0x0020,
  5100. "KeyF": 0x0021,
  5101. "KeyG": 0x0022,
  5102. "KeyH": 0x0023,
  5103. "KeyJ": 0x0024,
  5104. "KeyK": 0x0025,
  5105. "KeyL": 0x0026,
  5106. "Semicolon": 0x0027,
  5107. "Quote": 0x0028,
  5108. "Backquote": 0x0029,
  5109. "ShiftLeft": 0x002A,
  5110. "Backslash": 0x002B,
  5111. "KeyZ": 0x002C,
  5112. "KeyX": 0x002D,
  5113. "KeyC": 0x002E,
  5114. "KeyV": 0x002F,
  5115. "KeyB": 0x0030,
  5116. "KeyN": 0x0031,
  5117. "KeyM": 0x0032,
  5118. "Comma": 0x0033,
  5119. "Period": 0x0034,
  5120. "Slash": 0x0035,
  5121. "ShiftRight": 0x0036,
  5122. "NumpadMultiply": 0x0037,
  5123. "AltLeft": 0x0038,
  5124. "Space": 0x0039,
  5125. "CapsLock": 0x003A,
  5126. "F1": 0x003B,
  5127. "F2": 0x003C,
  5128. "F3": 0x003D,
  5129. "F4": 0x003E,
  5130. "F5": 0x003F,
  5131. "F6": 0x0040,
  5132. "F7": 0x0041,
  5133. "F8": 0x0042,
  5134. "F9": 0x0043,
  5135. "F10": 0x0044,
  5136. "Pause": 0xE045,
  5137. "ScrollLock": 0x0046,
  5138. "Numpad7": 0x0047,
  5139. "Numpad8": 0x0048,
  5140. "Numpad9": 0x0049,
  5141. "NumpadSubtract": 0x004A,
  5142. "Numpad4": 0x004B,
  5143. "Numpad5": 0x004C,
  5144. "Numpad6": 0x004D,
  5145. "NumpadAdd": 0x004E,
  5146. "Numpad1": 0x004F,
  5147. "Numpad2": 0x0050,
  5148. "Numpad3": 0x0051,
  5149. "Numpad0": 0x0052,
  5150. "NumpadDecimal": 0x0053,
  5151. "IntlBackslash": 0x0056,
  5152. "F11": 0x0057,
  5153. "F12": 0x0058,
  5154. "IntlYen": 0x007D,
  5155. "MediaTrackPrevious": 0xE010,
  5156. "MediaTrackNext": 0xE019,
  5157. "NumpadEnter": 0xE01C,
  5158. "ControlRight": 0xE01D,
  5159. "VolumeMute": 0xE020,
  5160. "MediaPlayPause": 0xE022,
  5161. "MediaStop": 0xE024,
  5162. "VolumeDown": 0xE02E,
  5163. "VolumeUp": 0xE030,
  5164. "BrowserHome": 0xE032,
  5165. "NumpadDivide": 0xE035,
  5166. "PrintScreen": 0xE037,
  5167. "AltRight": 0xE038,
  5168. "NumLock": 0x0045,
  5169. "Home": 0xE047,
  5170. "ArrowUp": 0xE048,
  5171. "PageUp": 0xE049,
  5172. "ArrowLeft": 0xE04B,
  5173. "ArrowRight": 0xE04D,
  5174. "End": 0xE04F,
  5175. "ArrowDown": 0xE050,
  5176. "PageDown": 0xE051,
  5177. "Insert": 0xE052,
  5178. "Delete": 0xE053,
  5179. "MetaLeft": 0xE05B,
  5180. "MetaRight": 0xE05C,
  5181. "ContextMenu": 0xE05D,
  5182. "BrowserSearch": 0xE065,
  5183. "BrowserFavorites": 0xE066,
  5184. "BrowserRefresh": 0xE067,
  5185. "BrowserStop": 0xE068,
  5186. "BrowserForward": 0xE069,
  5187. "BrowserBack": 0xE06A,
  5188. "NumpadComma": 0x007E,
  5189. "NumpadEqual": 0x0059,
  5190. "F13": 0x0064,
  5191. "F14": 0x0065,
  5192. "F15": 0x0066,
  5193. "F16": 0x0067,
  5194. "F17": 0x0068,
  5195. "F18": 0x0069,
  5196. "F19": 0x006A,
  5197. "F20": 0x006B,
  5198. "F21": 0x006C,
  5199. "F22": 0x006D,
  5200. "F23": 0x006E,
  5201. "F24": 0x0076,
  5202. "KanaMode": 0x0070,
  5203. "Lang2": 0x0071,
  5204. "Lang1": 0x0072,
  5205. "IntlRo": 0x0073,
  5206. "Convert": 0x0079,
  5207. "NonConvert": 0x007B,
  5208. "LaunchApp2": 0xE021,
  5209. "Power": 0xE05E,
  5210. "LaunchApp1": 0xE06B,
  5211. "LaunchMail": 0xE06C,
  5212. "MediaSelect": 0xE06D
  5213. };
  5214.  
  5215. function $$$utils$common$$shrinkBuf(buf, size) {
  5216. if (buf.length === size) { return buf; }
  5217. if (buf.subarray) { return buf.subarray(0, size); }
  5218. buf.length = size;
  5219. return buf;
  5220. }
  5221.  
  5222. function $$$utils$common$$arraySet(dest, src, src_offs, len, dest_offs) {
  5223. if (src.subarray && dest.subarray) {
  5224. dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
  5225. return;
  5226. }
  5227. // Fallback to ordinary array
  5228. for (var i = 0; i < len; i++) {
  5229. dest[dest_offs + i] = src[src_offs + i];
  5230. }
  5231. }
  5232.  
  5233. function $$$utils$common$$flattenChunks(chunks) {
  5234. var i, l, len, pos, chunk, result;
  5235.  
  5236. // calculate data length
  5237. len = 0;
  5238. for (i = 0, l = chunks.length; i < l; i++) {
  5239. len += chunks[i].length;
  5240. }
  5241.  
  5242. // join chunks
  5243. result = new Uint8Array(len);
  5244. pos = 0;
  5245. for (i = 0, l = chunks.length; i < l; i++) {
  5246. chunk = chunks[i];
  5247. result.set(chunk, pos);
  5248. pos += chunk.length;
  5249. }
  5250.  
  5251. return result;
  5252. }
  5253.  
  5254. const $$$utils$common$$Buf8 = Uint8Array;
  5255. const $$$utils$common$$Buf16 = Uint16Array;
  5256. const $$$utils$common$$Buf32 = Int32Array;
  5257.  
  5258. function $$adler32$$adler32(adler, buf, len, pos) {
  5259. var s1 = (adler & 0xffff) |0,
  5260. s2 = ((adler >>> 16) & 0xffff) |0,
  5261. n = 0;
  5262.  
  5263. while (len !== 0) {
  5264. // Set limit ~ twice less than 5552, to keep
  5265. // s2 in 31-bits, because we force signed ints.
  5266. // in other case %= will fail.
  5267. n = len > 2000 ? 2000 : len;
  5268. len -= n;
  5269.  
  5270. do {
  5271. s1 = (s1 + buf[pos++]) |0;
  5272. s2 = (s2 + s1) |0;
  5273. } while (--n);
  5274.  
  5275. s1 %= 65521;
  5276. s2 %= 65521;
  5277. }
  5278.  
  5279. return (s1 | (s2 << 16)) |0;
  5280. }
  5281.  
  5282. var $$adler32$$default = $$adler32$$adler32;
  5283.  
  5284. function $$crc32$$makeTable() {
  5285. var c, table = [];
  5286.  
  5287. for (var n = 0; n < 256; n++) {
  5288. c = n;
  5289. for (var k = 0; k < 8; k++) {
  5290. c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
  5291. }
  5292. table[n] = c;
  5293. }
  5294.  
  5295. return table;
  5296. }
  5297.  
  5298. var $$crc32$$default = $$crc32$$makeTable;
  5299.  
  5300. // Create table on load. Just 255 signed longs. Not a problem.
  5301. var $$crc32$$crcTable = $$crc32$$makeTable();
  5302.  
  5303.  
  5304. function $$crc32$$crc32(crc, buf, len, pos) {
  5305. var t = $$crc32$$crcTable,
  5306. end = pos + len;
  5307.  
  5308. crc ^= -1;
  5309.  
  5310. for (var i = pos; i < end; i++) {
  5311. crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
  5312. }
  5313.  
  5314. return (crc ^ (-1)); // >>> 0;
  5315. }
  5316. // See state defs from inflate.js
  5317. var $$inffast$$BAD = 30;/* got a data error -- remain here until reset */
  5318. var $$inffast$$TYPE = 12;
  5319.  
  5320. function $$inffast$$inflate_fast(strm, start) {
  5321. var state;
  5322. var _in; /* local strm.input */
  5323. var last; /* have enough input while in < last */
  5324. var _out; /* local strm.output */
  5325. var beg; /* inflate()'s initial strm.output */
  5326. var end; /* while out < end, enough space available */
  5327. //#ifdef INFLATE_STRICT
  5328. var dmax; /* maximum distance from zlib header */
  5329. //#endif
  5330. var wsize; /* window size or zero if not using window */
  5331. var whave; /* valid bytes in the window */
  5332. var wnext; /* window write index */
  5333. // Use `s_window` instead `window`, avoid conflict with instrumentation tools
  5334. var s_window; /* allocated sliding window, if wsize != 0 */
  5335. var hold; /* local strm.hold */
  5336. var bits; /* local strm.bits */
  5337. var lcode; /* local strm.lencode */
  5338. var dcode; /* local strm.distcode */
  5339. var lmask; /* mask for first level of length codes */
  5340. var dmask; /* mask for first level of distance codes */
  5341. var here; /* retrieved table entry */
  5342. var op; /* code bits, operation, extra bits, or */
  5343. /* window position, window bytes to copy */
  5344. var len; /* match length, unused bytes */
  5345. var dist; /* match distance */
  5346. var from; /* where to copy match from */
  5347. var from_source;
  5348.  
  5349.  
  5350. var input, output; // JS specific, because we have no pointers
  5351.  
  5352. /* copy state to local variables */
  5353. state = strm.state;
  5354. //here = state.here;
  5355. _in = strm.next_in;
  5356. input = strm.input;
  5357. last = _in + (strm.avail_in - 5);
  5358. _out = strm.next_out;
  5359. output = strm.output;
  5360. beg = _out - (start - strm.avail_out);
  5361. end = _out + (strm.avail_out - 257);
  5362. //#ifdef INFLATE_STRICT
  5363. dmax = state.dmax;
  5364. //#endif
  5365. wsize = state.wsize;
  5366. whave = state.whave;
  5367. wnext = state.wnext;
  5368. s_window = state.window;
  5369. hold = state.hold;
  5370. bits = state.bits;
  5371. lcode = state.lencode;
  5372. dcode = state.distcode;
  5373. lmask = (1 << state.lenbits) - 1;
  5374. dmask = (1 << state.distbits) - 1;
  5375.  
  5376.  
  5377. /* decode literals and length/distances until end-of-block or not enough
  5378. input data or output space */
  5379.  
  5380. top:
  5381. do {
  5382. if (bits < 15) {
  5383. hold += input[_in++] << bits;
  5384. bits += 8;
  5385. hold += input[_in++] << bits;
  5386. bits += 8;
  5387. }
  5388.  
  5389. here = lcode[hold & lmask];
  5390.  
  5391. dolen:
  5392. for (;;) { // Goto emulation
  5393. op = here >>> 24/*here.bits*/;
  5394. hold >>>= op;
  5395. bits -= op;
  5396. op = (here >>> 16) & 0xff/*here.op*/;
  5397. if (op === 0) { /* literal */
  5398. //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
  5399. // "inflate: literal '%c'\n" :
  5400. // "inflate: literal 0x%02x\n", here.val));
  5401. output[_out++] = here & 0xffff/*here.val*/;
  5402. }
  5403. else if (op & 16) { /* length base */
  5404. len = here & 0xffff/*here.val*/;
  5405. op &= 15; /* number of extra bits */
  5406. if (op) {
  5407. if (bits < op) {
  5408. hold += input[_in++] << bits;
  5409. bits += 8;
  5410. }
  5411. len += hold & ((1 << op) - 1);
  5412. hold >>>= op;
  5413. bits -= op;
  5414. }
  5415. //Tracevv((stderr, "inflate: length %u\n", len));
  5416. if (bits < 15) {
  5417. hold += input[_in++] << bits;
  5418. bits += 8;
  5419. hold += input[_in++] << bits;
  5420. bits += 8;
  5421. }
  5422. here = dcode[hold & dmask];
  5423.  
  5424. dodist:
  5425. for (;;) { // goto emulation
  5426. op = here >>> 24/*here.bits*/;
  5427. hold >>>= op;
  5428. bits -= op;
  5429. op = (here >>> 16) & 0xff/*here.op*/;
  5430.  
  5431. if (op & 16) { /* distance base */
  5432. dist = here & 0xffff/*here.val*/;
  5433. op &= 15; /* number of extra bits */
  5434. if (bits < op) {
  5435. hold += input[_in++] << bits;
  5436. bits += 8;
  5437. if (bits < op) {
  5438. hold += input[_in++] << bits;
  5439. bits += 8;
  5440. }
  5441. }
  5442. dist += hold & ((1 << op) - 1);
  5443. //#ifdef INFLATE_STRICT
  5444. if (dist > dmax) {
  5445. strm.msg = 'invalid distance too far back';
  5446. state.mode = $$inffast$$BAD;
  5447. break top;
  5448. }
  5449. //#endif
  5450. hold >>>= op;
  5451. bits -= op;
  5452. //Tracevv((stderr, "inflate: distance %u\n", dist));
  5453. op = _out - beg; /* max distance in output */
  5454. if (dist > op) { /* see if copy from window */
  5455. op = dist - op; /* distance back in window */
  5456. if (op > whave) {
  5457. if (state.sane) {
  5458. strm.msg = 'invalid distance too far back';
  5459. state.mode = $$inffast$$BAD;
  5460. break top;
  5461. }
  5462.  
  5463. // (!) This block is disabled in zlib defailts,
  5464. // don't enable it for binary compatibility
  5465. //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
  5466. // if (len <= op - whave) {
  5467. // do {
  5468. // output[_out++] = 0;
  5469. // } while (--len);
  5470. // continue top;
  5471. // }
  5472. // len -= op - whave;
  5473. // do {
  5474. // output[_out++] = 0;
  5475. // } while (--op > whave);
  5476. // if (op === 0) {
  5477. // from = _out - dist;
  5478. // do {
  5479. // output[_out++] = output[from++];
  5480. // } while (--len);
  5481. // continue top;
  5482. // }
  5483. //#endif
  5484. }
  5485. from = 0; // window index
  5486. from_source = s_window;
  5487. if (wnext === 0) { /* very common case */
  5488. from += wsize - op;
  5489. if (op < len) { /* some from window */
  5490. len -= op;
  5491. do {
  5492. output[_out++] = s_window[from++];
  5493. } while (--op);
  5494. from = _out - dist; /* rest from output */
  5495. from_source = output;
  5496. }
  5497. }
  5498. else if (wnext < op) { /* wrap around window */
  5499. from += wsize + wnext - op;
  5500. op -= wnext;
  5501. if (op < len) { /* some from end of window */
  5502. len -= op;
  5503. do {
  5504. output[_out++] = s_window[from++];
  5505. } while (--op);
  5506. from = 0;
  5507. if (wnext < len) { /* some from start of window */
  5508. op = wnext;
  5509. len -= op;
  5510. do {
  5511. output[_out++] = s_window[from++];
  5512. } while (--op);
  5513. from = _out - dist; /* rest from output */
  5514. from_source = output;
  5515. }
  5516. }
  5517. }
  5518. else { /* contiguous in window */
  5519. from += wnext - op;
  5520. if (op < len) { /* some from window */
  5521. len -= op;
  5522. do {
  5523. output[_out++] = s_window[from++];
  5524. } while (--op);
  5525. from = _out - dist; /* rest from output */
  5526. from_source = output;
  5527. }
  5528. }
  5529. while (len > 2) {
  5530. output[_out++] = from_source[from++];
  5531. output[_out++] = from_source[from++];
  5532. output[_out++] = from_source[from++];
  5533. len -= 3;
  5534. }
  5535. if (len) {
  5536. output[_out++] = from_source[from++];
  5537. if (len > 1) {
  5538. output[_out++] = from_source[from++];
  5539. }
  5540. }
  5541. }
  5542. else {
  5543. from = _out - dist; /* copy direct from output */
  5544. do { /* minimum length is three */
  5545. output[_out++] = output[from++];
  5546. output[_out++] = output[from++];
  5547. output[_out++] = output[from++];
  5548. len -= 3;
  5549. } while (len > 2);
  5550. if (len) {
  5551. output[_out++] = output[from++];
  5552. if (len > 1) {
  5553. output[_out++] = output[from++];
  5554. }
  5555. }
  5556. }
  5557. }
  5558. else if ((op & 64) === 0) { /* 2nd level distance code */
  5559. here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
  5560. continue dodist;
  5561. }
  5562. else {
  5563. strm.msg = 'invalid distance code';
  5564. state.mode = $$inffast$$BAD;
  5565. break top;
  5566. }
  5567.  
  5568. break; // need to emulate goto via "continue"
  5569. }
  5570. }
  5571. else if ((op & 64) === 0) { /* 2nd level length code */
  5572. here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
  5573. continue dolen;
  5574. }
  5575. else if (op & 32) { /* end-of-block */
  5576. //Tracevv((stderr, "inflate: end of block\n"));
  5577. state.mode = $$inffast$$TYPE;
  5578. break top;
  5579. }
  5580. else {
  5581. strm.msg = 'invalid literal/length code';
  5582. state.mode = $$inffast$$BAD;
  5583. break top;
  5584. }
  5585.  
  5586. break; // need to emulate goto via "continue"
  5587. }
  5588. } while (_in < last && _out < end);
  5589.  
  5590. /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
  5591. len = bits >> 3;
  5592. _in -= len;
  5593. bits -= len << 3;
  5594. hold &= (1 << bits) - 1;
  5595.  
  5596. /* update state and return */
  5597. strm.next_in = _in;
  5598. strm.next_out = _out;
  5599. strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
  5600. strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
  5601. state.hold = hold;
  5602. state.bits = bits;
  5603. return;
  5604. }
  5605.  
  5606. var $$inffast$$default = $$inffast$$inflate_fast;
  5607.  
  5608. var $$inftrees$$MAXBITS = 15;
  5609. var $$inftrees$$ENOUGH_LENS = 852;
  5610. var $$inftrees$$ENOUGH_DISTS = 592;
  5611. //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
  5612.  
  5613. var $$inftrees$$CODES = 0;
  5614. var $$inftrees$$LENS = 1;
  5615. var $$inftrees$$DISTS = 2;
  5616.  
  5617. var $$inftrees$$lbase = [ /* Length codes 257..285 base */
  5618. 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  5619. 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
  5620. ];
  5621.  
  5622. var $$inftrees$$lext = [ /* Length codes 257..285 extra */
  5623. 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
  5624. 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
  5625. ];
  5626.  
  5627. var $$inftrees$$dbase = [ /* Distance codes 0..29 base */
  5628. 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  5629. 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  5630. 8193, 12289, 16385, 24577, 0, 0
  5631. ];
  5632.  
  5633. var $$inftrees$$dext = [ /* Distance codes 0..29 extra */
  5634. 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
  5635. 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
  5636. 28, 28, 29, 29, 64, 64
  5637. ];
  5638.  
  5639. function $$inftrees$$inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) {
  5640. var bits = opts.bits;
  5641. //here = opts.here; /* table entry for duplication */
  5642.  
  5643. var len = 0; /* a code's length in bits */
  5644. var sym = 0; /* index of code symbols */
  5645. var min = 0, max = 0; /* minimum and maximum code lengths */
  5646. var root = 0; /* number of index bits for root table */
  5647. var curr = 0; /* number of index bits for current table */
  5648. var drop = 0; /* code bits to drop for sub-table */
  5649. var left = 0; /* number of prefix codes available */
  5650. var used = 0; /* code entries in table used */
  5651. var huff = 0; /* Huffman code */
  5652. var incr; /* for incrementing code, index */
  5653. var fill; /* index for replicating entries */
  5654. var low; /* low bits for current root entry */
  5655. var mask; /* mask for low root bits */
  5656. var next; /* next available space in table */
  5657. var base = null; /* base value table to use */
  5658. var base_index = 0;
  5659. // var shoextra; /* extra bits table to use */
  5660. var end; /* use base and extra for symbol > end */
  5661. var count = new $$$utils$common$$.Buf16($$inftrees$$MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */
  5662. var offs = new $$$utils$common$$.Buf16($$inftrees$$MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */
  5663. var extra = null;
  5664. var extra_index = 0;
  5665.  
  5666. var here_bits, here_op, here_val;
  5667.  
  5668. /*
  5669. Process a set of code lengths to create a canonical Huffman code. The
  5670. code lengths are lens[0..codes-1]. Each length corresponds to the
  5671. symbols 0..codes-1. The Huffman code is generated by first sorting the
  5672. symbols by length from short to long, and retaining the symbol order
  5673. for codes with equal lengths. Then the code starts with all zero bits
  5674. for the first code of the shortest length, and the codes are integer
  5675. increments for the same length, and zeros are appended as the length
  5676. increases. For the deflate format, these bits are stored backwards
  5677. from their more natural integer increment ordering, and so when the
  5678. decoding tables are built in the large loop below, the integer codes
  5679. are incremented backwards.
  5680.  
  5681. This routine assumes, but does not check, that all of the entries in
  5682. lens[] are in the range 0..MAXBITS. The caller must assure this.
  5683. 1..MAXBITS is interpreted as that code length. zero means that that
  5684. symbol does not occur in this code.
  5685.  
  5686. The codes are sorted by computing a count of codes for each length,
  5687. creating from that a table of starting indices for each length in the
  5688. sorted table, and then entering the symbols in order in the sorted
  5689. table. The sorted table is work[], with that space being provided by
  5690. the caller.
  5691.  
  5692. The length counts are used for other purposes as well, i.e. finding
  5693. the minimum and maximum length codes, determining if there are any
  5694. codes at all, checking for a valid set of lengths, and looking ahead
  5695. at length counts to determine sub-table sizes when building the
  5696. decoding tables.
  5697. */
  5698.  
  5699. /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
  5700. for (len = 0; len <= $$inftrees$$MAXBITS; len++) {
  5701. count[len] = 0;
  5702. }
  5703. for (sym = 0; sym < codes; sym++) {
  5704. count[lens[lens_index + sym]]++;
  5705. }
  5706.  
  5707. /* bound code lengths, force root to be within code lengths */
  5708. root = bits;
  5709. for (max = $$inftrees$$MAXBITS; max >= 1; max--) {
  5710. if (count[max] !== 0) { break; }
  5711. }
  5712. if (root > max) {
  5713. root = max;
  5714. }
  5715. if (max === 0) { /* no symbols to code at all */
  5716. //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
  5717. //table.bits[opts.table_index] = 1; //here.bits = (var char)1;
  5718. //table.val[opts.table_index++] = 0; //here.val = (var short)0;
  5719. table[table_index++] = (1 << 24) | (64 << 16) | 0;
  5720.  
  5721.  
  5722. //table.op[opts.table_index] = 64;
  5723. //table.bits[opts.table_index] = 1;
  5724. //table.val[opts.table_index++] = 0;
  5725. table[table_index++] = (1 << 24) | (64 << 16) | 0;
  5726.  
  5727. opts.bits = 1;
  5728. return 0; /* no symbols, but wait for decoding to report error */
  5729. }
  5730. for (min = 1; min < max; min++) {
  5731. if (count[min] !== 0) { break; }
  5732. }
  5733. if (root < min) {
  5734. root = min;
  5735. }
  5736.  
  5737. /* check for an over-subscribed or incomplete set of lengths */
  5738. left = 1;
  5739. for (len = 1; len <= $$inftrees$$MAXBITS; len++) {
  5740. left <<= 1;
  5741. left -= count[len];
  5742. if (left < 0) {
  5743. return -1;
  5744. } /* over-subscribed */
  5745. }
  5746. if (left > 0 && (type === $$inftrees$$CODES || max !== 1)) {
  5747. return -1; /* incomplete set */
  5748. }
  5749.  
  5750. /* generate offsets into symbol table for each length for sorting */
  5751. offs[1] = 0;
  5752. for (len = 1; len < $$inftrees$$MAXBITS; len++) {
  5753. offs[len + 1] = offs[len] + count[len];
  5754. }
  5755.  
  5756. /* sort symbols by length, by symbol order within each length */
  5757. for (sym = 0; sym < codes; sym++) {
  5758. if (lens[lens_index + sym] !== 0) {
  5759. work[offs[lens[lens_index + sym]]++] = sym;
  5760. }
  5761. }
  5762.  
  5763. /*
  5764. Create and fill in decoding tables. In this loop, the table being
  5765. filled is at next and has curr index bits. The code being used is huff
  5766. with length len. That code is converted to an index by dropping drop
  5767. bits off of the bottom. For codes where len is less than drop + curr,
  5768. those top drop + curr - len bits are incremented through all values to
  5769. fill the table with replicated entries.
  5770.  
  5771. root is the number of index bits for the root table. When len exceeds
  5772. root, sub-tables are created pointed to by the root entry with an index
  5773. of the low root bits of huff. This is saved in low to check for when a
  5774. new sub-table should be started. drop is zero when the root table is
  5775. being filled, and drop is root when sub-tables are being filled.
  5776.  
  5777. When a new sub-table is needed, it is necessary to look ahead in the
  5778. code lengths to determine what size sub-table is needed. The length
  5779. counts are used for this, and so count[] is decremented as codes are
  5780. entered in the tables.
  5781.  
  5782. used keeps track of how many table entries have been allocated from the
  5783. provided *table space. It is checked for LENS and DIST tables against
  5784. the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
  5785. the initial root table size constants. See the comments in inftrees.h
  5786. for more information.
  5787.  
  5788. sym increments through all symbols, and the loop terminates when
  5789. all codes of length max, i.e. all codes, have been processed. This
  5790. routine permits incomplete codes, so another loop after this one fills
  5791. in the rest of the decoding tables with invalid code markers.
  5792. */
  5793.  
  5794. /* set up for code type */
  5795. // poor man optimization - use if-else instead of switch,
  5796. // to avoid deopts in old v8
  5797. if (type === $$inftrees$$CODES) {
  5798. base = extra = work; /* dummy value--not used */
  5799. end = 19;
  5800.  
  5801. } else if (type === $$inftrees$$LENS) {
  5802. base = $$inftrees$$lbase;
  5803. base_index -= 257;
  5804. extra = $$inftrees$$lext;
  5805. extra_index -= 257;
  5806. end = 256;
  5807.  
  5808. } else { /* DISTS */
  5809. base = $$inftrees$$dbase;
  5810. extra = $$inftrees$$dext;
  5811. end = -1;
  5812. }
  5813.  
  5814. /* initialize opts for loop */
  5815. huff = 0; /* starting code */
  5816. sym = 0; /* starting code symbol */
  5817. len = min; /* starting code length */
  5818. next = table_index; /* current table to fill in */
  5819. curr = root; /* current table index bits */
  5820. drop = 0; /* current bits to drop from code for index */
  5821. low = -1; /* trigger new sub-table when len > root */
  5822. used = 1 << root; /* use root table entries */
  5823. mask = used - 1; /* mask for comparing low */
  5824.  
  5825. /* check available table space */
  5826. if ((type === $$inftrees$$LENS && used > $$inftrees$$ENOUGH_LENS) ||
  5827. (type === $$inftrees$$DISTS && used > $$inftrees$$ENOUGH_DISTS)) {
  5828. return 1;
  5829. }
  5830.  
  5831. /* process all codes and make table entries */
  5832. for (;;) {
  5833. /* create table entry */
  5834. here_bits = len - drop;
  5835. if (work[sym] < end) {
  5836. here_op = 0;
  5837. here_val = work[sym];
  5838. }
  5839. else if (work[sym] > end) {
  5840. here_op = extra[extra_index + work[sym]];
  5841. here_val = base[base_index + work[sym]];
  5842. }
  5843. else {
  5844. here_op = 32 + 64; /* end of block */
  5845. here_val = 0;
  5846. }
  5847.  
  5848. /* replicate for those indices with low len bits equal to huff */
  5849. incr = 1 << (len - drop);
  5850. fill = 1 << curr;
  5851. min = fill; /* save offset to next table */
  5852. do {
  5853. fill -= incr;
  5854. table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
  5855. } while (fill !== 0);
  5856.  
  5857. /* backwards increment the len-bit code huff */
  5858. incr = 1 << (len - 1);
  5859. while (huff & incr) {
  5860. incr >>= 1;
  5861. }
  5862. if (incr !== 0) {
  5863. huff &= incr - 1;
  5864. huff += incr;
  5865. } else {
  5866. huff = 0;
  5867. }
  5868.  
  5869. /* go to next symbol, update count, len */
  5870. sym++;
  5871. if (--count[len] === 0) {
  5872. if (len === max) { break; }
  5873. len = lens[lens_index + work[sym]];
  5874. }
  5875.  
  5876. /* create new sub-table if needed */
  5877. if (len > root && (huff & mask) !== low) {
  5878. /* if first time, transition to sub-tables */
  5879. if (drop === 0) {
  5880. drop = root;
  5881. }
  5882.  
  5883. /* increment past last table */
  5884. next += min; /* here min is 1 << curr */
  5885.  
  5886. /* determine length of next table */
  5887. curr = len - drop;
  5888. left = 1 << curr;
  5889. while (curr + drop < max) {
  5890. left -= count[curr + drop];
  5891. if (left <= 0) { break; }
  5892. curr++;
  5893. left <<= 1;
  5894. }
  5895.  
  5896. /* check for enough space */
  5897. used += 1 << curr;
  5898. if ((type === $$inftrees$$LENS && used > $$inftrees$$ENOUGH_LENS) ||
  5899. (type === $$inftrees$$DISTS && used > $$inftrees$$ENOUGH_DISTS)) {
  5900. return 1;
  5901. }
  5902.  
  5903. /* point entry in root table to sub-table */
  5904. low = huff & mask;
  5905. /*table.op[low] = curr;
  5906. table.bits[low] = root;
  5907. table.val[low] = next - opts.table_index;*/
  5908. table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
  5909. }
  5910. }
  5911.  
  5912. /* fill in remaining table entry if code is incomplete (guaranteed to have
  5913. at most one remaining entry, since if the code is incomplete, the
  5914. maximum code length that was allowed to get this far is one bit) */
  5915. if (huff !== 0) {
  5916. //table.op[next + huff] = 64; /* invalid code marker */
  5917. //table.bits[next + huff] = len - drop;
  5918. //table.val[next + huff] = 0;
  5919. table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
  5920. }
  5921.  
  5922. /* set return parameters */
  5923. //opts.table_index += used;
  5924. opts.bits = root;
  5925. return 0;
  5926. }
  5927.  
  5928. var $$inftrees$$default = $$inftrees$$inflate_table;
  5929.  
  5930. var $$$vendor$pako$lib$zlib$inflate$$CODES = 0;
  5931. var $$$vendor$pako$lib$zlib$inflate$$LENS = 1;
  5932. var $$$vendor$pako$lib$zlib$inflate$$DISTS = 2;
  5933.  
  5934. /* Public constants ==========================================================*/
  5935. /* ===========================================================================*/
  5936.  
  5937.  
  5938. /* Allowed flush values; see deflate() and inflate() below for details */
  5939. //var Z_NO_FLUSH = 0;
  5940. //var Z_PARTIAL_FLUSH = 1;
  5941. //var Z_SYNC_FLUSH = 2;
  5942. //var Z_FULL_FLUSH = 3;
  5943. var $$$vendor$pako$lib$zlib$inflate$$Z_FINISH = 4;
  5944. var $$$vendor$pako$lib$zlib$inflate$$Z_BLOCK = 5;
  5945. var $$$vendor$pako$lib$zlib$inflate$$Z_TREES = 6;
  5946.  
  5947.  
  5948. /* Return codes for the compression/decompression functions. Negative values
  5949. * are errors, positive values are used for special but normal events.
  5950. */
  5951. var $$$vendor$pako$lib$zlib$inflate$$Z_OK = 0;
  5952. var $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_END = 1;
  5953. var $$$vendor$pako$lib$zlib$inflate$$Z_NEED_DICT = 2;
  5954. //var Z_ERRNO = -1;
  5955. var $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR = -2;
  5956. var $$$vendor$pako$lib$zlib$inflate$$Z_DATA_ERROR = -3;
  5957. var $$$vendor$pako$lib$zlib$inflate$$Z_MEM_ERROR = -4;
  5958. var $$$vendor$pako$lib$zlib$inflate$$Z_BUF_ERROR = -5;
  5959. //var Z_VERSION_ERROR = -6;
  5960.  
  5961. /* The deflate compression method */
  5962. var $$$vendor$pako$lib$zlib$inflate$$Z_DEFLATED = 8;
  5963.  
  5964.  
  5965. /* STATES ====================================================================*/
  5966. /* ===========================================================================*/
  5967.  
  5968.  
  5969. var $$$vendor$pako$lib$zlib$inflate$$HEAD = 1;/* i: waiting for magic header */
  5970. var $$$vendor$pako$lib$zlib$inflate$$FLAGS = 2;/* i: waiting for method and flags (gzip) */
  5971. var $$$vendor$pako$lib$zlib$inflate$$TIME = 3;/* i: waiting for modification time (gzip) */
  5972. var $$$vendor$pako$lib$zlib$inflate$$OS = 4;/* i: waiting for extra flags and operating system (gzip) */
  5973. var $$$vendor$pako$lib$zlib$inflate$$EXLEN = 5;/* i: waiting for extra length (gzip) */
  5974. var $$$vendor$pako$lib$zlib$inflate$$EXTRA = 6;/* i: waiting for extra bytes (gzip) */
  5975. var $$$vendor$pako$lib$zlib$inflate$$NAME = 7;/* i: waiting for end of file name (gzip) */
  5976. var $$$vendor$pako$lib$zlib$inflate$$COMMENT = 8;/* i: waiting for end of comment (gzip) */
  5977. var $$$vendor$pako$lib$zlib$inflate$$HCRC = 9;/* i: waiting for header crc (gzip) */
  5978. var $$$vendor$pako$lib$zlib$inflate$$DICTID = 10;/* i: waiting for dictionary check value */
  5979. var $$$vendor$pako$lib$zlib$inflate$$DICT = 11;/* waiting for inflateSetDictionary() call */
  5980. var $$$vendor$pako$lib$zlib$inflate$$TYPE = 12;/* i: waiting for type bits, including last-flag bit */
  5981. var $$$vendor$pako$lib$zlib$inflate$$TYPEDO = 13;/* i: same, but skip check to exit inflate on new block */
  5982. var $$$vendor$pako$lib$zlib$inflate$$STORED = 14;/* i: waiting for stored size (length and complement) */
  5983. var $$$vendor$pako$lib$zlib$inflate$$COPY_ = 15;/* i/o: same as COPY below, but only first time in */
  5984. var $$$vendor$pako$lib$zlib$inflate$$COPY = 16;/* i/o: waiting for input or output to copy stored block */
  5985. var $$$vendor$pako$lib$zlib$inflate$$TABLE = 17;/* i: waiting for dynamic block table lengths */
  5986. var $$$vendor$pako$lib$zlib$inflate$$LENLENS = 18;/* i: waiting for code length code lengths */
  5987. var $$$vendor$pako$lib$zlib$inflate$$CODELENS = 19;/* i: waiting for length/lit and distance code lengths */
  5988. var $$$vendor$pako$lib$zlib$inflate$$LEN_ = 20;/* i: same as LEN below, but only first time in */
  5989. var $$$vendor$pako$lib$zlib$inflate$$LEN = 21;/* i: waiting for length/lit/eob code */
  5990. var $$$vendor$pako$lib$zlib$inflate$$LENEXT = 22;/* i: waiting for length extra bits */
  5991. var $$$vendor$pako$lib$zlib$inflate$$DIST = 23;/* i: waiting for distance code */
  5992. var $$$vendor$pako$lib$zlib$inflate$$DISTEXT = 24;/* i: waiting for distance extra bits */
  5993. var $$$vendor$pako$lib$zlib$inflate$$MATCH = 25;/* o: waiting for output space to copy string */
  5994. var $$$vendor$pako$lib$zlib$inflate$$LIT = 26;/* o: waiting for output space to write literal */
  5995. var $$$vendor$pako$lib$zlib$inflate$$CHECK = 27;/* i: waiting for 32-bit check value */
  5996. var $$$vendor$pako$lib$zlib$inflate$$LENGTH = 28;/* i: waiting for 32-bit length (gzip) */
  5997. var $$$vendor$pako$lib$zlib$inflate$$DONE = 29;/* finished check, done -- remain here until reset */
  5998. var $$$vendor$pako$lib$zlib$inflate$$BAD = 30;/* got a data error -- remain here until reset */
  5999. var $$$vendor$pako$lib$zlib$inflate$$MEM = 31;/* got an inflate() memory error -- remain here until reset */
  6000. var $$$vendor$pako$lib$zlib$inflate$$SYNC = 32;/* looking for synchronization bytes to restart inflate() */
  6001.  
  6002. /* ===========================================================================*/
  6003.  
  6004.  
  6005.  
  6006. var $$$vendor$pako$lib$zlib$inflate$$ENOUGH_LENS = 852;
  6007. var $$$vendor$pako$lib$zlib$inflate$$ENOUGH_DISTS = 592;
  6008. //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
  6009.  
  6010. var $$$vendor$pako$lib$zlib$inflate$$MAX_WBITS = 15;
  6011. /* 32K LZ77 window */
  6012. var $$$vendor$pako$lib$zlib$inflate$$DEF_WBITS = $$$vendor$pako$lib$zlib$inflate$$MAX_WBITS;
  6013.  
  6014.  
  6015. function $$$vendor$pako$lib$zlib$inflate$$zswap32(q) {
  6016. return (((q >>> 24) & 0xff) +
  6017. ((q >>> 8) & 0xff00) +
  6018. ((q & 0xff00) << 8) +
  6019. ((q & 0xff) << 24));
  6020. }
  6021.  
  6022.  
  6023. function $$$vendor$pako$lib$zlib$inflate$$InflateState() {
  6024. this.mode = 0; /* current inflate mode */
  6025. this.last = false; /* true if processing last block */
  6026. this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
  6027. this.havedict = false; /* true if dictionary provided */
  6028. this.flags = 0; /* gzip header method and flags (0 if zlib) */
  6029. this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
  6030. this.check = 0; /* protected copy of check value */
  6031. this.total = 0; /* protected copy of output count */
  6032. // TODO: may be {}
  6033. this.head = null; /* where to save gzip header information */
  6034.  
  6035. /* sliding window */
  6036. this.wbits = 0; /* log base 2 of requested window size */
  6037. this.wsize = 0; /* window size or zero if not using window */
  6038. this.whave = 0; /* valid bytes in the window */
  6039. this.wnext = 0; /* window write index */
  6040. this.window = null; /* allocated sliding window, if needed */
  6041.  
  6042. /* bit accumulator */
  6043. this.hold = 0; /* input bit accumulator */
  6044. this.bits = 0; /* number of bits in "in" */
  6045.  
  6046. /* for string and stored block copying */
  6047. this.length = 0; /* literal or length of data to copy */
  6048. this.offset = 0; /* distance back to copy string from */
  6049.  
  6050. /* for table and code decoding */
  6051. this.extra = 0; /* extra bits needed */
  6052.  
  6053. /* fixed and dynamic code tables */
  6054. this.lencode = null; /* starting table for length/literal codes */
  6055. this.distcode = null; /* starting table for distance codes */
  6056. this.lenbits = 0; /* index bits for lencode */
  6057. this.distbits = 0; /* index bits for distcode */
  6058.  
  6059. /* dynamic table building */
  6060. this.ncode = 0; /* number of code length code lengths */
  6061. this.nlen = 0; /* number of length code lengths */
  6062. this.ndist = 0; /* number of distance code lengths */
  6063. this.have = 0; /* number of code lengths in lens[] */
  6064. this.next = null; /* next available space in codes[] */
  6065.  
  6066. this.lens = new $$$utils$common$$.Buf16(320); /* temporary storage for code lengths */
  6067. this.work = new $$$utils$common$$.Buf16(288); /* work area for code table building */
  6068.  
  6069. /*
  6070. because we don't have pointers in js, we use lencode and distcode directly
  6071. as buffers so we don't need codes
  6072. */
  6073. //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */
  6074. this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */
  6075. this.distdyn = null; /* dynamic table for distance codes (JS specific) */
  6076. this.sane = 0; /* if false, allow invalid distance too far */
  6077. this.back = 0; /* bits back of last unprocessed length/lit */
  6078. this.was = 0; /* initial length of match */
  6079. }
  6080.  
  6081. function $$$vendor$pako$lib$zlib$inflate$$inflateResetKeep(strm) {
  6082. var state;
  6083.  
  6084. if (!strm || !strm.state) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  6085. state = strm.state;
  6086. strm.total_in = strm.total_out = state.total = 0;
  6087. strm.msg = ''; /*Z_NULL*/
  6088. if (state.wrap) { /* to support ill-conceived Java test suite */
  6089. strm.adler = state.wrap & 1;
  6090. }
  6091. state.mode = $$$vendor$pako$lib$zlib$inflate$$HEAD;
  6092. state.last = 0;
  6093. state.havedict = 0;
  6094. state.dmax = 32768;
  6095. state.head = null/*Z_NULL*/;
  6096. state.hold = 0;
  6097. state.bits = 0;
  6098. //state.lencode = state.distcode = state.next = state.codes;
  6099. state.lencode = state.lendyn = new $$$utils$common$$.Buf32($$$vendor$pako$lib$zlib$inflate$$ENOUGH_LENS);
  6100. state.distcode = state.distdyn = new $$$utils$common$$.Buf32($$$vendor$pako$lib$zlib$inflate$$ENOUGH_DISTS);
  6101.  
  6102. state.sane = 1;
  6103. state.back = -1;
  6104. //Tracev((stderr, "inflate: reset\n"));
  6105. return $$$vendor$pako$lib$zlib$inflate$$Z_OK;
  6106. }
  6107.  
  6108. function $$$vendor$pako$lib$zlib$inflate$$inflateReset(strm) {
  6109. var state;
  6110.  
  6111. if (!strm || !strm.state) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  6112. state = strm.state;
  6113. state.wsize = 0;
  6114. state.whave = 0;
  6115. state.wnext = 0;
  6116. return $$$vendor$pako$lib$zlib$inflate$$inflateResetKeep(strm);
  6117.  
  6118. }
  6119.  
  6120. function $$$vendor$pako$lib$zlib$inflate$$inflateReset2(strm, windowBits) {
  6121. var wrap;
  6122. var state;
  6123.  
  6124. /* get the state */
  6125. if (!strm || !strm.state) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  6126. state = strm.state;
  6127.  
  6128. /* extract wrap request from windowBits parameter */
  6129. if (windowBits < 0) {
  6130. wrap = 0;
  6131. windowBits = -windowBits;
  6132. }
  6133. else {
  6134. wrap = (windowBits >> 4) + 1;
  6135. if (windowBits < 48) {
  6136. windowBits &= 15;
  6137. }
  6138. }
  6139.  
  6140. /* set number of window bits, free window if different */
  6141. if (windowBits && (windowBits < 8 || windowBits > 15)) {
  6142. return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR;
  6143. }
  6144. if (state.window !== null && state.wbits !== windowBits) {
  6145. state.window = null;
  6146. }
  6147.  
  6148. /* update state and reset the rest of it */
  6149. state.wrap = wrap;
  6150. state.wbits = windowBits;
  6151. return $$$vendor$pako$lib$zlib$inflate$$inflateReset(strm);
  6152. }
  6153.  
  6154. function $$$vendor$pako$lib$zlib$inflate$$inflateInit2(strm, windowBits) {
  6155. var ret;
  6156. var state;
  6157.  
  6158. if (!strm) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  6159. //strm.msg = Z_NULL; /* in case we return an error */
  6160.  
  6161. state = new $$$vendor$pako$lib$zlib$inflate$$InflateState();
  6162.  
  6163. //if (state === Z_NULL) return Z_MEM_ERROR;
  6164. //Tracev((stderr, "inflate: allocated\n"));
  6165. strm.state = state;
  6166. state.window = null/*Z_NULL*/;
  6167. ret = $$$vendor$pako$lib$zlib$inflate$$inflateReset2(strm, windowBits);
  6168. if (ret !== $$$vendor$pako$lib$zlib$inflate$$Z_OK) {
  6169. strm.state = null/*Z_NULL*/;
  6170. }
  6171. return ret;
  6172. }
  6173.  
  6174. function $$$vendor$pako$lib$zlib$inflate$$inflateInit(strm) {
  6175. return $$$vendor$pako$lib$zlib$inflate$$inflateInit2(strm, $$$vendor$pako$lib$zlib$inflate$$DEF_WBITS);
  6176. }
  6177.  
  6178.  
  6179. /*
  6180. Return state with length and distance decoding tables and index sizes set to
  6181. fixed code decoding. Normally this returns fixed tables from inffixed.h.
  6182. If BUILDFIXED is defined, then instead this routine builds the tables the
  6183. first time it's called, and returns those tables the first time and
  6184. thereafter. This reduces the size of the code by about 2K bytes, in
  6185. exchange for a little execution time. However, BUILDFIXED should not be
  6186. used for threaded applications, since the rewriting of the tables and virgin
  6187. may not be thread-safe.
  6188. */
  6189. var $$$vendor$pako$lib$zlib$inflate$$virgin = true;
  6190.  
  6191. var $$$vendor$pako$lib$zlib$inflate$$lenfix, $$$vendor$pako$lib$zlib$inflate$$distfix; // We have no pointers in JS, so keep tables separate
  6192.  
  6193. function $$$vendor$pako$lib$zlib$inflate$$fixedtables(state) {
  6194. /* build fixed huffman tables if first call (may not be thread safe) */
  6195. if ($$$vendor$pako$lib$zlib$inflate$$virgin) {
  6196. var sym;
  6197.  
  6198. $$$vendor$pako$lib$zlib$inflate$$lenfix = new $$$utils$common$$.Buf32(512);
  6199. $$$vendor$pako$lib$zlib$inflate$$distfix = new $$$utils$common$$.Buf32(32);
  6200.  
  6201. /* literal/length table */
  6202. sym = 0;
  6203. while (sym < 144) { state.lens[sym++] = 8; }
  6204. while (sym < 256) { state.lens[sym++] = 9; }
  6205. while (sym < 280) { state.lens[sym++] = 7; }
  6206. while (sym < 288) { state.lens[sym++] = 8; }
  6207.  
  6208. $$inftrees$$default($$$vendor$pako$lib$zlib$inflate$$LENS, state.lens, 0, 288, $$$vendor$pako$lib$zlib$inflate$$lenfix, 0, state.work, { bits: 9 });
  6209.  
  6210. /* distance table */
  6211. sym = 0;
  6212. while (sym < 32) { state.lens[sym++] = 5; }
  6213.  
  6214. $$inftrees$$default($$$vendor$pako$lib$zlib$inflate$$DISTS, state.lens, 0, 32, $$$vendor$pako$lib$zlib$inflate$$distfix, 0, state.work, { bits: 5 });
  6215.  
  6216. /* do this just once */
  6217. $$$vendor$pako$lib$zlib$inflate$$virgin = false;
  6218. }
  6219.  
  6220. state.lencode = $$$vendor$pako$lib$zlib$inflate$$lenfix;
  6221. state.lenbits = 9;
  6222. state.distcode = $$$vendor$pako$lib$zlib$inflate$$distfix;
  6223. state.distbits = 5;
  6224. }
  6225.  
  6226.  
  6227. /*
  6228. Update the window with the last wsize (normally 32K) bytes written before
  6229. returning. If window does not exist yet, create it. This is only called
  6230. when a window is already in use, or when output has been written during this
  6231. inflate call, but the end of the deflate stream has not been reached yet.
  6232. It is also called to create a window for dictionary data when a dictionary
  6233. is loaded.
  6234.  
  6235. Providing output buffers larger than 32K to inflate() should provide a speed
  6236. advantage, since only the last 32K of output is copied to the sliding window
  6237. upon return from inflate(), and since all distances after the first 32K of
  6238. output will fall in the output data, making match copies simpler and faster.
  6239. The advantage may be dependent on the size of the processor's data caches.
  6240. */
  6241. function $$$vendor$pako$lib$zlib$inflate$$updatewindow(strm, src, end, copy) {
  6242. var dist;
  6243. var state = strm.state;
  6244.  
  6245. /* if it hasn't been done already, allocate space for the window */
  6246. if (state.window === null) {
  6247. state.wsize = 1 << state.wbits;
  6248. state.wnext = 0;
  6249. state.whave = 0;
  6250.  
  6251. state.window = new $$$utils$common$$.Buf8(state.wsize);
  6252. }
  6253.  
  6254. /* copy state->wsize or less output bytes into the circular window */
  6255. if (copy >= state.wsize) {
  6256. $$$utils$common$$.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
  6257. state.wnext = 0;
  6258. state.whave = state.wsize;
  6259. }
  6260. else {
  6261. dist = state.wsize - state.wnext;
  6262. if (dist > copy) {
  6263. dist = copy;
  6264. }
  6265. //zmemcpy(state->window + state->wnext, end - copy, dist);
  6266. $$$utils$common$$.arraySet(state.window, src, end - copy, dist, state.wnext);
  6267. copy -= dist;
  6268. if (copy) {
  6269. //zmemcpy(state->window, end - copy, copy);
  6270. $$$utils$common$$.arraySet(state.window, src, end - copy, copy, 0);
  6271. state.wnext = copy;
  6272. state.whave = state.wsize;
  6273. }
  6274. else {
  6275. state.wnext += dist;
  6276. if (state.wnext === state.wsize) { state.wnext = 0; }
  6277. if (state.whave < state.wsize) { state.whave += dist; }
  6278. }
  6279. }
  6280. return 0;
  6281. }
  6282.  
  6283. function $$$vendor$pako$lib$zlib$inflate$$inflate(strm, flush) {
  6284. var state;
  6285. var input, output; // input/output buffers
  6286. var next; /* next input INDEX */
  6287. var put; /* next output INDEX */
  6288. var have, left; /* available input and output */
  6289. var hold; /* bit buffer */
  6290. var bits; /* bits in bit buffer */
  6291. var _in, _out; /* save starting available input and output */
  6292. var copy; /* number of stored or match bytes to copy */
  6293. var from; /* where to copy match bytes from */
  6294. var from_source;
  6295. var here = 0; /* current decoding table entry */
  6296. var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
  6297. //var last; /* parent table entry */
  6298. var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
  6299. var len; /* length to copy for repeats, bits to drop */
  6300. var ret; /* return code */
  6301. var hbuf = new $$$utils$common$$.Buf8(4); /* buffer for gzip header crc calculation */
  6302. var opts;
  6303.  
  6304. var n; // temporary var for NEED_BITS
  6305.  
  6306. var order = /* permutation of code lengths */
  6307. [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
  6308.  
  6309.  
  6310. if (!strm || !strm.state || !strm.output ||
  6311. (!strm.input && strm.avail_in !== 0)) {
  6312. return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR;
  6313. }
  6314.  
  6315. state = strm.state;
  6316. if (state.mode === $$$vendor$pako$lib$zlib$inflate$$TYPE) { state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPEDO; } /* skip check */
  6317.  
  6318.  
  6319. //--- LOAD() ---
  6320. put = strm.next_out;
  6321. output = strm.output;
  6322. left = strm.avail_out;
  6323. next = strm.next_in;
  6324. input = strm.input;
  6325. have = strm.avail_in;
  6326. hold = state.hold;
  6327. bits = state.bits;
  6328. //---
  6329.  
  6330. _in = have;
  6331. _out = left;
  6332. ret = $$$vendor$pako$lib$zlib$inflate$$Z_OK;
  6333.  
  6334. inf_leave: // goto emulation
  6335. for (;;) {
  6336. switch (state.mode) {
  6337. case $$$vendor$pako$lib$zlib$inflate$$HEAD:
  6338. if (state.wrap === 0) {
  6339. state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPEDO;
  6340. break;
  6341. }
  6342. //=== NEEDBITS(16);
  6343. while (bits < 16) {
  6344. if (have === 0) { break inf_leave; }
  6345. have--;
  6346. hold += input[next++] << bits;
  6347. bits += 8;
  6348. }
  6349. //===//
  6350. if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */
  6351. state.check = 0/*crc32(0L, Z_NULL, 0)*/;
  6352. //=== CRC2(state.check, hold);
  6353. hbuf[0] = hold & 0xff;
  6354. hbuf[1] = (hold >>> 8) & 0xff;
  6355. state.check = $$crc32$$default(state.check, hbuf, 2, 0);
  6356. //===//
  6357.  
  6358. //=== INITBITS();
  6359. hold = 0;
  6360. bits = 0;
  6361. //===//
  6362. state.mode = $$$vendor$pako$lib$zlib$inflate$$FLAGS;
  6363. break;
  6364. }
  6365. state.flags = 0; /* expect zlib header */
  6366. if (state.head) {
  6367. state.head.done = false;
  6368. }
  6369. if (!(state.wrap & 1) || /* check if zlib header allowed */
  6370. (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
  6371. strm.msg = 'incorrect header check';
  6372. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6373. break;
  6374. }
  6375. if ((hold & 0x0f)/*BITS(4)*/ !== $$$vendor$pako$lib$zlib$inflate$$Z_DEFLATED) {
  6376. strm.msg = 'unknown compression method';
  6377. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6378. break;
  6379. }
  6380. //--- DROPBITS(4) ---//
  6381. hold >>>= 4;
  6382. bits -= 4;
  6383. //---//
  6384. len = (hold & 0x0f)/*BITS(4)*/ + 8;
  6385. if (state.wbits === 0) {
  6386. state.wbits = len;
  6387. }
  6388. else if (len > state.wbits) {
  6389. strm.msg = 'invalid window size';
  6390. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6391. break;
  6392. }
  6393. state.dmax = 1 << len;
  6394. //Tracev((stderr, "inflate: zlib header ok\n"));
  6395. strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
  6396. state.mode = hold & 0x200 ? $$$vendor$pako$lib$zlib$inflate$$DICTID : $$$vendor$pako$lib$zlib$inflate$$TYPE;
  6397. //=== INITBITS();
  6398. hold = 0;
  6399. bits = 0;
  6400. //===//
  6401. break;
  6402. case $$$vendor$pako$lib$zlib$inflate$$FLAGS:
  6403. //=== NEEDBITS(16); */
  6404. while (bits < 16) {
  6405. if (have === 0) { break inf_leave; }
  6406. have--;
  6407. hold += input[next++] << bits;
  6408. bits += 8;
  6409. }
  6410. //===//
  6411. state.flags = hold;
  6412. if ((state.flags & 0xff) !== $$$vendor$pako$lib$zlib$inflate$$Z_DEFLATED) {
  6413. strm.msg = 'unknown compression method';
  6414. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6415. break;
  6416. }
  6417. if (state.flags & 0xe000) {
  6418. strm.msg = 'unknown header flags set';
  6419. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6420. break;
  6421. }
  6422. if (state.head) {
  6423. state.head.text = ((hold >> 8) & 1);
  6424. }
  6425. if (state.flags & 0x0200) {
  6426. //=== CRC2(state.check, hold);
  6427. hbuf[0] = hold & 0xff;
  6428. hbuf[1] = (hold >>> 8) & 0xff;
  6429. state.check = $$crc32$$default(state.check, hbuf, 2, 0);
  6430. //===//
  6431. }
  6432. //=== INITBITS();
  6433. hold = 0;
  6434. bits = 0;
  6435. //===//
  6436. state.mode = $$$vendor$pako$lib$zlib$inflate$$TIME;
  6437. /* falls through */
  6438. case $$$vendor$pako$lib$zlib$inflate$$TIME:
  6439. //=== NEEDBITS(32); */
  6440. while (bits < 32) {
  6441. if (have === 0) { break inf_leave; }
  6442. have--;
  6443. hold += input[next++] << bits;
  6444. bits += 8;
  6445. }
  6446. //===//
  6447. if (state.head) {
  6448. state.head.time = hold;
  6449. }
  6450. if (state.flags & 0x0200) {
  6451. //=== CRC4(state.check, hold)
  6452. hbuf[0] = hold & 0xff;
  6453. hbuf[1] = (hold >>> 8) & 0xff;
  6454. hbuf[2] = (hold >>> 16) & 0xff;
  6455. hbuf[3] = (hold >>> 24) & 0xff;
  6456. state.check = $$crc32$$default(state.check, hbuf, 4, 0);
  6457. //===
  6458. }
  6459. //=== INITBITS();
  6460. hold = 0;
  6461. bits = 0;
  6462. //===//
  6463. state.mode = $$$vendor$pako$lib$zlib$inflate$$OS;
  6464. /* falls through */
  6465. case $$$vendor$pako$lib$zlib$inflate$$OS:
  6466. //=== NEEDBITS(16); */
  6467. while (bits < 16) {
  6468. if (have === 0) { break inf_leave; }
  6469. have--;
  6470. hold += input[next++] << bits;
  6471. bits += 8;
  6472. }
  6473. //===//
  6474. if (state.head) {
  6475. state.head.xflags = (hold & 0xff);
  6476. state.head.os = (hold >> 8);
  6477. }
  6478. if (state.flags & 0x0200) {
  6479. //=== CRC2(state.check, hold);
  6480. hbuf[0] = hold & 0xff;
  6481. hbuf[1] = (hold >>> 8) & 0xff;
  6482. state.check = $$crc32$$default(state.check, hbuf, 2, 0);
  6483. //===//
  6484. }
  6485. //=== INITBITS();
  6486. hold = 0;
  6487. bits = 0;
  6488. //===//
  6489. state.mode = $$$vendor$pako$lib$zlib$inflate$$EXLEN;
  6490. /* falls through */
  6491. case $$$vendor$pako$lib$zlib$inflate$$EXLEN:
  6492. if (state.flags & 0x0400) {
  6493. //=== NEEDBITS(16); */
  6494. while (bits < 16) {
  6495. if (have === 0) { break inf_leave; }
  6496. have--;
  6497. hold += input[next++] << bits;
  6498. bits += 8;
  6499. }
  6500. //===//
  6501. state.length = hold;
  6502. if (state.head) {
  6503. state.head.extra_len = hold;
  6504. }
  6505. if (state.flags & 0x0200) {
  6506. //=== CRC2(state.check, hold);
  6507. hbuf[0] = hold & 0xff;
  6508. hbuf[1] = (hold >>> 8) & 0xff;
  6509. state.check = $$crc32$$default(state.check, hbuf, 2, 0);
  6510. //===//
  6511. }
  6512. //=== INITBITS();
  6513. hold = 0;
  6514. bits = 0;
  6515. //===//
  6516. }
  6517. else if (state.head) {
  6518. state.head.extra = null/*Z_NULL*/;
  6519. }
  6520. state.mode = $$$vendor$pako$lib$zlib$inflate$$EXTRA;
  6521. /* falls through */
  6522. case $$$vendor$pako$lib$zlib$inflate$$EXTRA:
  6523. if (state.flags & 0x0400) {
  6524. copy = state.length;
  6525. if (copy > have) { copy = have; }
  6526. if (copy) {
  6527. if (state.head) {
  6528. len = state.head.extra_len - state.length;
  6529. if (!state.head.extra) {
  6530. // Use untyped array for more conveniend processing later
  6531. state.head.extra = new Array(state.head.extra_len);
  6532. }
  6533. $$$utils$common$$.arraySet(
  6534. state.head.extra,
  6535. input,
  6536. next,
  6537. // extra field is limited to 65536 bytes
  6538. // - no need for additional size check
  6539. copy,
  6540. /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
  6541. len
  6542. );
  6543. //zmemcpy(state.head.extra + len, next,
  6544. // len + copy > state.head.extra_max ?
  6545. // state.head.extra_max - len : copy);
  6546. }
  6547. if (state.flags & 0x0200) {
  6548. state.check = $$crc32$$default(state.check, input, copy, next);
  6549. }
  6550. have -= copy;
  6551. next += copy;
  6552. state.length -= copy;
  6553. }
  6554. if (state.length) { break inf_leave; }
  6555. }
  6556. state.length = 0;
  6557. state.mode = $$$vendor$pako$lib$zlib$inflate$$NAME;
  6558. /* falls through */
  6559. case $$$vendor$pako$lib$zlib$inflate$$NAME:
  6560. if (state.flags & 0x0800) {
  6561. if (have === 0) { break inf_leave; }
  6562. copy = 0;
  6563. do {
  6564. // TODO: 2 or 1 bytes?
  6565. len = input[next + copy++];
  6566. /* use constant limit because in js we should not preallocate memory */
  6567. if (state.head && len &&
  6568. (state.length < 65536 /*state.head.name_max*/)) {
  6569. state.head.name += String.fromCharCode(len);
  6570. }
  6571. } while (len && copy < have);
  6572.  
  6573. if (state.flags & 0x0200) {
  6574. state.check = $$crc32$$default(state.check, input, copy, next);
  6575. }
  6576. have -= copy;
  6577. next += copy;
  6578. if (len) { break inf_leave; }
  6579. }
  6580. else if (state.head) {
  6581. state.head.name = null;
  6582. }
  6583. state.length = 0;
  6584. state.mode = $$$vendor$pako$lib$zlib$inflate$$COMMENT;
  6585. /* falls through */
  6586. case $$$vendor$pako$lib$zlib$inflate$$COMMENT:
  6587. if (state.flags & 0x1000) {
  6588. if (have === 0) { break inf_leave; }
  6589. copy = 0;
  6590. do {
  6591. len = input[next + copy++];
  6592. /* use constant limit because in js we should not preallocate memory */
  6593. if (state.head && len &&
  6594. (state.length < 65536 /*state.head.comm_max*/)) {
  6595. state.head.comment += String.fromCharCode(len);
  6596. }
  6597. } while (len && copy < have);
  6598. if (state.flags & 0x0200) {
  6599. state.check = $$crc32$$default(state.check, input, copy, next);
  6600. }
  6601. have -= copy;
  6602. next += copy;
  6603. if (len) { break inf_leave; }
  6604. }
  6605. else if (state.head) {
  6606. state.head.comment = null;
  6607. }
  6608. state.mode = $$$vendor$pako$lib$zlib$inflate$$HCRC;
  6609. /* falls through */
  6610. case $$$vendor$pako$lib$zlib$inflate$$HCRC:
  6611. if (state.flags & 0x0200) {
  6612. //=== NEEDBITS(16); */
  6613. while (bits < 16) {
  6614. if (have === 0) { break inf_leave; }
  6615. have--;
  6616. hold += input[next++] << bits;
  6617. bits += 8;
  6618. }
  6619. //===//
  6620. if (hold !== (state.check & 0xffff)) {
  6621. strm.msg = 'header crc mismatch';
  6622. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6623. break;
  6624. }
  6625. //=== INITBITS();
  6626. hold = 0;
  6627. bits = 0;
  6628. //===//
  6629. }
  6630. if (state.head) {
  6631. state.head.hcrc = ((state.flags >> 9) & 1);
  6632. state.head.done = true;
  6633. }
  6634. strm.adler = state.check = 0;
  6635. state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPE;
  6636. break;
  6637. case $$$vendor$pako$lib$zlib$inflate$$DICTID:
  6638. //=== NEEDBITS(32); */
  6639. while (bits < 32) {
  6640. if (have === 0) { break inf_leave; }
  6641. have--;
  6642. hold += input[next++] << bits;
  6643. bits += 8;
  6644. }
  6645. //===//
  6646. strm.adler = state.check = $$$vendor$pako$lib$zlib$inflate$$zswap32(hold);
  6647. //=== INITBITS();
  6648. hold = 0;
  6649. bits = 0;
  6650. //===//
  6651. state.mode = $$$vendor$pako$lib$zlib$inflate$$DICT;
  6652. /* falls through */
  6653. case $$$vendor$pako$lib$zlib$inflate$$DICT:
  6654. if (state.havedict === 0) {
  6655. //--- RESTORE() ---
  6656. strm.next_out = put;
  6657. strm.avail_out = left;
  6658. strm.next_in = next;
  6659. strm.avail_in = have;
  6660. state.hold = hold;
  6661. state.bits = bits;
  6662. //---
  6663. return $$$vendor$pako$lib$zlib$inflate$$Z_NEED_DICT;
  6664. }
  6665. strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
  6666. state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPE;
  6667. /* falls through */
  6668. case $$$vendor$pako$lib$zlib$inflate$$TYPE:
  6669. if (flush === $$$vendor$pako$lib$zlib$inflate$$Z_BLOCK || flush === $$$vendor$pako$lib$zlib$inflate$$Z_TREES) { break inf_leave; }
  6670. /* falls through */
  6671. case $$$vendor$pako$lib$zlib$inflate$$TYPEDO:
  6672. if (state.last) {
  6673. //--- BYTEBITS() ---//
  6674. hold >>>= bits & 7;
  6675. bits -= bits & 7;
  6676. //---//
  6677. state.mode = $$$vendor$pako$lib$zlib$inflate$$CHECK;
  6678. break;
  6679. }
  6680. //=== NEEDBITS(3); */
  6681. while (bits < 3) {
  6682. if (have === 0) { break inf_leave; }
  6683. have--;
  6684. hold += input[next++] << bits;
  6685. bits += 8;
  6686. }
  6687. //===//
  6688. state.last = (hold & 0x01)/*BITS(1)*/;
  6689. //--- DROPBITS(1) ---//
  6690. hold >>>= 1;
  6691. bits -= 1;
  6692. //---//
  6693.  
  6694. switch ((hold & 0x03)/*BITS(2)*/) {
  6695. case 0: /* stored block */
  6696. //Tracev((stderr, "inflate: stored block%s\n",
  6697. // state.last ? " (last)" : ""));
  6698. state.mode = $$$vendor$pako$lib$zlib$inflate$$STORED;
  6699. break;
  6700. case 1: /* fixed block */
  6701. $$$vendor$pako$lib$zlib$inflate$$fixedtables(state);
  6702. //Tracev((stderr, "inflate: fixed codes block%s\n",
  6703. // state.last ? " (last)" : ""));
  6704. state.mode = $$$vendor$pako$lib$zlib$inflate$$LEN_; /* decode codes */
  6705. if (flush === $$$vendor$pako$lib$zlib$inflate$$Z_TREES) {
  6706. //--- DROPBITS(2) ---//
  6707. hold >>>= 2;
  6708. bits -= 2;
  6709. //---//
  6710. break inf_leave;
  6711. }
  6712. break;
  6713. case 2: /* dynamic block */
  6714. //Tracev((stderr, "inflate: dynamic codes block%s\n",
  6715. // state.last ? " (last)" : ""));
  6716. state.mode = $$$vendor$pako$lib$zlib$inflate$$TABLE;
  6717. break;
  6718. case 3:
  6719. strm.msg = 'invalid block type';
  6720. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6721. }
  6722. //--- DROPBITS(2) ---//
  6723. hold >>>= 2;
  6724. bits -= 2;
  6725. //---//
  6726. break;
  6727. case $$$vendor$pako$lib$zlib$inflate$$STORED:
  6728. //--- BYTEBITS() ---// /* go to byte boundary */
  6729. hold >>>= bits & 7;
  6730. bits -= bits & 7;
  6731. //---//
  6732. //=== NEEDBITS(32); */
  6733. while (bits < 32) {
  6734. if (have === 0) { break inf_leave; }
  6735. have--;
  6736. hold += input[next++] << bits;
  6737. bits += 8;
  6738. }
  6739. //===//
  6740. if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
  6741. strm.msg = 'invalid stored block lengths';
  6742. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6743. break;
  6744. }
  6745. state.length = hold & 0xffff;
  6746. //Tracev((stderr, "inflate: stored length %u\n",
  6747. // state.length));
  6748. //=== INITBITS();
  6749. hold = 0;
  6750. bits = 0;
  6751. //===//
  6752. state.mode = $$$vendor$pako$lib$zlib$inflate$$COPY_;
  6753. if (flush === $$$vendor$pako$lib$zlib$inflate$$Z_TREES) { break inf_leave; }
  6754. /* falls through */
  6755. case $$$vendor$pako$lib$zlib$inflate$$COPY_:
  6756. state.mode = $$$vendor$pako$lib$zlib$inflate$$COPY;
  6757. /* falls through */
  6758. case $$$vendor$pako$lib$zlib$inflate$$COPY:
  6759. copy = state.length;
  6760. if (copy) {
  6761. if (copy > have) { copy = have; }
  6762. if (copy > left) { copy = left; }
  6763. if (copy === 0) { break inf_leave; }
  6764. //--- zmemcpy(put, next, copy); ---
  6765. $$$utils$common$$.arraySet(output, input, next, copy, put);
  6766. //---//
  6767. have -= copy;
  6768. next += copy;
  6769. left -= copy;
  6770. put += copy;
  6771. state.length -= copy;
  6772. break;
  6773. }
  6774. //Tracev((stderr, "inflate: stored end\n"));
  6775. state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPE;
  6776. break;
  6777. case $$$vendor$pako$lib$zlib$inflate$$TABLE:
  6778. //=== NEEDBITS(14); */
  6779. while (bits < 14) {
  6780. if (have === 0) { break inf_leave; }
  6781. have--;
  6782. hold += input[next++] << bits;
  6783. bits += 8;
  6784. }
  6785. //===//
  6786. state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
  6787. //--- DROPBITS(5) ---//
  6788. hold >>>= 5;
  6789. bits -= 5;
  6790. //---//
  6791. state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
  6792. //--- DROPBITS(5) ---//
  6793. hold >>>= 5;
  6794. bits -= 5;
  6795. //---//
  6796. state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
  6797. //--- DROPBITS(4) ---//
  6798. hold >>>= 4;
  6799. bits -= 4;
  6800. //---//
  6801. //#ifndef PKZIP_BUG_WORKAROUND
  6802. if (state.nlen > 286 || state.ndist > 30) {
  6803. strm.msg = 'too many length or distance symbols';
  6804. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6805. break;
  6806. }
  6807. //#endif
  6808. //Tracev((stderr, "inflate: table sizes ok\n"));
  6809. state.have = 0;
  6810. state.mode = $$$vendor$pako$lib$zlib$inflate$$LENLENS;
  6811. /* falls through */
  6812. case $$$vendor$pako$lib$zlib$inflate$$LENLENS:
  6813. while (state.have < state.ncode) {
  6814. //=== NEEDBITS(3);
  6815. while (bits < 3) {
  6816. if (have === 0) { break inf_leave; }
  6817. have--;
  6818. hold += input[next++] << bits;
  6819. bits += 8;
  6820. }
  6821. //===//
  6822. state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
  6823. //--- DROPBITS(3) ---//
  6824. hold >>>= 3;
  6825. bits -= 3;
  6826. //---//
  6827. }
  6828. while (state.have < 19) {
  6829. state.lens[order[state.have++]] = 0;
  6830. }
  6831. // We have separate tables & no pointers. 2 commented lines below not needed.
  6832. //state.next = state.codes;
  6833. //state.lencode = state.next;
  6834. // Switch to use dynamic table
  6835. state.lencode = state.lendyn;
  6836. state.lenbits = 7;
  6837.  
  6838. opts = { bits: state.lenbits };
  6839. ret = $$inftrees$$default($$$vendor$pako$lib$zlib$inflate$$CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
  6840. state.lenbits = opts.bits;
  6841.  
  6842. if (ret) {
  6843. strm.msg = 'invalid code lengths set';
  6844. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6845. break;
  6846. }
  6847. //Tracev((stderr, "inflate: code lengths ok\n"));
  6848. state.have = 0;
  6849. state.mode = $$$vendor$pako$lib$zlib$inflate$$CODELENS;
  6850. /* falls through */
  6851. case $$$vendor$pako$lib$zlib$inflate$$CODELENS:
  6852. while (state.have < state.nlen + state.ndist) {
  6853. for (;;) {
  6854. here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
  6855. here_bits = here >>> 24;
  6856. here_op = (here >>> 16) & 0xff;
  6857. here_val = here & 0xffff;
  6858.  
  6859. if ((here_bits) <= bits) { break; }
  6860. //--- PULLBYTE() ---//
  6861. if (have === 0) { break inf_leave; }
  6862. have--;
  6863. hold += input[next++] << bits;
  6864. bits += 8;
  6865. //---//
  6866. }
  6867. if (here_val < 16) {
  6868. //--- DROPBITS(here.bits) ---//
  6869. hold >>>= here_bits;
  6870. bits -= here_bits;
  6871. //---//
  6872. state.lens[state.have++] = here_val;
  6873. }
  6874. else {
  6875. if (here_val === 16) {
  6876. //=== NEEDBITS(here.bits + 2);
  6877. n = here_bits + 2;
  6878. while (bits < n) {
  6879. if (have === 0) { break inf_leave; }
  6880. have--;
  6881. hold += input[next++] << bits;
  6882. bits += 8;
  6883. }
  6884. //===//
  6885. //--- DROPBITS(here.bits) ---//
  6886. hold >>>= here_bits;
  6887. bits -= here_bits;
  6888. //---//
  6889. if (state.have === 0) {
  6890. strm.msg = 'invalid bit length repeat';
  6891. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6892. break;
  6893. }
  6894. len = state.lens[state.have - 1];
  6895. copy = 3 + (hold & 0x03);//BITS(2);
  6896. //--- DROPBITS(2) ---//
  6897. hold >>>= 2;
  6898. bits -= 2;
  6899. //---//
  6900. }
  6901. else if (here_val === 17) {
  6902. //=== NEEDBITS(here.bits + 3);
  6903. n = here_bits + 3;
  6904. while (bits < n) {
  6905. if (have === 0) { break inf_leave; }
  6906. have--;
  6907. hold += input[next++] << bits;
  6908. bits += 8;
  6909. }
  6910. //===//
  6911. //--- DROPBITS(here.bits) ---//
  6912. hold >>>= here_bits;
  6913. bits -= here_bits;
  6914. //---//
  6915. len = 0;
  6916. copy = 3 + (hold & 0x07);//BITS(3);
  6917. //--- DROPBITS(3) ---//
  6918. hold >>>= 3;
  6919. bits -= 3;
  6920. //---//
  6921. }
  6922. else {
  6923. //=== NEEDBITS(here.bits + 7);
  6924. n = here_bits + 7;
  6925. while (bits < n) {
  6926. if (have === 0) { break inf_leave; }
  6927. have--;
  6928. hold += input[next++] << bits;
  6929. bits += 8;
  6930. }
  6931. //===//
  6932. //--- DROPBITS(here.bits) ---//
  6933. hold >>>= here_bits;
  6934. bits -= here_bits;
  6935. //---//
  6936. len = 0;
  6937. copy = 11 + (hold & 0x7f);//BITS(7);
  6938. //--- DROPBITS(7) ---//
  6939. hold >>>= 7;
  6940. bits -= 7;
  6941. //---//
  6942. }
  6943. if (state.have + copy > state.nlen + state.ndist) {
  6944. strm.msg = 'invalid bit length repeat';
  6945. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6946. break;
  6947. }
  6948. while (copy--) {
  6949. state.lens[state.have++] = len;
  6950. }
  6951. }
  6952. }
  6953.  
  6954. /* handle error breaks in while */
  6955. if (state.mode === $$$vendor$pako$lib$zlib$inflate$$BAD) { break; }
  6956.  
  6957. /* check for end-of-block code (better have one) */
  6958. if (state.lens[256] === 0) {
  6959. strm.msg = 'invalid code -- missing end-of-block';
  6960. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6961. break;
  6962. }
  6963.  
  6964. /* build code tables -- note: do not change the lenbits or distbits
  6965. values here (9 and 6) without reading the comments in inftrees.h
  6966. concerning the ENOUGH constants, which depend on those values */
  6967. state.lenbits = 9;
  6968.  
  6969. opts = { bits: state.lenbits };
  6970. ret = $$inftrees$$default($$$vendor$pako$lib$zlib$inflate$$LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
  6971. // We have separate tables & no pointers. 2 commented lines below not needed.
  6972. // state.next_index = opts.table_index;
  6973. state.lenbits = opts.bits;
  6974. // state.lencode = state.next;
  6975.  
  6976. if (ret) {
  6977. strm.msg = 'invalid literal/lengths set';
  6978. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6979. break;
  6980. }
  6981.  
  6982. state.distbits = 6;
  6983. //state.distcode.copy(state.codes);
  6984. // Switch to use dynamic table
  6985. state.distcode = state.distdyn;
  6986. opts = { bits: state.distbits };
  6987. ret = $$inftrees$$default($$$vendor$pako$lib$zlib$inflate$$DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
  6988. // We have separate tables & no pointers. 2 commented lines below not needed.
  6989. // state.next_index = opts.table_index;
  6990. state.distbits = opts.bits;
  6991. // state.distcode = state.next;
  6992.  
  6993. if (ret) {
  6994. strm.msg = 'invalid distances set';
  6995. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  6996. break;
  6997. }
  6998. //Tracev((stderr, 'inflate: codes ok\n'));
  6999. state.mode = $$$vendor$pako$lib$zlib$inflate$$LEN_;
  7000. if (flush === $$$vendor$pako$lib$zlib$inflate$$Z_TREES) { break inf_leave; }
  7001. /* falls through */
  7002. case $$$vendor$pako$lib$zlib$inflate$$LEN_:
  7003. state.mode = $$$vendor$pako$lib$zlib$inflate$$LEN;
  7004. /* falls through */
  7005. case $$$vendor$pako$lib$zlib$inflate$$LEN:
  7006. if (have >= 6 && left >= 258) {
  7007. //--- RESTORE() ---
  7008. strm.next_out = put;
  7009. strm.avail_out = left;
  7010. strm.next_in = next;
  7011. strm.avail_in = have;
  7012. state.hold = hold;
  7013. state.bits = bits;
  7014. //---
  7015. $$inffast$$default(strm, _out);
  7016. //--- LOAD() ---
  7017. put = strm.next_out;
  7018. output = strm.output;
  7019. left = strm.avail_out;
  7020. next = strm.next_in;
  7021. input = strm.input;
  7022. have = strm.avail_in;
  7023. hold = state.hold;
  7024. bits = state.bits;
  7025. //---
  7026.  
  7027. if (state.mode === $$$vendor$pako$lib$zlib$inflate$$TYPE) {
  7028. state.back = -1;
  7029. }
  7030. break;
  7031. }
  7032. state.back = 0;
  7033. for (;;) {
  7034. here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/
  7035. here_bits = here >>> 24;
  7036. here_op = (here >>> 16) & 0xff;
  7037. here_val = here & 0xffff;
  7038.  
  7039. if (here_bits <= bits) { break; }
  7040. //--- PULLBYTE() ---//
  7041. if (have === 0) { break inf_leave; }
  7042. have--;
  7043. hold += input[next++] << bits;
  7044. bits += 8;
  7045. //---//
  7046. }
  7047. if (here_op && (here_op & 0xf0) === 0) {
  7048. last_bits = here_bits;
  7049. last_op = here_op;
  7050. last_val = here_val;
  7051. for (;;) {
  7052. here = state.lencode[last_val +
  7053. ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
  7054. here_bits = here >>> 24;
  7055. here_op = (here >>> 16) & 0xff;
  7056. here_val = here & 0xffff;
  7057.  
  7058. if ((last_bits + here_bits) <= bits) { break; }
  7059. //--- PULLBYTE() ---//
  7060. if (have === 0) { break inf_leave; }
  7061. have--;
  7062. hold += input[next++] << bits;
  7063. bits += 8;
  7064. //---//
  7065. }
  7066. //--- DROPBITS(last.bits) ---//
  7067. hold >>>= last_bits;
  7068. bits -= last_bits;
  7069. //---//
  7070. state.back += last_bits;
  7071. }
  7072. //--- DROPBITS(here.bits) ---//
  7073. hold >>>= here_bits;
  7074. bits -= here_bits;
  7075. //---//
  7076. state.back += here_bits;
  7077. state.length = here_val;
  7078. if (here_op === 0) {
  7079. //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
  7080. // "inflate: literal '%c'\n" :
  7081. // "inflate: literal 0x%02x\n", here.val));
  7082. state.mode = $$$vendor$pako$lib$zlib$inflate$$LIT;
  7083. break;
  7084. }
  7085. if (here_op & 32) {
  7086. //Tracevv((stderr, "inflate: end of block\n"));
  7087. state.back = -1;
  7088. state.mode = $$$vendor$pako$lib$zlib$inflate$$TYPE;
  7089. break;
  7090. }
  7091. if (here_op & 64) {
  7092. strm.msg = 'invalid literal/length code';
  7093. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7094. break;
  7095. }
  7096. state.extra = here_op & 15;
  7097. state.mode = $$$vendor$pako$lib$zlib$inflate$$LENEXT;
  7098. /* falls through */
  7099. case $$$vendor$pako$lib$zlib$inflate$$LENEXT:
  7100. if (state.extra) {
  7101. //=== NEEDBITS(state.extra);
  7102. n = state.extra;
  7103. while (bits < n) {
  7104. if (have === 0) { break inf_leave; }
  7105. have--;
  7106. hold += input[next++] << bits;
  7107. bits += 8;
  7108. }
  7109. //===//
  7110. state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
  7111. //--- DROPBITS(state.extra) ---//
  7112. hold >>>= state.extra;
  7113. bits -= state.extra;
  7114. //---//
  7115. state.back += state.extra;
  7116. }
  7117. //Tracevv((stderr, "inflate: length %u\n", state.length));
  7118. state.was = state.length;
  7119. state.mode = $$$vendor$pako$lib$zlib$inflate$$DIST;
  7120. /* falls through */
  7121. case $$$vendor$pako$lib$zlib$inflate$$DIST:
  7122. for (;;) {
  7123. here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
  7124. here_bits = here >>> 24;
  7125. here_op = (here >>> 16) & 0xff;
  7126. here_val = here & 0xffff;
  7127.  
  7128. if ((here_bits) <= bits) { break; }
  7129. //--- PULLBYTE() ---//
  7130. if (have === 0) { break inf_leave; }
  7131. have--;
  7132. hold += input[next++] << bits;
  7133. bits += 8;
  7134. //---//
  7135. }
  7136. if ((here_op & 0xf0) === 0) {
  7137. last_bits = here_bits;
  7138. last_op = here_op;
  7139. last_val = here_val;
  7140. for (;;) {
  7141. here = state.distcode[last_val +
  7142. ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
  7143. here_bits = here >>> 24;
  7144. here_op = (here >>> 16) & 0xff;
  7145. here_val = here & 0xffff;
  7146.  
  7147. if ((last_bits + here_bits) <= bits) { break; }
  7148. //--- PULLBYTE() ---//
  7149. if (have === 0) { break inf_leave; }
  7150. have--;
  7151. hold += input[next++] << bits;
  7152. bits += 8;
  7153. //---//
  7154. }
  7155. //--- DROPBITS(last.bits) ---//
  7156. hold >>>= last_bits;
  7157. bits -= last_bits;
  7158. //---//
  7159. state.back += last_bits;
  7160. }
  7161. //--- DROPBITS(here.bits) ---//
  7162. hold >>>= here_bits;
  7163. bits -= here_bits;
  7164. //---//
  7165. state.back += here_bits;
  7166. if (here_op & 64) {
  7167. strm.msg = 'invalid distance code';
  7168. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7169. break;
  7170. }
  7171. state.offset = here_val;
  7172. state.extra = (here_op) & 15;
  7173. state.mode = $$$vendor$pako$lib$zlib$inflate$$DISTEXT;
  7174. /* falls through */
  7175. case $$$vendor$pako$lib$zlib$inflate$$DISTEXT:
  7176. if (state.extra) {
  7177. //=== NEEDBITS(state.extra);
  7178. n = state.extra;
  7179. while (bits < n) {
  7180. if (have === 0) { break inf_leave; }
  7181. have--;
  7182. hold += input[next++] << bits;
  7183. bits += 8;
  7184. }
  7185. //===//
  7186. state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
  7187. //--- DROPBITS(state.extra) ---//
  7188. hold >>>= state.extra;
  7189. bits -= state.extra;
  7190. //---//
  7191. state.back += state.extra;
  7192. }
  7193. //#ifdef INFLATE_STRICT
  7194. if (state.offset > state.dmax) {
  7195. strm.msg = 'invalid distance too far back';
  7196. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7197. break;
  7198. }
  7199. //#endif
  7200. //Tracevv((stderr, "inflate: distance %u\n", state.offset));
  7201. state.mode = $$$vendor$pako$lib$zlib$inflate$$MATCH;
  7202. /* falls through */
  7203. case $$$vendor$pako$lib$zlib$inflate$$MATCH:
  7204. if (left === 0) { break inf_leave; }
  7205. copy = _out - left;
  7206. if (state.offset > copy) { /* copy from window */
  7207. copy = state.offset - copy;
  7208. if (copy > state.whave) {
  7209. if (state.sane) {
  7210. strm.msg = 'invalid distance too far back';
  7211. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7212. break;
  7213. }
  7214. // (!) This block is disabled in zlib defailts,
  7215. // don't enable it for binary compatibility
  7216. //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
  7217. // Trace((stderr, "inflate.c too far\n"));
  7218. // copy -= state.whave;
  7219. // if (copy > state.length) { copy = state.length; }
  7220. // if (copy > left) { copy = left; }
  7221. // left -= copy;
  7222. // state.length -= copy;
  7223. // do {
  7224. // output[put++] = 0;
  7225. // } while (--copy);
  7226. // if (state.length === 0) { state.mode = LEN; }
  7227. // break;
  7228. //#endif
  7229. }
  7230. if (copy > state.wnext) {
  7231. copy -= state.wnext;
  7232. from = state.wsize - copy;
  7233. }
  7234. else {
  7235. from = state.wnext - copy;
  7236. }
  7237. if (copy > state.length) { copy = state.length; }
  7238. from_source = state.window;
  7239. }
  7240. else { /* copy from output */
  7241. from_source = output;
  7242. from = put - state.offset;
  7243. copy = state.length;
  7244. }
  7245. if (copy > left) { copy = left; }
  7246. left -= copy;
  7247. state.length -= copy;
  7248. do {
  7249. output[put++] = from_source[from++];
  7250. } while (--copy);
  7251. if (state.length === 0) { state.mode = $$$vendor$pako$lib$zlib$inflate$$LEN; }
  7252. break;
  7253. case $$$vendor$pako$lib$zlib$inflate$$LIT:
  7254. if (left === 0) { break inf_leave; }
  7255. output[put++] = state.length;
  7256. left--;
  7257. state.mode = $$$vendor$pako$lib$zlib$inflate$$LEN;
  7258. break;
  7259. case $$$vendor$pako$lib$zlib$inflate$$CHECK:
  7260. if (state.wrap) {
  7261. //=== NEEDBITS(32);
  7262. while (bits < 32) {
  7263. if (have === 0) { break inf_leave; }
  7264. have--;
  7265. // Use '|' insdead of '+' to make sure that result is signed
  7266. hold |= input[next++] << bits;
  7267. bits += 8;
  7268. }
  7269. //===//
  7270. _out -= left;
  7271. strm.total_out += _out;
  7272. state.total += _out;
  7273. if (_out) {
  7274. strm.adler = state.check =
  7275. /*UPDATE(state.check, put - _out, _out);*/
  7276. (state.flags ? $$crc32$$default(state.check, output, _out, put - _out) : $$adler32$$default(state.check, output, _out, put - _out));
  7277.  
  7278. }
  7279. _out = left;
  7280. // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
  7281. if ((state.flags ? hold : $$$vendor$pako$lib$zlib$inflate$$zswap32(hold)) !== state.check) {
  7282. strm.msg = 'incorrect data check';
  7283. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7284. break;
  7285. }
  7286. //=== INITBITS();
  7287. hold = 0;
  7288. bits = 0;
  7289. //===//
  7290. //Tracev((stderr, "inflate: check matches trailer\n"));
  7291. }
  7292. state.mode = $$$vendor$pako$lib$zlib$inflate$$LENGTH;
  7293. /* falls through */
  7294. case $$$vendor$pako$lib$zlib$inflate$$LENGTH:
  7295. if (state.wrap && state.flags) {
  7296. //=== NEEDBITS(32);
  7297. while (bits < 32) {
  7298. if (have === 0) { break inf_leave; }
  7299. have--;
  7300. hold += input[next++] << bits;
  7301. bits += 8;
  7302. }
  7303. //===//
  7304. if (hold !== (state.total & 0xffffffff)) {
  7305. strm.msg = 'incorrect length check';
  7306. state.mode = $$$vendor$pako$lib$zlib$inflate$$BAD;
  7307. break;
  7308. }
  7309. //=== INITBITS();
  7310. hold = 0;
  7311. bits = 0;
  7312. //===//
  7313. //Tracev((stderr, "inflate: length matches trailer\n"));
  7314. }
  7315. state.mode = $$$vendor$pako$lib$zlib$inflate$$DONE;
  7316. /* falls through */
  7317. case $$$vendor$pako$lib$zlib$inflate$$DONE:
  7318. ret = $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_END;
  7319. break inf_leave;
  7320. case $$$vendor$pako$lib$zlib$inflate$$BAD:
  7321. ret = $$$vendor$pako$lib$zlib$inflate$$Z_DATA_ERROR;
  7322. break inf_leave;
  7323. case $$$vendor$pako$lib$zlib$inflate$$MEM:
  7324. return $$$vendor$pako$lib$zlib$inflate$$Z_MEM_ERROR;
  7325. case $$$vendor$pako$lib$zlib$inflate$$SYNC:
  7326. /* falls through */
  7327. default:
  7328. return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR;
  7329. }
  7330. }
  7331.  
  7332. // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
  7333.  
  7334. /*
  7335. Return from inflate(), updating the total counts and the check value.
  7336. If there was no progress during the inflate() call, return a buffer
  7337. error. Call updatewindow() to create and/or update the window state.
  7338. Note: a memory error from inflate() is non-recoverable.
  7339. */
  7340.  
  7341. //--- RESTORE() ---
  7342. strm.next_out = put;
  7343. strm.avail_out = left;
  7344. strm.next_in = next;
  7345. strm.avail_in = have;
  7346. state.hold = hold;
  7347. state.bits = bits;
  7348. //---
  7349.  
  7350. if (state.wsize || (_out !== strm.avail_out && state.mode < $$$vendor$pako$lib$zlib$inflate$$BAD &&
  7351. (state.mode < $$$vendor$pako$lib$zlib$inflate$$CHECK || flush !== $$$vendor$pako$lib$zlib$inflate$$Z_FINISH))) {
  7352. if ($$$vendor$pako$lib$zlib$inflate$$updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
  7353. state.mode = $$$vendor$pako$lib$zlib$inflate$$MEM;
  7354. return $$$vendor$pako$lib$zlib$inflate$$Z_MEM_ERROR;
  7355. }
  7356. }
  7357. _in -= strm.avail_in;
  7358. _out -= strm.avail_out;
  7359. strm.total_in += _in;
  7360. strm.total_out += _out;
  7361. state.total += _out;
  7362. if (state.wrap && _out) {
  7363. strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
  7364. (state.flags ? $$crc32$$default(state.check, output, _out, strm.next_out - _out) : $$adler32$$default(state.check, output, _out, strm.next_out - _out));
  7365. }
  7366. strm.data_type = state.bits + (state.last ? 64 : 0) +
  7367. (state.mode === $$$vendor$pako$lib$zlib$inflate$$TYPE ? 128 : 0) +
  7368. (state.mode === $$$vendor$pako$lib$zlib$inflate$$LEN_ || state.mode === $$$vendor$pako$lib$zlib$inflate$$COPY_ ? 256 : 0);
  7369. if (((_in === 0 && _out === 0) || flush === $$$vendor$pako$lib$zlib$inflate$$Z_FINISH) && ret === $$$vendor$pako$lib$zlib$inflate$$Z_OK) {
  7370. ret = $$$vendor$pako$lib$zlib$inflate$$Z_BUF_ERROR;
  7371. }
  7372. return ret;
  7373. }
  7374.  
  7375. function $$$vendor$pako$lib$zlib$inflate$$inflateEnd(strm) {
  7376.  
  7377. if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
  7378. return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR;
  7379. }
  7380.  
  7381. var state = strm.state;
  7382. if (state.window) {
  7383. state.window = null;
  7384. }
  7385. strm.state = null;
  7386. return $$$vendor$pako$lib$zlib$inflate$$Z_OK;
  7387. }
  7388.  
  7389. function $$$vendor$pako$lib$zlib$inflate$$inflateGetHeader(strm, head) {
  7390. var state;
  7391.  
  7392. /* check state */
  7393. if (!strm || !strm.state) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  7394. state = strm.state;
  7395. if ((state.wrap & 2) === 0) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  7396.  
  7397. /* save header structure */
  7398. state.head = head;
  7399. head.done = false;
  7400. return $$$vendor$pako$lib$zlib$inflate$$Z_OK;
  7401. }
  7402.  
  7403. function $$$vendor$pako$lib$zlib$inflate$$inflateSetDictionary(strm, dictionary) {
  7404. var dictLength = dictionary.length;
  7405.  
  7406. var state;
  7407. var dictid;
  7408. var ret;
  7409.  
  7410. /* check state */
  7411. if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR; }
  7412. state = strm.state;
  7413.  
  7414. if (state.wrap !== 0 && state.mode !== $$$vendor$pako$lib$zlib$inflate$$DICT) {
  7415. return $$$vendor$pako$lib$zlib$inflate$$Z_STREAM_ERROR;
  7416. }
  7417.  
  7418. /* check for correct dictionary identifier */
  7419. if (state.mode === $$$vendor$pako$lib$zlib$inflate$$DICT) {
  7420. dictid = 1; /* adler32(0, null, 0)*/
  7421. /* dictid = adler32(dictid, dictionary, dictLength); */
  7422. dictid = $$adler32$$default(dictid, dictionary, dictLength, 0);
  7423. if (dictid !== state.check) {
  7424. return $$$vendor$pako$lib$zlib$inflate$$Z_DATA_ERROR;
  7425. }
  7426. }
  7427. /* copy dictionary to window using updatewindow(), which will amend the
  7428. existing dictionary if appropriate */
  7429. ret = $$$vendor$pako$lib$zlib$inflate$$updatewindow(strm, dictionary, dictLength, dictLength);
  7430. if (ret) {
  7431. state.mode = $$$vendor$pako$lib$zlib$inflate$$MEM;
  7432. return $$$vendor$pako$lib$zlib$inflate$$Z_MEM_ERROR;
  7433. }
  7434. state.havedict = 1;
  7435. // Tracev((stderr, "inflate: dictionary set\n"));
  7436. return $$$vendor$pako$lib$zlib$inflate$$Z_OK;
  7437. }
  7438.  
  7439. const $$$vendor$pako$lib$zlib$inflate$$inflateInfo = 'pako inflate (from Nodeca project)';
  7440.  
  7441. function $$$vendor$pako$lib$zlib$zstream$$ZStream() {
  7442. /* next input byte */
  7443. this.input = null; // JS specific, because we have no pointers
  7444. this.next_in = 0;
  7445. /* number of bytes available at input */
  7446. this.avail_in = 0;
  7447. /* total number of input bytes read so far */
  7448. this.total_in = 0;
  7449. /* next output byte should be put there */
  7450. this.output = null; // JS specific, because we have no pointers
  7451. this.next_out = 0;
  7452. /* remaining free space at output */
  7453. this.avail_out = 0;
  7454. /* total number of bytes output so far */
  7455. this.total_out = 0;
  7456. /* last error message, NULL if no error */
  7457. this.msg = ''/*Z_NULL*/;
  7458. /* not visible by applications */
  7459. this.state = null;
  7460. /* best guess about the data type: binary or text */
  7461. this.data_type = 2/*Z_UNKNOWN*/;
  7462. /* adler32 value of the uncompressed data */
  7463. this.adler = 0;
  7464. }
  7465.  
  7466. var $$$vendor$pako$lib$zlib$zstream$$default = $$$vendor$pako$lib$zlib$zstream$$ZStream;
  7467.  
  7468. $$inflator$$Inflate.prototype = {
  7469. inflate: function (data, flush, expected) {
  7470. this.strm.input = data;
  7471. this.strm.avail_in = this.strm.input.length;
  7472. this.strm.next_in = 0;
  7473. this.strm.next_out = 0;
  7474.  
  7475. // resize our output buffer if it's too small
  7476. // (we could just use multiple chunks, but that would cause an extra
  7477. // allocation each time to flatten the chunks)
  7478. if (expected > this.chunkSize) {
  7479. this.chunkSize = expected;
  7480. this.strm.output = new Uint8Array(this.chunkSize);
  7481. }
  7482.  
  7483. this.strm.avail_out = this.chunkSize;
  7484.  
  7485. $$$vendor$pako$lib$zlib$inflate$$inflate(this.strm, flush);
  7486.  
  7487. return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
  7488. },
  7489.  
  7490. reset: function () {
  7491. $$$vendor$pako$lib$zlib$inflate$$inflateReset(this.strm);
  7492. }
  7493. };
  7494.  
  7495. function $$inflator$$Inflate() {
  7496. this.strm = new $$$vendor$pako$lib$zlib$zstream$$default();
  7497. this.chunkSize = 1024 * 10 * 10;
  7498. this.strm.output = new Uint8Array(this.chunkSize);
  7499. this.windowBits = 5;
  7500.  
  7501. $$$vendor$pako$lib$zlib$inflate$$inflateInit(this.strm, this.windowBits);
  7502. }
  7503.  
  7504. var $$inflator$$default = $$inflator$$Inflate;
  7505.  
  7506. function $$$core$rfb$$RFB(defaults) {
  7507. "use strict";
  7508. if (!defaults) {
  7509. defaults = {};
  7510. }
  7511.  
  7512. this._rfb_host = '';
  7513. this._rfb_port = 5900;
  7514. this._rfb_password = '';
  7515. this._rfb_path = '';
  7516.  
  7517. this._rfb_connection_state = '';
  7518. this._rfb_init_state = '';
  7519. this._rfb_version = 0;
  7520. this._rfb_max_version = 3.8;
  7521. this._rfb_auth_scheme = '';
  7522. this._rfb_disconnect_reason = "";
  7523.  
  7524. this._rfb_tightvnc = false;
  7525. this._rfb_xvp_ver = 0;
  7526.  
  7527. // In preference order
  7528. this._encodings = [
  7529. ['COPYRECT', 0x01 ],
  7530. ['TIGHT', 0x07 ],
  7531. ['TIGHT_PNG', -260 ],
  7532. ['HEXTILE', 0x05 ],
  7533. ['RRE', 0x02 ],
  7534. ['RAW', 0x00 ],
  7535.  
  7536. // Psuedo-encoding settings
  7537.  
  7538. //['JPEG_quality_lo', -32 ],
  7539. ['JPEG_quality_med', -26 ],
  7540. //['JPEG_quality_hi', -23 ],
  7541. //['compress_lo', -255 ],
  7542. ['compress_hi', -254 ],
  7543. //['compress_max', -247 ],
  7544.  
  7545. ['DesktopSize', -223 ],
  7546. ['last_rect', -224 ],
  7547. ['Cursor', -239 ],
  7548. ['QEMUExtendedKeyEvent', -258 ],
  7549. ['ExtendedDesktopSize', -308 ],
  7550. ['xvp', -309 ],
  7551. ['Fence', -312 ],
  7552. ['ContinuousUpdates', -313 ]
  7553. ];
  7554.  
  7555. this._encHandlers = {};
  7556. this._encNames = {};
  7557. this._encStats = {};
  7558.  
  7559. this._sock = null; // Websock object
  7560. this._display = null; // Display object
  7561. this._flushing = false; // Display flushing state
  7562. this._keyboard = null; // Keyboard input handler object
  7563. this._mouse = null; // Mouse input handler object
  7564. this._disconnTimer = null; // disconnection timer
  7565.  
  7566. this._supportsFence = false;
  7567.  
  7568. this._supportsContinuousUpdates = false;
  7569. this._enabledContinuousUpdates = false;
  7570.  
  7571. // Frame buffer update state
  7572. this._FBU = {
  7573. rects: 0,
  7574. subrects: 0, // RRE
  7575. lines: 0, // RAW
  7576. tiles: 0, // HEXTILE
  7577. bytes: 0,
  7578. x: 0,
  7579. y: 0,
  7580. width: 0,
  7581. height: 0,
  7582. encoding: 0,
  7583. subencoding: -1,
  7584. background: null,
  7585. zlib: [] // TIGHT zlib streams
  7586. };
  7587.  
  7588. this._fb_width = 0;
  7589. this._fb_height = 0;
  7590. this._fb_name = "";
  7591.  
  7592. this._destBuff = null;
  7593. this._paletteBuff = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel)
  7594.  
  7595. this._rre_chunk_sz = 100;
  7596.  
  7597. this._timing = {
  7598. last_fbu: 0,
  7599. fbu_total: 0,
  7600. fbu_total_cnt: 0,
  7601. full_fbu_total: 0,
  7602. full_fbu_cnt: 0,
  7603.  
  7604. fbu_rt_start: 0,
  7605. fbu_rt_total: 0,
  7606. fbu_rt_cnt: 0,
  7607. pixels: 0
  7608. };
  7609.  
  7610. this._supportsSetDesktopSize = false;
  7611. this._screen_id = 0;
  7612. this._screen_flags = 0;
  7613.  
  7614. // Mouse state
  7615. this._mouse_buttonMask = 0;
  7616. this._mouse_arr = [];
  7617. this._viewportDragging = false;
  7618. this._viewportDragPos = {};
  7619. this._viewportHasMoved = false;
  7620.  
  7621. // QEMU Extended Key Event support - default to false
  7622. this._qemuExtKeyEventSupported = false;
  7623.  
  7624. // set the default value on user-facing properties
  7625. $$util$properties$$set_defaults(this, defaults, {
  7626. 'target': 'null', // VNC display rendering Canvas object
  7627. 'focusContainer': document, // DOM element that captures keyboard input
  7628. 'encrypt': false, // Use TLS/SSL/wss encryption
  7629. 'local_cursor': false, // Request locally rendered cursor
  7630. 'shared': true, // Request shared mode
  7631. 'view_only': false, // Disable client mouse/keyboard
  7632. 'xvp_password_sep': '@', // Separator for XVP password fields
  7633. 'disconnectTimeout': 3, // Time (s) to wait for disconnection
  7634. 'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection
  7635. 'repeaterID': '', // [UltraVNC] RepeaterID to connect to
  7636. 'viewportDrag': false, // Move the viewport on mouse drags
  7637.  
  7638. // Callback functions
  7639. 'onUpdateState': function () { }, // onUpdateState(rfb, state, oldstate): connection state change
  7640. 'onNotification': function () { }, // onNotification(rfb, msg, level, options): notification for UI
  7641. 'onDisconnected': function () { }, // onDisconnected(rfb, reason): disconnection finished
  7642. 'onPasswordRequired': function () { }, // onPasswordRequired(rfb, msg): VNC password is required
  7643. 'onClipboard': function () { }, // onClipboard(rfb, text): RFB clipboard contents received
  7644. 'onBell': function () { }, // onBell(rfb): RFB Bell message received
  7645. 'onFBUReceive': function () { }, // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed
  7646. 'onFBUComplete': function () { }, // onFBUComplete(rfb, fbu): RFB FBU received and processed
  7647. 'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized
  7648. 'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received
  7649. 'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection
  7650. });
  7651.  
  7652. // main setup
  7653. $$$core$util$logging$$.Debug(">> RFB.constructor");
  7654.  
  7655. // populate encHandlers with bound versions
  7656. Object.keys($$$core$rfb$$RFB.encodingHandlers).forEach(function (encName) {
  7657. this._encHandlers[encName] = $$$core$rfb$$RFB.encodingHandlers[encName].bind(this);
  7658. }.bind(this));
  7659.  
  7660. // Create lookup tables based on encoding number
  7661. for (var i = 0; i < this._encodings.length; i++) {
  7662. this._encHandlers[this._encodings[i][1]] = this._encHandlers[this._encodings[i][0]];
  7663. this._encNames[this._encodings[i][1]] = this._encodings[i][0];
  7664. this._encStats[this._encodings[i][1]] = [0, 0];
  7665. }
  7666.  
  7667. // NB: nothing that needs explicit teardown should be done
  7668. // before this point, since this can throw an exception
  7669. try {
  7670. this._display = new $$$core$display$$default({target: this._target,
  7671. onFlush: this._onFlush.bind(this)});
  7672. } catch (exc) {
  7673. $$$core$util$logging$$.Error("Display exception: " + exc);
  7674. throw exc;
  7675. }
  7676.  
  7677. this._keyboard = new $$input$devices$$Keyboard({target: this._focusContainer,
  7678. onKeyEvent: this._handleKeyEvent.bind(this)});
  7679.  
  7680. this._mouse = new $$input$devices$$Mouse({target: this._target,
  7681. onMouseButton: this._handleMouseButton.bind(this),
  7682. onMouseMove: this._handleMouseMove.bind(this)});
  7683.  
  7684. this._sock = new $$websock$$default();
  7685. this._sock.on('message', this._handle_message.bind(this));
  7686. this._sock.on('open', function () {
  7687. if ((this._rfb_connection_state === 'connecting') &&
  7688. (this._rfb_init_state === '')) {
  7689. this._rfb_init_state = 'ProtocolVersion';
  7690. $$$core$util$logging$$.Debug("Starting VNC handshake");
  7691. } else {
  7692. this._fail("Unexpected server connection");
  7693. }
  7694. }.bind(this));
  7695. this._sock.on('close', function (e) {
  7696. $$$core$util$logging$$.Warn("WebSocket on-close event");
  7697. var msg = "";
  7698. if (e.code) {
  7699. msg = " (code: " + e.code;
  7700. if (e.reason) {
  7701. msg += ", reason: " + e.reason;
  7702. }
  7703. msg += ")";
  7704. }
  7705. switch (this._rfb_connection_state) {
  7706. case 'disconnecting':
  7707. this._updateConnectionState('disconnected');
  7708. break;
  7709. case 'connecting':
  7710. this._fail('Failed to connect to server', msg);
  7711. break;
  7712. case 'connected':
  7713. // Handle disconnects that were initiated server-side
  7714. this._updateConnectionState('disconnecting');
  7715. this._updateConnectionState('disconnected');
  7716. break;
  7717. case 'disconnected':
  7718. this._fail("Unexpected server disconnect",
  7719. "Already disconnected: " + msg);
  7720. break;
  7721. default:
  7722. this._fail("Unexpected server disconnect",
  7723. "Not in any state yet: " + msg);
  7724. break;
  7725. }
  7726. this._sock.off('close');
  7727. }.bind(this));
  7728. this._sock.on('error', function (e) {
  7729. $$$core$util$logging$$.Warn("WebSocket on-error event");
  7730. });
  7731.  
  7732. this._init_vars();
  7733. this._cleanup();
  7734.  
  7735. var rmode = this._display.get_render_mode();
  7736. $$$core$util$logging$$.Info("Using native WebSockets, render mode: " + rmode);
  7737.  
  7738. $$$core$util$logging$$.Debug("<< RFB.constructor");
  7739. }
  7740.  
  7741. var $$$core$rfb$$default = $$$core$rfb$$RFB;
  7742.  
  7743. $$$core$rfb$$RFB.prototype = {
  7744. // Public methods
  7745. connect: function (host, port, password, path) {
  7746. this._rfb_host = host;
  7747. this._rfb_port = port;
  7748. this._rfb_password = (password !== undefined) ? password : "";
  7749. this._rfb_path = (path !== undefined) ? path : "";
  7750.  
  7751. if (!this._rfb_host || !this._rfb_port) {
  7752. return this._fail(
  7753. $$$core$util$localization$$default("Must set host and port"));
  7754. }
  7755.  
  7756. this._rfb_init_state = '';
  7757. this._updateConnectionState('connecting');
  7758. return true;
  7759. },
  7760.  
  7761. disconnect: function () {
  7762. this._updateConnectionState('disconnecting');
  7763. this._sock.off('error');
  7764. this._sock.off('message');
  7765. this._sock.off('open');
  7766. },
  7767.  
  7768. sendPassword: function (passwd) {
  7769. this._rfb_password = passwd;
  7770. setTimeout(this._init_msg.bind(this), 0);
  7771. },
  7772.  
  7773. sendCtrlAltDel: function () {
  7774. if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; }
  7775. $$$core$util$logging$$.Info("Sending Ctrl-Alt-Del");
  7776.  
  7777. this.sendKey($$$core$input$keysym$$default.XK_Control_L, "ControlLeft", true);
  7778. this.sendKey($$$core$input$keysym$$default.XK_Alt_L, "AltLeft", true);
  7779. this.sendKey($$$core$input$keysym$$default.XK_Delete, "Delete", true);
  7780. this.sendKey($$$core$input$keysym$$default.XK_Delete, "Delete", false);
  7781. this.sendKey($$$core$input$keysym$$default.XK_Alt_L, "AltLeft", false);
  7782. this.sendKey($$$core$input$keysym$$default.XK_Control_L, "ControlLeft", false);
  7783.  
  7784. return true;
  7785. },
  7786.  
  7787. xvpOp: function (ver, op) {
  7788. if (this._rfb_xvp_ver < ver) { return false; }
  7789. $$$core$util$logging$$.Info("Sending XVP operation " + op + " (version " + ver + ")");
  7790. this._sock.send_string("\xFA\x00" + String.fromCharCode(ver) + String.fromCharCode(op));
  7791. return true;
  7792. },
  7793.  
  7794. xvpShutdown: function () {
  7795. return this.xvpOp(1, 2);
  7796. },
  7797.  
  7798. xvpReboot: function () {
  7799. return this.xvpOp(1, 3);
  7800. },
  7801.  
  7802. xvpReset: function () {
  7803. return this.xvpOp(1, 4);
  7804. },
  7805.  
  7806. // Send a key press. If 'down' is not specified then send a down key
  7807. // followed by an up key.
  7808. sendKey: function (keysym, code, down) {
  7809. if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; }
  7810.  
  7811. if (down === undefined) {
  7812. this.sendKey(keysym, code, true);
  7813. this.sendKey(keysym, code, false);
  7814. return true;
  7815. }
  7816.  
  7817. if (this._qemuExtKeyEventSupported) {
  7818. var scancode = $$input$xtscancodes$$default[code];
  7819.  
  7820. if (scancode === undefined) {
  7821. $$$core$util$logging$$.Error('Unable to find a xt scancode for code: ' + code);
  7822. // FIXME: not in the spec, but this is what
  7823. // gtk-vnc does
  7824. scancode = 0;
  7825. }
  7826.  
  7827. $$$core$util$logging$$.Info("Sending key (" + (down ? "down" : "up") + "): keysym " + keysym + ", scancode " + scancode);
  7828.  
  7829. $$$core$rfb$$RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode);
  7830. } else {
  7831. $$$core$util$logging$$.Info("Sending keysym (" + (down ? "down" : "up") + "): " + keysym);
  7832. $$$core$rfb$$RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0);
  7833. }
  7834.  
  7835. return true;
  7836. },
  7837.  
  7838. clipboardPasteFrom: function (text) {
  7839. if (this._rfb_connection_state !== 'connected' || this._view_only) { return; }
  7840. $$$core$rfb$$RFB.messages.clientCutText(this._sock, text);
  7841. },
  7842.  
  7843. // Requests a change of remote desktop size. This message is an extension
  7844. // and may only be sent if we have received an ExtendedDesktopSize message
  7845. requestDesktopSize: function (width, height) {
  7846. if (this._rfb_connection_state !== 'connected' ||
  7847. this._view_only) {
  7848. return false;
  7849. }
  7850.  
  7851. if (this._supportsSetDesktopSize) {
  7852. $$$core$rfb$$RFB.messages.setDesktopSize(this._sock, width, height,
  7853. this._screen_id, this._screen_flags);
  7854. this._sock.flush();
  7855. return true;
  7856. } else {
  7857. return false;
  7858. }
  7859. },
  7860.  
  7861.  
  7862. // Private methods
  7863.  
  7864. _connect: function () {
  7865. $$$core$util$logging$$.Debug(">> RFB.connect");
  7866. this._init_vars();
  7867.  
  7868. var uri;
  7869. if (typeof UsingSocketIO !== 'undefined') {
  7870. uri = 'http';
  7871. } else {
  7872. uri = this._encrypt ? 'wss' : 'ws';
  7873. }
  7874.  
  7875. uri += '://' + this._rfb_host + ':' + this._rfb_port + '/' + this._rfb_path;
  7876. $$$core$util$logging$$.Info("connecting to " + uri);
  7877.  
  7878. try {
  7879. // WebSocket.onopen transitions to the RFB init states
  7880. this._sock.open(uri, this._wsProtocols);
  7881. } catch (e) {
  7882. if (e.name === 'SyntaxError') {
  7883. this._fail("Invalid host or port value given", e);
  7884. } else {
  7885. this._fail("Error while connecting", e);
  7886. }
  7887. }
  7888.  
  7889. $$$core$util$logging$$.Debug("<< RFB.connect");
  7890. },
  7891.  
  7892. _disconnect: function () {
  7893. $$$core$util$logging$$.Debug(">> RFB.disconnect");
  7894. this._cleanup();
  7895. this._sock.close();
  7896. this._print_stats();
  7897. $$$core$util$logging$$.Debug("<< RFB.disconnect");
  7898. },
  7899.  
  7900. _init_vars: function () {
  7901. // reset state
  7902. this._FBU.rects = 0;
  7903. this._FBU.subrects = 0; // RRE and HEXTILE
  7904. this._FBU.lines = 0; // RAW
  7905. this._FBU.tiles = 0; // HEXTILE
  7906. this._FBU.zlibs = []; // TIGHT zlib encoders
  7907. this._mouse_buttonMask = 0;
  7908. this._mouse_arr = [];
  7909. this._rfb_tightvnc = false;
  7910.  
  7911. // Clear the per connection encoding stats
  7912. var i;
  7913. for (i = 0; i < this._encodings.length; i++) {
  7914. this._encStats[this._encodings[i][1]][0] = 0;
  7915. }
  7916.  
  7917. for (i = 0; i < 4; i++) {
  7918. this._FBU.zlibs[i] = new $$inflator$$default();
  7919. }
  7920. },
  7921.  
  7922. _print_stats: function () {
  7923. $$$core$util$logging$$.Info("Encoding stats for this connection:");
  7924. var i, s;
  7925. for (i = 0; i < this._encodings.length; i++) {
  7926. s = this._encStats[this._encodings[i][1]];
  7927. if (s[0] + s[1] > 0) {
  7928. $$$core$util$logging$$.Info(" " + this._encodings[i][0] + ": " + s[0] + " rects");
  7929. }
  7930. }
  7931.  
  7932. $$$core$util$logging$$.Info("Encoding stats since page load:");
  7933. for (i = 0; i < this._encodings.length; i++) {
  7934. s = this._encStats[this._encodings[i][1]];
  7935. $$$core$util$logging$$.Info(" " + this._encodings[i][0] + ": " + s[1] + " rects");
  7936. }
  7937. },
  7938.  
  7939. _cleanup: function () {
  7940. if (!this._view_only) { this._keyboard.ungrab(); }
  7941. if (!this._view_only) { this._mouse.ungrab(); }
  7942. this._display.defaultCursor();
  7943. if ($$$core$util$logging$$.get_logging() !== 'debug') {
  7944. // Show noVNC logo on load and when disconnected, unless in
  7945. // debug mode
  7946. this._display.clear();
  7947. }
  7948. },
  7949.  
  7950. /*
  7951. * Connection states:
  7952. * connecting
  7953. * connected
  7954. * disconnecting
  7955. * disconnected - permanent state
  7956. */
  7957. _updateConnectionState: function (state) {
  7958. var oldstate = this._rfb_connection_state;
  7959.  
  7960. if (state === oldstate) {
  7961. $$$core$util$logging$$.Debug("Already in state '" + state + "', ignoring");
  7962. return;
  7963. }
  7964.  
  7965. // The 'disconnected' state is permanent for each RFB object
  7966. if (oldstate === 'disconnected') {
  7967. $$$core$util$logging$$.Error("Tried changing state of a disconnected RFB object");
  7968. return;
  7969. }
  7970.  
  7971. // Ensure proper transitions before doing anything
  7972. switch (state) {
  7973. case 'connected':
  7974. if (oldstate !== 'connecting') {
  7975. $$$core$util$logging$$.Error("Bad transition to connected state, " +
  7976. "previous connection state: " + oldstate);
  7977. return;
  7978. }
  7979. break;
  7980.  
  7981. case 'disconnected':
  7982. if (oldstate !== 'disconnecting') {
  7983. $$$core$util$logging$$.Error("Bad transition to disconnected state, " +
  7984. "previous connection state: " + oldstate);
  7985. return;
  7986. }
  7987. break;
  7988.  
  7989. case 'connecting':
  7990. if (oldstate !== '') {
  7991. $$$core$util$logging$$.Error("Bad transition to connecting state, " +
  7992. "previous connection state: " + oldstate);
  7993. return;
  7994. }
  7995. break;
  7996.  
  7997. case 'disconnecting':
  7998. if (oldstate !== 'connected' && oldstate !== 'connecting') {
  7999. $$$core$util$logging$$.Error("Bad transition to disconnecting state, " +
  8000. "previous connection state: " + oldstate);
  8001. return;
  8002. }
  8003. break;
  8004.  
  8005. default:
  8006. $$$core$util$logging$$.Error("Unknown connection state: " + state);
  8007. return;
  8008. }
  8009.  
  8010. // State change actions
  8011.  
  8012. this._rfb_connection_state = state;
  8013. this._onUpdateState(this, state, oldstate);
  8014.  
  8015. var smsg = "New state '" + state + "', was '" + oldstate + "'.";
  8016. $$$core$util$logging$$.Debug(smsg);
  8017.  
  8018. if (this._disconnTimer && state !== 'disconnecting') {
  8019. $$$core$util$logging$$.Debug("Clearing disconnect timer");
  8020. clearTimeout(this._disconnTimer);
  8021. this._disconnTimer = null;
  8022.  
  8023. // make sure we don't get a double event
  8024. this._sock.off('close');
  8025. }
  8026.  
  8027. switch (state) {
  8028. case 'disconnected':
  8029. // Call onDisconnected callback after onUpdateState since
  8030. // we don't know if the UI only displays the latest message
  8031. if (this._rfb_disconnect_reason !== "") {
  8032. this._onDisconnected(this, this._rfb_disconnect_reason);
  8033. } else {
  8034. // No reason means clean disconnect
  8035. this._onDisconnected(this);
  8036. }
  8037. break;
  8038.  
  8039. case 'connecting':
  8040. this._connect();
  8041. break;
  8042.  
  8043. case 'disconnecting':
  8044. this._disconnect();
  8045.  
  8046. this._disconnTimer = setTimeout(function () {
  8047. this._rfb_disconnect_reason = $$$core$util$localization$$default("Disconnect timeout");
  8048. this._updateConnectionState('disconnected');
  8049. }.bind(this), this._disconnectTimeout * 1000);
  8050. break;
  8051. }
  8052. },
  8053.  
  8054. /* Print errors and disconnect
  8055. *
  8056. * The optional parameter 'details' is used for information that
  8057. * should be logged but not sent to the user interface.
  8058. */
  8059. _fail: function (msg, details) {
  8060. var fullmsg = msg;
  8061. if (typeof details !== 'undefined') {
  8062. fullmsg = msg + " (" + details + ")";
  8063. }
  8064. switch (this._rfb_connection_state) {
  8065. case 'disconnecting':
  8066. $$$core$util$logging$$.Error("Failed when disconnecting: " + fullmsg);
  8067. break;
  8068. case 'connected':
  8069. $$$core$util$logging$$.Error("Failed while connected: " + fullmsg);
  8070. break;
  8071. case 'connecting':
  8072. $$$core$util$logging$$.Error("Failed when connecting: " + fullmsg);
  8073. break;
  8074. default:
  8075. $$$core$util$logging$$.Error("RFB failure: " + fullmsg);
  8076. break;
  8077. }
  8078. this._rfb_disconnect_reason = msg; //This is sent to the UI
  8079.  
  8080. // Transition to disconnected without waiting for socket to close
  8081. this._updateConnectionState('disconnecting');
  8082. this._updateConnectionState('disconnected');
  8083.  
  8084. return false;
  8085. },
  8086.  
  8087. /*
  8088. * Send a notification to the UI. Valid levels are:
  8089. * 'normal'|'warn'|'error'
  8090. *
  8091. * NOTE: Options could be added in the future.
  8092. * NOTE: If this function is called multiple times, remember that the
  8093. * interface could be only showing the latest notification.
  8094. */
  8095. _notification: function(msg, level, options) {
  8096. switch (level) {
  8097. case 'normal':
  8098. case 'warn':
  8099. case 'error':
  8100. $$$core$util$logging$$.Debug("Notification[" + level + "]:" + msg);
  8101. break;
  8102. default:
  8103. $$$core$util$logging$$.Error("Invalid notification level: " + level);
  8104. return;
  8105. }
  8106.  
  8107. if (options) {
  8108. this._onNotification(this, msg, level, options);
  8109. } else {
  8110. this._onNotification(this, msg, level);
  8111. }
  8112. },
  8113.  
  8114. _handle_message: function () {
  8115. if (this._sock.rQlen() === 0) {
  8116. $$$core$util$logging$$.Warn("handle_message called on an empty receive queue");
  8117. return;
  8118. }
  8119.  
  8120. switch (this._rfb_connection_state) {
  8121. case 'disconnected':
  8122. $$$core$util$logging$$.Error("Got data while disconnected");
  8123. break;
  8124. case 'connected':
  8125. while (true) {
  8126. if (this._flushing) {
  8127. break;
  8128. }
  8129. if (!this._normal_msg()) {
  8130. break;
  8131. }
  8132. if (this._sock.rQlen() === 0) {
  8133. break;
  8134. }
  8135. }
  8136. break;
  8137. default:
  8138. this._init_msg();
  8139. break;
  8140. }
  8141. },
  8142.  
  8143. _handleKeyEvent: function (keysym, code, down) {
  8144. this.sendKey(keysym, code, down);
  8145. },
  8146.  
  8147. _handleMouseButton: function (x, y, down, bmask) {
  8148. if (down) {
  8149. this._mouse_buttonMask |= bmask;
  8150. } else {
  8151. this._mouse_buttonMask &= ~bmask;
  8152. }
  8153.  
  8154. if (this._viewportDrag) {
  8155. if (down && !this._viewportDragging) {
  8156. this._viewportDragging = true;
  8157. this._viewportDragPos = {'x': x, 'y': y};
  8158.  
  8159. // Skip sending mouse events
  8160. return;
  8161. } else {
  8162. this._viewportDragging = false;
  8163.  
  8164. // If the viewport didn't actually move, then treat as a mouse click event
  8165. // Send the button down event here, as the button up event is sent at the end of this function
  8166. if (!this._viewportHasMoved && !this._view_only) {
  8167. $$$core$rfb$$RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), bmask);
  8168. }
  8169. this._viewportHasMoved = false;
  8170. }
  8171. }
  8172.  
  8173. if (this._view_only) { return; } // View only, skip mouse events
  8174.  
  8175. if (this._rfb_connection_state !== 'connected') { return; }
  8176. $$$core$rfb$$RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask);
  8177. },
  8178.  
  8179. _handleMouseMove: function (x, y) {
  8180. if (this._viewportDragging) {
  8181. var deltaX = this._viewportDragPos.x - x;
  8182. var deltaY = this._viewportDragPos.y - y;
  8183.  
  8184. // The goal is to trigger on a certain physical width, the
  8185. // devicePixelRatio brings us a bit closer but is not optimal.
  8186. var dragThreshold = 10 * (window.devicePixelRatio || 1);
  8187.  
  8188. if (this._viewportHasMoved || (Math.abs(deltaX) > dragThreshold ||
  8189. Math.abs(deltaY) > dragThreshold)) {
  8190. this._viewportHasMoved = true;
  8191.  
  8192. this._viewportDragPos = {'x': x, 'y': y};
  8193. this._display.viewportChangePos(deltaX, deltaY);
  8194. }
  8195.  
  8196. // Skip sending mouse events
  8197. return;
  8198. }
  8199.  
  8200. if (this._view_only) { return; } // View only, skip mouse events
  8201.  
  8202. if (this._rfb_connection_state !== 'connected') { return; }
  8203. $$$core$rfb$$RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask);
  8204. },
  8205.  
  8206. // Message Handlers
  8207.  
  8208. _negotiate_protocol_version: function () {
  8209. if (this._sock.rQlen() < 12) {
  8210. return this._fail("Error while negotiating with server",
  8211. "Incomplete protocol version");
  8212. }
  8213.  
  8214. var sversion = this._sock.rQshiftStr(12).substr(4, 7);
  8215. $$$core$util$logging$$.Info("Server ProtocolVersion: " + sversion);
  8216. var is_repeater = 0;
  8217. switch (sversion) {
  8218. case "000.000": // UltraVNC repeater
  8219. is_repeater = 1;
  8220. break;
  8221. case "003.003":
  8222. case "003.006": // UltraVNC
  8223. case "003.889": // Apple Remote Desktop
  8224. this._rfb_version = 3.3;
  8225. break;
  8226. case "003.007":
  8227. this._rfb_version = 3.7;
  8228. break;
  8229. case "003.008":
  8230. case "004.000": // Intel AMT KVM
  8231. case "004.001": // RealVNC 4.6
  8232. case "005.000": // RealVNC 5.3
  8233. this._rfb_version = 3.8;
  8234. break;
  8235. default:
  8236. return this._fail("Unsupported server",
  8237. "Invalid server version: " + sversion);
  8238. }
  8239.  
  8240. if (is_repeater) {
  8241. var repeaterID = this._repeaterID;
  8242. while (repeaterID.length < 250) {
  8243. repeaterID += "\0";
  8244. }
  8245. this._sock.send_string(repeaterID);
  8246. return true;
  8247. }
  8248.  
  8249. if (this._rfb_version > this._rfb_max_version) {
  8250. this._rfb_version = this._rfb_max_version;
  8251. }
  8252.  
  8253. var cversion = "00" + parseInt(this._rfb_version, 10) +
  8254. ".00" + ((this._rfb_version * 10) % 10);
  8255. this._sock.send_string("RFB " + cversion + "\n");
  8256. $$$core$util$logging$$.Debug('Sent ProtocolVersion: ' + cversion);
  8257.  
  8258. this._rfb_init_state = 'Security';
  8259. },
  8260.  
  8261. _negotiate_security: function () {
  8262. // Polyfill since IE and PhantomJS doesn't have
  8263. // TypedArray.includes()
  8264. function includes(item, array) {
  8265. for (var i = 0; i < array.length; i++) {
  8266. if (array[i] === item) {
  8267. return true;
  8268. }
  8269. }
  8270. return false;
  8271. }
  8272.  
  8273. if (this._rfb_version >= 3.7) {
  8274. // Server sends supported list, client decides
  8275. var num_types = this._sock.rQshift8();
  8276. if (this._sock.rQwait("security type", num_types, 1)) { return false; }
  8277.  
  8278. if (num_types === 0) {
  8279. var strlen = this._sock.rQshift32();
  8280. var reason = this._sock.rQshiftStr(strlen);
  8281. return this._fail("Error while negotiating with server",
  8282. "Security failure: " + reason);
  8283. }
  8284.  
  8285. var types = this._sock.rQshiftBytes(num_types);
  8286. $$$core$util$logging$$.Debug("Server security types: " + types);
  8287.  
  8288. // Look for each auth in preferred order
  8289. this._rfb_auth_scheme = 0;
  8290. if (includes(1, types)) {
  8291. this._rfb_auth_scheme = 1; // None
  8292. } else if (includes(22, types)) {
  8293. this._rfb_auth_scheme = 22; // XVP
  8294. } else if (includes(16, types)) {
  8295. this._rfb_auth_scheme = 16; // Tight
  8296. } else if (includes(2, types)) {
  8297. this._rfb_auth_scheme = 2; // VNC Auth
  8298. } else {
  8299. return this._fail("Unsupported server",
  8300. "Unsupported security types: " + types);
  8301. }
  8302.  
  8303. this._sock.send([this._rfb_auth_scheme]);
  8304. } else {
  8305. // Server decides
  8306. if (this._sock.rQwait("security scheme", 4)) { return false; }
  8307. this._rfb_auth_scheme = this._sock.rQshift32();
  8308. }
  8309.  
  8310. this._rfb_init_state = 'Authentication';
  8311. $$$core$util$logging$$.Debug('Authenticating using scheme: ' + this._rfb_auth_scheme);
  8312.  
  8313. return this._init_msg(); // jump to authentication
  8314. },
  8315.  
  8316. // authentication
  8317. _negotiate_xvp_auth: function () {
  8318. var xvp_sep = this._xvp_password_sep;
  8319. var xvp_auth = this._rfb_password.split(xvp_sep);
  8320. if (xvp_auth.length < 3) {
  8321. var msg = 'XVP credentials required (user' + xvp_sep +
  8322. 'target' + xvp_sep + 'password) -- got only ' + this._rfb_password;
  8323. this._onPasswordRequired(this, msg);
  8324. return false;
  8325. }
  8326.  
  8327. var xvp_auth_str = String.fromCharCode(xvp_auth[0].length) +
  8328. String.fromCharCode(xvp_auth[1].length) +
  8329. xvp_auth[0] +
  8330. xvp_auth[1];
  8331. this._sock.send_string(xvp_auth_str);
  8332. this._rfb_password = xvp_auth.slice(2).join(xvp_sep);
  8333. this._rfb_auth_scheme = 2;
  8334. return this._negotiate_authentication();
  8335. },
  8336.  
  8337. _negotiate_std_vnc_auth: function () {
  8338. if (this._rfb_password.length === 0) {
  8339. this._onPasswordRequired(this);
  8340. return false;
  8341. }
  8342.  
  8343. if (this._sock.rQwait("auth challenge", 16)) { return false; }
  8344.  
  8345. // TODO(directxman12): make genDES not require an Array
  8346. var challenge = Array.prototype.slice.call(this._sock.rQshiftBytes(16));
  8347. var response = $$$core$rfb$$RFB.genDES(this._rfb_password, challenge);
  8348. this._sock.send(response);
  8349. this._rfb_init_state = "SecurityResult";
  8350. return true;
  8351. },
  8352.  
  8353. _negotiate_tight_tunnels: function (numTunnels) {
  8354. var clientSupportedTunnelTypes = {
  8355. 0: { vendor: 'TGHT', signature: 'NOTUNNEL' }
  8356. };
  8357. var serverSupportedTunnelTypes = {};
  8358. // receive tunnel capabilities
  8359. for (var i = 0; i < numTunnels; i++) {
  8360. var cap_code = this._sock.rQshift32();
  8361. var cap_vendor = this._sock.rQshiftStr(4);
  8362. var cap_signature = this._sock.rQshiftStr(8);
  8363. serverSupportedTunnelTypes[cap_code] = { vendor: cap_vendor, signature: cap_signature };
  8364. }
  8365.  
  8366. // choose the notunnel type
  8367. if (serverSupportedTunnelTypes[0]) {
  8368. if (serverSupportedTunnelTypes[0].vendor != clientSupportedTunnelTypes[0].vendor ||
  8369. serverSupportedTunnelTypes[0].signature != clientSupportedTunnelTypes[0].signature) {
  8370. return this._fail("Unsupported server",
  8371. "Client's tunnel type had the incorrect " +
  8372. "vendor or signature");
  8373. }
  8374. this._sock.send([0, 0, 0, 0]); // use NOTUNNEL
  8375. return false; // wait until we receive the sub auth count to continue
  8376. } else {
  8377. return this._fail("Unsupported server",
  8378. "Server wanted tunnels, but doesn't support " +
  8379. "the notunnel type");
  8380. }
  8381. },
  8382.  
  8383. _negotiate_tight_auth: function () {
  8384. if (!this._rfb_tightvnc) { // first pass, do the tunnel negotiation
  8385. if (this._sock.rQwait("num tunnels", 4)) { return false; }
  8386. var numTunnels = this._sock.rQshift32();
  8387. if (numTunnels > 0 && this._sock.rQwait("tunnel capabilities", 16 * numTunnels, 4)) { return false; }
  8388.  
  8389. this._rfb_tightvnc = true;
  8390.  
  8391. if (numTunnels > 0) {
  8392. this._negotiate_tight_tunnels(numTunnels);
  8393. return false; // wait until we receive the sub auth to continue
  8394. }
  8395. }
  8396.  
  8397. // second pass, do the sub-auth negotiation
  8398. if (this._sock.rQwait("sub auth count", 4)) { return false; }
  8399. var subAuthCount = this._sock.rQshift32();
  8400. if (subAuthCount === 0) { // empty sub-auth list received means 'no auth' subtype selected
  8401. this._rfb_init_state = 'SecurityResult';
  8402. return true;
  8403. }
  8404.  
  8405. if (this._sock.rQwait("sub auth capabilities", 16 * subAuthCount, 4)) { return false; }
  8406.  
  8407. var clientSupportedTypes = {
  8408. 'STDVNOAUTH__': 1,
  8409. 'STDVVNCAUTH_': 2
  8410. };
  8411.  
  8412. var serverSupportedTypes = [];
  8413.  
  8414. for (var i = 0; i < subAuthCount; i++) {
  8415. var capNum = this._sock.rQshift32();
  8416. var capabilities = this._sock.rQshiftStr(12);
  8417. serverSupportedTypes.push(capabilities);
  8418. }
  8419.  
  8420. for (var authType in clientSupportedTypes) {
  8421. if (serverSupportedTypes.indexOf(authType) != -1) {
  8422. this._sock.send([0, 0, 0, clientSupportedTypes[authType]]);
  8423.  
  8424. switch (authType) {
  8425. case 'STDVNOAUTH__': // no auth
  8426. this._rfb_init_state = 'SecurityResult';
  8427. return true;
  8428. case 'STDVVNCAUTH_': // VNC auth
  8429. this._rfb_auth_scheme = 2;
  8430. return this._init_msg();
  8431. default:
  8432. return this._fail("Unsupported server",
  8433. "Unsupported tiny auth scheme: " +
  8434. authType);
  8435. }
  8436. }
  8437. }
  8438.  
  8439. return this._fail("Unsupported server",
  8440. "No supported sub-auth types!");
  8441. },
  8442.  
  8443. _negotiate_authentication: function () {
  8444. switch (this._rfb_auth_scheme) {
  8445. case 0: // connection failed
  8446. if (this._sock.rQwait("auth reason", 4)) { return false; }
  8447. var strlen = this._sock.rQshift32();
  8448. var reason = this._sock.rQshiftStr(strlen);
  8449. return this._fail("Authentication failure", reason);
  8450.  
  8451. case 1: // no auth
  8452. if (this._rfb_version >= 3.8) {
  8453. this._rfb_init_state = 'SecurityResult';
  8454. return true;
  8455. }
  8456. this._rfb_init_state = 'ClientInitialisation';
  8457. return this._init_msg();
  8458.  
  8459. case 22: // XVP auth
  8460. return this._negotiate_xvp_auth();
  8461.  
  8462. case 2: // VNC authentication
  8463. return this._negotiate_std_vnc_auth();
  8464.  
  8465. case 16: // TightVNC Security Type
  8466. return this._negotiate_tight_auth();
  8467.  
  8468. default:
  8469. return this._fail("Unsupported server",
  8470. "Unsupported auth scheme: " +
  8471. this._rfb_auth_scheme);
  8472. }
  8473. },
  8474.  
  8475. _handle_security_result: function () {
  8476. if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
  8477. switch (this._sock.rQshift32()) {
  8478. case 0: // OK
  8479. this._rfb_init_state = 'ClientInitialisation';
  8480. $$$core$util$logging$$.Debug('Authentication OK');
  8481. return this._init_msg();
  8482. case 1: // failed
  8483. if (this._rfb_version >= 3.8) {
  8484. var length = this._sock.rQshift32();
  8485. if (this._sock.rQwait("SecurityResult reason", length, 8)) { return false; }
  8486. var reason = this._sock.rQshiftStr(length);
  8487. return this._fail("Authentication failure", reason);
  8488. } else {
  8489. return this._fail("Authentication failure");
  8490. }
  8491. return false;
  8492. case 2:
  8493. return this._fail("Too many authentication attempts");
  8494. default:
  8495. return this._fail("Unsupported server",
  8496. "Unknown SecurityResult");
  8497. }
  8498. },
  8499.  
  8500. _negotiate_server_init: function () {
  8501. if (this._sock.rQwait("server initialization", 24)) { return false; }
  8502.  
  8503. /* Screen size */
  8504. this._fb_width = this._sock.rQshift16();
  8505. this._fb_height = this._sock.rQshift16();
  8506. this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4);
  8507.  
  8508. /* PIXEL_FORMAT */
  8509. var bpp = this._sock.rQshift8();
  8510. var depth = this._sock.rQshift8();
  8511. var big_endian = this._sock.rQshift8();
  8512. var true_color = this._sock.rQshift8();
  8513.  
  8514. var red_max = this._sock.rQshift16();
  8515. var green_max = this._sock.rQshift16();
  8516. var blue_max = this._sock.rQshift16();
  8517. var red_shift = this._sock.rQshift8();
  8518. var green_shift = this._sock.rQshift8();
  8519. var blue_shift = this._sock.rQshift8();
  8520. this._sock.rQskipBytes(3); // padding
  8521.  
  8522. // NB(directxman12): we don't want to call any callbacks or print messages until
  8523. // *after* we're past the point where we could backtrack
  8524.  
  8525. /* Connection name/title */
  8526. var name_length = this._sock.rQshift32();
  8527. if (this._sock.rQwait('server init name', name_length, 24)) { return false; }
  8528. this._fb_name = $$util$strings$$decodeUTF8(this._sock.rQshiftStr(name_length));
  8529.  
  8530. if (this._rfb_tightvnc) {
  8531. if (this._sock.rQwait('TightVNC extended server init header', 8, 24 + name_length)) { return false; }
  8532. // In TightVNC mode, ServerInit message is extended
  8533. var numServerMessages = this._sock.rQshift16();
  8534. var numClientMessages = this._sock.rQshift16();
  8535. var numEncodings = this._sock.rQshift16();
  8536. this._sock.rQskipBytes(2); // padding
  8537.  
  8538. var totalMessagesLength = (numServerMessages + numClientMessages + numEncodings) * 16;
  8539. if (this._sock.rQwait('TightVNC extended server init header', totalMessagesLength, 32 + name_length)) { return false; }
  8540.  
  8541. // we don't actually do anything with the capability information that TIGHT sends,
  8542. // so we just skip the all of this.
  8543.  
  8544. // TIGHT server message capabilities
  8545. this._sock.rQskipBytes(16 * numServerMessages);
  8546.  
  8547. // TIGHT client message capabilities
  8548. this._sock.rQskipBytes(16 * numClientMessages);
  8549.  
  8550. // TIGHT encoding capabilities
  8551. this._sock.rQskipBytes(16 * numEncodings);
  8552. }
  8553.  
  8554. // NB(directxman12): these are down here so that we don't run them multiple times
  8555. // if we backtrack
  8556. $$$core$util$logging$$.Info("Screen: " + this._fb_width + "x" + this._fb_height +
  8557. ", bpp: " + bpp + ", depth: " + depth +
  8558. ", big_endian: " + big_endian +
  8559. ", true_color: " + true_color +
  8560. ", red_max: " + red_max +
  8561. ", green_max: " + green_max +
  8562. ", blue_max: " + blue_max +
  8563. ", red_shift: " + red_shift +
  8564. ", green_shift: " + green_shift +
  8565. ", blue_shift: " + blue_shift);
  8566.  
  8567. if (big_endian !== 0) {
  8568. $$$core$util$logging$$.Warn("Server native endian is not little endian");
  8569. }
  8570.  
  8571. if (red_shift !== 16) {
  8572. $$$core$util$logging$$.Warn("Server native red-shift is not 16");
  8573. }
  8574.  
  8575. if (blue_shift !== 0) {
  8576. $$$core$util$logging$$.Warn("Server native blue-shift is not 0");
  8577. }
  8578.  
  8579. // we're past the point where we could backtrack, so it's safe to call this
  8580. this._onDesktopName(this, this._fb_name);
  8581.  
  8582. this._display.resize(this._fb_width, this._fb_height);
  8583. this._onFBResize(this, this._fb_width, this._fb_height);
  8584.  
  8585. if (!this._view_only) { this._keyboard.grab(); }
  8586. if (!this._view_only) { this._mouse.grab(); }
  8587.  
  8588. $$$core$rfb$$RFB.messages.pixelFormat(this._sock, 4, 3, true);
  8589. $$$core$rfb$$RFB.messages.clientEncodings(this._sock, this._encodings, this._local_cursor);
  8590. $$$core$rfb$$RFB.messages.fbUpdateRequest(this._sock, false, 0, 0, this._fb_width, this._fb_height);
  8591.  
  8592. this._timing.fbu_rt_start = (new Date()).getTime();
  8593. this._timing.pixels = 0;
  8594.  
  8595. this._updateConnectionState('connected');
  8596. return true;
  8597. },
  8598.  
  8599. /* RFB protocol initialization states:
  8600. * ProtocolVersion
  8601. * Security
  8602. * Authentication
  8603. * SecurityResult
  8604. * ClientInitialization - not triggered by server message
  8605. * ServerInitialization
  8606. */
  8607. _init_msg: function () {
  8608. switch (this._rfb_init_state) {
  8609. case 'ProtocolVersion':
  8610. return this._negotiate_protocol_version();
  8611.  
  8612. case 'Security':
  8613. return this._negotiate_security();
  8614.  
  8615. case 'Authentication':
  8616. return this._negotiate_authentication();
  8617.  
  8618. case 'SecurityResult':
  8619. return this._handle_security_result();
  8620.  
  8621. case 'ClientInitialisation':
  8622. this._sock.send([this._shared ? 1 : 0]); // ClientInitialisation
  8623. this._rfb_init_state = 'ServerInitialisation';
  8624. return true;
  8625.  
  8626. case 'ServerInitialisation':
  8627. return this._negotiate_server_init();
  8628.  
  8629. default:
  8630. return this._fail("Internal error", "Unknown init state: " +
  8631. this._rfb_init_state);
  8632. }
  8633. },
  8634.  
  8635. _handle_set_colour_map_msg: function () {
  8636. $$$core$util$logging$$.Debug("SetColorMapEntries");
  8637.  
  8638. return this._fail("Protocol error", "Unexpected SetColorMapEntries message");
  8639. },
  8640.  
  8641. _handle_server_cut_text: function () {
  8642. $$$core$util$logging$$.Debug("ServerCutText");
  8643.  
  8644. if (this._sock.rQwait("ServerCutText header", 7, 1)) { return false; }
  8645. this._sock.rQskipBytes(3); // Padding
  8646. var length = this._sock.rQshift32();
  8647. if (this._sock.rQwait("ServerCutText", length, 8)) { return false; }
  8648.  
  8649. var text = this._sock.rQshiftStr(length);
  8650.  
  8651. if (this._view_only) { return true; }
  8652.  
  8653. this._onClipboard(this, text);
  8654.  
  8655. return true;
  8656. },
  8657.  
  8658. _handle_server_fence_msg: function() {
  8659. if (this._sock.rQwait("ServerFence header", 8, 1)) { return false; }
  8660. this._sock.rQskipBytes(3); // Padding
  8661. var flags = this._sock.rQshift32();
  8662. var length = this._sock.rQshift8();
  8663.  
  8664. if (this._sock.rQwait("ServerFence payload", length, 9)) { return false; }
  8665.  
  8666. if (length > 64) {
  8667. $$$core$util$logging$$.Warn("Bad payload length (" + length + ") in fence response");
  8668. length = 64;
  8669. }
  8670.  
  8671. var payload = this._sock.rQshiftStr(length);
  8672.  
  8673. this._supportsFence = true;
  8674.  
  8675. /*
  8676. * Fence flags
  8677. *
  8678. * (1<<0) - BlockBefore
  8679. * (1<<1) - BlockAfter
  8680. * (1<<2) - SyncNext
  8681. * (1<<31) - Request
  8682. */
  8683.  
  8684. if (!(flags & (1<<31))) {
  8685. return this._fail("Internal error",
  8686. "Unexpected fence response");
  8687. }
  8688.  
  8689. // Filter out unsupported flags
  8690. // FIXME: support syncNext
  8691. flags &= (1<<0) | (1<<1);
  8692.  
  8693. // BlockBefore and BlockAfter are automatically handled by
  8694. // the fact that we process each incoming message
  8695. // synchronuosly.
  8696. $$$core$rfb$$RFB.messages.clientFence(this._sock, flags, payload);
  8697.  
  8698. return true;
  8699. },
  8700.  
  8701. _handle_xvp_msg: function () {
  8702. if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; }
  8703. this._sock.rQskip8(); // Padding
  8704. var xvp_ver = this._sock.rQshift8();
  8705. var xvp_msg = this._sock.rQshift8();
  8706.  
  8707. switch (xvp_msg) {
  8708. case 0: // XVP_FAIL
  8709. $$$core$util$logging$$.Error("Operation Failed");
  8710. this._notification("XVP Operation Failed", 'error');
  8711. break;
  8712. case 1: // XVP_INIT
  8713. this._rfb_xvp_ver = xvp_ver;
  8714. $$$core$util$logging$$.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")");
  8715. this._onXvpInit(this._rfb_xvp_ver);
  8716. break;
  8717. default:
  8718. this._fail("Unexpected server message",
  8719. "Illegal server XVP message " + xvp_msg);
  8720. break;
  8721. }
  8722.  
  8723. return true;
  8724. },
  8725.  
  8726. _normal_msg: function () {
  8727. var msg_type;
  8728.  
  8729. if (this._FBU.rects > 0) {
  8730. msg_type = 0;
  8731. } else {
  8732. msg_type = this._sock.rQshift8();
  8733. }
  8734.  
  8735. switch (msg_type) {
  8736. case 0: // FramebufferUpdate
  8737. var ret = this._framebufferUpdate();
  8738. if (ret && !this._enabledContinuousUpdates) {
  8739. $$$core$rfb$$RFB.messages.fbUpdateRequest(this._sock, true, 0, 0,
  8740. this._fb_width, this._fb_height);
  8741. }
  8742. return ret;
  8743.  
  8744. case 1: // SetColorMapEntries
  8745. return this._handle_set_colour_map_msg();
  8746.  
  8747. case 2: // Bell
  8748. $$$core$util$logging$$.Debug("Bell");
  8749. this._onBell(this);
  8750. return true;
  8751.  
  8752. case 3: // ServerCutText
  8753. return this._handle_server_cut_text();
  8754.  
  8755. case 150: // EndOfContinuousUpdates
  8756. var first = !(this._supportsContinuousUpdates);
  8757. this._supportsContinuousUpdates = true;
  8758. this._enabledContinuousUpdates = false;
  8759. if (first) {
  8760. this._enabledContinuousUpdates = true;
  8761. this._updateContinuousUpdates();
  8762. $$$core$util$logging$$.Info("Enabling continuous updates.");
  8763. } else {
  8764. // FIXME: We need to send a framebufferupdaterequest here
  8765. // if we add support for turning off continuous updates
  8766. }
  8767. return true;
  8768.  
  8769. case 248: // ServerFence
  8770. return this._handle_server_fence_msg();
  8771.  
  8772. case 250: // XVP
  8773. return this._handle_xvp_msg();
  8774.  
  8775. default:
  8776. this._fail("Unexpected server message", "Type:" + msg_type);
  8777. $$$core$util$logging$$.Debug("sock.rQslice(0, 30): " + this._sock.rQslice(0, 30));
  8778. return true;
  8779. }
  8780. },
  8781.  
  8782. _onFlush: function() {
  8783. this._flushing = false;
  8784. // Resume processing
  8785. if (this._sock.rQlen() > 0) {
  8786. this._handle_message();
  8787. }
  8788. },
  8789.  
  8790. _framebufferUpdate: function () {
  8791. var ret = true;
  8792. var now;
  8793.  
  8794. if (this._FBU.rects === 0) {
  8795. if (this._sock.rQwait("FBU header", 3, 1)) { return false; }
  8796. this._sock.rQskip8(); // Padding
  8797. this._FBU.rects = this._sock.rQshift16();
  8798. this._FBU.bytes = 0;
  8799. this._timing.cur_fbu = 0;
  8800. if (this._timing.fbu_rt_start > 0) {
  8801. now = (new Date()).getTime();
  8802. $$$core$util$logging$$.Info("First FBU latency: " + (now - this._timing.fbu_rt_start));
  8803. }
  8804.  
  8805. // Make sure the previous frame is fully rendered first
  8806. // to avoid building up an excessive queue
  8807. if (this._display.pending()) {
  8808. this._flushing = true;
  8809. this._display.flush();
  8810. return false;
  8811. }
  8812. }
  8813.  
  8814. while (this._FBU.rects > 0) {
  8815. if (this._rfb_connection_state !== 'connected') { return false; }
  8816.  
  8817. if (this._sock.rQwait("FBU", this._FBU.bytes)) { return false; }
  8818. if (this._FBU.bytes === 0) {
  8819. if (this._sock.rQwait("rect header", 12)) { return false; }
  8820. /* New FramebufferUpdate */
  8821.  
  8822. var hdr = this._sock.rQshiftBytes(12);
  8823. this._FBU.x = (hdr[0] << 8) + hdr[1];
  8824. this._FBU.y = (hdr[2] << 8) + hdr[3];
  8825. this._FBU.width = (hdr[4] << 8) + hdr[5];
  8826. this._FBU.height = (hdr[6] << 8) + hdr[7];
  8827. this._FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) +
  8828. (hdr[10] << 8) + hdr[11], 10);
  8829.  
  8830. this._onFBUReceive(this,
  8831. {'x': this._FBU.x, 'y': this._FBU.y,
  8832. 'width': this._FBU.width, 'height': this._FBU.height,
  8833. 'encoding': this._FBU.encoding,
  8834. 'encodingName': this._encNames[this._FBU.encoding]});
  8835.  
  8836. if (!this._encNames[this._FBU.encoding]) {
  8837. this._fail("Unexpected server message",
  8838. "Unsupported encoding " +
  8839. this._FBU.encoding);
  8840. return false;
  8841. }
  8842. }
  8843.  
  8844. this._timing.last_fbu = (new Date()).getTime();
  8845.  
  8846. ret = this._encHandlers[this._FBU.encoding]();
  8847.  
  8848. now = (new Date()).getTime();
  8849. this._timing.cur_fbu += (now - this._timing.last_fbu);
  8850.  
  8851. if (ret) {
  8852. this._encStats[this._FBU.encoding][0]++;
  8853. this._encStats[this._FBU.encoding][1]++;
  8854. this._timing.pixels += this._FBU.width * this._FBU.height;
  8855. }
  8856.  
  8857. if (this._timing.pixels >= (this._fb_width * this._fb_height)) {
  8858. if ((this._FBU.width === this._fb_width && this._FBU.height === this._fb_height) ||
  8859. this._timing.fbu_rt_start > 0) {
  8860. this._timing.full_fbu_total += this._timing.cur_fbu;
  8861. this._timing.full_fbu_cnt++;
  8862. $$$core$util$logging$$.Info("Timing of full FBU, curr: " +
  8863. this._timing.cur_fbu + ", total: " +
  8864. this._timing.full_fbu_total + ", cnt: " +
  8865. this._timing.full_fbu_cnt + ", avg: " +
  8866. (this._timing.full_fbu_total / this._timing.full_fbu_cnt));
  8867. }
  8868.  
  8869. if (this._timing.fbu_rt_start > 0) {
  8870. var fbu_rt_diff = now - this._timing.fbu_rt_start;
  8871. this._timing.fbu_rt_total += fbu_rt_diff;
  8872. this._timing.fbu_rt_cnt++;
  8873. $$$core$util$logging$$.Info("full FBU round-trip, cur: " +
  8874. fbu_rt_diff + ", total: " +
  8875. this._timing.fbu_rt_total + ", cnt: " +
  8876. this._timing.fbu_rt_cnt + ", avg: " +
  8877. (this._timing.fbu_rt_total / this._timing.fbu_rt_cnt));
  8878. this._timing.fbu_rt_start = 0;
  8879. }
  8880. }
  8881.  
  8882. if (!ret) { return ret; } // need more data
  8883. }
  8884.  
  8885. this._display.flip();
  8886.  
  8887. this._onFBUComplete(this,
  8888. {'x': this._FBU.x, 'y': this._FBU.y,
  8889. 'width': this._FBU.width, 'height': this._FBU.height,
  8890. 'encoding': this._FBU.encoding,
  8891. 'encodingName': this._encNames[this._FBU.encoding]});
  8892.  
  8893. return true; // We finished this FBU
  8894. },
  8895.  
  8896. _updateContinuousUpdates: function() {
  8897. if (!this._enabledContinuousUpdates) { return; }
  8898.  
  8899. $$$core$rfb$$RFB.messages.enableContinuousUpdates(this._sock, true, 0, 0,
  8900. this._fb_width, this._fb_height);
  8901. }
  8902. };
  8903.  
  8904. $$util$properties$$make_properties($$$core$rfb$$RFB, [
  8905. ['target', 'wo', 'dom'], // VNC display rendering Canvas object
  8906. ['focusContainer', 'wo', 'dom'], // DOM element that captures keyboard input
  8907. ['encrypt', 'rw', 'bool'], // Use TLS/SSL/wss encryption
  8908. ['local_cursor', 'rw', 'bool'], // Request locally rendered cursor
  8909. ['shared', 'rw', 'bool'], // Request shared mode
  8910. ['view_only', 'rw', 'bool'], // Disable client mouse/keyboard
  8911. ['xvp_password_sep', 'rw', 'str'], // Separator for XVP password fields
  8912. ['disconnectTimeout', 'rw', 'int'], // Time (s) to wait for disconnection
  8913. ['wsProtocols', 'rw', 'arr'], // Protocols to use in the WebSocket connection
  8914. ['repeaterID', 'rw', 'str'], // [UltraVNC] RepeaterID to connect to
  8915. ['viewportDrag', 'rw', 'bool'], // Move the viewport on mouse drags
  8916.  
  8917. // Callback functions
  8918. ['onUpdateState', 'rw', 'func'], // onUpdateState(rfb, state, oldstate): connection state change
  8919. ['onNotification', 'rw', 'func'], // onNotification(rfb, msg, level, options): notification for the UI
  8920. ['onDisconnected', 'rw', 'func'], // onDisconnected(rfb, reason): disconnection finished
  8921. ['onPasswordRequired', 'rw', 'func'], // onPasswordRequired(rfb, msg): VNC password is required
  8922. ['onClipboard', 'rw', 'func'], // onClipboard(rfb, text): RFB clipboard contents received
  8923. ['onBell', 'rw', 'func'], // onBell(rfb): RFB Bell message received
  8924. ['onFBUReceive', 'rw', 'func'], // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed
  8925. ['onFBUComplete', 'rw', 'func'], // onFBUComplete(rfb, fbu): RFB FBU received and processed
  8926. ['onFBResize', 'rw', 'func'], // onFBResize(rfb, width, height): frame buffer resized
  8927. ['onDesktopName', 'rw', 'func'], // onDesktopName(rfb, name): desktop name received
  8928. ['onXvpInit', 'rw', 'func'] // onXvpInit(version): XVP extensions active for this connection
  8929. ]);
  8930.  
  8931. $$$core$rfb$$RFB.prototype.set_local_cursor = function (cursor) {
  8932. if (!cursor || (cursor in {'0': 1, 'no': 1, 'false': 1})) {
  8933. this._local_cursor = false;
  8934. this._display.disableLocalCursor(); //Only show server-side cursor
  8935. } else {
  8936. if (this._display.get_cursor_uri()) {
  8937. this._local_cursor = true;
  8938. } else {
  8939. $$$core$util$logging$$.Warn("Browser does not support local cursor");
  8940. this._display.disableLocalCursor();
  8941. }
  8942. }
  8943.  
  8944. // Need to send an updated list of encodings if we are connected
  8945. if (this._rfb_connection_state === "connected") {
  8946. $$$core$rfb$$RFB.messages.clientEncodings(this._sock, this._encodings, cursor);
  8947. }
  8948. };
  8949.  
  8950. $$$core$rfb$$RFB.prototype.set_view_only = function (view_only) {
  8951. this._view_only = view_only;
  8952.  
  8953. if (this._rfb_connection_state === "connecting" ||
  8954. this._rfb_connection_state === "connected") {
  8955. if (view_only) {
  8956. this._keyboard.ungrab();
  8957. this._mouse.ungrab();
  8958. } else {
  8959. this._keyboard.grab();
  8960. this._mouse.grab();
  8961. }
  8962. }
  8963. };
  8964.  
  8965. $$$core$rfb$$RFB.prototype.get_display = function () { return this._display; };
  8966. $$$core$rfb$$RFB.prototype.get_keyboard = function () { return this._keyboard; };
  8967. $$$core$rfb$$RFB.prototype.get_mouse = function () { return this._mouse; };
  8968.  
  8969. // Class Methods
  8970. $$$core$rfb$$RFB.messages = {
  8971. keyEvent: function (sock, keysym, down) {
  8972. var buff = sock._sQ;
  8973. var offset = sock._sQlen;
  8974.  
  8975. buff[offset] = 4; // msg-type
  8976. buff[offset + 1] = down;
  8977.  
  8978. buff[offset + 2] = 0;
  8979. buff[offset + 3] = 0;
  8980.  
  8981. buff[offset + 4] = (keysym >> 24);
  8982. buff[offset + 5] = (keysym >> 16);
  8983. buff[offset + 6] = (keysym >> 8);
  8984. buff[offset + 7] = keysym;
  8985.  
  8986. sock._sQlen += 8;
  8987. sock.flush();
  8988. },
  8989.  
  8990. QEMUExtendedKeyEvent: function (sock, keysym, down, keycode) {
  8991. function getRFBkeycode(xt_scancode) {
  8992. var upperByte = (keycode >> 8);
  8993. var lowerByte = (keycode & 0x00ff);
  8994. if (upperByte === 0xe0 && lowerByte < 0x7f) {
  8995. lowerByte = lowerByte | 0x80;
  8996. return lowerByte;
  8997. }
  8998. return xt_scancode;
  8999. }
  9000.  
  9001. var buff = sock._sQ;
  9002. var offset = sock._sQlen;
  9003.  
  9004. buff[offset] = 255; // msg-type
  9005. buff[offset + 1] = 0; // sub msg-type
  9006.  
  9007. buff[offset + 2] = (down >> 8);
  9008. buff[offset + 3] = down;
  9009.  
  9010. buff[offset + 4] = (keysym >> 24);
  9011. buff[offset + 5] = (keysym >> 16);
  9012. buff[offset + 6] = (keysym >> 8);
  9013. buff[offset + 7] = keysym;
  9014.  
  9015. var RFBkeycode = getRFBkeycode(keycode);
  9016.  
  9017. buff[offset + 8] = (RFBkeycode >> 24);
  9018. buff[offset + 9] = (RFBkeycode >> 16);
  9019. buff[offset + 10] = (RFBkeycode >> 8);
  9020. buff[offset + 11] = RFBkeycode;
  9021.  
  9022. sock._sQlen += 12;
  9023. sock.flush();
  9024. },
  9025.  
  9026. pointerEvent: function (sock, x, y, mask) {
  9027. var buff = sock._sQ;
  9028. var offset = sock._sQlen;
  9029.  
  9030. buff[offset] = 5; // msg-type
  9031.  
  9032. buff[offset + 1] = mask;
  9033.  
  9034. buff[offset + 2] = x >> 8;
  9035. buff[offset + 3] = x;
  9036.  
  9037. buff[offset + 4] = y >> 8;
  9038. buff[offset + 5] = y;
  9039.  
  9040. sock._sQlen += 6;
  9041. sock.flush();
  9042. },
  9043.  
  9044. // TODO(directxman12): make this unicode compatible?
  9045. clientCutText: function (sock, text) {
  9046. var buff = sock._sQ;
  9047. var offset = sock._sQlen;
  9048.  
  9049. buff[offset] = 6; // msg-type
  9050.  
  9051. buff[offset + 1] = 0; // padding
  9052. buff[offset + 2] = 0; // padding
  9053. buff[offset + 3] = 0; // padding
  9054.  
  9055. var n = text.length;
  9056.  
  9057. buff[offset + 4] = n >> 24;
  9058. buff[offset + 5] = n >> 16;
  9059. buff[offset + 6] = n >> 8;
  9060. buff[offset + 7] = n;
  9061.  
  9062. for (var i = 0; i < n; i++) {
  9063. buff[offset + 8 + i] = text.charCodeAt(i);
  9064. }
  9065.  
  9066. sock._sQlen += 8 + n;
  9067. sock.flush();
  9068. },
  9069.  
  9070. setDesktopSize: function (sock, width, height, id, flags) {
  9071. var buff = sock._sQ;
  9072. var offset = sock._sQlen;
  9073.  
  9074. buff[offset] = 251; // msg-type
  9075. buff[offset + 1] = 0; // padding
  9076. buff[offset + 2] = width >> 8; // width
  9077. buff[offset + 3] = width;
  9078. buff[offset + 4] = height >> 8; // height
  9079. buff[offset + 5] = height;
  9080.  
  9081. buff[offset + 6] = 1; // number-of-screens
  9082. buff[offset + 7] = 0; // padding
  9083.  
  9084. // screen array
  9085. buff[offset + 8] = id >> 24; // id
  9086. buff[offset + 9] = id >> 16;
  9087. buff[offset + 10] = id >> 8;
  9088. buff[offset + 11] = id;
  9089. buff[offset + 12] = 0; // x-position
  9090. buff[offset + 13] = 0;
  9091. buff[offset + 14] = 0; // y-position
  9092. buff[offset + 15] = 0;
  9093. buff[offset + 16] = width >> 8; // width
  9094. buff[offset + 17] = width;
  9095. buff[offset + 18] = height >> 8; // height
  9096. buff[offset + 19] = height;
  9097. buff[offset + 20] = flags >> 24; // flags
  9098. buff[offset + 21] = flags >> 16;
  9099. buff[offset + 22] = flags >> 8;
  9100. buff[offset + 23] = flags;
  9101.  
  9102. sock._sQlen += 24;
  9103. sock.flush();
  9104. },
  9105.  
  9106. clientFence: function (sock, flags, payload) {
  9107. var buff = sock._sQ;
  9108. var offset = sock._sQlen;
  9109.  
  9110. buff[offset] = 248; // msg-type
  9111.  
  9112. buff[offset + 1] = 0; // padding
  9113. buff[offset + 2] = 0; // padding
  9114. buff[offset + 3] = 0; // padding
  9115.  
  9116. buff[offset + 4] = flags >> 24; // flags
  9117. buff[offset + 5] = flags >> 16;
  9118. buff[offset + 6] = flags >> 8;
  9119. buff[offset + 7] = flags;
  9120.  
  9121. var n = payload.length;
  9122.  
  9123. buff[offset + 8] = n; // length
  9124.  
  9125. for (var i = 0; i < n; i++) {
  9126. buff[offset + 9 + i] = payload.charCodeAt(i);
  9127. }
  9128.  
  9129. sock._sQlen += 9 + n;
  9130. sock.flush();
  9131. },
  9132.  
  9133. enableContinuousUpdates: function (sock, enable, x, y, width, height) {
  9134. var buff = sock._sQ;
  9135. var offset = sock._sQlen;
  9136.  
  9137. buff[offset] = 150; // msg-type
  9138. buff[offset + 1] = enable; // enable-flag
  9139.  
  9140. buff[offset + 2] = x >> 8; // x
  9141. buff[offset + 3] = x;
  9142. buff[offset + 4] = y >> 8; // y
  9143. buff[offset + 5] = y;
  9144. buff[offset + 6] = width >> 8; // width
  9145. buff[offset + 7] = width;
  9146. buff[offset + 8] = height >> 8; // height
  9147. buff[offset + 9] = height;
  9148.  
  9149. sock._sQlen += 10;
  9150. sock.flush();
  9151. },
  9152.  
  9153. pixelFormat: function (sock, bpp, depth, true_color) {
  9154. var buff = sock._sQ;
  9155. var offset = sock._sQlen;
  9156.  
  9157. buff[offset] = 0; // msg-type
  9158.  
  9159. buff[offset + 1] = 0; // padding
  9160. buff[offset + 2] = 0; // padding
  9161. buff[offset + 3] = 0; // padding
  9162.  
  9163. buff[offset + 4] = bpp * 8; // bits-per-pixel
  9164. buff[offset + 5] = depth * 8; // depth
  9165. buff[offset + 6] = 0; // little-endian
  9166. buff[offset + 7] = true_color ? 1 : 0; // true-color
  9167.  
  9168. buff[offset + 8] = 0; // red-max
  9169. buff[offset + 9] = 255; // red-max
  9170.  
  9171. buff[offset + 10] = 0; // green-max
  9172. buff[offset + 11] = 255; // green-max
  9173.  
  9174. buff[offset + 12] = 0; // blue-max
  9175. buff[offset + 13] = 255; // blue-max
  9176.  
  9177. buff[offset + 14] = 16; // red-shift
  9178. buff[offset + 15] = 8; // green-shift
  9179. buff[offset + 16] = 0; // blue-shift
  9180.  
  9181. buff[offset + 17] = 0; // padding
  9182. buff[offset + 18] = 0; // padding
  9183. buff[offset + 19] = 0; // padding
  9184.  
  9185. sock._sQlen += 20;
  9186. sock.flush();
  9187. },
  9188.  
  9189. clientEncodings: function (sock, encodings, local_cursor) {
  9190. var buff = sock._sQ;
  9191. var offset = sock._sQlen;
  9192.  
  9193. buff[offset] = 2; // msg-type
  9194. buff[offset + 1] = 0; // padding
  9195.  
  9196. // offset + 2 and offset + 3 are encoding count
  9197.  
  9198. var i, j = offset + 4, cnt = 0;
  9199. for (i = 0; i < encodings.length; i++) {
  9200. if (encodings[i][0] === "Cursor" && !local_cursor) {
  9201. $$$core$util$logging$$.Debug("Skipping Cursor pseudo-encoding");
  9202. } else {
  9203. var enc = encodings[i][1];
  9204. buff[j] = enc >> 24;
  9205. buff[j + 1] = enc >> 16;
  9206. buff[j + 2] = enc >> 8;
  9207. buff[j + 3] = enc;
  9208.  
  9209. j += 4;
  9210. cnt++;
  9211. }
  9212. }
  9213.  
  9214. buff[offset + 2] = cnt >> 8;
  9215. buff[offset + 3] = cnt;
  9216.  
  9217. sock._sQlen += j - offset;
  9218. sock.flush();
  9219. },
  9220.  
  9221. fbUpdateRequest: function (sock, incremental, x, y, w, h) {
  9222. var buff = sock._sQ;
  9223. var offset = sock._sQlen;
  9224.  
  9225. if (typeof(x) === "undefined") { x = 0; }
  9226. if (typeof(y) === "undefined") { y = 0; }
  9227.  
  9228. buff[offset] = 3; // msg-type
  9229. buff[offset + 1] = incremental ? 1 : 0;
  9230.  
  9231. buff[offset + 2] = (x >> 8) & 0xFF;
  9232. buff[offset + 3] = x & 0xFF;
  9233.  
  9234. buff[offset + 4] = (y >> 8) & 0xFF;
  9235. buff[offset + 5] = y & 0xFF;
  9236.  
  9237. buff[offset + 6] = (w >> 8) & 0xFF;
  9238. buff[offset + 7] = w & 0xFF;
  9239.  
  9240. buff[offset + 8] = (h >> 8) & 0xFF;
  9241. buff[offset + 9] = h & 0xFF;
  9242.  
  9243. sock._sQlen += 10;
  9244. sock.flush();
  9245. }
  9246. };
  9247.  
  9248. $$$core$rfb$$RFB.genDES = function (password, challenge) {
  9249. var passwd = [];
  9250. for (var i = 0; i < password.length; i++) {
  9251. passwd.push(password.charCodeAt(i));
  9252. }
  9253. return (new $$des$$default(passwd)).encrypt(challenge);
  9254. };
  9255.  
  9256. $$$core$rfb$$RFB.encodingHandlers = {
  9257. RAW: function () {
  9258. if (this._FBU.lines === 0) {
  9259. this._FBU.lines = this._FBU.height;
  9260. }
  9261.  
  9262. this._FBU.bytes = this._FBU.width * 4; // at least a line
  9263. if (this._sock.rQwait("RAW", this._FBU.bytes)) { return false; }
  9264. var cur_y = this._FBU.y + (this._FBU.height - this._FBU.lines);
  9265. var curr_height = Math.min(this._FBU.lines,
  9266. Math.floor(this._sock.rQlen() / (this._FBU.width * 4)));
  9267. this._display.blitImage(this._FBU.x, cur_y, this._FBU.width,
  9268. curr_height, this._sock.get_rQ(),
  9269. this._sock.get_rQi());
  9270. this._sock.rQskipBytes(this._FBU.width * curr_height * 4);
  9271. this._FBU.lines -= curr_height;
  9272.  
  9273. if (this._FBU.lines > 0) {
  9274. this._FBU.bytes = this._FBU.width * 4; // At least another line
  9275. } else {
  9276. this._FBU.rects--;
  9277. this._FBU.bytes = 0;
  9278. }
  9279.  
  9280. return true;
  9281. },
  9282.  
  9283. COPYRECT: function () {
  9284. this._FBU.bytes = 4;
  9285. if (this._sock.rQwait("COPYRECT", 4)) { return false; }
  9286. this._display.copyImage(this._sock.rQshift16(), this._sock.rQshift16(),
  9287. this._FBU.x, this._FBU.y, this._FBU.width,
  9288. this._FBU.height);
  9289.  
  9290. this._FBU.rects--;
  9291. this._FBU.bytes = 0;
  9292. return true;
  9293. },
  9294.  
  9295. RRE: function () {
  9296. var color;
  9297. if (this._FBU.subrects === 0) {
  9298. this._FBU.bytes = 4 + 4;
  9299. if (this._sock.rQwait("RRE", 4 + 4)) { return false; }
  9300. this._FBU.subrects = this._sock.rQshift32();
  9301. color = this._sock.rQshiftBytes(4); // Background
  9302. this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, color);
  9303. }
  9304.  
  9305. while (this._FBU.subrects > 0 && this._sock.rQlen() >= (4 + 8)) {
  9306. color = this._sock.rQshiftBytes(4);
  9307. var x = this._sock.rQshift16();
  9308. var y = this._sock.rQshift16();
  9309. var width = this._sock.rQshift16();
  9310. var height = this._sock.rQshift16();
  9311. this._display.fillRect(this._FBU.x + x, this._FBU.y + y, width, height, color);
  9312. this._FBU.subrects--;
  9313. }
  9314.  
  9315. if (this._FBU.subrects > 0) {
  9316. var chunk = Math.min(this._rre_chunk_sz, this._FBU.subrects);
  9317. this._FBU.bytes = (4 + 8) * chunk;
  9318. } else {
  9319. this._FBU.rects--;
  9320. this._FBU.bytes = 0;
  9321. }
  9322.  
  9323. return true;
  9324. },
  9325.  
  9326. HEXTILE: function () {
  9327. var rQ = this._sock.get_rQ();
  9328. var rQi = this._sock.get_rQi();
  9329.  
  9330. if (this._FBU.tiles === 0) {
  9331. this._FBU.tiles_x = Math.ceil(this._FBU.width / 16);
  9332. this._FBU.tiles_y = Math.ceil(this._FBU.height / 16);
  9333. this._FBU.total_tiles = this._FBU.tiles_x * this._FBU.tiles_y;
  9334. this._FBU.tiles = this._FBU.total_tiles;
  9335. }
  9336.  
  9337. while (this._FBU.tiles > 0) {
  9338. this._FBU.bytes = 1;
  9339. if (this._sock.rQwait("HEXTILE subencoding", this._FBU.bytes)) { return false; }
  9340. var subencoding = rQ[rQi]; // Peek
  9341. if (subencoding > 30) { // Raw
  9342. this._fail("Unexpected server message",
  9343. "Illegal hextile subencoding: " + subencoding);
  9344. return false;
  9345. }
  9346.  
  9347. var subrects = 0;
  9348. var curr_tile = this._FBU.total_tiles - this._FBU.tiles;
  9349. var tile_x = curr_tile % this._FBU.tiles_x;
  9350. var tile_y = Math.floor(curr_tile / this._FBU.tiles_x);
  9351. var x = this._FBU.x + tile_x * 16;
  9352. var y = this._FBU.y + tile_y * 16;
  9353. var w = Math.min(16, (this._FBU.x + this._FBU.width) - x);
  9354. var h = Math.min(16, (this._FBU.y + this._FBU.height) - y);
  9355.  
  9356. // Figure out how much we are expecting
  9357. if (subencoding & 0x01) { // Raw
  9358. this._FBU.bytes += w * h * 4;
  9359. } else {
  9360. if (subencoding & 0x02) { // Background
  9361. this._FBU.bytes += 4;
  9362. }
  9363. if (subencoding & 0x04) { // Foreground
  9364. this._FBU.bytes += 4;
  9365. }
  9366. if (subencoding & 0x08) { // AnySubrects
  9367. this._FBU.bytes++; // Since we aren't shifting it off
  9368. if (this._sock.rQwait("hextile subrects header", this._FBU.bytes)) { return false; }
  9369. subrects = rQ[rQi + this._FBU.bytes - 1]; // Peek
  9370. if (subencoding & 0x10) { // SubrectsColoured
  9371. this._FBU.bytes += subrects * (4 + 2);
  9372. } else {
  9373. this._FBU.bytes += subrects * 2;
  9374. }
  9375. }
  9376. }
  9377.  
  9378. if (this._sock.rQwait("hextile", this._FBU.bytes)) { return false; }
  9379.  
  9380. // We know the encoding and have a whole tile
  9381. this._FBU.subencoding = rQ[rQi];
  9382. rQi++;
  9383. if (this._FBU.subencoding === 0) {
  9384. if (this._FBU.lastsubencoding & 0x01) {
  9385. // Weird: ignore blanks are RAW
  9386. $$$core$util$logging$$.Debug(" Ignoring blank after RAW");
  9387. } else {
  9388. this._display.fillRect(x, y, w, h, this._FBU.background);
  9389. }
  9390. } else if (this._FBU.subencoding & 0x01) { // Raw
  9391. this._display.blitImage(x, y, w, h, rQ, rQi);
  9392. rQi += this._FBU.bytes - 1;
  9393. } else {
  9394. if (this._FBU.subencoding & 0x02) { // Background
  9395. this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
  9396. rQi += 4;
  9397. }
  9398. if (this._FBU.subencoding & 0x04) { // Foreground
  9399. this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
  9400. rQi += 4;
  9401. }
  9402.  
  9403. this._display.startTile(x, y, w, h, this._FBU.background);
  9404. if (this._FBU.subencoding & 0x08) { // AnySubrects
  9405. subrects = rQ[rQi];
  9406. rQi++;
  9407.  
  9408. for (var s = 0; s < subrects; s++) {
  9409. var color;
  9410. if (this._FBU.subencoding & 0x10) { // SubrectsColoured
  9411. color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
  9412. rQi += 4;
  9413. } else {
  9414. color = this._FBU.foreground;
  9415. }
  9416. var xy = rQ[rQi];
  9417. rQi++;
  9418. var sx = (xy >> 4);
  9419. var sy = (xy & 0x0f);
  9420.  
  9421. var wh = rQ[rQi];
  9422. rQi++;
  9423. var sw = (wh >> 4) + 1;
  9424. var sh = (wh & 0x0f) + 1;
  9425.  
  9426. this._display.subTile(sx, sy, sw, sh, color);
  9427. }
  9428. }
  9429. this._display.finishTile();
  9430. }
  9431. this._sock.set_rQi(rQi);
  9432. this._FBU.lastsubencoding = this._FBU.subencoding;
  9433. this._FBU.bytes = 0;
  9434. this._FBU.tiles--;
  9435. }
  9436.  
  9437. if (this._FBU.tiles === 0) {
  9438. this._FBU.rects--;
  9439. }
  9440.  
  9441. return true;
  9442. },
  9443.  
  9444. getTightCLength: function (arr) {
  9445. var header = 1, data = 0;
  9446. data += arr[0] & 0x7f;
  9447. if (arr[0] & 0x80) {
  9448. header++;
  9449. data += (arr[1] & 0x7f) << 7;
  9450. if (arr[1] & 0x80) {
  9451. header++;
  9452. data += arr[2] << 14;
  9453. }
  9454. }
  9455. return [header, data];
  9456. },
  9457.  
  9458. display_tight: function (isTightPNG) {
  9459. this._FBU.bytes = 1; // compression-control byte
  9460. if (this._sock.rQwait("TIGHT compression-control", this._FBU.bytes)) { return false; }
  9461.  
  9462. var checksum = function (data) {
  9463. var sum = 0;
  9464. for (var i = 0; i < data.length; i++) {
  9465. sum += data[i];
  9466. if (sum > 65536) sum -= 65536;
  9467. }
  9468. return sum;
  9469. };
  9470.  
  9471. var resetStreams = 0;
  9472. var streamId = -1;
  9473. var decompress = function (data, expected) {
  9474. for (var i = 0; i < 4; i++) {
  9475. if ((resetStreams >> i) & 1) {
  9476. this._FBU.zlibs[i].reset();
  9477. $$$core$util$logging$$.Info("Reset zlib stream " + i);
  9478. }
  9479. }
  9480.  
  9481. //var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0);
  9482. var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected);
  9483. /*if (uncompressed.status !== 0) {
  9484. Log.Error("Invalid data in zlib stream");
  9485. }*/
  9486.  
  9487. //return uncompressed.data;
  9488. return uncompressed;
  9489. }.bind(this);
  9490.  
  9491. var indexedToRGBX2Color = function (data, palette, width, height) {
  9492. // Convert indexed (palette based) image data to RGB
  9493. // TODO: reduce number of calculations inside loop
  9494. var dest = this._destBuff;
  9495. var w = Math.floor((width + 7) / 8);
  9496. var w1 = Math.floor(width / 8);
  9497.  
  9498. /*for (var y = 0; y < height; y++) {
  9499. var b, x, dp, sp;
  9500. var yoffset = y * width;
  9501. var ybitoffset = y * w;
  9502. var xoffset, targetbyte;
  9503. for (x = 0; x < w1; x++) {
  9504. xoffset = yoffset + x * 8;
  9505. targetbyte = data[ybitoffset + x];
  9506. for (b = 7; b >= 0; b--) {
  9507. dp = (xoffset + 7 - b) * 3;
  9508. sp = (targetbyte >> b & 1) * 3;
  9509. dest[dp] = palette[sp];
  9510. dest[dp + 1] = palette[sp + 1];
  9511. dest[dp + 2] = palette[sp + 2];
  9512. }
  9513. }
  9514.  
  9515. xoffset = yoffset + x * 8;
  9516. targetbyte = data[ybitoffset + x];
  9517. for (b = 7; b >= 8 - width % 8; b--) {
  9518. dp = (xoffset + 7 - b) * 3;
  9519. sp = (targetbyte >> b & 1) * 3;
  9520. dest[dp] = palette[sp];
  9521. dest[dp + 1] = palette[sp + 1];
  9522. dest[dp + 2] = palette[sp + 2];
  9523. }
  9524. }*/
  9525.  
  9526. for (var y = 0; y < height; y++) {
  9527. var b, x, dp, sp;
  9528. for (x = 0; x < w1; x++) {
  9529. for (b = 7; b >= 0; b--) {
  9530. dp = (y * width + x * 8 + 7 - b) * 4;
  9531. sp = (data[y * w + x] >> b & 1) * 3;
  9532. dest[dp] = palette[sp];
  9533. dest[dp + 1] = palette[sp + 1];
  9534. dest[dp + 2] = palette[sp + 2];
  9535. dest[dp + 3] = 255;
  9536. }
  9537. }
  9538.  
  9539. for (b = 7; b >= 8 - width % 8; b--) {
  9540. dp = (y * width + x * 8 + 7 - b) * 4;
  9541. sp = (data[y * w + x] >> b & 1) * 3;
  9542. dest[dp] = palette[sp];
  9543. dest[dp + 1] = palette[sp + 1];
  9544. dest[dp + 2] = palette[sp + 2];
  9545. dest[dp + 3] = 255;
  9546. }
  9547. }
  9548.  
  9549. return dest;
  9550. }.bind(this);
  9551.  
  9552. var indexedToRGBX = function (data, palette, width, height) {
  9553. // Convert indexed (palette based) image data to RGB
  9554. var dest = this._destBuff;
  9555. var total = width * height * 4;
  9556. for (var i = 0, j = 0; i < total; i += 4, j++) {
  9557. var sp = data[j] * 3;
  9558. dest[i] = palette[sp];
  9559. dest[i + 1] = palette[sp + 1];
  9560. dest[i + 2] = palette[sp + 2];
  9561. dest[i + 3] = 255;
  9562. }
  9563.  
  9564. return dest;
  9565. }.bind(this);
  9566.  
  9567. var rQi = this._sock.get_rQi();
  9568. var rQ = this._sock.rQwhole();
  9569. var cmode, data;
  9570. var cl_header, cl_data;
  9571.  
  9572. var handlePalette = function () {
  9573. var numColors = rQ[rQi + 2] + 1;
  9574. var paletteSize = numColors * 3;
  9575. this._FBU.bytes += paletteSize;
  9576. if (this._sock.rQwait("TIGHT palette " + cmode, this._FBU.bytes)) { return false; }
  9577.  
  9578. var bpp = (numColors <= 2) ? 1 : 8;
  9579. var rowSize = Math.floor((this._FBU.width * bpp + 7) / 8);
  9580. var raw = false;
  9581. if (rowSize * this._FBU.height < 12) {
  9582. raw = true;
  9583. cl_header = 0;
  9584. cl_data = rowSize * this._FBU.height;
  9585. //clength = [0, rowSize * this._FBU.height];
  9586. } else {
  9587. // begin inline getTightCLength (returning two-item arrays is bad for performance with GC)
  9588. var cl_offset = rQi + 3 + paletteSize;
  9589. cl_header = 1;
  9590. cl_data = 0;
  9591. cl_data += rQ[cl_offset] & 0x7f;
  9592. if (rQ[cl_offset] & 0x80) {
  9593. cl_header++;
  9594. cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
  9595. if (rQ[cl_offset + 1] & 0x80) {
  9596. cl_header++;
  9597. cl_data += rQ[cl_offset + 2] << 14;
  9598. }
  9599. }
  9600. // end inline getTightCLength
  9601. }
  9602.  
  9603. this._FBU.bytes += cl_header + cl_data;
  9604. if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
  9605.  
  9606. // Shift ctl, filter id, num colors, palette entries, and clength off
  9607. this._sock.rQskipBytes(3);
  9608. //var palette = this._sock.rQshiftBytes(paletteSize);
  9609. this._sock.rQshiftTo(this._paletteBuff, paletteSize);
  9610. this._sock.rQskipBytes(cl_header);
  9611.  
  9612. if (raw) {
  9613. data = this._sock.rQshiftBytes(cl_data);
  9614. } else {
  9615. data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height);
  9616. }
  9617.  
  9618. // Convert indexed (palette based) image data to RGB
  9619. var rgbx;
  9620. if (numColors == 2) {
  9621. rgbx = indexedToRGBX2Color(data, this._paletteBuff, this._FBU.width, this._FBU.height);
  9622. this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
  9623. } else {
  9624. rgbx = indexedToRGBX(data, this._paletteBuff, this._FBU.width, this._FBU.height);
  9625. this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
  9626. }
  9627.  
  9628.  
  9629. return true;
  9630. }.bind(this);
  9631.  
  9632. var handleCopy = function () {
  9633. var raw = false;
  9634. var uncompressedSize = this._FBU.width * this._FBU.height * 3;
  9635. if (uncompressedSize < 12) {
  9636. raw = true;
  9637. cl_header = 0;
  9638. cl_data = uncompressedSize;
  9639. } else {
  9640. // begin inline getTightCLength (returning two-item arrays is for peformance with GC)
  9641. var cl_offset = rQi + 1;
  9642. cl_header = 1;
  9643. cl_data = 0;
  9644. cl_data += rQ[cl_offset] & 0x7f;
  9645. if (rQ[cl_offset] & 0x80) {
  9646. cl_header++;
  9647. cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
  9648. if (rQ[cl_offset + 1] & 0x80) {
  9649. cl_header++;
  9650. cl_data += rQ[cl_offset + 2] << 14;
  9651. }
  9652. }
  9653. // end inline getTightCLength
  9654. }
  9655. this._FBU.bytes = 1 + cl_header + cl_data;
  9656. if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
  9657.  
  9658. // Shift ctl, clength off
  9659. this._sock.rQshiftBytes(1 + cl_header);
  9660.  
  9661. if (raw) {
  9662. data = this._sock.rQshiftBytes(cl_data);
  9663. } else {
  9664. data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize);
  9665. }
  9666.  
  9667. this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false);
  9668.  
  9669. return true;
  9670. }.bind(this);
  9671.  
  9672. var ctl = this._sock.rQpeek8();
  9673.  
  9674. // Keep tight reset bits
  9675. resetStreams = ctl & 0xF;
  9676.  
  9677. // Figure out filter
  9678. ctl = ctl >> 4;
  9679. streamId = ctl & 0x3;
  9680.  
  9681. if (ctl === 0x08) cmode = "fill";
  9682. else if (ctl === 0x09) cmode = "jpeg";
  9683. else if (ctl === 0x0A) cmode = "png";
  9684. else if (ctl & 0x04) cmode = "filter";
  9685. else if (ctl < 0x04) cmode = "copy";
  9686. else return this._fail("Unexpected server message",
  9687. "Illegal tight compression received, " +
  9688. "ctl: " + ctl);
  9689.  
  9690. if (isTightPNG && (cmode === "filter" || cmode === "copy")) {
  9691. return this._fail("Unexpected server message",
  9692. "filter/copy received in tightPNG mode");
  9693. }
  9694.  
  9695. switch (cmode) {
  9696. // fill use depth because TPIXELs drop the padding byte
  9697. case "fill": // TPIXEL
  9698. this._FBU.bytes += 3;
  9699. break;
  9700. case "jpeg": // max clength
  9701. this._FBU.bytes += 3;
  9702. break;
  9703. case "png": // max clength
  9704. this._FBU.bytes += 3;
  9705. break;
  9706. case "filter": // filter id + num colors if palette
  9707. this._FBU.bytes += 2;
  9708. break;
  9709. case "copy":
  9710. break;
  9711. }
  9712.  
  9713. if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
  9714.  
  9715. // Determine FBU.bytes
  9716. switch (cmode) {
  9717. case "fill":
  9718. // skip ctl byte
  9719. this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, [rQ[rQi + 3], rQ[rQi + 2], rQ[rQi + 1]], false);
  9720. this._sock.rQskipBytes(4);
  9721. break;
  9722. case "png":
  9723. case "jpeg":
  9724. // begin inline getTightCLength (returning two-item arrays is for peformance with GC)
  9725. var cl_offset = rQi + 1;
  9726. cl_header = 1;
  9727. cl_data = 0;
  9728. cl_data += rQ[cl_offset] & 0x7f;
  9729. if (rQ[cl_offset] & 0x80) {
  9730. cl_header++;
  9731. cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
  9732. if (rQ[cl_offset + 1] & 0x80) {
  9733. cl_header++;
  9734. cl_data += rQ[cl_offset + 2] << 14;
  9735. }
  9736. }
  9737. // end inline getTightCLength
  9738. this._FBU.bytes = 1 + cl_header + cl_data; // ctl + clength size + jpeg-data
  9739. if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
  9740.  
  9741. // We have everything, render it
  9742. this._sock.rQskipBytes(1 + cl_header); // shift off clt + compact length
  9743. data = this._sock.rQshiftBytes(cl_data);
  9744. this._display.imageRect(this._FBU.x, this._FBU.y, "image/" + cmode, data);
  9745. break;
  9746. case "filter":
  9747. var filterId = rQ[rQi + 1];
  9748. if (filterId === 1) {
  9749. if (!handlePalette()) { return false; }
  9750. } else {
  9751. // Filter 0, Copy could be valid here, but servers don't send it as an explicit filter
  9752. // Filter 2, Gradient is valid but not use if jpeg is enabled
  9753. this._fail("Unexpected server message",
  9754. "Unsupported tight subencoding received, " +
  9755. "filter: " + filterId);
  9756. }
  9757. break;
  9758. case "copy":
  9759. if (!handleCopy()) { return false; }
  9760. break;
  9761. }
  9762.  
  9763.  
  9764. this._FBU.bytes = 0;
  9765. this._FBU.rects--;
  9766.  
  9767. return true;
  9768. },
  9769.  
  9770. TIGHT: function () { return this._encHandlers.display_tight(false); },
  9771. TIGHT_PNG: function () { return this._encHandlers.display_tight(true); },
  9772.  
  9773. last_rect: function () {
  9774. this._FBU.rects = 0;
  9775. return true;
  9776. },
  9777.  
  9778. handle_FB_resize: function () {
  9779. this._fb_width = this._FBU.width;
  9780. this._fb_height = this._FBU.height;
  9781. this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4);
  9782. this._display.resize(this._fb_width, this._fb_height);
  9783. this._onFBResize(this, this._fb_width, this._fb_height);
  9784. this._timing.fbu_rt_start = (new Date()).getTime();
  9785. this._updateContinuousUpdates();
  9786.  
  9787. this._FBU.bytes = 0;
  9788. this._FBU.rects -= 1;
  9789. return true;
  9790. },
  9791.  
  9792. ExtendedDesktopSize: function () {
  9793. this._FBU.bytes = 1;
  9794. if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; }
  9795.  
  9796. this._supportsSetDesktopSize = true;
  9797. var number_of_screens = this._sock.rQpeek8();
  9798.  
  9799. this._FBU.bytes = 4 + (number_of_screens * 16);
  9800. if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; }
  9801.  
  9802. this._sock.rQskipBytes(1); // number-of-screens
  9803. this._sock.rQskipBytes(3); // padding
  9804.  
  9805. for (var i = 0; i < number_of_screens; i += 1) {
  9806. // Save the id and flags of the first screen
  9807. if (i === 0) {
  9808. this._screen_id = this._sock.rQshiftBytes(4); // id
  9809. this._sock.rQskipBytes(2); // x-position
  9810. this._sock.rQskipBytes(2); // y-position
  9811. this._sock.rQskipBytes(2); // width
  9812. this._sock.rQskipBytes(2); // height
  9813. this._screen_flags = this._sock.rQshiftBytes(4); // flags
  9814. } else {
  9815. this._sock.rQskipBytes(16);
  9816. }
  9817. }
  9818.  
  9819. /*
  9820. * The x-position indicates the reason for the change:
  9821. *
  9822. * 0 - server resized on its own
  9823. * 1 - this client requested the resize
  9824. * 2 - another client requested the resize
  9825. */
  9826.  
  9827. // We need to handle errors when we requested the resize.
  9828. if (this._FBU.x === 1 && this._FBU.y !== 0) {
  9829. var msg = "";
  9830. // The y-position indicates the status code from the server
  9831. switch (this._FBU.y) {
  9832. case 1:
  9833. msg = "Resize is administratively prohibited";
  9834. break;
  9835. case 2:
  9836. msg = "Out of resources";
  9837. break;
  9838. case 3:
  9839. msg = "Invalid screen layout";
  9840. break;
  9841. default:
  9842. msg = "Unknown reason";
  9843. break;
  9844. }
  9845. this._notification("Server did not accept the resize request: "
  9846. + msg, 'normal');
  9847. return true;
  9848. }
  9849.  
  9850. this._encHandlers.handle_FB_resize();
  9851. return true;
  9852. },
  9853.  
  9854. DesktopSize: function () {
  9855. this._encHandlers.handle_FB_resize();
  9856. return true;
  9857. },
  9858.  
  9859. Cursor: function () {
  9860. $$$core$util$logging$$.Debug(">> set_cursor");
  9861. var x = this._FBU.x; // hotspot-x
  9862. var y = this._FBU.y; // hotspot-y
  9863. var w = this._FBU.width;
  9864. var h = this._FBU.height;
  9865.  
  9866. var pixelslength = w * h * 4;
  9867. var masklength = Math.floor((w + 7) / 8) * h;
  9868.  
  9869. this._FBU.bytes = pixelslength + masklength;
  9870. if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; }
  9871.  
  9872. this._display.changeCursor(this._sock.rQshiftBytes(pixelslength),
  9873. this._sock.rQshiftBytes(masklength),
  9874. x, y, w, h);
  9875.  
  9876. this._FBU.bytes = 0;
  9877. this._FBU.rects--;
  9878.  
  9879. $$$core$util$logging$$.Debug("<< set_cursor");
  9880. return true;
  9881. },
  9882.  
  9883. QEMUExtendedKeyEvent: function () {
  9884. this._FBU.rects--;
  9885.  
  9886. var keyboardEvent = document.createEvent("keyboardEvent");
  9887. if (keyboardEvent.code !== undefined) {
  9888. this._qemuExtKeyEventSupported = true;
  9889. }
  9890. },
  9891.  
  9892. JPEG_quality_lo: function () {
  9893. $$$core$util$logging$$.Error("Server sent jpeg_quality pseudo-encoding");
  9894. },
  9895.  
  9896. compress_lo: function () {
  9897. $$$core$util$logging$$.Error("Server sent compress level pseudo-encoding");
  9898. }
  9899. };
  9900.  
  9901. function $$webutil$$init_logging(level) {
  9902. "use strict";
  9903. if (typeof level !== "undefined") {
  9904. $$$core$util$logging$$init_logging(level);
  9905. } else {
  9906. var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/);
  9907. $$$core$util$logging$$init_logging(param || undefined);
  9908. }
  9909. }
  9910.  
  9911. function $$webutil$$getQueryVar(name, defVal) {
  9912. "use strict";
  9913. var re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
  9914. match = document.location.href.match(re);
  9915. if (typeof defVal === 'undefined') { defVal = null; }
  9916. if (match) {
  9917. return decodeURIComponent(match[1]);
  9918. } else {
  9919. return defVal;
  9920. }
  9921. }
  9922.  
  9923. function $$webutil$$getHashVar(name, defVal) {
  9924. "use strict";
  9925. var re = new RegExp('.*[&#]' + name + '=([^&]*)'),
  9926. match = document.location.hash.match(re);
  9927. if (typeof defVal === 'undefined') { defVal = null; }
  9928. if (match) {
  9929. return decodeURIComponent(match[1]);
  9930. } else {
  9931. return defVal;
  9932. }
  9933. }
  9934.  
  9935. function $$webutil$$getConfigVar(name, defVal) {
  9936. "use strict";
  9937. var val = $$webutil$$getHashVar(name);
  9938. if (val === null) {
  9939. val = $$webutil$$getQueryVar(name, defVal);
  9940. }
  9941. return val;
  9942. }
  9943.  
  9944. function $$webutil$$createCookie(name, value, days) {
  9945. "use strict";
  9946. var date, expires;
  9947. if (days) {
  9948. date = new Date();
  9949. date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
  9950. expires = "; expires=" + date.toGMTString();
  9951. } else {
  9952. expires = "";
  9953. }
  9954.  
  9955. var secure;
  9956. if (document.location.protocol === "https:") {
  9957. secure = "; secure";
  9958. } else {
  9959. secure = "";
  9960. }
  9961. document.cookie = name + "=" + value + expires + "; path=/" + secure;
  9962. }
  9963.  
  9964. function $$webutil$$readCookie(name, defaultValue) {
  9965. "use strict";
  9966. var nameEQ = name + "=",
  9967. ca = document.cookie.split(';');
  9968.  
  9969. for (var i = 0; i < ca.length; i += 1) {
  9970. var c = ca[i];
  9971. while (c.charAt(0) === ' ') { c = c.substring(1, c.length); }
  9972. if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length, c.length); }
  9973. }
  9974. return (typeof defaultValue !== 'undefined') ? defaultValue : null;
  9975. }
  9976.  
  9977. function $$webutil$$eraseCookie(name) {
  9978. "use strict";
  9979. $$webutil$$createCookie(name, "", -1);
  9980. }
  9981.  
  9982. /*
  9983. * Setting handling.
  9984. */
  9985.  
  9986. var $$webutil$$settings = {};
  9987.  
  9988. function $$webutil$$initSettings(callback /*, ...callbackArgs */) {
  9989. "use strict";
  9990. var callbackArgs = Array.prototype.slice.call(arguments, 1);
  9991. if (window.chrome && window.chrome.storage) {
  9992. window.chrome.storage.sync.get(function (cfg) {
  9993. $$webutil$$settings = cfg;
  9994. console.log($$webutil$$settings);
  9995. if (callback) {
  9996. callback.apply(this, callbackArgs);
  9997. }
  9998. });
  9999. } else {
  10000. // No-op
  10001. if (callback) {
  10002. callback.apply(this, callbackArgs);
  10003. }
  10004. }
  10005. }
  10006.  
  10007. function $$webutil$$writeSetting(name, value) {
  10008. "use strict";
  10009. if (window.chrome && window.chrome.storage) {
  10010. //console.log("writeSetting:", name, value);
  10011. if ($$webutil$$settings[name] !== value) {
  10012. $$webutil$$settings[name] = value;
  10013. window.chrome.storage.sync.set($$webutil$$settings);
  10014. }
  10015. } else {
  10016. localStorage.setItem(name, value);
  10017. }
  10018. }
  10019.  
  10020. function $$webutil$$readSetting(name, defaultValue) {
  10021. "use strict";
  10022. var value;
  10023. if (window.chrome && window.chrome.storage) {
  10024. value = $$webutil$$settings[name];
  10025. } else {
  10026. value = localStorage.getItem(name);
  10027. }
  10028. if (typeof value === "undefined") {
  10029. value = null;
  10030. }
  10031. if (value === null && typeof defaultValue !== undefined) {
  10032. return defaultValue;
  10033. } else {
  10034. return value;
  10035. }
  10036. }
  10037.  
  10038. function $$webutil$$eraseSetting(name) {
  10039. "use strict";
  10040. if (window.chrome && window.chrome.storage) {
  10041. window.chrome.storage.sync.remove(name);
  10042. delete $$webutil$$settings[name];
  10043. } else {
  10044. localStorage.removeItem(name);
  10045. }
  10046. }
  10047.  
  10048. function $$webutil$$injectParamIfMissing(path, param, value) {
  10049. // force pretend that we're dealing with a relative path
  10050. // (assume that we wanted an extra if we pass one in)
  10051. path = "/" + path;
  10052.  
  10053. var elem = document.createElement('a');
  10054. elem.href = path;
  10055.  
  10056. var param_eq = encodeURIComponent(param) + "=";
  10057. var query;
  10058. if (elem.search) {
  10059. query = elem.search.slice(1).split('&');
  10060. } else {
  10061. query = [];
  10062. }
  10063.  
  10064. if (!query.some(function (v) { return v.startsWith(param_eq); })) {
  10065. query.push(param_eq + encodeURIComponent(value));
  10066. elem.search = "?" + query.join("&");
  10067. }
  10068.  
  10069. // some browsers (e.g. IE11) may occasionally omit the leading slash
  10070. // in the elem.pathname string. Handle that case gracefully.
  10071. if (elem.pathname.charAt(0) == "/") {
  10072. return elem.pathname.slice(1) + elem.search + elem.hash;
  10073. } else {
  10074. return elem.pathname + elem.search + elem.hash;
  10075. }
  10076. }
  10077.  
  10078. function $$webutil$$fetchJSON(path, resolve, reject) {
  10079. // NB: IE11 doesn't support JSON as a responseType
  10080. const req = new XMLHttpRequest();
  10081. req.open('GET', path);
  10082.  
  10083. req.onload = function () {
  10084. if (req.status === 200) {
  10085. try {
  10086. var resObj = JSON.parse(req.responseText);
  10087. } catch (err) {
  10088. reject(err);
  10089. return;
  10090. }
  10091. resolve(resObj);
  10092. } else {
  10093. reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status));
  10094. }
  10095. };
  10096.  
  10097. req.onerror = function (evt) {
  10098. reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message));
  10099. };
  10100.  
  10101. req.ontimeout = function (evt) {
  10102. reject(new Error("XHR timed out while trying to load '" + path + "'"));
  10103. };
  10104.  
  10105. req.send();
  10106. }
  10107.  
  10108. function $$pve$$PVEUI(UI) {
  10109. this.consoletype = $$webutil$$.getQueryVar('console');
  10110. this.vmid = $$webutil$$.getQueryVar('vmid');
  10111. this.vmname = $$webutil$$.getQueryVar('vmname');
  10112. this.nodename = $$webutil$$.getQueryVar('node');
  10113. this.resize = $$webutil$$.getQueryVar('resize');
  10114. this.lastFBWidth = undefined;
  10115. this.lastFBHeight = undefined;
  10116. this.sizeUpdateTimer = undefined;
  10117. this.UI = UI;
  10118.  
  10119. var baseUrl = '/nodes/' + this.nodename;
  10120. var url;
  10121. var params = { websocket: 1 };
  10122. var title;
  10123.  
  10124. switch (this.consoletype) {
  10125. case 'kvm':
  10126. baseUrl += '/qemu/' + this.vmid;
  10127. url = baseUrl + '/vncproxy';
  10128. title = "VM " + this.vmid;
  10129. if (this.vmname) {
  10130. title += " ('" + this.vmname + "')";
  10131. }
  10132. break;
  10133. case 'lxc':
  10134. baseUrl += '/lxc/' + this.vmid;
  10135. url = baseUrl + '/vncproxy';
  10136. title = "CT " + this.vmid;
  10137. if (this.vmname) {
  10138. title += " ('" + this.vmname + "')";
  10139. }
  10140. break;
  10141. case 'shell':
  10142. url = baseUrl + '/vncshell';
  10143. title = "node '" + this.nodename + "'";
  10144. break;
  10145. case 'upgrade':
  10146. url = baseUrl + '/vncshell';
  10147. params.upgrade = 1;
  10148. title = 'System upgrade on node ' + this.nodename;
  10149. break;
  10150. default:
  10151. throw 'implement me';
  10152. break;
  10153. }
  10154.  
  10155. if (this.resize == 'scale' &&
  10156. (this.consoletype === 'lxc' || this.consoletype === 'shell')) {
  10157. var size = this.getFBSize();
  10158. params.width = size.width;
  10159. params.height = size.height;
  10160. }
  10161.  
  10162. this.baseUrl = baseUrl;
  10163. this.url = url;
  10164. this.params = params;
  10165. document.title = title;
  10166. }
  10167.  
  10168. var $$pve$$default = $$pve$$PVEUI;
  10169.  
  10170. $$pve$$PVEUI.prototype = {
  10171. urlEncode: function(object) {
  10172. var i,value, params = [];
  10173.  
  10174. for (i in object) {
  10175. if (object.hasOwnProperty(i)) {
  10176. value = object[i];
  10177. if (value === undefined) value = '';
  10178. params.push(encodeURIComponent(i) + '=' + encodeURIComponent(String(value)));
  10179. }
  10180. }
  10181.  
  10182. return params.join('&');
  10183. },
  10184.  
  10185. API2Request: function(reqOpts) {
  10186. var me = this;
  10187.  
  10188. reqOpts.method = reqOpts.method || 'GET';
  10189.  
  10190. var xhr = new XMLHttpRequest();
  10191.  
  10192. xhr.onload = function() {
  10193. var scope = reqOpts.scope || this;
  10194. var result;
  10195. var errmsg;
  10196.  
  10197. if (xhr.readyState === 4) {
  10198. var ctype = xhr.getResponseHeader('Content-Type');
  10199. if (xhr.status === 200) {
  10200. if (ctype.match(/application\/json;/)) {
  10201. result = JSON.parse(xhr.responseText);
  10202. } else {
  10203. errmsg = 'got unexpected content type ' + ctype;
  10204. }
  10205. } else {
  10206. errmsg = 'Error ' + xhr.status + ': ' + xhr.statusText;
  10207. }
  10208. } else {
  10209. errmsg = 'Connection error - server offline?';
  10210. }
  10211.  
  10212. if (errmsg !== undefined) {
  10213. if (reqOpts.failure) {
  10214. reqOpts.failure.call(scope, errmsg);
  10215. }
  10216. } else {
  10217. if (reqOpts.success) {
  10218. reqOpts.success.call(scope, result);
  10219. }
  10220. }
  10221. if (reqOpts.callback) {
  10222. reqOpts.callback.call(scope, errmsg === undefined);
  10223. }
  10224. }
  10225.  
  10226. var data = me.urlEncode(reqOpts.params || {});
  10227.  
  10228. if (reqOpts.method === 'GET') {
  10229. xhr.open(reqOpts.method, "/api2/json" + reqOpts.url + '?' + data);
  10230. } else {
  10231. xhr.open(reqOpts.method, "/api2/json" + reqOpts.url);
  10232. }
  10233. xhr.setRequestHeader('Cache-Control', 'no-cache');
  10234. if (reqOpts.method === 'POST' || reqOpts.method === 'PUT') {
  10235. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  10236. xhr.setRequestHeader('CSRFPreventionToken', PVE.CSRFPreventionToken);
  10237. xhr.send(data);
  10238. } else if (reqOpts.method === 'GET') {
  10239. xhr.send();
  10240. } else {
  10241. throw "unknown method";
  10242. }
  10243. },
  10244.  
  10245. pve_detect_migrated_vm: function() {
  10246. var me = this;
  10247. if (me.consoletype === 'kvm') {
  10248. // try to detect migrated VM
  10249. me.API2Request({
  10250. url: '/cluster/resources',
  10251. method: 'GET',
  10252. success: function(result) {
  10253. var list = result.data;
  10254. list.every(function(item) {
  10255. if (item.type === 'qemu' && item.vmid == me.vmid) {
  10256. var url = "?" + me.urlEncode({
  10257. console: me.consoletype,
  10258. novnc: 1,
  10259. vmid: me.vmid,
  10260. vmname: me.vmname,
  10261. node: item.node,
  10262. resize: me.resize
  10263. });
  10264. location.href = url;
  10265. return false; // break
  10266. }
  10267. return true;
  10268. });
  10269. }
  10270. });
  10271. } else if(me.consoletype === 'lxc') {
  10272. // lxc restart migration can take a while,
  10273. // so we need to find out if we are really migrating
  10274. var migrating;
  10275. var check = setInterval(function() {
  10276. if (migrating === undefined ||
  10277. migrating === true) {
  10278. // check (again) if migrating
  10279. me.UI.showStatus('Waiting for connection...', 'warning', 5000);
  10280. me.API2Request({
  10281. url: me.baseUrl + '/config',
  10282. method: 'GET',
  10283. success: function(result) {
  10284. var lock = result.data.lock;
  10285. if (lock == 'migrate') {
  10286. migrating = true;
  10287. me.UI.showStatus('Migration detected, waiting...', 'warning', 5000);
  10288. } else {
  10289. migrating = false;
  10290. }
  10291. },
  10292. failure: function() {
  10293. migrating = false;
  10294. }
  10295. });
  10296. } else {
  10297. // not migrating any more
  10298. me.UI.showStatus('Connection resumed', 'warning');
  10299. clearInterval(check);
  10300. me.API2Request({
  10301. url: '/cluster/resources',
  10302. method: 'GET',
  10303. success: function(result) {
  10304. var list = result.data;
  10305. list.every(function(item) {
  10306. if (item.type === 'lxc' && item.vmid == me.vmid) {
  10307. var url = "?" + me.urlEncode({
  10308. console: me.consoletype,
  10309. novnc: 1,
  10310. vmid: me.vmid,
  10311. vmname: me.vmname,
  10312. node: item.node,
  10313. resize: me.resize
  10314. });
  10315. location.href = url;
  10316. return false; // break
  10317. }
  10318. return true;
  10319. });
  10320. }
  10321. });
  10322. }
  10323. }, 5000);
  10324. }
  10325.  
  10326. },
  10327.  
  10328. pve_vm_command: function(cmd, params, reload) {
  10329. var me = this;
  10330. var baseUrl;
  10331. var confirmMsg = "";
  10332.  
  10333. switch(cmd) {
  10334. case "start":
  10335. reload = 1;
  10336. case "shutdown":
  10337. case "stop":
  10338. case "reset":
  10339. case "suspend":
  10340. case "resume":
  10341. confirmMsg = "Do you really want to " + cmd + " VM/CT {0}?";
  10342. break;
  10343. case "reload":
  10344. location.reload();
  10345. break;
  10346. default:
  10347. throw "implement me " + cmd;
  10348. }
  10349.  
  10350. confirmMsg = confirmMsg.replace('{0}', me.vmid);
  10351.  
  10352. if (confirmMsg !== "" && confirm(confirmMsg) !== true) {
  10353. return;
  10354. }
  10355.  
  10356. me.UI.closePVECommandPanel();
  10357.  
  10358. if (me.consoletype === 'kvm') {
  10359. baseUrl = '/nodes/' + me.nodename + '/qemu/' + me.vmid;
  10360. } else if (me.consoletype === 'lxc') {
  10361. baseUrl = '/nodes/' + me.nodename + '/lxc/' + me.vmid;
  10362. } else {
  10363. throw "unknown VM type";
  10364. }
  10365.  
  10366. me.API2Request({
  10367. params: params,
  10368. url: baseUrl + "/status/" + cmd,
  10369. method: 'POST',
  10370. failure: function(msg) {
  10371. me.UI.showStatus(msg, 'warning');
  10372. },
  10373. success: function() {
  10374. me.UI.showStatus("VM command '" + cmd +"' successful", 'normal');
  10375. if (reload) {
  10376. setTimeout(function() {
  10377. location.reload();
  10378. }, 1000);
  10379. };
  10380. }
  10381. });
  10382. },
  10383.  
  10384. addPVEHandlers: function() {
  10385. var me = this;
  10386. document.getElementById('pve_commands_button')
  10387. .addEventListener('click', me.UI.togglePVECommandPanel);
  10388.  
  10389. // show/hide the buttons
  10390. document.getElementById('noVNC_settings_button')
  10391. .classList.add('noVNC_hidden');
  10392. document.getElementById('noVNC_disconnect_button')
  10393. .classList.add('noVNC_hidden');
  10394. if (me.consoletype === 'kvm') {
  10395. document.getElementById('noVNC_clipboard_button')
  10396. .classList.add('noVNC_hidden');
  10397. }
  10398.  
  10399. if (me.consoletype === 'shell' || me.consoletype === 'upgrade') {
  10400. document.getElementById('pve_commands_button')
  10401. .classList.add('noVNC_hidden');
  10402. }
  10403.  
  10404. // add command logic
  10405. var commandArray = [
  10406. { cmd: 'start', kvm: 1, lxc: 1},
  10407. { cmd: 'stop', kvm: 1, lxc: 1},
  10408. { cmd: 'shutdown', kvm: 1, lxc: 1},
  10409. { cmd: 'suspend', kvm: 1},
  10410. { cmd: 'resume', kvm: 1},
  10411. { cmd: 'reset', kvm: 1},
  10412. { cmd: 'reload', kvm: 1, lxc: 1, shell: 1},
  10413. ];
  10414.  
  10415. commandArray.forEach(function(item) {
  10416. var el = document.getElementById('pve_command_'+item.cmd);
  10417. if (!el) {
  10418. return;
  10419. }
  10420.  
  10421. if (item[me.consoletype] === 1) {
  10422. el.onclick = function() {
  10423. me.pve_vm_command(item.cmd);
  10424. };
  10425. } else {
  10426. el.classList.add('noVNC_hidden');
  10427. }
  10428. });
  10429.  
  10430. //edge/ie11 quirk
  10431. var canvas = document.getElementById('noVNC_canvas');
  10432. canvas.onclick = canvas.focus;
  10433. },
  10434.  
  10435. getFBSize: function() {
  10436. var oh;
  10437. var ow;
  10438.  
  10439. if (window.innerHeight) {
  10440. oh = window.innerHeight;
  10441. ow = window.innerWidth;
  10442. } else if (document.documentElement &&
  10443. document.documentElement.clientHeight) {
  10444. oh = document.documentElement.clientHeight;
  10445. ow = document.documentElement.clientWidth;
  10446. } else if (document.body) {
  10447. oh = document.body.clientHeight;
  10448. ow = document.body.clientWidth;
  10449. } else {
  10450. throw "can't get window size";
  10451. }
  10452.  
  10453. return { width: ow, height: oh };
  10454. },
  10455.  
  10456. pveStart: function(callback) {
  10457. var me = this;
  10458. me.API2Request({
  10459. url: me.url,
  10460. method: 'POST',
  10461. params: me.params,
  10462. success: function(result) {
  10463. var wsparams = me.urlEncode({
  10464. port: result.data.port,
  10465. vncticket: result.data.ticket
  10466. });
  10467.  
  10468. document.getElementById('noVNC_password_input').value = result.data.ticket;
  10469. me.UI.updateSetting('path', 'api2/json' + me.baseUrl + '/vncwebsocket' + "?" + wsparams);
  10470.  
  10471. callback();
  10472. },
  10473. failure: function(msg) {
  10474. me.UI.showStatus(msg, 'error');
  10475. }
  10476. });
  10477. },
  10478.  
  10479. updateFBSize: function(rfb, width, height, clip) {
  10480. var me = this;
  10481. console.log(arguments);
  10482. try {
  10483. // Note: window size must be even number for firefox
  10484. me.lastFBWidth = Math.floor((width + 1)/2)*2;
  10485. me.lastFBHeight = Math.floor((height + 1)/2)*2;
  10486.  
  10487. if (me.sizeUpdateTimer !== undefined) {
  10488. clearInterval(me.sizeUpdateTimer);
  10489. }
  10490. if (clip) return;
  10491.  
  10492. var update_size = function() {
  10493. // we do not want to resize if we are in fullscreen
  10494. if (document.fullscreenElement || // alternative standard method
  10495. document.mozFullScreenElement || // currently working methods
  10496. document.webkitFullscreenElement ||
  10497. document.msFullscreenElement) {
  10498. return;
  10499. }
  10500.  
  10501. var oldsize = me.getFBSize();
  10502. var offsetw = me.lastFBWidth - oldsize.width;
  10503. var offseth = me.lastFBHeight - oldsize.height;
  10504. if (offsetw !== 0 || offseth !== 0) {
  10505. //console.log("try resize by " + offsetw + " " + offseth);
  10506. try {
  10507. window.resizeBy(offsetw, offseth);
  10508. // wait a little an then fix the scrollbars
  10509. // on chrome
  10510. setTimeout(function() {
  10511. me.UI.fixScrollbars();
  10512. }, 100);
  10513. } catch (e) {
  10514. console.log('resizing did not work', e);
  10515. }
  10516. }
  10517. };
  10518.  
  10519. update_size();
  10520. me.sizeUpdateTimer = setInterval(update_size, 1000);
  10521.  
  10522. } catch(e) {
  10523. console.log(e);
  10524. }
  10525. },
  10526. };
  10527.  
  10528. const app$ui$$UI = {
  10529.  
  10530. connected: false,
  10531. desktopName: "",
  10532.  
  10533. resizeTimeout: null,
  10534. statusTimeout: null,
  10535. hideKeyboardTimeout: null,
  10536. idleControlbarTimeout: null,
  10537. closeControlbarTimeout: null,
  10538.  
  10539. controlbarGrabbed: false,
  10540. controlbarDrag: false,
  10541. controlbarMouseDownClientY: 0,
  10542. controlbarMouseDownOffsetY: 0,
  10543.  
  10544. isSafari: false,
  10545. rememberedClipSetting: null,
  10546. lastKeyboardinput: null,
  10547. defaultKeyboardinputLen: 100,
  10548.  
  10549. inhibit_reconnect: true,
  10550. reconnect_callback: null,
  10551. reconnect_password: null,
  10552.  
  10553. prime: function(callback) {
  10554. if (document.readyState === "interactive" || document.readyState === "complete") {
  10555. app$ui$$UI.load(callback);
  10556. } else {
  10557. document.addEventListener('DOMContentLoaded', app$ui$$UI.load.bind(app$ui$$UI, callback));
  10558. }
  10559. },
  10560.  
  10561. // Setup rfb object, load settings from browser storage, then call
  10562. // UI.init to setup the UI/menus
  10563. load: function(callback) {
  10564. $$webutil$$.initSettings(app$ui$$UI.start, callback);
  10565. },
  10566.  
  10567. // Render default UI and initialize settings menu
  10568. start: function(callback) {
  10569.  
  10570. app$ui$$UI.PVE = new $$pve$$default(app$ui$$UI);
  10571. // Setup global variables first
  10572. app$ui$$UI.isSafari = (navigator.userAgent.indexOf('Safari') !== -1 &&
  10573. navigator.userAgent.indexOf('Chrome') === -1);
  10574.  
  10575. app$ui$$UI.initSettings();
  10576.  
  10577. // Translate the DOM
  10578. $$$core$util$localization$$l10n.translateDOM();
  10579.  
  10580. // Adapt the interface for touch screen devices
  10581. if ($$$core$util$browsers$$isTouchDevice) {
  10582. document.documentElement.classList.add("noVNC_touch");
  10583. // Remove the address bar
  10584. setTimeout(function() { window.scrollTo(0, 1); }, 100);
  10585. }
  10586.  
  10587. // Restore control bar position
  10588. if ($$webutil$$.readSetting('controlbar_pos') === 'right') {
  10589. app$ui$$UI.toggleControlbarSide();
  10590. }
  10591.  
  10592. app$ui$$UI.initFullscreen();
  10593.  
  10594. // Setup event handlers
  10595. app$ui$$UI.addResizeHandlers();
  10596. app$ui$$UI.addControlbarHandlers();
  10597. app$ui$$UI.addTouchSpecificHandlers();
  10598. app$ui$$UI.addExtraKeysHandlers();
  10599. app$ui$$UI.addXvpHandlers();
  10600. app$ui$$UI.addConnectionControlHandlers();
  10601. app$ui$$UI.addClipboardHandlers();
  10602. app$ui$$UI.addSettingsHandlers();
  10603.  
  10604. // add pve specific event handlers
  10605. app$ui$$UI.PVE.addPVEHandlers();
  10606. document.getElementById("noVNC_status")
  10607. .addEventListener('click', app$ui$$UI.hideStatus);
  10608.  
  10609. // Bootstrap fallback input handler
  10610. app$ui$$UI.keyboardinputReset();
  10611.  
  10612. app$ui$$UI.openControlbar();
  10613.  
  10614. app$ui$$UI.updateViewClip();
  10615.  
  10616. app$ui$$UI.updateVisualState();
  10617.  
  10618. document.getElementById('noVNC_setting_host').focus();
  10619. document.documentElement.classList.remove("noVNC_loading");
  10620.  
  10621. app$ui$$UI.PVE.pveStart(function() {
  10622. app$ui$$UI.connect();
  10623.  
  10624. if (typeof callback === "function") {
  10625. callback(app$ui$$UI.rfb);
  10626. }
  10627. });
  10628. },
  10629.  
  10630. initFullscreen: function() {
  10631. // Only show the button if fullscreen is properly supported
  10632. // * Safari doesn't support alphanumerical input while in fullscreen
  10633. if (!app$ui$$UI.isSafari &&
  10634. (document.documentElement.requestFullscreen ||
  10635. document.documentElement.mozRequestFullScreen ||
  10636. document.documentElement.webkitRequestFullscreen ||
  10637. document.body.msRequestFullscreen)) {
  10638. document.getElementById('noVNC_fullscreen_button')
  10639. .classList.remove("noVNC_hidden");
  10640. app$ui$$UI.addFullscreenHandlers();
  10641. }
  10642. },
  10643.  
  10644. initSettings: function() {
  10645. var i;
  10646.  
  10647. // Logging selection dropdown
  10648. var llevels = ['error', 'warn', 'info', 'debug'];
  10649. for (i = 0; i < llevels.length; i += 1) {
  10650. app$ui$$UI.addOption(document.getElementById('noVNC_setting_logging'),llevels[i], llevels[i]);
  10651. }
  10652.  
  10653. // Settings with immediate effects
  10654. app$ui$$UI.initSetting('logging', 'warn');
  10655. app$ui$$UI.updateLogging();
  10656.  
  10657. // if port == 80 (or 443) then it won't be present and should be
  10658. // set manually
  10659. var port = window.location.port;
  10660. if (!port) {
  10661. if (window.location.protocol.substring(0,5) == 'https') {
  10662. port = 443;
  10663. }
  10664. else if (window.location.protocol.substring(0,4) == 'http') {
  10665. port = 80;
  10666. }
  10667. }
  10668.  
  10669. /* Populate the controls if defaults are provided in the URL */
  10670. app$ui$$UI.initSetting('host', window.location.hostname);
  10671. app$ui$$UI.initSetting('port', port);
  10672. app$ui$$UI.initSetting('encrypt', true);
  10673. app$ui$$UI.initSetting('cursor', !$$$core$util$browsers$$isTouchDevice);
  10674. app$ui$$UI.initSetting('clip', false);
  10675. // we need updateSetting because
  10676. // otherwise we load from browser storage
  10677. // we want to overwrite the resize mode from url
  10678. var resize = $$webutil$$.getQueryVar('resize');
  10679. app$ui$$UI.updateSetting('resize', resize);
  10680. app$ui$$UI.initSetting('shared', true);
  10681. app$ui$$UI.initSetting('view_only', false);
  10682. app$ui$$UI.initSetting('path', 'websockify');
  10683. app$ui$$UI.initSetting('repeaterID', '');
  10684. app$ui$$UI.initSetting('reconnect', false);
  10685. app$ui$$UI.initSetting('reconnect_delay', 5000);
  10686.  
  10687. app$ui$$UI.setupSettingLabels();
  10688. },
  10689. // Adds a link to the label elements on the corresponding input elements
  10690. setupSettingLabels: function() {
  10691. var labels = document.getElementsByTagName('LABEL');
  10692. for (var i = 0; i < labels.length; i++) {
  10693. var htmlFor = labels[i].htmlFor;
  10694. if (htmlFor != '') {
  10695. var elem = document.getElementById(htmlFor);
  10696. if (elem) elem.label = labels[i];
  10697. } else {
  10698. // If 'for' isn't set, use the first input element child
  10699. var children = labels[i].children;
  10700. for (var j = 0; j < children.length; j++) {
  10701. if (children[j].form !== undefined) {
  10702. children[j].label = labels[i];
  10703. break;
  10704. }
  10705. }
  10706. }
  10707. }
  10708. },
  10709.  
  10710. initRFB: function() {
  10711. try {
  10712. app$ui$$UI.rfb = new $$$core$rfb$$default({'target': document.getElementById('noVNC_canvas'),
  10713. 'onNotification': app$ui$$UI.notification,
  10714. 'onUpdateState': app$ui$$UI.updateState,
  10715. 'onDisconnected': app$ui$$UI.disconnectFinished,
  10716. 'onPasswordRequired': app$ui$$UI.passwordRequired,
  10717. 'onXvpInit': app$ui$$UI.updateXvpButton,
  10718. 'onClipboard': app$ui$$UI.clipboardReceive,
  10719. 'onBell': app$ui$$UI.bell,
  10720. 'onFBUComplete': app$ui$$UI.initialResize,
  10721. 'onFBResize': app$ui$$UI.updateSessionSize,
  10722. 'onDesktopName': app$ui$$UI.updateDesktopName});
  10723. return true;
  10724. } catch (exc) {
  10725. var msg = "Unable to create RFB client -- " + exc;
  10726. $$$core$util$logging$$.Error(msg);
  10727. app$ui$$UI.showStatus(msg, 'error');
  10728. return false;
  10729. }
  10730. },
  10731.  
  10732. /* ------^-------
  10733. * /INIT
  10734. * ==============
  10735. * EVENT HANDLERS
  10736. * ------v------*/
  10737.  
  10738. addResizeHandlers: function() {
  10739. window.addEventListener('resize', app$ui$$UI.applyResizeMode);
  10740. window.addEventListener('resize', app$ui$$UI.updateViewClip);
  10741. },
  10742.  
  10743. addControlbarHandlers: function() {
  10744. document.getElementById("noVNC_control_bar")
  10745. .addEventListener('mousemove', app$ui$$UI.activateControlbar);
  10746. document.getElementById("noVNC_control_bar")
  10747. .addEventListener('mouseup', app$ui$$UI.activateControlbar);
  10748. document.getElementById("noVNC_control_bar")
  10749. .addEventListener('mousedown', app$ui$$UI.activateControlbar);
  10750. document.getElementById("noVNC_control_bar")
  10751. .addEventListener('keypress', app$ui$$UI.activateControlbar);
  10752.  
  10753. document.getElementById("noVNC_control_bar")
  10754. .addEventListener('mousedown', app$ui$$UI.keepControlbar);
  10755. document.getElementById("noVNC_control_bar")
  10756. .addEventListener('keypress', app$ui$$UI.keepControlbar);
  10757.  
  10758. document.getElementById("noVNC_view_drag_button")
  10759. .addEventListener('click', app$ui$$UI.toggleViewDrag);
  10760.  
  10761. document.getElementById("noVNC_control_bar_handle")
  10762. .addEventListener('mousedown', app$ui$$UI.controlbarHandleMouseDown);
  10763. document.getElementById("noVNC_control_bar_handle")
  10764. .addEventListener('mouseup', app$ui$$UI.controlbarHandleMouseUp);
  10765. document.getElementById("noVNC_control_bar_handle")
  10766. .addEventListener('mousemove', app$ui$$UI.dragControlbarHandle);
  10767. // resize events aren't available for elements
  10768. window.addEventListener('resize', app$ui$$UI.updateControlbarHandle);
  10769.  
  10770. var exps = document.getElementsByClassName("noVNC_expander");
  10771. for (var i = 0;i < exps.length;i++) {
  10772. exps[i].addEventListener('click', app$ui$$UI.toggleExpander);
  10773. }
  10774. },
  10775.  
  10776. addTouchSpecificHandlers: function() {
  10777. document.getElementById("noVNC_mouse_button0")
  10778. .addEventListener('click', function () { app$ui$$UI.setMouseButton(1); });
  10779. document.getElementById("noVNC_mouse_button1")
  10780. .addEventListener('click', function () { app$ui$$UI.setMouseButton(2); });
  10781. document.getElementById("noVNC_mouse_button2")
  10782. .addEventListener('click', function () { app$ui$$UI.setMouseButton(4); });
  10783. document.getElementById("noVNC_mouse_button4")
  10784. .addEventListener('click', function () { app$ui$$UI.setMouseButton(0); });
  10785. document.getElementById("noVNC_keyboard_button")
  10786. .addEventListener('click', app$ui$$UI.toggleVirtualKeyboard);
  10787.  
  10788. document.getElementById("noVNC_keyboardinput")
  10789. .addEventListener('input', app$ui$$UI.keyInput);
  10790. document.getElementById("noVNC_keyboardinput")
  10791. .addEventListener('focus', app$ui$$UI.onfocusVirtualKeyboard);
  10792. document.getElementById("noVNC_keyboardinput")
  10793. .addEventListener('blur', app$ui$$UI.onblurVirtualKeyboard);
  10794. document.getElementById("noVNC_keyboardinput")
  10795. .addEventListener('submit', function () { return false; });
  10796.  
  10797. document.documentElement
  10798. .addEventListener('mousedown', app$ui$$UI.keepVirtualKeyboard, true);
  10799.  
  10800. document.getElementById("noVNC_control_bar")
  10801. .addEventListener('touchstart', app$ui$$UI.activateControlbar);
  10802. document.getElementById("noVNC_control_bar")
  10803. .addEventListener('touchmove', app$ui$$UI.activateControlbar);
  10804. document.getElementById("noVNC_control_bar")
  10805. .addEventListener('touchend', app$ui$$UI.activateControlbar);
  10806. document.getElementById("noVNC_control_bar")
  10807. .addEventListener('input', app$ui$$UI.activateControlbar);
  10808.  
  10809. document.getElementById("noVNC_control_bar")
  10810. .addEventListener('touchstart', app$ui$$UI.keepControlbar);
  10811. document.getElementById("noVNC_control_bar")
  10812. .addEventListener('input', app$ui$$UI.keepControlbar);
  10813.  
  10814. document.getElementById("noVNC_control_bar_handle")
  10815. .addEventListener('touchstart', app$ui$$UI.controlbarHandleMouseDown);
  10816. document.getElementById("noVNC_control_bar_handle")
  10817. .addEventListener('touchend', app$ui$$UI.controlbarHandleMouseUp);
  10818. document.getElementById("noVNC_control_bar_handle")
  10819. .addEventListener('touchmove', app$ui$$UI.dragControlbarHandle);
  10820. },
  10821.  
  10822. addExtraKeysHandlers: function() {
  10823. document.getElementById("noVNC_toggle_extra_keys_button")
  10824. .addEventListener('click', app$ui$$UI.toggleExtraKeys);
  10825. document.getElementById("noVNC_toggle_ctrl_button")
  10826. .addEventListener('click', app$ui$$UI.toggleCtrl);
  10827. document.getElementById("noVNC_toggle_alt_button")
  10828. .addEventListener('click', app$ui$$UI.toggleAlt);
  10829. document.getElementById("noVNC_send_tab_button")
  10830. .addEventListener('click', app$ui$$UI.sendTab);
  10831. document.getElementById("noVNC_send_esc_button")
  10832. .addEventListener('click', app$ui$$UI.sendEsc);
  10833. document.getElementById("noVNC_send_ctrl_alt_del_button")
  10834. .addEventListener('click', app$ui$$UI.sendCtrlAltDel);
  10835. },
  10836.  
  10837. addXvpHandlers: function() {
  10838. document.getElementById("noVNC_xvp_shutdown_button")
  10839. .addEventListener('click', function() { app$ui$$UI.rfb.xvpShutdown(); });
  10840. document.getElementById("noVNC_xvp_reboot_button")
  10841. .addEventListener('click', function() { app$ui$$UI.rfb.xvpReboot(); });
  10842. document.getElementById("noVNC_xvp_reset_button")
  10843. .addEventListener('click', function() { app$ui$$UI.rfb.xvpReset(); });
  10844. document.getElementById("noVNC_xvp_button")
  10845. .addEventListener('click', app$ui$$UI.toggleXvpPanel);
  10846. },
  10847.  
  10848. addConnectionControlHandlers: function() {
  10849. document.getElementById("noVNC_disconnect_button")
  10850. .addEventListener('click', app$ui$$UI.disconnect);
  10851. document.getElementById("noVNC_connect_button")
  10852. .addEventListener('click', app$ui$$UI.connect);
  10853. document.getElementById("noVNC_cancel_reconnect_button")
  10854. .addEventListener('click', app$ui$$UI.cancelReconnect);
  10855.  
  10856. document.getElementById("noVNC_password_button")
  10857. .addEventListener('click', app$ui$$UI.setPassword);
  10858. },
  10859.  
  10860. addClipboardHandlers: function() {
  10861. document.getElementById("noVNC_clipboard_button")
  10862. .addEventListener('click', app$ui$$UI.toggleClipboardPanel);
  10863. document.getElementById("noVNC_clipboard_text")
  10864. .addEventListener('focus', app$ui$$UI.displayBlur);
  10865. document.getElementById("noVNC_clipboard_text")
  10866. .addEventListener('blur', app$ui$$UI.displayFocus);
  10867. document.getElementById("noVNC_clipboard_text")
  10868. .addEventListener('change', app$ui$$UI.clipboardSend);
  10869. document.getElementById("noVNC_clipboard_clear_button")
  10870. .addEventListener('click', app$ui$$UI.clipboardClear);
  10871. },
  10872.  
  10873. // Add a call to save settings when the element changes,
  10874. // unless the optional parameter changeFunc is used instead.
  10875. addSettingChangeHandler: function(name, changeFunc) {
  10876. var settingElem = document.getElementById("noVNC_setting_" + name);
  10877. if (changeFunc === undefined) {
  10878. changeFunc = function () { app$ui$$UI.saveSetting(name); };
  10879. }
  10880. settingElem.addEventListener('change', changeFunc);
  10881. },
  10882.  
  10883. addSettingsHandlers: function() {
  10884. document.getElementById("noVNC_settings_button")
  10885. .addEventListener('click', app$ui$$UI.toggleSettingsPanel);
  10886.  
  10887. app$ui$$UI.addSettingChangeHandler('encrypt');
  10888. app$ui$$UI.addSettingChangeHandler('cursor');
  10889. app$ui$$UI.addSettingChangeHandler('cursor', app$ui$$UI.updateLocalCursor);
  10890. app$ui$$UI.addSettingChangeHandler('resize');
  10891. app$ui$$UI.addSettingChangeHandler('resize', app$ui$$UI.enableDisableViewClip);
  10892. app$ui$$UI.addSettingChangeHandler('resize', app$ui$$UI.applyResizeMode);
  10893. app$ui$$UI.addSettingChangeHandler('clip');
  10894. app$ui$$UI.addSettingChangeHandler('clip', app$ui$$UI.updateViewClip);
  10895. app$ui$$UI.addSettingChangeHandler('shared');
  10896. app$ui$$UI.addSettingChangeHandler('view_only');
  10897. app$ui$$UI.addSettingChangeHandler('view_only', app$ui$$UI.updateViewOnly);
  10898. app$ui$$UI.addSettingChangeHandler('host');
  10899. app$ui$$UI.addSettingChangeHandler('port');
  10900. app$ui$$UI.addSettingChangeHandler('path');
  10901. app$ui$$UI.addSettingChangeHandler('repeaterID');
  10902. app$ui$$UI.addSettingChangeHandler('logging');
  10903. app$ui$$UI.addSettingChangeHandler('logging', app$ui$$UI.updateLogging);
  10904. app$ui$$UI.addSettingChangeHandler('reconnect');
  10905. app$ui$$UI.addSettingChangeHandler('reconnect_delay');
  10906. },
  10907.  
  10908. addFullscreenHandlers: function() {
  10909. document.getElementById("noVNC_fullscreen_button")
  10910. .addEventListener('click', app$ui$$UI.toggleFullscreen);
  10911.  
  10912. window.addEventListener('fullscreenchange', app$ui$$UI.updateFullscreenButton);
  10913. window.addEventListener('mozfullscreenchange', app$ui$$UI.updateFullscreenButton);
  10914. window.addEventListener('webkitfullscreenchange', app$ui$$UI.updateFullscreenButton);
  10915. window.addEventListener('msfullscreenchange', app$ui$$UI.updateFullscreenButton);
  10916. },
  10917.  
  10918. /* ------^-------
  10919. * /EVENT HANDLERS
  10920. * ==============
  10921. * VISUAL
  10922. * ------v------*/
  10923.  
  10924. updateState: function(rfb, state, oldstate) {
  10925. var msg;
  10926.  
  10927. document.documentElement.classList.remove("noVNC_connecting");
  10928. document.documentElement.classList.remove("noVNC_connected");
  10929. document.documentElement.classList.remove("noVNC_disconnecting");
  10930. document.documentElement.classList.remove("noVNC_reconnecting");
  10931.  
  10932. switch (state) {
  10933. case 'connecting':
  10934. document.getElementById("noVNC_transition_text").textContent = $$$core$util$localization$$default("Connecting...");
  10935. document.documentElement.classList.add("noVNC_connecting");
  10936. break;
  10937. case 'connected':
  10938. app$ui$$UI.connected = true;
  10939. app$ui$$UI.inhibit_reconnect = false;
  10940. app$ui$$UI.pveAllowMigratedTest = true;
  10941. document.documentElement.classList.add("noVNC_connected");
  10942. if (rfb && rfb.get_encrypt()) {
  10943. msg = $$$core$util$localization$$default("Connected (encrypted) to ") + app$ui$$UI.desktopName;
  10944. } else {
  10945. msg = $$$core$util$localization$$default("Connected (unencrypted) to ") + app$ui$$UI.desktopName;
  10946. }
  10947. app$ui$$UI.showStatus(msg);
  10948. rfb.get_keyboard().set_focused(true);
  10949. document.getElementById("noVNC_canvas").focus();
  10950. break;
  10951. case 'disconnecting':
  10952. app$ui$$UI.connected = false;
  10953. document.getElementById("noVNC_transition_text").textContent = $$$core$util$localization$$default("Disconnecting...");
  10954. document.documentElement.classList.add("noVNC_disconnecting");
  10955. break;
  10956. case 'disconnected':
  10957. app$ui$$UI.showStatus($$$core$util$localization$$default("Disconnected"));
  10958. if (app$ui$$UI.pveAllowMigratedTest === true) {
  10959. app$ui$$UI.pveAllowMigratedTest = false;
  10960. app$ui$$UI.PVE.pve_detect_migrated_vm();
  10961. }
  10962. break;
  10963. default:
  10964. msg = "Invalid UI state";
  10965. $$$core$util$logging$$.Error(msg);
  10966. app$ui$$UI.showStatus(msg, 'error');
  10967. break;
  10968. }
  10969.  
  10970. app$ui$$UI.updateVisualState();
  10971. },
  10972.  
  10973. // Disable/enable controls depending on connection state
  10974. updateVisualState: function() {
  10975. //Log.Debug(">> updateVisualState");
  10976.  
  10977. app$ui$$UI.enableDisableViewClip();
  10978.  
  10979. if ($$$core$util$browsers$$browserSupportsCursorURIs() && !$$$core$util$browsers$$isTouchDevice) {
  10980. app$ui$$UI.enableSetting('cursor');
  10981. } else {
  10982. app$ui$$UI.disableSetting('cursor');
  10983. }
  10984.  
  10985. if (app$ui$$UI.connected) {
  10986. app$ui$$UI.disableSetting('encrypt');
  10987. app$ui$$UI.disableSetting('shared');
  10988. app$ui$$UI.disableSetting('host');
  10989. app$ui$$UI.disableSetting('port');
  10990. app$ui$$UI.disableSetting('path');
  10991. app$ui$$UI.disableSetting('repeaterID');
  10992. app$ui$$UI.updateViewClip();
  10993. app$ui$$UI.setMouseButton(1);
  10994.  
  10995. // Hide the controlbar after 2 seconds
  10996. app$ui$$UI.closeControlbarTimeout = setTimeout(app$ui$$UI.closeControlbar, 2000);
  10997. } else {
  10998. app$ui$$UI.enableSetting('encrypt');
  10999. app$ui$$UI.enableSetting('shared');
  11000. app$ui$$UI.enableSetting('host');
  11001. app$ui$$UI.enableSetting('port');
  11002. app$ui$$UI.enableSetting('path');
  11003. app$ui$$UI.enableSetting('repeaterID');
  11004. app$ui$$UI.updateXvpButton(0);
  11005. app$ui$$UI.keepControlbar();
  11006. }
  11007.  
  11008. // Hide input related buttons in view only mode
  11009. if (app$ui$$UI.rfb && app$ui$$UI.rfb.get_view_only()) {
  11010. document.getElementById('noVNC_keyboard_button')
  11011. .classList.add('noVNC_hidden');
  11012. document.getElementById('noVNC_toggle_extra_keys_button')
  11013. .classList.add('noVNC_hidden');
  11014. } else {
  11015. document.getElementById('noVNC_keyboard_button')
  11016. .classList.remove('noVNC_hidden');
  11017. document.getElementById('noVNC_toggle_extra_keys_button')
  11018. .classList.remove('noVNC_hidden');
  11019. }
  11020.  
  11021. // State change disables viewport dragging.
  11022. // It is enabled (toggled) by direct click on the button
  11023. app$ui$$UI.setViewDrag(false);
  11024.  
  11025. // State change also closes the password dialog
  11026. document.getElementById('noVNC_password_dlg')
  11027. .classList.remove('noVNC_open');
  11028.  
  11029. //Log.Debug("<< updateVisualState");
  11030. },
  11031.  
  11032. showStatus: function(text, status_type, time) {
  11033. var statusElem = document.getElementById('noVNC_status');
  11034.  
  11035. clearTimeout(app$ui$$UI.statusTimeout);
  11036.  
  11037. if (typeof status_type === 'undefined') {
  11038. status_type = 'normal';
  11039. }
  11040.  
  11041. statusElem.classList.remove("noVNC_status_normal");
  11042. statusElem.classList.remove("noVNC_status_warn");
  11043. statusElem.classList.remove("noVNC_status_error");
  11044.  
  11045. switch (status_type) {
  11046. case 'warning':
  11047. case 'warn':
  11048. statusElem.classList.add("noVNC_status_warn");
  11049. break;
  11050. case 'error':
  11051. statusElem.classList.add("noVNC_status_error");
  11052. break;
  11053. case 'normal':
  11054. case 'info':
  11055. default:
  11056. statusElem.classList.add("noVNC_status_normal");
  11057. break;
  11058. }
  11059.  
  11060. statusElem.textContent = text;
  11061. statusElem.classList.add("noVNC_open");
  11062.  
  11063. // If no time was specified, show the status for 1.5 seconds
  11064. if (typeof time === 'undefined') {
  11065. time = 1500;
  11066. }
  11067.  
  11068. // Error messages do not timeout
  11069. if (status_type !== 'error') {
  11070. app$ui$$UI.statusTimeout = window.setTimeout(app$ui$$UI.hideStatus, time);
  11071. }
  11072. },
  11073.  
  11074. hideStatus: function() {
  11075. clearTimeout(app$ui$$UI.statusTimeout);
  11076. document.getElementById('noVNC_status').classList.remove("noVNC_open");
  11077. },
  11078.  
  11079. notification: function (rfb, msg, level, options) {
  11080. app$ui$$UI.showStatus(msg, level);
  11081. },
  11082.  
  11083. activateControlbar: function(event) {
  11084. clearTimeout(app$ui$$UI.idleControlbarTimeout);
  11085. // We manipulate the anchor instead of the actual control
  11086. // bar in order to avoid creating new a stacking group
  11087. document.getElementById('noVNC_control_bar_anchor')
  11088. .classList.remove("noVNC_idle");
  11089. app$ui$$UI.idleControlbarTimeout = window.setTimeout(app$ui$$UI.idleControlbar, 2000);
  11090. },
  11091.  
  11092. idleControlbar: function() {
  11093. document.getElementById('noVNC_control_bar_anchor')
  11094. .classList.add("noVNC_idle");
  11095. },
  11096.  
  11097. keepControlbar: function() {
  11098. clearTimeout(app$ui$$UI.closeControlbarTimeout);
  11099. },
  11100.  
  11101. openControlbar: function() {
  11102. document.getElementById('noVNC_control_bar')
  11103. .classList.add("noVNC_open");
  11104. },
  11105.  
  11106. closeControlbar: function() {
  11107. app$ui$$UI.closeAllPanels();
  11108. document.getElementById('noVNC_control_bar')
  11109. .classList.remove("noVNC_open");
  11110. },
  11111.  
  11112. toggleControlbar: function() {
  11113. if (document.getElementById('noVNC_control_bar')
  11114. .classList.contains("noVNC_open")) {
  11115. app$ui$$UI.closeControlbar();
  11116. } else {
  11117. app$ui$$UI.openControlbar();
  11118. }
  11119. },
  11120.  
  11121. toggleControlbarSide: function () {
  11122. // Temporarily disable animation to avoid weird movement
  11123. var bar = document.getElementById('noVNC_control_bar');
  11124. bar.style.transitionDuration = '0s';
  11125. bar.addEventListener('transitionend', function () { this.style.transitionDuration = ""; });
  11126.  
  11127. var anchor = document.getElementById('noVNC_control_bar_anchor');
  11128. if (anchor.classList.contains("noVNC_right")) {
  11129. $$webutil$$.writeSetting('controlbar_pos', 'left');
  11130. anchor.classList.remove("noVNC_right");
  11131. } else {
  11132. $$webutil$$.writeSetting('controlbar_pos', 'right');
  11133. anchor.classList.add("noVNC_right");
  11134. }
  11135.  
  11136. // Consider this a movement of the handle
  11137. app$ui$$UI.controlbarDrag = true;
  11138. },
  11139.  
  11140. dragControlbarHandle: function (e) {
  11141. if (!app$ui$$UI.controlbarGrabbed) return;
  11142.  
  11143. var ptr = $$$core$util$events$$getPointerEvent(e);
  11144.  
  11145. var anchor = document.getElementById('noVNC_control_bar_anchor');
  11146. if (ptr.clientX < (window.innerWidth * 0.1)) {
  11147. if (anchor.classList.contains("noVNC_right")) {
  11148. app$ui$$UI.toggleControlbarSide();
  11149. }
  11150. } else if (ptr.clientX > (window.innerWidth * 0.9)) {
  11151. if (!anchor.classList.contains("noVNC_right")) {
  11152. app$ui$$UI.toggleControlbarSide();
  11153. }
  11154. }
  11155.  
  11156. if (!app$ui$$UI.controlbarDrag) {
  11157. // The goal is to trigger on a certain physical width, the
  11158. // devicePixelRatio brings us a bit closer but is not optimal.
  11159. var dragThreshold = 10 * (window.devicePixelRatio || 1);
  11160. var dragDistance = Math.abs(ptr.clientY - app$ui$$UI.controlbarMouseDownClientY);
  11161.  
  11162. if (dragDistance < dragThreshold) return;
  11163.  
  11164. app$ui$$UI.controlbarDrag = true;
  11165. }
  11166.  
  11167. var eventY = ptr.clientY - app$ui$$UI.controlbarMouseDownOffsetY;
  11168.  
  11169. app$ui$$UI.moveControlbarHandle(eventY);
  11170.  
  11171. e.preventDefault();
  11172. e.stopPropagation();
  11173. app$ui$$UI.keepControlbar();
  11174. app$ui$$UI.activateControlbar();
  11175. },
  11176.  
  11177. // Move the handle but don't allow any position outside the bounds
  11178. moveControlbarHandle: function (viewportRelativeY) {
  11179. var handle = document.getElementById("noVNC_control_bar_handle");
  11180. var handleHeight = handle.getBoundingClientRect().height;
  11181. var controlbarBounds = document.getElementById("noVNC_control_bar")
  11182. .getBoundingClientRect();
  11183. var margin = 10;
  11184.  
  11185. // These heights need to be non-zero for the below logic to work
  11186. if (handleHeight === 0 || controlbarBounds.height === 0) {
  11187. return;
  11188. }
  11189.  
  11190. var newY = viewportRelativeY;
  11191.  
  11192. // Check if the coordinates are outside the control bar
  11193. if (newY < controlbarBounds.top + margin) {
  11194. // Force coordinates to be below the top of the control bar
  11195. newY = controlbarBounds.top + margin;
  11196.  
  11197. } else if (newY > controlbarBounds.top +
  11198. controlbarBounds.height - handleHeight - margin) {
  11199. // Force coordinates to be above the bottom of the control bar
  11200. newY = controlbarBounds.top +
  11201. controlbarBounds.height - handleHeight - margin;
  11202. }
  11203.  
  11204. // Corner case: control bar too small for stable position
  11205. if (controlbarBounds.height < (handleHeight + margin * 2)) {
  11206. newY = controlbarBounds.top +
  11207. (controlbarBounds.height - handleHeight) / 2;
  11208. }
  11209.  
  11210. // The transform needs coordinates that are relative to the parent
  11211. var parentRelativeY = newY - controlbarBounds.top;
  11212. handle.style.transform = "translateY(" + parentRelativeY + "px)";
  11213. },
  11214.  
  11215. updateControlbarHandle: function () {
  11216. // Since the control bar is fixed on the viewport and not the page,
  11217. // the move function expects coordinates relative the the viewport.
  11218. var handle = document.getElementById("noVNC_control_bar_handle");
  11219. var handleBounds = handle.getBoundingClientRect();
  11220. app$ui$$UI.moveControlbarHandle(handleBounds.top);
  11221. },
  11222.  
  11223. controlbarHandleMouseUp: function(e) {
  11224. if ((e.type == "mouseup") && (e.button != 0)) return;
  11225.  
  11226. // mouseup and mousedown on the same place toggles the controlbar
  11227. if (app$ui$$UI.controlbarGrabbed && !app$ui$$UI.controlbarDrag) {
  11228. app$ui$$UI.toggleControlbar();
  11229. e.preventDefault();
  11230. e.stopPropagation();
  11231. app$ui$$UI.keepControlbar();
  11232. app$ui$$UI.activateControlbar();
  11233. }
  11234. app$ui$$UI.controlbarGrabbed = false;
  11235. },
  11236.  
  11237. controlbarHandleMouseDown: function(e) {
  11238. if ((e.type == "mousedown") && (e.button != 0)) return;
  11239.  
  11240. var ptr = $$$core$util$events$$getPointerEvent(e);
  11241.  
  11242. var handle = document.getElementById("noVNC_control_bar_handle");
  11243. var bounds = handle.getBoundingClientRect();
  11244.  
  11245. // Touch events have implicit capture
  11246. if (e.type === "mousedown") {
  11247. $$$core$util$events$$setCapture(handle);
  11248. }
  11249.  
  11250. app$ui$$UI.controlbarGrabbed = true;
  11251. app$ui$$UI.controlbarDrag = false;
  11252.  
  11253. app$ui$$UI.controlbarMouseDownClientY = ptr.clientY;
  11254. app$ui$$UI.controlbarMouseDownOffsetY = ptr.clientY - bounds.top;
  11255. e.preventDefault();
  11256. e.stopPropagation();
  11257. app$ui$$UI.keepControlbar();
  11258. app$ui$$UI.activateControlbar();
  11259. },
  11260.  
  11261. toggleExpander: function(e) {
  11262. if (this.classList.contains("noVNC_open")) {
  11263. this.classList.remove("noVNC_open");
  11264. } else {
  11265. this.classList.add("noVNC_open");
  11266. }
  11267. },
  11268.  
  11269. /* ------^-------
  11270. * /VISUAL
  11271. * ==============
  11272. * SETTINGS
  11273. * ------v------*/
  11274.  
  11275. // Initial page load read/initialization of settings
  11276. initSetting: function(name, defVal) {
  11277. // Check Query string followed by cookie
  11278. var val = $$webutil$$.getConfigVar(name);
  11279. if (val === null) {
  11280. val = $$webutil$$.readSetting(name, defVal);
  11281. }
  11282. app$ui$$UI.updateSetting(name, val);
  11283. return val;
  11284. },
  11285.  
  11286. // Update cookie and form control setting. If value is not set, then
  11287. // updates from control to current cookie setting.
  11288. updateSetting: function(name, value) {
  11289.  
  11290. // Save the cookie for this session
  11291. if (typeof value !== 'undefined') {
  11292. $$webutil$$.writeSetting(name, value);
  11293. }
  11294.  
  11295. // Update the settings control
  11296. value = app$ui$$UI.getSetting(name);
  11297.  
  11298. var ctrl = document.getElementById('noVNC_setting_' + name);
  11299. if (ctrl.type === 'checkbox') {
  11300. ctrl.checked = value;
  11301.  
  11302. } else if (typeof ctrl.options !== 'undefined') {
  11303. for (var i = 0; i < ctrl.options.length; i += 1) {
  11304. if (ctrl.options[i].value === value) {
  11305. ctrl.selectedIndex = i;
  11306. break;
  11307. }
  11308. }
  11309. } else {
  11310. /*Weird IE9 error leads to 'null' appearring
  11311. in textboxes instead of ''.*/
  11312. if (value === null) {
  11313. value = "";
  11314. }
  11315. ctrl.value = value;
  11316. }
  11317. },
  11318.  
  11319. // Save control setting to cookie
  11320. saveSetting: function(name) {
  11321. var val, ctrl = document.getElementById('noVNC_setting_' + name);
  11322. if (ctrl.type === 'checkbox') {
  11323. val = ctrl.checked;
  11324. } else if (typeof ctrl.options !== 'undefined') {
  11325. val = ctrl.options[ctrl.selectedIndex].value;
  11326. } else {
  11327. val = ctrl.value;
  11328. }
  11329. $$webutil$$.writeSetting(name, val);
  11330. //Log.Debug("Setting saved '" + name + "=" + val + "'");
  11331. return val;
  11332. },
  11333.  
  11334. // Read form control compatible setting from cookie
  11335. getSetting: function(name) {
  11336. var ctrl = document.getElementById('noVNC_setting_' + name);
  11337. var val = $$webutil$$.readSetting(name);
  11338. if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') {
  11339. if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) {
  11340. val = false;
  11341. } else {
  11342. val = true;
  11343. }
  11344. }
  11345. return val;
  11346. },
  11347.  
  11348. // These helpers compensate for the lack of parent-selectors and
  11349. // previous-sibling-selectors in CSS which are needed when we want to
  11350. // disable the labels that belong to disabled input elements.
  11351. disableSetting: function(name) {
  11352. var ctrl = document.getElementById('noVNC_setting_' + name);
  11353. ctrl.disabled = true;
  11354. ctrl.label.classList.add('noVNC_disabled');
  11355. },
  11356.  
  11357. enableSetting: function(name) {
  11358. var ctrl = document.getElementById('noVNC_setting_' + name);
  11359. ctrl.disabled = false;
  11360. ctrl.label.classList.remove('noVNC_disabled');
  11361. },
  11362.  
  11363. /* ------^-------
  11364. * /SETTINGS
  11365. * ==============
  11366. * PANELS
  11367. * ------v------*/
  11368.  
  11369. closeAllPanels: function() {
  11370. app$ui$$UI.closeSettingsPanel();
  11371. app$ui$$UI.closeXvpPanel();
  11372. app$ui$$UI.closeClipboardPanel();
  11373. app$ui$$UI.closeExtraKeys();
  11374. app$ui$$UI.closePVECommandPanel();
  11375. },
  11376.  
  11377. /* ------^-------
  11378. * /PANELS
  11379. * ==============
  11380. * SETTINGS (panel)
  11381. * ------v------*/
  11382.  
  11383. openSettingsPanel: function() {
  11384. app$ui$$UI.closeAllPanels();
  11385. app$ui$$UI.openControlbar();
  11386.  
  11387. // Refresh UI elements from saved cookies
  11388. app$ui$$UI.updateSetting('encrypt');
  11389. if ($$$core$util$browsers$$browserSupportsCursorURIs()) {
  11390. app$ui$$UI.updateSetting('cursor');
  11391. } else {
  11392. app$ui$$UI.updateSetting('cursor', !$$$core$util$browsers$$isTouchDevice);
  11393. app$ui$$UI.disableSetting('cursor');
  11394. }
  11395. app$ui$$UI.updateSetting('clip');
  11396. app$ui$$UI.updateSetting('resize');
  11397. app$ui$$UI.updateSetting('shared');
  11398. app$ui$$UI.updateSetting('view_only');
  11399. app$ui$$UI.updateSetting('path');
  11400. app$ui$$UI.updateSetting('repeaterID');
  11401. app$ui$$UI.updateSetting('logging');
  11402. app$ui$$UI.updateSetting('reconnect');
  11403. app$ui$$UI.updateSetting('reconnect_delay');
  11404.  
  11405. document.getElementById('noVNC_settings')
  11406. .classList.add("noVNC_open");
  11407. document.getElementById('noVNC_settings_button')
  11408. .classList.add("noVNC_selected");
  11409. },
  11410.  
  11411. closeSettingsPanel: function() {
  11412. document.getElementById('noVNC_settings')
  11413. .classList.remove("noVNC_open");
  11414. document.getElementById('noVNC_settings_button')
  11415. .classList.remove("noVNC_selected");
  11416. },
  11417.  
  11418. toggleSettingsPanel: function() {
  11419. if (document.getElementById('noVNC_settings')
  11420. .classList.contains("noVNC_open")) {
  11421. app$ui$$UI.closeSettingsPanel();
  11422. } else {
  11423. app$ui$$UI.openSettingsPanel();
  11424. }
  11425. },
  11426.  
  11427. /* ------^-------
  11428. * /SETTINGS
  11429. * ==============
  11430. * XVP
  11431. * ------v------*/
  11432.  
  11433. openXvpPanel: function() {
  11434. app$ui$$UI.closeAllPanels();
  11435. app$ui$$UI.openControlbar();
  11436.  
  11437. document.getElementById('noVNC_xvp')
  11438. .classList.add("noVNC_open");
  11439. document.getElementById('noVNC_xvp_button')
  11440. .classList.add("noVNC_selected");
  11441. },
  11442.  
  11443. closeXvpPanel: function() {
  11444. document.getElementById('noVNC_xvp')
  11445. .classList.remove("noVNC_open");
  11446. document.getElementById('noVNC_xvp_button')
  11447. .classList.remove("noVNC_selected");
  11448. },
  11449.  
  11450. toggleXvpPanel: function() {
  11451. if (document.getElementById('noVNC_xvp')
  11452. .classList.contains("noVNC_open")) {
  11453. app$ui$$UI.closeXvpPanel();
  11454. } else {
  11455. app$ui$$UI.openXvpPanel();
  11456. }
  11457. },
  11458.  
  11459. // Disable/enable XVP button
  11460. updateXvpButton: function(ver) {
  11461. if (ver >= 1 && !app$ui$$UI.rfb.get_view_only()) {
  11462. document.getElementById('noVNC_xvp_button')
  11463. .classList.remove("noVNC_hidden");
  11464. } else {
  11465. document.getElementById('noVNC_xvp_button')
  11466. .classList.add("noVNC_hidden");
  11467. // Close XVP panel if open
  11468. app$ui$$UI.closeXvpPanel();
  11469. }
  11470. },
  11471.  
  11472. /* ------^-------
  11473. * /XVP
  11474. * ==============
  11475. * CLIPBOARD
  11476. * ------v------*/
  11477.  
  11478. openClipboardPanel: function() {
  11479. app$ui$$UI.closeAllPanels();
  11480. app$ui$$UI.openControlbar();
  11481.  
  11482. document.getElementById('noVNC_clipboard')
  11483. .classList.add("noVNC_open");
  11484. document.getElementById('noVNC_clipboard_button')
  11485. .classList.add("noVNC_selected");
  11486. },
  11487.  
  11488. closeClipboardPanel: function() {
  11489. document.getElementById('noVNC_clipboard')
  11490. .classList.remove("noVNC_open");
  11491. document.getElementById('noVNC_clipboard_button')
  11492. .classList.remove("noVNC_selected");
  11493. },
  11494.  
  11495. toggleClipboardPanel: function() {
  11496. if (document.getElementById('noVNC_clipboard')
  11497. .classList.contains("noVNC_open")) {
  11498. app$ui$$UI.closeClipboardPanel();
  11499. } else {
  11500. app$ui$$UI.openClipboardPanel();
  11501. }
  11502. },
  11503.  
  11504. clipboardReceive: function(rfb, text) {
  11505. $$$core$util$logging$$.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "...");
  11506. document.getElementById('noVNC_clipboard_text').value = text;
  11507. $$$core$util$logging$$.Debug("<< UI.clipboardReceive");
  11508. },
  11509.  
  11510. clipboardClear: function() {
  11511. document.getElementById('noVNC_clipboard_text').value = "";
  11512. app$ui$$UI.rfb.clipboardPasteFrom("");
  11513. },
  11514.  
  11515. clipboardSend: function() {
  11516. var text = document.getElementById('noVNC_clipboard_text').value;
  11517. $$$core$util$logging$$.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "...");
  11518. app$ui$$UI.rfb.clipboardPasteFrom(text);
  11519. $$$core$util$logging$$.Debug("<< UI.clipboardSend");
  11520. },
  11521.  
  11522. /* ------^-------
  11523. * /CLIPBOARD
  11524. * ==============
  11525. * CONNECTION
  11526. * ------v------*/
  11527.  
  11528. openConnectPanel: function() {
  11529. document.getElementById('noVNC_connect_dlg')
  11530. .classList.add("noVNC_open");
  11531. },
  11532.  
  11533. closeConnectPanel: function() {
  11534. document.getElementById('noVNC_connect_dlg')
  11535. .classList.remove("noVNC_open");
  11536. },
  11537.  
  11538. connect: function(event, password) {
  11539. var host = app$ui$$UI.getSetting('host');
  11540. var port = app$ui$$UI.getSetting('port');
  11541. var path = app$ui$$UI.getSetting('path');
  11542.  
  11543. if (typeof password === 'undefined') {
  11544. password = $$webutil$$.getConfigVar('password');
  11545. }
  11546.  
  11547. var password = document.getElementById('noVNC_password_input').value;
  11548.  
  11549. if (!password) {
  11550. password = $$webutil$$.getConfigVar('password');
  11551. }
  11552.  
  11553. if (password === null) {
  11554. password = undefined;
  11555. }
  11556.  
  11557. if ((!host) || (!port)) {
  11558. var msg = $$$core$util$localization$$default("Must set host and port");
  11559. $$$core$util$logging$$.Error(msg);
  11560. app$ui$$UI.showStatus(msg, 'error');
  11561. return;
  11562. }
  11563.  
  11564. if (!app$ui$$UI.initRFB()) return;
  11565.  
  11566. app$ui$$UI.closeAllPanels();
  11567. app$ui$$UI.closeConnectPanel();
  11568.  
  11569. app$ui$$UI.rfb.set_encrypt(app$ui$$UI.getSetting('encrypt'));
  11570. app$ui$$UI.rfb.set_shared(app$ui$$UI.getSetting('shared'));
  11571. app$ui$$UI.rfb.set_repeaterID(app$ui$$UI.getSetting('repeaterID'));
  11572.  
  11573. app$ui$$UI.updateLocalCursor();
  11574. app$ui$$UI.updateViewOnly();
  11575.  
  11576. app$ui$$UI.rfb.connect(host, port, password, path);
  11577. },
  11578.  
  11579. disconnect: function() {
  11580. app$ui$$UI.closeAllPanels();
  11581. app$ui$$UI.rfb.disconnect();
  11582.  
  11583. // Disable automatic reconnecting
  11584. app$ui$$UI.inhibit_reconnect = true;
  11585.  
  11586. // Restore the callback used for initial resize
  11587. app$ui$$UI.rfb.set_onFBUComplete(app$ui$$UI.initialResize);
  11588.  
  11589. // Don't display the connection settings until we're actually disconnected
  11590. },
  11591.  
  11592. reconnect: function() {
  11593. app$ui$$UI.reconnect_callback = null;
  11594.  
  11595. // if reconnect has been disabled in the meantime, do nothing.
  11596. if (app$ui$$UI.inhibit_reconnect) {
  11597. return;
  11598. }
  11599.  
  11600. app$ui$$UI.connect(null, app$ui$$UI.reconnect_password);
  11601. },
  11602.  
  11603. disconnectFinished: function (rfb, reason) {
  11604. if (typeof reason !== 'undefined') {
  11605. app$ui$$UI.showStatus(reason, 'error');
  11606. } else if (app$ui$$UI.getSetting('reconnect', false) === true && !app$ui$$UI.inhibit_reconnect) {
  11607. document.getElementById("noVNC_transition_text").textContent = $$$core$util$localization$$default("Reconnecting...");
  11608. document.documentElement.classList.add("noVNC_reconnecting");
  11609.  
  11610. var delay = parseInt(app$ui$$UI.getSetting('reconnect_delay'));
  11611. app$ui$$UI.reconnect_callback = setTimeout(app$ui$$UI.reconnect, delay);
  11612. return;
  11613. }
  11614.  
  11615. app$ui$$UI.openControlbar();
  11616. app$ui$$UI.openConnectPanel();
  11617. },
  11618.  
  11619. cancelReconnect: function() {
  11620. if (app$ui$$UI.reconnect_callback !== null) {
  11621. clearTimeout(app$ui$$UI.reconnect_callback);
  11622. app$ui$$UI.reconnect_callback = null;
  11623. }
  11624.  
  11625. document.documentElement.classList.remove("noVNC_reconnecting");
  11626. app$ui$$UI.openControlbar();
  11627. app$ui$$UI.openConnectPanel();
  11628. },
  11629.  
  11630. /* ------^-------
  11631. * /CONNECTION
  11632. * ==============
  11633. * PASSWORD
  11634. * ------v------*/
  11635.  
  11636. passwordRequired: function(rfb, msg) {
  11637.  
  11638. document.getElementById('noVNC_password_dlg')
  11639. .classList.add('noVNC_open');
  11640.  
  11641. setTimeout(function () {
  11642. document.getElementById('noVNC_password_input').focus();
  11643. }, 100);
  11644.  
  11645. if (typeof msg === 'undefined') {
  11646. msg = $$$core$util$localization$$default("Password is required");
  11647. }
  11648. $$$core$util$logging$$.Warn(msg);
  11649. app$ui$$UI.showStatus(msg, "warning");
  11650. },
  11651.  
  11652. setPassword: function(e) {
  11653. var password = document.getElementById('noVNC_password_input').value;
  11654. app$ui$$UI.rfb.sendPassword(password);
  11655. app$ui$$UI.reconnect_password = password;
  11656. document.getElementById('noVNC_password_dlg')
  11657. .classList.remove('noVNC_open');
  11658. // Prevent actually submitting the form
  11659. e.preventDefault();
  11660. },
  11661.  
  11662. /* ------^-------
  11663. * /PASSWORD
  11664. * ==============
  11665. * FULLSCREEN
  11666. * ------v------*/
  11667.  
  11668. toggleFullscreen: function() {
  11669. if (document.fullscreenElement || // alternative standard method
  11670. document.mozFullScreenElement || // currently working methods
  11671. document.webkitFullscreenElement ||
  11672. document.msFullscreenElement) {
  11673. if (document.exitFullscreen) {
  11674. document.exitFullscreen();
  11675. } else if (document.mozCancelFullScreen) {
  11676. document.mozCancelFullScreen();
  11677. } else if (document.webkitExitFullscreen) {
  11678. document.webkitExitFullscreen();
  11679. } else if (document.msExitFullscreen) {
  11680. document.msExitFullscreen();
  11681. }
  11682.  
  11683. // when changing from fullscreen to window,
  11684. // re enable auto resize
  11685. if ($$webutil$$.getQueryVar('resize') === null) {
  11686. app$ui$$UI.updateSetting('resize', null);
  11687. setTimeout(function() {
  11688. app$ui$$UI.fixScrollbars();
  11689. }, 100);
  11690. }
  11691. } else {
  11692. if (document.documentElement.requestFullscreen) {
  11693. document.documentElement.requestFullscreen();
  11694. } else if (document.documentElement.mozRequestFullScreen) {
  11695. document.documentElement.mozRequestFullScreen();
  11696. } else if (document.documentElement.webkitRequestFullscreen) {
  11697. document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  11698. } else if (document.body.msRequestFullscreen) {
  11699. document.body.msRequestFullscreen();
  11700. }
  11701. // we want scaling in fullscreen mode
  11702. app$ui$$UI.updateSetting('resize', 'scale');
  11703. }
  11704. app$ui$$UI.enableDisableViewClip();
  11705. app$ui$$UI.updateFullscreenButton();
  11706. },
  11707.  
  11708. updateFullscreenButton: function() {
  11709. if (document.fullscreenElement || // alternative standard method
  11710. document.mozFullScreenElement || // currently working methods
  11711. document.webkitFullscreenElement ||
  11712. document.msFullscreenElement ) {
  11713. document.getElementById('noVNC_fullscreen_button')
  11714. .classList.add("noVNC_selected");
  11715. } else {
  11716. document.getElementById('noVNC_fullscreen_button')
  11717. .classList.remove("noVNC_selected");
  11718. }
  11719. },
  11720.  
  11721. /* ------^-------
  11722. * /FULLSCREEN
  11723. * ==============
  11724. * RESIZE
  11725. * ------v------*/
  11726.  
  11727. // Apply remote resizing or local scaling
  11728. applyResizeMode: function() {
  11729. if (!app$ui$$UI.rfb) return;
  11730.  
  11731. var screen = app$ui$$UI.screenSize();
  11732.  
  11733. if (screen && app$ui$$UI.connected && app$ui$$UI.rfb.get_display()) {
  11734.  
  11735. var display = app$ui$$UI.rfb.get_display();
  11736. var resizeMode = app$ui$$UI.getSetting('resize');
  11737. display.set_scale(1);
  11738.  
  11739. // Make sure the viewport is adjusted first
  11740. app$ui$$UI.updateViewClip();
  11741.  
  11742. if (resizeMode === 'remote') {
  11743.  
  11744. // Request changing the resolution of the remote display to
  11745. // the size of the local browser viewport.
  11746.  
  11747. // In order to not send multiple requests before the browser-resize
  11748. // is finished we wait 0.5 seconds before sending the request.
  11749. clearTimeout(app$ui$$UI.resizeTimeout);
  11750. app$ui$$UI.resizeTimeout = setTimeout(function(){
  11751. // Request a remote size covering the viewport
  11752. if (app$ui$$UI.rfb.requestDesktopSize(screen.w, screen.h)) {
  11753. $$$core$util$logging$$.Debug('Requested new desktop size: ' +
  11754. screen.w + 'x' + screen.h);
  11755. }
  11756. }, 500);
  11757.  
  11758. } else if (resizeMode === 'scale' || resizeMode === 'downscale') {
  11759. var downscaleOnly = resizeMode === 'downscale';
  11760. display.autoscale(screen.w, screen.h, downscaleOnly);
  11761. app$ui$$UI.fixScrollbars();
  11762. }
  11763. }
  11764. },
  11765.  
  11766. // Gets the the size of the available viewport in the browser window
  11767. screenSize: function() {
  11768. var screen = document.getElementById('noVNC_screen');
  11769. return {w: screen.offsetWidth, h: screen.offsetHeight};
  11770. },
  11771.  
  11772. // Normally we only apply the current resize mode after a window resize
  11773. // event. This means that when a new connection is opened, there is no
  11774. // resize mode active.
  11775. // We have to wait until the first FBU because this is where the client
  11776. // will find the supported encodings of the server. Some calls later in
  11777. // the chain is dependant on knowing the server-capabilities.
  11778. initialResize: function(rfb, fbu) {
  11779. app$ui$$UI.applyResizeMode();
  11780. // After doing this once, we remove the callback.
  11781. app$ui$$UI.rfb.set_onFBUComplete(function() { });
  11782. },
  11783.  
  11784. /* ------^-------
  11785. * /RESIZE
  11786. * ==============
  11787. * CLIPPING
  11788. * ------v------*/
  11789.  
  11790. // Set and configure viewport clipping
  11791. setViewClip: function(clip) {
  11792. app$ui$$UI.updateSetting('clip', clip);
  11793. app$ui$$UI.updateViewClip();
  11794. },
  11795.  
  11796. // Update parameters that depend on the clip setting
  11797. updateViewClip: function() {
  11798. if (!app$ui$$UI.rfb) return;
  11799.  
  11800. var display = app$ui$$UI.rfb.get_display();
  11801. var cur_clip = display.get_viewport();
  11802. var new_clip = app$ui$$UI.getSetting('clip');
  11803.  
  11804. var resizeSetting = app$ui$$UI.getSetting('resize');
  11805. if (resizeSetting === 'downscale' || resizeSetting === 'scale') {
  11806. // Disable clipping if we are scaling
  11807. new_clip = false;
  11808. } else if ($$$core$util$browsers$$isTouchDevice) {
  11809. // Touch devices usually have shit scrollbars
  11810. new_clip = true;
  11811. }
  11812.  
  11813. if (cur_clip !== new_clip) {
  11814. display.set_viewport(new_clip);
  11815. }
  11816.  
  11817. var size = app$ui$$UI.screenSize();
  11818.  
  11819. if (new_clip && size) {
  11820. // When clipping is enabled, the screen is limited to
  11821. // the size of the browser window.
  11822. display.viewportChangeSize(size.w, size.h);
  11823. app$ui$$UI.fixScrollbars();
  11824. }
  11825.  
  11826. // Changing the viewport may change the state of
  11827. // the dragging button
  11828. app$ui$$UI.updateViewDrag();
  11829. },
  11830.  
  11831. // Handle special cases where clipping is forced on/off or locked
  11832. enableDisableViewClip: function() {
  11833. var resizeSetting = app$ui$$UI.getSetting('resize');
  11834. // Disable clipping if we are scaling, connected or on touch
  11835. if (resizeSetting === 'downscale' || resizeSetting === 'scale' ||
  11836. $$$core$util$browsers$$isTouchDevice) {
  11837. app$ui$$UI.disableSetting('clip');
  11838. } else {
  11839. app$ui$$UI.enableSetting('clip');
  11840. }
  11841. },
  11842.  
  11843. /* ------^-------
  11844. * /CLIPPING
  11845. * ==============
  11846. * VIEWDRAG
  11847. * ------v------*/
  11848.  
  11849. toggleViewDrag: function() {
  11850. if (!app$ui$$UI.rfb) return;
  11851.  
  11852. var drag = app$ui$$UI.rfb.get_viewportDrag();
  11853. app$ui$$UI.setViewDrag(!drag);
  11854. },
  11855.  
  11856. // Set the view drag mode which moves the viewport on mouse drags
  11857. setViewDrag: function(drag) {
  11858. if (!app$ui$$UI.rfb) return;
  11859.  
  11860. app$ui$$UI.rfb.set_viewportDrag(drag);
  11861.  
  11862. app$ui$$UI.updateViewDrag();
  11863. },
  11864.  
  11865. updateViewDrag: function() {
  11866. var clipping = false;
  11867.  
  11868. if (!app$ui$$UI.connected) return;
  11869.  
  11870. // Check if viewport drag is possible. It is only possible
  11871. // if the remote display is clipping the client display.
  11872. if (app$ui$$UI.rfb.get_display().get_viewport() &&
  11873. app$ui$$UI.rfb.get_display().clippingDisplay()) {
  11874. clipping = true;
  11875. }
  11876.  
  11877. var viewDragButton = document.getElementById('noVNC_view_drag_button');
  11878.  
  11879. if (!clipping &&
  11880. app$ui$$UI.rfb.get_viewportDrag()) {
  11881. // The size of the remote display is the same or smaller
  11882. // than the client display. Make sure viewport drag isn't
  11883. // active when it can't be used.
  11884. app$ui$$UI.rfb.set_viewportDrag(false);
  11885. }
  11886.  
  11887. if (app$ui$$UI.rfb.get_viewportDrag()) {
  11888. viewDragButton.classList.add("noVNC_selected");
  11889. } else {
  11890. viewDragButton.classList.remove("noVNC_selected");
  11891. }
  11892.  
  11893. // Different behaviour for touch vs non-touch
  11894. // The button is disabled instead of hidden on touch devices
  11895. if ($$$core$util$browsers$$isTouchDevice) {
  11896. viewDragButton.classList.remove("noVNC_hidden");
  11897.  
  11898. if (clipping) {
  11899. viewDragButton.disabled = false;
  11900. } else {
  11901. viewDragButton.disabled = true;
  11902. }
  11903. } else {
  11904. viewDragButton.disabled = false;
  11905.  
  11906. if (clipping) {
  11907. viewDragButton.classList.remove("noVNC_hidden");
  11908. } else {
  11909. viewDragButton.classList.add("noVNC_hidden");
  11910. }
  11911. }
  11912. },
  11913.  
  11914. /* ------^-------
  11915. * /VIEWDRAG
  11916. * ==============
  11917. * KEYBOARD
  11918. * ------v------*/
  11919.  
  11920. showVirtualKeyboard: function() {
  11921. if (!$$$core$util$browsers$$isTouchDevice) return;
  11922.  
  11923. var input = document.getElementById('noVNC_keyboardinput');
  11924.  
  11925. if (document.activeElement == input) return;
  11926.  
  11927. input.focus();
  11928.  
  11929. try {
  11930. var l = input.value.length;
  11931. // Move the caret to the end
  11932. input.setSelectionRange(l, l);
  11933. } catch (err) {} // setSelectionRange is undefined in Google Chrome
  11934. },
  11935.  
  11936. hideVirtualKeyboard: function() {
  11937. if (!$$$core$util$browsers$$isTouchDevice) return;
  11938.  
  11939. var input = document.getElementById('noVNC_keyboardinput');
  11940.  
  11941. if (document.activeElement != input) return;
  11942.  
  11943. input.blur();
  11944. },
  11945.  
  11946. toggleVirtualKeyboard: function () {
  11947. if (document.getElementById('noVNC_keyboard_button')
  11948. .classList.contains("noVNC_selected")) {
  11949. app$ui$$UI.hideVirtualKeyboard();
  11950. } else {
  11951. app$ui$$UI.showVirtualKeyboard();
  11952. }
  11953. },
  11954.  
  11955. onfocusVirtualKeyboard: function(event) {
  11956. document.getElementById('noVNC_keyboard_button')
  11957. .classList.add("noVNC_selected");
  11958. },
  11959.  
  11960. onblurVirtualKeyboard: function(event) {
  11961. document.getElementById('noVNC_keyboard_button')
  11962. .classList.remove("noVNC_selected");
  11963. },
  11964.  
  11965. keepVirtualKeyboard: function(event) {
  11966. var input = document.getElementById('noVNC_keyboardinput');
  11967.  
  11968. // Only prevent focus change if the virtual keyboard is active
  11969. if (document.activeElement != input) {
  11970. return;
  11971. }
  11972.  
  11973. // Only allow focus to move to other elements that need
  11974. // focus to function properly
  11975. if (event.target.form !== undefined) {
  11976. switch (event.target.type) {
  11977. case 'text':
  11978. case 'email':
  11979. case 'search':
  11980. case 'password':
  11981. case 'tel':
  11982. case 'url':
  11983. case 'textarea':
  11984. case 'select-one':
  11985. case 'select-multiple':
  11986. return;
  11987. }
  11988. }
  11989.  
  11990. event.preventDefault();
  11991. },
  11992.  
  11993. keyboardinputReset: function() {
  11994. var kbi = document.getElementById('noVNC_keyboardinput');
  11995. kbi.value = new Array(app$ui$$UI.defaultKeyboardinputLen).join("_");
  11996. app$ui$$UI.lastKeyboardinput = kbi.value;
  11997. },
  11998.  
  11999. // When normal keyboard events are left uncought, use the input events from
  12000. // the keyboardinput element instead and generate the corresponding key events.
  12001. // This code is required since some browsers on Android are inconsistent in
  12002. // sending keyCodes in the normal keyboard events when using on screen keyboards.
  12003. keyInput: function(event) {
  12004.  
  12005. if (!app$ui$$UI.rfb) return;
  12006.  
  12007. var newValue = event.target.value;
  12008.  
  12009. if (!app$ui$$UI.lastKeyboardinput) {
  12010. app$ui$$UI.keyboardinputReset();
  12011. }
  12012. var oldValue = app$ui$$UI.lastKeyboardinput;
  12013.  
  12014. var newLen;
  12015. try {
  12016. // Try to check caret position since whitespace at the end
  12017. // will not be considered by value.length in some browsers
  12018. newLen = Math.max(event.target.selectionStart, newValue.length);
  12019. } catch (err) {
  12020. // selectionStart is undefined in Google Chrome
  12021. newLen = newValue.length;
  12022. }
  12023. var oldLen = oldValue.length;
  12024.  
  12025. var backspaces;
  12026. var inputs = newLen - oldLen;
  12027. if (inputs < 0) {
  12028. backspaces = -inputs;
  12029. } else {
  12030. backspaces = 0;
  12031. }
  12032.  
  12033. // Compare the old string with the new to account for
  12034. // text-corrections or other input that modify existing text
  12035. var i;
  12036. for (i = 0; i < Math.min(oldLen, newLen); i++) {
  12037. if (newValue.charAt(i) != oldValue.charAt(i)) {
  12038. inputs = newLen - i;
  12039. backspaces = oldLen - i;
  12040. break;
  12041. }
  12042. }
  12043.  
  12044. // Send the key events
  12045. for (i = 0; i < backspaces; i++) {
  12046. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_BackSpace, "Backspace");
  12047. }
  12048. for (i = newLen - inputs; i < newLen; i++) {
  12049. app$ui$$UI.rfb.sendKey($$$core$input$keysymdef$$default.lookup(newValue.charCodeAt(i)));
  12050. }
  12051.  
  12052. // Control the text content length in the keyboardinput element
  12053. if (newLen > 2 * app$ui$$UI.defaultKeyboardinputLen) {
  12054. app$ui$$UI.keyboardinputReset();
  12055. } else if (newLen < 1) {
  12056. // There always have to be some text in the keyboardinput
  12057. // element with which backspace can interact.
  12058. app$ui$$UI.keyboardinputReset();
  12059. // This sometimes causes the keyboard to disappear for a second
  12060. // but it is required for the android keyboard to recognize that
  12061. // text has been added to the field
  12062. event.target.blur();
  12063. // This has to be ran outside of the input handler in order to work
  12064. setTimeout(event.target.focus.bind(event.target), 0);
  12065. } else {
  12066. app$ui$$UI.lastKeyboardinput = newValue;
  12067. }
  12068. },
  12069.  
  12070. /* ------^-------
  12071. * /KEYBOARD
  12072. * ==============
  12073. * EXTRA KEYS
  12074. * ------v------*/
  12075.  
  12076. openExtraKeys: function() {
  12077. app$ui$$UI.closeAllPanels();
  12078. app$ui$$UI.openControlbar();
  12079.  
  12080. document.getElementById('noVNC_modifiers')
  12081. .classList.add("noVNC_open");
  12082. document.getElementById('noVNC_toggle_extra_keys_button')
  12083. .classList.add("noVNC_selected");
  12084. },
  12085.  
  12086. closeExtraKeys: function() {
  12087. document.getElementById('noVNC_modifiers')
  12088. .classList.remove("noVNC_open");
  12089. document.getElementById('noVNC_toggle_extra_keys_button')
  12090. .classList.remove("noVNC_selected");
  12091. },
  12092.  
  12093. toggleExtraKeys: function() {
  12094. if(document.getElementById('noVNC_modifiers')
  12095. .classList.contains("noVNC_open")) {
  12096. app$ui$$UI.closeExtraKeys();
  12097. } else {
  12098. app$ui$$UI.openExtraKeys();
  12099. }
  12100. },
  12101.  
  12102. sendEsc: function() {
  12103. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Escape, "Escape");
  12104. },
  12105.  
  12106. sendTab: function() {
  12107. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Tab);
  12108. },
  12109.  
  12110. toggleCtrl: function() {
  12111. var btn = document.getElementById('noVNC_toggle_ctrl_button');
  12112. if (btn.classList.contains("noVNC_selected")) {
  12113. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Control_L, "ControlLeft", false);
  12114. btn.classList.remove("noVNC_selected");
  12115. } else {
  12116. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Control_L, "ControlLeft", true);
  12117. btn.classList.add("noVNC_selected");
  12118. }
  12119. },
  12120.  
  12121. toggleAlt: function() {
  12122. var btn = document.getElementById('noVNC_toggle_alt_button');
  12123. if (btn.classList.contains("noVNC_selected")) {
  12124. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Alt_L, "AltLeft", false);
  12125. btn.classList.remove("noVNC_selected");
  12126. } else {
  12127. app$ui$$UI.rfb.sendKey($$$core$input$keysym$$default.XK_Alt_L, "AltLeft", true);
  12128. btn.classList.add("noVNC_selected");
  12129. }
  12130. },
  12131.  
  12132. sendCtrlAltDel: function() {
  12133. app$ui$$UI.rfb.sendCtrlAltDel();
  12134. },
  12135.  
  12136. /* ------^-------
  12137. * /EXTRA KEYS
  12138. * ==============
  12139. * PVE
  12140. * ------v------*/
  12141.  
  12142. togglePVECommandPanel: function() {
  12143. if (document.getElementById('pve_commands').classList.contains("noVNC_open")) {
  12144. app$ui$$UI.closePVECommandPanel();
  12145. } else {
  12146. app$ui$$UI.openPVECommandPanel();
  12147. }
  12148. },
  12149.  
  12150. openPVECommandPanel: function() {
  12151. var me = this;
  12152. app$ui$$UI.closeAllPanels();
  12153. app$ui$$UI.openControlbar();
  12154.  
  12155. document.getElementById('pve_commands').classList.add("noVNC_open");
  12156. document.getElementById('pve_commands_button').classList.add("noVNC_selected");
  12157. },
  12158.  
  12159. closePVECommandPanel: function() {
  12160. document.getElementById('pve_commands').classList.remove("noVNC_open");
  12161. document.getElementById('pve_commands_button').classList.remove("noVNC_selected");
  12162. },
  12163.  
  12164. /* ------^-------
  12165. * /PVE
  12166. * ==============
  12167. * MISC
  12168. * ------v------*/
  12169. setMouseButton: function(num) {
  12170. var view_only = app$ui$$UI.rfb.get_view_only();
  12171. if (app$ui$$UI.rfb && !view_only) {
  12172. app$ui$$UI.rfb.get_mouse().set_touchButton(num);
  12173. }
  12174.  
  12175. var blist = [0, 1,2,4];
  12176. for (var b = 0; b < blist.length; b++) {
  12177. var button = document.getElementById('noVNC_mouse_button' +
  12178. blist[b]);
  12179. if (blist[b] === num && !view_only) {
  12180. button.classList.remove("noVNC_hidden");
  12181. } else {
  12182. button.classList.add("noVNC_hidden");
  12183. }
  12184. }
  12185. },
  12186.  
  12187. displayBlur: function() {
  12188. if (app$ui$$UI.rfb && !app$ui$$UI.rfb.get_view_only()) {
  12189. app$ui$$UI.rfb.get_keyboard().set_focused(false);
  12190. app$ui$$UI.rfb.get_mouse().set_focused(false);
  12191. }
  12192. },
  12193.  
  12194. displayFocus: function() {
  12195. if (app$ui$$UI.rfb && !app$ui$$UI.rfb.get_view_only()) {
  12196. app$ui$$UI.rfb.get_keyboard().set_focused(true);
  12197. app$ui$$UI.rfb.get_mouse().set_focused(true);
  12198. }
  12199. },
  12200.  
  12201. updateLocalCursor: function() {
  12202. if (!app$ui$$UI.rfb) return;
  12203. app$ui$$UI.rfb.set_local_cursor(app$ui$$UI.getSetting('cursor'));
  12204. },
  12205.  
  12206. updateViewOnly: function() {
  12207. if (!app$ui$$UI.rfb) return;
  12208. app$ui$$UI.rfb.set_view_only(app$ui$$UI.getSetting('view_only'));
  12209. },
  12210.  
  12211. updateLogging: function() {
  12212. $$webutil$$.init_logging(app$ui$$UI.getSetting('logging'));
  12213. },
  12214.  
  12215. updateSessionSize: function(rfb, width, height) {
  12216. var resize = app$ui$$UI.getSetting('resize');
  12217.  
  12218. if (resize == 'null') {
  12219. var clip = app$ui$$UI.getSetting('clip');
  12220. app$ui$$UI.PVE.updateFBSize(rfb, width, height, clip);
  12221. }
  12222.  
  12223. app$ui$$UI.applyResizeMode();
  12224. app$ui$$UI.updateViewClip();
  12225. app$ui$$UI.updateViewDrag();
  12226. },
  12227.  
  12228. fixScrollbars: function() {
  12229. // This is a hack because Chrome screws up the calculation
  12230. // for when scrollbars are needed. So to fix it we temporarily
  12231. // toggle them off and on.
  12232. var screen = document.getElementById('noVNC_screen');
  12233. screen.style.overflow = 'hidden';
  12234. // Force Chrome to recalculate the layout by asking for
  12235. // an element's dimensions
  12236. screen.getBoundingClientRect();
  12237. screen.style.overflow = "";
  12238. },
  12239.  
  12240. updateDesktopName: function(rfb, name) {
  12241. app$ui$$UI.desktopName = name;
  12242. // Display the desktop name in the document title
  12243. document.title = name + " - noVNC";
  12244. },
  12245.  
  12246. bell: function(rfb) {
  12247. if ($$webutil$$.getConfigVar('bell', 'on') === 'on') {
  12248. document.getElementById('noVNC_bell').play()
  12249. .catch(function(e) {
  12250. if (e.name === "NotAllowedError") {
  12251. // Ignore when the browser doesn't let us play audio.
  12252. // It is common that the browsers require audio to be
  12253. // initiated from a user action.
  12254. } else {
  12255. $$$core$util$logging$$.Error("Unable to play bell: " + e);
  12256. }
  12257. });
  12258. }
  12259. },
  12260.  
  12261. //Helper to add options to dropdown.
  12262. addOption: function(selectbox, text, value) {
  12263. var optn = document.createElement("OPTION");
  12264. optn.text = text;
  12265. optn.value = value;
  12266. selectbox.options.add(optn);
  12267. },
  12268.  
  12269. /* ------^-------
  12270. * /MISC
  12271. * ==============
  12272. */
  12273. };
  12274.  
  12275. // Set up translations
  12276. var app$ui$$LINGUAS = ["de", "el", "nl", "sv"];
  12277. $$$core$util$localization$$l10n.setup(app$ui$$LINGUAS);
  12278. if ($$$core$util$localization$$l10n.language !== "en" && $$$core$util$localization$$l10n.dictionary === undefined) {
  12279. $$webutil$$.fetchJSON('/novnc/app/locale/' + $$$core$util$localization$$l10n.language + '.json', function (translations) {
  12280. $$$core$util$localization$$l10n.dictionary = translations;
  12281.  
  12282. // wait for translations to load before loading the UI
  12283. app$ui$$UI.prime();
  12284. }, function (err) {
  12285. throw err;
  12286. });
  12287. } else {
  12288. app$ui$$UI.prime();
  12289. }
  12290.  
  12291. var app$ui$$default = app$ui$$UI;
  12292. }).call(this);
Add Comment
Please, Sign In to add comment