shift-shell/containments/homescreens/folio/package/contents/ui/DelegateDragItem.qml
Micah Stanley d4eaf693c6 Folio/Halcyon: Expand Background Blur Effect using a MaskLayer
This merge request expands upon the folio and halcyon background blur effects, making the folio background blur include the backgrounds of folder icons, the favorites bar, and wallpaper selector, and for halcyon, it now includes the folder icons, app library, search, and wallpaper selector. To accomplish this, a mask layer plugin was created to easily attach to these elements. This way, we can use a `OpacityMask` to cut out from the existing blur layer, thus hopefully keeping the performance cost low. And with my limited testing, it does at least seems to run about the same on my oneplus 6t, though it is not really a low end device, so I can not fairly judge the impact for something slower (eg. PinePhone). To be on the safe side, a third option was also added to the folio settings, allowing for the ability to toggle back to the old functionality if needed.

![Screenshot_20250613_135521](/uploads/d5aa81d6589b61fbba675e4a6e621b55/Screenshot_20250613_135521.png)
![Screenshot_20250613_135536](/uploads/bd726459a131f736e2711ced3fe90d4f/Screenshot_20250613_135536.png)
![Screenshot_20250613_135505](/uploads/c603627b4e65d4b956a1e0b6463d28f3/Screenshot_20250613_135505.png)
![Screenshot_20250627_093729](/uploads/e5f1ad672361c2b9bae23e57905336eb/Screenshot_20250627_093729.png)
2025-06-27 14:27:30 -04:00

187 lines
6.2 KiB
QML

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami 2.20 as Kirigami
import org.kde.private.mobile.homescreen.folio 1.0 as Folio
import org.kde.plasma.private.mobileshell as MobileShell
import "./delegate"
Item {
id: root
property Folio.HomeScreen folio
property MobileShell.MaskManager maskManager
property Folio.FolioDelegate delegate
width: folio.HomeScreenState.pageCellWidth
height: folio.HomeScreenState.pageCellHeight
readonly property real dropAnimationRunning: dragXAnim.running || dragYAnim.running
// ignore widget dragging, that is not handled by this component
readonly property bool isWidgetDrag: folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
visible: false
x: folio.HomeScreenState.delegateDragX
y: folio.HomeScreenState.delegateDragY
function setXBinding() {
x = Qt.binding(() => folio.HomeScreenState.delegateDragX);
}
function setYBinding() {
y = Qt.binding(() => folio.HomeScreenState.delegateDragY);
}
// animate drop x
NumberAnimation on x {
id: dragXAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
onFinished: {
root.visible = false;
root.setXBinding();
}
}
// animate drop y
NumberAnimation on y {
id: dragYAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
onFinished: {
root.visible = false;
root.setYBinding();
}
}
// animate scale if it's an app being placed into a folder
ScaleAnimator on scale {
id: scaleAnim
to: 0
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutCubic
}
Connections {
id: stateWatcher
target: folio.HomeScreenState
property var delegateDroppedOn: null
// reset and show drag item
function onSwipeStateChanged() {
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && !isWidgetDrag) {
root.scale = 1.0;
root.visible = true;
}
}
// save the existing delegate at the spot (this is called before the delegate is dropped)
function onDelegateDragEnded() {
if (root.isWidgetDrag) {
return;
}
let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition;
switch (dropPosition.location) {
case Folio.DelegateDragPosition.Pages:
stateWatcher.delegateDroppedOn = folio.HomeScreenState.getPageDelegateAt(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
break;
case Folio.DelegateDragPosition.Favourites:
stateWatcher.delegateDroppedOn = folio.HomeScreenState.getFavouritesDelegateAt(dropPosition.favouritesPosition);
break;
case Folio.DelegateDragPosition.Folder:
stateWatcher.delegateDroppedOn = null;
break;
}
}
}
Connections {
target: folio.HomeScreenState.dragState
// animate from when the delegate is dropped to its drop position
function onDelegateDroppedAndPlaced() {
if (root.isWidgetDrag) {
return;
}
let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition;
let pos = null;
switch (dropPosition.location) {
case Folio.DelegateDragPosition.Pages:
pos = folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
break;
case Folio.DelegateDragPosition.Favourites:
pos = folio.HomeScreenState.getFavouritesDelegateScreenPosition(dropPosition.favouritesPosition);
break;
case Folio.DelegateDragPosition.Folder:
pos = folio.HomeScreenState.getFolderDelegateScreenPosition(dropPosition.folderPosition);
break;
}
dragXAnim.to = pos.x;
dragYAnim.to = pos.y;
dragXAnim.restart();
dragYAnim.restart();
if (stateWatcher.delegateDroppedOn &&
stateWatcher.delegateDroppedOn.type != Folio.FolioDelegate.None &&
dragState.dropDelegate.type === Folio.FolioDelegate.Application) {
// scale animation if we are creating, or inserting into a folder
scaleAnim.restart();
}
}
// if the drop has been abandoned, just hide
function onNewDelegateDropAbandoned() {
root.visible = false;
}
}
// simulate an icon delegate
ColumnLayout {
anchors.fill: parent
spacing: 0
// icon
DelegateIconLoader {
id: loader
folio: root.folio
maskManager: root.maskManager
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.minimumWidth: folio.FolioSettings.delegateIconSize
Layout.minimumHeight: folio.FolioSettings.delegateIconSize
Layout.preferredHeight: Layout.minimumHeight
delegate: root.delegate
layer.enabled: true
layer.effect: DelegateShadow {}
}
// simulate the delegate label for positioning purposes
DelegateLabel {
id: label
opacity: 0
Layout.fillWidth: true
Layout.preferredHeight: folio.HomeScreenState.pageDelegateLabelHeight
Layout.topMargin: folio.HomeScreenState.pageDelegateLabelSpacing
Layout.leftMargin: -parent.anchors.leftMargin + Kirigami.Units.smallSpacing
Layout.rightMargin: -parent.anchors.rightMargin + Kirigami.Units.smallSpacing
}
}
}