1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-31 08:52:49 -05:00

Compare commits

...

8 Commits

Author SHA1 Message Date
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
23 changed files with 315 additions and 10 deletions

View File

@@ -19,10 +19,12 @@ func init() {
Register("fedora-asahi-remix", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution { Register("fedora-asahi-remix", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan) return NewFedoraDistribution(config, logChan)
}) })
Register("bluefin", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution { Register("bluefin", "#0B57A4", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan) return NewFedoraDistribution(config, logChan)
}) })
Register("ultramarine", "#00078b", FamilyFedora, func(config DistroConfig, logChan chan<- string) Distribution {
return NewFedoraDistribution(config, logChan)
})
} }
type FedoraDistribution struct { 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, ", "))) f.log(fmt.Sprintf("Installing DNF packages: %s", strings.Join(packages, ", ")))
args := []string{"dnf", "install", "-y"} 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...) args = append(args, packages...)
progressChan <- InstallProgressMsg{ progressChan <- InstallProgressMsg{

View File

@@ -171,6 +171,7 @@ Singleton {
property string spotlightModalViewMode: "list" property string spotlightModalViewMode: "list"
property bool sortAppsAlphabetically: false property bool sortAppsAlphabetically: false
property int appLauncherGridColumns: 4 property int appLauncherGridColumns: 4
property bool spotlightCloseNiriOverview: true
property string weatherLocation: "New York, NY" property string weatherLocation: "New York, NY"
property string weatherCoordinates: "40.7128,-74.0060" property string weatherCoordinates: "40.7128,-74.0060"

View File

@@ -97,6 +97,7 @@ var SPEC = {
spotlightModalViewMode: { def: "list" }, spotlightModalViewMode: { def: "list" },
sortAppsAlphabetically: { def: false }, sortAppsAlphabetically: { def: false },
appLauncherGridColumns: { def: 4 }, appLauncherGridColumns: { def: 4 },
spotlightCloseNiriOverview: { def: true },
weatherLocation: { def: "New York, NY" }, weatherLocation: { def: "New York, NY" },
weatherCoordinates: { def: "40.7128,-74.0060" }, weatherCoordinates: { def: "40.7128,-74.0060" },

View File

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

View File

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

View File

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

View File

@@ -95,11 +95,6 @@ PanelWindow {
return WlrKeyboardFocus.Exclusive return WlrKeyboardFocus.Exclusive
} }
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && shouldHaveFocus
}
onVisibleChanged: { onVisibleChanged: {
if (root.visible) { if (root.visible) {
opened() opened()
@@ -245,7 +240,7 @@ PanelWindow {
clip: false clip: false
layer.enabled: true layer.enabled: true
layer.smooth: false 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 opacity: root.shouldBeVisible ? 1 : 0
scale: modalContainer.scaleValue scale: modalContainer.scaleValue
x: Theme.snap(modalContainer.animX + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5, root.dpr) 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
import QtQuick.Controls import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Hyprland
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Modals.Common import qs.Modals.Common
@@ -12,6 +13,11 @@ DankModal {
layerNamespace: "dms:color-picker" layerNamespace: "dms:color-picker"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string pickerTitle: "Choose Color" property string pickerTitle: "Choose Color"
property color selectedColor: SessionData.recentColors.length > 0 ? SessionData.recentColors[0] : Theme.primary property color selectedColor: SessionData.recentColors.length > 0 ? SessionData.recentColors[0] : Theme.primary
property var onColorSelectedCallback: null property var onColorSelectedCallback: null

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Hyprland
import Quickshell.Io import Quickshell.Io
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
@@ -14,6 +15,11 @@ DankModal {
layerNamespace: "dms:spotlight" layerNamespace: "dms:spotlight"
HyprlandFocusGrab {
windows: [spotlightModal]
active: CompositorService.isHyprland && spotlightModal.shouldHaveFocus
}
property bool spotlightOpen: false property bool spotlightOpen: false
property alias spotlightContent: spotlightContentInstance property alias spotlightContent: spotlightContentInstance

View File

@@ -1,4 +1,6 @@
import QtQuick import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common import qs.Common
import qs.Modals.Common import qs.Modals.Common
import qs.Services import qs.Services
@@ -9,6 +11,11 @@ DankModal {
layerNamespace: "dms:wifi-password" layerNamespace: "dms:wifi-password"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string wifiPasswordSSID: "" property string wifiPasswordSSID: ""
property string wifiPasswordInput: "" property string wifiPasswordInput: ""
property string wifiUsernameInput: "" property string wifiUsernameInput: ""

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 { StyledRect {
width: parent.width width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2 height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2

View File

@@ -0,0 +1,117 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
Scope {
id: niriOverviewScope
// Only show overlay when in overview and spotlight is not open
property bool overlayActive: NiriService.inOverview && !(PopoutService.spotlightModal?.spotlightOpen ?? false)
Loader {
id: niriOverlayLoader
active: NiriService.inOverview
asynchronous: false
sourceComponent: Variants {
id: overlayVariants
model: Quickshell.screens
PanelWindow {
id: overlayWindow
required property var modelData
screen: modelData
visible: niriOverviewScope.overlayActive
color: "transparent"
WlrLayershell.namespace: "dms:niri-overview-overlay"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: niriOverviewScope.overlayActive ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
implicitWidth: 0
implicitHeight: 0
anchors {
top: true
left: true
right: false
bottom: false
}
FocusScope {
id: keyboardFocusScope
anchors.fill: parent
visible: niriOverviewScope.overlayActive
focus: niriOverviewScope.overlayActive
Keys.onPressed: event => {
// Handle arrow keys and escape for navigation, mimicking niri's harcoded keybinds
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
}
// Allowing delete and backspace will produce a broken text
if (event.modifiers & (Qt.ControlModifier | Qt.MetaModifier) || [Qt.Key_Delete, Qt.Key_Backspace].includes(event.key)) {
event.accepted = false
return
}
// For any other key (printable characters), open spotlight
if (!event.isAutoRepeat) {
Qt.callLater(() => {
if (PopoutService.spotlightModal) {
if (event.text) {
PopoutService.spotlightModal.showWithQuery(event.text.trim())
}
}
})
event.accepted = true
}
}
Connections {
target: niriOverviewScope
function onOverlayActiveChanged() {
if (niriOverviewScope.overlayActive) {
Qt.callLater(() => keyboardFocusScope.forceActiveFocus())
}
}
}
}
}
}
}
}

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) { function switchToWorkspace(workspaceIndex) {
return send({ return send({
"Action": { "Action": {

View File

@@ -34,7 +34,7 @@ Singleton {
} }
PwObjectTracker { PwObjectTracker {
objects: Pipewire.nodes.values.filter(node => node.audio && !node.isStream) objects: Pipewire.nodes.values.filter(node => !node.isStream)
} }
readonly property bool cameraActive: { readonly property bool cameraActive: {