mirror of
https://github.com/kbumsik/VirtScreen.git
synced 2025-03-09 15:40:18 +00:00
Moved virtual screen device to advanced
This commit is contained in:
parent
7f3448a25e
commit
710864a44d
7 changed files with 145 additions and 53 deletions
|
@ -277,6 +277,17 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: displayOptionsLoader
|
||||||
|
active: false
|
||||||
|
source: "DisplayOptionsDialog.qml"
|
||||||
|
onLoaded: {
|
||||||
|
item.onClosed.connect(function() {
|
||||||
|
displayOptionsLoader.active = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: vncOptionsLoader
|
id: vncOptionsLoader
|
||||||
active: false
|
active: false
|
||||||
|
|
70
virtscreen/assets/DisplayOptionsDialog.qml
Normal file
70
virtscreen/assets/DisplayOptionsDialog.qml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Controls.Material 2.3
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
title: "Display Options"
|
||||||
|
focus: true
|
||||||
|
modal: true
|
||||||
|
visible: true
|
||||||
|
standardButtons: Dialog.Ok
|
||||||
|
x: (window.width - width) / 2
|
||||||
|
y: (window.width - height) / 2
|
||||||
|
width: popupWidth
|
||||||
|
height: 250
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
Label { id: deviceLabel; text: "Device"; }
|
||||||
|
ComboBox {
|
||||||
|
id: deviceComboBox
|
||||||
|
anchors.left: deviceLabel.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: 100
|
||||||
|
textRole: "name"
|
||||||
|
model: backend.screens
|
||||||
|
currentIndex: {
|
||||||
|
if (settings.virt.device) {
|
||||||
|
for (var i = 0; i < model.length; i++) {
|
||||||
|
if (model[i].name == settings.virt.device) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.virt.device = '';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
onActivated: function(index) {
|
||||||
|
settings.virt.device = model[index].name;
|
||||||
|
}
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
width: deviceComboBox.width
|
||||||
|
text: modelData.name
|
||||||
|
font.weight: deviceComboBox.currentIndex === index ? Font.Bold : Font.Normal
|
||||||
|
enabled: modelData.connected ? false : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font { pointSize: 10 }
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: "<b>Warning</b>: Edit only if 'VIRTUAL1' is not available<br/>" +
|
||||||
|
"If so, please note that the virtual screen may be<br/>" +
|
||||||
|
"unstable/unavailable depending on a graphic<br/>" +
|
||||||
|
"card and its driver."
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
// Empty layout
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onAccepted: {}
|
||||||
|
onRejected: {}
|
||||||
|
}
|
|
@ -59,26 +59,14 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.left: parent.left
|
Layout.alignment: Qt.AlignRight
|
||||||
anchors.right: parent.right
|
Button {
|
||||||
Label { id: deviceLabel; text: "Device"; }
|
text: "Advanced"
|
||||||
ComboBox {
|
font.capitalization: Font.MixedCase
|
||||||
id: deviceComboBox
|
onClicked: displayOptionsLoader.active = true;
|
||||||
anchors.left: deviceLabel.right
|
background.opacity : 0
|
||||||
anchors.right: parent.right
|
onHoveredChanged: hovered ? background.opacity = 0.4
|
||||||
anchors.leftMargin: 100
|
:background.opacity = 0;
|
||||||
textRole: "name"
|
|
||||||
model: backend.screens
|
|
||||||
currentIndex: backend.virtScreenIndex
|
|
||||||
onActivated: function(index) {
|
|
||||||
backend.virtScreenIndex = index
|
|
||||||
}
|
|
||||||
delegate: ItemDelegate {
|
|
||||||
width: deviceComboBox.width
|
|
||||||
text: modelData.name
|
|
||||||
font.weight: deviceComboBox.currentIndex === index ? Font.Bold : Font.Normal
|
|
||||||
enabled: modelData.connected ? false : true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import QtQuick.Controls.Material 2.3
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
Dialog {
|
Dialog {
|
||||||
id: preferenceDialog
|
|
||||||
title: "VNC Options"
|
title: "VNC Options"
|
||||||
focus: true
|
focus: true
|
||||||
modal: true
|
modal: true
|
||||||
|
|
|
@ -84,7 +84,7 @@ ColumnLayout {
|
||||||
GroupBox {
|
GroupBox {
|
||||||
title: "Available IP addresses"
|
title: "Available IP addresses"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: 150
|
implicitHeight: 145
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
ListView {
|
ListView {
|
||||||
|
|
|
@ -10,6 +10,12 @@ Item {
|
||||||
property var settings: JSON.parse(backend.settings)
|
property var settings: JSON.parse(backend.settings)
|
||||||
property bool autostart: settings.vnc.autostart
|
property bool autostart: settings.vnc.autostart
|
||||||
|
|
||||||
|
function createVirtScreen () {
|
||||||
|
backend.createVirtScreen(settings.virt.device, settings.virt.width,
|
||||||
|
settings.virt.height, settings.virt.portrait,
|
||||||
|
settings.virt.hidpi);
|
||||||
|
}
|
||||||
|
|
||||||
function startVNC () {
|
function startVNC () {
|
||||||
var options = '';
|
var options = '';
|
||||||
var data = settings.x11vncOptions;
|
var data = settings.x11vncOptions;
|
||||||
|
@ -185,8 +191,7 @@ Item {
|
||||||
// Give a very short delay to show busyDialog.
|
// Give a very short delay to show busyDialog.
|
||||||
timer.setTimeout (function() {
|
timer.setTimeout (function() {
|
||||||
if (!backend.virtScreenCreated) {
|
if (!backend.virtScreenCreated) {
|
||||||
backend.createVirtScreen(settings.virt.width, settings.virt.height,
|
createVirtScreen();
|
||||||
settings.virt.portrait, settings.virt.hidpi);
|
|
||||||
} else {
|
} else {
|
||||||
// If auto start enabled, stop VNC first then
|
// If auto start enabled, stop VNC first then
|
||||||
if (autostart && (backend.vncState != Backend.OFF)) {
|
if (autostart && (backend.vncState != Backend.OFF)) {
|
||||||
|
|
|
@ -257,7 +257,6 @@ class DisplayProperty(QObject):
|
||||||
# Screen adjustment class
|
# Screen adjustment class
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
class XRandR(SubprocessWrapper):
|
class XRandR(SubprocessWrapper):
|
||||||
DEFAULT_VIRT_SCREEN = "VIRTUAL1"
|
|
||||||
VIRT_SCREEN_SUFFIX = "_virt"
|
VIRT_SCREEN_SUFFIX = "_virt"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -266,6 +265,7 @@ class XRandR(SubprocessWrapper):
|
||||||
self.screens: List[Display] = []
|
self.screens: List[Display] = []
|
||||||
self.virt: Display() = None
|
self.virt: Display() = None
|
||||||
self.primary: Display() = None
|
self.primary: Display() = None
|
||||||
|
self.virt_name: str = ''
|
||||||
self.virt_idx: int = None
|
self.virt_idx: int = None
|
||||||
self.primary_idx: int = None
|
self.primary_idx: int = None
|
||||||
# Primary display
|
# Primary display
|
||||||
|
@ -276,13 +276,14 @@ class XRandR(SubprocessWrapper):
|
||||||
self.primary = None
|
self.primary = None
|
||||||
self.virt = None
|
self.virt = None
|
||||||
self.screens = []
|
self.screens = []
|
||||||
|
self.virt_idx = None
|
||||||
self.primary_idx = None
|
self.primary_idx = None
|
||||||
pattern = re.compile(r"^(\S*)\s+(connected|disconnected)\s+((primary)\s+)?"
|
pattern = re.compile(r"^(\S*)\s+(connected|disconnected)\s+((primary)\s+)?"
|
||||||
r"((\d+)x(\d+)\+(\d+)\+(\d+)\s+)?.*$", re.M)
|
r"((\d+)x(\d+)\+(\d+)\+(\d+)\s+)?.*$", re.M)
|
||||||
for idx, match in enumerate(pattern.finditer(output)):
|
for idx, match in enumerate(pattern.finditer(output)):
|
||||||
screen = Display()
|
screen = Display()
|
||||||
screen.name = match.group(1)
|
screen.name = match.group(1)
|
||||||
if (self.virt_idx is None) and (screen.name == self.DEFAULT_VIRT_SCREEN):
|
if self.virt_name and screen.name == self.virt_name:
|
||||||
self.virt_idx = idx
|
self.virt_idx = idx
|
||||||
screen.primary = True if match.group(4) else False
|
screen.primary = True if match.group(4) else False
|
||||||
if screen.primary:
|
if screen.primary:
|
||||||
|
@ -299,19 +300,23 @@ class XRandR(SubprocessWrapper):
|
||||||
print("Display information:")
|
print("Display information:")
|
||||||
for s in self.screens:
|
for s in self.screens:
|
||||||
print("\t", s)
|
print("\t", s)
|
||||||
|
if self.primary_idx is None:
|
||||||
|
raise RuntimeError("There is no primary screen detected.\n"
|
||||||
|
"Go to display settings and set\n"
|
||||||
|
"a primary screen\n")
|
||||||
if self.virt_idx == self.primary_idx:
|
if self.virt_idx == self.primary_idx:
|
||||||
raise RuntimeError("Virtual screen must be selected other than the primary screen")
|
raise RuntimeError("Virtual screen must be selected other than the primary screen")
|
||||||
if self.virt_idx is None:
|
if self.virt_idx is not None:
|
||||||
for idx, screen in enumerate(self.screens):
|
self.virt = self.screens[self.virt_idx]
|
||||||
if not screen.connected and not screen.active:
|
elif self.virt_name and self.virt_idx is None:
|
||||||
self.virt_idx = idx
|
raise RuntimeError("No virtual screen name found")
|
||||||
break
|
|
||||||
if self.virt_idx is None:
|
|
||||||
raise RuntimeError("There is no available devices for virtual screen")
|
|
||||||
self.virt = self.screens[self.virt_idx]
|
|
||||||
self.primary = self.screens[self.primary_idx]
|
self.primary = self.screens[self.primary_idx]
|
||||||
|
|
||||||
def _add_screen_mode(self, width, height, portrait, hidpi) -> None:
|
def _add_screen_mode(self, width, height, portrait, hidpi) -> None:
|
||||||
|
if not self.virt or not self.virt_name:
|
||||||
|
raise RuntimeError("No virtual screen selected.\n"
|
||||||
|
"Go to Display->Virtual Display->Advaced\n"
|
||||||
|
"To select a device.")
|
||||||
# Set virtual screen property first
|
# Set virtual screen property first
|
||||||
self.virt.width = width
|
self.virt.width = width
|
||||||
self.virt.height = height
|
self.virt.height = height
|
||||||
|
@ -353,6 +358,7 @@ class XRandR(SubprocessWrapper):
|
||||||
|
|
||||||
def create_virtual_screen(self, width, height, portrait=False, hidpi=False) -> None:
|
def create_virtual_screen(self, width, height, portrait=False, hidpi=False) -> None:
|
||||||
print("creating: ", self.virt)
|
print("creating: ", self.virt)
|
||||||
|
self._update_screens()
|
||||||
self._add_screen_mode(width, height, portrait, hidpi)
|
self._add_screen_mode(width, height, portrait, hidpi)
|
||||||
self.check_output(f"xrandr --output {self.virt.name} --mode {self.mode_name}")
|
self.check_output(f"xrandr --output {self.virt.name} --mode {self.mode_name}")
|
||||||
self.check_output("sleep 5")
|
self.check_output("sleep 5")
|
||||||
|
@ -360,6 +366,7 @@ class XRandR(SubprocessWrapper):
|
||||||
self._update_screens()
|
self._update_screens()
|
||||||
|
|
||||||
def delete_virtual_screen(self) -> None:
|
def delete_virtual_screen(self) -> None:
|
||||||
|
self._update_screens()
|
||||||
try:
|
try:
|
||||||
self.virt.name
|
self.virt.name
|
||||||
self.mode_name
|
self.mode_name
|
||||||
|
@ -400,7 +407,6 @@ class Backend(QObject):
|
||||||
# Virtual screen properties
|
# Virtual screen properties
|
||||||
self.xrandr: XRandR = XRandR()
|
self.xrandr: XRandR = XRandR()
|
||||||
self._virtScreenCreated: bool = False
|
self._virtScreenCreated: bool = False
|
||||||
self._virtScreenIndex: int = self.xrandr.virt_idx
|
|
||||||
# VNC server properties
|
# VNC server properties
|
||||||
self._vncUsePassword: bool = False
|
self._vncUsePassword: bool = False
|
||||||
self._vncState: self.VNCState = self.VNCState.OFF
|
self._vncState: self.VNCState = self.VNCState.OFF
|
||||||
|
@ -473,18 +479,11 @@ class Backend(QObject):
|
||||||
|
|
||||||
@pyqtProperty(QQmlListProperty, constant=True)
|
@pyqtProperty(QQmlListProperty, constant=True)
|
||||||
def screens(self):
|
def screens(self):
|
||||||
return QQmlListProperty(DisplayProperty, self, [DisplayProperty(x) for x in self.xrandr.screens])
|
try:
|
||||||
|
return QQmlListProperty(DisplayProperty, self, [DisplayProperty(x) for x in self.xrandr.screens])
|
||||||
@pyqtProperty(int, notify=onVirtScreenIndexChanged)
|
except RuntimeError as e:
|
||||||
def virtScreenIndex(self):
|
self.onError.emit(str(e))
|
||||||
return self._virtScreenIndex
|
return QQmlListProperty(DisplayProperty, self, [])
|
||||||
|
|
||||||
@virtScreenIndex.setter
|
|
||||||
def virtScreenIndex(self, virtScreenIndex):
|
|
||||||
print("Changing virt to ", virtScreenIndex)
|
|
||||||
self.xrandr.virt_idx = virtScreenIndex
|
|
||||||
self.xrandr.virt = self.xrandr.screens[self.xrandr.virt_idx]
|
|
||||||
self._virtScreenIndex = virtScreenIndex
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify=onVncUsePasswordChanged)
|
@pyqtProperty(bool, notify=onVncUsePasswordChanged)
|
||||||
def vncUsePassword(self):
|
def vncUsePassword(self):
|
||||||
|
@ -523,7 +522,11 @@ class Backend(QObject):
|
||||||
|
|
||||||
@pyqtProperty(DisplayProperty)
|
@pyqtProperty(DisplayProperty)
|
||||||
def primary(self):
|
def primary(self):
|
||||||
self._primaryProp = DisplayProperty(self.xrandr.get_primary_screen())
|
try:
|
||||||
|
self._primaryProp = DisplayProperty(self.xrandr.get_primary_screen())
|
||||||
|
except RuntimeError as e:
|
||||||
|
self.onError.emit(str(e))
|
||||||
|
return
|
||||||
return self._primaryProp
|
return self._primaryProp
|
||||||
|
|
||||||
@pyqtProperty(int)
|
@pyqtProperty(int)
|
||||||
|
@ -537,14 +540,18 @@ class Backend(QObject):
|
||||||
return cursor.y()
|
return cursor.y()
|
||||||
|
|
||||||
# Qt Slots
|
# Qt Slots
|
||||||
@pyqtSlot(int, int, bool, bool)
|
@pyqtSlot(str, int, int, bool, bool)
|
||||||
def createVirtScreen(self, width, height, portrait, hidpi):
|
def createVirtScreen(self, device, width, height, portrait, hidpi):
|
||||||
|
self.xrandr.virt_name = device
|
||||||
print("Creating a Virtual Screen...")
|
print("Creating a Virtual Screen...")
|
||||||
try:
|
try:
|
||||||
self.xrandr.create_virtual_screen(width, height, portrait, hidpi)
|
self.xrandr.create_virtual_screen(width, height, portrait, hidpi)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
self.onError.emit(str(e.cmd) + '\n' + e.stdout.decode('utf-8'))
|
self.onError.emit(str(e.cmd) + '\n' + e.stdout.decode('utf-8'))
|
||||||
return
|
return
|
||||||
|
except RuntimeError as e:
|
||||||
|
self.onError.emit(str(e))
|
||||||
|
return
|
||||||
self.virtScreenCreated = True
|
self.virtScreenCreated = True
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -554,7 +561,11 @@ class Backend(QObject):
|
||||||
self.onError.emit("Turn off the VNC server first")
|
self.onError.emit("Turn off the VNC server first")
|
||||||
self.virtScreenCreated = True
|
self.virtScreenCreated = True
|
||||||
return
|
return
|
||||||
self.xrandr.delete_virtual_screen()
|
try:
|
||||||
|
self.xrandr.delete_virtual_screen()
|
||||||
|
except RuntimeError as e:
|
||||||
|
self.onError.emit(str(e))
|
||||||
|
return
|
||||||
self.virtScreenCreated = False
|
self.virtScreenCreated = False
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
@ -619,7 +630,11 @@ class Backend(QObject):
|
||||||
|
|
||||||
logfile = open(X11VNC_LOG_PATH, "wb")
|
logfile = open(X11VNC_LOG_PATH, "wb")
|
||||||
self.vncServer = ProcessProtocol(_onConnected, _onReceived, _onReceived, _onEnded, logfile)
|
self.vncServer = ProcessProtocol(_onConnected, _onReceived, _onReceived, _onEnded, logfile)
|
||||||
virt = self.xrandr.get_virtual_screen()
|
try:
|
||||||
|
virt = self.xrandr.get_virtual_screen()
|
||||||
|
except RuntimeError as e:
|
||||||
|
self.onError.emit(str(e))
|
||||||
|
return
|
||||||
clip = f"{virt.width}x{virt.height}+{virt.x_offset}+{virt.y_offset}"
|
clip = f"{virt.width}x{virt.height}+{virt.x_offset}+{virt.y_offset}"
|
||||||
arg = f"x11vnc -rfbport {port} -clip {clip} {options}"
|
arg = f"x11vnc -rfbport {port} -clip {clip} {options}"
|
||||||
if self.vncUsePassword:
|
if self.vncUsePassword:
|
||||||
|
@ -717,7 +732,11 @@ def main():
|
||||||
QMessageBox.critical(None, "VirtScreen",
|
QMessageBox.critical(None, "VirtScreen",
|
||||||
"x11vnc is not installed.")
|
"x11vnc is not installed.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
try:
|
||||||
|
test = XRandR()
|
||||||
|
except RuntimeError as e:
|
||||||
|
QMessageBox.critical(None, "VirtScreen", str(e))
|
||||||
|
sys.exit(1)
|
||||||
# Replace Twisted reactor with qt5reactor
|
# Replace Twisted reactor with qt5reactor
|
||||||
import qt5reactor # pylint: disable=E0401
|
import qt5reactor # pylint: disable=E0401
|
||||||
qt5reactor.install()
|
qt5reactor.install()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue