This commit is contained in:
Roberto Alsina 2020-01-31 19:17:50 -03:00
parent 6c62d979c8
commit 680a350007
3 changed files with 60 additions and 19 deletions

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# RandRoll
None of the existing display configuration tools does what I think is "the right thing".
So I went and wrote one.
## The Right Thing
* Don't start from a stored config, use xrandr to read the systems' current state
* Allow creating "profiles" that will get applied smartly (not there yet)
* Generate a xrandr invocation to reflect the desired configuration
* Allow per-monitor scaling
* Allow arbitrary monitor positioning
* Implement "scale everything so all the pixels are the same size" (not done yet)
## To try:
If you have PySide2: `python main.py` in the folder where main.py is located.
## TODO:
* Implement other things
* Make it a proper app, with installation and whatnot
* Forget about it forever

40
main.py
View File

@ -1,8 +1,9 @@
from copy import deepcopy
import shlex
import subprocess
import sys
from PySide2.QtCore import QFile, QObject, Slot
from PySide2.QtCore import QFile, QObject
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QGraphicsScene
@ -11,19 +12,20 @@ from monitor_item import MonitorItem
def gen_xrandr_from_data(data):
"""Takes monitor data and generates a xrandr command line."""
cli = ['xrandr']
cli = ["xrandr"]
for name, mon in data.items():
cli.append(f'--output {name}')
cli.append(f"--output {name}")
cli.append(f'--pos {int(mon["pos_x"])}x{int(mon["pos_y"])}')
cli.append(f'--mode {mon["current_mode"]}')
mod_x, mod_y = [int(n) for n in mon['current_mode'].split('x')]
mod_x, mod_y = [int(n) for n in mon["current_mode"].split("x")]
cli.append(f'--scale {mon["res_x"]/mod_x}x{mon["res_y"]/mod_y}')
if mon['primary']:
cli.append('--primary')
if not mon['enabled']:
cli.append('--off')
if mon["primary"]:
cli.append("--primary")
if not mon["enabled"]:
cli.append("--off")
return " ".join(cli)
return ' '.join(cli)
def parse_monitor(line):
parts = line.split()
@ -68,6 +70,7 @@ class Window(QObject):
super().__init__()
self.ui = ui
ui.show()
self.ui.setWindowTitle('Display Configuration')
self.ui.screenCombo.currentTextChanged.connect(self.monitor_selected)
self.xrandr_info = {}
self.get_xrandr_info()
@ -92,7 +95,7 @@ class Window(QObject):
def do_apply(self):
cli = gen_xrandr_from_data(self.xrandr_info)
print(cli)
subprocess.check_call(shlex.split(cli))
def fill_ui(self):
"""Load data from xrandr and setup the whole thing."""
@ -114,13 +117,17 @@ class Window(QObject):
mode = self.ui.modes.currentText()
if not mode:
return
print(f'Changing {mon} to {mode}')
self.xrandr_info[mon]['current_mode'] = mode
mode_x, mode_y = mode.split('x')
print(f"Changing {mon} to {mode}")
self.xrandr_info[mon]["current_mode"] = mode
mode_x, mode_y = mode.split("x")
# use resolution via scaling
self.xrandr_info[mon]['res_x'] = int(int(mode_x) * self.ui.horizontalScale.value() / 100)
self.xrandr_info[mon]['res_y'] = int(int(mode_y) * self.ui.verticalScale.value() / 100)
self.xrandr_info[mon]['item'].update_visuals(self.xrandr_info[mon])
self.xrandr_info[mon]["res_x"] = int(
int(mode_x) * self.ui.horizontalScale.value() / 100
)
self.xrandr_info[mon]["res_y"] = int(
int(mode_y) * self.ui.verticalScale.value() / 100
)
self.xrandr_info[mon]["item"].update_visuals(self.xrandr_info[mon])
def monitor_moved(self):
"Update xrandr_info with new monitor positions"
@ -221,7 +228,6 @@ class Window(QObject):
self.mode_changed() # Not really, but it's the same thing
if __name__ == "__main__":
app = QApplication(sys.argv)

16
main.ui
View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<class>Main</class>
<widget class="QDialog" name="Main">
<property name="geometry">
<rect>
<x>0</x>
@ -169,6 +169,9 @@
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="resetButton">
<property name="toolTip">
<string>Reset to initial configuration</string>
</property>
<property name="text">
<string>Reset</string>
</property>
@ -189,6 +192,9 @@
</item>
<item>
<widget class="QPushButton" name="okButton">
<property name="toolTip">
<string>Apply configuration and close</string>
</property>
<property name="text">
<string>Ok</string>
</property>
@ -196,6 +202,9 @@
</item>
<item>
<widget class="QPushButton" name="applyButton">
<property name="toolTip">
<string>Apply configuration</string>
</property>
<property name="text">
<string>Apply</string>
</property>
@ -203,6 +212,9 @@
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="toolTip">
<string>Close without applying configuration</string>
</property>
<property name="text">
<string>Cancel</string>
</property>