1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-29 16:02:51 -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 {
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

@@ -171,6 +171,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

@@ -97,6 +97,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

@@ -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,6 +15,11 @@ DankModal {
layerNamespace: "dms:spotlight"
HyprlandFocusGrab {
windows: [spotlightModal]
active: CompositorService.isHyprland && spotlightModal.shouldHaveFocus
}
property bool spotlightOpen: false
property alias spotlightContent: spotlightContentInstance

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:wifi-password"
HyprlandFocusGrab {
windows: [root]
active: CompositorService.isHyprland && root.shouldHaveFocus
}
property string wifiPasswordSSID: ""
property string wifiPasswordInput: ""
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 {
width: parent.width
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) {
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