mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
136 lines
3.7 KiB
QML
136 lines
3.7 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
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
|
|
NumberAnimation on contentY {
|
|
id: anim
|
|
duration: Kirigami.Units.longDuration * 2
|
|
easing.type: Easing.OutQuad
|
|
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();
|
|
}
|
|
}
|
|
}
|