Added support for all orientations and offsets

This commit is contained in:
mattmcclaskey 2023-09-20 08:17:05 -04:00
parent cb1bc7f787
commit c35b8c68f3
No known key found for this signature in database
3 changed files with 116 additions and 43 deletions

View File

@ -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() {
},

View File

@ -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,

View File

@ -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,