xpra icon
Bug tracker and wiki

Ticket #2701: var-let-const.patch

File var-let-const.patch, 135.9 KB (added by brief, 3 months ago)
  • Client.js

     
    1515
    1616"use strict";
    1717
    18 var XPRA_CLIENT_FORCE_NO_WORKER = false;
    19 var CLIPBOARD_IMAGES = true;
    20 var CLIPBOARD_EVENT_DELAY = 100;
     18const XPRA_CLIENT_FORCE_NO_WORKER = false;
     19const CLIPBOARD_IMAGES = true;
     20const CLIPBOARD_EVENT_DELAY = 100;
    2121
    2222function XpraClient(container) {
    2323        // the container div is the "screen" on the HTML page where we
     
    2828        }
    2929        // assign callback for window resize event
    3030        if (window.jQuery) {
    31                 var me = this;
     31                const me = this;
    3232                jQuery(window).resize(jQuery.debounce(250, function (e) {
    3333                        me._screen_resized(e, me);
    3434                }));
     
    187187        this.topindex = 0;
    188188        this.focus = -1;
    189189
     190        const me = this;
    190191        jQuery("#screen").mousedown(function (e) {
    191192                me.on_mousedown(e);
    192193        });
     
    196197        jQuery("#screen").mousemove(function (e) {
    197198                me.on_mousemove(e);
    198199        });
    199         var me = this;
    200         var div = document.getElementById("screen");
     200
     201        const div = document.getElementById("screen");
    201202        function on_mousescroll(e) {
    202203                me.on_mousescroll(e);
    203204        }
     
    221222XpraClient.prototype.send_log = function(level, args) {
    222223        if(this.remote_logging && this.server_remote_logging && this.connected) {
    223224                try {
    224                         var sargs = [];
    225                         for(var i = 0; i < args.length; i++) {
     225                        const sargs = [];
     226                        for(let i = 0; i < args.length; i++) {
    226227                                sargs.push(unescape(encodeURIComponent(String(args[i]))));
    227228                        }
    228229                        this.send(["logging", level, sargs]);
    229230                } catch (e) {
    230231                        this.cerror("remote logging failed");
    231                         for(var i = 0; i < args.length; i++) {
     232                        for(let i = 0; i < args.length; i++) {
    232233                                this.clog(" argument", i, typeof args[i], ":", "'"+args[i]+"'");
    233234                        }
    234235                }
     
    236237}
    237238XpraClient.prototype.exc = function() {
    238239        //first argument is the exception:
    239         var exception = arguments[0];
    240         var args = Array.from(arguments);
     240        const exception = arguments[0];
     241        let args = Array.from(arguments);
    241242        args = args.splice(1);
    242243        if (args.length>0) {
    243244                this.cerror(args);
     
    277278        Utilities.clog.apply(Utilities, arguments);
    278279}
    279280XpraClient.prototype.debug = function() {
    280         var category = arguments[0];
    281         var args = Array.from(arguments);
     281        const category = arguments[0];
     282        let args = Array.from(arguments);
    282283        args = args.splice(1);
    283284        if (this.debug_categories.includes(category)) {
    284285                if (category!="network") {
     
    357358}
    358359
    359360XpraClient.prototype.connect = function() {
    360         var details = this.host + ":" + this.port + this.path;
     361        let details = this.host + ":" + this.port + this.path;
    361362        if (this.ssl) {
    362363                details += " with ssl";
    363364        }
     
    374375        if(window.Worker) {
    375376                this.clog("we have webworker support");
    376377                // spawn worker that checks for a websocket
    377                 var me = this;
    378                 var worker = new Worker('js/lib/wsworker_check.js');
     378                const me = this;
     379                const worker = new Worker('js/lib/wsworker_check.js');
    379380                worker.addEventListener('message', function(e) {
    380                         var data = e.data;
     381                        const data = e.data;
    381382                        switch (data['result']) {
    382383                        case true:
    383384                                // yey, we can use websocket in worker!
     
    416417        // set protocol to deliver packets to our packet router
    417418        this.protocol.set_packet_handler(this._route_packet, this);
    418419        // make uri
    419         var uri = "ws://";
     420        let uri = "ws://";
    420421        if (this.ssl)
    421422                uri = "wss://";
    422423        uri += this.host;
     
    448449}
    449450
    450451XpraClient.prototype.redraw_windows = function() {
    451         for (var i in this.id_to_window) {
    452                 var iwin = this.id_to_window[i];
     452        for (const i in this.id_to_window) {
     453                const iwin = this.id_to_window[i];
    453454                this.request_redraw(iwin);
    454455        }
    455456}
    456457
    457458XpraClient.prototype.close_windows = function() {
    458         for (var i in this.id_to_window) {
    459                 var iwin = this.id_to_window[i];
     459        for (const i in this.id_to_window) {
     460                const iwin = this.id_to_window[i];
    460461                window.removeWindowListItem(i);
    461462                iwin.destroy();
    462463        }
     
    500501        // remove an encoding from our hello.encodings.core list
    501502        // as if we don't support it
    502503        this.clog("disable", encoding);
    503         var index = this.supported_encodings.indexOf(encoding);
     504        const index = this.supported_encodings.indexOf(encoding);
    504505        if(index > -1) {
    505506                this.supported_encodings.splice(index, 1);
    506507        }
     
    508509
    509510XpraClient.prototype._route_packet = function(packet, ctx) {
    510511        // ctx refers to `this` because we came through a callback
    511         var packet_type = "";
    512         var fn = "";
     512        let packet_type = "";
     513        let fn = "";
    513514        packet_type = packet[0];
    514515        ctx.debug("network", "received a", packet_type, "packet");
    515516        fn = ctx.packet_handlers[packet_type];
     
    528529        }
    529530        this.desktop_width = this.container.clientWidth;
    530531        this.desktop_height = this.container.clientHeight;
    531         var newsize = [this.desktop_width, this.desktop_height];
    532         var packet = ["desktop_size", newsize[0], newsize[1], this._get_screen_sizes()];
     532        const newsize = [this.desktop_width, this.desktop_height];
     533        const packet = ["desktop_size", newsize[0], newsize[1], this._get_screen_sizes()];
    533534        ctx.send(packet);
    534535        // call the screen_resized function on all open windows
    535         for (var i in ctx.id_to_window) {
    536                 var iwin = ctx.id_to_window[i];
     536        for (const i in ctx.id_to_window) {
     537                const iwin = ctx.id_to_window[i];
    537538                iwin.screen_resized();
    538539        }
    539540}
     
    542543 * Keyboard
    543544 */
    544545XpraClient.prototype.init_keyboard = function() {
    545         var me = this;
     546        const me = this;
    546547        // modifier keys:
    547548        this.num_lock_modifier = null;
    548549        this.alt_modifier = null;
     
    554555        this.capture_keyboard = true;
    555556        // assign the key callbacks
    556557        document.addEventListener('keydown', function(e) {
    557                 var r = me._keyb_onkeydown(e, me);
     558                const r = me._keyb_onkeydown(e, me);
    558559                if (!r) {
    559560                        e.preventDefault();
    560561                }
    561562        });
    562563        document.addEventListener('keyup', function (e) {
    563                 var r = me._keyb_onkeyup(e, me);
     564                const r = me._keyb_onkeyup(e, me);
    564565                if (!r) {
    565566                        e.preventDefault();
    566567                }
     
    575576         * then we translate them.
    576577         */
    577578        //convert generic modifiers "meta" and "alt" into their x11 name:
    578         var modifiers = get_event_modifiers(event);
     579        const modifiers = get_event_modifiers(event);
    579580        return this.translate_modifiers(modifiers);
    580581}
    581582
     
    586587         * And also swap keys for macos clients.
    587588         */
    588589        //convert generic modifiers "meta" and "alt" into their x11 name:
    589         var alt = this.alt_modifier;
    590         var control = this.control_modifier;
    591         var meta = this.meta_modifier;
    592         var altgr = this.altgr_modifier;
     590        const alt = this.alt_modifier;
     591        let control = this.control_modifier;
     592        let meta = this.meta_modifier;
     593        const altgr = this.altgr_modifier;
    593594        if (this.swap_keys) {
    594595                meta = this.control_modifier;
    595596                control = this.meta_modifier;
    596597        }
    597598
    598         var new_modifiers = modifiers.slice();
    599         var index = modifiers.indexOf("meta");
     599        const new_modifiers = modifiers.slice();
     600        let index = modifiers.indexOf("meta");
    600601        if (index>=0 && meta)
    601602                new_modifiers[index] = meta;
    602603        index = modifiers.indexOf("control");
     
    640641         * This function may send the new detected keyboard layout.
    641642         * (ignoring the keyboard_layout preference)
    642643         */
    643         var now = Utilities.monotonicTime();
     644        const now = Utilities.monotonicTime();
    644645        if (now<this.browser_language_change_embargo_time) {
    645646                return;
    646647        }
    647         var new_layout = null;
     648        let new_layout = null;
    648649        if (key_layout) {
    649650                new_layout = key_layout;
    650651        }
     
    652653                //we may have used a different layout for a specific key,
    653654                //and now this new key doesn't need it anymore,
    654655                //so we may want to switch back to the original layout:
    655                 var l = Utilities.getFirstBrowserLanguage();
     656                const l = Utilities.getFirstBrowserLanguage();
    656657                if (l && this.browser_language != l) {
    657658                        //if the browser language has changed,
    658659                        //this takes precedence over the configuration
     
    697698        if (window.event)
    698699                event = window.event;
    699700
    700         var keyname = event.code || "";
    701         var keycode = event.which || event.keyCode;
     701        let keyname = event.code || "";
     702        const keycode = event.which || event.keyCode;
    702703        if (keycode==229) {
    703704                //this usually fires when we have received the event via "oninput" already
    704705                return;
    705706        }
    706         var str = event.key || String.fromCharCode(keycode);
     707        let str = event.key || String.fromCharCode(keycode);
    707708
    708709        this.debug("keyboard", "processKeyEvent(", pressed, ", ", event, ") key=", keyname, "keycode=", keycode);
    709710
     
    712713                this.num_lock = !this.num_lock;
    713714        }
    714715
    715         var key_language = null;
     716        let key_language = null;
    716717        //special case for numpad,
    717718        //try to distinguish arrowpad and numpad:
    718719        //(for arrowpad, keyname==str)
     
    729730                keyname = CHAR_TO_NAME[str];
    730731                if (keyname.includes("_")) {
    731732                        //ie: Thai_dochada
    732                         var lang = keyname.split("_")[0];
     733                        const lang = keyname.split("_")[0];
    733734                        key_language = KEYSYM_TO_LAYOUT[lang];
    734735                }
    735736        }
     
    740741
    741742        this._check_browser_language(key_language);
    742743
    743         var DOM_KEY_LOCATION_RIGHT = 2;
     744        const DOM_KEY_LOCATION_RIGHT = 2;
    744745        if (keyname.match("_L$") && event.location==DOM_KEY_LOCATION_RIGHT)
    745746                keyname = keyname.replace("_L", "_R")
    746747
     
    754755        //if (this.num_lock && keycode>=96 && keycode<106)
    755756        //      keyname = "KP_"+(keycode-96);
    756757
    757         var raw_modifiers = get_event_modifiers(event);
    758         var modifiers = this._keyb_get_modifiers(event);
    759         var keyval = keycode;
    760         var group = 0;
     758        const raw_modifiers = get_event_modifiers(event);
     759        const modifiers = this._keyb_get_modifiers(event);
     760        const keyval = keycode;
     761        const group = 0;
    761762
    762         var shift = modifiers.includes("shift");
    763         var capslock = modifiers.includes("capslock");
     763        const shift = modifiers.includes("shift");
     764        const capslock = modifiers.includes("capslock");
    764765        if ((capslock && shift) || (!capslock && !shift)) {
    765766                str = str.toLowerCase();
    766767        }
    767768
    768         var ostr = str;
     769        const ostr = str;
    769770        if (this.swap_keys) {
    770771                if (keyname=="Control_L") {
    771772                        keyname = "Meta_L";
     
    788789        //if (keyname=="Control_L" || keyname=="Control_R")
    789790        this._poll_clipboard(event);
    790791
    791         var allow_default = false;
     792        let allow_default = false;
    792793        if (this.clipboard_enabled) {
    793794                //allow some key events that need to be seen by the browser
    794795                //for handling the clipboard:
    795                 var clipboard_modifier_keys = ["Control_L", "Control_R", "Shift_L", "Shift_R"];
    796                 var clipboard_modifier = "control";
     796                let clipboard_modifier_keys = ["Control_L", "Control_R", "Shift_L", "Shift_R"];
     797                let clipboard_modifier = "control";
    797798                if (Utilities.isMacOS()) {
    798799                        //Apple does things differently, as usual:
    799800                        clipboard_modifier_keys = ["Meta_L", "Meta_R", "Shift_L", "Shift_R"];
     
    809810                        this.debug("keyboard", "passing clipboard combination Shift+Insert to browser");
    810811                        allow_default = true;
    811812                }
    812                 var clipboard_mod_set = raw_modifiers.includes(clipboard_modifier);
     813                const clipboard_mod_set = raw_modifiers.includes(clipboard_modifier);
    813814                if (clipboard_mod_set) {
    814                         var l = keyname.toLowerCase();
     815                        const l = keyname.toLowerCase();
    815816                        if (l=="c" || l=="x" || l=="v") {
    816817                                this.debug("keyboard", "passing clipboard combination to browser:", clipboard_modifier, "+", keyname);
    817818                                allow_default = true;
     
    823824        }
    824825
    825826        if (this.topwindow != null) {
    826                 var packet = ["key-action", this.topwindow, keyname, pressed, modifiers, keyval, str, keycode, group];
     827                let packet = ["key-action", this.topwindow, keyname, pressed, modifiers, keyval, str, keycode, group];
    827828                this.key_packets.push(packet);
    828829                if (pressed && Utilities.isMacOS() && raw_modifiers.includes("meta") && ostr!="meta") {
    829830                        //macos will swallow the key release event if the meta modifier is pressed,
     
    835836                //if there is a chance that we're in the process of handling
    836837                //a clipboard event (a click or control-v)
    837838                //then we send with a slight delay:
    838                 var delay = 0;
    839                 var now = Utilities.monotonicTime();
     839                let delay = 0;
     840                const now = Utilities.monotonicTime();
    840841                if (this.clipboard_delayed_event_time>now) {
    841842                        delay = this.clipboard_delayed_event_time-now;
    842843                }
    843                 var me = this;
     844                const me = this;
    844845                setTimeout(function () {
    845846                        while (me.key_packets.length>0) {
    846847                                me.send(me.key_packets.shift());
     
    871872
    872873XpraClient.prototype._get_keycodes = function() {
    873874        //keycodes.append((nn(keyval), nn(name), nn(keycode), nn(group), nn(level)))
    874         var keycodes = [];
    875         var kc;
    876         for(var keycode in CHARCODE_TO_NAME) {
     875        const keycodes = [];
     876        let kc;
     877        for(const keycode in CHARCODE_TO_NAME) {
    877878                kc = parseInt(keycode);
    878879                keycodes.push([kc, CHARCODE_TO_NAME[keycode], kc, 0, 0]);
    879880        }
     
    887888
    888889XpraClient.prototype._get_DPI = function() {
    889890        "use strict";
    890         var dpi_div = document.getElementById("dpi");
     891        const dpi_div = document.getElementById("dpi");
    891892        if (dpi_div != undefined) {
    892893                //show("dpiX="+dpi_div.offsetWidth+", dpiY="+dpi_div.offsetHeight);
    893894                if (dpi_div.offsetWidth>0 && dpi_div.offsetHeight>0)
     
    901902}
    902903
    903904XpraClient.prototype._get_screen_sizes = function() {
    904         var dpi = this._get_DPI();
    905         var screen_size = [this.container.clientWidth, this.container.clientHeight];
    906         var wmm = Math.round(screen_size[0]*25.4/dpi);
    907         var hmm = Math.round(screen_size[1]*25.4/dpi);
    908         var monitor = ["Canvas", 0, 0, screen_size[0], screen_size[1], wmm, hmm];
    909         var screen = ["HTML", screen_size[0], screen_size[1],
     905        const dpi = this._get_DPI();
     906        const screen_size = [this.container.clientWidth, this.container.clientHeight];
     907        const wmm = Math.round(screen_size[0]*25.4/dpi);
     908        const hmm = Math.round(screen_size[1]*25.4/dpi);
     909        const monitor = ["Canvas", 0, 0, screen_size[0], screen_size[1], wmm, hmm];
     910        const screen = ["HTML", screen_size[0], screen_size[1],
    910911                                wmm, hmm,
    911912                                [monitor],
    912913                                0, 0, screen_size[0], screen_size[1]
     
    927928}
    928929
    929930XpraClient.prototype._update_capabilities = function(appendobj) {
    930         for (var attr in appendobj) {
     931        for (const attr in appendobj) {
    931932                this.capabilities[attr] = appendobj[attr];
    932933        }
    933934}
     
    936937 * Ping
    937938 */
    938939XpraClient.prototype._check_server_echo = function(ping_sent_time) {
    939         var last = this.server_ok;
     940        const last = this.server_ok;
    940941        this.server_ok = this.last_ping_echoed_time >= ping_sent_time;
    941942        //this.clog("check_server_echo", this.server_ok, "last", last, "last_time", this.last_ping_echoed_time, "this_this", ping_sent_time);
    942943        if(last != this.server_ok) {
     
    945946                } else {
    946947                        this.clog("server connection is OK");
    947948                }
    948                 for (var i in this.id_to_window) {
    949                         var iwin = this.id_to_window[i];
     949                for (const i in this.id_to_window) {
     950                        const iwin = this.id_to_window[i];
    950951                        iwin.set_spinner(this.server_ok);
    951952                }
    952953        }
     
    971972
    972973
    973974XpraClient.prototype._emit_event = function(event_type) {
    974         var event = document.createEvent("Event");
     975        const event = document.createEvent("Event");
    975976        event.initEvent(event_type, true, true);
    976977        document.dispatchEvent(event);
    977978}
     
    10111012        }
    10121013        this.clog("hello capabilities", this.capabilities);
    10131014        // verify:
    1014         for (var key in this.capabilities) {
    1015                 var value = this.capabilities[key];
     1015        for (const key in this.capabilities) {
     1016                const value = this.capabilities[key];
    10161017                if(key==null) {
    10171018                        throw new Error("invalid null key in hello packet data");
    10181019                }
     
    10261027
    10271028XpraClient.prototype._make_hello_base = function() {
    10281029        this.capabilities = {};
    1029         var digests = ["hmac", "hmac+md5", "xor"]
     1030        const digests = ["hmac", "hmac+md5", "xor"];
    10301031        if (typeof forge!=='undefined') {
    10311032                try {
    10321033                        this.debug("network", "forge.md.algorithms=", forge.md.algorithms);
    1033                         for (var hash in forge.md.algorithms) {
     1034                        for (const hash in forge.md.algorithms) {
    10341035                                digests.push("hmac+"+hash);
    10351036                        }
    10361037                        this.debug("network", "digests:", digests);
     
    10831084                        "bandwidth-limit"       : this.bandwidth_limit,
    10841085                })
    10851086        }
    1086         var ci = Utilities.getConnectionInfo();
     1087        const ci = Utilities.getConnectionInfo();
    10871088        if (ci) {
    10881089                this._update_capabilities({
    10891090                        "connection-data"       : ci,
    10901091                })
    10911092        }
    1092         var LZ4 = require('lz4');
     1093        const LZ4 = require('lz4');
    10931094        if(LZ4) {
    10941095                this._update_capabilities({
    10951096                        "lz4"                                           : true,
     
    11261127}
    11271128
    11281129XpraClient.prototype._make_hello = function() {
    1129         var selections = null;
     1130        let selections = null;
    11301131        if (navigator.clipboard && navigator.clipboard.readText && navigator.clipboard.writeText) {
    11311132                //we don't need the primary contents,
    11321133                //we can use the async clipboard
     
    12491250 */
    12501251XpraClient.prototype.getMouse = function(e, window) {
    12511252        // get mouse position take into account scroll
    1252         var mx = e.clientX + jQuery(document).scrollLeft();
    1253         var my = e.clientY + jQuery(document).scrollTop();
     1253        let mx = e.clientX + jQuery(document).scrollLeft();
     1254        let my = e.clientY + jQuery(document).scrollTop();
    12541255
    12551256        // check last mouse position incase the event
    12561257        // hasn't provided it - bug #854
     
    12681269                this.last_mouse_y = my;
    12691270        }
    12701271
    1271         var mbutton = 0;
     1272        let mbutton = 0;
    12721273        if ("which" in e)  // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
    12731274                mbutton = Math.max(0, e.which);
    12741275        else if ("button" in e)  // IE, Opera (zero based)
     
    13021303        if (this.server_readonly || this.mouse_grabbed || !this.connected) {
    13031304                return;
    13041305        }
    1305         var mouse = this.getMouse(e, window),
     1306        const mouse = this.getMouse(e, window),
    13061307                x = Math.round(mouse.x),
    13071308                y = Math.round(mouse.y);
    1308         var modifiers = this._keyb_get_modifiers(e);
    1309         var buttons = [];
    1310         var wid = 0;
     1309        const modifiers = this._keyb_get_modifiers(e);
     1310        const buttons = [];
     1311        let wid = 0;
    13111312        if (window) {
    13121313                wid = window.wid;
    13131314        }
     
    13281329        if (this.server_readonly || this.mouse_grabbed || !this.connected) {
    13291330                return;
    13301331        }
    1331         var send_delay = 0;
     1332        let send_delay = 0;
    13321333        if (this._poll_clipboard(e)) {
    13331334                send_delay = CLIPBOARD_EVENT_DELAY;
    13341335        }
    1335         var mouse = this.getMouse(e, window),
     1336        const mouse = this.getMouse(e, window),
    13361337                x = Math.round(mouse.x),
    13371338                y = Math.round(mouse.y);
    1338         var modifiers = this._keyb_get_modifiers(e);
    1339         var buttons = [];
    1340         var wid = 0;
     1339        const modifiers = this._keyb_get_modifiers(e);
     1340        const buttons = [];
     1341        let wid = 0;
    13411342        if (window) {
    13421343                wid = window.wid;
    13431344        }
     
    13451346        if (wid>0 && this.focus != wid) {
    13461347                this._window_set_focus(window);
    13471348        }
    1348         var button = mouse.button;
     1349        let button = mouse.button;
    13491350        this.debug("mouse", "click:", button, pressed, x, y);
    13501351        if (button==4) {
    13511352                button = 8;
     
    13531354        else if (button==5) {
    13541355                button = 9;
    13551356        }
    1356         var me = this;
     1357        const me = this;
    13571358        setTimeout(function() {
    13581359                this.clipboard_delayed_event_time = Utilities.monotonicTime()+CLIPBOARD_EVENT_DELAY;
    13591360                me.send(["button-action", wid, button, pressed, [x, y], modifiers, buttons]);
     
    13681369        if (this.server_readonly || this.mouse_grabbed || !this.connected) {
    13691370                return;
    13701371        }
    1371         var mouse = this.getMouse(e, window),
     1372        const mouse = this.getMouse(e, window),
    13721373                x = Math.round(mouse.x),
    13731374                y = Math.round(mouse.y);
    1374         var modifiers = this._keyb_get_modifiers(e);
    1375         var buttons = [];
    1376         var wid = 0;
     1375        const modifiers = this._keyb_get_modifiers(e);
     1376        const buttons = [];
     1377        let wid = 0;
    13771378        if (window) {
    13781379                wid = window.wid;
    13791380        }
    1380         var wheel = Utilities.normalizeWheel(e);
     1381        const wheel = Utilities.normalizeWheel(e);
    13811382        this.debug("mouse", "normalized wheel event:", wheel);
    13821383        //clamp to prevent event floods:
    1383         var px = Math.min(1200, wheel.pixelX);
    1384         var py = Math.min(1200, wheel.pixelY);
     1384        let px = Math.min(1200, wheel.pixelX);
     1385        let py = Math.min(1200, wheel.pixelY);
    13851386        if (this.scroll_reverse_x) {
    13861387                px = -px;
    13871388        }
     
    13891390                py = -py;
    13901391        }
    13911392       
    1392         var apx = Math.abs(px);
    1393         var apy = Math.abs(py);
     1393        const apx = Math.abs(px);
     1394        const apy = Math.abs(py);
    13941395        if (this.server_precise_wheel) {
    13951396                if (apx>0) {
    1396                         var btn_x = (px>=0) ? 6 : 7;
    1397                         var xdist = Math.round(px*1000/120);
     1397                        const btn_x = (px>=0) ? 6 : 7;
     1398                        const xdist = Math.round(px*1000/120);
    13981399                        this.send(["wheel-motion", wid, btn_x, -xdist,
    13991400                                [x, y], modifiers, buttons]);
    14001401                }
    14011402                if (apy>0) {
    1402                         var btn_y = (py>=0) ? 5 : 4;
    1403                         var ydist = Math.round(py*1000/120);
     1403                        const btn_y = (py>=0) ? 5 : 4;
     1404                        const ydist = Math.round(py*1000/120);
    14041405                        this.send(["wheel-motion", wid, btn_y, -ydist,
    14051406                                [x, y], modifiers, buttons]);
    14061407                }
     
    14201421                this.wheel_delta_y += py;
    14211422        }
    14221423        //send synthetic click+release as many times as needed:
    1423         var wx = Math.abs(this.wheel_delta_x);
    1424         var wy = Math.abs(this.wheel_delta_y);
    1425         var btn_x = (this.wheel_delta_x>=0) ? 6 : 7;
    1426         var btn_y = (this.wheel_delta_y>=0) ? 5 : 4;
     1424        let wx = Math.abs(this.wheel_delta_x);
     1425        let wy = Math.abs(this.wheel_delta_y);
     1426        const btn_x = (this.wheel_delta_x>=0) ? 6 : 7;
     1427        const btn_y = (this.wheel_delta_y>=0) ? 5 : 4;
    14271428        while (wx>=120) {
    14281429                wx -= 120;
    14291430                this.send(["button-action", wid, btn_x, true, [x, y], modifiers, buttons]);
     
    14441445        //see if the clipboard contents have changed:
    14451446        if (navigator.clipboard && navigator.clipboard.readText) {
    14461447                this.debug("clipboard", "polling using", navigator.clipboard.readText);
    1447                 var client = this;
     1448                const client = this;
    14481449                //warning: this can take a while,
    14491450                //so we may send the click before the clipboard contents...
    14501451                navigator.clipboard.readText().then(function(text) {
    14511452                        client.debug("clipboard", "paste event, text=", text);
    1452                         var clipboard_buffer = unescape(encodeURIComponent(text));
     1453                        const clipboard_buffer = unescape(encodeURIComponent(text));
    14531454                        if (clipboard_buffer!=client.clipboard_buffer) {
    14541455                                client.debug("clipboard", "clipboard contents have changed");
    14551456                                client.clipboard_buffer = clipboard_buffer;
     
    14611462                return false;
    14621463        }
    14631464        //fallback code:
    1464         var datatype = "text/plain";
    1465         var clipboardData = (e.originalEvent || e).clipboardData;
     1465        let datatype = "text/plain";
     1466        let clipboardData = (e.originalEvent || e).clipboardData;
    14661467        //IE: must use window.clipboardData because the event clipboardData is null!
    14671468        if (!clipboardData) {
    14681469                clipboardData = window.clipboardData;
     
    14741475        if (Utilities.isIE()) {
    14751476                datatype = "Text";
    14761477        }
    1477         var clipboard_buffer = unescape(encodeURIComponent(clipboardData.getData(datatype)));
     1478        const clipboard_buffer = unescape(encodeURIComponent(clipboardData.getData(datatype)));
    14781479        this.debug("clipboard", "paste event, data=", clipboard_buffer);
    14791480        if (clipboard_buffer==this.clipboard_buffer) {
    14801481                return false;
     
    14981499        if (win.override_redirect || win.tray) {
    14991500                return;
    15001501        }
    1501         var client = win.client;
    1502         var wid = win.wid;
     1502        const client = win.client;
     1503        const wid = win.wid;
    15031504        if (client.focus == wid) {
    15041505                return;
    15051506        }
    1506         var top_stacking_layer = Object.keys(client.id_to_window).length;
    1507         var old_stacking_layer = win.stacking_layer;
     1507        const top_stacking_layer = Object.keys(client.id_to_window).length;
     1508        const old_stacking_layer = win.stacking_layer;
    15081509        client.focus = wid;
    15091510        client.topwindow = wid;
    15101511        client.send(["focus", wid, []]);
    15111512        //set the focused flag on all windows,
    15121513        //adjust stacking order:
    1513         var iwin = null;
    1514         for (var i in client.id_to_window) {
     1514        let iwin = null;
     1515        for (const i in client.id_to_window) {
    15151516                iwin = client.id_to_window[i];
    15161517                iwin.focused = (i==wid);
    15171518                if (iwin.focused) {
     
    15681569XpraClient.prototype.do_reconnect = function() {
    15691570        //try again:
    15701571        this.reconnect_in_progress = true;
    1571         var me = this;
    1572         var protocol = this.protocol;
     1572        const me = this;
     1573        const protocol = this.protocol;
    15731574        setTimeout(function(){
    15741575                try {
    15751576                        me.close_windows();
     
    16191620
    16201621XpraClient.prototype._process_disconnect = function(packet, ctx) {
    16211622        // save the disconnect reason
    1622         var reason = packet[1];
     1623        const reason = packet[1];
    16231624        ctx.debug("main", "disconnect reason:", reason);
    16241625        if (ctx.reconnect_in_progress) {
    16251626                return;
     
    16361637}
    16371638
    16381639XpraClient.prototype._connection_change = function(e) {
    1639         var ci = Utilities.getConnectionInfo();
     1640        const ci = Utilities.getConnectionInfo();
    16401641        this.clog("connection status - change event=", e, ", connection info=", ci, "tell server:", this.server_connection_data);
    16411642        if (ci && this.server_connection_data) {
    16421643                this.send(["connection-data", ci]);
     
    16511652                clearTimeout(ctx.hello_timer);
    16521653                ctx.hello_timer = null;
    16531654        }
    1654         var hello = packet[1];
     1655        const hello = packet[1];
    16551656        ctx.server_display = hello["display"] || "";
    16561657        ctx.server_platform = hello["platform"] || "";
    16571658        ctx.server_remote_logging = hello["remote-logging.multi-line"];
     
    16741675                ctx.protocol.set_cipher_out(ctx.cipher_out_caps, ctx.encryption_key);
    16751676        }
    16761677        // find the modifier to use for Num_Lock
    1677         var modifier_keycodes = hello['modifier_keycodes']
     1678        const modifier_keycodes = hello['modifier_keycodes']
    16781679        if (modifier_keycodes) {
    1679                 for (var modifier in modifier_keycodes) {
     1680                for (const modifier in modifier_keycodes) {
    16801681                        if (modifier_keycodes.hasOwnProperty(modifier)) {
    1681                                 var mappings = modifier_keycodes[modifier];
    1682                                 for (var keycode in mappings) {
    1683                                         var keys = mappings[keycode];
    1684                                         for (var index in keys) {
    1685                                                 var key=keys[index];
     1682                                const mappings = modifier_keycodes[modifier];
     1683                                for (const keycode in mappings) {
     1684                                        const keys = mappings[keycode];
     1685                                        for (const index in keys) {
     1686                                                const key=keys[index];
    16861687                                                if (key=="Num_Lock") {
    16871688                                                        ctx.num_lock_modifier = modifier;
    16881689                                                }
     
    16921693                }
    16931694        }
    16941695
    1695         var version = hello["version"];
     1696        const version = hello["version"];
    16961697        try {
    1697                 var vparts = version.split(".");
    1698                 var vno = [];
    1699                 for (var i=0; i<vparts.length;i++) {
     1698                const vparts = version.split(".");
     1699                const vno = [];
     1700                for (let i=0; i<vparts.length;i++) {
    17001701                        vno[i] = parseInt(vparts[i]);
    17011702                }
    17021703                if (vno[0]<=0 && vno[1]<10) {
     
    17131714        ctx.log("got hello: server version", version, "accepted our connection");
    17141715        //figure out "alt" and "meta" keys:
    17151716        if ("modifier_keycodes" in hello) {
    1716                 var modifier_keycodes = hello["modifier_keycodes"];
    1717                 for (var mod in modifier_keycodes) {
     1717                const modifier_keycodes = hello["modifier_keycodes"];
     1718                for (const mod in modifier_keycodes) {
    17181719                        //show("modifier_keycode["+mod+"]="+modifier_keycodes[mod].toSource());
    1719                         var keys = modifier_keycodes[mod];
    1720                         for (var i=0; i<keys.length; i++) {
    1721                                 var key = keys[i];
     1720                        const keys = modifier_keycodes[mod];
     1721                        for (let i=0; i<keys.length; i++) {
     1722                                const key = keys[i];
    17221723                                //the first value is usually the integer keycode,
    17231724                                //the second one is the actual key name,
    17241725                                //doesn't hurt to test both:
    1725                                 for (var j=0; j<key.length; j++) {
     1726                                for (let j=0; j<key.length; j++) {
    17261727                                        if ("Alt_L"==key[j])
    17271728                                                ctx.alt_modifier = mod;
    17281729                                        else if ("Meta_L"==key[j])
     
    17541755                                        ctx.warn("audio codec "+ctx.audio_codec+" is not supported by the server");
    17551756                                        ctx.audio_codec = null;
    17561757                                        //find the best one we can use:
    1757                                         for(var i = 0; i < MediaSourceConstants.PREFERRED_CODEC_ORDER.length; i++) {
    1758                                                 var codec = MediaSourceConstants.PREFERRED_CODEC_ORDER[i];
     1758                                        for (const i = 0; i < MediaSourceConstants.PREFERRED_CODEC_ORDER.length; i++) {
     1759                                                const codec = MediaSourceConstants.PREFERRED_CODEC_ORDER[i];
    17591760                                                if ((codec in ctx.audio_codecs) && (ctx.server_audio_codecs.indexOf(codec)>=0)){
    17601761                                                        if (ctx.mediasource_codecs[codec]) {
    17611762                                                                ctx.audio_framework = "mediasource";
     
    18031804        ctx.remote_printing = Boolean(hello["printing"]);
    18041805        if (ctx.remote_printing && ctx.printing) {
    18051806                // send our printer definition
    1806                 var printers = {
     1807                const printers = {
    18071808                        "HTML5 client": {
    18081809                                "printer-info": "Print to PDF in client browser",
    18091810                                "printer-make-and-model": "HTML5 client version",
     
    18331834}
    18341835
    18351836XpraClient.prototype._process_encodings = function(packet, ctx) {
    1836         var caps = packet[1];
     1837        const caps = packet[1];
    18371838        ctx.log("update encodings:", caps);
    18381839}
    18391840
     
    18401841
    18411842XpraClient.prototype.process_xdg_menu = function() {
    18421843        this.log("received xdg start menu data");
    1843         var key;
     1844        let key;
    18441845        //remove current menu:
    18451846        $('#startmenu li').remove();
    1846         var startmenu = document.getElementById("startmenu");
     1847        const startmenu = document.getElementById("startmenu");
    18471848        for(key in this.xdg_menu){
    1848                 var category = this.xdg_menu[key];
    1849                 var li = document.createElement("li");
     1849                const category = this.xdg_menu[key];
     1850                const li = document.createElement("li");
    18501851                li.className = "-hasSubmenu";
    18511852
    1852                 var catDivLeft = document.createElement("div");
     1853                const catDivLeft = document.createElement("div");
    18531854                        catDivLeft.className="menu-divleft";
    18541855                catDivLeft.appendChild(this.xdg_image(category.IconData, category.IconType));
    18551856
    1856                 var a = document.createElement("a");
     1857                const a = document.createElement("a");
    18571858                a.appendChild(catDivLeft);
    18581859                a.appendChild(document.createTextNode(this.xdg_menu[key].Name));
    18591860                a.href = "#";
    18601861                li.appendChild(a);
    18611862
    1862                 var ul = document.createElement("ul");
     1863                const ul = document.createElement("ul");
    18631864
    18641865                //TODO need to figure out how to do this properly
    18651866                a.onmouseenter= function(){
     
    18691870                        this.parentElement.childNodes[1].className="";
    18701871                };
    18711872
    1872                 var xdg_menu_cats = category.Entries;
     1873                const xdg_menu_cats = category.Entries;
    18731874                for(key in xdg_menu_cats){
    1874                         var entry = xdg_menu_cats[key];
    1875                         var li2 = document.createElement("li");
    1876                         var a2 = document.createElement("a");
     1875                        const entry = xdg_menu_cats[key];
     1876                        const li2 = document.createElement("li");
     1877                        const a2 = document.createElement("a");
    18771878
    1878                         var name = entry.Name;
     1879                        let name = entry.Name;
    18791880                        name = Utilities.trimString(name,15);
    1880                         var command = entry.Exec.replace(/%[uUfF]/g,"");
     1881                        const command = entry.Exec.replace(/%[uUfF]/g, "");
    18811882
    1882                         var divLeft = document.createElement("div");
     1883                        const divLeft = document.createElement("div");
    18831884                        divLeft.className = "menu-divleft";
    18841885                        divLeft.appendChild(this.xdg_image(entry.IconData, entry.IconType));
    18851886
    1886                         var titleDiv = document.createElement("div");
     1887                        const titleDiv = document.createElement("div");
    18871888                        titleDiv.appendChild(document.createTextNode(name));
    18881889                        titleDiv.className = "menu-content-left";
    18891890                        divLeft.appendChild(titleDiv);
     
    18911892                        a2.appendChild(divLeft);
    18921893                        a2.title = command;
    18931894
    1894                         var me = this;
     1895                        const me = this;
    18951896                        a2.onclick = function(){
    1896                                 var ignore = "False";
     1897                                const ignore = "False";
    18971898                                me.start_command(this.innerText, this.title, ignore);
    18981899                                document.getElementById("menu_list").className="-hide";
    18991900                        };
     
    19141915
    19151916
    19161917XpraClient.prototype._process_setting_change = function(packet, ctx) {
    1917         var setting = packet[1],
     1918        const setting = packet[1],
    19181919                value = packet[2];
    19191920        if (setting=="xdg-menu") {
    19201921                ctx.xdg_menu = value;
     
    19251926}
    19261927
    19271928XpraClient.prototype.xdg_image = function(icon_data, icon_type) {
    1928         var img = new Image();
     1929        const img = new Image();
    19291930        if (typeof icon_data !== 'undefined'){
    19301931                if (typeof icon_data === 'string') {
    19311932                        icon_data = Utilities.StringToUint8(icon_data);
     
    19641965                        return;
    19651966                }
    19661967        }
    1967         var digest = packet[3];
    1968         var server_salt = packet[1];
    1969         var client_salt = null;
    1970         var salt_digest = packet[4] || "xor";
    1971         var l = server_salt.length;
     1968        const digest = packet[3];
     1969        const server_salt = packet[1];
     1970        let client_salt = null;
     1971        const salt_digest = packet[4] || "xor";
     1972        let l = server_salt.length;
    19721973        if (salt_digest=="xor") {
    19731974                //don't use xor over unencrypted connections unless explicitly allowed:
    19741975                if (digest == "xor") {
     
    19881989        }
    19891990        client_salt = Utilities.getSalt(l);
    19901991        ctx.clog("challenge using salt digest", salt_digest);
    1991         var salt = ctx._gendigest(salt_digest, client_salt, server_salt);
     1992        const salt = ctx._gendigest(salt_digest, client_salt, server_salt);
    19921993        if (!salt) {
    19931994                this.callback_close("server requested an unsupported salt digest " + salt_digest);
    19941995                return;
    19951996        }
    19961997        ctx.clog("challenge using digest", digest);
    1997         var challenge_response = ctx._gendigest(digest, ctx.password, salt);
     1998        const challenge_response = ctx._gendigest(digest, ctx.password, salt);
    19981999        if (challenge_response) {
    19992000                ctx._send_hello(challenge_response, client_salt);
    20002001        }
     
    20052006
    20062007XpraClient.prototype._gendigest = function(digest, password, salt) {
    20072008        if (digest.startsWith("hmac")) {
    2008                 var hash="md5";
     2009                let hash = "md5";
    20092010                if (digest.indexOf("+")>0) {
    20102011                        hash = digest.split("+")[1];
    20112012                }
    20122013                this.clog("hmac using hash", hash);
    2013                 var hmac = forge.hmac.create();
     2014                const hmac = forge.hmac.create();
    20142015                hmac.start(hash, password);
    20152016                hmac.update(salt);
    20162017                return hmac.digest().toHex();
    20172018        } else if (digest == "xor") {
    2018                 var trimmed_salt = salt.slice(0, password.length);
     2019                const trimmed_salt = salt.slice(0, password.length);
    20192020                return Utilities.xorString(trimmed_salt, password);
    20202021        } else {
    20212022                return null;
     
    20272028        if (this.reconnect_in_progress) {
    20282029                return;
    20292030        }
    2030         var me = this;
    2031         var now_ms = Math.ceil(Utilities.monotonicTime());
     2031        const me = this;
     2032        const now_ms = Math.ceil(Utilities.monotonicTime());
    20322033        this.send(["ping", now_ms]);
    20332034        // add timeout to wait for ping timout
    20342035        this.ping_timeout_timer = setTimeout(function () {
     
    20352036                me._check_echo_timeout(now_ms);
    20362037        }, this.PING_TIMEOUT);
    20372038        // add timeout to detect temporary ping miss for spinners
    2038         var wait = 2000;
     2039        const wait = 2000;
    20392040        this.ping_grace_timer = setTimeout(function () {
    20402041                me._check_server_echo(now_ms);
    20412042        }, wait);
     
    20422043}
    20432044
    20442045XpraClient.prototype._process_ping = function(packet, ctx) {
    2045         var echotime = packet[1];
     2046        const echotime = packet[1];
    20462047        ctx.last_ping_server_time = echotime;
    20472048        if (packet.length>2) {
    20482049                //prefer system time (packet[1] is monotonic)
    20492050                ctx.last_ping_server_time = packet[2];
    20502051        }
    2051         var sid = "";
     2052        let sid = "";
    20522053        if (packet.length>=4) {
    20532054                sid = packet[3];
    20542055        }
    20552056        ctx.last_ping_local_time = new Date().getTime();
    2056         var l1=0, l2=0, l3=0;
     2057        const l1 = 0, l2=0, l3=0;
    20572058        ctx.send(["ping_echo", echotime, l1, l2, l3, 0, sid]);
    20582059}
    20592060
    20602061XpraClient.prototype._process_ping_echo = function(packet, ctx) {
    20612062        ctx.last_ping_echoed_time = packet[1];
    2062         var l1 = packet[2],
     2063        const l1 = packet[2],
    20632064                l2 = packet[3],
    20642065                l3 = packet[4];
    20652066        ctx.client_ping_latency = packet[5];
     
    20752076 */
    20762077XpraClient.prototype.start_info_timer = function() {
    20772078        if (this.info_timer==null) {
    2078                 var me = this;
     2079                const me = this;
    20792080                this.info_timer = setInterval(function () {
    20802081                        if (me.info_timer!=null) {
    20812082                                me.send_info_request();
     
    20942095        ctx.info_request_pending = false;
    20952096        ctx.server_last_info = packet[1];
    20962097        ctx.debug("network", "info-response:", ctx.server_last_info);
    2097         var event = document.createEvent("Event");
     2098        const event = document.createEvent("Event");
    20982099        event.initEvent('info-response', true, true);
    20992100        event.data = ctx.server_last_info;
    21002101        document.dispatchEvent(event);
     
    21122113 * System Tray forwarding
    21132114 */
    21142115XpraClient.prototype._process_new_tray = function(packet, ctx) {
    2115         var wid = packet[1],
    2116                 w = packet[2],
    2117                 h = packet[3],
    2118                 metadata = packet[4];
    2119         var mydiv = document.createElement("div");
     2116        const wid = packet[1];
     2117        let w = packet[2];
     2118        let h = packet[3];
     2119        const metadata = packet[4];
     2120        const mydiv = document.createElement("div");
    21202121        mydiv.id = String(wid);
    2121         var mycanvas = document.createElement("canvas");
     2122        const mycanvas = document.createElement("canvas");
    21222123        mydiv.appendChild(mycanvas);
    21232124
    2124         var float_tray = document.getElementById("float_tray");
    2125         var float_menu = document.getElementById("float_menu");
     2125        const float_tray = document.getElementById("float_tray");
     2126        const float_menu = document.getElementById("float_menu");
    21262127        $('#float_menu').children().show();
    21272128        //increase size for tray icon
    2128         var new_width = float_menu_width + float_menu_item_size - float_menu_padding + 5;
     2129        const new_width = float_menu_width + float_menu_item_size - float_menu_padding + 5;
    21292130        float_menu.style.width = new_width + "px";
    21302131        float_menu_width=$('#float_menu').width() + 10;
    21312132        mydiv.style.backgroundColor = "white";
    21322133
    21332134        float_tray.appendChild(mydiv);
    2134         var x = 0;
    2135         var y = 0;
     2135        const x = 0;
     2136        const y = 0;
    21362137        w = float_menu_item_size;
    21372138        h = float_menu_item_size;
    21382139
    21392140        mycanvas.width = w;
    21402141        mycanvas.height = h;
    2141         var win = new XpraWindow(ctx, mycanvas, wid, x, y, w, h,
     2142        const win = new XpraWindow(ctx, mycanvas, wid, x, y, w, h,
    21422143                metadata,
    21432144                false,
    21442145                true,
     
    21552156        ctx.send_tray_configure(wid);
    21562157}
    21572158XpraClient.prototype.send_tray_configure = function(wid) {
    2158         var div = jQuery("#" + String(wid));
    2159         var x = Math.round(div.offset().left);
    2160         var y = Math.round(div.offset().top);
    2161         var w = float_menu_item_size,
     2159        const div = jQuery("#" + String(wid));
     2160        const x = Math.round(div.offset().left);
     2161        const y = Math.round(div.offset().top);
     2162        const w = float_menu_item_size,
    21622163                h = float_menu_item_size;
    21632164        this.clog("tray", wid, "position:", x, y);
    21642165        this.send(["configure-window", Number(wid), x, y, w, h, {}]);
     
    21742175}
    21752176
    21762177XpraClient.prototype.reconfigure_all_trays = function() {
    2177         var float_menu = document.getElementById("float_menu");
     2178        const float_menu = document.getElementById("float_menu");
    21782179        float_menu_width = (float_menu_item_size*4) + float_menu_padding;
    2179         for (var twid in this.id_to_window) {
    2180                 var twin = this.id_to_window[twid];
     2180        for (const twid in this.id_to_window) {
     2181                const twin = this.id_to_window[twid];
    21812182                if (twin && twin.tray) {
    21822183                        float_menu_width = float_menu_width + float_menu_item_size;
    21832184                        this.send_tray_configure(twid);
     
    21952196 */
    21962197XpraClient.prototype._new_window = function(wid, x, y, w, h, metadata, override_redirect, client_properties) {
    21972198        // each window needs their own DIV that contains a canvas
    2198         var mydiv = document.createElement("div");
     2199        const mydiv = document.createElement("div");
    21992200        mydiv.id = String(wid);
    2200         var mycanvas = document.createElement("canvas");
     2201        const mycanvas = document.createElement("canvas");
    22012202        mydiv.appendChild(mycanvas);
    2202         var screen = document.getElementById("screen");
     2203        const screen = document.getElementById("screen");
    22032204        screen.appendChild(mydiv);
    22042205        // set initial sizes
    22052206        mycanvas.width = w;
    22062207        mycanvas.height = h;
    22072208        // create the XpraWindow object to own the new div
    2208         var win = new XpraWindow(this, mycanvas, wid, x, y, w, h,
     2209        const win = new XpraWindow(this, mycanvas, wid, x, y, w, h,
    22092210                metadata,
    22102211                override_redirect,
    22112212                false,
     
    22192220                this._window_closed
    22202221                );
    22212222        if(win && !override_redirect && win.metadata["window-type"]=="NORMAL"){
    2222                 var decodedTitle = decodeURIComponent(escape(win.title));
    2223                 var trimmedTitle = Utilities.trimString(decodedTitle,30);
     2223                const decodedTitle = decodeURIComponent(escape(win.title));
     2224                const trimmedTitle = Utilities.trimString(decodedTitle,30);
    22242225                window.addWindowListItem(wid, trimmedTitle);
    22252226        }
    22262227        this.id_to_window[wid] = win;
    22272228        if (!override_redirect) {
    2228                 var geom = win.get_internal_geometry();
     2229                const geom = win.get_internal_geometry();
    22292230                this.send(["map-window", wid, geom.x, geom.y, geom.w, geom.h, this._get_client_properties(win)]);
    22302231                this._window_set_focus(win);
    22312232        }
     
    22322233}
    22332234
    22342235XpraClient.prototype._new_window_common = function(packet, override_redirect) {
    2235         var wid = packet[1],
    2236                 x = packet[2],
    2237                 y = packet[3],
    2238                 w = packet[4],
    2239                 h = packet[5],
    2240                 metadata = packet[6];
     2236        const wid = packet[1];
     2237        let x = packet[2];
     2238        let y = packet[3];
     2239        const w = packet[4];
     2240        let h = packet[5];
     2241        const metadata = packet[6];
    22412242        if (wid in this.id_to_window)
    22422243                throw new Error("we already have a window " + wid);
    22432244        if (w<=0 || h<=0) {
     
    22442245                this.error("window dimensions are wrong:", w, h);
    22452246                w, h = 1, 1;
    22462247        }
    2247         var client_properties = {}
     2248        let client_properties = {}
    22482249        if (packet.length>=8)
    22492250                client_properties = packet[7];
    22502251        if (x==0 && y==0 && !metadata["set-initial-position"]) {
    22512252                //find a good position for it
    2252                 var l = Object.keys(this.id_to_window).length;
     2253                const l = Object.keys(this.id_to_window).length;
    22532254                if (l==0) {
    22542255                        //first window: center it
    22552256                        if (w<=this.desktop_width) {
     
    22732274}
    22742275
    22752276XpraClient.prototype._get_client_properties = function(win) {
    2276         var cp = win.client_properties;
     2277        const cp = win.client_properties;
    22772278        cp["encodings.rgb_formats"] = this.RGB_FORMATS;
    22782279        return cp;
    22792280}
     
    22812282XpraClient.prototype._window_geometry_changed = function(win) {
    22822283        // window callbacks are called from the XpraWindow function context
    22832284        // so use win.client instead of `this` to refer to the client
    2284         var geom = win.get_internal_geometry();
    2285         var wid = win.wid;
     2285        const geom = win.get_internal_geometry();
     2286        const wid = win.wid;
    22862287        win.client.send(["configure-window", wid, geom.x, geom.y, geom.w, geom.h, win.client._get_client_properties(win)]);
    22872288}
    22882289
     
    22952296}
    22962297
    22972298XpraClient.prototype._process_window_metadata = function(packet, ctx) {
    2298         var wid = packet[1],
     2299        const wid = packet[1],
    22992300                metadata = packet[2],
    23002301                win = ctx.id_to_window[wid];
    23012302        if (win!=null) {
     
    23042305}
    23052306
    23062307XpraClient.prototype._process_initiate_moveresize = function(packet, ctx) {
    2307         var wid = packet[1],
     2308        const wid = packet[1],
    23082309                win = ctx.id_to_window[wid];
    23092310        if (win!=null) {
    2310                 var x_root = packet[2],
     2311                const x_root = packet[2],
    23112312                        y_root = packet[3],
    23122313                        direction = packet[4],
    23132314                        button = packet[5],
     
    23172318}
    23182319
    23192320XpraClient.prototype._process_pointer_position = function(packet, ctx) {
    2320         var wid = packet[1],
    2321                 x = packet[2],
     2321        const wid = packet[1];
     2322        let x = packet[2],
    23222323                y = packet[3];
    2323         var win = ctx.id_to_window[wid];
     2324        const win = ctx.id_to_window[wid];
    23242325        if (packet.length>=6) {
    23252326                //we can use window relative coordinates:
    23262327                if (win) {
     
    23282329                        y = win.y + packet[5];
    23292330                }
    23302331        }
    2331         var shadow_pointer = document.getElementById("shadow_pointer");
    2332         var style = shadow_pointer.style;
    2333         var cursor_url = null,
     2332        const shadow_pointer = document.getElementById("shadow_pointer");
     2333        const style = shadow_pointer.style;
     2334        let cursor_url = null,
    23342335                w = 32,
    23352336                h = 32,
    23362337                xhot = 0,
     
    23642365}
    23652366
    23662367XpraClient.prototype._process_lost_window = function(packet, ctx) {
    2367         var wid = packet[1];
    2368         var win = ctx.id_to_window[wid];
     2368        const wid = packet[1];
     2369        const win = ctx.id_to_window[wid];
    23692370        if(win && !win.override_redirect && win.metadata["window-type"]=="NORMAL"){
    23702371                window.removeWindowListItem(wid);
    23712372        }
     
    23882389}
    23892390
    23902391XpraClient.prototype._process_raise_window = function(packet, ctx) {
    2391         var wid = packet[1];
    2392         var win = ctx.id_to_window[wid];
     2392        const wid = packet[1];
     2393        const win = ctx.id_to_window[wid];
    23932394        if (win!=null) {
    23942395                ctx._window_set_focus(win);
    23952396        }
     
    23962397}
    23972398
    23982399XpraClient.prototype._process_window_resized = function(packet, ctx) {
    2399         var wid = packet[1];
    2400         var width = packet[2];
    2401         var height = packet[3];
    2402         var win = ctx.id_to_window[wid];
     2400        const wid = packet[1];
     2401        const width = packet[2];
     2402        const height = packet[3];
     2403        const win = ctx.id_to_window[wid];
    24032404        if (win!=null) {
    24042405                win.resize(width, height);
    24052406        }
     
    24062407}
    24072408
    24082409XpraClient.prototype._process_window_move_resize = function(packet, ctx) {
    2409         var wid = packet[1];
    2410         var x = packet[2];
    2411         var y = packet[3];
    2412         var width = packet[4];
    2413         var height = packet[5];
    2414         var win = ctx.id_to_window[wid];
     2410        const wid = packet[1];
     2411        const x = packet[2];
     2412        const y = packet[3];
     2413        const width = packet[4];
     2414        const height = packet[5];
     2415        const win = ctx.id_to_window[wid];
    24152416        if (win!=null) {
    24162417                win.move_resize(x, y, width, height);
    24172418        }
     
    24182419}
    24192420
    24202421XpraClient.prototype._process_configure_override_redirect = function(packet, ctx) {
    2421         var wid = packet[1];
    2422         var x = packet[2];
    2423         var y = packet[3];
    2424         var width = packet[4];
    2425         var height = packet[5];
    2426         var win = ctx.id_to_window[wid];
     2422        const wid = packet[1];
     2423        const x = packet[2];
     2424        const y = packet[3];
     2425        const width = packet[4];
     2426        const height = packet[5];
     2427        const win = ctx.id_to_window[wid];
    24272428        if (win!=null) {
    24282429                win.move_resize(x, y, width, height);
    24292430        }
     
    24362437}
    24372438
    24382439XpraClient.prototype._process_bell = function(packet, ctx) {
    2439         var percent = packet[3];
    2440         var pitch = packet[4];
    2441         var duration = packet[5];
     2440        const percent = packet[3];
     2441        const pitch = packet[4];
     2442        const duration = packet[5];
    24422443        if (ctx.audio_context!=null) {
    2443                 var oscillator = ctx.audio_context.createOscillator();
    2444                 var gainNode = ctx.audio_context.createGain();
     2444                const oscillator = ctx.audio_context.createOscillator();
     2445                const gainNode = ctx.audio_context.createGain();
    24452446                oscillator.connect(gainNode);
    24462447                gainNode.connect(ctx.audio_context.destination);
    24472448                gainNode.gain.setValueAtTime(percent, ctx.audio_context.currentTime);
     
    24502451                setTimeout(function(){oscillator.stop()}, duration);
    24512452        }
    24522453        else {
    2453                 var snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
     2454                const snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
    24542455                snd.play();
    24552456        }
    24562457        return;
     
    24622463XpraClient.prototype._process_notify_show = function(packet, ctx) {
    24632464        //TODO: add UI switch to disable notifications
    24642465        //unused:
    2465         //var dbus_id = packet[1];
    2466         //var app_name = packet[3];
    2467         //var app_icon = packet[5];
    2468         var nid = packet[2];
    2469         var replaces_nid = packet[4];
    2470         var summary = packet[6];
    2471         var body = packet[7];
    2472         var expire_timeout = packet[8];
    2473         var icon = packet[9];
    2474         var actions = packet[10];
    2475         var hints = packet[11];
     2466        //const dbus_id = packet[1];
     2467        //const app_name = packet[3];
     2468        //const app_icon = packet[5];
     2469        const nid = packet[2];
     2470        const replaces_nid = packet[4];
     2471        const summary = packet[6];
     2472        const body = packet[7];
     2473        const expire_timeout = packet[8];
     2474        const icon = packet[9];
     2475        const actions = packet[10];
     2476        const hints = packet[11];
    24762477        if(window.closeNotification) {
    24772478                if (replaces_nid>0) {
    24782479                        window.closeNotification(replaces_nid);
     
    24822483
    24832484        if ("Notification" in window && actions.length==0) {
    24842485                function notify() {
    2485                         var icon_url = "";
     2486                        let icon_url = "";
    24862487                        if (icon) {
    24872488                                icon_url = "data:image/png;base64," + Utilities.ArrayBufferToBase64(icon);
    24882489                        }
    24892490                        /*
    2490                         var nactions = [];
     2491                        const nactions = [];
    24912492                        if (actions) {
    24922493                                ctx.log("actions=", actions);
    2493                                 for (var i=0; i<actions.length/2;++i) {
     2494                                for (let i=0; i<actions.length/2;++i) {
    24942495                                        nactions.push({
    24952496                                                "action"        : actions[i*2],
    24962497                                                "title"         : actions[i*2+1],
     
    24972498                                        });
    24982499                                }
    24992500                        }*/
    2500                         var notification = new Notification(summary, { body: body, icon: icon_url });
     2501                        const notification = new Notification(summary, { body: body, icon: icon_url });
    25012502                        notification.onclose = function() {
    2502                                 var reason = 2; //closed by the user - best guess...
     2503                                const reason = 2;       //closed by the user - best guess...
    25032504                                ctx.send(["notification-close", nid, reason, ""]);
    25042505                        };
    25052506                        notification.onclick = function() {
     
    25452546 * Cursors
    25462547 */
    25472548XpraClient.prototype.reset_cursor = function(packet, ctx) {
    2548         for (var wid in ctx.id_to_window) {
    2549                 var window = ctx.id_to_window[wid];
     2549        for (const wid in ctx.id_to_window) {
     2550                const window = ctx.id_to_window[wid];
    25502551                window.reset_cursor();
    25512552        }
    25522553        return;
     
    25622563                return;
    25632564        }
    25642565        //we require a png encoded cursor packet:
    2565         var encoding = packet[1];
     2566        const encoding = packet[1];
    25662567        if (encoding!="png") {
    25672568                ctx.warn("invalid cursor encoding: "+encoding);
    25682569                return;
    25692570        }
    2570         var w = packet[4];
    2571         var h = packet[5];
    2572         var xhot = packet[6];
    2573         var yhot = packet[7];
    2574         var img_data = packet[9];
    2575         for (var wid in ctx.id_to_window) {
    2576                 var window = ctx.id_to_window[wid];
     2571        const w = packet[4];
     2572        const h = packet[5];
     2573        const xhot = packet[6];
     2574        const yhot = packet[7];
     2575        const img_data = packet[9];
     2576        for (const wid in ctx.id_to_window) {
     2577                const window = ctx.id_to_window[wid];
    25772578                window.set_cursor(encoding, w, h, xhot, yhot, img_data);
    25782579        }
    25792580}
    25802581
    25812582XpraClient.prototype._process_window_icon = function(packet, ctx) {
    2582         var wid = packet[1];
    2583         var w = packet[2];
    2584         var h = packet[3];
    2585         var encoding = packet[4];
    2586         var img_data = packet[5];
     2583        const wid = packet[1];
     2584        const w = packet[2];
     2585        const h = packet[3];
     2586        const encoding = packet[4];
     2587        const img_data = packet[5];
    25872588        ctx.debug("main", "window-icon: ", encoding, " size ", w, "x", h);
    2588         var win = ctx.id_to_window[wid];
     2589        const win = ctx.id_to_window[wid];
    25892590        if (win) {
    2590                 var src = win.update_icon(w, h, encoding, img_data);
     2591                const src = win.update_icon(w, h, encoding, img_data);
    25912592                //update favicon too:
    25922593                if (wid==ctx.focus || ctx.server_is_desktop || ctx.server_is_shadow) {
    25932594                        jQuery("#favicon").attr("href", src);
     
    26302631                }
    26312632                // schedule a screen refresh if one is not already due:
    26322633                if (this.draw_pending==0) {
    2633                         var now = Utilities.monotonicTime();
     2634                        const now = Utilities.monotonicTime();
    26342635                        this.draw_pending = now;
    2635                         var me = this;
     2636                        const me = this;
    26362637                        window.requestAnimationFrame(function() {
    26372638                                me.debug("draw", "animation frame:", me.pending_redraw.length, "windows to paint, processing delay", Utilities.monotonicTime()-me.draw_pending, "ms");
    26382639                                me.draw_pending = 0;
    26392640                                // draw all the windows in the list:
    26402641                                while (me.pending_redraw.length>0) {
    2641                                         var w = me.pending_redraw.shift();
     2642                                        const w = me.pending_redraw.shift();
    26422643                                        w.draw();
    26432644                                }
    26442645                        });
     
    26572658                //no valid draw packet, likely handle errors for that here
    26582659                return;
    26592660        }
    2660         var ptype = packet[0],
     2661        const ptype = packet[0],
    26612662                wid = packet[1];
    2662         var win = ctx.id_to_window[wid];
     2663        const win = ctx.id_to_window[wid];
    26632664        if (ptype=="eos") {
    26642665                ctx.debug("draw", "eos for window", wid);
    26652666                if (win) {
     
    26682669                return;
    26692670        }
    26702671
    2671         var start = Utilities.monotonicTime(),
     2672        const start = Utilities.monotonicTime(),
    26722673                x = packet[2],
    26732674                y = packet[3],
    26742675                width = packet[4],
     
    26762677                coding = packet[6],
    26772678                data = packet[7],
    26782679                packet_sequence = packet[8],
    2679                 rowstride = packet[9],
    2680                 options = {};
     2680                rowstride = packet[9];
     2681        let options = {};
    26812682        if (packet.length>10)
    26822683                options = packet[10];
    2683         var protocol = ctx.protocol;
     2684        const protocol = ctx.protocol;
    26842685        if (!protocol) {
    26852686                return;
    26862687        }
     
    26972698                        width, height,
    26982699                        coding, data, packet_sequence, rowstride, options,
    26992700                        function (error) {
    2700                                 var flush = options["flush"] || 0;
    2701                                 var decode_time = -1;
     2701                                const flush = options["flush"] || 0;
     2702                                let decode_time = -1;
    27022703                                if(flush==0) {
    27032704                                        ctx.request_redraw(win);
    27042705                                }
     
    27312732        this.debug("audio", "init_audio() enabled=", this.audio_enabled, ", mediasource enabled=", this.audio_mediasource_enabled, ", aurora enabled=", this.audio_aurora_enabled, ", http-stream enabled=", this.audio_httpstream_enabled);
    27322733        if(this.audio_mediasource_enabled) {
    27332734                this.mediasource_codecs = MediaSourceUtil.getMediaSourceAudioCodecs(ignore_audio_blacklist);
    2734                 for (var codec_option in this.mediasource_codecs) {
     2735                for (const codec_option in this.mediasource_codecs) {
    27352736                        this.audio_codecs[codec_option] = this.mediasource_codecs[codec_option];
    27362737                }
    27372738        }
    27382739        if(this.audio_aurora_enabled) {
    27392740                this.aurora_codecs = MediaSourceUtil.getAuroraAudioCodecs();
    2740                 for (var codec_option in this.aurora_codecs) {
     2741                for (const codec_option in this.aurora_codecs) {
    27412742                        if(codec_option in this.audio_codecs) {
    27422743                                //we already have native MediaSource support!
    27432744                                continue;
     
    27462747                }
    27472748        }
    27482749        if (this.audio_httpstream_enabled) {
    2749                 var stream_codecs = ["mp3"];
    2750                 for (var i in stream_codecs) {
    2751                         var codec_option = stream_codecs[i];
     2750                const stream_codecs = ["mp3"];
     2751                for (const i in stream_codecs) {
     2752                        const codec_option = stream_codecs[i];
    27522753                        if (!(codec_option in this.audio_codecs)) {
    27532754                                this.audio_codecs[codec_option] = codec_option;
    27542755                        }
     
    27992800XpraClient.prototype._sound_start_receiving = function() {
    28002801        if (!this.audio_framework || !this.audio_codec) {
    28012802                //choose a codec + framework to use
    2802                 var codecs_supported = MediaSourceUtil.get_supported_codecs(this.audio_mediasource_enabled,
     2803                const codecs_supported = MediaSourceUtil.get_supported_codecs(this.audio_mediasource_enabled,
    28032804                                this.audio_aurora_enabled,
    28042805                                this.audio_httpstream_enabled,
    28052806                                false);
    2806                 var audio_codec = MediaSourceUtil.get_best_codec(codecs_supported);
     2807                const audio_codec = MediaSourceUtil.get_best_codec(codecs_supported);
    28072808                if (!audio_codec) {
    28082809                        this.log("no codec found");
    28092810                        return;
    28102811                }
    2811                 var acparts = audio_codec.split(":");
     2812                const acparts = audio_codec.split(":");
    28122813                this.audio_framework = acparts[0];
    28132814                this.audio_codec = acparts[1];
    28142815        }
     
    28422843        this.audio.setAttribute('autoplay', true);
    28432844        this.audio.setAttribute('controls', false);
    28442845        this.audio.setAttribute('loop', true);
    2845         var url = "http";
     2846        let url = "http";
    28462847        if (this.ssl) {
    28472848                url = "https";
    28482849        }
     
    28542855                url += "/";
    28552856        }
    28562857        url += "audio.mp3?uuid="+this.uuid;
    2857         var source = document.createElement("source");
     2858        const source = document.createElement("source");
    28582859        source.type = "audio/mpeg";
    28592860        source.src = url;
    28602861        this.audio.appendChild(source);
     
    28682869}
    28692870
    28702871XpraClient.prototype._sound_start_mediasource = function() {
    2871         var me = this;
     2872        const me = this;
    28722873
    28732874        function audio_error(event) {
    28742875                if(me.audio) {
     
    29132914                        return;
    29142915                }
    29152916                //ie: codec_string = "audio/mp3";
    2916                 var codec_string = MediaSourceConstants.CODEC_STRING[me.audio_codec];
     2917                const codec_string = MediaSourceConstants.CODEC_STRING[me.audio_codec];
    29172918                if(codec_string==null) {
    29182919                        me.error("invalid codec '"+me.audio_codec+"'");
    29192920                        me.close_audio();
     
    29222923                me.log("using audio codec string for "+me.audio_codec+": "+codec_string);
    29232924
    29242925                //Create a SourceBuffer:
    2925                 var asb = null;
     2926                let asb;
    29262927                try {
    29272928                        asb = me.media_source.addSourceBuffer(codec_string);
    29282929                } catch (e) {
     
    30203021        }
    30213022
    30223023        try {
    3023                 var codec = packet[1];
    3024                 var buf = packet[2];
    3025                 var options = packet[3];
    3026                 var metadata = packet[4];
     3024                const codec = packet[1];
     3025                const buf = packet[2];
     3026                const options = packet[3];
     3027                const metadata = packet[4];
    30273028
    30283029                if (options["start-of-stream"] == 1) {
    30293030                        ctx._audio_start_stream();
     
    30523053}
    30533054
    30543055XpraClient.prototype.add_sound_data = function(codec, buf, metadata) {
    3055         var MIN_START_BUFFERS = 4;
    3056         var MAX_BUFFERS = 250;
    3057         var CONCAT = true;
     3056        let MIN_START_BUFFERS = 4;
     3057        const MAX_BUFFERS = 250;
     3058        const CONCAT = true;
    30583059        this.debug("audio", "sound-data: ", codec, ", ", buf.length, "bytes");
    30593060        if (this.audio_buffers.length>=MAX_BUFFERS) {
    30603061                this.warn("audio queue overflowing: "+this.audio_buffers.length+", stopping");
     
    30653066        if (metadata) {
    30663067                this.debug("audio", "audio metadata=", metadata);
    30673068                //push metadata first:
    3068                 for (var i = 0; i < metadata.length; i++) {
     3069                for (let i = 0; i < metadata.length; i++) {
    30693070                        this.debug("audio", "metadata[", i, "]=", metadata[i], ", length=", metadata[i].length, ", type=", Object.prototype.toString.call(metadata[i]));
    30703071                        this.audio_buffers.push(Utilities.StringToUint8(metadata[i]));
    30713072                }
     
    30753076        if (buf != null) {
    30763077                this.audio_buffers.push(buf);
    30773078        }
    3078         var ab = this.audio_buffers;
     3079        const ab = this.audio_buffers;
    30793080        if (this._audio_ready() && (this.audio_buffers_count>0 || ab.length >= MIN_START_BUFFERS)) {
    30803081                if (CONCAT) {
    30813082                        if (ab.length==1) {
     
    30843085                        }
    30853086                        else {
    30863087                                //concatenate all pending buffers into one:
    3087                                 var size = 0;
    3088                                 for (var i=0,j=ab.length;i<j;++i) {
     3088                                let size = 0;
     3089                                for (let i=0,j=ab.length;i<j;++i) {
    30893090                                        size += ab[i].length;
    30903091                                }
    30913092                                buf = new Uint8Array(size);
    30923093                                size = 0;
    3093                                 for (var i=0,j=ab.length;i<j;++i) {
    3094                                         var v = ab[i];
     3094                                for (let i=0,j=ab.length;i<j;++i) {
     3095                                        const v = ab[i];
    30953096                                        if (v.length>0) {
    30963097                                                buf.set(v, size);
    30973098                                                size += v.length;
     
    31033104                }
    31043105                else {
    31053106                        this.audio_buffers_count += ab.length;
    3106                         for (var i=0,j=ab.length;i<j;++i) {
     3107                        for (let i=0,j=ab.length;i<j;++i) {
    31073108                                this.push_audio_buffer(ab[i]);
    31083109                        }
    31093110                }
     
    31173118                //nothing to do: ready to play
    31183119                return;
    31193120        }
     3121        const me = this;
    31203122        if (this.audio_framework=="mediasource") {
    3121                 var me = this;
    31223123                this.audio.play().then(function(result) {
    31233124                        me.debug("audio", "stream playing", result);
    31243125                }, function(err) {
     
    31443145                        this.debug("audio", "mediasource state=", MediaSourceConstants.READY_STATE[this.audio.readyState], ", network state=", MediaSourceConstants.NETWORK_STATE[this.audio.networkState]);
    31453146                        this.debug("audio", "audio paused=", this.audio.paused, ", queue size=", this.audio_buffers.length, ", source ready=", this.audio_source_ready, ", source buffer updating=", this.audio_source_buffer.updating);
    31463147                }
    3147                 var asb = this.audio_source_buffer;
     3148                const asb = this.audio_source_buffer;
    31483149                return (asb!=null) && (!asb.updating);
    31493150        }
    31503151        else {
     
    31553156XpraClient.prototype.push_audio_buffer = function(buf) {
    31563157        if (this.audio_framework=="mediasource") {
    31573158                this.audio_source_buffer.appendBuffer(buf);
    3158                 var b = this.audio_source_buffer.buffered;
     3159                const b = this.audio_source_buffer.buffered;
    31593160                if (b && b.length>=1) {
    3160                         //for (var i=0; i<b.length;i++) {
     3161                        //for (let i=0; i<b.length;i++) {
    31613162                        //      this.clog("buffered[", i, "]=", b.start(i), b.end(i));
    31623163                        //}
    3163                         var p = this.audio.played;
    3164                         //for (var i=0; i<p.length;i++) {
     3164                        const p = this.audio.played;
     3165                        //for (let i=0; i<p.length;i++) {
    31653166                        //      this.clog("played[", i, "]=", p.start(i), p.end(i));
    31663167                        //}
    3167                         var e = b.end(0)
    3168                         var buf_size = Math.round(1000*(e - this.audio.currentTime));
     3168                        const e = b.end(0);
     3169                        const buf_size = Math.round(1000*(e - this.audio.currentTime));
    31693170                        this.debug("audio", "buffer size=", buf_size, "ms, currentTime=", this.audio.currentTime);
    31703171                }
    31713172        }
     
    32043205                return;
    32053206        }
    32063207        this.debug("clipboard", "sending clipboard token with data:", data);
    3207         var claim = true;       //Boolean(navigator.clipboard && navigator.clipboard.readText && navigator.clipboard.writeText);
    3208         var greedy = true;
    3209         var synchronous = true;
    3210         var packet;
     3208        const claim = true;     //Boolean(navigator.clipboard && navigator.clipboard.readText && navigator.clipboard.writeText);
     3209        const greedy = true;
     3210        const synchronous = true;
     3211        let packet;
    32113212        if (data) {
    32123213                packet = ["clipboard-token", "CLIPBOARD", ["UTF8_STRING", "text/plain"],
    32133214                        "UTF8_STRING", "UTF8_STRING", 8, "bytes", data,
     
    32253226        if (!ctx.clipboard_enabled) {
    32263227                return;
    32273228        }
    3228         var selection = packet[1];
    3229         var targets = [];
    3230         var target = null;
    3231         var dtype = null;
    3232         var dformat = null;
    3233         var wire_encoding = null;
    3234         var wire_data = null;
     3229        const selection = packet[1];
     3230        let targets = [];
     3231        let target = null;
     3232        let dtype = null;
     3233        let dformat = null;
     3234        let wire_encoding = null;
     3235        let wire_data = null;
    32353236        if (packet.length>=3) {
    32363237                targets = packet[2];
    32373238        }
     
    32453246                ctx.clipboard_server_buffers[selection] = [target, dtype, dformat, wire_encoding, wire_data];
    32463247        }
    32473248
    3248         var is_valid_target = target && ctx.clipboard_targets.includes(target);
     3249        const is_valid_target = target && ctx.clipboard_targets.includes(target);
    32493250        ctx.debug("clipboard", "clipboard token received");
    32503251        ctx.debug("clipboard", "targets=", targets);
    32513252        ctx.debug("clipboard", "target=", target, "is valid:", is_valid_target);
     
    32583259        // when we get a click, control-C or control-X event
    32593260        // (when access to the clipboard is allowed)
    32603261        if (is_valid_target) {
    3261                 var is_text = dtype.toLowerCase().indexOf("text")>=0 || dtype.toLowerCase().indexOf("string")>=0;
     3262                const is_text = dtype.toLowerCase().indexOf("text")>=0 || dtype.toLowerCase().indexOf("string")>=0;
    32623263                if (is_text) {
    32633264                        try {
    32643265                                wire_data = Utilities.Uint8ToString(wire_data);
     
    32823283                }
    32833284                else if (CLIPBOARD_IMAGES && dtype=="image/png" && dformat==8 && wire_encoding=="bytes" && navigator.clipboard && navigator.clipboard.write) {
    32843285                        ctx.debug("clipboard", "png image received");
    3285                         var blob = new Blob([wire_data], {type: dtype});
     3286                        const blob = new Blob([wire_data], {type: dtype});
    32863287                        ctx.debug("clipboard", "created blob", blob);
    3287                         var item = new ClipboardItem({"image/png": blob});
     3288                        const item = new ClipboardItem({"image/png": blob});
    32883289                        ctx.debug("clipboard", "created ClipboardItem", item);
    3289                         var items = [item];
     3290                        const items = [item];
    32903291                        ctx.debug("clipboard", "created ClipboardItem list", items);
    32913292                        navigator.clipboard.write(items).then(function() {
    32923293                                ctx.debug("clipboard", "copied png image to clipboard");
     
    33093310XpraClient.prototype._process_clipboard_request = function(packet, ctx) {
    33103311        // we shouldn't be handling clipboard requests
    33113312        // unless we have support for navigator.clipboard:
    3312         var request_id = packet[1],
     3313        const request_id = packet[1],
    33133314                selection = packet[2];
    3314                 //target = packet[3];
     3315        //target = packet[3];
    33153316
    33163317        ctx.debug("clipboard", selection+" request");
    33173318
     
    33263327                if (navigator.clipboard.read) {
    33273328                        ctx.debug("clipboard", "request using read()");
    33283329                        navigator.clipboard.read().then(function(data) {
    3329                                 var item = null;
    3330                                 var itemtype = null;
     3330                                let item = null;
     3331                                let itemtype = null;
    33313332                                ctx.debug("clipboard", "request via read() data=", data);
    3332                                 for (var i = 0; i < data.length; i++) {
     3333                                for (let i = 0; i < data.length; i++) {
    33333334                                        item = data[i];
    33343335                                        ctx.debug("clipboard", "item", i, "types:", item.types);
    3335                                         for (var j = 0; j < item.types.length; j++) {
     3336                                        for (let j = 0; j < item.types.length; j++) {
    33363337                                                itemtype = item.types[j];
    33373338                                                if (itemtype == "text/plain") {
    33383339                                                        item.getType(itemtype).then(function(blob) {
    3339                                                                 var fileReader = new FileReader();
     3340                                                                const fileReader = new FileReader();
    33403341                                                                fileReader.onload = function(event) {
    33413342                                                                        ctx.send_clipboard_string(request_id, selection, event.target.result);
    33423343                                                                };
     
    33503351                                                }
    33513352                                                else if (itemtype == "image/png") {
    33523353                                                        item.getType(itemtype).then(function(blob) {
    3353                                                                 var fileReader = new FileReader();
     3354                                                                const fileReader = new FileReader();
    33543355                                                                fileReader.onload = function(event) {
    33553356                                                                        ctx.send_clipboard_contents(request_id, selection, itemtype, 8, "bytes", event.target.result);
    33563357                                                                };
     
    33753376                        ctx.debug("clipboard", "clipboard request using readText()");
    33763377                        navigator.clipboard.readText().then(function(text) {
    33773378                                ctx.debug("clipboard", "clipboard request via readText() text=", text);
    3378                                 var primary_server_buffer = ctx.clipboard_server_buffers["PRIMARY"];
     3379                                const primary_server_buffer = ctx.clipboard_server_buffers["PRIMARY"];
    33793380                                if (primary_server_buffer && primary_server_buffer[2]==8 && primary_server_buffer[3]=="bytes" && text==primary_server_buffer[4]) {
    33803381                                        //we have set the clipboard contents to the PRIMARY selection
    33813382                                        //and the server is asking for the CLIPBOARD selection
     
    33933394                        return;
    33943395                }
    33953396        }
    3396         var clipboard_buffer = ctx.get_clipboard_buffer() || "";
     3397        const clipboard_buffer = ctx.get_clipboard_buffer() || "";
    33973398        ctx.send_clipboard_string(request_id, selection, clipboard_buffer, "UTF8_STRING");
    33983399}
    33993400
    34003401XpraClient.prototype.resend_clipboard_server_buffer = function(request_id, selection) {
    3401         var server_buffer = this.clipboard_server_buffers["CLIPBOARD"];
     3402        const server_buffer = this.clipboard_server_buffers["CLIPBOARD"];
    34023403        this.debug("clipboard", "resend_clipboard_server_buffer:", server_buffer);
    34033404        if (!server_buffer) {
    34043405                this.send_clipboard_string(request_id, selection, "", "UTF8_STRING");
    34053406                return;
    34063407        }
    3407         var target = server_buffer[0];
    3408         var dtype = server_buffer[1];
    3409         var dformat = server_buffer[2];
    3410         var wire_encoding = server_buffer[3];
    3411         var wire_data = server_buffer[4];
     3408        const target = server_buffer[0];
     3409        const dtype = server_buffer[1];
     3410        const dformat = server_buffer[2];
     3411        const wire_encoding = server_buffer[3];
     3412        const wire_data = server_buffer[4];
    34123413        this.send_clipboard_contents(request_id, selection, dtype, dformat, wire_encoding, wire_data);
    34133414}
    34143415
    34153416XpraClient.prototype.send_clipboard_string = function(request_id, selection, clipboard_buffer, datatype) {
    3416         var packet;
     3417        let packet;
    34173418        if (clipboard_buffer == "") {
    34183419                packet = ["clipboard-contents-none", request_id, selection];
    34193420        } else {
     
    34243425}
    34253426
    34263427XpraClient.prototype.send_clipboard_contents = function(request_id, selection, datatype, dformat, encoding, clipboard_buffer) {
    3427         var packet;
     3428        let packet;
    34283429        if (clipboard_buffer == "") {
    34293430                packet = ["clipboard-contents-none", request_id, selection];
    34303431        } else {
     
    34373438 * File transfers and printing
    34383439 */
    34393440XpraClient.prototype._process_send_file = function(packet, ctx) {
    3440         var basefilename = packet[1];
    3441         var mimetype = packet[2];
    3442         var printit = packet[3];
    3443         var datasize = packet[5];
    3444         var data = packet[6];
     3441        const basefilename = packet[1];
     3442        const mimetype = packet[2];
     3443        const printit = packet[3];
     3444        const datasize = packet[5];
     3445        const data = packet[6];
    34453446
    34463447        // check the data size for file
    34473448        if(data.length != datasize) {
     
    34783479                return;
    34793480        }
    34803481        this.log("got "+data.length+" bytes of PDF to print");
    3481         var b64data = btoa(uintToString(data));
    3482         var win = window.open(
     3482        const b64data = btoa(uintToString(data));
     3483        const win = window.open(
    34833484                        'data:application/pdf;base64,'+b64data,
    34843485                        '_blank'
    34853486        );
     
    34943495                this.warn("cannot send file: file transfers are disabled!");
    34953496                return;
    34963497        }
    3497         var packet = ["send-file", filename, mimetype, false, this.remote_open_files, size, buffer, {}];
     3498        const packet = ["send-file", filename, mimetype, false, this.remote_open_files, size, buffer, {}];
    34983499        this.send(packet);
    34993500}
    35003501
    35013502XpraClient.prototype.start_command = function(name, command, ignore) {
    3502         var packet = ["start-command", name, command, ignore];
     3503        const packet = ["start-command", name, command, ignore];
    35033504        this.send(packet);
    35043505}
    35053506
    35063507XpraClient.prototype._process_open_url = function(packet, ctx) {
    3507         var url = packet[1];
    3508         //var send_id = packet[2];
     3508        const url = packet[1];
     3509        //const send_id = packet[2];
    35093510        if (!ctx.open_url) {
    35103511                ctx.cwarn("Warning: received a request to open URL '%s'", url);
    35113512                ctx.clog(" but opening of URLs is disabled");
     
    35123513                return
    35133514        }
    35143515        ctx.clog("opening url:", url);
    3515         var new_window = window.open(url, '_blank');
     3516        const new_window = window.open(url, '_blank');
    35163517        if(!new_window || new_window.closed || typeof new_window.closed=='undefined')
    35173518        {
    35183519                //Popup blocked, display link in notification
    3519                 var summary = "Open URL";
    3520                 var body = "<a href=\""+url+"\" target=\"_blank\">"+url+"</a>";
    3521                 var timeout = 10;
     3520                const summary = "Open URL";
     3521                const body = "<a href=\""+url+"\" target=\"_blank\">"+url+"</a>";
     3522                const timeout = 10;
    35223523                window.doNotification("", 0, summary, body, timeout, null, null, null, null, null);
    35233524        }
    35243525}
  • Keycodes.js

     
    5858                "ArrowUp"                       : "KP_Up",
    5959                "PageUp"                        : "KP_Prior",
    6060};
    61 for (var i=0; i<=9; i++) {
     61for (let i=0; i<=9; i++) {
    6262        KEY_TO_NAME["Numpad"+i] = ""+i;
    6363        KEY_TO_NAME["KP"+i]     = "KP"+i;
    6464}
    65 for (var i=1; i<=20; i++) {
     65for (let i=1; i<=20; i++) {
    6666        KEY_TO_NAME["F"+i]      = "F"+i;
    6767}
    6868
     
    16241624        " "                                     : "space",
    16251625        };
    16261626//console.debug("KEYSYM_TO_UNICODE=", KEYSYM_TO_UNICODE);
    1627 for (var keysym in KEYSYM_TO_UNICODE) {
    1628     var u = KEYSYM_TO_UNICODE[keysym];
    1629     var char = String.fromCharCode(u);
    1630     CHAR_TO_NAME[char] = keysym;
     1627for (let keysym in KEYSYM_TO_UNICODE) {
     1628        const u = KEYSYM_TO_UNICODE[keysym];
     1629        const char = String.fromCharCode(u);
     1630        CHAR_TO_NAME[char] = keysym;
    16311631}
    16321632//console.debug("CHAR_TO_NAME=", KEYSYM_TO_UNICODE);
    16331633
     
    17251725        221     : "bracketright",
    17261726        222     : "apostrophe",
    17271727};
    1728 for (var i=0; i<26; i++) {
     1728for (let i=0; i<26; i++) {
    17291729        CHARCODE_TO_NAME[65+i] = "abcdefghijklmnopqrstuvwxyz"[i];
    17301730}
    17311731for (i=0; i<10; i++) {
     
    17511751 * @returns {Array} of strings
    17521752 */
    17531753function get_event_modifiers(event) {
    1754         var modifiers = [];
     1754        const modifiers = [];
    17551755        if (event.getModifierState) {
    17561756                if (event.getModifierState("Control"))
    17571757                        modifiers.push("control");
  • MediaSourceUtil.js

     
    55 */
    66'use strict';
    77
    8 var MediaSourceConstants = {
     8const MediaSourceConstants = {
    99
    1010                CODEC_DESCRIPTION : {
    1111                                "mp4a"                  : 'mpeg4: aac',
     
    101101};
    102102
    103103
    104 var MediaSourceUtil = {
     104const MediaSourceUtil = {
    105105
    106106                getMediaSourceClass : function() {
    107107                        return window.MediaSource || window.WebKitMediaSource;
     
    108108                },
    109109
    110110                getMediaSource : function() {
    111                         var ms = MediaSourceUtil.getMediaSourceClass();
     111                        const ms = MediaSourceUtil.getMediaSourceClass();
    112112                        if(!ms) {
    113113                                throw new Error("no MediaSource support!");
    114114                        }
     
    120120                        if(Utilities.isIE()) {
    121121                                return {};
    122122                        }
    123                         var codecs_supported = {};
     123                        const codecs_supported = {};
    124124                        if(AV && AV.Decoder && AV.Decoder.find) {
    125                                 for (var codec_option in MediaSourceConstants.AURORA_CODECS) {
    126                                         var codec_string = MediaSourceConstants.AURORA_CODECS[codec_option];
    127                                         var decoder = AV.Decoder.find(codec_string);
     125                                for (const codec_option in MediaSourceConstants.AURORA_CODECS) {
     126                                        const codec_string = MediaSourceConstants.AURORA_CODECS[codec_option];
     127                                        const decoder = AV.Decoder.find(codec_string);
    128128                                        if(decoder) {
    129129                                                Utilities.log("audio codec aurora OK  '"+codec_option+"' / '"+codec_string+"'");
    130130                                                codecs_supported[codec_option] = codec_string;
     
    138138                },
    139139
    140140                getMediaSourceAudioCodecs : function(ignore_blacklist) {
    141                         var media_source_class = MediaSourceUtil.getMediaSourceClass();
     141                        const media_source_class = MediaSourceUtil.getMediaSourceClass();
    142142                        if(!media_source_class) {
    143143                                Utilities.log("audio forwarding: no media source API support");
    144144                                return [];
     
    147147                        if(Utilities.isIE()) {
    148148                                return [];
    149149                        }
    150                         var codecs_supported = [];
    151                         for (var codec_option in MediaSourceConstants.CODEC_STRING) {
    152                                 var codec_string = MediaSourceConstants.CODEC_STRING[codec_option];
     150                        const codecs_supported = [];
     151                        for (const codec_option in MediaSourceConstants.CODEC_STRING) {
     152                                const codec_string = MediaSourceConstants.CODEC_STRING[codec_option];
    153153                                try {
    154154                                        if(!media_source_class.isTypeSupported(codec_string)) {
    155155                                                Utilities.log("audio codec MediaSource NOK: '"+codec_option+"' / '"+codec_string+"'");
     
    156156                                                //add whitelisting here?
    157157                                                continue;
    158158                                        }
    159                                         var blacklist = [];
     159                                        let blacklist = [];
    160160                                        if (Utilities.isFirefox() || Utilities.isSafari()) {
    161161                                                blacklist += ["opus+mka", "vorbis+mka"];
    162162                                                if (Utilities.isSafari()) {
     
    191191                },
    192192
    193193                getSupportedAudioCodecs : function() {
    194                         var codecs_supported = MediaSourceUtil.getMediaSourceAudioCodecs();
    195                         var aurora_codecs = MediaSourceUtil.getAuroraAudioCodecs();
    196                         for (var codec_option in aurora_codecs) {
     194                        const codecs_supported = MediaSourceUtil.getMediaSourceAudioCodecs();
     195                        const aurora_codecs = MediaSourceUtil.getAuroraAudioCodecs();
     196                        for (const codec_option in aurora_codecs) {
    197197                                if(codec_option in codecs_supported) {
    198198                                        //we already have native MediaSource support!
    199199                                        continue;
     
    207207                        if(!codecs) {
    208208                                return null;
    209209                        }
    210                         var codec_options = Object.keys(codecs);
    211                         for (var i = 0; i < MediaSourceConstants.PREFERRED_CODEC_ORDER.length; i++) {
    212                                 var codec_option = MediaSourceConstants.PREFERRED_CODEC_ORDER[i];
     210                        const codec_options = Object.keys(codecs);
     211                        for (let i = 0; i < MediaSourceConstants.PREFERRED_CODEC_ORDER.length; i++) {
     212                                const codec_option = MediaSourceConstants.PREFERRED_CODEC_ORDER[i];
    213213                                if(codec_options.includes(codec_option)) {
    214214                                        return codec_option;
    215215                                }
     
    219219
    220220                addMediaSourceEventDebugListeners : function(media_source, source_type) {
    221221                        function debug_source_event(event) {
    222                                 var msg = ""+source_type+" source "+event;
     222                                let msg = ""+source_type+" source "+event;
    223223                                try {
    224224                                        msg += ": "+media_source.readyState;
    225225                                }
     
    251251
    252252                addSourceBufferEventDebugListeners : function(asb, element_type) {
    253253                        function debug_buffer_event(event) {
    254                                 var msg = ""+element_type+" buffer "+event;
     254                                const msg = ""+element_type+" buffer "+event;
    255255                                console.debug(msg);
    256256                        }
    257257                        asb.addEventListener('updatestart', function(e) { debug_buffer_event('updatestart'); });
     
    261261                },
    262262
    263263                get_supported_codecs : function(mediasource, aurora, http, ignore_audio_blacklist) {
    264                         var codecs_supported = {};
     264                        const codecs_supported = {};
    265265                        if (mediasource) {
    266                                 var mediasource_codecs = MediaSourceUtil.getMediaSourceAudioCodecs(ignore_audio_blacklist);
    267                                 for (var codec_option in mediasource_codecs) {
     266                                const mediasource_codecs = MediaSourceUtil.getMediaSourceAudioCodecs(ignore_audio_blacklist);
     267                                for (const codec_option in mediasource_codecs) {
    268268                                        codecs_supported["mediasource:"+codec_option] = MediaSourceConstants.CODEC_DESCRIPTION[codec_option];
    269269                                }
    270270                        }
    271271                        if (aurora) {
    272                                 var aurora_codecs = MediaSourceUtil.getAuroraAudioCodecs();
    273                                 for (var codec_option in aurora_codecs) {
     272                                const aurora_codecs = MediaSourceUtil.getAuroraAudioCodecs();
     273                                for (const codec_option in aurora_codecs) {
    274274                                        if(codec_option in codecs_supported) {
    275275                                                //we already have native MediaSource support!
    276276                                                continue;
     
    279279                                }
    280280                        }
    281281                        if (http) {
    282                                 var stream_codecs = ["mp3"];
    283                                 for (var i in stream_codecs) {
    284                                         var codec_option = stream_codecs[i];
     282                                const stream_codecs = ["mp3"];
     283                                for (const i in stream_codecs) {
     284                                        const codec_option = stream_codecs[i];
    285285                                        console.log("stream codecs=", stream_codecs, "codec=", codec_option);
    286286                                        codecs_supported["http-stream:"+codec_option] = "http stream: "+MediaSourceConstants.CODEC_DESCRIPTION[codec_option];
    287287                                }
     
    290290                },
    291291
    292292                get_best_codec : function(codecs_supported) {
    293                         var best_codec = null;
    294                         var best_distance = MediaSourceConstants.PREFERRED_CODEC_ORDER.length;
    295                         for (var codec_option in codecs_supported) {
    296                                 var cs = codec_option.split(":")[1];
    297                                 var distance = MediaSourceConstants.PREFERRED_CODEC_ORDER.indexOf(cs);
     293                        let best_codec = null;
     294                        let best_distance = MediaSourceConstants.PREFERRED_CODEC_ORDER.length;
     295                        for (const codec_option in codecs_supported) {
     296                                const cs = codec_option.split(":")[1];
     297                                const distance = MediaSourceConstants.PREFERRED_CODEC_ORDER.indexOf(cs);
    298298                                if (distance>=0 && distance<best_distance) {
    299299                                        best_codec = codec_option;
    300300                                        best_distance = distance;
  • Menu-custom.js

     
    2424*/
    2525
    2626function addWindowListItem(wid, title){
    27         var li = document.createElement("li");
     27        const li = document.createElement("li");
    2828        li.className="windowlist-li";
    2929        li.id = "windowlistitem"+wid;
    3030
    31         var a = document.createElement("a");
     31        const a = document.createElement("a");
    3232
    3333        a.id = "windowlistitemlink"+wid;
    3434
     
    4545                client._window_set_focus(client.id_to_window[wid]);
    4646        };
    4747
    48         var divLeft = document.createElement("div");
     48        const divLeft = document.createElement("div");
    4949        divLeft.id="windowlistdivleft"+wid;
    5050        divLeft.className="menu-divleft";
    51         var img = new Image();
     51        const img = new Image();
    5252        img.id = "windowlistitemicon"+wid;
    5353        img.src="/favicon.png";
    5454        img.className="menu-content-left";
    5555        divLeft.appendChild(img);
    5656
    57         var titleDiv = document.createElement("div");
     57        const titleDiv = document.createElement("div");
    5858        titleDiv.appendChild(document.createTextNode(title));
    5959        titleDiv.id = "windowlistitemtitle"+wid;
    6060        titleDiv.className="menu-content-left";
    6161        divLeft.appendChild(titleDiv);
    6262
    63         var divRight = document.createElement("div");
     63        const divRight = document.createElement("div");
    6464        divRight.className="menu-divright";
    6565
    66         var img2 = new Image();
     66        const img2 = new Image();
    6767        img2.id = "windowlistitemclose"+wid;
    6868        img2.src="icons/close.png";
    6969        img2.title="Close";
    7070        img2.className="menu-content-right";
    7171        img2.onclick=function(){client._window_closed(client.id_to_window[wid])};
    72         var img3 = new Image();
     72        const img3 = new Image();
    7373        img3.id = "windowlistitemmax"+wid;
    7474        img3.src="icons/maximize.png";
    7575        img3.title="Maximize";
    7676        img3.onclick=function(){client.id_to_window[wid].toggle_maximized()};
    7777        img3.className="menu-content-right";
    78         var img4 = new Image();
     78        const img4 = new Image();
    7979        img4.id = "windowlistitemmin"+wid;
    8080        img4.src="icons/minimize.png";
    8181        img4.title="Minimize";
     
    9393}
    9494
    9595function removeWindowListItem(itemId){
    96         var element = document.getElementById("windowlistitem" + itemId);
     96        const element = document.getElementById("windowlistitem" + itemId);
    9797        if(element && element.parentNode){
    9898                element.parentNode.removeChild(element);
    9999        }
  • Menu.js

     
    3131    }
    3232
    3333    function forEach(collection, iterator){
    34         for(var key in Object.keys(collection)){
     34        for(const key in Object.keys(collection)){
    3535            iterator(collection[key]);
    3636        }
    3737    }
    3838
    39     function showMenu(menu){
    40         var menu = this;
    41         var ul = $("ul", menu)[0];
     39    function showMenu(){
     40        const menu = this;
     41        const ul = $("ul", menu)[0];
    4242        //hack to hide the menu from javascript
    4343        if(!ul){
    4444                        return;
     
    6262        }, 25);
    6363    }
    6464
    65     function hideMenu(menu){
    66         var menu = this;
    67         var ul = $("ul", menu)[0];
     65    function hideMenu(){
     66        const menu = this;
     67        const ul = $("ul", menu)[0];
    6868
    6969        if(!ul || !ul.classList.contains("-visible")) return;
    7070
     
    7676        }, 300);
    7777    }
    7878
    79     function hideAllInactiveMenus(menu){
    80         var menu = this;
     79    function hideAllInactiveMenus(){
     80        const menu = this;
    8181        forEach(
    8282            $("li.-hasSubmenu.-active:not(:hover)", menu.parent),
    8383            function(e){
     
    8686        );
    8787    }
    8888
    89     function hideAllMenus(menu){
    90         var menu = this;
     89    function hideAllMenus(){
     90        const menu = this;
    9191        forEach(
    9292            $("li.-hasSubmenu", menu.parent),
    9393            function(e){
  • Notifications.js

     
    1313
    1414        window.doNotification = function(type, nid, title, message, timeout, icon, actions, hints, onAction, onClose){
    1515                console.debug("doNotification", type, nid, title, message, timeout, icon, actions, hints, onAction, onClose);
    16                 var nID = 'notification' + nid;
    17                 var a = $('<div id="' + nID + '" class="alert ' + type + '">'+
     16                const nID = 'notification' + nid;
     17                const a = $('<div id="' + nID + '" class="alert ' + type + '">'+
    1818                                        '<img class="notification_icon" id="notification_icon' + nID + '"></img>'+
    1919                                        '<span class="title">'+title+'</span>'+
    2020                                        '<span class="message">' + message + '</span>'+
     
    2222                                  '</div>');
    2323                $('.notifications').prepend(a);
    2424                if (actions) {
    25                         var notification_buttons = $('<div class="notification_buttons"></div>');
     25                        const notification_buttons = $('<div class="notification_buttons"></div>');
    2626                        a.append(notification_buttons);
    27                         for (var i = 0; i < actions.length; i+=2) {
    28                                 var action_id = actions[i];
    29                                 var action_label = actions[i+1];
    30                                 var notification_button = window._notification_button(nid, action_id, action_label, onAction, onClose);
     27                        for (let i = 0; i < actions.length; i+=2) {
     28                                const action_id = actions[i];
     29                                const action_label = actions[i+1];
     30                                const notification_button = window._notification_button(nid, action_id, action_label, onAction, onClose);
    3131                                notification_buttons.append(notification_button);
    3232                        }
    3333                }
    3434                $('.notifications').prepend(a);
    3535                if (icon) {
    36                         var encoding = icon[0],
     36                        const encoding = icon[0],
    3737                                //w = icon[1],
    3838                                //h = icon[2],
    3939                                img_data = icon[3];
    4040                        if (encoding=="png") {
    41                                 var src = "data:image/"+encoding+";base64," + window.btoa(img_data);
     41                                const src = "data:image/"+encoding+";base64," + window.btoa(img_data);
    4242                                $("#notification_icon"+nID).attr('src', src);
    4343                        }
    4444                }
     
    6161
    6262                if(timeout){
    6363                        a.data('timeLeft', timeout);
    64                         var it = setInterval(function() {
    65                                 var tleft = a.data('timeLeft') - 1;
     64                        const it = setInterval(function() {
     65                                const tleft = a.data('timeLeft') - 1;
    6666                                if (a.data('timeLeft') === 0) {
    6767                                        a.find('.dismiss').trigger('click');
    6868                                        if (onClose) {
     
    7979        };
    8080
    8181        window._notification_button = function(nid, action_id, action_label, onAction, onClose) {
    82                 var notification_button = $('<div class="notification_button" id=notification"'+action_id+'">'+action_label+'</div>');
     82                const notification_button = $('<div class="notification_button" id=notification"'+action_id+'">'+action_label+'</div>');
    8383                notification_button.on("click", function() {
    8484                        window.closeNotification(nid);
    8585                        if (onAction) {
     
    9393        }
    9494
    9595        window.cancelNotificationTimer = function(nid) {
    96                 var timer = window.notification_timers[nid];
     96                const timer = window.notification_timers[nid];
    9797                if (timer) {
    9898                        window.clearInterval(timer);
    9999                        delete window.notification_timers[nid];
     
    100100                }
    101101        }
    102102        window.cancelNotificationTimers = function() {
    103                 for (var nid in window.notification_timers) {
     103                for (const nid in window.notification_timers) {
    104104                        window.cancelNotificationTimer(nid);
    105105                }
    106106        }
     
    107107
    108108        window.closeNotification = function(nid) {
    109109                window.cancelNotificationTimer(nid);
    110                 var nID = 'notification' + nid;
     110                const nID = 'notification' + nid;
    111111                $('.notifications').find('#'+nID).find('.dismiss').trigger('click');
    112112        }
    113113
  • Protocol.js

     
    2929}
    3030
    3131XpraProtocolWorkerHost.prototype.open = function(uri) {
    32         var me = this;
     32        const me = this;
    3333        if (this.worker) {
    3434                //re-use the existing worker:
    3535                this.worker.postMessage({'c': 'o', 'u': uri});
     
    3737        }
    3838        this.worker = new Worker('js/Protocol.js');
    3939        this.worker.addEventListener('message', function(e) {
    40                 var data = e.data;
     40                const data = e.data;
    4141                switch (data.c) {
    4242                        case 'r':
    4343                                me.worker.postMessage({'c': 'o', 'u': uri});
     
    106106}
    107107
    108108XpraProtocol.prototype.open = function(uri) {
    109         var me = this;
     109        const me = this;
    110110        // (re-)init
    111111        this.raw_packets = [];
    112112        this.rQ = [];
     
    171171}
    172172
    173173XpraProtocol.prototype.do_process_receive_queue = function() {
    174         var i = 0, j = 0;
     174        let i = 0, j = 0;
    175175        if (this.header.length<8 && this.rQ.length>0) {
    176176                //add from receive queue data to header until we get the 8 bytes we need:
    177177                while (this.header.length<8 && this.rQ.length>0) {
    178                         var slice = this.rQ[0];
    179                         var needed = 8-this.header.length;
    180                         var n = Math.min(needed, slice.length);
     178                        const slice = this.rQ[0];
     179                        const needed = 8-this.header.length;
     180                        const n = Math.min(needed, slice.length);
    181181                        //copy at most n characters:
    182182                        for (i = 0; i < n; i++) {
    183183                                this.header.push(slice[i]);
     
    211211                return false;
    212212        }
    213213
    214         var proto_flags = this.header[1];
    215         var proto_crypto = proto_flags & 0x2;
     214        const proto_flags = this.header[1];
     215        const proto_crypto = proto_flags & 0x2;
    216216        if (proto_flags!=0) {
    217217                // check for crypto protocol flag
    218218                if (!(proto_crypto)) {
     
    221221                }
    222222        }
    223223
    224         var level = this.header[2];
     224        const level = this.header[2];
    225225        if (level & 0x20) {
    226226                this.protocol_error("lzo compression is not supported");
    227227                return false;
    228228        }
    229         var index = this.header[3];
     229        const index = this.header[3];
    230230        if (index>=20) {
    231231                this.protocol_error("invalid packet index: "+index);
    232232                return false;
    233233        }
    234         var packet_size = 0;
     234        let packet_size = 0;
    235235        for (i=0; i<4; i++) {
    236236                packet_size = packet_size*0x100;
    237237                packet_size += this.header[4+i];
     
    238238        }
    239239
    240240        // work out padding if necessary
    241         var padding = 0
     241        let padding = 0;
    242242        if (proto_crypto) {
    243243                padding = (this.cipher_in_block_size - packet_size % this.cipher_in_block_size);
    244244                packet_size += padding;
     
    245245        }
    246246
    247247        // verify that we have enough data for the full payload:
    248         var rsize = 0;
     248        let rsize = 0;
    249249        for (i=0,j=this.rQ.length;i<j;++i) {
    250250                rsize += this.rQ[i].length;
    251251        }
     
    256256        // done parsing the header, the next packet will need a new one:
    257257        this.header = [];
    258258
    259         var packet_data = null;
     259        let packet_data = null;
    260260        if (this.rQ[0].length==packet_size) {
    261261                //exact match: the payload is in a buffer already:
    262262                packet_data = this.rQ.shift();
     
    266266                packet_data = new Uint8Array(packet_size);
    267267                rsize = 0;
    268268                while (rsize < packet_size) {
    269                         var slice = this.rQ[0];
    270                         var needed = packet_size - rsize;
     269                        const slice = this.rQ[0];
     270                        const needed = packet_size - rsize;
    271271                        //console.log("slice:", slice.length, "bytes, needed", needed);
    272272                        if (slice.length>needed) {
    273273                                //add part of this slice:
     
    287287        // decrypt if needed
    288288        if (proto_crypto) {
    289289                this.cipher_in.update(forge.util.createBuffer(uintToString(packet_data)));
    290                 var decrypted = this.cipher_in.output.getBytes();
     290                const decrypted = this.cipher_in.output.getBytes();
    291291                packet_data = [];
    292292                for (i=0; i<decrypted.length; i++)
    293293                        packet_data.push(decrypted[i].charCodeAt(0));
     
    296296
    297297        //decompress it if needed:
    298298        if (level!=0) {
     299                let inflated;
    299300                if (level & 0x10) {
    300301                        // lz4
    301302                        // python-lz4 inserts the length of the uncompressed data as an int
    302303                        // at the start of the stream
    303                         var d = packet_data.subarray(0, 4);
     304                        const d = packet_data.subarray(0, 4);
    304305                        // output buffer length is stored as little endian
    305                         var length = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
     306                        const length = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
    306307                        // decode the LZ4 block
    307308                        // console.log("lz4 decompress packet size", packet_size, ", lz4 length=", length);
    308                         var inflated = new Uint8Array(length);
    309                         var uncompressedSize = LZ4.decodeBlock(packet_data, inflated, 4);
     309                        inflated = new Uint8Array(length);
     310                        const uncompressedSize = LZ4.decodeBlock(packet_data, inflated, 4);
    310311                        // if lz4 errors out at the end of the buffer, ignore it:
    311312                        if (uncompressedSize<=0 && packet_size+uncompressedSize!=0) {
    312313                                this.protocol_error("failed to decompress lz4 data, error code: "+uncompressedSize);
     
    316317                        inflated = BrotliDecode(packet_data);
    317318                } else {
    318319                        // zlib
    319                         var inflated = new Zlib.Inflate(packet_data).decompress();
     320                        inflated = new Zlib.Inflate(packet_data).decompress();
    320321                }
    321322                //debug("inflated("+packet_data+")="+inflated);
    322323                packet_data = inflated;
     
    328329                this.raw_packets[index] = packet_data;
    329330        } else {
    330331                //decode raw packet string into objects:
    331                 var packet = null;
     332                let packet = null;
    332333                try {
    333334                        packet = bdecode(packet_data);
    334                         for (var index in this.raw_packets) {
     335                        for (let index in this.raw_packets) {
    335336                                packet[index] = this.raw_packets[index];
    336337                        }
    337338                        this.raw_packets = {}
     
    345346                try {
    346347                        // pass to our packet handler
    347348                        if((packet[0] === 'draw') && (packet[6] !== 'scroll')){
    348                                 var img_data = packet[7];
     349                                const img_data = packet[7];
    349350                                if (typeof img_data === 'string') {
    350                                         var uint = new Uint8Array(img_data.length);
     351                                        const uint = new Uint8Array(img_data.length);
    351352                                        for(i=0,j=img_data.length;i<j;++i) {
    352353                                                uint[i] = img_data.charCodeAt(i);
    353354                                        }
     
    356357                        }
    357358                        if (this.is_worker){
    358359                                this.mQ[this.mQ.length] = packet;
    359                                 var me = this;
     360                                const me = this;
    360361                                setTimeout(function() {
    361362                                                me.process_message_queue();
    362363                                        }, this.process_interval);
     
    375376
    376377XpraProtocol.prototype.process_send_queue = function() {
    377378        while(this.sQ.length !== 0 && this.websocket) {
    378                 var packet = this.sQ.shift();
     379                const packet = this.sQ.shift();
    379380                if(!packet){
    380381                        return;
    381382                }
    382383
    383384                //debug("send worker:"+packet);
    384                 var bdata = null;
     385                let bdata = null;
    385386                try {
    386387                        bdata = bencode(packet);
    387388                }
     
    389390                        console.error("Error: failed to bencode packet:", packet);
    390391                        continue;
    391392                }
    392                 var proto_flags = 0;
    393                 var payload_size = bdata.length;
     393                let proto_flags = 0;
     394                const payload_size = bdata.length;
    394395                // encryption
    395396                if(this.cipher_out) {
    396397                        proto_flags = 0x2;
    397                         var padding_size = this.cipher_out_block_size - (payload_size % this.cipher_out_block_size);
    398                         for (var i = padding_size - 1; i >= 0; i--) {
     398                        const padding_size = this.cipher_out_block_size - (payload_size % this.cipher_out_block_size);
     399                        for (let i = padding_size - 1; i >= 0; i--) {
    399400                                bdata += String.fromCharCode(padding_size);
    400401                        };
    401402                        this.cipher_out.update(forge.util.createBuffer(bdata));
    402403                        bdata = this.cipher_out.output.getBytes();
    403404                }
    404                 var actual_size = bdata.length;
     405                const actual_size = bdata.length;
    405406                //convert string to a byte array:
    406                 var cdata = [];
    407                 for (var i=0; i<actual_size; i++)
     407                const cdata = [];
     408                for (let i=0; i<actual_size; i++)
    408409                        cdata.push(ord(bdata[i]));
    409                 var level = 0;
     410                const level = 0;
    410411                /*
    411                 var use_zlib = false;           //does not work...
     412                const use_zlib = false;         //does not work...
    412413                if (use_zlib) {
    413414                        cdata = new Zlib.Deflate(cdata).compress();
    414415                        level = 1;
    415416                }*/
    416417                //struct.pack('!BBBBL', ord("P"), proto_flags, level, index, payload_size)
    417                 var header = ["P".charCodeAt(0), proto_flags, level, 0];
    418                 for (var i=3; i>=0; i--)
     418                let header = ["P".charCodeAt(0), proto_flags, level, 0];
     419                for (let i=3; i>=0; i--)
    419420                        header.push((payload_size >> (8*i)) & 0xFF);
    420421                //concat data to header, saves an intermediate array which may or may not have
    421422                //been optimised out by the JS compiler anyway, but it's worth a shot
     
    430431
    431432XpraProtocol.prototype.process_message_queue = function() {
    432433        while(this.mQ.length !== 0){
    433                 var packet = this.mQ.shift();
     434                const packet = this.mQ.shift();
    434435
    435436                if(!packet){
    436437                        return;
    437438                }
    438439
    439                 var raw_draw_buffer = (packet[0] === 'draw') && (packet[6] !== 'scroll');
     440                const raw_draw_buffer = (packet[0] === 'draw') && (packet[6] !== 'scroll');
    440441                postMessage({'c': 'p', 'p': packet}, raw_draw_buffer ? [packet[7].buffer] : []);
    441442        }
    442443}
     
    443444
    444445XpraProtocol.prototype.send = function(packet) {
    445446        this.sQ[this.sQ.length] = packet;
    446         var me = this;
     447        const me = this;
    447448        setTimeout(function() {
    448449                me.process_send_queue();
    449450                }, this.process_interval);
     
    457458XpraProtocol.prototype.set_cipher_in = function(caps, key) {
    458459        this.cipher_in_block_size = 32;
    459460        // stretch the password
    460         var secret = forge.pkcs5.pbkdf2(key, caps['cipher.key_salt'], caps['cipher.key_stretch_iterations'], this.cipher_in_block_size);
     461        const secret = forge.pkcs5.pbkdf2(key, caps['cipher.key_salt'], caps['cipher.key_stretch_iterations'], this.cipher_in_block_size);
    461462        // start the cipher
    462463        this.cipher_in = forge.cipher.createDecipher('AES-CBC', secret);
    463464        this.cipher_in.start({iv: caps['cipher.iv']});
     
    466467XpraProtocol.prototype.set_cipher_out = function(caps, key) {
    467468        this.cipher_out_block_size = 32;
    468469        // stretch the password
    469         var secret = forge.pkcs5.pbkdf2(key, caps['cipher.key_salt'], caps['cipher.key_stretch_iterations'], this.cipher_out_block_size);
     470        const secret = forge.pkcs5.pbkdf2(key, caps['cipher.key_salt'], caps['cipher.key_stretch_iterations'], this.cipher_out_block_size);
    470471        // start the cipher
    471472        this.cipher_out = forge.cipher.createCipher('AES-CBC', secret);
    472473        this.cipher_out.start({iv: caps['cipher.iv']});
     
    487488                'lib/brotli_decode.js',
    488489                'lib/forge.js');
    489490        // make protocol instance
    490         var protocol = new XpraProtocol();
     491        const protocol = new XpraProtocol();
    491492        protocol.is_worker = true;
    492493        // we create a custom packet handler which posts packet as a message
    493494        protocol.set_packet_handler(function (packet, ctx) {
    494                 var raw_draw_buffer = (packet[0] === 'draw') && (packet[6] !== 'scroll');
     495                const raw_draw_buffer = (packet[0] === 'draw') && (packet[6] !== 'scroll');
    495496                postMessage({'c': 'p', 'p': packet}, raw_draw_buffer ? [packet[7].buffer] : []);
    496497        }, null);
    497498        // attach listeners from main thread
    498499        self.addEventListener('message', function(e) {
    499                 var data = e.data;
     500                const data = e.data;
    500501                switch (data.c) {
    501502                case 'o':
    502503                        protocol.open(data.u);
     
    528529
    529530
    530531// initialise LZ4 library
    531 var Buffer = require('buffer').Buffer;
    532 var LZ4 = require('lz4');
     532const Buffer = require('buffer').Buffer;
     533const LZ4 = require('lz4');
  • Utilities.js

     
    99
    1010'use strict';
    1111
    12 var Utilities = {
     12const Utilities = {
    1313        VERSION : "4.0",
    1414        REVISION : "0",
    1515        LOCAL_MODIFICATIONS : "0",
     
    4848        },
    4949
    5050        getHexUUID: function() {
    51                 var s = [];
    52                 var hexDigits = "0123456789abcdef";
    53                 for (var i = 0; i < 36; i++) {
     51                const s = [];
     52                const hexDigits = "0123456789abcdef";
     53                for (let i = 0; i < 36; i++) {
    5454                        if (i==8 || i==13 || i==18 || i==23) {
    5555                                s[i] = "-";
    5656                        }
     
    5858                                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    5959                        }
    6060                }
    61                 var uuid = s.join("");
     61                const uuid = s.join("");
    6262                return uuid;
    6363        },
    6464
     
    6666                if(l<32 || l>256) {
    6767                        throw 'invalid salt length';
    6868                }
    69                 var s = '';
     69                let s = '';
    7070                while (s.length<l) {
    7171                        s += Utilities.getHexUUID();
    7272                }
     
    7474        },
    7575
    7676        xorString: function(str1, str2){
    77                 var result = '';
     77                let result = '';
    7878                if(str1.length !== str2.length) {
    7979                        throw 'strings must be equal length';
    8080                }
    81                 for(var i = 0; i < str1.length; i++) {
     81                for(let i = 0; i < str1.length; i++) {
    8282                        result += String.fromCharCode(str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0));
    8383                }
    8484                return result;
     
    8585        },
    8686
    8787        trimString: function(str, trimLength){
    88                 var trimString = str.length > trimLength ?
     88                const trimString = str.length > trimLength ?
    8989                    str.substring(0, trimLength - 3) + "..." :
    9090                    str;
    9191                return trimString;
     
    137137        },
    138138
    139139        getFirstBrowserLanguage : function () {
    140                 var nav = window.navigator,
    141                         browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
    142                         i,
    143                         language;
     140                const nav = window.navigator,
     141                        browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];
     142                let language;
    144143                // support for HTML 5.1 "navigator.languages"
    145144                if (Array.isArray(nav.languages)) {
    146                         for (i = 0; i < nav.languages.length; i++) {
     145                        for (let i = 0; i < nav.languages.length; i++) {
    147146                                language = nav.languages[i];
    148147                                if (language && language.length) {
    149148                                        return language;
     
    151150                        }
    152151                }
    153152                // support for other well known properties in browsers
    154                 for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
    155                         var prop = browserLanguagePropertyKeys[i];
     153                for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {
     154                        const prop = browserLanguagePropertyKeys[i];
    156155                        language = nav[prop];
    157156                        //console.debug(prop, "=", language);
    158157                        if (language && language.length) {
     
    163162        },
    164163
    165164        getKeyboardLayout: function() {
    166                 var v = Utilities.getFirstBrowserLanguage();
     165                let v = Utilities.getFirstBrowserLanguage();
    167166                console.debug("getFirstBrowserLanguage()=", v);
    168167                if (v==null) {
    169168                        return "us";
    170169                }
    171                 var layout = LANGUAGE_TO_LAYOUT[v];
     170                let layout = LANGUAGE_TO_LAYOUT[v];
    172171                if (!layout) {
    173172                        //ie: v="en_GB";
    174173                        v = v.split(',')[0];
    175                         var l = v.split('-', 2);
     174                        let l = v.split('-', 2);
    176175                        if (l.length === 1){
    177176                                l = v.split('_', 2);
    178177                        }
    179178                        //ie: "en"
    180179                        layout=l[1].toLowerCase();
    181                         var tmp = LANGUAGE_TO_LAYOUT[v];
     180                        const tmp = LANGUAGE_TO_LAYOUT[v];
    182181                        if (tmp) {
    183182                                layout = tmp;
    184183                        }
     
    188187        },
    189188
    190189        canUseWebP : function() {
    191             var elem = document.createElement('canvas');
    192             var ctx = elem.getContext('2d');
     190            const elem = document.createElement('canvas');
     191            const ctx = elem.getContext('2d');
    193192            if (!ctx) {
    194193                return false;
    195194            }
     
    204203                if (Utilities.audio_context) {
    205204                        return Utilities.audio_context;
    206205                }
    207                 var acc = Utilities.getAudioContextClass();
     206                const acc = Utilities.getAudioContextClass();
    208207                if(!acc) {
    209208                        return null;
    210209                }
     
    226225
    227226
    228227        isFirefox : function() {
    229                 var ua = navigator.userAgent.toLowerCase();
     228                const ua = navigator.userAgent.toLowerCase();
    230229                return ua.includes("firefox");
    231230        },
    232231        isOpera : function() {
    233                 var ua = navigator.userAgent.toLowerCase();
     232                const ua = navigator.userAgent.toLowerCase();
    234233                return ua.includes("opera");
    235234        },
    236235        isSafari : function() {
    237                 var ua = navigator.userAgent.toLowerCase();
     236                const ua = navigator.userAgent.toLowerCase();
    238237                return ua.includes("safari") && !ua.includes('chrome');
    239238        },
    240239        isEdge : function() {
     
    241240                return navigator.userAgent.includes("Edge");
    242241        },
    243242        isChrome : function () {
    244                 var isChromium = window.chrome,
     243                const isChromium = window.chrome,
    245244                        winNav = window.navigator,
    246245                        vendorName = winNav.vendor,
    247246                        isOpera = winNav.userAgent.includes("OPR"),
     
    262261        },
    263262
    264263        is_64bit : function() {
    265                 var _to_check = [] ;
     264                let _to_check = [] ;
    266265                if (window.navigator.cpuClass)
    267266                        _to_check.push((window.navigator.cpuClass + "").toLowerCase());
    268267                if (window.navigator.platform)
     
    269268                        _to_check.push((window.navigator.platform + "").toLowerCase());
    270269                if (navigator.userAgent)
    271270                        _to_check.push((navigator.userAgent + "").toLowerCase());
    272                 var _64bits_signatures = ["x86_64", "x86-64", "Win64", "x64;", "amd64", "AMD64", "WOW64", "x64_64", "ia64", "sparc64", "ppc64", "IRIX64"];
    273                 var _i, _c;
    274                 for (_c=0; _c<_to_check.length; _c++) {
    275                         for (_i=0 ; _i<_64bits_signatures.length; _i++) {
     271                const _64bits_signatures = ["x86_64", "x86-64", "Win64", "x64;", "amd64", "AMD64", "WOW64", "x64_64", "ia64", "sparc64", "ppc64", "IRIX64"];
     272                for (let _c=0; _c<_to_check.length; _c++) {
     273                        for (let _i=0 ; _i<_64bits_signatures.length; _i++) {
    276274                                if (_to_check[_c].indexOf(_64bits_signatures[_i].toLowerCase())!=-1) {
    277275                                        return true;
    278276                                }
     
    322320        },
    323321
    324322        isEventSupported : function(event) {
    325                 var testEl = document.createElement('div');
    326                 var isSupported;
     323                let testEl = document.createElement('div');
     324                let isSupported;
    327325
    328326                event = 'on' + event;
    329327                isSupported = (event in testEl);
     
    340338        //BSD license
    341339        normalizeWheel : function(/*object*/ event) /*object*/ {
    342340                // Reasonable defaults
    343                 var PIXEL_STEP  = 10;
    344                 var LINE_HEIGHT = 40;
    345                 var PAGE_HEIGHT = 800;
     341                const PIXEL_STEP  = 10;
     342                const LINE_HEIGHT = 40;
     343                const PAGE_HEIGHT = 800;
    346344
    347                 var sX = 0, sY = 0,       // spinX, spinY
     345                let sX = 0, sY = 0,       // spinX, spinY
    348346                        pX = 0, pY = 0;       // pixelX, pixelY
    349347
    350348                // Legacy
     
    389387        },
    390388
    391389        saveFile : function(filename, data, mimetype) {
    392             var a = document.createElement("a");
     390            const a = document.createElement("a");
    393391            a.setAttribute("style", "display: none");
    394392            document.body.appendChild(a);
    395             var blob = new Blob([data], mimetype);
    396             var url = window.URL.createObjectURL(blob);
     393            const blob = new Blob([data], mimetype);
     394            const url = window.URL.createObjectURL(blob);
    397395            if (navigator.msSaveOrOpenBlob) {
    398396                navigator.msSaveOrOpenBlob(blob, filename);
    399397            } else {
     
    412410        },
    413411
    414412        StringToUint8 : function(str) {
    415                 var u8a = new Uint8Array(str.length);
    416                 for(var i=0,j=str.length;i<j;++i){
     413                const u8a = new Uint8Array(str.length);
     414                for(let i=0,j=str.length;i<j;++i){
    417415                        u8a[i] = str.charCodeAt(i);
    418416                }
    419417                return u8a;
     
    420418        },
    421419
    422420        Uint8ToString : function(u8a){
    423                 var CHUNK_SZ = 0x8000;
    424                 var c = [];
    425                 for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
     421                const CHUNK_SZ = 0x8000;
     422                const c = [];
     423                for (let i=0; i < u8a.length; i+=CHUNK_SZ) {
    426424                        c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
    427425                }
    428426                return c.join("");
     
    431429        ArrayBufferToBase64 : function(uintArray) {
    432430                // apply in chunks of 10400 to avoid call stack overflow
    433431                // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
    434                 var s = "";
    435                 var skip = 10400;
     432                let s = "";
     433                const skip = 10400;
    436434                if (uintArray.subarray) {
    437                         for (var i=0, len=uintArray.length; i<len; i+=skip) {
     435                        for (let i=0, len=uintArray.length; i<len; i+=skip) {
    438436                                s += String.fromCharCode.apply(null, uintArray.subarray(i, Math.min(i + skip, len)));
    439437                        }
    440438                } else {
    441                         for (var i=0, len=uintArray.length; i<len; i+=skip) {
     439                        for (let i=0, len=uintArray.length; i<len; i+=skip) {
    442440                                s += String.fromCharCode.apply(null, uintArray.slice(i, Math.min(i + skip, len)));
    443441                        }
    444442                }
     
    446444        },
    447445
    448446        convertDataURIToBinary : function (dataURI) {
    449                 var BASE64_MARKER = ';base64,';
    450                 var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
    451                 var base64 = dataURI.substring(base64Index);
    452                 var raw = window.atob(base64);
    453                 var rawLength = raw.length;
    454                 var array = new Uint8Array(new ArrayBuffer(rawLength));
     447                const BASE64_MARKER = ';base64,';
     448                const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
     449                const base64 = dataURI.substring(base64Index);
     450                const raw = window.atob(base64);
     451                const rawLength = raw.length;
     452                const array = new Uint8Array(new ArrayBuffer(rawLength));
    455453
    456454                for(i = 0; i < rawLength; i++) {
    457455                        array[i] = raw.charCodeAt(i);
     
    461459
    462460
    463461        parseINIString : function (data) {
    464             var regex = {
     462            const regex = {
    465463                section: /^\s*\[\s*([^\]]*)\s*\]\s*$/,
    466464                param: /^\s*([^=]+?)\s*=\s*(.*?)\s*$/,
    467465                comment: /^\s*;.*$/
    468466            };
    469             var value = {};
    470             var lines = data.split(/[\r\n]+/);
    471             var section = null;
     467            const value = {};
     468            const lines = data.split(/[\r\n]+/);
     469            let section = null;
    472470            lines.forEach(function(line){
    473471                if(regex.comment.test(line)){
    474472                    return;
    475473                }else if(regex.param.test(line)){
    476                     var match = line.match(regex.param);
     474                    const match = line.match(regex.param);
    477475                    if(section){
    478476                        value[section][match[1]] = match[2];
    479477                    }else{
     
    480478                        value[match[1]] = match[2];
    481479                    }
    482480                }else if(regex.section.test(line)){
    483                     var match = line.match(regex.section);
     481                    const match = line.match(regex.section);
    484482                    value[match[1]] = {};
    485483                    section = match[1];
    486484                }else if(line.length == 0 && section){
     
    497495         * This method parses that string into a user-friendly key/value pair object.
    498496         */
    499497        ParseResponseHeaders : function(headerStr) {
    500                 var headers = {};
     498                const headers = {};
    501499                if (!headerStr) {
    502500                        return headers;
    503501                }
    504                 var headerPairs = headerStr.split('\u000d\u000a');
    505                 for (var i = 0; i < headerPairs.length; i++) {
    506                         var headerPair = headerPairs[i];
     502                const headerPairs = headerStr.split('\u000d\u000a');
     503                for (let i = 0; i < headerPairs.length; i++) {
     504                        const headerPair = headerPairs[i];
    507505                        // Can't use split() here because it does the wrong thing
    508506                        // if the header value has the string ": " in it.
    509                         var index = headerPair.indexOf('\u003a\u0020');
     507                        const index = headerPair.indexOf('\u003a\u0020');
    510508                        if (index > 0) {
    511                                 var key = headerPair.substring(0, index);
    512                                 var val = headerPair.substring(index + 2);
     509                                const key = headerPair.substring(0, index);
     510                                const val = headerPair.substring(index + 2);
    513511                                headers[key] = val;
    514512                        }
    515513                }
     
    517515        },
    518516
    519517        parseParams : function(q) {
    520                 var params = {},
    521                                 e,
    522                                 a = /\+/g,      // Regex for replacing addition symbol with a space
     518                const params = {};
     519                let e;
     520                const a = /\+/g,        // Regex for replacing addition symbol with a space
    523521                                r = /([^&=]+)=?([^&]*)/g,
    524522                                d = function (s) { return decodeURIComponent(s.replace(a, " ")); };
    525523                while (e = r.exec(q))
     
    528526        },
    529527
    530528        getparam : function(prop) {
    531                 var getParameter = window.location.getParameter;
     529                let getParameter = window.location.getParameter;
    532530                if (!getParameter) {
    533531                        getParameter = function(key) {
    534532                                if (!window.location.queryStringParams)
     
    536534                                return window.location.queryStringParams[key];
    537535                        };
    538536                }
    539                 var value = getParameter(prop);
     537                let value = getParameter(prop);
    540538                try {
    541539                        if (value === undefined && typeof(sessionStorage) !== undefined) {
    542540                                value = sessionStorage.getItem(prop);
     
    550548
    551549
    552550        getboolparam : function(prop, default_value) {
    553                 var v = Utilities.getparam(prop);
     551                const v = Utilities.getparam(prop);
    554552                if(v===null) {
    555553                        return default_value;
    556554                }
     
    562560                        return false;
    563561                }
    564562                try {
    565                         var key = "just for testing sessionStorage support";
     563                        const key = "just for testing sessionStorage support";
    566564                    sessionStorage.setItem(key, "store-whatever");
    567565                    sessionStorage.removeItem(key);
    568566                    return true;
     
    574572
    575573
    576574        getConnectionInfo : function() {
    577                 var c = navigator.connection;
     575                const c = navigator.connection;
    578576                if (!c) {
    579577                        return {};
    580578                }
    581                 var i = {};
     579                const i = {};
    582580                if (c.type) {
    583581                        i["type"] = c.type;
    584582                }
     
    599597};
    600598
    601599
    602 var MOVERESIZE_SIZE_TOPLEFT      = 0;
    603 var MOVERESIZE_SIZE_TOP          = 1;
    604 var MOVERESIZE_SIZE_TOPRIGHT     = 2;
    605 var MOVERESIZE_SIZE_RIGHT        = 3;
    606 var MOVERESIZE_SIZE_BOTTOMRIGHT  = 4;
    607 var MOVERESIZE_SIZE_BOTTOM       = 5;
    608 var MOVERESIZE_SIZE_BOTTOMLEFT   = 6;
    609 var MOVERESIZE_SIZE_LEFT         = 7;
    610 var MOVERESIZE_MOVE              = 8;
    611 var MOVERESIZE_SIZE_KEYBOARD     = 9;
    612 var MOVERESIZE_MOVE_KEYBOARD     = 10;
    613 var MOVERESIZE_CANCEL            = 11;
    614 var MOVERESIZE_DIRECTION_STRING = {
     600const MOVERESIZE_SIZE_TOPLEFT      = 0;
     601const MOVERESIZE_SIZE_TOP          = 1;
     602const MOVERESIZE_SIZE_TOPRIGHT     = 2;
     603const MOVERESIZE_SIZE_RIGHT        = 3;
     604const MOVERESIZE_SIZE_BOTTOMRIGHT  = 4;
     605const MOVERESIZE_SIZE_BOTTOM       = 5;
     606const MOVERESIZE_SIZE_BOTTOMLEFT   = 6;
     607const MOVERESIZE_SIZE_LEFT         = 7;
     608const MOVERESIZE_MOVE              = 8;
     609const MOVERESIZE_SIZE_KEYBOARD     = 9;
     610const MOVERESIZE_MOVE_KEYBOARD     = 10;
     611const MOVERESIZE_CANCEL            = 11;
     612const MOVERESIZE_DIRECTION_STRING = {
    615613                               0    : "SIZE_TOPLEFT",
    616614                               1    : "SIZE_TOP",
    617615                               2    : "SIZE_TOPRIGHT",
     
    625623                               10   : "MOVE_KEYBOARD",
    626624                               11       : "CANCEL",
    627625                               };
    628 var MOVERESIZE_DIRECTION_JS_NAME = {
     626const MOVERESIZE_DIRECTION_JS_NAME = {
    629627        0       : "nw",
    630628        1       : "n",
    631629        2       : "ne",
     
    637635        };
    638636
    639637//convert a language code into an X11 keyboard layout code:
    640 var LANGUAGE_TO_LAYOUT = {
     638const LANGUAGE_TO_LAYOUT = {
    641639                "en_GB" : "gb",
    642640                "en"    : "us",
    643641                "zh"    : "cn",
  • Window.js

     
    2222 */
    2323function XpraWindow(client, canvas_state, wid, x, y, w, h, metadata, override_redirect, tray, client_properties, geometry_cb, mouse_move_cb, mouse_down_cb, mouse_up_cb, mouse_scroll_cb, set_focus_cb, window_closed_cb, htmldiv) {
    2424        // use me in jquery callbacks as we lose 'this'
    25         var me = this;
     25        const me = this;
    2626        // there might be more than one client
    2727        this.client = client;
    2828        this.log = function() { client.log.apply(client, arguments); };
     
    212212        this.spinnerdiv = jQuery('#spinner'+String(wid));
    213213
    214214        // listen for mouse wheel events on my window
    215         var div = document.getElementById(wid);
     215        const div = document.getElementById(wid);
    216216        function on_mousescroll(e) {
    217217                me.on_mousescroll(e);
    218218        }
     
    242242                this.canvas.addEventListener("pointermove", function(ev) {
    243243                        me.debug("mouse", "pointermove:", ev);
    244244                        if (me.pointer_down==ev.pointerId) {
    245                                 var dx = ev.offsetX-me.pointer_last_x;
    246                                 var dy = ev.offsetY-me.pointer_last_y;
     245                                const dx = ev.offsetX-me.pointer_last_x;
     246                                const dy = ev.offsetY-me.pointer_last_y;
    247247                                me.pointer_last_x = ev.offsetX;
    248248                                me.pointer_last_y = ev.offsetY;
    249                                 var mult = 20.0*(window.devicePixelRatio || 1);
     249                                const mult = 20.0*(window.devicePixelRatio || 1);
    250250                                ev.wheelDeltaX = Math.round(dx*mult);
    251251                                ev.wheelDeltaY = Math.round(dy*mult);
    252252                                on_mousescroll(ev);
     
    302302                //moving them would mess that up
    303303                return;
    304304        }
    305         var oldx = this.x;
    306         var oldy = this.y;
     305        const oldx = this.x;
     306        const oldy = this.y;
    307307        // for now make sure we don't out of top left
    308308        // this will be much smarter!
    309         var min_visible = 10;
    310         var desktop_size = this.client._get_desktop_size();
    311         var ww = desktop_size[0];
    312         var wh = desktop_size[1];
     309        const min_visible = 10;
     310        const desktop_size = this.client._get_desktop_size();
     311        const ww = desktop_size[0];
     312        const wh = desktop_size[1];
    313313        //this.log("x=", this.x, "y=", this.y, "w=", this.w, "h=", this.h, "leftoffset=", this.leftoffset, "topoffset=", this.topoffset, " - ww=", ww, "wh=", wh);
    314314        if(oldx + this.w <= min_visible) {
    315315                this.x = min_visible - this.w + this.leftoffset;
     
    415415
    416416
    417417XpraWindow.prototype.update_zindex = function() {
    418         var z = 5000 + this.stacking_layer;
     418        let z = 5000 + this.stacking_layer;
    419419        if (this.tray) {
    420420                z = 0;
    421421        }
     
    430430        else if (this.windowtype=="UTILITY" || this.windowtype=="DIALOG") {
    431431                z = 15000;
    432432        }
    433         var above = this.metadata["above"];
     433        const above = this.metadata["above"];
    434434        if (above) {
    435435                z += 5000;
    436436        }
    437437        else {
    438                 var below = this.metadata["below"];
     438                const below = this.metadata["below"];
    439439                if (below) {
    440440                        z -= 5000;
    441441                }
     
    454454XpraWindow.prototype.update_metadata = function(metadata, safe) {
    455455        //update our metadata cache with new key-values:
    456456        this.debug("main", "update_metadata(", metadata, ")");
    457         for (var attrname in metadata) {
     457        for (let attrname in metadata) {
    458458                this.metadata[attrname] = metadata[attrname];
    459459        }
    460460        if(safe) {
     
    471471XpraWindow.prototype.set_metadata_safe = function(metadata) {
    472472        if ("title" in metadata) {
    473473                this.title = metadata["title"];
    474                 var decodedTitle = decodeURIComponent(escape(this.title));
     474                const decodedTitle = decodeURIComponent(escape(this.title));
    475475                jQuery('#title' + this.wid).html(decodedTitle);
    476         var trimmedTitle = Utilities.trimString(decodedTitle,30);
     476                const trimmedTitle = Utilities.trimString(decodedTitle, 30);
    477477                jQuery('#windowlistitemtitle'+this.wid).text(trimmedTitle);
    478478        }
    479479        if ("has-alpha" in metadata) {
     
    490490                this.apply_size_constraints();
    491491        }
    492492        if ("opacity" in metadata) {
    493                 var opacity = metadata["opacity"];
     493                let opacity = metadata["opacity"];
    494494                if (opacity<0) {
    495495                        opacity = 1.0;
    496496                }
     
    500500                jQuery(this.div).css('opacity', ''+opacity);
    501501        }
    502502        //if the attribute is set, add the corresponding css class:
    503         var attrs = ["modal", "above", "below"];
    504         for (var i = 0; i < attrs.length; i++) {
    505                 var attr = attrs[i];
     503        const attrs = ["modal", "above", "below"];
     504        for (let i = 0; i < attrs.length; i++) {
     505                const attr = attrs[i];
    506506                if (attr in metadata) {
    507                         var value = metadata[attr];
     507                        const value = metadata[attr];
    508508                        if (value) {
    509509                                jQuery(this.div).addClass(attr);
    510510                        }
     
    517517                this.apply_size_constraints();
    518518        }
    519519        if ("class-instance" in metadata) {
    520                 var wm_class = metadata["class-instance"];
    521                 var classes = jQuery(this.div).prop("classList");
     520                const wm_class = metadata["class-instance"];
     521                const classes = jQuery(this.div).prop("classList");
    522522                if (classes) {
    523523                        //remove any existing "wmclass-" classes not in the new wm_class list:
    524                         for (var i = 0; i < classes.length; i++) {
    525                                 var tclass = ""+classes[i];
     524                        for (let i = 0; i < classes.length; i++) {
     525                                const tclass = ""+classes[i];
    526526                                if (tclass.indexOf("wmclass-")===0 && wm_class && !wm_class.includes(tclass)) {
    527527                                        jQuery(this.div).removeClass(tclass);
    528528                                }
     
    530530                }
    531531                if (wm_class) {
    532532                        //add new wm-class:
    533                         for (var i = 0; i < wm_class.length; i++) {
    534                                 var tclass = wm_class[i].replace(/[^0-9a-zA-Z]/g, '');
     533                        for (let i = 0; i < wm_class.length; i++) {
     534                                const tclass = wm_class[i].replace(/[^0-9a-zA-Z]/g, '');
    535535                                if (tclass && !jQuery(this.div).hasClass(tclass)) {
    536536                                        jQuery(this.div).addClass("wmclass-"+tclass);
    537537                                }
     
    550550        else {
    551551                jQuery(this.div).draggable('enable');
    552552        }
    553         var hdec = 0, wdec = 0;
     553        let hdec = 0;
     554        const wdec = 0;
    554555        if (this.decorations) {
    555556                //adjust for header
    556557                hdec = jQuery('#head' + this.wid).outerHeight(true);
    557558        }
    558         var min_size = null, max_size = null;
    559         var size_constraints = this.metadata["size-constraints"];
     559        let min_size = null, max_size = null;
     560        const size_constraints = this.metadata["size-constraints"];
    560561        if (size_constraints) {
    561562                min_size = size_constraints["minimum-size"];
    562563                max_size = size_constraints["maximum-size"];
    563564        }
    564         var minw=null, minh=null;
     565        let minw=null, minh=null;
    565566        if (min_size) {
    566567                minw = min_size[0]+wdec;
    567568                minh = min_size[1]+hdec;
    568569        }
    569         var maxw=null, maxh=null;
     570        let maxw=null, maxh=null;
    570571        if (max_size) {
    571572                maxw = max_size[0]+wdec;
    572573                maxh = max_size[1]+hdec;
     
    747748        // should be as simple as this
    748749        // in future we may have a taskbar for minimized windows
    749750        // which should be subtracted from screen size
    750         var screen_size = this.client._get_desktop_size();
     751        const screen_size = this.client._get_desktop_size();
    751752        this.x = 0 + this.leftoffset;
    752753        this.y = 0 + this.topoffset;
    753754        this.w = (screen_size[0] - this.leftoffset) - this.rightoffset;
     
    785786 * store internal geometry, external is always in CSS left and top
    786787 */
    787788XpraWindow.prototype.handle_moved = function(e) {
    788         var left = Math.round(e.position.left),
     789        const left = Math.round(e.position.left),
    789790                top = Math.round(e.position.top);
    790791        this.debug("geometry", "handle_moved(", e, ") left=", left, ", top=", top);
    791792        // add on padding to the event position so that
     
    811812        if (this.client.server_is_shadow) {
    812813                //note: when this window is created,
    813814                // it may not have been added to the client's list yet
    814                 var ids = Object.keys(this.client.id_to_window);
     815                const ids = Object.keys(this.client.id_to_window);
    815816                if (ids.length==0 || ids[0]==this.wid) {
    816817                        //single window, recenter it:
    817818                        this.recenter();
     
    825826};
    826827
    827828XpraWindow.prototype.recenter = function(force_update_geometry) {
    828         var x = this.x,
     829        let x = this.x,
    829830                y = this.y;
    830831        this.debug("geometry", "recenter() x=", x, ", y=", y, ", desktop size: ", this.client.desktop_width, this.client.desktop_height);
    831832        x = Math.round((this.client.desktop_width-this.w)/2);
     
    847848
    848849
    849850XpraWindow.prototype.match_screen_size = function() {
    850         var maxw = this.client.desktop_width;
    851         var maxh = this.client.desktop_height;
    852         var neww = 0, newh = 0;
     851        const maxw = this.client.desktop_width;
     852        const maxh = this.client.desktop_height;
     853        let neww = 0, newh = 0;
    853854        if (this.client.server_resize_exact) {
    854855                neww = maxw;
    855856                newh = maxh;
     
    862863                }
    863864                //try to find the best screen size to use,
    864865                //cannot be larger than the browser area
    865                 var best = 0;
    866                 var w = 0, h = 0;
    867                 var screen_sizes = this.client.server_screen_sizes;
    868                 var screen_size;
    869                 for (var i = 0; i < screen_sizes.length; i++) {
     866                let best = 0;
     867                let w = 0, h = 0;
     868                const screen_sizes = this.client.server_screen_sizes;
     869                let screen_size;
     870                for (let i = 0; i < screen_sizes.length; i++) {
    870871                        screen_size = screen_sizes[i];
    871872                        w = screen_size[0];
    872873                        h = screen_size[1];
     
    879880                if (neww==0 && newh==0) {
    880881                        //not found, try to find the smallest one:
    881882                        best = 0;
    882                         for (var i = 0; i < screen_sizes.length; i++) {
     883                        for (let i = 0; i < screen_sizes.length; i++) {
    883884                                screen_size = screen_sizes[i];
    884885                                w = screen_size[0];
    885886                                h = screen_size[1];
     
    930931};
    931932
    932933XpraWindow.prototype.initiate_moveresize = function(mousedown_event, x_root, y_root, direction, button, source_indication) {
    933         var dir_str = MOVERESIZE_DIRECTION_STRING[direction];
     934        const dir_str = MOVERESIZE_DIRECTION_STRING[direction];
    934935        this.log("initiate_moveresize", dir_str, [x_root, y_root, direction, button, source_indication]);
    935936        if (direction==MOVERESIZE_MOVE && mousedown_event) {
    936                 var e = mousedown_event;
     937                const e = mousedown_event;
    937938                e.type = "mousedown.draggable";
    938939                e.target = this.div[0];
    939940                this.div.trigger(e);
     
    944945                jQuery(this.div).draggable('enable');
    945946        }
    946947        else if (direction in MOVERESIZE_DIRECTION_JS_NAME) {
    947                 var js_dir = MOVERESIZE_DIRECTION_JS_NAME[direction];
    948                 var resize_widget = jQuery(this.div).find(".ui-resizable-handle.ui-resizable-"+js_dir).first();
     948                const js_dir = MOVERESIZE_DIRECTION_JS_NAME[direction];
     949                const resize_widget = jQuery(this.div).find(".ui-resizable-handle.ui-resizable-"+js_dir).first();
    949950                if (resize_widget) {
    950                         var pageX = resize_widget.offset().left;
    951                         var pageY = resize_widget.offset().top;
     951                        const pageX = resize_widget.offset().left;
     952                        const pageY = resize_widget.offset().top;
    952953                        resize_widget.trigger("mouseover");
    953954                        resize_widget.trigger({ type: "mousedown", which: 1, pageX: pageX, pageY: pageY });
    954955                }
     
    984985
    985986
    986987XpraWindow.prototype.update_icon = function(width, height, encoding, img_data) {
    987         var src = "/favicon.png";
     988        let src = "/favicon.png";
    988989        if (encoding=="png") {
    989990                //move title to the right:
    990991                $("#title"+ String(this.wid)).css('left', 32);
    991992                if (typeof img_data === 'string') {
    992                         var uint = new Uint8Array(img_data.length);
    993                         for(var i=0;i<img_data.length;++i) {
     993                        const uint = new Uint8Array(img_data.length);
     994                        for(let i=0;i<img_data.length;++i) {
    994995                                uint[i] = img_data.charCodeAt(i);
    995996                        }
    996997                        img_data = uint;
     
    10101011
    10111012XpraWindow.prototype.set_cursor = function(encoding, w, h, xhot, yhot, img_data) {
    10121013        if (encoding=="png") {
    1013                 var cursor_url = "url('data:image/"+encoding+";base64," + window.btoa(img_data) + "')";
     1014                const cursor_url = "url('data:image/" + encoding + ";base64," + window.btoa(img_data) + "')";
    10141015                jQuery("#"+String(this.wid)).css("cursor", cursor_url+", default");
    10151016                //CSS3 with hotspot:
    10161017                jQuery("#"+String(this.wid)).css("cursor", cursor_url+" "+xhot+" "+yhot+", auto");
     
    10451046 * The following function inits the Broadway h264 decoder
    10461047 */
    10471048XpraWindow.prototype._init_broadway = function(enc_width, enc_height, width, height) {
    1048         var me = this;
     1049        const me = this;
    10491050        this.broadway_decoder = new Decoder({
    10501051                "rgb":  true,
    10511052                "size": { "width" : enc_width, "height" : enc_height },
     
    10621063        if(!this.broadway_decoder) {
    10631064                return;
    10641065        }
    1065         var img = this.offscreen_canvas_ctx.createImageData(p_width, p_height);
     1066        const img = this.offscreen_canvas_ctx.createImageData(p_width, p_height);
    10661067        img.data.set(buffer);
    1067         var x = this.broadway_paint_location[0];
    1068         var y = this.broadway_paint_location[1];
     1068        const x = this.broadway_paint_location[0];
     1069        const y = this.broadway_paint_location[1];
    10691070        this.offscreen_canvas_ctx.putImageData(img, x, y, 0, 0, enc_width, enc_height);
    10701071        if(enc_width!=width || enc_height!=height) {
    10711072                //scale it:
     
    11021103
    11031104XpraWindow.prototype._push_video_buffers = function() {
    11041105        this.debug("draw", "_push_video_buffers()");
    1105         var vsb = this.video_source_buffer;
    1106         var vb = this.video_buffers;
     1106        const vsb = this.video_source_buffer;
     1107        const vb = this.video_buffers;
    11071108        if(!vb || !vsb || !this.video_source_ready) {
    11081109                return;
    11091110        }
     
    11111112                return;
    11121113        }
    11131114        while(vb.length>0 && !vsb.updating) {
    1114                 var buffers = vb.splice(0, 20);
    1115                 var buffer = [].concat.apply([], buffers);
     1115                const buffers = vb.splice(0, 20);
     1116                const buffer = [].concat.apply([], buffers);
    11161117                vsb.appendBuffer(new Uint8Array(buffer).buffer);
    11171118                /*
    11181119                 * one at a time:
    1119                 var img_data = vb.shift();
    1120         var array = new Uint8Array(img_data);
    1121             vsb.appendBuffer(array.buffer);
     1120                const img_data = vb.shift();
     1121                const array = new Uint8Array(img_data);
     1122                vsb.appendBuffer(array.buffer);
    11221123                 */
    1123             this.video_buffers_count += buffers.length;
     1124                this.video_buffers_count += buffers.length;
    11241125        }
    11251126        if(vb.length>0) {
    11261127                setTimeout(this._push_video_buffers, 25);
     
    11281129}
    11291130
    11301131XpraWindow.prototype._init_video = function(width, height, coding, profile, level) {
    1131         var me = this;
     1132        const me = this;
    11321133        this.media_source = MediaSourceUtil.getMediaSource();
    11331134        //MediaSourceUtil.addMediaSourceEventDebugListeners(this.media_source, "video");
    11341135        //<video> element:
     
    11531154        this.video_buffers_count = 0;
    11541155        this.video_source_ready = false;
    11551156
    1156         var codec_string = "";
     1157        let codec_string = "";
    11571158        if(coding=="h264+mp4" || coding=="mpeg4+mp4") {
    11581159                //ie: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
    11591160                codec_string = 'video/mp4; codecs="avc1.' + MediaSourceConstants.H264_PROFILE_CODE[profile] + MediaSourceConstants.H264_LEVEL_CODE[level]+'"';
     
    11701171        this.log("video codec string: "+codec_string+" for "+coding+" profile '"+profile+"', level '"+level+"'");
    11711172        this.media_source.addEventListener('sourceopen', function() {
    11721173                me.log("video media source open");
    1173                 var vsb = me.media_source.addSourceBuffer(codec_string);
    1174             vsb.mode = "sequence";
     1174                const vsb = me.media_source.addSourceBuffer(codec_string);
     1175                vsb.mode = "sequence";
    11751176                me.video_source_buffer = vsb;
    11761177                if (me.debug_categories.includes("draw")) {
    11771178                        MediaSourceUtil.addSourceBufferEventDebugListeners(vsb, "video");
     
    11931194                //push video under the canvas:
    11941195                this.video.style.zIndex = "-1";
    11951196                //copy video to canvas:
    1196                 var width = this.video.getAttribute("width");
    1197                 var height = this.video.getAttribute("height");
    1198         this.offscreen_canvas_ctx.drawImage(this.video, 0, 0, width, height);
     1197                const width = this.video.getAttribute("width");
     1198                const height = this.video.getAttribute("height");
     1199                this.offscreen_canvas_ctx.drawImage(this.video, 0, 0, width, height);
    11991200        }
    12001201}
    12011202
     
    12071208 */
    12081209XpraWindow.prototype.paint = function paint() {
    12091210        //process all paint request in order using the paint_queue:
    1210         var item = Array.prototype.slice.call(arguments);
     1211        const item = Array.prototype.slice.call(arguments);
    12111212        this.paint_queue.push(item);
    12121213        this.may_paint_now();
    12131214}
     
    12181219 */
    12191220XpraWindow.prototype.may_paint_now = function paint() {
    12201221        this.debug("draw", "may_paint_now() paint pending=", this.paint_pending, ", paint queue length=", this.paint_queue.length);
    1221         var now = Utilities.monotonicTime();
     1222        let now = Utilities.monotonicTime();
    12221223        while ((this.paint_pending==0 || (now-this.paint_pending)>=2000) && this.paint_queue.length>0) {
    12231224                this.paint_pending = now;
    1224                 var item = this.paint_queue.shift();
     1225                const item = this.paint_queue.shift();
    12251226                this.do_paint.apply(this, item);
    12261227                now = Utilities.monotonicTime();
    12271228        }
    12281229}
    12291230
    1230 var DEFAULT_BOX_COLORS = {
     1231const DEFAULT_BOX_COLORS = {
    12311232        "png"     : "yellow",
    12321233        "h264"    : "blue",
    12331234        "vp8"     : "green",
     
    12461247
    12471248XpraWindow.prototype.get_jsmpeg_renderer = function get_jsmpeg_renderer() {
    12481249        if (this.jsmpeg_renderer==null) {
    1249                 var options = new Object();
     1250                const options = new Object();
    12501251                //webgl is still buggy
    12511252                //if (JSMpeg.Renderer.WebGL.IsSupported()) {
    12521253                //      this.jsmpeg_renderer = new JSMpeg.Renderer.WebGL(options);
     
    12681269
    12691270XpraWindow.prototype.do_paint = function paint(x, y, width, height, coding, img_data, packet_sequence, rowstride, options, decode_callback) {
    12701271        this.debug("draw", "do_paint(", img_data.length, " bytes of ", ("zlib" in options?"zlib ":""), coding, " data ", width, "x", height, " at ", x, ",", y, ") focused=", this.focused);
    1271         var me = this;
     1272        const me = this;
    12721273
    1273         var enc_width = width;
    1274         var enc_height = height;
    1275         var scaled_size = options["scaled_size"];
     1274        let enc_width = width;
     1275        let enc_height = height;
     1276        const scaled_size = options["scaled_size"];
    12761277        if(scaled_size) {
    12771278                enc_width = scaled_size[0];
    12781279                enc_height = scaled_size[1];
     
    12871288                img_data = null;
    12881289                me.paint_pending = 0;
    12891290                if (me.paint_debug && !skip_box) {
    1290                         var color = DEFAULT_BOX_COLORS[coding] || "white";
     1291                        const color = DEFAULT_BOX_COLORS[coding] || "white";
    12911292                        paint_box(color, x, y, width, height);
    12921293                }
    12931294                decode_callback();
     
    13031304        try {
    13041305                if (coding=="rgb32") {
    13051306                        this._non_video_paint(coding);
    1306                         var img = this.offscreen_canvas_ctx.createImageData(width, height);
     1307                        const img = this.offscreen_canvas_ctx.createImageData(width, height);
    13071308                        //show("options="+(options).toSource());
    13081309                        if (options!=null && options["zlib"]>0) {
    13091310                                //show("decompressing "+img_data.length+" bytes of "+coding+"/zlib");
    1310                                 var inflated = new Zlib.Inflate(img_data).decompress();
     1311                                const inflated = new Zlib.Inflate(img_data).decompress();
    13111312                                //show("rgb32 data inflated from "+img_data.length+" to "+inflated.length+" bytes");
    13121313                                img_data = inflated;
    13131314                        } else if (options!=null && options["lz4"]>0) {
    13141315                                // in future we need to make sure that we use typed arrays everywhere...
     1316                                let d;
    13151317                                if(img_data.subarray) {
    1316                                         var d = img_data.subarray(0, 4);
     1318                                        d = img_data.subarray(0, 4);
    13171319                                } else {
    1318                                         var d = img_data.slice(0, 4);
     1320                                        d = img_data.slice(0, 4);
    13191321                                }
    13201322                                // will always be little endian
    1321                                 var length = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
     1323                                const length = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
    13221324                                // decode the LZ4 block
    1323                                 var inflated = new Buffer(length);
     1325                                const inflated = new Buffer(length);
     1326                                let uncompressedSize;
    13241327                                if(img_data.subarray) {
    1325                                         var uncompressedSize = LZ4.decodeBlock(img_data.subarray(4), inflated);
     1328                                        uncompressedSize = LZ4.decodeBlock(img_data.subarray(4), inflated);
    13261329                                } else {
    1327                                         var uncompressedSize = LZ4.decodeBlock(img_data.slice(4), inflated);
     1330                                        uncompressedSize = LZ4.decodeBlock(img_data.slice(4), inflated);
    13281331                                }
    13291332                                img_data = inflated.slice(0, uncompressedSize);
    13301333                        }
     
    13421345                }
    13431346                else if (coding=="jpeg" || coding=="png" || coding=="webp") {
    13441347                        this._non_video_paint(coding);
    1345                         var j = new Image();
     1348                        const j = new Image();
    13461349                        j.onload = function () {
    13471350                                if (j.width==0 || j.height==0) {
    13481351                                        paint_error("invalid image size: "+j.width+"x"+j.height);
     
    13601363                        j.src = "data:image/"+coding+";base64," + Utilities.ArrayBufferToBase64(img_data);
    13611364                }
    13621365                else if (coding=="mpeg1") {
    1363                         var frame = options["frame"] || 0;
     1366                        const frame = options["frame"] || 0;
    13641367                        if (frame==0 || this.jsmpeg_decoder==null) {
    1365                                 var options = new Object();
     1368                                const options = new Object();
    13661369                                options.streaming = true;
    13671370                                options.decodeFirstFrame = false;
    13681371                                this.jsmpeg_decoder = new JSMpeg.Decoder.MPEG1Video(options);
    13691372                                //TODO: instead of delegating, we should probably subclass the renderer
    13701373                                // (but which one! GL or not?):
    1371                                 var renderer = new Object();
     1374                                const renderer = new Object();
    13721375                                renderer.render = function render(Y, Cr, Cb) {
    1373                                         var jsmpeg_renderer = me.get_jsmpeg_renderer();
     1376                                        const jsmpeg_renderer = me.get_jsmpeg_renderer();
    13741377                                        jsmpeg_renderer.render(Y, Cr, Cb);
    1375                                         var canvas = jsmpeg_renderer.canvas;
     1378                                        const canvas = jsmpeg_renderer.canvas;
    13761379                                        me.offscreen_canvas_ctx.drawImage(canvas, x, y, width, height);
    13771380                                        paint_box("olive", x, y, width, height);
    13781381                                }
    13791382                                renderer.resize = function resize(newWidth, newHeight) {
    1380                                         var jsmpeg_renderer = me.get_jsmpeg_renderer();
     1383                                        const jsmpeg_renderer = me.get_jsmpeg_renderer();
    13811384                                        jsmpeg_renderer.resize(newWidth, newHeight);
    13821385                                }
    13831386                                this.jsmpeg_decoder.connect(renderer);
    13841387                        }
    1385                         var pts = frame;
     1388                        const pts = frame;
    13861389                        this.jsmpeg_decoder.write(pts, img_data);
    1387                         var decoded = this.jsmpeg_decoder.decode();
     1390                        const decoded = this.jsmpeg_decoder.decode();
    13881391                        this.debug("draw", coding, "frame", frame, "data len=", img_data.length, "decoded=", decoded);
    13891392                        //TODO: only call painted when we have actually painted the frame?
    13901393                        painted();
    13911394                }
    13921395                else if (coding=="h264") {
    1393                         var frame = options["frame"] || 0;
     1396                        const frame = options["frame"] || 0;
    13941397                        if(frame==0) {
    13951398                                this._close_broadway();
    13961399                        }
     
    14091412                        painted();
    14101413                }
    14111414                else if (coding=="h264+mp4" || coding=="vp8+webm" || coding=="mpeg4+mp4") {
    1412                         var frame = options["frame"] || -1;
     1415                        const frame = options["frame"] || -1;
    14131416                        if(frame==0) {
    14141417                                this._close_video();
    14151418                        }
    14161419                        if(!this.video) {
    1417                                 var profile = options["profile"] || "baseline";
    1418                                 var level = options["level"] || "3.0";
     1420                                const profile = options["profile"] || "baseline";
     1421                                const level = options["level"] || "3.0";
    14191422                                this._init_video(width, height, coding, profile, level);
    14201423                        }
    14211424                        else {
     
    14311434                                }
    14321435                                this._push_video_buffers();
    14331436                                //try to throttle input:
    1434                                 var delay = Math.max(10, 50*(this.video_buffers.length-25));
     1437                                const delay = Math.max(10, 50 * (this.video_buffers.length - 25));
    14351438                                setTimeout(function() {
    14361439                                        painted();
    14371440                                        me.may_paint_now();
     
    14411444                }
    14421445                else if (coding=="scroll") {
    14431446                        this._non_video_paint(coding);
    1444                         for(var i=0,j=img_data.length;i<j;++i) {
    1445                                 var scroll_data = img_data[i];
     1447                        for(let i=0,j=img_data.length;i<j;++i) {
     1448                                const scroll_data = img_data[i];
    14461449                                this.debug("draw", "scroll", i, ":", scroll_data);
    1447                                 var sx = scroll_data[0],
     1450                                const sx = scroll_data[0],
    14481451                                        sy = scroll_data[1],
    14491452                                        sw = scroll_data[2],
    14501453                                        sh = scroll_data[3],