mirror of
https://github.com/ralsina/xrandroll.git
synced 2024-11-24 12:02:23 +00:00
README
This commit is contained in:
parent
6c62d979c8
commit
680a350007
23
README.md
Normal file
23
README.md
Normal 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
40
main.py
@ -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
16
main.ui
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user