diff --git a/app/ui_screen.js b/app/ui_screen.js index 4ec64a02..85d24f07 100644 --- a/app/ui_screen.js +++ b/app/ui_screen.js @@ -92,6 +92,20 @@ const UI = { UI.rfb.enableQOI = true; } + // attach secondary display with relative position, relative x, and relative y + // relativePosition: + // 0: primary display is to left + // 1: primary display is up top + // 2: primary display is to right + // 3: primary display is down below + // relativePositionX: + // non-zero number only allowed if relativePosition is 1 or 3 + // How many pixels on the X axis is the secondary screens starting position from the primary displays + // relativePositionY: + // non-zero number only allowed if relativePosition is 0 or 2 + // How many pixels on the Y axis is the secondary screens starting position from the primary displays + UI.rfb.attachSecondaryDisplay(3, 0, 0); + if (supportsBinaryClipboard()) { // explicitly request permission to the clipboard navigator.permissions.query({ name: "clipboard-read" }).then((result) => { Log.Debug('binary clipboard enabled') }); @@ -200,6 +214,11 @@ const UI = { } }, + hideStatus() { + clearTimeout(UI.statusTimeout); + document.getElementById('noVNC_status').classList.remove("noVNC_open"); + }, + disconnect() { }, diff --git a/core/display.js b/core/display.js index ad21264c..269ccca2 100644 --- a/core/display.js +++ b/core/display.js @@ -97,6 +97,8 @@ export default class Display { x: 0, y: 0, relativePosition: 0, + relativePositionX: 0, + relativePositionY: 0, pixelRatio: window.devicePixelRatio, containerHeight: this._target.parentNode.offsetHeight, containerWidth: this._target.parentNode.offsetWidth, @@ -120,6 +122,30 @@ export default class Display { // ===== PROPERTIES ===== + get relativePosition() { return this._screens[0].relativePosition; } + set relativePosition(value) { + if (!this._isPrimaryDisplay && value >= 0 && value < 4) { + this._screens[0].relativePosition = value; + //reset relative X and Y + this._screens[0].relativePositionX = 0; + this._screens[0].relativePositionY = 0; + } + } + + get relativePositionX() { return this._screens[0].relativePositionX; } + set relativePositionX(value) { + if (!this._isPrimaryDisplay && (this._screens[0].relativePosition == 1 || this._screens[0].relativePosition == 3)) { + this._screens[0].relativePositionX = value; + } + } + + get relativePositionY() { return this._screens[0].relativePositionY; } + set relativePositionY(value) { + if (!this._isPrimaryDisplay && (this._screens[0].relativePosition == 0 || this._screens[0].relativePosition == 2)) { + this._screens[0].relativePositionY = value; + } + } + get screens() { return this._screens; } get screenId() { return this._screenID; } @@ -226,9 +252,7 @@ export default class Display { let data = { screens: null, serverWidth: 0, - serverHeight: 0, - clientWidth: 0, - clientHeight: 0 + serverHeight: 0 } //recalculate primary display container size @@ -274,54 +298,72 @@ export default class Display { this._screens[i].serverWidth = width; this._screens[i].serverHeight = height; - - //this logic will only support monitors laid out side by side - //TODO: two vertically stacked monitors would require light refactoring here - data.serverWidth += width; - data.serverHeight = Math.max(data.serverHeight, height); - data.clientWidth += this._screens[i].width; - data.clientHeight = Math.max(data.clientHeight, this._screens[i].height); this._screens[i].scale = scale; } - //calculate positions of monitors, this logic will only support two monitors side by side in either order + const primary_screen = this._screens[0]; + //reset primary display position + primary_screen.x = 0; + primary_screen.y = 0; + let total_server_width = primary_screen.serverWidth; + let total_server_height = primary_screen.serverHeight; + + //TODO: The following logic will only support two monitors + // Calculate total area of all screens and positions of each screen within the total area if (this._screens.length > 1) { - const primary_screen = this._screens[0]; + const secondary_screen = this._screens[1]; - let total_width = 0; - let total_height = 0; + secondary_screen.x = 0; + secondary_screen.y = 0; switch (this._screens[1].relativePosition) { case 0: //primary screen is to left - total_width = secondary_screen.serverWidth + primary_screen.serverWidth; - total_height = Math.max(primary_screen.serverHeight, secondary_screen.serverHeight); + total_server_width = secondary_screen.serverWidth + primary_screen.serverWidth; + total_server_height = Math.max(primary_screen.serverHeight, secondary_screen.serverHeight) + Math.abs(secondary_screen.relativePositionY); secondary_screen.x = primary_screen.serverWidth; - if (secondary_screen.serverHeight < primary_screen.serverHeight) { - if ((total_height - secondary_screen.serverHeight) > 1) { - secondary_screen.y = Math.abs(Math.round(((total_height - secondary_screen.serverHeight) / 2))) - } + + if (secondary_screen.relativePositionY >= 0) { + secondary_screen.y = secondary_screen.relativePositionY; } else { - secondary_screen.y = 0; - if ((total_height - secondary_screen.serverHeight) > 1) { - this._screens[0].y = Math.abs(Math.round(((total_height - secondary_screen.serverHeight) / 2))) - } + primary_screen.y = Math.abs(secondary_screen.relativePositionY); + } + + break; + case 1: + //primary screen is up above + total_server_width = Math.max(primary_screen.serverWidth, secondary_screen.serverWidth) + Math.abs(secondary_screen.relativePositionX); + total_server_height = secondary_screen.serverHeight + primary_screen.serverHeight; + secondary_screen.y = primary_screen.serverHeight; + + if (secondary_screen.relativePositionX >= 0) { + secondary_screen.x = secondary_screen.relativePositionX; + } else { + primary_screen.x = Math.abs(secondary_screen.relativePositionX); } break; case 2: //primary screen is to right - total_width = primary_screen.serverWidth + secondary_screen.serverWidth; - total_height = Math.max(primary_screen.serverHeight, secondary_screen.serverHeight); - this._screens[0].x = secondary_screen.serverWidth; - if (secondary_screen.serverHeight < primary_screen.serverHeight) { - if ((total_height - secondary_screen.serverHeight) > 1) { - secondary_screen.y = Math.abs(Math.round(((total_height - secondary_screen.serverHeight) / 2))) - } + total_server_width = secondary_screen.serverWidth + primary_screen.serverWidth; + total_server_height = Math.max(primary_screen.serverHeight, secondary_screen.serverHeight) + Math.abs(secondary_screen.relativePositionY); + primary_screen.x = secondary_screen.serverWidth; + + if (secondary_screen.relativePositionY >= 0) { + secondary_screen.y = secondary_screen.relativePositionY; } else { - secondary_screen.y = 0; - if ((total_height - secondary_screen.serverHeight) > 1) { - primary_screen.y = Math.abs(Math.round(((total_height - secondary_screen.serverHeight) / 2))) - } + primary_screen.y = Math.abs(secondary_screen.relativePositionY); + } + break; + case 3: + //primary screen is down below + total_server_width = Math.max(primary_screen.serverWidth, secondary_screen.serverWidth) + Math.abs(secondary_screen.relativePositionX); + total_server_height = secondary_screen.serverHeight + primary_screen.serverHeight; + primary_screen.y = secondary_screen.serverHeight; + + if (secondary_screen.relativePositionX >= 0) { + secondary_screen.x = secondary_screen.relativePositionX; + } else { + primary_screen.x = Math.abs(secondary_screen.relativePositionX); } break; default: @@ -331,11 +373,13 @@ export default class Display { } data.screens = this._screens; + data.serverWidth = total_server_width; + data.serverHeight = total_server_height; return data; } - addScreen(screenID, width, height, relativePosition, pixelRatio, containerHeight, containerWidth) { + addScreen(screenID, width, height, relativePosition, relativePositionX, relativePositionY, pixelRatio, containerHeight, containerWidth) { if (this._isPrimaryDisplay) { //currently only support one secondary screen if (this._screens.length > 1) { @@ -353,6 +397,8 @@ export default class Display { x: 0, y: 0, relativePosition: relativePosition, + relativePositionX: relativePositionX, + relativePositionY: relativePositionY, pixelRatio: pixelRatio, containerHeight: containerHeight, containerWidth: containerWidth, diff --git a/core/rfb.js b/core/rfb.js index 313115b5..210911a9 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -300,11 +300,7 @@ export default class RFB extends EventTargetMixin { if (this._isPrimaryDisplay) { this._setupWebSocket(); - } else { - this._updateConnectionState('connecting'); - this._registerSecondaryDisplay(); - this._updateConnectionState('connected'); - } + } Log.Debug("<< RFB.constructor"); @@ -736,6 +732,16 @@ export default class RFB extends EventTargetMixin { // ===== PUBLIC METHODS ===== + attachSecondaryDisplay(relativePosition, relativePositionX, relativePositionY) { + this._display.relativePosition = relativePosition; + this._display.relativePositionX = relativePositionX; + this._display.relativePositionY = relativePositionY; + + this._updateConnectionState('connecting'); + this._registerSecondaryDisplay(); + this._updateConnectionState('connected'); + } + /* This function must be called after changing any properties that effect rendering quality */ @@ -1629,7 +1635,7 @@ export default class RFB extends EventTargetMixin { // Secondary to Primary screen message switch (event.data.eventType) { case 'register': - this._display.addScreen(event.data.screenID, event.data.width, event.data.height, event.data.relativePosition, event.data.pixelRatio, event.data.containerHeight, event.data.containerWidth); + this._display.addScreen(event.data.screenID, event.data.width, event.data.height, event.data.relativePosition, event.data.relativePositionX, event.data.relativePositionY, event.data.pixelRatio, event.data.containerHeight, event.data.containerWidth); const size = this._screenSize(); RFB.messages.setDesktopSize(this._sock, size, this._screenFlags); this._updateContinuousUpdates(); @@ -1688,7 +1694,9 @@ export default class RFB extends EventTargetMixin { height: screen.height, x: 0, y: 0, - relativePosition: 0, + relativePosition: screen.relativePosition, + relativePositionX: screen.relativePositionX, + relativePositionY: screen.relativePositionY, pixelRatio: screen.pixelRatio, containerWidth: screen.containerWidth, containerHeight: screen.containerHeight,