var pi = handler.get_default_pi(); // peer information var chat_msgs = []; var svg_fullscreen = ; var svg_action = ; var svg_display = ; var svg_secure = ; var svg_insecure = ; var svg_insecure_relay = ; var svg_secure_relay = ; var cur_window_state = view.windowState; function check_state_change() { if (view.windowState != cur_window_state) { stateChanged(); } self.timer(30ms, check_state_change); } if (is_linux) { check_state_change(); } else { view << event statechange { stateChanged(); } } function get_id() { return handler.get_option('alias') || handler.get_id() } function stateChanged() { stdout.println('state changed from ' + cur_window_state + ' -> ' + view.windowState); cur_window_state = view.windowState; adjustBorder(); adaptDisplay(); if (cur_window_state != View.WINDOW_MINIMIZED) { view.focus = handler; // to make focus away from restore/maximize button, so that enter key work } var fs = view.windowState == View.WINDOW_FULL_SCREEN; var el = $(#fullscreen); if (el) el.attributes.toggleClass("active", fs); el = $(#maximize); if (el) { el.state.disabled = fs; } if (fs) { $(header).style.set { display: "none", }; } } var header; var old_window_state = View.WINDOW_SHOWN; class Header: Reactor.Component { function this() { header = this; } function render() { var icon_conn; var title_conn; if (this.secure_connection && this.direct_connection) { icon_conn = svg_secure; title_conn = translate("Direct and encrypted connection"); } else if (this.secure_connection && !this.direct_connection) { icon_conn = svg_secure_relay; title_conn = translate("Relayed and encrypted connection"); } else if (!this.secure_connection && this.direct_connection) { icon_conn = svg_insecure; title_conn = translate("Direct and unencrypted connection"); } else { icon_conn = svg_insecure_relay; title_conn = translate("Relayed and unencrypted connection"); } var title = get_id(); if (pi.hostname) title += "(" + pi.username + "@" + pi.hostname + ")"; if ((pi.displays || []).length == 0) { return
{title}
; } var screens = pi.displays.map(function(d, i) { return
{i+1}
; }); updateWindowToolbarPosition(); var style = "flow:horizontal;"; if (is_osx) style += "margin:*"; self.timer(1ms, toggleMenuState); return
{is_osx || is_xfce ? "" : {svg_fullscreen}}
{icon_conn}
{get_id()}
{screens}
{this.renderGlobalScreens()}
{svg_chat} {svg_action} {svg_display} {this.renderDisplayPop()} {this.renderActionPop()}
; } function renderDisplayPop() { return
  • {translate('Adjust Window')}
  • {svg_checkmark}{translate('Original')}
  • {svg_checkmark}{translate('Shrink')}
  • {svg_checkmark}{translate('Stretch')}
  • {svg_checkmark}{translate('Good image quality')}
  • {svg_checkmark}{translate('Balanced')}
  • {svg_checkmark}{translate('Optimize reaction time')}
  • {svg_checkmark}{translate('Custom')}
  • {svg_checkmark}{translate('Show remote cursor')}
  • {audio_enabled ?
  • {svg_checkmark}{translate('Mute')}
  • : ""} {is_win && pi.platform == 'Windows' && file_enabled ?
  • {svg_checkmark}{translate('File transfer')}
  • : ""} {keyboard_enabled && clipboard_enabled ?
  • {svg_checkmark}{translate('Disable clipboard')}
  • : ""} {keyboard_enabled ?
  • {svg_checkmark}{translate('Lock after session end')}
  • : ""} {keyboard_enabled && pi.platform == "Windows" ?
  • {svg_checkmark}{translate('Privacy mode')}
  • : ""} ; } function renderActionPop() { return
  • {translate('Transfer File')}
  • {translate('TCP Tunneling')}
  • {keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ?
  • {translate('Insert')} Ctrl + Alt + Del
  • : ""}
    {keyboard_enabled ?
  • {translate('Insert Lock')}
  • : ""} {keyboard_enabled && pi.platform == "Windows" ?
  • {translate("Block user input")}
  • : ""}
  • {translate('Refresh')}
  • ; } function renderGlobalScreens() { if (pi.displays.length < 3) return ""; var x0 = 9999999; var y0 = 9999999; var x = -9999999; var y = -9999999; pi.displays.map(function(d, i) { if (d.x < x0) x0 = d.x; if (d.y < y0) y0 = d.y; var dx = d.x + d.width; if (dx > x) x = dx; var dy = d.y + d.height; if (dy > y) y = dy; }); var w = x - x0; var h = y - y0; var scale = 16. / h; var screens = pi.displays.map(function(d, i) { var min_wh = d.width > d.height ? d.height : d.width; var fs = min_wh * 0.9 * scale; var style = "width:" + (d.width * scale) + "px;" + "height:" + (d.height * scale) + "px;" + "left:" + ((d.x - x0) * scale) + "px;" + "top:" + ((d.y - y0) * scale) + "px;" + "font-size:" + fs + "px;"; if (is_osx) { style += "line-height:" + fs + "px;"; } return
    {i+1}
    ; }); var style = "width:" + (w * scale) + "px; height:" + (h * scale) + "px;"; return
    {screens}
    ; } event click $(#fullscreen) (_, el) { if (view.windowState == View.WINDOW_FULL_SCREEN) { if (old_window_state == View.WINDOW_MAXIMIZED) { view.windowState = View.WINDOW_SHOWN; } view.windowState = old_window_state; } else { old_window_state = view.windowState; if (view.windowState == View.WINDOW_MAXIMIZED) { view.windowState = View.WINDOW_SHOWN; } view.windowState = View.WINDOW_FULL_SCREEN; if (is_linux) { self.timer(150ms, function() { view.windowState = View.WINDOW_FULL_SCREEN; }); } } } event click $(#chat) { startChat(); } event click $(#action) (_, me) { var menu = $(menu#action-options); me.popup(menu); } event click $(#display) (_, me) { var menu = $(menu#display-options); me.popup(menu); } event click $(#screen) (_, me) { if (pi.current_display == me.index) return; handler.switch_display(me.index); } event click $(#transfer-file) { handler.transfer_file(); } event click $(#tunnel) { handler.tunnel(); } event click $(#ctrl-alt-del) { handler.ctrl_alt_del(); } event click $(#lock-screen) { handler.lock_screen(); } event click $(#refresh) { handler.refresh_video(); } event click $(#block-input) { if (!input_blocked) { handler.toggle_option("block-input"); input_blocked = true; $(#block-input).text = translate("Unblock user input"); } else { handler.toggle_option("unblock-input"); input_blocked = false; $(#block-input).text = translate("Block user input"); } } event click $(menu#display-options>li) (_, me) { if (me.id == "custom") { handle_custom_image_quality(); } else if (me.attributes.hasClass("toggle-option")) { handler.toggle_option(me.id); toggleMenuState(); } else if (!me.attributes.hasClass("selected")) { var type = me.attributes["type"]; if (type == "image-quality") { handler.save_image_quality(me.id); } else if (type == "view-style") { handler.save_view_style(me.id); adaptDisplay(); } toggleMenuState(); } } } function handle_custom_image_quality() { var tmp = handler.get_custom_image_quality(); var bitrate0 = tmp[0] || 50; var quantizer0 = tmp.length > 1 ? tmp[1] : 100; msgbox("custom", "Custom Image Quality", "
    \
    x% bitrate
    \
    x% quantizer
    \
    ", function(res=null) { if (!res) return; if (!res.bitrate) return; handler.save_custom_image_quality(res.bitrate, res.quantizer); toggleMenuState(); }); } function toggleMenuState() { var values = []; var q = handler.get_image_quality(); if (!q) q = "balanced"; values.push(q); var s = handler.get_view_style(); if (!s) s = "original"; values.push(s); for (var el in $$(menu#display-options>li)) { el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); } for (var id in ["show-remote-cursor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end", "privacy-mode"]) { var el = self.select('#' + id); if (el) { var value = handler.get_toggle_option(id); el.attributes.toggleClass("selected", value); if (id == "privacy-mode") { var el = $(li#block-input); if (el) { el.state.disabled = value; } } } } } if (is_osx) { $(header).content(
    ); $(header).attributes["role"] = "window-caption"; } else { if (is_file_transfer || is_port_forward) { $(caption).content(
    ); } else { $(div.window-toolbar).content(
    ); } setWindowButontsAndIcon(); } if (!(is_file_transfer || is_port_forward)) { $(header).style.set { height: "32px", }; if (!is_osx) { $(div.window-icon).style.set { size: "32px", }; } } handler.updatePi = function(v) { pi = v; header.update(); if (is_port_forward) { view.windowState = View.WINDOW_MINIMIZED; } } handler.switchDisplay = function(i) { pi.current_display = i; header.update(); } function updateWindowToolbarPosition() { if (is_osx) return; self.timer(1ms, function() { var el = $(div.window-toolbar); var w1 = el.box(#width, #border); var w2 = $(header).box(#width, #border); var x = (w2 - w1) / 2; el.style.set { left: x + "px", display: "block", }; }); } view.on("size", function() { // ensure size is done, so add timer self.timer(1ms, function() { updateWindowToolbarPosition(); adaptDisplay(); }); }); handler.newMessage = function(text) { chat_msgs.push({text: text, name: pi.username || "", time: getNowStr()}); startChat(); } function sendMsg(text) { chat_msgs.push({text: text, name: "me", time: getNowStr()}); handler.send_chat(text); if (chatbox) chatbox.refresh(); } var chatbox; function startChat() { if (chatbox) { chatbox.windowState = View.WINDOW_SHOWN; chatbox.refresh(); return; } var icon = handler.get_icon(); var (sx, sy, sw, sh) = view.screenBox(#workarea, #rectw); var w = 300; var h = 400; var x = (sx + sw - w) / 2; var y = sy + 80; var params = { type: View.FRAME_WINDOW, x: x, y: y, width: w, height: h, client: true, parameters: { msgs: chat_msgs, callback: sendMsg, icon: icon }, caption: get_id(), }; var html = handler.get_chatbox(); if (html) params.html = html; else params.url = self.url("chatbox.html"); chatbox = view.window(params); } handler.setConnectionType = function(secured, direct) { header.update({ secure_connection: secured, direct_connection: direct, }); }