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 svg_recording_off = ;
var svg_recording_on = ;
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;
var is_edit_os_password;
class EditOsPassword: Reactor.Component {
function render() {
return {svg_edit} ;
}
function onMouse(evt) {
if (evt.type == Event.MOUSE_DOWN) {
is_edit_os_password = true;
editOSPassword();
}
}
}
function editOSPassword(login=false) {
var p0 = handler.get_option('os-password');
msgbox("custom-os-password", 'OS Password', p0, "", function(res=null) {
if (!res) return;
var a0 = handler.get_option('auto-login') != '';
var p = (res.password || '').trim();
var a = res.auto_login || false;
if (p == p0 && a == a0) return;
if (p != p0) handler.set_option('os-password', p);
if (a != a0) handler.set_option('auto-login', a ? 'Y' : '');
if (p && login) {
handler.input_os_password(p, true);
}
});
}
var recording = false;
class Header: Reactor.Component {
this var conn_note = "";
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, updatePrivacyMode);
self.timer(1ms, toggleMenuState);
return
{is_osx || is_xfce ? "" :
{svg_fullscreen} }
{icon_conn}
{get_id()}
{screens}
{this.renderGlobalScreens()}
{svg_chat}
{svg_action}
{svg_display}
{svg_keyboard}
{recording_enabled ?
{recording ? svg_recording_on : svg_recording_off} : ""}
{this.renderKeyboardPop()}
{this.renderDisplayPop()}
{this.renderActionPop()}
;
}
function renderKeyboardPop(){
return
{svg_checkmark} {translate('Legacy mode')}
{svg_checkmark} {translate('Map mode')}
;
}
function renderDisplayPop() {
var codecs = handler.supported_hwcodec();
var show_codec = handler.has_hwcodec() && (codecs[0] || codecs[1]);
var cursor_embedded = false;
if ((pi.displays || []).length > 0) {
if (pi.displays.length > pi.current_display) {
cursor_embedded = pi.displays[pi.current_display].cursor_embedded;
}
}
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')}
{show_codec ?
{svg_checkmark} Auto
{svg_checkmark} VP9
{codecs[0] ?
{svg_checkmark} H264 : ""}
{codecs[1] ?
{svg_checkmark} H265 : ""}
: ""}
{!cursor_embedded && {svg_checkmark} {translate('Show remote cursor')} }
{svg_checkmark} {translate('Show quality monitor')}
{audio_enabled ? {svg_checkmark} {translate('Mute')} : ""}
{is_win && pi.platform == 'Windows' && file_enabled ? {svg_checkmark} {translate('Allow file copy and paste')} : ""}
{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
{keyboard_enabled ? {translate('OS Password')} : ""}
{translate('Transfer File')}
{translate('TCP Tunneling')}
{handler.get_audit_server("conn") && {translate('Note')} }
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? {translate('Insert')} Ctrl + Alt + Del : ""}
{restart_enabled && (pi.platform == "Linux" || pi.platform == "Windows" || pi.platform == "Mac OS") ? {translate('Restart Remote Device')} : ""}
{keyboard_enabled ? {translate('Insert Lock')} : ""}
{keyboard_enabled && pi.platform == "Windows" && pi.sas_enabled ? {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 $(#keyboard) (_, me) {
var menu = $(menu#keyboard-options);
me.popup(menu);
}
event click $(span#recording) (_, me) {
recording = !recording;
header.update();
if (recording)
handler.refresh_video();
else
handler.record_screen(false, display_width, display_height);
}
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 $(#os-password) (evt) {
if (is_edit_os_password) {
is_edit_os_password = false;
return;
}
var p = handler.get_option('os-password');
if (!p) editOSPassword(true);
else handler.input_os_password(p, true);
}
event click $(#tunnel) {
handler.tunnel();
}
event click $(#note) {
var self = this;
msgbox("custom", "Note",
, "", function(res=null) {
if (!res) return;
if (!res.text) return;
self.conn_note = res.text;
handler.send_note(res.text);
}, 280);
}
event click $(#ctrl-alt-del) {
handler.ctrl_alt_del();
}
event click $(#restart_remote_device) {
msgbox(
"restart-confirmation",
translate("Restart Remote Device"),
translate("Are you sure you want to restart") + " " + pi.username + "@" + pi.hostname + "(" + get_id() + ") ?",
"",
function(res=null) {
if (res != null) handler.restart_remote_device();
}
);
}
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.id == "privacy-mode") {
togglePrivacyMode(me.id);
} else if (me.id == "show-quality-monitor") {
toggleQualityMonitor(me.id);
} 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();
} else if (type == "codec-preference") {
handler.set_option("codec-preference", me.id);
handler.change_prefer_codec();
}
toggleMenuState();
}
}
event click $(menu#keyboard-options>li) (_, me) {
if (me.id == "legacy") {
handler.save_keyboard_mode("legacy");
} else if (me.id == "map") {
handler.save_keyboard_mode("map");
} else if (me.id == "translate") {
handler.save_keyboard_mode("translate");
}
toggleMenuState()
}
}
function handle_custom_image_quality() {
var tmp = handler.get_custom_image_quality();
var bitrate = (tmp[0] || 50);
msgbox("custom", "Custom Image Quality", "", "", function(res=null) {
if (!res) return;
if (!res.bitrate) return;
handler.save_custom_image_quality(res.bitrate);
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);
var k = handler.get_keyboard_mode();
values.push(k);
var c = handler.get_option("codec-preference");
if (!c) c = "auto";
values.push(c);
var a = handler.get_audio_mode();
if (!a) a = "guest-to-host";
values.push(a);
for (var el in $$(menu#display-options li)) {
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
}
for (var el in $$(menu#keyboard-options>li)) {
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
}
for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) {
var el = self.select('#' + id);
if (el) {
var value = handler.get_toggle_option(id);
el.attributes.toggleClass("selected", 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;
}
}
function updatePrivacyMode() {
var el = $(li#privacy-mode);
if (el) {
var supported = handler.is_privacy_mode_supported();
if (!supported) {
// el.attributes.toggleClass("line-through", true);
el.style["display"]="none";
} else {
var value = handler.get_toggle_option("privacy-mode");
el.attributes.toggleClass("selected", value);
var el = $(li#block-input);
if (el) {
el.state.disabled = value;
}
}
}
}
handler.updatePrivacyMode = updatePrivacyMode;
function togglePrivacyMode(privacy_id) {
var supported = handler.is_privacy_mode_supported();
if (!supported) {
msgbox("nocancel", translate("Privacy mode"), translate("Unsupported"), "", function() { });
} else {
handler.toggle_option(privacy_id);
}
}
function toggleQualityMonitor(name) {
var show = handler.get_toggle_option(name);
if (show) {
$(#quality-monitor).style.set{ display: "none" };
} else {
$(#quality-monitor).style.set{ display: "block" };
}
handler.toggle_option(name);
toggleMenuState();
}
handler.updateBlockInputState = function(input_blocked) {
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");
}
}
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 / scaleFactor;
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 = scaleIt(300);
var h = scaleIt(400);
var x = (sx + sw - w) / 2;
var y = sy + scaleIt(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,
});
}