diff --git a/app/styles/base.css b/app/styles/base.css index ab8a0a1a..f26f77e0 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -1197,7 +1197,24 @@ a:visited { * Multi Display Arrangement * ---------------------------------------- */ - +#noVNC_identify_monitor { + position: fixed; + z-index: 999999; + background: rgba(0,0,0,0.7); + color: white; + font-size: 30px; + top: 0; + right: 0; + width: 100px; + height: 100px; + display: none; + justify-content: center; + align-items: center; + border-bottom-left-radius: 10px; +} +#noVNC_identify_monitor.show { + display: flex; +} .flex { display: flex; } diff --git a/app/ui.js b/app/ui.js index d5728604..1a35e508 100644 --- a/app/ui.js +++ b/app/ui.js @@ -584,6 +584,7 @@ const UI = { UI.showControlInput("noVNC_displays_button"); UI.addClickHandle('noVNC_displays_button', UI.openDisplays); UI.addClickHandle('noVNC_close_displays', UI.closeDisplays); + UI.addClickHandle('noVNC_identify_monitors_button', UI._identify); UI.addClickHandle('noVNC_addMonitor', UI.addSecondaryMonitor); UI.addClickHandle('noVNC_refreshMonitors', UI.displaysRefresh); @@ -1439,6 +1440,20 @@ const UI = { UI.rfb.enableQOI = true; } + this._supportsBroadcastChannel = (typeof BroadcastChannel !== "undefined"); + if (this._supportsBroadcastChannel) { + this._controlChannel = new BroadcastChannel("registrationChannel"); + this._controlChannel.addEventListener('message', (event) => { + switch (event.data.eventType) { + case 'identify': + UI.identify(event.data) + break; + } + }); + + } + + //Only explicitly request permission to clipboard on browsers that support binary clipboard access if (supportsBinaryClipboard()) { // explicitly request permission to the clipboard @@ -1838,6 +1853,20 @@ const UI = { * /MULTI-MONITOR SUPPORT * ==============*/ + _identify(e) { + UI.rfb.identify(UI.monitors) + }, + + identify(data) { + const screenID = UI.monitors[0].id + const screen = data.screens.find(el => el.id === screenID) + document.getElementById('noVNC_identify_monitor').innerHTML = screen.num + document.getElementById('noVNC_identify_monitor').classList.add("show") + setTimeout(() => { + document.getElementById('noVNC_identify_monitor').classList.remove("show") + }, 3500) + }, + openDisplays() { document.getElementById('noVNC_displays').classList.add("noVNC_open"); if (UI.monitors.length < 1 ) { diff --git a/app/ui_screen.js b/app/ui_screen.js index cc2bb792..625b359a 100644 --- a/app/ui_screen.js +++ b/app/ui_screen.js @@ -7,7 +7,7 @@ import * as Log from '../core/util/logging.js'; const UI = { connected: false, - + screenID: null, //Initial Loading of the UI prime() { this.start(); @@ -92,8 +92,23 @@ const UI = { UI.rfb.enableQOI = true; } + this._supportsBroadcastChannel = (typeof BroadcastChannel !== "undefined"); + if (this._supportsBroadcastChannel) { + this._controlChannel = new BroadcastChannel("registrationChannel"); + this._controlChannel.addEventListener('message', (event) => { + switch (event.data.eventType) { + case 'identify': + UI.identify(event.data) + break; + } + }); + + } + + + //attach this secondary display to the primary display - UI.rfb.attachSecondaryDisplay(); + UI.screenID = UI.rfb.attachSecondaryDisplay(); if (supportsBinaryClipboard()) { // explicitly request permission to the clipboard @@ -150,6 +165,16 @@ const UI = { } }, + identify(data) { + const screen = data.screens.find(el => el.id === UI.screenID) + document.getElementById('noVNC_identify_monitor').innerHTML = screen.num + document.getElementById('noVNC_identify_monitor').classList.add("show") + setTimeout(() => { + document.getElementById('noVNC_identify_monitor').classList.remove("show") + }, 3500) + }, + + showStatus(text, statusType, time, kasm = false) { // If inside the full Kasm CDI framework, don't show messages unless explicitly told to if (WebUtil.isInsideKasmVDI() && !kasm) { diff --git a/core/rfb.js b/core/rfb.js index 69bd0964..f21b6a3b 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -740,8 +740,9 @@ export default class RFB extends EventTargetMixin { attachSecondaryDisplay() { this._updateConnectionState('connecting'); - this._registerSecondaryDisplay(); + const id = this._registerSecondaryDisplay(); this._updateConnectionState('connected'); + return id } applyScreenPlan(screenPlan) { @@ -1758,10 +1759,19 @@ export default class RFB extends EventTargetMixin { this._controlChannel.postMessage(message); if (!this._viewOnly) { this._keyboard.grab(); } + return screen.screenID } } + identify(screens) { + let message = { + eventType: 'identify', + screens + } + this._controlChannel.postMessage(message); + } + _handleSecondaryDisplayMessage(event) { if (this._isPrimaryDisplay) { diff --git a/screen.html b/screen.html index e0d3fb79..360ad94f 100644 --- a/screen.html +++ b/screen.html @@ -92,4 +92,5 @@ +