mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
displays: add niri-specific layout options to configurator
This commit is contained in:
@@ -14,34 +14,63 @@ Distribution-aware installer with TUI for deploying DMS and compositor configura
|
|||||||
|
|
||||||
## System Integration
|
## System Integration
|
||||||
|
|
||||||
**Wayland Protocols**
|
### Wayland Protocols (Client)
|
||||||
- `wlr-gamma-control-unstable-v1` - Night mode and gamma control
|
|
||||||
- `wlr-screencopy-unstable-v1` - Screen capture for color picker
|
|
||||||
- `wlr-layer-shell-unstable-v1` - Overlay surfaces for color picker
|
|
||||||
- `wp-viewporter` - Fractional scaling support
|
|
||||||
- `dwl-ipc-unstable-v2` - dwl/MangoWC workspace integration
|
|
||||||
- `ext-workspace-v1` - Workspace protocol support
|
|
||||||
- `wlr-output-management-unstable-v1` - Display configuration
|
|
||||||
|
|
||||||
**DBus Interfaces**
|
All Wayland protocols are consumed as a client - connecting to the compositor.
|
||||||
- NetworkManager/iwd - Network management
|
|
||||||
- logind - Session control and inhibit locks
|
|
||||||
- accountsservice - User account information
|
|
||||||
- CUPS - Printer management
|
|
||||||
- Custom IPC via unix socket (JSON API)
|
|
||||||
|
|
||||||
**Hardware Control**
|
| Protocol | Purpose |
|
||||||
- DDC/CI protocol - External monitor brightness control (like `ddcutil`)
|
| ----------------------------------------- | ----------------------------------------------------------- |
|
||||||
- Backlight control - Internal display brightness via `login1` or sysfs
|
| `wlr-gamma-control-unstable-v1` | Night mode color temperature control |
|
||||||
- LED control - Keyboard/device LED management
|
| `wlr-screencopy-unstable-v1` | Screen capture for color picker/screenshot |
|
||||||
- evdev input monitoring - Keyboard state tracking (caps lock, etc.)
|
| `wlr-layer-shell-unstable-v1` | Overlay surfaces for color picker UI/screenshot |
|
||||||
|
| `wlr-output-management-unstable-v1` | Display configuration |
|
||||||
|
| `wlr-output-power-management-unstable-v1` | DPMS on/off CLI |
|
||||||
|
| `wp-viewporter` | Fractional scaling support (color picker/screenshot UIs) |
|
||||||
|
| `keyboard-shortcuts-inhibit-unstable-v1` | Inhibit compositor shortcuts during color picker/screenshot |
|
||||||
|
| `ext-data-control-v1` | Clipboard history and persistence |
|
||||||
|
| `ext-workspace-v1` | Workspace integration |
|
||||||
|
| `dwl-ipc-unstable-v2` | dwl/MangoWC IPC for tags, outputs, etc. |
|
||||||
|
|
||||||
|
### DBus Interfaces
|
||||||
|
|
||||||
|
**Client (consuming external services):**
|
||||||
|
|
||||||
|
| Interface | Purpose |
|
||||||
|
| -------------------------------- | --------------------------------------------- |
|
||||||
|
| `org.bluez` | Bluetooth management with pairing agent |
|
||||||
|
| `org.freedesktop.NetworkManager` | Network management |
|
||||||
|
| `net.connman.iwd` | iwd Wi-Fi backend |
|
||||||
|
| `org.freedesktop.network1` | systemd-networkd integration |
|
||||||
|
| `org.freedesktop.login1` | Session control, sleep inhibitors, brightness |
|
||||||
|
| `org.freedesktop.Accounts` | User account information |
|
||||||
|
| `org.freedesktop.portal.Desktop` | Desktop appearance settings (color scheme) |
|
||||||
|
| CUPS via IPP + D-Bus | Printer management with job notifications |
|
||||||
|
|
||||||
|
**Server (implementing interfaces):**
|
||||||
|
|
||||||
|
| Interface | Purpose |
|
||||||
|
| ----------------------------- | -------------------------------------- |
|
||||||
|
| `org.freedesktop.ScreenSaver` | Screensaver inhibit for video playback |
|
||||||
|
|
||||||
|
Custom IPC via unix socket (JSON API) for shell communication.
|
||||||
|
|
||||||
|
### Hardware Control
|
||||||
|
|
||||||
|
| Subsystem | Method | Purpose |
|
||||||
|
| --------- | ------------------- | ---------------------------------- |
|
||||||
|
| DDC/CI | I2C direct | External monitor brightness |
|
||||||
|
| Backlight | logind or sysfs | Internal display brightness |
|
||||||
|
| evdev | `/dev/input/event*` | Keyboard state (caps lock LED) |
|
||||||
|
| udev | netlink monitor | Backlight device updates (for OSD) |
|
||||||
|
|
||||||
|
### Plugin System
|
||||||
|
|
||||||
**Plugin System**
|
|
||||||
- Plugin registry integration
|
- Plugin registry integration
|
||||||
- Plugin lifecycle management
|
- Plugin lifecycle management
|
||||||
- Settings persistence
|
- Settings persistence
|
||||||
|
|
||||||
## CLI Commands
|
## CLI Commands
|
||||||
|
|
||||||
- `dms run [-d]` - Start shell (optionally as daemon)
|
- `dms run [-d]` - Start shell (optionally as daemon)
|
||||||
- `dms restart` / `dms kill` - Manage running processes
|
- `dms restart` / `dms kill` - Manage running processes
|
||||||
- `dms ipc <command>` - Send IPC commands (toggle launcher, notifications, etc.)
|
- `dms ipc <command>` - Send IPC commands (toggle launcher, notifications, etc.)
|
||||||
@@ -70,6 +99,7 @@ The on-screen preview displays the selected format. JSON output includes hex, RG
|
|||||||
Requires Go 1.24+
|
Requires Go 1.24+
|
||||||
|
|
||||||
**Development build:**
|
**Development build:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make # Build dms CLI
|
make # Build dms CLI
|
||||||
make dankinstall # Build installer
|
make dankinstall # Build installer
|
||||||
@@ -77,6 +107,7 @@ make test # Run tests
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Distribution build:**
|
**Distribution build:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make dist # Build without update/greeter features
|
make dist # Build without update/greeter features
|
||||||
```
|
```
|
||||||
@@ -84,6 +115,7 @@ make dist # Build without update/greeter features
|
|||||||
Produces `bin/dms-linux-amd64` and `bin/dms-linux-arm64`
|
Produces `bin/dms-linux-amd64` and `bin/dms-linux-arm64`
|
||||||
|
|
||||||
**Installation:**
|
**Installation:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo make install # Install to /usr/local/bin/dms
|
sudo make install # Install to /usr/local/bin/dms
|
||||||
```
|
```
|
||||||
@@ -91,6 +123,7 @@ sudo make install # Install to /usr/local/bin/dms
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
**Setup pre-commit hooks:**
|
**Setup pre-commit hooks:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git config core.hooksPath .githooks
|
git config core.hooksPath .githooks
|
||||||
```
|
```
|
||||||
@@ -98,6 +131,7 @@ git config core.hooksPath .githooks
|
|||||||
This runs gofmt, golangci-lint, tests, and builds before each commit when `core/` files are staged.
|
This runs gofmt, golangci-lint, tests, and builds before each commit when `core/` files are staged.
|
||||||
|
|
||||||
**Regenerating Wayland Protocol Bindings:**
|
**Regenerating Wayland Protocol Bindings:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go install github.com/rajveermalviya/go-wayland/cmd/go-wayland-scanner@latest
|
go install github.com/rajveermalviya/go-wayland/cmd/go-wayland-scanner@latest
|
||||||
go-wayland-scanner -i internal/proto/xml/wlr-gamma-control-unstable-v1.xml \
|
go-wayland-scanner -i internal/proto/xml/wlr-gamma-control-unstable-v1.xml \
|
||||||
@@ -105,6 +139,7 @@ go-wayland-scanner -i internal/proto/xml/wlr-gamma-control-unstable-v1.xml \
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Module Structure:**
|
**Module Structure:**
|
||||||
|
|
||||||
- `cmd/` - Binary entrypoints (dms, dankinstall)
|
- `cmd/` - Binary entrypoints (dms, dankinstall)
|
||||||
- `internal/distros/` - Distribution-specific installation logic
|
- `internal/distros/` - Distribution-specific installation logic
|
||||||
- `internal/proto/` - Wayland protocol bindings
|
- `internal/proto/` - Wayland protocol bindings
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior
|
||||||
|
|
||||||
import QtCore
|
import QtCore
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -360,47 +360,48 @@ Singleton {
|
|||||||
property string displayNameMode: "system"
|
property string displayNameMode: "system"
|
||||||
property var screenPreferences: ({})
|
property var screenPreferences: ({})
|
||||||
property var showOnLastDisplay: ({})
|
property var showOnLastDisplay: ({})
|
||||||
|
property var niriOutputSettings: ({})
|
||||||
|
|
||||||
property var barConfigs: [
|
property var barConfigs: [
|
||||||
{
|
{
|
||||||
id: "default",
|
"id": "default",
|
||||||
name: "Main Bar",
|
"name": "Main Bar",
|
||||||
enabled: true,
|
"enabled": true,
|
||||||
position: 0,
|
"position": 0,
|
||||||
screenPreferences: ["all"],
|
"screenPreferences": ["all"],
|
||||||
showOnLastDisplay: true,
|
"showOnLastDisplay": true,
|
||||||
leftWidgets: ["launcherButton", "workspaceSwitcher", "focusedWindow"],
|
"leftWidgets": ["launcherButton", "workspaceSwitcher", "focusedWindow"],
|
||||||
centerWidgets: ["music", "clock", "weather"],
|
"centerWidgets": ["music", "clock", "weather"],
|
||||||
rightWidgets: ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"],
|
"rightWidgets": ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"],
|
||||||
spacing: 4,
|
"spacing": 4,
|
||||||
innerPadding: 4,
|
"innerPadding": 4,
|
||||||
bottomGap: 0,
|
"bottomGap": 0,
|
||||||
transparency: 1.0,
|
"transparency": 1.0,
|
||||||
widgetTransparency: 1.0,
|
"widgetTransparency": 1.0,
|
||||||
squareCorners: false,
|
"squareCorners": false,
|
||||||
noBackground: false,
|
"noBackground": false,
|
||||||
gothCornersEnabled: false,
|
"gothCornersEnabled": false,
|
||||||
gothCornerRadiusOverride: false,
|
"gothCornerRadiusOverride": false,
|
||||||
gothCornerRadiusValue: 12,
|
"gothCornerRadiusValue": 12,
|
||||||
borderEnabled: false,
|
"borderEnabled": false,
|
||||||
borderColor: "surfaceText",
|
"borderColor": "surfaceText",
|
||||||
borderOpacity: 1.0,
|
"borderOpacity": 1.0,
|
||||||
borderThickness: 1,
|
"borderThickness": 1,
|
||||||
widgetOutlineEnabled: false,
|
"widgetOutlineEnabled": false,
|
||||||
widgetOutlineColor: "primary",
|
"widgetOutlineColor": "primary",
|
||||||
widgetOutlineOpacity: 1.0,
|
"widgetOutlineOpacity": 1.0,
|
||||||
widgetOutlineThickness: 1,
|
"widgetOutlineThickness": 1,
|
||||||
fontScale: 1.0,
|
"fontScale": 1.0,
|
||||||
autoHide: false,
|
"autoHide": false,
|
||||||
autoHideDelay: 250,
|
"autoHideDelay": 250,
|
||||||
openOnOverview: false,
|
"openOnOverview": false,
|
||||||
visible: true,
|
"visible": true,
|
||||||
popupGapsAuto: true,
|
"popupGapsAuto": true,
|
||||||
popupGapsManual: 4,
|
"popupGapsManual": 4,
|
||||||
maximizeDetection: true,
|
"maximizeDetection": true,
|
||||||
scrollEnabled: true,
|
"scrollEnabled": true,
|
||||||
scrollXBehavior: "column",
|
"scrollXBehavior": "column",
|
||||||
scrollYBehavior: "workspace"
|
"scrollYBehavior": "workspace"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -458,25 +459,25 @@ Singleton {
|
|||||||
|
|
||||||
const configScript = `mkdir -p ${_configDir}/gtk-3.0 ${_configDir}/gtk-4.0
|
const configScript = `mkdir -p ${_configDir}/gtk-3.0 ${_configDir}/gtk-4.0
|
||||||
|
|
||||||
for config_dir in ${_configDir}/gtk-3.0 ${_configDir}/gtk-4.0; do
|
for config_dir in ${_configDir}/gtk-3.0 ${_configDir}/gtk-4.0; do
|
||||||
settings_file="$config_dir/settings.ini"
|
settings_file="$config_dir/settings.ini"
|
||||||
if [ -f "$settings_file" ]; then
|
if [ -f "$settings_file" ]; then
|
||||||
if grep -q "^gtk-icon-theme-name=" "$settings_file"; then
|
if grep -q "^gtk-icon-theme-name=" "$settings_file"; then
|
||||||
sed -i 's/^gtk-icon-theme-name=.*/gtk-icon-theme-name=${gtkThemeName}/' "$settings_file"
|
sed -i 's/^gtk-icon-theme-name=.*/gtk-icon-theme-name=${gtkThemeName}/' "$settings_file"
|
||||||
else
|
else
|
||||||
if grep -q "\\[Settings\\]" "$settings_file"; then
|
if grep -q "\\[Settings\\]" "$settings_file"; then
|
||||||
sed -i '/\\[Settings\\]/a gtk-icon-theme-name=${gtkThemeName}' "$settings_file"
|
sed -i '/\\[Settings\\]/a gtk-icon-theme-name=${gtkThemeName}' "$settings_file"
|
||||||
else
|
else
|
||||||
echo -e '\\n[Settings]\\ngtk-icon-theme-name=${gtkThemeName}' >> "$settings_file"
|
echo -e '\\n[Settings]\\ngtk-icon-theme-name=${gtkThemeName}' >> "$settings_file"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
else
|
fi
|
||||||
|
else
|
||||||
echo -e '[Settings]\\ngtk-icon-theme-name=${gtkThemeName}' > "$settings_file"
|
echo -e '[Settings]\\ngtk-icon-theme-name=${gtkThemeName}' > "$settings_file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
rm -rf ~/.cache/icon-cache ~/.cache/thumbnails 2>/dev/null || true
|
rm -rf ~/.cache/icon-cache ~/.cache/thumbnails 2>/dev/null || true
|
||||||
pkill -HUP -f 'gtk' 2>/dev/null || true`;
|
pkill -HUP -f 'gtk' 2>/dev/null || true`;
|
||||||
|
|
||||||
Quickshell.execDetached(["sh", "-lc", configScript]);
|
Quickshell.execDetached(["sh", "-lc", configScript]);
|
||||||
}
|
}
|
||||||
@@ -489,36 +490,36 @@ pkill -HUP -f 'gtk' 2>/dev/null || true`;
|
|||||||
const qtThemeNameEscaped = qtThemeName.replace(/'/g, "'\\''");
|
const qtThemeNameEscaped = qtThemeName.replace(/'/g, "'\\''");
|
||||||
|
|
||||||
const script = `mkdir -p ${_configDir}/qt5ct ${_configDir}/qt6ct ${_configDir}/environment.d 2>/dev/null || true
|
const script = `mkdir -p ${_configDir}/qt5ct ${_configDir}/qt6ct ${_configDir}/environment.d 2>/dev/null || true
|
||||||
update_qt_icon_theme() {
|
update_qt_icon_theme() {
|
||||||
local config_file="$1"
|
local config_file="$1"
|
||||||
local theme_name="$2"
|
local theme_name="$2"
|
||||||
if [ -f "$config_file" ]; then
|
if [ -f "$config_file" ]; then
|
||||||
if grep -q "^\\[Appearance\\]" "$config_file"; then
|
if grep -q "^\\[Appearance\\]" "$config_file"; then
|
||||||
if grep -q "^icon_theme=" "$config_file"; then
|
if grep -q "^icon_theme=" "$config_file"; then
|
||||||
sed -i "s/^icon_theme=.*/icon_theme=$theme_name/" "$config_file"
|
sed -i "s/^icon_theme=.*/icon_theme=$theme_name/" "$config_file"
|
||||||
else
|
else
|
||||||
sed -i "/^\\[Appearance\\]/a icon_theme=$theme_name" "$config_file"
|
sed -i "/^\\[Appearance\\]/a icon_theme=$theme_name" "$config_file"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "\\n[Appearance]\\nicon_theme=%s\\n" "$theme_name" >> "$config_file"
|
printf "\\n[Appearance]\\nicon_theme=%s\\n" "$theme_name" >> "$config_file"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "[Appearance]\\nicon_theme=%s\\n" "$theme_name" > "$config_file"
|
printf "[Appearance]\\nicon_theme=%s\\n" "$theme_name" > "$config_file"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
update_qt_icon_theme ${_configDir}/qt5ct/qt5ct.conf '${qtThemeNameEscaped}'
|
update_qt_icon_theme ${_configDir}/qt5ct/qt5ct.conf '${qtThemeNameEscaped}'
|
||||||
update_qt_icon_theme ${_configDir}/qt6ct/qt6ct.conf '${qtThemeNameEscaped}'
|
update_qt_icon_theme ${_configDir}/qt6ct/qt6ct.conf '${qtThemeNameEscaped}'
|
||||||
rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || true`;
|
rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || true`;
|
||||||
|
|
||||||
Quickshell.execDetached(["sh", "-lc", script]);
|
Quickshell.execDetached(["sh", "-lc", script]);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var _hooks: ({
|
readonly property var _hooks: ({
|
||||||
applyStoredTheme: applyStoredTheme,
|
"applyStoredTheme": applyStoredTheme,
|
||||||
regenSystemThemes: regenSystemThemes,
|
"regenSystemThemes": regenSystemThemes,
|
||||||
updateNiriLayout: updateNiriLayout,
|
"updateNiriLayout": updateNiriLayout,
|
||||||
applyStoredIconTheme: applyStoredIconTheme,
|
"applyStoredIconTheme": applyStoredIconTheme,
|
||||||
updateBarConfigs: updateBarConfigs
|
"updateBarConfigs": updateBarConfigs
|
||||||
})
|
})
|
||||||
|
|
||||||
function set(key, value) {
|
function set(key, value) {
|
||||||
@@ -723,7 +724,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
let leftBar = 0;
|
let leftBar = 0;
|
||||||
let rightBar = 0;
|
let rightBar = 0;
|
||||||
|
|
||||||
for (let i = 0; i < enabledBars.length; i++) {
|
for (var i = 0; i < enabledBars.length; i++) {
|
||||||
const other = enabledBars[i];
|
const other = enabledBars[i];
|
||||||
if (other.id === barConfig.id)
|
if (other.id === barConfig.id)
|
||||||
continue;
|
continue;
|
||||||
@@ -793,7 +794,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
|
|
||||||
if (barConfig) {
|
if (barConfig) {
|
||||||
const enabledBars = getEnabledBarConfigs();
|
const enabledBars = getEnabledBarConfigs();
|
||||||
for (let i = 0; i < enabledBars.length; i++) {
|
for (var i = 0; i < enabledBars.length; i++) {
|
||||||
const other = enabledBars[i];
|
const other = enabledBars[i];
|
||||||
if (other.id === barConfig.id)
|
if (other.id === barConfig.id)
|
||||||
continue;
|
continue;
|
||||||
@@ -925,7 +926,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const conflicts = [];
|
const conflicts = [];
|
||||||
const enabledBars = getEnabledBarConfigs();
|
const enabledBars = getEnabledBarConfigs();
|
||||||
|
|
||||||
for (let i = 0; i < enabledBars.length; i++) {
|
for (var i = 0; i < enabledBars.length; i++) {
|
||||||
const other = enabledBars[i];
|
const other = enabledBars[i];
|
||||||
if (other.id === barId)
|
if (other.id === barId)
|
||||||
continue;
|
continue;
|
||||||
@@ -938,9 +939,9 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const hasAll = barScreens.includes("all") || otherScreens.includes("all");
|
const hasAll = barScreens.includes("all") || otherScreens.includes("all");
|
||||||
if (hasAll) {
|
if (hasAll) {
|
||||||
conflicts.push({
|
conflicts.push({
|
||||||
barId: other.id,
|
"barId": other.id,
|
||||||
barName: other.name,
|
"barName": other.name,
|
||||||
reason: "Same position on all screens"
|
"reason": "Same position on all screens"
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -948,9 +949,9 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const overlapping = barScreens.some(screen => otherScreens.includes(screen));
|
const overlapping = barScreens.some(screen => otherScreens.includes(screen));
|
||||||
if (overlapping) {
|
if (overlapping) {
|
||||||
conflicts.push({
|
conflicts.push({
|
||||||
barId: other.id,
|
"barId": other.id,
|
||||||
barName: other.name,
|
"barName": other.name,
|
||||||
reason: "Same position on overlapping screens"
|
"reason": "Same position on overlapping screens"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -972,7 +973,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
|
|
||||||
function getScreensSortedByPosition() {
|
function getScreensSortedByPosition() {
|
||||||
const screens = [];
|
const screens = [];
|
||||||
for (let i = 0; i < Quickshell.screens.length; i++) {
|
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||||
screens.push(Quickshell.screens[i]);
|
screens.push(Quickshell.screens[i]);
|
||||||
}
|
}
|
||||||
screens.sort((a, b) => {
|
screens.sort((a, b) => {
|
||||||
@@ -989,7 +990,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const sorted = getScreensSortedByPosition();
|
const sorted = getScreensSortedByPosition();
|
||||||
let modelCount = 0;
|
let modelCount = 0;
|
||||||
let screenIndex = -1;
|
let screenIndex = -1;
|
||||||
for (let i = 0; i < sorted.length; i++) {
|
for (var i = 0; i < sorted.length; i++) {
|
||||||
if (sorted[i].model === screen.model) {
|
if (sorted[i].model === screen.model) {
|
||||||
if (sorted[i].name === screen.name) {
|
if (sorted[i].name === screen.name) {
|
||||||
screenIndex = modelCount;
|
screenIndex = modelCount;
|
||||||
@@ -1187,7 +1188,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
spacing: spacing
|
"spacing": spacing
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (typeof NiriService !== "undefined" && CompositorService.isNiri) {
|
if (typeof NiriService !== "undefined" && CompositorService.isNiri) {
|
||||||
@@ -1216,7 +1217,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
position: position
|
"position": position
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,7 +1225,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
leftWidgets: order
|
"leftWidgets": order
|
||||||
});
|
});
|
||||||
updateListModel(leftWidgetsModel, order);
|
updateListModel(leftWidgetsModel, order);
|
||||||
}
|
}
|
||||||
@@ -1234,7 +1235,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
centerWidgets: order
|
"centerWidgets": order
|
||||||
});
|
});
|
||||||
updateListModel(centerWidgetsModel, order);
|
updateListModel(centerWidgetsModel, order);
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1245,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
rightWidgets: order
|
"rightWidgets": order
|
||||||
});
|
});
|
||||||
updateListModel(rightWidgetsModel, order);
|
updateListModel(rightWidgetsModel, order);
|
||||||
}
|
}
|
||||||
@@ -1257,9 +1258,9 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
leftWidgets: defaultLeft,
|
"leftWidgets": defaultLeft,
|
||||||
centerWidgets: defaultCenter,
|
"centerWidgets": defaultCenter,
|
||||||
rightWidgets: defaultRight
|
"rightWidgets": defaultRight
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateListModel(leftWidgetsModel, defaultLeft);
|
updateListModel(leftWidgetsModel, defaultLeft);
|
||||||
@@ -1307,7 +1308,7 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
const defaultBar = barConfigs[0] || getBarConfig("default");
|
const defaultBar = barConfigs[0] || getBarConfig("default");
|
||||||
if (defaultBar) {
|
if (defaultBar) {
|
||||||
updateBarConfig(defaultBar.id, {
|
updateBarConfig(defaultBar.id, {
|
||||||
visible: !defaultBar.visible
|
"visible": !defaultBar.visible
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1345,6 +1346,42 @@ rm -rf '${home}'/.cache/icon-cache '${home}'/.cache/thumbnails 2>/dev/null || tr
|
|||||||
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNiriOutputSetting(outputId, key, defaultValue) {
|
||||||
|
if (!niriOutputSettings[outputId])
|
||||||
|
return defaultValue;
|
||||||
|
return niriOutputSettings[outputId][key] !== undefined ? niriOutputSettings[outputId][key] : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNiriOutputSetting(outputId, key, value) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
|
||||||
|
if (!updated[outputId])
|
||||||
|
updated[outputId] = {};
|
||||||
|
updated[outputId][key] = value;
|
||||||
|
niriOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNiriOutputSettings(outputId) {
|
||||||
|
const settings = niriOutputSettings[outputId];
|
||||||
|
return settings ? JSON.parse(JSON.stringify(settings)) : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNiriOutputSettings(outputId, settings) {
|
||||||
|
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
|
||||||
|
updated[outputId] = settings;
|
||||||
|
niriOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeNiriOutputSettings(outputId) {
|
||||||
|
if (!niriOutputSettings[outputId])
|
||||||
|
return;
|
||||||
|
const updated = JSON.parse(JSON.stringify(niriOutputSettings));
|
||||||
|
delete updated[outputId];
|
||||||
|
niriOutputSettings = updated;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: leftWidgetsModel
|
id: leftWidgetsModel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ var SPEC = {
|
|||||||
displayNameMode: { def: "system" },
|
displayNameMode: { def: "system" },
|
||||||
screenPreferences: { def: {} },
|
screenPreferences: { def: {} },
|
||||||
showOnLastDisplay: { def: {} },
|
showOnLastDisplay: { def: {} },
|
||||||
|
niriOutputSettings: { def: {} },
|
||||||
|
|
||||||
barConfigs: { def: [{
|
barConfigs: { def: [{
|
||||||
id: "default",
|
id: "default",
|
||||||
|
|||||||
@@ -32,9 +32,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +47,8 @@ FocusScope {
|
|||||||
sourceComponent: TimeWeatherTab {}
|
sourceComponent: TimeWeatherTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +64,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +81,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,9 +96,8 @@ FocusScope {
|
|||||||
sourceComponent: WorkspacesTab {}
|
sourceComponent: WorkspacesTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +113,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,9 +128,8 @@ FocusScope {
|
|||||||
sourceComponent: DisplayConfigTab {}
|
sourceComponent: DisplayConfigTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,9 +143,8 @@ FocusScope {
|
|||||||
sourceComponent: GammaControlTab {}
|
sourceComponent: GammaControlTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,9 +158,8 @@ FocusScope {
|
|||||||
sourceComponent: DisplayWidgetsTab {}
|
sourceComponent: DisplayWidgetsTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,9 +173,8 @@ FocusScope {
|
|||||||
sourceComponent: NetworkTab {}
|
sourceComponent: NetworkTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +188,8 @@ FocusScope {
|
|||||||
sourceComponent: PrinterTab {}
|
sourceComponent: PrinterTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,9 +203,8 @@ FocusScope {
|
|||||||
sourceComponent: LauncherTab {}
|
sourceComponent: LauncherTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,9 +218,8 @@ FocusScope {
|
|||||||
sourceComponent: ThemeColorsTab {}
|
sourceComponent: ThemeColorsTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,9 +233,8 @@ FocusScope {
|
|||||||
sourceComponent: LockScreenTab {}
|
sourceComponent: LockScreenTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,9 +250,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,9 +265,8 @@ FocusScope {
|
|||||||
sourceComponent: AboutTab {}
|
sourceComponent: AboutTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,9 +280,8 @@ FocusScope {
|
|||||||
sourceComponent: TypographyMotionTab {}
|
sourceComponent: TypographyMotionTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,9 +295,8 @@ FocusScope {
|
|||||||
sourceComponent: SoundsTab {}
|
sourceComponent: SoundsTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,9 +310,8 @@ FocusScope {
|
|||||||
sourceComponent: MediaPlayerTab {}
|
sourceComponent: MediaPlayerTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,9 +325,8 @@ FocusScope {
|
|||||||
sourceComponent: NotificationsTab {}
|
sourceComponent: NotificationsTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,9 +340,8 @@ FocusScope {
|
|||||||
sourceComponent: OSDTab {}
|
sourceComponent: OSDTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,9 +355,8 @@ FocusScope {
|
|||||||
sourceComponent: RunningAppsTab {}
|
sourceComponent: RunningAppsTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,9 +370,8 @@ FocusScope {
|
|||||||
sourceComponent: SystemUpdaterTab {}
|
sourceComponent: SystemUpdaterTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,9 +385,8 @@ FocusScope {
|
|||||||
sourceComponent: PowerSleepTab {}
|
sourceComponent: PowerSleepTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,9 +402,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,9 +417,8 @@ FocusScope {
|
|||||||
sourceComponent: ClipboardTab {}
|
sourceComponent: ClipboardTab {}
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active && item) {
|
if (active && item)
|
||||||
Qt.callLater(() => item.forceActiveFocus());
|
Qt.callLater(() => item.forceActiveFocus());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -32,15 +32,17 @@ StyledRect {
|
|||||||
|
|
||||||
readonly property bool collapsed: collapsible && !expanded
|
readonly property bool collapsed: collapsible && !expanded
|
||||||
readonly property bool hasHeader: root.title !== "" || root.iconName !== ""
|
readonly property bool hasHeader: root.title !== "" || root.iconName !== ""
|
||||||
property bool animationsEnabled: false
|
property bool userToggledCollapse: false
|
||||||
|
|
||||||
Component.onCompleted: Qt.callLater(() => animationsEnabled = true)
|
|
||||||
|
|
||||||
Behavior on height {
|
Behavior on height {
|
||||||
enabled: root.animationsEnabled
|
enabled: root.userToggledCollapse
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
|
onRunningChanged: {
|
||||||
|
if (!running)
|
||||||
|
root.userToggledCollapse = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +100,7 @@ StyledRect {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
if (!root.collapsible)
|
if (!root.collapsible)
|
||||||
return;
|
return;
|
||||||
|
root.userToggledCollapse = true;
|
||||||
root.expanded = !root.expanded;
|
root.expanded = !root.expanded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,14 +111,6 @@ StyledRect {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
visible: !root.collapsed
|
visible: !root.collapsed
|
||||||
opacity: root.collapsed ? 0 : 1
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -580,7 +580,6 @@ Singleton {
|
|||||||
const windowIndex = windows.findIndex(w => w.id === data.id);
|
const windowIndex = windows.findIndex(w => w.id === data.id);
|
||||||
if (windowIndex < 0)
|
if (windowIndex < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const updatedWindows = [...windows];
|
const updatedWindows = [...windows];
|
||||||
const updatedWindow = {};
|
const updatedWindow = {};
|
||||||
for (let prop in updatedWindows[windowIndex]) {
|
for (let prop in updatedWindows[windowIndex]) {
|
||||||
@@ -1140,8 +1139,15 @@ Singleton {
|
|||||||
for (const outputName in data) {
|
for (const outputName in data) {
|
||||||
const output = data[outputName];
|
const output = data[outputName];
|
||||||
const identifier = getOutputIdentifier(output, outputName);
|
const identifier = getOutputIdentifier(output, outputName);
|
||||||
|
const niriSettings = SettingsData.getNiriOutputSettings(identifier);
|
||||||
|
|
||||||
kdlContent += `output "${identifier}" {\n`;
|
kdlContent += `output "${identifier}" {\n`;
|
||||||
|
|
||||||
|
if (niriSettings.disabled) {
|
||||||
|
kdlContent += ` off\n}\n\n`;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (output.current_mode !== undefined && output.modes && output.modes[output.current_mode]) {
|
if (output.current_mode !== undefined && output.modes && output.modes[output.current_mode]) {
|
||||||
const mode = output.modes[output.current_mode];
|
const mode = output.modes[output.current_mode];
|
||||||
kdlContent += ` mode "${mode.width}x${mode.height}@${(mode.refresh_rate / 1000).toFixed(3)}"\n`;
|
kdlContent += ` mode "${mode.width}x${mode.height}@${(mode.refresh_rate / 1000).toFixed(3)}"\n`;
|
||||||
@@ -1172,9 +1178,21 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (output.vrr_enabled) {
|
if (output.vrr_enabled) {
|
||||||
kdlContent += ` variable-refresh-rate\n`;
|
const vrrOnDemand = niriSettings.vrrOnDemand ?? false;
|
||||||
|
kdlContent += vrrOnDemand ? ` variable-refresh-rate on-demand=true\n` : ` variable-refresh-rate\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (niriSettings.focusAtStartup) {
|
||||||
|
kdlContent += ` focus-at-startup\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (niriSettings.backdropColor) {
|
||||||
|
kdlContent += ` backdrop-color "${niriSettings.backdropColor}"\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
kdlContent += generateHotCornersBlock(niriSettings);
|
||||||
|
kdlContent += generateLayoutBlock(niriSettings);
|
||||||
|
|
||||||
kdlContent += `}\n\n`;
|
kdlContent += `}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,6 +1209,49 @@ Singleton {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateHotCornersBlock(niriSettings) {
|
||||||
|
if (!niriSettings.hotCorners)
|
||||||
|
return "";
|
||||||
|
const hc = niriSettings.hotCorners;
|
||||||
|
if (hc.off)
|
||||||
|
return ` hot-corners {\n off\n }\n`;
|
||||||
|
const corners = hc.corners || [];
|
||||||
|
if (corners.length === 0)
|
||||||
|
return "";
|
||||||
|
let block = ` hot-corners {\n`;
|
||||||
|
for (const corner of corners) {
|
||||||
|
block += ` ${corner}\n`;
|
||||||
|
}
|
||||||
|
block += ` }\n`;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateLayoutBlock(niriSettings) {
|
||||||
|
if (!niriSettings.layout)
|
||||||
|
return "";
|
||||||
|
const layout = niriSettings.layout;
|
||||||
|
const hasSettings = layout.gaps !== undefined || layout.defaultColumnWidth || layout.presetColumnWidths || layout.alwaysCenterSingleColumn !== undefined;
|
||||||
|
if (!hasSettings)
|
||||||
|
return "";
|
||||||
|
let block = ` layout {\n`;
|
||||||
|
if (layout.gaps !== undefined)
|
||||||
|
block += ` gaps ${layout.gaps}\n`;
|
||||||
|
if (layout.defaultColumnWidth?.type === "proportion")
|
||||||
|
block += ` default-column-width { proportion ${layout.defaultColumnWidth.value}; }\n`;
|
||||||
|
if (layout.presetColumnWidths && layout.presetColumnWidths.length > 0) {
|
||||||
|
block += ` preset-column-widths {\n`;
|
||||||
|
for (const preset of layout.presetColumnWidths) {
|
||||||
|
if (preset.type === "proportion")
|
||||||
|
block += ` proportion ${preset.value}\n`;
|
||||||
|
}
|
||||||
|
block += ` }\n`;
|
||||||
|
}
|
||||||
|
if (layout.alwaysCenterSingleColumn !== undefined)
|
||||||
|
block += layout.alwaysCenterSingleColumn ? ` always-center-single-column\n` : ` always-center-single-column false\n`;
|
||||||
|
block += ` }\n`;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function screenshot(): string {
|
function screenshot(): string {
|
||||||
if (!CompositorService.isNiri) {
|
if (!CompositorService.isNiri) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Rectangle {
|
|||||||
property int buttonHeight: 40
|
property int buttonHeight: 40
|
||||||
property int horizontalPadding: Theme.spacingL
|
property int horizontalPadding: Theme.spacingL
|
||||||
|
|
||||||
signal clicked()
|
signal clicked
|
||||||
|
|
||||||
width: Math.max(contentRow.implicitWidth + horizontalPadding * 2, 64)
|
width: Math.max(contentRow.implicitWidth + horizontalPadding * 2, 64)
|
||||||
height: buttonHeight
|
height: buttonHeight
|
||||||
@@ -29,9 +29,11 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
color: {
|
color: {
|
||||||
if (pressed) return Theme.primaryPressed
|
if (pressed)
|
||||||
if (hovered) return Theme.primaryHover
|
return Theme.primaryPressed;
|
||||||
return "transparent"
|
if (hovered)
|
||||||
|
return Theme.primaryHover;
|
||||||
|
return "transparent";
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ Flow {
|
|||||||
property int buttonPadding: Theme.spacingL
|
property int buttonPadding: Theme.spacingL
|
||||||
property int checkIconSize: Theme.iconSizeSmall
|
property int checkIconSize: Theme.iconSizeSmall
|
||||||
property int textSize: Theme.fontSizeMedium
|
property int textSize: Theme.fontSizeMedium
|
||||||
|
property bool userInteracted: false
|
||||||
|
|
||||||
signal selectionChanged(int index, bool selected)
|
signal selectionChanged(int index, bool selected)
|
||||||
signal animationCompleted()
|
signal animationCompleted()
|
||||||
@@ -27,7 +28,10 @@ Flow {
|
|||||||
Timer {
|
Timer {
|
||||||
id: animationTimer
|
id: animationTimer
|
||||||
interval: Theme.shortDuration
|
interval: Theme.shortDuration
|
||||||
onTriggered: root.animationCompleted()
|
onTriggered: {
|
||||||
|
root.userInteracted = false;
|
||||||
|
root.animationCompleted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSelected(index) {
|
function isSelected(index) {
|
||||||
@@ -38,6 +42,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selectItem(index) {
|
function selectItem(index) {
|
||||||
|
userInteracted = true;
|
||||||
if (multiSelect) {
|
if (multiSelect) {
|
||||||
const modelValue = model[index]
|
const modelValue = model[index]
|
||||||
let newSelection = [...currentSelection]
|
let newSelection = [...currentSelection]
|
||||||
@@ -93,6 +98,7 @@ Flow {
|
|||||||
bottomRightRadius: (isLast || selected) ? Theme.cornerRadius : 4
|
bottomRightRadius: (isLast || selected) ? Theme.cornerRadius : 4
|
||||||
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -100,6 +106,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on topLeftRadius {
|
Behavior on topLeftRadius {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -107,6 +114,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on topRightRadius {
|
Behavior on topRightRadius {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -114,6 +122,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on bottomLeftRadius {
|
Behavior on bottomLeftRadius {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -121,6 +130,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on bottomRightRadius {
|
Behavior on bottomRightRadius {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -128,6 +138,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
|
enabled: root.userInteracted
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -176,6 +187,7 @@ Flow {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
@@ -183,6 +195,7 @@ Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
|
enabled: root.userInteracted
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.emphasizedEasing
|
easing.type: Theme.emphasizedEasing
|
||||||
|
|||||||
Reference in New Issue
Block a user