shift-shell/containments/homescreens/halcyon/qml/SearchWidget.qml
Marco Allegretti a37734b74a Move homescreens to shared motion
Use Motion wrappers and state layers across Folio and Halcyon delegates, drawers, folders, resize handles, and dock feedback. Also align Folio edit/drop highlights with theme colors instead of fixed white overlays.
2026-05-21 11:13:36 +02:00

137 lines
3.8 KiB
QML

/*
* SPDX-FileCopyrightText: 2014 Aaron Seigo <aseigo@kde.org>
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
* SPDX-FileCopyrightText: 2021-2025 Devin Lin <devin@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.kirigami as Kirigami
Item {
id: root
// Content margins
property real topPadding: 0
property real bottomPadding: 0
property real leftPadding: 0
property real rightPadding: 0
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
// Call when the gesture has started
function startGesture() {
krunnerScreen.clearField();
flickable.contentY = flickable.closedContentY;
}
// Call when the touch gesture has been updated
function updateGestureOffset(yOffset) {
flickable.contentY = Math.max(0, Math.min(flickable.closedContentY, flickable.contentY + yOffset));
}
// Call when the touch gesture has let go
function endGesture() {
flickable.opening ? open() : close();
}
// Open the search widget (animated)
function open() {
anim.to = flickable.openedContentY;
anim.restart();
}
// Close the search widget (animated)
function close() {
anim.to = flickable.closedContentY;
anim.restart();
}
// Emitted when it is requested to force active focus on the parent and release focus on the widget
signal releaseFocusRequested()
readonly property real openFactor: Math.max(0, Math.min(1, 1 - flickable.contentY / flickable.closedContentY))
readonly property bool isOpen: openFactor != 0
// Pass focus to search screen
onFocusChanged: {
if (focus) {
krunnerScreen.requestFocus();
}
}
Rectangle {
id: background
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.3)
opacity: root.openFactor
}
Flickable {
id: flickable
anchors.fill: parent
anchors.topMargin: root.topPadding
anchors.bottomMargin: root.bottomPadding
anchors.leftMargin: root.leftPadding
anchors.rightMargin: root.rightPadding
opacity: root.openFactor
contentHeight: flickable.height + flickable.closedContentY
contentY: flickable.closedContentY
property real oldContentY: contentY
property bool opening: false
// The y at which the flickable is fully open
readonly property real closedContentY: Kirigami.Units.gridUnit * 5
// The y at which the flickable is fully closed
readonly property real openedContentY: 0
onContentYChanged: {
opening = contentY < oldContentY;
oldContentY = contentY;
if (krunnerScreen.focus) {
// Unfocus from search
root.releaseFocusRequested();
}
}
onMovementEnded: root.endGesture()
onDraggingChanged: {
if (!dragging) {
root.endGesture();
}
}
MobileShell.MotionNumberAnimation on contentY {
id: anim
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
running: false
onFinished: {
if (anim.to === flickable.openedContentY) {
krunnerScreen.requestFocus();
} else {
// Unfocus from search
root.releaseFocusRequested();
}
}
}
MobileShell.KRunnerScreen {
id: krunnerScreen
width: parent.width
height: parent.height
onRequestedClose: root.close();
}
}
}