mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-01 19:18:28 -04:00
launcher: add option to choose spotlight style on niri overview
This commit is contained in:
@@ -520,6 +520,7 @@ Singleton {
|
|||||||
property var appDrawerSectionViewModes: ({})
|
property var appDrawerSectionViewModes: ({})
|
||||||
onAppDrawerSectionViewModesChanged: saveSettings()
|
onAppDrawerSectionViewModesChanged: saveSettings()
|
||||||
property bool niriOverviewOverlayEnabled: true
|
property bool niriOverviewOverlayEnabled: true
|
||||||
|
property string niriOverviewLauncherStyle: "full"
|
||||||
property string dankLauncherV2Size: "compact"
|
property string dankLauncherV2Size: "compact"
|
||||||
property bool dankLauncherV2ShowSourceBadges: true
|
property bool dankLauncherV2ShowSourceBadges: true
|
||||||
property bool dankLauncherV2BorderEnabled: false
|
property bool dankLauncherV2BorderEnabled: false
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ var SPEC = {
|
|||||||
spotlightSectionViewModes: { def: {} },
|
spotlightSectionViewModes: { def: {} },
|
||||||
appDrawerSectionViewModes: { def: {} },
|
appDrawerSectionViewModes: { def: {} },
|
||||||
niriOverviewOverlayEnabled: { def: true },
|
niriOverviewOverlayEnabled: { def: true },
|
||||||
|
niriOverviewLauncherStyle: { def: "full" },
|
||||||
dankLauncherV2Size: { def: "compact" },
|
dankLauncherV2Size: { def: "compact" },
|
||||||
dankLauncherV2ShowSourceBadges: { def: true },
|
dankLauncherV2ShowSourceBadges: { def: true },
|
||||||
dankLauncherV2BorderEnabled: { def: false },
|
dankLauncherV2BorderEnabled: { def: false },
|
||||||
|
|||||||
@@ -120,18 +120,6 @@ Item {
|
|||||||
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0
|
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0
|
||||||
readonly property bool useSingleWindow: CompositorService.isHyprland || useBackgroundDarken
|
readonly property bool useSingleWindow: CompositorService.isHyprland || useBackgroundDarken
|
||||||
|
|
||||||
// Blur region isn't auto-committed on geometry changes; kick twice to catch resize settling.
|
|
||||||
function _kickBlurCommit() {
|
|
||||||
launcherBlur.kick();
|
|
||||||
Qt.callLater(launcherBlur.kick);
|
|
||||||
}
|
|
||||||
|
|
||||||
onAlignedXChanged: _kickBlurCommit()
|
|
||||||
onAlignedYChanged: _kickBlurCommit()
|
|
||||||
onAlignedWidthChanged: _kickBlurCommit()
|
|
||||||
on_ContentImplicitHChanged: _kickBlurCommit()
|
|
||||||
onContentVisibleChanged: _kickBlurCommit()
|
|
||||||
|
|
||||||
signal dialogClosed
|
signal dialogClosed
|
||||||
|
|
||||||
function _ensureContentLoadedAndInitialize(query, mode) {
|
function _ensureContentLoadedAndInitialize(query, mode) {
|
||||||
@@ -354,9 +342,6 @@ Item {
|
|||||||
blurRadius: root.cornerRadius
|
blurRadius: root.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
onWidthChanged: root._kickBlurCommit()
|
|
||||||
onHeightChanged: root._kickBlurCommit()
|
|
||||||
|
|
||||||
WlrLayershell.namespace: "dms:spotlight"
|
WlrLayershell.namespace: "dms:spotlight"
|
||||||
WlrLayershell.layer: root.effectiveLauncherLayer
|
WlrLayershell.layer: root.effectiveLauncherLayer
|
||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
@@ -441,9 +426,6 @@ Item {
|
|||||||
|
|
||||||
opacity: contentVisible ? 1 : 0
|
opacity: contentVisible ? 1 : 0
|
||||||
|
|
||||||
onOpacityChanged: root._kickBlurCommit()
|
|
||||||
onSlideOffsetChanged: root._kickBlurCommit()
|
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: contentVisible ? root._openDuration : root._closeDuration
|
duration: contentVisible ? root._openDuration : root._closeDuration
|
||||||
|
|||||||
@@ -322,9 +322,13 @@ DankPopout {
|
|||||||
DankTabBar {
|
DankTabBar {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
|
|
||||||
|
// Effective visibility is false while the popout window is unmapped, so gating
|
||||||
|
// height on `visible` collapses the bar between opens and resizes the surface
|
||||||
|
// mid-animation. Gate on the model instead.
|
||||||
|
readonly property bool hasTabs: (model?.length ?? 0) > 0
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: visible ? 48 : 0
|
height: hasTabs ? 48 : 0
|
||||||
visible: model.length > 0
|
visible: hasTabs
|
||||||
currentIndex: root.currentTabIndex
|
currentIndex: root.currentTabIndex
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
equalWidthTabs: true
|
equalWidthTabs: true
|
||||||
@@ -356,8 +360,8 @@ DankPopout {
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: visible ? Theme.spacingXS : 0
|
height: tabBar.hasTabs ? Theme.spacingXS : 0
|
||||||
visible: tabBar.visible
|
visible: tabBar.hasTabs
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|||||||
@@ -223,8 +223,9 @@ Rectangle {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: dankWarning
|
id: dankWarning
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: CalendarService && CalendarService.dankNeedsLaunch
|
readonly property bool showWarning: CalendarService?.dankNeedsLaunch ?? false
|
||||||
height: visible ? Math.max(28, warningRow.implicitHeight) + Theme.spacingS : 0
|
visible: showWarning
|
||||||
|
height: showWarning ? Math.max(28, warningRow.implicitHeight) + Theme.spacingS : 0
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.warningHover
|
color: Theme.warningHover
|
||||||
border.color: Theme.withAlpha(Theme.warning, 0.35)
|
border.color: Theme.withAlpha(Theme.warning, 0.35)
|
||||||
|
|||||||
@@ -770,6 +770,20 @@ Item {
|
|||||||
checked: SettingsData.niriOverviewOverlayEnabled
|
checked: SettingsData.niriOverviewOverlayEnabled
|
||||||
onToggled: checked => SettingsData.set("niriOverviewOverlayEnabled", checked)
|
onToggled: checked => SettingsData.set("niriOverviewOverlayEnabled", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsButtonGroupRow {
|
||||||
|
visible: SettingsData.niriOverviewOverlayEnabled
|
||||||
|
settingKey: "niriOverviewLauncherStyle"
|
||||||
|
tags: ["launcher", "niri", "overview", "overlay", "style", "spotlight", "full"]
|
||||||
|
text: I18n.tr("Default Opens")
|
||||||
|
model: [I18n.tr("Full"), I18n.tr("Spotlight")]
|
||||||
|
currentIndex: SettingsData.niriOverviewLauncherStyle === "spotlight" ? 1 : 0
|
||||||
|
onSelectionChanged: (index, selected) => {
|
||||||
|
if (!selected)
|
||||||
|
return;
|
||||||
|
SettingsData.set("niriOverviewLauncherStyle", index === 1 ? "spotlight" : "full");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
|
|||||||
@@ -101,6 +101,23 @@ Scope {
|
|||||||
readonly property bool overlayVisible: NiriService.inOverview || niriOverviewScope.isClosing
|
readonly property bool overlayVisible: NiriService.inOverview || niriOverviewScope.isClosing
|
||||||
property bool hasActivePopout: !!PopoutManager.currentPopoutsByScreen[screen.name]
|
property bool hasActivePopout: !!PopoutManager.currentPopoutsByScreen[screen.name]
|
||||||
property bool hasActiveModal: !!ModalManager.currentModalsByScreen[screen.name]
|
property bool hasActiveModal: !!ModalManager.currentModalsByScreen[screen.name]
|
||||||
|
readonly property bool useSpotlightStyle: SettingsData.niriOverviewLauncherStyle === "spotlight"
|
||||||
|
readonly property var launcherContent: useSpotlightStyle ? spotlightLauncherLoader.item : fullLauncherLoader.item
|
||||||
|
|
||||||
|
readonly property QtObject fakeParentModal: QtObject {
|
||||||
|
readonly property bool spotlightOpen: spotlightContainer.visible
|
||||||
|
readonly property bool isClosing: niriOverviewScope.isClosing
|
||||||
|
readonly property real alignedX: spotlightContainer.x
|
||||||
|
readonly property real alignedY: spotlightContainer.y
|
||||||
|
readonly property real screenHeight: overlayWindow.screen?.height ?? 1080
|
||||||
|
function hide() {
|
||||||
|
if (niriOverviewScope.searchActive) {
|
||||||
|
niriOverviewScope.hideSpotlight();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NiriService.toggleOverview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: PopoutManager
|
target: PopoutManager
|
||||||
@@ -219,13 +236,13 @@ Scope {
|
|||||||
|
|
||||||
if (event.isAutoRepeat || !event.text)
|
if (event.isAutoRepeat || !event.text)
|
||||||
return;
|
return;
|
||||||
if (!launcherContent?.searchField)
|
if (!overlayWindow.launcherContent?.searchField)
|
||||||
return;
|
return;
|
||||||
const trimmedText = event.text.trim();
|
const trimmedText = event.text.trim();
|
||||||
launcherContent.searchField.text = trimmedText;
|
overlayWindow.launcherContent.searchField.text = trimmedText;
|
||||||
launcherContent.controller.setSearchQuery(trimmedText);
|
overlayWindow.launcherContent.controller.setSearchQuery(trimmedText);
|
||||||
niriOverviewScope.showSpotlight(overlayWindow.screen.name);
|
niriOverviewScope.showSpotlight(overlayWindow.screen.name);
|
||||||
Qt.callLater(() => launcherContent.searchField.forceActiveFocus());
|
Qt.callLater(() => overlayWindow.launcherContent.searchField.forceActiveFocus());
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +254,7 @@ Scope {
|
|||||||
// edge and slide in from beyond that edge. In any other mode the
|
// edge and slide in from beyond that edge. In any other mode the
|
||||||
// spotlight stays centered — identical to master.
|
// spotlight stays centered — identical to master.
|
||||||
readonly property string connectedEmergeSide: SettingsData.frameLauncherEmergeSide || "bottom"
|
readonly property string connectedEmergeSide: SettingsData.frameLauncherEmergeSide || "bottom"
|
||||||
readonly property real _centerY: (parent.height - height) / 2
|
readonly property real _centerY: overlayWindow.useSpotlightStyle ? Math.max(0, parent.height * 0.33 - 28) : (parent.height - height) / 2
|
||||||
readonly property real _connectedRestY: {
|
readonly property real _connectedRestY: {
|
||||||
if (!Theme.isConnectedEffect || !overlayWindow.screen)
|
if (!Theme.isConnectedEffect || !overlayWindow.screen)
|
||||||
return _centerY;
|
return _centerY;
|
||||||
@@ -277,8 +294,8 @@ Scope {
|
|||||||
return 600;
|
return 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
width: Math.min(baseWidth, overlayWindow.screen.width - 100)
|
width: overlayWindow.useSpotlightStyle ? Math.min(680, overlayWindow.screen.width - 80) : Math.min(baseWidth, overlayWindow.screen.width - 100)
|
||||||
height: Math.min(baseHeight, overlayWindow.screen.height - 100)
|
height: overlayWindow.useSpotlightStyle ? Math.ceil(overlayWindow.launcherContent?.implicitHeight ?? 56) : Math.min(baseHeight, overlayWindow.screen.height - 100)
|
||||||
|
|
||||||
readonly property bool animatingOut: niriOverviewScope.isClosing && overlayWindow.isSpotlightScreen
|
readonly property bool animatingOut: niriOverviewScope.isClosing && overlayWindow.isSpotlightScreen
|
||||||
|
|
||||||
@@ -344,57 +361,51 @@ Scope {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
|
|
||||||
Keys.onPressed: event => launcherContent.activeContextMenu?.handleKey(event)
|
Keys.onPressed: event => overlayWindow.launcherContent?.activeContextMenu?.handleKey(event)
|
||||||
|
|
||||||
Keys.onEscapePressed: event => {
|
Keys.onEscapePressed: event => {
|
||||||
launcherContent.activeContextMenu?.handleKey(event);
|
overlayWindow.launcherContent?.activeContextMenu?.handleKey(event);
|
||||||
if (!event.accepted)
|
if (!event.accepted)
|
||||||
launcherContent.parentModal?.hide();
|
overlayWindow.launcherContent?.parentModal?.hide();
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherContent {
|
Loader {
|
||||||
id: launcherContent
|
id: fullLauncherLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 0
|
active: !overlayWindow.useSpotlightStyle
|
||||||
|
sourceComponent: LauncherContent {
|
||||||
property var fakeParentModal: QtObject {
|
parentModal: overlayWindow.fakeParentModal
|
||||||
property bool spotlightOpen: spotlightContainer.visible
|
|
||||||
property bool isClosing: niriOverviewScope.isClosing
|
|
||||||
property real alignedX: spotlightContainer.x
|
|
||||||
property real alignedY: spotlightContainer.y
|
|
||||||
function hide() {
|
|
||||||
if (niriOverviewScope.searchActive) {
|
|
||||||
niriOverviewScope.hideSpotlight();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NiriService.toggleOverview();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Loader {
|
||||||
target: launcherContent.searchField
|
id: spotlightLauncherLoader
|
||||||
function onTextChanged() {
|
anchors.fill: parent
|
||||||
if (launcherContent.searchField.text.length > 0 || !niriOverviewScope.searchActive)
|
active: overlayWindow.useSpotlightStyle
|
||||||
return;
|
sourceComponent: SpotlightLauncherContent {
|
||||||
niriOverviewScope.hideSpotlight();
|
parentModal: overlayWindow.fakeParentModal
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Connections {
|
||||||
parentModal = fakeParentModal;
|
target: overlayWindow.launcherContent?.searchField ?? null
|
||||||
|
function onTextChanged() {
|
||||||
|
if (overlayWindow.launcherContent.searchField.text.length > 0 || !niriOverviewScope.searchActive)
|
||||||
|
return;
|
||||||
|
niriOverviewScope.hideSpotlight();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: launcherContent.controller
|
target: overlayWindow.launcherContent?.controller ?? null
|
||||||
function onItemExecuted() {
|
function onItemExecuted() {
|
||||||
niriOverviewScope.releaseKeyboard = true;
|
niriOverviewScope.releaseKeyboard = true;
|
||||||
}
|
}
|
||||||
function onModeChanged(mode) {
|
function onModeChanged(mode) {
|
||||||
if (launcherContent.controller.autoSwitchedToFiles)
|
if (overlayWindow.launcherContent.controller.autoSwitchedToFiles)
|
||||||
return;
|
return;
|
||||||
SessionData.setNiriOverviewLastMode(mode);
|
SessionData.setNiriOverviewLastMode(mode);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,42 @@ Item {
|
|||||||
targetWindow.BackgroundEffect.blurRegion = _active ? blurRegion : null;
|
targetWindow.BackgroundEffect.blurRegion = _active ? blurRegion : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Republish after geometry settles, plus one trailing pass.
|
||||||
|
onBlurXChanged: settleKickAction.restart()
|
||||||
|
onBlurYChanged: settleKickAction.restart()
|
||||||
|
onBlurWidthChanged: settleKickAction.restart()
|
||||||
|
onBlurHeightChanged: settleKickAction.restart()
|
||||||
|
onBlurRadiusChanged: settleKickAction.restart()
|
||||||
|
onClipEnabledChanged: settleKickAction.restart()
|
||||||
|
onClipXChanged: settleKickAction.restart()
|
||||||
|
onClipYChanged: settleKickAction.restart()
|
||||||
|
onClipWidthChanged: settleKickAction.restart()
|
||||||
|
onClipHeightChanged: settleKickAction.restart()
|
||||||
|
|
||||||
|
function _runSettleKick() {
|
||||||
|
if (!targetWindow?.visible)
|
||||||
|
return;
|
||||||
|
kick();
|
||||||
|
settleRepeatTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
DeferredAction {
|
||||||
|
id: settleKickAction
|
||||||
|
interval: 16
|
||||||
|
onTriggered: root._runSettleKick()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: settleRepeatTimer
|
||||||
|
interval: 96
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
if (!root.targetWindow?.visible)
|
||||||
|
return;
|
||||||
|
root.kick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _scheduleLifecycleKick() {
|
function _scheduleLifecycleKick() {
|
||||||
lifecycleKickAction.restart();
|
lifecycleKickAction.restart();
|
||||||
}
|
}
|
||||||
@@ -98,6 +134,12 @@ Item {
|
|||||||
else
|
else
|
||||||
root._clear();
|
root._clear();
|
||||||
}
|
}
|
||||||
|
function onWidthChanged() {
|
||||||
|
settleKickAction.restart();
|
||||||
|
}
|
||||||
|
function onHeightChanged() {
|
||||||
|
settleKickAction.restart();
|
||||||
|
}
|
||||||
function onResourcesLost() {
|
function onResourcesLost() {
|
||||||
root._clear();
|
root._clear();
|
||||||
// Re-arm so blur self-heals since instances are no longer recreated per open
|
// Re-arm so blur self-heals since instances are no longer recreated per open
|
||||||
|
|||||||
@@ -2398,6 +2398,26 @@
|
|||||||
"style"
|
"style"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "niriOverviewLauncherStyle",
|
||||||
|
"label": "Default Opens",
|
||||||
|
"tabIndex": 9,
|
||||||
|
"category": "Launcher",
|
||||||
|
"keywords": [
|
||||||
|
"default",
|
||||||
|
"drawer",
|
||||||
|
"full",
|
||||||
|
"launcher",
|
||||||
|
"menu",
|
||||||
|
"niri",
|
||||||
|
"opens",
|
||||||
|
"overlay",
|
||||||
|
"overview",
|
||||||
|
"spotlight",
|
||||||
|
"start",
|
||||||
|
"style"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "niriOverviewOverlayEnabled",
|
"section": "niriOverviewOverlayEnabled",
|
||||||
"label": "Enable Overview Overlay",
|
"label": "Enable Overview Overlay",
|
||||||
|
|||||||
Reference in New Issue
Block a user