mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
niri: embed spotlight to same window as overview layer
This commit is contained in:
@@ -3,26 +3,47 @@ import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Modals.Spotlight
|
||||
import qs.Services
|
||||
|
||||
Scope {
|
||||
id: niriOverviewScope
|
||||
|
||||
// Only show overlay when in overview and spotlight is not open
|
||||
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 && PopoutService.spotlightModal?.openedFromOverview) {
|
||||
PopoutService.spotlightModal.hide()
|
||||
if (!NiriService.inOverview) {
|
||||
hideSpotlight()
|
||||
} else {
|
||||
searchActive = false
|
||||
searchActiveScreen = ""
|
||||
}
|
||||
}
|
||||
|
||||
function onCurrentOutputChanged() {
|
||||
if (NiriService.inOverview && searchActive && searchActiveScreen !== "" && searchActiveScreen !== NiriService.currentOutput) {
|
||||
hideSpotlight()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: niriOverlayLoader
|
||||
active: NiriService.inOverview
|
||||
active: overlayActive
|
||||
asynchronous: false
|
||||
|
||||
sourceComponent: Variants {
|
||||
@@ -33,92 +54,159 @@ Scope {
|
||||
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: niriOverviewScope.overlayActive
|
||||
visible: NiriService.inOverview
|
||||
color: "transparent"
|
||||
|
||||
WlrLayershell.namespace: "dms:niri-overview-overlay"
|
||||
WlrLayershell.namespace: "dms:niri-overview-spotlight"
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: niriOverviewScope.overlayActive ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
WlrLayershell.keyboardFocus: {
|
||||
if (!NiriService.inOverview) return WlrKeyboardFocus.None
|
||||
if (!isActiveScreen) return WlrKeyboardFocus.None
|
||||
return WlrKeyboardFocus.Exclusive
|
||||
}
|
||||
|
||||
implicitWidth: 0
|
||||
implicitHeight: 0
|
||||
onShouldShowSpotlightChanged: {
|
||||
if (!shouldShowSpotlight && isActiveScreen) {
|
||||
Qt.callLater(() => keyboardFocusScope.forceActiveFocus())
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: false
|
||||
bottom: false
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
|
||||
FocusScope {
|
||||
id: keyboardFocusScope
|
||||
anchors.fill: parent
|
||||
visible: niriOverviewScope.overlayActive
|
||||
focus: niriOverviewScope.overlayActive
|
||||
focus: true
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (!overlayWindow.shouldShowSpotlight) {
|
||||
if ([Qt.Key_Escape, Qt.Key_Return].includes(event.key)) {
|
||||
NiriService.toggleOverview()
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
|
||||
// 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_Left) {
|
||||
NiriService.moveColumnLeft()
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
if (event.key === Qt.Key_Right) {
|
||||
NiriService.moveColumnRight()
|
||||
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_Up) {
|
||||
NiriService.moveWorkspaceUp()
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
if (event.key === Qt.Key_Down) {
|
||||
NiriService.moveWorkspaceDown()
|
||||
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
|
||||
}
|
||||
|
||||
// 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.openedFromOverview = true
|
||||
PopoutService.spotlightModal.showWithQuery(event.text.trim())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
event.accepted = true
|
||||
}
|
||||
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
|
||||
|
||||
layer.enabled: true
|
||||
layer.smooth: false
|
||||
layer.textureSize: Qt.size(Math.round(width * overlayWindow.dpr), Math.round(height * overlayWindow.dpr))
|
||||
|
||||
Connections {
|
||||
target: niriOverviewScope
|
||||
function onOverlayActiveChanged() {
|
||||
if (niriOverviewScope.overlayActive) {
|
||||
Qt.callLater(() => keyboardFocusScope.forceActiveFocus())
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user