1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-02 18:42:06 -04:00

Compare commits

...

18 Commits

Author SHA1 Message Date
bbedward
4eb896629d net: fix VPN prompting for password 2025-11-21 12:59:12 -05:00
bbedward
b310e66275 themes: shift catpuccin palete 2025-11-21 09:30:58 -05:00
bbedward
b39da1bea7 cc: bit of extra height for some detail items 2025-11-21 09:15:59 -05:00
Pi Home Server
fa575d0574 Fix background color of the privacy widget (#779) 2025-11-21 09:05:56 -05:00
bbedward
dfe2f3771b theme: add colorful bar widget option 2025-11-21 00:07:23 -05:00
bbedward
46caeb0445 sounds: only play audio changed when trigger by us 2025-11-20 23:38:06 -05:00
bbedward
59cc9c7006 niri: ensure overview spotlight is hidden when main window is brought up 2025-11-20 21:23:56 -05:00
bbedward
12e91534eb niri: empty input region & disable spotlight content when not open 2025-11-20 16:44:46 -05:00
bbedward
d9da88ceb5 niri: embed spotlight to same window as overview layer 2025-11-20 16:28:26 -05:00
bbedward
2dbfec0307 niri: close spotlight when closing overview 2025-11-20 13:56:35 -05:00
Lucas
09cf8c9641 niri: add spotlight on overview typing functionality (#774) 2025-11-20 13:48:30 -05:00
Pi Home Server
f1bed4d6a3 Feature/privacy widget fix (#772)
* Fix active camera icon

* Fix active camera icon
2025-11-20 12:30:23 -05:00
bbedward
2ed6c33c83 missing import 2025-11-19 19:14:47 -05:00
bbedward
7ad532ed17 dankinstall: add ultramarine 2025-11-19 18:53:41 -05:00
bbedward
92fe8c5b14 hyprland: restore focus grab to tray menus 2025-11-19 17:24:14 -05:00
bbedward
8e95572589 modals: move HyprFocusGrab out of common Modal 2025-11-19 17:16:51 -05:00
bbedward
62da862a66 modal: round textureSize pixels 2025-11-19 14:36:08 -05:00
bbedward
993e34f548 dankinstall: weakdeps for niri/system 2025-11-19 09:35:22 -05:00
63 changed files with 847 additions and 232 deletions

View File

@@ -19,10 +19,12 @@ func init() {
Register("fedora-asahi-remix", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan)
})
Register("bluefin", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan)
})
Register("ultramarine", "#00078b", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan)
})
}
type FedoraDistribution struct {
@@ -506,6 +508,14 @@ func (f *FedoraDistribution) installDNFPackages(ctx context.Context, packages []
f.log(fmt.Sprintf("Installing DNF packages: %s", strings.Join(packages, ", ")))
args := []string{"dnf", "install", "-y"}
for _, pkg := range packages {
if pkg == "niri" || pkg == "niri-git" {
args = append(args, "--setopt=install_weak_deps=False")
break
}
}
args = append(args, packages...)
progressChan <- InstallProgressMsg{

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"time"
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
@@ -125,8 +126,9 @@ func (a *SecretAgent) GetSecrets(
connType, displayName, vpnSvc := readConnTypeAndName(conn)
ssid := readSSID(conn)
fields := fieldsNeeded(settingName, hints)
vpnPasswordFlags := readVPNPasswordFlags(conn, settingName)
log.Infof("[SecretAgent] connType=%s, name=%s, vpnSvc=%s, fields=%v, flags=%d", connType, displayName, vpnSvc, fields, flags)
log.Infof("[SecretAgent] connType=%s, name=%s, vpnSvc=%s, fields=%v, flags=%d, vpnPasswordFlags=%d", connType, displayName, vpnSvc, fields, flags, vpnPasswordFlags)
if a.backend != nil {
a.backend.stateMutex.RLock()
@@ -163,57 +165,70 @@ func (a *SecretAgent) GetSecrets(
}
if len(fields) == 0 {
// For VPN connections with no hints, we can't provide a proper UI.
// Defer to other agents (like nm-applet or VPN-specific auth dialogs)
// that can handle the VPN type properly (e.g., OpenConnect with SAML, etc.)
if settingName == "vpn" {
log.Infof("[SecretAgent] VPN with empty hints - deferring to other agents for %s", vpnSvc)
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
}
if a.backend != nil {
a.backend.stateMutex.RLock()
isConnectingVPN := a.backend.state.IsConnectingVPN
a.backend.stateMutex.RUnlock()
const (
NM_SETTING_SECRET_FLAG_NONE = 0
NM_SETTING_SECRET_FLAG_AGENT_OWNED = 1
NM_SETTING_SECRET_FLAG_NOT_SAVED = 2
NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 4
)
if !isConnectingVPN {
log.Infof("[SecretAgent] VPN with empty hints - deferring to other agents for %s", vpnSvc)
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
}
var passwordFlags uint32 = 0xFFFF
switch settingName {
case "802-11-wireless-security":
if wifiSecSettings, ok := conn["802-11-wireless-security"]; ok {
if flagsVariant, ok := wifiSecSettings["psk-flags"]; ok {
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
passwordFlags = pwdFlags
}
}
}
case "802-1x":
if dot1xSettings, ok := conn["802-1x"]; ok {
if flagsVariant, ok := dot1xSettings["password-flags"]; ok {
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
passwordFlags = pwdFlags
}
}
log.Infof("[SecretAgent] VPN with empty hints but we're connecting - prompting for password")
fields = []string{"password"}
} else {
log.Infof("[SecretAgent] VPN with empty hints - deferring to other agents for %s", vpnSvc)
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
}
}
if passwordFlags == 0xFFFF {
log.Warnf("[SecretAgent] Could not determine password-flags for empty hints - returning NoSecrets error")
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
} else if passwordFlags&NM_SETTING_SECRET_FLAG_NOT_REQUIRED != 0 {
log.Infof("[SecretAgent] Secrets not required (flags=%d)", passwordFlags)
out := nmSettingMap{}
out[settingName] = nmVariantMap{}
return out, nil
} else if passwordFlags&NM_SETTING_SECRET_FLAG_AGENT_OWNED != 0 {
log.Warnf("[SecretAgent] Secrets are agent-owned but we don't store secrets (flags=%d) - returning NoSecrets error", passwordFlags)
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
} else {
log.Infof("[SecretAgent] No secrets needed, using system stored secrets (flags=%d)", passwordFlags)
out := nmSettingMap{}
out[settingName] = nmVariantMap{}
return out, nil
if len(fields) == 0 {
const (
NM_SETTING_SECRET_FLAG_NONE = 0
NM_SETTING_SECRET_FLAG_AGENT_OWNED = 1
NM_SETTING_SECRET_FLAG_NOT_SAVED = 2
NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 4
)
var passwordFlags uint32 = 0xFFFF
switch settingName {
case "802-11-wireless-security":
if wifiSecSettings, ok := conn["802-11-wireless-security"]; ok {
if flagsVariant, ok := wifiSecSettings["psk-flags"]; ok {
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
passwordFlags = pwdFlags
}
}
}
case "802-1x":
if dot1xSettings, ok := conn["802-1x"]; ok {
if flagsVariant, ok := dot1xSettings["password-flags"]; ok {
if pwdFlags, ok := flagsVariant.Value().(uint32); ok {
passwordFlags = pwdFlags
}
}
}
}
if passwordFlags == 0xFFFF {
log.Warnf("[SecretAgent] Could not determine password-flags for empty hints - returning NoSecrets error")
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
} else if passwordFlags&NM_SETTING_SECRET_FLAG_NOT_REQUIRED != 0 {
log.Infof("[SecretAgent] Secrets not required (flags=%d)", passwordFlags)
out := nmSettingMap{}
out[settingName] = nmVariantMap{}
return out, nil
} else if passwordFlags&NM_SETTING_SECRET_FLAG_AGENT_OWNED != 0 {
log.Warnf("[SecretAgent] Secrets are agent-owned but we don't store secrets (flags=%d) - returning NoSecrets error", passwordFlags)
return nil, dbus.NewError("org.freedesktop.NetworkManager.SecretAgent.Error.NoSecrets", nil)
} else {
log.Infof("[SecretAgent] No secrets needed, using system stored secrets (flags=%d)", passwordFlags)
out := nmSettingMap{}
out[settingName] = nmVariantMap{}
return out, nil
}
}
}
@@ -343,13 +358,11 @@ func (a *SecretAgent) GetSecrets(
// Update settings based on type
switch settingName {
case "vpn":
// Set password-flags=0 and add secrets to vpn section
vpn, ok := existingSettings["vpn"]
if !ok {
vpn = make(map[string]dbus.Variant)
}
// Get existing data map (vpn.data is string->string)
var data map[string]string
if dataVariant, ok := vpn["data"]; ok {
if dm, ok := dataVariant.Value().(map[string]string); ok {
@@ -364,11 +377,9 @@ func (a *SecretAgent) GetSecrets(
data = make(map[string]string)
}
// Update password-flags to 0 (system-stored)
data["password-flags"] = "0"
vpn["data"] = dbus.MakeVariant(data)
// Add secrets (vpn.secrets is string->string)
secs := make(map[string]string)
for k, v := range reply.Secrets {
secs[k] = v
@@ -379,14 +390,12 @@ func (a *SecretAgent) GetSecrets(
log.Infof("[SecretAgent] Updated VPN settings: password-flags=0, secrets with %d fields", len(secs))
case "802-11-wireless-security":
// Set psk-flags=0 for WiFi
wifiSec, ok := existingSettings["802-11-wireless-security"]
if !ok {
wifiSec = make(map[string]dbus.Variant)
}
wifiSec["psk-flags"] = dbus.MakeVariant(uint32(0))
// Add PSK secret
if psk, ok := reply.Secrets["psk"]; ok {
wifiSec["psk"] = dbus.MakeVariant(psk)
log.Infof("[SecretAgent] Updated WiFi settings: psk-flags=0")
@@ -394,14 +403,12 @@ func (a *SecretAgent) GetSecrets(
settings["802-11-wireless-security"] = wifiSec
case "802-1x":
// Set password-flags=0 for 802.1x
dot1x, ok := existingSettings["802-1x"]
if !ok {
dot1x = make(map[string]dbus.Variant)
}
dot1x["password-flags"] = dbus.MakeVariant(uint32(0))
// Add password secret
if password, ok := reply.Secrets["password"]; ok {
dot1x["password"] = dbus.MakeVariant(password)
log.Infof("[SecretAgent] Updated 802.1x settings: password-flags=0")
@@ -507,6 +514,39 @@ func fieldsNeeded(setting string, hints []string) []string {
}
}
func readVPNPasswordFlags(conn map[string]nmVariantMap, settingName string) uint32 {
if settingName != "vpn" {
return 0xFFFF
}
vpnSettings, ok := conn["vpn"]
if !ok {
return 0xFFFF
}
dataVariant, ok := vpnSettings["data"]
if !ok {
return 0xFFFF
}
dataMap, ok := dataVariant.Value().(map[string]string)
if !ok {
return 0xFFFF
}
flagsStr, ok := dataMap["password-flags"]
if !ok {
return 0xFFFF
}
flags64, err := strconv.ParseUint(flagsStr, 10, 32)
if err != nil {
return 0xFFFF
}
return uint32(flags64)
}
func reasonFromFlags(flags uint32) string {
const (
NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0

View File

@@ -235,7 +235,7 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
}
nm := b.nmConn.(gonetworkmanager.NetworkManager)
activeConn, err := nm.ActivateConnection(targetConn, nil, nil)
_, err = nm.ActivateConnection(targetConn, nil, nil)
if err != nil {
b.stateMutex.Lock()
b.state.IsConnectingVPN = false
@@ -249,20 +249,6 @@ func (b *NetworkManagerBackend) ConnectVPN(uuidOrName string, singleActive bool)
return fmt.Errorf("failed to activate VPN: %w", err)
}
if activeConn != nil {
state, _ := activeConn.GetPropertyState()
if state == 2 {
b.stateMutex.Lock()
b.state.IsConnectingVPN = false
b.state.ConnectingVPNUUID = ""
b.stateMutex.Unlock()
b.ListActiveVPN()
if b.onStateChange != nil {
b.onStateChange()
}
}
}
return nil
}

View File

@@ -44,6 +44,11 @@ Singleton {
SuspendThenHibernate
}
enum WidgetColorMode {
Default,
Colorful
}
readonly property string defaultFontFamily: "Inter Variable"
readonly property string defaultMonoFontFamily: "Fira Code"
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
@@ -70,6 +75,7 @@ Singleton {
property real popupTransparency: 1.0
property real dockTransparency: 1
property string widgetBackgroundColor: "sch"
property string widgetColorMode: "default"
property real cornerRadius: 12
property bool use24HourClock: true
@@ -171,6 +177,7 @@ Singleton {
property string spotlightModalViewMode: "list"
property bool sortAppsAlphabetically: false
property int appLauncherGridColumns: 4
property bool spotlightCloseNiriOverview: true
property string weatherLocation: "New York, NY"
property string weatherCoordinates: "40.7128,-74.0060"

View File

@@ -2,16 +2,16 @@
// Separated from Theme.qml to keep that file clean
const CatppuccinMocha = {
surface: "#313244",
surface: "#181825",
surfaceText: "#cdd6f4",
surfaceVariant: "#313244",
surfaceVariant: "#1e1e2e",
surfaceVariantText: "#a6adc8",
background: "#1e1e2e",
background: "#181825",
backgroundText: "#cdd6f4",
outline: "#6c7086",
surfaceContainer: "#45475a",
surfaceContainerHigh: "#585b70",
surfaceContainerHighest: "#6c7086"
surfaceContainer: "#1e1e2e",
surfaceContainerHigh: "#313244",
surfaceContainerHighest: "#45475a"
}
const CatppuccinLatte = {

View File

@@ -665,6 +665,34 @@ Singleton {
}
}
property color widgetIconColor: {
if (typeof SettingsData === "undefined") {
return surfaceText
}
switch (SettingsData.widgetColorMode) {
case "colorful":
return surfaceText
case "default":
default:
return surfaceText
}
}
property color widgetTextColor: {
if (typeof SettingsData === "undefined") {
return surfaceText
}
switch (SettingsData.widgetColorMode) {
case "colorful":
return primary
case "default":
default:
return surfaceText
}
}
function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5

View File

@@ -18,6 +18,7 @@ var SPEC = {
dockTransparency: { def: 1.0, coerce: percentToUnit },
widgetBackgroundColor: { def: "sch" },
widgetColorMode: { def: "default" },
cornerRadius: { def: 12, onChange: "updateNiriLayout" },
use24HourClock: { def: true },
@@ -97,6 +98,7 @@ var SPEC = {
spotlightModalViewMode: { def: "list" },
sortAppsAlphabetically: { def: false },
appLauncherGridColumns: { def: 4 },
spotlightCloseNiriOverview: { def: true },
weatherLocation: { def: "New York, NY" },
weatherCoordinates: { def: "40.7128,-74.0060" },

View File

@@ -22,7 +22,7 @@ import qs.Modules.ProcessList
import qs.Modules.Settings
import qs.Modules.DankBar
import qs.Modules.DankBar.Popouts
import qs.Modules.HyprWorkspaces
import qs.Modules.WorkspaceOverlays
import qs.Modules.Plugins
import qs.Services
@@ -581,4 +581,12 @@ Item {
id: hyprlandOverview
}
}
LazyLoader {
id: niriOverviewOverlayLoader
active: CompositorService.isNiri
component: NiriOverviewOverlay {
id: niriOverviewOverlay
}
}
}

View File

@@ -1,4 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -9,6 +11,11 @@ DankModal {
layerNamespace: "dms:bluetooth-pairing"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string deviceName: ""
property string deviceAddress: ""
property string requestType: ""

View File

@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -14,6 +15,11 @@ DankModal {
layerNamespace: "dms:clipboard"
HyprlandFocusGrab {
windows: [clipboardHistoryModal]
active: CompositorService.isHyprland && clipboardHistoryModal.shouldHaveFocus
}
property int totalCount: 0
property var clipboardEntries: []
property string searchText: ""

View File

@@ -95,11 +95,6 @@ PanelWindow {
return WlrKeyboardFocus.Exclusive
}
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && shouldHaveFocus
}
onVisibleChanged: {
if (root.visible) {
opened()
@@ -245,7 +240,7 @@ PanelWindow {
clip: false
layer.enabled: true
layer.smooth: false
layer.textureSize: Qt.size(width * root.dpr, height * root.dpr)
layer.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
opacity: root.shouldBeVisible ? 1 : 0
scale: modalContainer.scaleValue
x: Theme.snap(modalContainer.animX + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5, root.dpr)

View File

@@ -1,6 +1,7 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -12,6 +13,11 @@ DankModal {
layerNamespace: "dms:color-picker"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string pickerTitle: "Choose Color"
property color selectedColor: SessionData.recentColors.length > 0 ? SessionData.recentColors[0] : Theme.primary
property var onColorSelectedCallback: null

View File

@@ -2,10 +2,13 @@ import Qt.labs.folderlistmodel
import QtCore
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
import qs.Modals.FileBrowser
import qs.Services
import qs.Widgets
DankModal {
@@ -13,6 +16,11 @@ DankModal {
layerNamespace: "dms:file-browser"
HyprlandFocusGrab {
windows: [fileBrowserModal]
active: CompositorService.isHyprland && fileBrowserModal.shouldHaveFocus
}
keepPopoutsOpen: true
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)

View File

@@ -1,4 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -11,6 +13,11 @@ DankModal {
layerNamespace: "dms:notification-center-modal"
HyprlandFocusGrab {
windows: [notificationModal]
active: CompositorService.isHyprland && notificationModal.shouldHaveFocus
}
property bool notificationModalOpen: false
property var notificationListRef: null

View File

@@ -1,4 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -9,6 +11,11 @@ DankModal {
layerNamespace: "dms:polkit"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string passwordInput: ""
property var currentFlow: PolkitService.agent?.flow
property bool isLoading: false

View File

@@ -1,5 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -10,6 +11,11 @@ DankModal {
layerNamespace: "dms:power-menu"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property int selectedIndex: 0
property int selectedRow: 0
property int selectedCol: 0

View File

@@ -22,7 +22,7 @@ Item {
width: parent.width
height: lockScreenSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
@@ -106,7 +106,7 @@ Item {
width: parent.width
height: timeoutSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
@@ -329,7 +329,7 @@ Item {
width: parent.width
height: powerMenuCustomSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
@@ -516,7 +516,7 @@ Item {
width: parent.width
height: powerCommandConfirmSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
@@ -560,7 +560,7 @@ Item {
width: parent.width
height: powerCommandCustomization.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0

View File

@@ -1,5 +1,7 @@
import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
@@ -13,6 +15,11 @@ DankModal {
layerNamespace: "dms:settings"
HyprlandFocusGrab {
windows: [settingsModal]
active: CompositorService.isHyprland && settingsModal.shouldHaveFocus
}
property Component settingsContent
property alias profileBrowser: profileBrowser
property int currentTabIndex: 0

View File

@@ -158,6 +158,10 @@ Item {
onAppLaunched: () => {
if (parentModal)
parentModal.hide()
if (SettingsData.spotlightCloseNiriOverview && NiriService.inOverview) {
NiriService.toggleOverview()
}
}
onViewModeSelected: mode => {
SettingsData.set("spotlightModalViewMode", mode)
@@ -170,6 +174,10 @@ Item {
onFileOpened: () => {
if (parentModal)
parentModal.hide()
if (SettingsData.spotlightCloseNiriOverview && NiriService.inOverview) {
NiriService.toggleOverview()
}
}
}

View File

@@ -1,6 +1,7 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import Quickshell.Widgets
import qs.Common
@@ -14,10 +15,17 @@ DankModal {
layerNamespace: "dms:spotlight"
HyprlandFocusGrab {
windows: [spotlightModal]
active: CompositorService.isHyprland && spotlightModal.shouldHaveFocus
}
property bool spotlightOpen: false
property alias spotlightContent: spotlightContentInstance
property bool openedFromOverview: false
function show() {
openedFromOverview = false
spotlightOpen = true
open()
@@ -49,6 +57,7 @@ DankModal {
}
function hide() {
openedFromOverview = false
spotlightOpen = false
close()
}

View File

@@ -1,4 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -8,6 +10,12 @@ DankModal {
id: root
layerNamespace: "dms:wifi-password"
keepPopoutsOpen: true
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string wifiPasswordSSID: ""
property string wifiPasswordInput: ""
@@ -101,7 +109,11 @@ DankModal {
shouldBeVisible: false
width: 420
height: requiresEnterprise ? 430 : 230
height: {
if (requiresEnterprise) return 430
if (isVpnPrompt) return 260
return 230
}
onShouldBeVisibleChanged: () => {
if (!shouldBeVisible) {
wifiPasswordInput = ""
@@ -314,7 +326,7 @@ DankModal {
if (passwordInput.text) secrets["password"] = passwordInput.text
if (wifiAnonymousIdentityInput) secrets["anonymous-identity"] = wifiAnonymousIdentityInput
}
NetworkService.submitCredentials(promptToken, secrets, true)
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked)
} else {
const username = requiresEnterprise ? usernameInput.text : ""
NetworkService.connectToWifi(
@@ -429,44 +441,91 @@ DankModal {
}
}
Row {
Column {
spacing: Theme.spacingS
width: parent.width
Rectangle {
id: showPasswordCheckbox
Row {
spacing: Theme.spacingS
property bool checked: false
Rectangle {
id: showPasswordCheckbox
width: 20
height: 20
radius: 4
color: checked ? Theme.primary : "transparent"
border.color: checked ? Theme.primary : Theme.outlineButton
border.width: 2
property bool checked: false
DankIcon {
anchors.centerIn: parent
name: "check"
size: 12
color: Theme.background
visible: parent.checked
width: 20
height: 20
radius: 4
color: checked ? Theme.primary : "transparent"
border.color: checked ? Theme.primary : Theme.outlineButton
border.width: 2
DankIcon {
anchors.centerIn: parent
name: "check"
size: 12
color: Theme.background
visible: parent.checked
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
}
StyledText {
text: I18n.tr("Show password")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: I18n.tr("Show password")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
Row {
spacing: Theme.spacingS
visible: isVpnPrompt
Rectangle {
id: savePasswordCheckbox
property bool checked: false
width: 20
height: 20
radius: 4
color: checked ? Theme.primary : "transparent"
border.color: checked ? Theme.primary : Theme.outlineButton
border.width: 2
DankIcon {
anchors.centerIn: parent
name: "check"
size: 12
color: Theme.background
visible: parent.checked
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
savePasswordCheckbox.checked = !savePasswordCheckbox.checked
}
}
}
StyledText {
text: I18n.tr("Save password")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}
@@ -558,7 +617,7 @@ DankModal {
if (passwordInput.text) secrets["password"] = passwordInput.text
if (wifiAnonymousIdentityInput) secrets["anonymous-identity"] = wifiAnonymousIdentityInput
}
NetworkService.submitCredentials(promptToken, secrets, true)
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked)
} else {
const username = requiresEnterprise ? usernameInput.text : ""
NetworkService.connectToWifi(

View File

@@ -16,10 +16,18 @@ Item {
property var widgetModel: null
property var collapseCallback: null
function getDetailHeight(section) {
const maxAvailable = parent ? parent.height - Theme.spacingS : 9999
if (section === "wifi") return Math.min(350, maxAvailable)
if (section === "bluetooth") return Math.min(350, maxAvailable)
if (section.startsWith("brightnessSlider_")) return Math.min(400, maxAvailable)
return Math.min(250, maxAvailable)
}
Loader {
id: pluginDetailLoader
width: parent.width
height: 250
height: parent.height - Theme.spacingS
y: Theme.spacingS
active: false
sourceComponent: null
@@ -28,7 +36,7 @@ Item {
Loader {
id: coreDetailLoader
width: parent.width
height: 250
height: parent.height - Theme.spacingS
y: Theme.spacingS
active: false
sourceComponent: null

View File

@@ -160,8 +160,9 @@ Column {
}
DetailHost {
id: detailHost
width: parent.width
height: active ? (250 + Theme.spacingS) : 0
height: active ? (getDetailHeight(root.expandedSection) + Theme.spacingS) : 0
property bool active: {
if (root.expandedSection === "")
return false

View File

@@ -64,7 +64,12 @@ DankPopout {
}
popupWidth: 550
popupHeight: Math.min((triggerScreen?.height ?? 1080) - 100, contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400)
popupHeight: {
const screenHeight = (triggerScreen?.height ?? 1080)
const maxHeight = screenHeight - 100
const contentHeight = contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400
return Math.min(maxHeight, contentHeight)
}
triggerX: (triggerScreen?.width ?? 1920) - 600 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.dankBarSpacing
triggerWidth: 80
@@ -72,9 +77,12 @@ DankPopout {
screen: triggerScreen
shouldBeVisible: false
property bool credentialsPromptOpen: NetworkService.credentialsRequested
WlrLayershell.keyboardFocus: {
if (!shouldBeVisible) return WlrKeyboardFocus.None
if (powerMenuOpen) return WlrKeyboardFocus.None
if (credentialsPromptOpen) return WlrKeyboardFocus.None
if (CompositorService.isHyprland) return WlrKeyboardFocus.OnDemand
return WlrKeyboardFocus.Exclusive
}

View File

@@ -180,7 +180,11 @@ Rectangle {
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
width: {
const iconWidth = Theme.iconSize
const pinButtonWidth = pinInputRow.width + Theme.spacingS * 4 + Theme.spacingM
return parent.parent.width - iconWidth - parent.spacing - pinButtonWidth - Theme.spacingM * 2
}
StyledText {
text: AudioService.displayName(modelData)

View File

@@ -187,7 +187,11 @@ Rectangle {
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
width: {
const iconWidth = Theme.iconSize
const pinButtonWidth = pinOutputRow.width + Theme.spacingS * 4 + Theme.spacingM
return parent.parent.width - iconWidth - parent.spacing - pinButtonWidth - Theme.spacingM * 2
}
StyledText {
text: AudioService.displayName(modelData)

View File

@@ -10,7 +10,12 @@ import qs.Modals
Rectangle {
id: root
implicitHeight: BluetoothService.adapter && BluetoothService.adapter.enabled ? headerRow.height + bluetoothContent.height + Theme.spacingM : headerRow.height
implicitHeight: {
if (height > 0) {
return height
}
return BluetoothService.adapter && BluetoothService.adapter.enabled ? headerRow.height + bluetoothContent.height + Theme.spacingM : headerRow.height
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)

View File

@@ -88,7 +88,12 @@ Rectangle {
SettingsData.set("brightnessDevicePins", pins)
}
implicitHeight: brightnessContent.height + Theme.spacingM
implicitHeight: {
if (height > 0) {
return height
}
return brightnessContent.height + Theme.spacingM
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)

View File

@@ -10,6 +10,9 @@ Rectangle {
id: root
implicitHeight: {
if (height > 0) {
return height
}
if (NetworkService.wifiToggling) {
return headerRow.height + wifiToggleContent.height + Theme.spacingM
}

View File

@@ -84,6 +84,7 @@ Row {
if (newValue > 0 && defaultSink.audio.muted) {
defaultSink.audio.muted = false
}
AudioService.playVolumeChangeSoundIfEnabled()
}
}
}

View File

@@ -31,7 +31,7 @@ BasePill {
size: Theme.barIconSize(battery.barThickness)
color: {
if (!BatteryService.batteryAvailable) {
return Theme.surfaceText
return Theme.widgetIconColor
}
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
@@ -42,7 +42,7 @@ BasePill {
return Theme.primary
}
return Theme.surfaceText
return Theme.widgetIconColor
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -50,7 +50,7 @@ BasePill {
StyledText {
text: BatteryService.batteryLevel.toString()
font.pixelSize: Theme.barTextSize(battery.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
visible: BatteryService.batteryAvailable
}
@@ -67,7 +67,7 @@ BasePill {
size: Theme.barIconSize(battery.barThickness, -4)
color: {
if (!BatteryService.batteryAvailable) {
return Theme.surfaceText;
return Theme.widgetIconColor;
}
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
@@ -78,7 +78,7 @@ BasePill {
return Theme.primary;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -86,7 +86,7 @@ BasePill {
StyledText {
text: `${BatteryService.batteryLevel}%`
font.pixelSize: Theme.barTextSize(battery.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable
}

View File

@@ -18,7 +18,7 @@ BasePill {
anchors.centerIn: parent
name: "content_paste"
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetIconColor
}
}
}

View File

@@ -36,7 +36,7 @@ BasePill {
}
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -52,7 +52,7 @@ BasePill {
}
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -65,7 +65,7 @@ BasePill {
StyledText {
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(0)
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -73,7 +73,7 @@ BasePill {
StyledText {
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -87,7 +87,7 @@ BasePill {
StyledText {
text: String(systemClock?.date?.getSeconds()).padStart(2, '0').charAt(0)
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -95,7 +95,7 @@ BasePill {
StyledText {
text: String(systemClock?.date?.getSeconds()).padStart(2, '0').charAt(1)
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
}
@@ -193,7 +193,7 @@ BasePill {
return systemClock?.date?.toLocaleTimeString(Qt.locale(), SettingsData.getEffectiveTimeFormat())
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.baseline: dateText.baseline
}
@@ -215,7 +215,7 @@ BasePill {
return systemClock?.date?.toLocaleDateString(Qt.locale(), "ddd d")
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}

View File

@@ -85,7 +85,7 @@ BasePill {
return "volume_up"
}
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetIconColor
anchors.centerIn: parent
}
@@ -104,6 +104,7 @@ BasePill {
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newVolume / 100
AudioService.playVolumeChangeSoundIfEnabled()
}
wheelEvent.accepted = true
}
@@ -113,7 +114,7 @@ BasePill {
DankIcon {
name: "settings"
size: Theme.barIconSize(root.barThickness)
color: root.isActive ? Theme.primary : Theme.surfaceText
color: root.isActive ? Theme.primary : Theme.widgetIconColor
anchors.horizontalCenter: parent.horizontalCenter
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
}
@@ -189,7 +190,7 @@ BasePill {
return "volume_up";
}
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetIconColor
anchors.centerIn: parent
}
@@ -210,6 +211,7 @@ BasePill {
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false;
AudioService.sink.audio.volume = newVolume / 100;
AudioService.playVolumeChangeSoundIfEnabled();
}
wheelEvent.accepted = true;
}
@@ -227,7 +229,7 @@ BasePill {
DankIcon {
name: "settings"
size: Theme.barIconSize(root.barThickness)
color: root.isActive ? Theme.primary : Theme.surfaceText
color: root.isActive ? Theme.primary : Theme.widgetIconColor
anchors.verticalCenter: parent.verticalCenter
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
}

View File

@@ -45,7 +45,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -59,7 +59,7 @@ BasePill {
return DgopService.cpuUsage.toFixed(0);
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -82,7 +82,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -96,7 +96,7 @@ BasePill {
return DgopService.cpuUsage.toFixed(0) + "%";
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -45,7 +45,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -59,7 +59,7 @@ BasePill {
return Math.round(DgopService.cpuTemperature).toString();
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -82,7 +82,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -96,7 +96,7 @@ BasePill {
return Math.round(DgopService.cpuTemperature) + "°";
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -58,14 +58,14 @@ BasePill {
DankIcon {
name: layout.getLayoutIcon(layout.currentLayoutSymbol)
size: Theme.barIconSize(layout.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: layout.currentLayoutSymbol
font.pixelSize: Theme.barTextSize(layout.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -79,14 +79,14 @@ BasePill {
DankIcon {
name: layout.getLayoutIcon(layout.currentLayoutSymbol)
size: Theme.barIconSize(layout.barThickness, -4)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: layout.currentLayoutSymbol
font.pixelSize: Theme.barTextSize(layout.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
}

View File

@@ -115,7 +115,7 @@ BasePill {
return root.diskUsagePercent.toFixed(0)
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -149,7 +149,7 @@ BasePill {
return root.selectedMount.mount
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone
@@ -163,7 +163,7 @@ BasePill {
return root.diskUsagePercent.toFixed(0) + "%"
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -124,7 +124,7 @@ BasePill {
anchors.centerIn: parent
size: 18
name: "sports_esports"
color: Theme.surfaceText
color: Theme.widgetTextColor
visible: {
if (!root.isVerticalOrientation || !activeWindow || !activeWindow.appId) return false
const moddedId = Paths.moddedAppId(activeWindow.appId)
@@ -148,7 +148,7 @@ BasePill {
return activeWindow.appId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
Row {
@@ -168,7 +168,7 @@ BasePill {
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
@@ -204,7 +204,7 @@ BasePill {
return title;
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1

View File

@@ -109,7 +109,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -123,7 +123,7 @@ BasePill {
return Math.round(root.displayTemp).toString();
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -146,7 +146,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -160,7 +160,7 @@ BasePill {
return Math.round(root.displayTemp) + "°";
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -18,7 +18,7 @@ BasePill {
anchors.centerIn: parent
name: SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
size: Theme.barIconSize(root.barThickness, -4)
color: Theme.surfaceText
color: Theme.widgetTextColor
}
}
}

View File

@@ -37,7 +37,7 @@ BasePill {
DankIcon {
name: "keyboard"
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -51,7 +51,7 @@ BasePill {
return root.currentLayout.substring(0, 2).toUpperCase()
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -65,7 +65,7 @@ BasePill {
StyledText {
text: root.currentLayout
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
}

View File

@@ -23,7 +23,7 @@ BasePill {
anchors.centerIn: parent
name: "apps"
size: Theme.barIconSize(root.barThickness, -4)
color: Theme.surfaceText
color: Theme.widgetIconColor
}
SystemLogo {

View File

@@ -175,7 +175,7 @@ BasePill {
anchors.verticalCenter: parent.verticalCenter
text: textContainer.displayText
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
wrapMode: Text.NoWrap
x: needsScrolling ? -scrollOffset : 0
onTextChanged: {
@@ -249,7 +249,7 @@ BasePill {
anchors.centerIn: parent
name: "skip_previous"
size: 12
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {
@@ -306,7 +306,7 @@ BasePill {
anchors.centerIn: parent
name: "skip_next"
size: 12
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {

View File

@@ -42,7 +42,7 @@ BasePill {
DankIcon {
name: "network_check"
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -80,7 +80,7 @@ BasePill {
DankIcon {
name: "network_check"
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -97,7 +97,7 @@ BasePill {
StyledText {
text: DgopService.networkRxRate > 0 ? root.formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone
@@ -133,7 +133,7 @@ BasePill {
StyledText {
text: DgopService.networkTxRate > 0 ? root.formatNetworkSpeed(DgopService.networkTxRate) : "0 B/s"
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -19,7 +19,7 @@ BasePill {
anchors.centerIn: parent
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
size: Theme.barIconSize(root.barThickness, -4)
color: SessionData.doNotDisturb ? Theme.error : (root.isActive ? Theme.primary : Theme.surfaceText)
color: SessionData.doNotDisturb ? Theme.error : (root.isActive ? Theme.primary : Theme.widgetIconColor)
}
Rectangle {

View File

@@ -44,7 +44,8 @@ Item {
return "transparent"
}
return Qt.rgba(privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r, privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g, privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b, (privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a) * Theme.widgetTransparency)
const baseColor = Theme.widgetBaseBackgroundColor
return Qt.rgba(privacyArea.containsMouse ? Theme.errorPressed.r : baseColor.r, privacyArea.containsMouse ? Theme.errorPressed.g : baseColor.g, privacyArea.containsMouse ? Theme.errorPressed.b : baseColor.b, (privacyArea.containsMouse ? Theme.errorPressed.a : baseColor.a) * Theme.widgetTransparency)
}
Column {
@@ -81,7 +82,7 @@ Item {
DankIcon {
name: "camera_video"
size: Theme.iconSizeSmall
color: Theme.surfaceText
color: Theme.widgetTextColor
filled: true
anchors.centerIn: parent
}
@@ -213,7 +214,7 @@ Item {
anchors.centerIn: parent
text: PrivacyService.getPrivacySummary()
font.pixelSize: Theme.barTextSize(barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
}
Rectangle {

View File

@@ -47,7 +47,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -61,7 +61,7 @@ BasePill {
return DgopService.memoryUsage.toFixed(0);
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -92,7 +92,7 @@ BasePill {
return Theme.tempWarning;
}
return Theme.surfaceText;
return Theme.widgetIconColor;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -110,7 +110,7 @@ BasePill {
return ramText;
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone

View File

@@ -292,7 +292,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
size: Theme.barIconSize(root.barThickness)
name: "sports_esports"
color: Theme.surfaceText
color: Theme.widgetTextColor
visible: {
const moddedId = Paths.moddedAppId(appId)
return moddedId.toLowerCase().includes("steam_app")
@@ -321,7 +321,7 @@ Item {
return appId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
Rectangle {
@@ -354,7 +354,7 @@ Item {
visible: !SettingsData.runningAppsCompactMode
text: windowTitle
font.pixelSize: Theme.barTextSize(barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
elide: Text.ElideRight
maximumLineCount: 1
}
@@ -527,7 +527,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
size: Theme.barIconSize(root.barThickness)
name: "sports_esports"
color: Theme.surfaceText
color: Theme.widgetTextColor
visible: {
const moddedId = Paths.moddedAppId(appId)
return moddedId.toLowerCase().includes("steam_app")
@@ -555,7 +555,7 @@ Item {
return appId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
Rectangle {
@@ -587,7 +587,7 @@ Item {
visible: !SettingsData.runningAppsCompactMode
text: windowTitle
font.pixelSize: Theme.barTextSize(barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
elide: Text.ElideRight
maximumLineCount: 1
}
@@ -777,7 +777,7 @@ Item {
anchors.centerIn: parent
text: I18n.tr("Close")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {

View File

@@ -161,7 +161,7 @@ Item {
return itemId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
}
@@ -206,7 +206,7 @@ Item {
anchors.centerIn: parent
name: root.menuOpen ? "expand_less" : "expand_more"
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {
@@ -294,7 +294,7 @@ Item {
return itemId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
}
@@ -346,7 +346,7 @@ Item {
}
}
size: Theme.barIconSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {
@@ -705,7 +705,7 @@ Item {
return itemId.charAt(0).toUpperCase()
}
font.pixelSize: 10
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {
@@ -1138,7 +1138,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
name: SessionData.isHiddenTrayId(menuRoot.trayItem?.id || "") ? "visibility" : "visibility_off"
size: 16
color: Theme.surfaceText
color: Theme.widgetTextColor
}
MouseArea {
@@ -1183,14 +1183,14 @@ Item {
DankIcon {
name: "arrow_back"
size: 16
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Back")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
}
@@ -1326,7 +1326,7 @@ Item {
anchors.centerIn: parent
name: "chevron_right"
size: 14
color: Theme.surfaceText
color: Theme.widgetTextColor
visible: menuEntry?.hasChildren ?? false
}
}

View File

@@ -112,7 +112,7 @@ BasePill {
anchors.verticalCenter: parent.verticalCenter
text: SystemUpdateService.updateCount.toString()
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
visible: root.hasUpdates && !root.isChecking
}
}

View File

@@ -31,7 +31,7 @@ BasePill {
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: Theme.barIconSize(root.barThickness, -6)
color: Theme.primary
color: Theme.widgetIconColor
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -44,7 +44,7 @@ BasePill {
return temp;
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
@@ -58,7 +58,7 @@ BasePill {
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: Theme.barIconSize(root.barThickness, -6)
color: Theme.primary
color: Theme.widgetIconColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -72,7 +72,7 @@ BasePill {
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
}
font.pixelSize: Theme.barTextSize(root.barThickness)
color: Theme.surfaceText
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
}

View File

@@ -727,7 +727,7 @@ Item {
anchors.centerIn: parent
size: 18
name: "sports_esports"
color: Theme.surfaceText
color: Theme.widgetTextColor
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isSteamApp
}
@@ -798,7 +798,7 @@ Item {
anchors.centerIn: parent
size: 18
name: "sports_esports"
color: Theme.surfaceText
color: Theme.widgetTextColor
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isSteamApp
}

View File

@@ -165,6 +165,7 @@ Item {
if (newVolume > 0 && defaultSink.audio.muted) {
defaultSink.audio.muted = false
}
AudioService.playVolumeChangeSoundIfEnabled()
}
Process {
@@ -1392,6 +1393,7 @@ Item {
if (volume > 0 && defaultSink.audio.muted) {
defaultSink.audio.muted = false
}
AudioService.playVolumeChangeSoundIfEnabled()
}
}
}

View File

@@ -591,6 +591,72 @@ Item {
}
}
StyledRect {
width: parent.width
height: niriOverviewSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 0
visible: CompositorService.isNiri
Column {
id: niriOverviewSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "open_in_new"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Close Overview on Launch")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - parent.children[0].width
- parent.children[1].width
- niriOverviewToggle.width - Theme.spacingM * 3
height: 1
}
DankToggle {
id: niriOverviewToggle
width: 32
height: 18
checked: SettingsData.spotlightCloseNiriOverview
anchors.verticalCenter: parent.verticalCenter
onToggled: checked => {
SettingsData.set("spotlightCloseNiriOverview", checked)
}
}
}
StyledText {
width: parent.width
text: I18n.tr("When enabled, launching an app from the launcher will automatically close the Niri overview if it's open.")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
}
}
}
StyledRect {
width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2

View File

@@ -704,6 +704,57 @@ Item {
}
}
Row {
width: parent.width
height: 40
spacing: Theme.spacingM
Column {
width: parent.width - widgetColorModeGroup.width - parent.spacing
anchors.verticalCenter: parent.verticalCenter
spacing: 2
StyledText {
text: I18n.tr("Widget Style")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: I18n.tr("Change bar appearance")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
}
DankButtonGroup {
id: widgetColorModeGroup
property int currentColorModeIndex: {
switch (SettingsData.widgetColorMode) {
case "default": return 0
case "colorful": return 1
default: return 0
}
}
model: ["default", "colorful"]
currentIndex: currentColorModeIndex
selectionMode: "single"
anchors.verticalCenter: parent.verticalCenter
onSelectionChanged: (index, selected) => {
if (!selected) return
const colorModeOptions = ["default", "colorful"]
SettingsData.set("widgetColorMode", colorModeOptions[index])
}
}
}
Column {
width: parent.width
spacing: Theme.spacingS

View File

@@ -0,0 +1,229 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Modals.Spotlight
import qs.Services
Scope {
id: niriOverviewScope
property bool searchActive: false
property string searchActiveScreen: ""
property bool overlayActive: NiriService.inOverview && !(PopoutService.spotlightModal?.spotlightOpen ?? false)
function showSpotlight(screenName) {
searchActive = true
searchActiveScreen = screenName
}
function hideSpotlight() {
searchActive = false
searchActiveScreen = ""
}
Connections {
target: NiriService
function onInOverviewChanged() {
if (!NiriService.inOverview) {
hideSpotlight()
} else {
searchActive = false
searchActiveScreen = ""
}
}
function onCurrentOutputChanged() {
if (NiriService.inOverview && searchActive && searchActiveScreen !== "" && searchActiveScreen !== NiriService.currentOutput) {
hideSpotlight()
}
}
}
Connections {
target: PopoutService.spotlightModal
function onSpotlightOpenChanged() {
if (PopoutService.spotlightModal?.spotlightOpen && searchActive) {
hideSpotlight()
}
}
}
Loader {
id: niriOverlayLoader
active: overlayActive
asynchronous: false
sourceComponent: Variants {
id: overlayVariants
model: Quickshell.screens
PanelWindow {
id: overlayWindow
required property var modelData
readonly property real dpr: CompositorService.getScreenScale(screen)
readonly property bool isActiveScreen: screen.name === NiriService.currentOutput
readonly property bool shouldShowSpotlight: niriOverviewScope.searchActive && screen.name === niriOverviewScope.searchActiveScreen
screen: modelData
visible: NiriService.inOverview
color: "transparent"
WlrLayershell.namespace: "dms:niri-overview-spotlight"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (!NiriService.inOverview) return WlrKeyboardFocus.None
if (!isActiveScreen) return WlrKeyboardFocus.None
return WlrKeyboardFocus.Exclusive
}
mask: Region {
item: shouldShowSpotlight ? spotlightContainer : null
}
onShouldShowSpotlightChanged: {
if (!shouldShowSpotlight && isActiveScreen) {
Qt.callLater(() => keyboardFocusScope.forceActiveFocus())
}
}
anchors {
top: true
left: true
right: true
bottom: true
}
FocusScope {
id: keyboardFocusScope
anchors.fill: parent
focus: true
Keys.onPressed: event => {
if (!overlayWindow.shouldShowSpotlight) {
if ([Qt.Key_Escape, Qt.Key_Return].includes(event.key)) {
NiriService.toggleOverview()
event.accepted = true
return
}
if (event.key === Qt.Key_Left) {
NiriService.moveColumnLeft()
event.accepted = true
return
}
if (event.key === Qt.Key_Right) {
NiriService.moveColumnRight()
event.accepted = true
return
}
if (event.key === Qt.Key_Up) {
NiriService.moveWorkspaceUp()
event.accepted = true
return
}
if (event.key === Qt.Key_Down) {
NiriService.moveWorkspaceDown()
event.accepted = true
return
}
if (event.modifiers & (Qt.ControlModifier | Qt.MetaModifier) || [Qt.Key_Delete, Qt.Key_Backspace].includes(event.key)) {
event.accepted = false
return
}
if (!event.isAutoRepeat && event.text) {
niriOverviewScope.showSpotlight(overlayWindow.screen.name)
if (spotlightContent?.searchField) {
spotlightContent.searchField.text = event.text.trim()
if (spotlightContent.appLauncher) {
spotlightContent.appLauncher.searchQuery = event.text.trim()
}
Qt.callLater(() => spotlightContent.searchField.forceActiveFocus())
}
event.accepted = true
}
}
}
}
Item {
id: spotlightContainer
x: Theme.snap((parent.width - width) / 2, overlayWindow.dpr)
y: Theme.snap((parent.height - height) / 2, overlayWindow.dpr)
width: Theme.px(500, overlayWindow.dpr)
height: Theme.px(600, overlayWindow.dpr)
property real scaleValue: 0.96
scale: scaleValue
opacity: overlayWindow.shouldShowSpotlight ? 1 : 0
enabled: overlayWindow.shouldShowSpotlight
layer.enabled: true
layer.smooth: false
layer.textureSize: Qt.size(Math.round(width * overlayWindow.dpr), Math.round(height * overlayWindow.dpr))
Connections {
target: overlayWindow
function onShouldShowSpotlightChanged() {
spotlightContainer.scaleValue = overlayWindow.shouldShowSpotlight ? 1.0 : 0.96
}
}
Behavior on scaleValue {
NumberAnimation {
duration: Theme.expressiveDurations.expressiveDefaultSpatial
easing.type: Easing.BezierSpline
easing.bezierCurve: niriOverviewScope.searchActive ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.expressiveDurations.expressiveDefaultSpatial
easing.type: Easing.BezierSpline
easing.bezierCurve: niriOverviewScope.searchActive ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
}
}
Rectangle {
anchors.fill: parent
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 1
}
SpotlightContent {
id: spotlightContent
anchors.fill: parent
anchors.margins: 0
property var fakeParentModal: QtObject {
property bool spotlightOpen: overlayWindow.shouldShowSpotlight
function hide() {
niriOverviewScope.hideSpotlight()
if (overlayWindow.isActiveScreen) {
Qt.callLater(() => keyboardFocusScope.forceActiveFocus())
}
}
}
Component.onCompleted: {
parentModal = fakeParentModal
}
}
}
}
}
}
}

View File

@@ -407,24 +407,9 @@ Singleton {
}
}
Timer {
id: volumeSoundDebounce
interval: 50
repeat: false
onTriggered: {
if (SettingsData.soundsEnabled && SettingsData.soundVolumeChanged) {
root.playVolumeChangeSound()
}
}
}
Connections {
target: root.sink && root.sink.audio ? root.sink.audio : null
enabled: root.sink && root.sink.audio
ignoreUnknownSignals: true
function onVolumeChanged() {
volumeSoundDebounce.restart()
function playVolumeChangeSoundIfEnabled() {
if (SettingsData.soundsEnabled && SettingsData.soundVolumeChanged) {
playVolumeChangeSound()
}
}
@@ -559,6 +544,7 @@ Singleton {
const newVolume = Math.max(0, Math.min(100, currentVolume + stepValue))
root.sink.audio.volume = newVolume / 100
root.playVolumeChangeSoundIfEnabled()
return `Volume increased to ${newVolume}%`
}
@@ -576,6 +562,7 @@ Singleton {
const newVolume = Math.max(0, Math.min(100, currentVolume - stepValue))
root.sink.audio.volume = newVolume / 100
root.playVolumeChangeSoundIfEnabled()
return `Volume decreased to ${newVolume}%`
}

View File

@@ -606,6 +606,38 @@ Singleton {
})
}
function moveColumnLeft() {
return send({
"Action": {
"FocusColumnLeft": {}
}
})
}
function moveColumnRight() {
return send({
"Action": {
"FocusColumnRight": {}
}
})
}
function moveWorkspaceDown() {
return send({
"Action": {
"FocusWorkspaceDown": {}
}
})
}
function moveWorkspaceUp() {
return send({
"Action": {
"FocusWorkspaceUp": {}
}
})
}
function switchToWorkspace(workspaceIndex) {
return send({
"Action": {

View File

@@ -34,7 +34,7 @@ Singleton {
}
PwObjectTracker {
objects: Pipewire.nodes.values.filter(node => node.audio && !node.isStream)
objects: Pipewire.nodes.values.filter(node => !node.isStream)
}
readonly property bool cameraActive: {
@@ -47,7 +47,7 @@ Singleton {
if (!node || !node.ready) {
continue
}
if (node.properties && node.properties["media.class"] === "Stream/Input/Video") {
if (node.properties["stream.is-live"] === "true") {
return true