Compare commits

...

21 commits

Author SHA1 Message Date
d9943d2e7a Let symbolic icons follow the color scheme
Declare FollowsColorScheme=true for the Shift icon theme so KDE apps recolor symbolic Places glyphs against dark and light surfaces. Document the requirement and guard it in the icon theme coverage test.
2026-05-23 09:30:21 +02:00
6cc92b7fa2 Add SPDX headers to motion QML components
Add missing SPDX copyright and license tags to Motion.qml,
MotionColorAnimation.qml, MotionNumberAnimation.qml, and
MotionStateLayer.qml to satisfy REUSE lint in CI.
2026-05-23 09:18:53 +02:00
36d9004473 Round normal window decorations
Reserve side and bottom decoration borders for normal windows and draw a rounded decoration frame so windows match the convergence workspace shape. Add static guards for the decoration and existing workspace-frame corner geometry.
2026-05-23 08:53:02 +02:00
d03f3585a3 Block native window menu during tiling 2026-05-22 09:39:45 +02:00
e951690c91 Route Folio task actions through tiling 2026-05-22 09:39:28 +02:00
5311dc8fe8 Own dynamic tiling window workflows 2026-05-22 09:39:11 +02:00
24e410c733 Respect animation settings in navigation tutorial
Gate the navigation KCM tutorial timings on ShellSettings animationsEnabled so the demo stops animating when the user disables shell animations.
2026-05-21 11:15:01 +02:00
753909a6ce Move shell and KWin surfaces to shared motion
Apply Motion tokens to startup, applet configuration, lockscreen controls, logout and splash transitions, KWin effects, and the mobile task switcher. Preserve timing-specific behavior where it drives runtime state.
2026-05-21 11:14:42 +02:00
88a4f5883b Move Folio gaming surfaces to shared motion
Use Motion tokens for the Game Center overlay, gaming HUD, quick settings drawer, and running-games panel. Keep gaming mode settings and gamepad behavior unchanged.
2026-05-21 11:14:00 +02:00
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
7f9087f342 Move shell popups to shared motion
Apply Motion tokens to notification drag and stack transitions, volume OSD feedback, KRunner field state, media controls height changes, and action-button popup affordances. Leave timeout and marquee animations as timing behavior.
2026-05-21 11:13:06 +02:00
1074b86225 Move shell chrome to shared motion
Use the Motion wrappers for action-drawer transitions, status bar feedback, panel reveal motion, startup feedback, and shell homescreen chrome. Keep non-animation settings reads in ShellSettings where they still control behavior.
2026-05-21 11:12:44 +02:00
8767df8b10 Add shared mobile shell motion primitives
Introduce a central Motion singleton for animation durations, easing, and press scale tokens. Add typed NumberAnimation/ColorAnimation wrappers and a reusable state-layer component so runtime QML can share the same animation policy.
2026-05-21 11:12:20 +02:00
75b9049a8c Page dynamic tiles by workspace
Keep one layout per output and virtual desktop. Move new windows to another existing desktop when the current page is full.

When a user moves a window onto a full page, replace the last focused window on that page and send it back to the source desktop. Use stable slot swaps instead of insert splits so the layout shape does not change during moves.
2026-05-20 09:38:37 +02:00
40beabede9 Keep tile preview effect inert
Nested KWin blacks out when this scene effect becomes visible. Leave the effect disabled and let the tiling script own swap and restore outlines.
2026-05-20 09:38:22 +02:00
f2f6f6f890 Stabilize nested preview startup
Use a concrete wallpaper image in generated shell config. Disable KSycoca watches when preview opts out, and keep the convergent window connection target nullable.
2026-05-20 09:38:08 +02:00
d2b3445f98 Ignore preview runtime state 2026-05-20 09:37:38 +02:00
cb4d842de3 Add primary tile promotion 2026-05-19 10:01:45 +02:00
7c51f76cc0 Reduce dynamic tile drag jitter 2026-05-19 10:00:43 +02:00
c6bd37dfc3 Stabilize automatic tile layouts 2026-05-19 09:55:25 +02:00
e0e51d7ffd Add dynamic tile drag preview 2026-05-19 09:47:45 +02:00
106 changed files with 3039 additions and 751 deletions

2
.gitignore vendored
View file

@ -21,6 +21,8 @@ build
*.kdev4
/build*
.prefix/
.preview-ab/
.preview-cache/
.preview-config/
.preview-data/
preview.sh

View file

@ -138,7 +138,7 @@ include(CheckIncludeFiles)
ecm_find_qmlmodule(org.kde.pipewire 0.1)
set(SHIFT_DEFAULT_WALLPAPER_URL "file://${KDE_INSTALL_FULL_WALLPAPERDIR}/SHIFT/")
set(SHIFT_DEFAULT_WALLPAPER_URL "file://${KDE_INSTALL_FULL_WALLPAPERDIR}/SHIFT/contents/images_dark/5120x2880.png")
set(SHIFT_SHELL_PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/shell")
file(REMOVE_RECURSE "${SHIFT_SHELL_PACKAGE_DIR}")
file(COPY shell/ DESTINATION "${SHIFT_SHELL_PACKAGE_DIR}" PATTERN "layout.js.in" EXCLUDE)

View file

@ -25,6 +25,7 @@ target_sources(mobileshellplugin PRIVATE ${mobileshellplugin_SRCS})
set_source_files_properties(
qml/components/AppLaunch.qml
qml/components/Constants.qml
qml/components/Motion.qml
qml/dataproviders/AudioInfo.qml
qml/dataproviders/BatteryInfo.qml
qml/dataproviders/BluetoothInfo.qml
@ -51,6 +52,10 @@ ecm_target_qml_sources(mobileshellplugin SOURCES
qml/components/HapticsEffect.qml
qml/components/ListView.qml
qml/components/MarqueeLabel.qml
qml/components/Motion.qml
qml/components/MotionColorAnimation.qml
qml/components/MotionNumberAnimation.qml
qml/components/MotionStateLayer.qml
qml/components/PanelBackground.qml
qml/components/ScreenEdgeDragEffect.qml
qml/components/StartupFeedbackPanelFill.qml

View file

@ -269,11 +269,11 @@ Item {
transitions: Transition {
SequentialAnimation {
PropertyAnimation {
MobileShell.MotionNumberAnimation {
id: drawerAnimation
properties: "offset"
easing.type: Easing.OutExpo
duration: root.state != "" ? Kirigami.Units.veryLongDuration : 0
type: MobileShell.Motion.SpatialSlow
duration: root.state != "" ? MobileShell.Motion.duration(type) : 0
}
ScriptAction {
script: {

View file

@ -22,10 +22,7 @@ Item {
property double brightnessPressedValue: 1
Behavior on brightnessPressedValue {
NumberAnimation {
duration: Kirigami.Units.longDuration * 2
easing.type: Easing.InOutQuad
}
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialExtended }
}
ScreenBrightness.ScreenBrightnessUtil {

View file

@ -70,7 +70,7 @@ Item {
Kirigami.Theme.backgroundColor.g,
Kirigami.Theme.backgroundColor.b,
0.9)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.OutQuad } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.StandardDecel } }
opacity: {
let base = Math.max(0, Math.min(brightnessPressedValue, actionDrawer.offset / root.minimizedQuickSettingsOffset));
return ShellSettings.Settings.convergenceModeEnabled ? base * 0.3 : base;

View file

@ -27,6 +27,7 @@ QQC2.Popup {
padding: Kirigami.Units.smallSpacing
readonly property int popupAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
property string currentPluginId: ""
property Item __currentItem: null
@ -72,11 +73,11 @@ QQC2.Popup {
}
enter: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
NumberAnimation { property: "scale"; from: 0.9; to: 1; duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { property: "opacity"; from: 0; to: 1; type: MobileShell.Motion.EffectsFast }
MobileShell.MotionNumberAnimation { property: "scale"; from: 0.9; to: 1; type: MobileShell.Motion.EffectsFast }
}
exit: Transition {
NumberAnimation { property: "opacity"; from: 1; to: 0; duration: Kirigami.Units.shortDuration; easing.type: Easing.InCubic }
MobileShell.MotionNumberAnimation { property: "opacity"; from: 1; to: 0; type: MobileShell.Motion.StandardAccel; duration: popup.popupAnimationDuration }
}
background: Kirigami.ShadowedRectangle {

View file

@ -47,6 +47,8 @@ MobileShell.BaseItem {
readonly property color disabledButtonColor: Kirigami.Theme.alternateBackgroundColor
readonly property color disabledButtonHoverColor: mixColor(Kirigami.Theme.alternateBackgroundColor, Kirigami.Theme.textColor, 0.06)
readonly property color disabledButtonPressedColor: Qt.darker(disabledButtonColor, 1.1)
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property real pressedScale: MobileShell.Motion.pressScaleIn
function mixColor(base, overlay, ratio) {
return Qt.rgba(
@ -67,10 +69,7 @@ MobileShell.BaseItem {
// scale animation on press
property real zoomScale: 1
Behavior on zoomScale {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.OutExpo
}
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Press }
}
transform: Scale {

View file

@ -12,7 +12,6 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.components 3.0 as PlasmaComponents
QuickSettingsDelegate {
@ -23,7 +22,7 @@ QuickSettingsDelegate {
readonly property int tileRadius: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
// scale animation on press
zoomScale: (ShellSettings.Settings.animationsEnabled && mouseArea.pressed) ? 0.9 : 1
zoomScale: mouseArea.pressed ? root.pressedScale : 1
background: Item {
// very simple shadow for performance
@ -61,7 +60,7 @@ QuickSettingsDelegate {
}
Behavior on color {
ColorAnimation { duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.shortDuration : 0; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast }
}
}
}

View file

@ -12,7 +12,6 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.components 3.0 as PlasmaComponents
QuickSettingsDelegate {
@ -21,7 +20,7 @@ QuickSettingsDelegate {
iconItem: icon
// scale animation on press
zoomScale: (ShellSettings.Settings.animationsEnabled && mouseArea.pressed) ? 0.9 : 1
zoomScale: mouseArea.pressed ? root.pressedScale : 1
background: Item {
// very simple shadow for performance
@ -58,7 +57,7 @@ QuickSettingsDelegate {
}
Behavior on color {
ColorAnimation { duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.shortDuration : 0; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast }
}
}
}

View file

@ -6,7 +6,6 @@ import QtQuick.Layouts 1.1
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
/**
* Management/detail row shown in convergence mode. Two interaction zones:
@ -49,6 +48,9 @@ Item {
return Kirigami.ColorUtils.linearInterpolation(bg, fg, 0.1);
}
}
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property real pressedScale: MobileShell.Motion.pressScaleIn
function mixColor(base, overlay, ratio) {
return Qt.rgba(
@ -117,14 +119,14 @@ Item {
}
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast }
}
}
// Scale on press
property real zoomScale: (ShellSettings.Settings.animationsEnabled && toggleMouse.pressed) ? 0.9 : 1
property real zoomScale: toggleMouse.pressed ? root.pressedScale : 1
Behavior on zoomScale {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.OutExpo }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Press }
}
transform: Scale {
origin.x: togglePill.width / 2
@ -160,7 +162,7 @@ Item {
opacity: root.enabled ? 1.0 : 0.4
Behavior on width {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast }
}
}
}
@ -186,17 +188,13 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
// Hover/press highlight
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
radius: Kirigami.Units.cornerRadius
color: detailMouse.pressed ? Qt.rgba(Kirigami.Theme.textColor.r,
Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.06)
: detailMouse.containsMouse ? Qt.rgba(Kirigami.Theme.textColor.r,
Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.03)
: "transparent"
hovered: detailMouse.containsMouse
pressed: detailMouse.pressed
hoverOpacity: 0.03
pressedOpacity: 0.06
}
MouseArea {

View file

@ -26,6 +26,7 @@ QQC2.Popup {
padding: Kirigami.Units.smallSpacing
readonly property int popupAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int trayItemCount: trayList.count
function show() {
@ -147,17 +148,20 @@ QQC2.Popup {
anchors.leftMargin: Kirigami.Units.smallSpacing
anchors.rightMargin: Kirigami.Units.smallSpacing
radius: Kirigami.Units.cornerRadius
color: trayMouse.pressed ? Qt.rgba(Kirigami.Theme.textColor.r,
Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.08)
: trayMouse.containsMouse ? Qt.rgba(Kirigami.Theme.textColor.r,
Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.04)
: Kirigami.Theme.alternateBackgroundColor
color: Kirigami.Theme.alternateBackgroundColor
border.width: 1
border.color: Kirigami.ColorUtils.linearInterpolation(
Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, trayItem.itemActive ? 0.16 : 0.08)
opacity: trayItem.itemActive ? 1 : 0.72
MobileShell.MotionStateLayer {
anchors.fill: parent
radius: parent.radius
hovered: trayMouse.containsMouse
pressed: trayMouse.pressed
hoverOpacity: 0.04
pressedOpacity: 0.08
}
}
RowLayout {
@ -237,11 +241,11 @@ QQC2.Popup {
}
enter: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
NumberAnimation { property: "scale"; from: 0.9; to: 1; duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { property: "opacity"; from: 0; to: 1; type: MobileShell.Motion.EffectsFast }
MobileShell.MotionNumberAnimation { property: "scale"; from: 0.9; to: 1; type: MobileShell.Motion.EffectsFast }
}
exit: Transition {
NumberAnimation { property: "opacity"; from: 1; to: 0; duration: Kirigami.Units.shortDuration; easing.type: Easing.InCubic }
MobileShell.MotionNumberAnimation { property: "opacity"; from: 1; to: 0; type: MobileShell.Motion.StandardAccel; duration: popup.popupAnimationDuration }
}
QQC2.Overlay.modal: Rectangle {

View file

@ -0,0 +1,106 @@
// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
pragma Singleton
QtObject {
id: root
enum Type {
Press,
Standard,
StandardAccel,
StandardDecel,
Emphasized,
EmphasizedAccel,
EmphasizedDecel,
SpatialFast,
SpatialDefault,
SpatialSlow,
SpatialExtended,
SpatialVerySlow,
EffectsFast,
EffectsDefault,
EffectsSlow
}
readonly property bool enabled: ShellSettings.Settings.animationsEnabled
readonly property int pressDuration: enabled ? Math.round(Kirigami.Units.shortDuration / 2) : 0
readonly property int standardDuration: enabled ? Kirigami.Units.longDuration : 0
readonly property int emphasizedDuration: enabled ? Kirigami.Units.longDuration + Kirigami.Units.shortDuration : 0
readonly property int spatialFastDuration: enabled ? Kirigami.Units.shortDuration : 0
readonly property int spatialDefaultDuration: enabled ? Kirigami.Units.longDuration : 0
readonly property int spatialSlowDuration: enabled ? Kirigami.Units.veryLongDuration : 0
readonly property int spatialExtendedDuration: enabled ? Kirigami.Units.longDuration * 2 : 0
readonly property int spatialVerySlowDuration: enabled ? Kirigami.Units.longDuration * 4 : 0
readonly property int effectsFastDuration: enabled ? Kirigami.Units.shortDuration : 0
readonly property int effectsDefaultDuration: enabled ? Kirigami.Units.longDuration : 0
readonly property int effectsSlowDuration: enabled ? Kirigami.Units.veryLongDuration : 0
readonly property real pressScaleIn: enabled ? 0.94 : 1
readonly property real pressScaleOut: enabled ? 1.08 : 1
readonly property real previewPressScale: enabled ? 0.95 : 1
readonly property real hiddenScale: enabled ? 0.72 : 1
readonly property real closeScaleOut: enabled ? 0.9 : 1
function duration(type: int): int {
switch (type) {
case Motion.Press:
return pressDuration;
case Motion.Emphasized:
case Motion.EmphasizedAccel:
case Motion.EmphasizedDecel:
return emphasizedDuration;
case Motion.SpatialFast:
return spatialFastDuration;
case Motion.SpatialDefault:
return spatialDefaultDuration;
case Motion.SpatialSlow:
return spatialSlowDuration;
case Motion.SpatialExtended:
return spatialExtendedDuration;
case Motion.SpatialVerySlow:
return spatialVerySlowDuration;
case Motion.EffectsFast:
return effectsFastDuration;
case Motion.EffectsDefault:
return effectsDefaultDuration;
case Motion.EffectsSlow:
return effectsSlowDuration;
default:
return standardDuration;
}
}
function easing(type: int): int {
switch (type) {
case Motion.StandardAccel:
case Motion.EmphasizedAccel:
return Easing.InQuart;
case Motion.StandardDecel:
case Motion.EmphasizedDecel:
return Easing.OutQuart;
case Motion.Emphasized:
return Easing.OutQuint;
case Motion.SpatialFast:
case Motion.SpatialDefault:
case Motion.SpatialSlow:
case Motion.SpatialExtended:
case Motion.SpatialVerySlow:
return Easing.OutExpo;
case Motion.Press:
case Motion.EffectsFast:
case Motion.EffectsDefault:
case Motion.EffectsSlow:
return Easing.OutCubic;
default:
return Easing.InOutQuad;
}
}
}

View file

@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
ColorAnimation {
property int type: Motion.EffectsFast
duration: Motion.duration(type)
easing.type: Motion.easing(type)
}

View file

@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
NumberAnimation {
property int type: Motion.Standard
duration: Motion.duration(type)
easing.type: Motion.easing(type)
}

View file

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
import org.kde.kirigami as Kirigami
Item {
id: root
property bool hovered: false
property bool pressed: false
property bool active: false
property bool stateLayerEnabled: true
property color color: Kirigami.Theme.textColor
property color activeColor: Kirigami.Theme.highlightColor
property real hoverOpacity: 0.08
property real pressedOpacity: 0.14
property real activeOpacity: 0.12
property real activeHoverOpacity: 0.18
property real radius: Kirigami.Units.cornerRadius
readonly property real layerOpacity: {
if (!stateLayerEnabled) {
return 0;
}
if (pressed) {
return pressedOpacity;
}
if (active) {
return hovered ? activeHoverOpacity : activeOpacity;
}
return hovered ? hoverOpacity : 0;
}
Rectangle {
anchors.fill: parent
radius: root.radius
color: root.active ? root.activeColor : root.color
opacity: root.layerOpacity
Behavior on color {
MotionColorAnimation { type: Motion.EffectsFast }
}
Behavior on opacity {
MotionNumberAnimation { type: Motion.EffectsFast }
}
}
}

View file

@ -62,9 +62,9 @@ Item {
// for example, popup notifition when opening the popup notifition drawer
// in these incidents, we animate the color to prevent harsh transitions
Behavior on panelColor {
ColorAnimation {
duration: animate ? Kirigami.Units.veryLongDuration * 1.5 : 0
easing.type: Easing.OutExpo
MotionColorAnimation {
type: Motion.SpatialSlow
duration: animate ? Math.round(Motion.duration(type) * 1.5) : 0
}
}

View file

@ -3,6 +3,8 @@
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.state as MobileShellState
// Component to supplement the StartupFeedback window maximization animation for panel backgrounds.
@ -15,14 +17,16 @@ Rectangle {
property var maximizedTracker
readonly property bool isShowing: height > 0
readonly property int heightAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int autoClearDelay: heightAnimationDuration + Kirigami.Units.veryLongDuration
// Smooth animation for colored rectangle
NumberAnimation on height {
MobileShell.MotionNumberAnimation on height {
id: heightAnim
from: 0
to: root.fullHeight
duration: 200
easing.type: Easing.OutExpo
type: MobileShell.Motion.SpatialDefault
duration: root.heightAnimationDuration
}
// Auto-clear safety net.
@ -38,7 +42,7 @@ Rectangle {
// the original mobile behaviour while fixing the convergence path.
Timer {
id: autoClearTimer
interval: 600 // animation duration (200) + settle time
interval: root.autoClearDelay
repeat: false
onTriggered: {
if (!root.maximizedTracker || !root.maximizedTracker.showingWindow) {

View file

@ -7,7 +7,7 @@ import QtQuick.Effects
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
@ -39,6 +39,8 @@ Item {
id: window
property var startupFeedback: model.delegate
readonly property int simpleOpenDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int loadingIndicatorFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
visibility: Window.Maximized
flags: Qt.FramelessWindowHint
@ -62,7 +64,7 @@ Item {
backgroundParent.y = -realHeight/2 + startupFeedback.iconStartY - root.topMargin;
}
if (ShellSettings.Settings.animationsEnabled) {
if (MobileShell.Motion.enabled) {
openAnimComplex.restart();
} else {
openAnimSimple.restart();
@ -78,35 +80,35 @@ Item {
ParallelAnimation {
id: parallelAnim
property real animationDuration: Kirigami.Units.longDuration + Kirigami.Units.shortDuration
property real animationDuration: MobileShell.Motion.duration(MobileShell.Motion.Emphasized)
ScaleAnimator {
target: background
from: background.scale
to: 1
duration: parallelAnim.animationDuration
easing.type: Easing.OutCubic
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
}
ScaleAnimator {
target: iconParent
from: iconParent.scale
to: 1
duration: parallelAnim.animationDuration
easing.type: Easing.OutCubic
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
}
XAnimator {
target: backgroundParent
from: backgroundParent.x
to: 0
duration: parallelAnim.animationDuration
easing.type: Easing.OutCubic
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
}
YAnimator {
target: backgroundParent
from: backgroundParent.y
to: 0
duration: parallelAnim.animationDuration
easing.type: Easing.OutCubic
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
}
}
@ -134,13 +136,13 @@ Item {
}
}
NumberAnimation {
MobileShell.MotionNumberAnimation {
target: windowRoot
properties: "opacity"
from: 0
to: 1
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
type: MobileShell.Motion.EffectsDefault
duration: window.simpleOpenDuration
}
ScriptAction {
@ -212,7 +214,10 @@ Item {
opacity: 0
Behavior on opacity {
NumberAnimation {}
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsFast
duration: window.loadingIndicatorFadeDuration
}
}
implicitHeight: Kirigami.Units.iconSizes.smallMedium

View file

@ -4,6 +4,8 @@
import QtQuick
import QtQuick.Window
import org.kde.kirigami as Kirigami
import org.kde.plasma.plasmoid
import org.kde.taskmanager as TaskManager
@ -142,7 +144,9 @@ Item {
opacity: 0
property real scaleAmount: 1
readonly property real zoomScaleOut: 0.8
readonly property real zoomScaleOut: 0.9
readonly property int opacityAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int scaleAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
function zoomIn() {
// don't use check animationsEnabled here, so we ensure the scale and opacity is always 1 when disabled
@ -166,17 +170,18 @@ Item {
opacity = 0;
}
NumberAnimation on opacity {
MobileShell.MotionNumberAnimation on opacity {
id: opacityAnim
duration: 300
type: MobileShell.Motion.EffectsDefault
duration: itemContainer.opacityAnimationDuration
running: false
}
NumberAnimation on scaleAmount {
MobileShell.MotionNumberAnimation on scaleAmount {
id: scaleAnim
duration: 600
type: MobileShell.Motion.SpatialSlow
duration: itemContainer.scaleAnimationDuration
running: false
easing.type: Easing.OutExpo
}
function evaluateAnimChange() {

View file

@ -19,6 +19,7 @@ Controls.Drawer {
property MobileShell.MaskManager maskManager
required property bool horizontal
readonly property int previewAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
signal wallpaperSettingsRequested()
@ -100,15 +101,15 @@ Controls.Drawer {
padding: Kirigami.Units.largeSpacing - (wallpapersView.currentIndex === index ? Kirigami.Units.smallSpacing : 0)
property real scaleAmount: wallpapersView.currentIndex === index ? 0 : Kirigami.Units.smallSpacing
Behavior on scaleAmount {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsDefault
duration: imageWallpaperDrawer.previewAnimationDuration
}
}
Behavior on padding {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsDefault
duration: imageWallpaperDrawer.previewAnimationDuration
}
}

View file

@ -22,6 +22,7 @@ Controls.AbstractButton {
property int shrinkSize: 0
property alias iconSource: icon.source
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
MobileShell.HapticsEffect {
id: haptics
@ -56,10 +57,10 @@ Controls.AbstractButton {
}
}
NumberAnimation on opacity {
MobileShell.MotionNumberAnimation on opacity {
id: opacityAnimator
duration: Kirigami.Units.shortDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.Press
duration: button.pressAnimationDuration
onFinished: {
// animate the state back
if (rect.buttonHeld && opacityAnimator.to === 0) {

View file

@ -26,6 +26,9 @@ Window {
property int angle: 0
property string iconSource
property bool active: false
readonly property int buttonAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property real hiddenScale: MobileShell.Motion.hiddenScale
readonly property real pressedScale: MobileShell.Motion.pressScaleOut
signal triggered()
@ -82,7 +85,7 @@ Window {
// Hide the root window after the button disappearing animation finishes.
Timer {
id: hideButton
interval: Kirigami.Units.longDuration
interval: root.buttonAnimationDuration
repeat: false
onTriggered: if (!active) root.visible = false;
}
@ -101,20 +104,14 @@ Window {
height: root.size
opacity: root.active ? 1 : 0
property double scale: !root.active ? 0.5 : (button.pressed ? 1.5 : 1)
property double scale: !root.active ? root.hiddenScale : (button.pressed ? root.pressedScale : 1)
Behavior on scale {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.OutBack
}
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.StandardDecel }
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCirc
}
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.StandardDecel }
}
transform: Scale {
@ -133,12 +130,20 @@ Window {
Controls.AbstractButton {
id: button
anchors.fill: parent
hoverEnabled: true
MobileShell.HapticsEffect {
id: haptics
}
contentItem: Item {
MobileShell.MotionStateLayer {
anchors.fill: parent
radius: root.size
hovered: button.hovered
pressed: button.pressed
}
Kirigami.Icon {
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.small

View file

@ -28,6 +28,10 @@ Item {
property int popupWidth
property real openOffset
property bool isConvergence: false
readonly property int primaryAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.5)
readonly property int secondaryAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
readonly property int stackAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
readonly property int stackMomentumAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 0.5)
// In convergence the popup enters from the bottom-right corner
readonly property real effectiveOpenOffset: isConvergence
@ -54,7 +58,7 @@ Item {
// due to it not looking great to have a notification sliding up while another one is sliding down
// we use a timer so that the current notification can know to use "closeWithScale" instead
property Timer queueTimer: Timer {
interval: Kirigami.Units.veryLongDuration
interval: notificationPopup.secondaryAnimationDuration
running: true
onTriggered: {
visible = true;
@ -113,9 +117,9 @@ Item {
// animate the notifications entering and exiting the expanded drawer
property real fullOffsetAn: fullOpenOffset
Behavior on fullOffsetAn {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.5
easing.type: Easing.OutExpo
MobileShell.MotionNumberAnimation {
duration: notificationPopup.primaryAnimationDuration
type: MobileShell.Motion.SpatialSlow
}
}
@ -125,21 +129,21 @@ Item {
// animate this value so that the popup in some situations will not jump around
property real scaleOriginY: inPopupDrawer && !popupDrawerOpened ? popupNotifications.currentPopupHeight : Math.round(popupHeight / 2)
Behavior on scaleOriginY {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration
easing.type: Easing.OutExpo
MobileShell.MotionNumberAnimation {
duration: notificationPopup.secondaryAnimationDuration
type: MobileShell.Motion.SpatialSlow
}
}
// the vertical drag offset for the notification popup
// we drag is released, animate back to 0
property real dragOffset: 0
NumberAnimation on dragOffset {
MobileShell.MotionNumberAnimation on dragOffset {
id: dragOffsetAn
running: false
to: 0
duration: Kirigami.Units.veryLongDuration * 1.5
easing.type: Easing.OutExpo
type: MobileShell.Motion.SpatialSlow
duration: notificationPopup.primaryAnimationDuration
}
// if the popup height ever changes, update the notification below with new height
@ -385,21 +389,21 @@ Item {
}
}
Behavior on drawerScale {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25
easing.type: Easing.OutQuint
MobileShell.MotionNumberAnimation {
duration: notificationPopup.stackAnimationDuration
type: MobileShell.Motion.Emphasized
}
}
Behavior on drawerAddedOffset {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25
easing.type: Easing.OutQuint
MobileShell.MotionNumberAnimation {
duration: notificationPopup.stackAnimationDuration
type: MobileShell.Motion.Emphasized
}
}
Behavior on drawerOpacity {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration * 1.25
easing.type: Easing.OutQuint
MobileShell.MotionNumberAnimation {
duration: notificationPopup.stackAnimationDuration
type: MobileShell.Motion.Emphasized
}
}
@ -487,27 +491,30 @@ Item {
if (notificationPopup.closedWithSwipe || (topPopup && popupClosing && popupBelow)) {
// make sure the speed it faster when closed with a swipe or if there is a popup below when closing
// as to make sure the speed feels comparable with the easing type is set to linear
return Kirigami.Units.veryLongDuration * 0.5;
return notificationPopup.stackMomentumAnimationDuration;
} else {
return Kirigami.Units.veryLongDuration * 1.25;
return notificationPopup.stackAnimationDuration;
}
}
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
MobileShell.MotionNumberAnimation {
properties: "offset"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration
}
PropertyAnimation {
MobileShell.MotionNumberAnimation {
properties: "scale"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration
}
PropertyAnimation {
MobileShell.MotionNumberAnimation {
properties: "popupOpacity"
type: MobileShell.Motion.SpatialSlow
easing.type: notificationItem.notificationEasing
duration: notificationItem.notificationDuration
}

View file

@ -36,6 +36,7 @@ Window {
// Margin between popup and screen edge in convergence mode; used in both
// the delegate x position and the input-region calculation so they stay in sync.
readonly property real convergencePopupMargin: Kirigami.Units.gridUnit * 2
readonly property int popupAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.5)
property var keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone
LayerShell.Window.scope: "notification"
@ -60,9 +61,9 @@ Window {
readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05)
color: popupDrawerOpened && visible ? backgroundColor : "transparent"
Behavior on color {
ColorAnimation {
duration: Kirigami.Units.veryLongDuration * 1.5
easing.type: Easing.OutExpo
MobileShell.MotionColorAnimation {
duration: notificationPopupManager.popupAnimationDuration
type: MobileShell.Motion.SpatialSlow
}
}
@ -82,7 +83,7 @@ Window {
// hide on timeout to give time to finish animations
Timer {
id: hideTimeout
interval: Kirigami.Units.veryLongDuration * 1.5
interval: notificationPopupManager.popupAnimationDuration
repeat: false
onTriggered: if (notifications.count == 0) notificationPopupManager.visible = false;
}
@ -153,12 +154,12 @@ Window {
resetContentY.running = true;
}
NumberAnimation on contentY {
MobileShell.MotionNumberAnimation on contentY {
id: resetContentY
running: false
to: 0
duration: Kirigami.Units.veryLongDuration * 1.5
easing.type: Easing.OutExpo
type: MobileShell.Motion.SpatialSlow
duration: notificationPopupManager.popupAnimationDuration
}
MouseArea {

View file

@ -16,6 +16,7 @@ import org.kde.kquickcontrolsaddons
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume
import "icon.js" as Icon
@ -24,6 +25,8 @@ import "icon.js" as Icon
Controls.AbstractButton {
id: baseItem
hoverEnabled: true
property string label
property alias listIcon: clientIcon.source
property string type // sink, source, source-output
@ -46,9 +49,15 @@ Controls.AbstractButton {
background: Rectangle {
radius: Kirigami.Units.cornerRadius
color: (baseItem.down)
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.3)
: 'transparent'
color: "transparent"
MobileShell.MotionStateLayer {
anchors.fill: parent
radius: parent.radius
hovered: baseItem.hovered
pressed: baseItem.down
active: baseItem.selected
}
}
contentItem: RowLayout {
@ -193,12 +202,11 @@ Controls.AbstractButton {
SequentialAnimation {
id: seqAnimation
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: toAnimation
target: slider
property: "to"
duration: Kirigami.Units.shortDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.EffectsFast
}
ScriptAction {
script: slider.updateVolume()

View file

@ -39,6 +39,7 @@ Window {
Kirigami.Theme.inherit: false
color: "transparent"
readonly property int popupAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
function showOverlay() {
if (cards.state == "closed") {
@ -116,8 +117,10 @@ Window {
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
properties: "offset"; easing.type: cards.state == "open" ? Easing.OutQuint : Easing.InQuint; duration: Kirigami.Units.veryLongDuration * 1.25
MobileShell.MotionNumberAnimation {
properties: "offset"
type: cards.state == "open" ? MobileShell.Motion.Emphasized : MobileShell.Motion.EmphasizedAccel
duration: window.popupAnimationDuration
}
}
ScriptAction {

View file

@ -35,6 +35,7 @@ Window {
LayerShell.Window.exclusionZone: -1
readonly property color backgroundColor: Qt.darker(Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95), 1.05)
readonly property int overlayAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow) * 1.25)
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
Kirigami.Theme.inherit: false
@ -83,7 +84,7 @@ Window {
pressDelay: 50
property real offset: -Kirigami.Units.gridUnit
property real scale: 0.95
property real cardScale: 0.95
state: "closed"
@ -94,7 +95,7 @@ Window {
target: flickable; offset: 0
}
PropertyChanges {
target: flickable; scale: 1.0
target: flickable; cardScale: 1.0
}
PropertyChanges {
target: flickable; opacity: 1.0
@ -109,7 +110,7 @@ Window {
target: flickable; offset: -Kirigami.Units.gridUnit * 3
}
PropertyChanges {
target: flickable; scale: 0.95
target: flickable; cardScale: 0.95
}
PropertyChanges {
target: flickable; opacity: 0.0
@ -123,17 +124,17 @@ Window {
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
properties: "offset"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25
MobileShell.MotionNumberAnimation {
properties: "offset"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
}
PropertyAnimation {
properties: "scale"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25
MobileShell.MotionNumberAnimation {
properties: "cardScale"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
}
PropertyAnimation {
properties: "opacity"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25
MobileShell.MotionNumberAnimation {
properties: "opacity"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
}
PropertyAnimation {
properties: "color"; easing.type: Easing.OutQuint; duration: Kirigami.Units.veryLongDuration * 1.25
MobileShell.MotionColorAnimation {
properties: "color"; type: MobileShell.Motion.Emphasized; duration: window.overlayAnimationDuration
}
}
ScriptAction {
@ -172,7 +173,7 @@ Window {
Layout.topMargin: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: cards.width
scale: flickable.scale
scale: flickable.cardScale
}
PopupCard {
@ -180,7 +181,7 @@ Window {
Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: Kirigami.Units.gridUnit
scaleFactor: flickable.scale
scaleFactor: flickable.cardScale
contentItem: PlasmaComponents.ToolButton {
id: audioSettingsButton

View file

@ -12,6 +12,7 @@ import org.kde.kquickcontrolsaddons
import org.kde.plasma.components as PC3
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume
// Audio volume slider. Value represents desired volume level in
@ -21,6 +22,7 @@ PC3.Slider {
id: control
property VolumeObject volumeObject
readonly property real mutedOpacity: 0.55
// When muted, the whole slider will appear slightly faded, but remain
// functional and interactive.
@ -37,22 +39,20 @@ PC3.Slider {
}
Behavior on volume {
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: animate
duration: Kirigami.Units.shortDuration
easing.type: Easing.OutQuad
type: MobileShell.Motion.EffectsFast
}
}
// When a maximum volume limit is raised/lower, animate the change.
Behavior on to {
NumberAnimation {
duration: Kirigami.Units.shortDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsFast
}
}
opacity: muted ? 0.5 : 1
opacity: muted ? mutedOpacity : 1
// Prevents the groove from showing through the handle
layer.enabled: opacity < 1

View file

@ -37,7 +37,7 @@ Item {
property color backgroundColor: "transparent"
Behavior on backgroundColor {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast }
}
/**
@ -101,7 +101,7 @@ Item {
opacity: ShellSettings.Settings.convergenceModeEnabled && statusBarHover.hovered ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast }
}
}
@ -240,7 +240,7 @@ Item {
opacity: ShellSettings.Settings.convergenceModeEnabled ? (statusBarHover.hovered ? 0.6 : 0.2) : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast }
}
}
}

View file

@ -7,20 +7,22 @@
import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
Item {
id: taskIcon
width: parent.height
height: width
readonly property int opacityAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
// Hide ApplicationStatus and Passive items
opacity: (model.category !== "ApplicationStatus" && model.status !== "Passive") ? 1 : 0
onOpacityChanged: visible = opacity
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsDefault
duration: taskIcon.opacityAnimationDuration
}
}

View file

@ -17,9 +17,18 @@ import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.milou as Milou
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
MouseArea {
id: root
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
readonly property color fieldColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
readonly property color fieldActiveColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.20)
readonly property color resultHoverColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.16)
readonly property color resultPressedColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
onClicked: root.requestedClose(false)
function requestFocus() {
@ -54,9 +63,9 @@ MouseArea {
background: Rectangle {
radius: Kirigami.Units.cornerRadius
color: Qt.rgba(255, 255, 255, (queryField.hovered || queryField.focus) ? 0.2 : 0.1)
color: (queryField.hovered || queryField.focus) ? root.fieldActiveColor : root.fieldColor
Behavior on color { ColorAnimation {} }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast } }
}
Kirigami.Theme.inherit: false
@ -66,8 +75,8 @@ MouseArea {
bottomPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
placeholderText: i18nc("@info:placeholder", "Search…")
placeholderTextColor: Qt.rgba(255, 255, 255, 0.8)
color: 'white'
placeholderTextColor: Kirigami.Theme.disabledTextColor
color: Kirigami.Theme.textColor
inputMethodHints: Qt.ImhNoPredictiveText // don't need to press "enter" to update text
font.weight: Font.Bold
@ -133,7 +142,7 @@ MouseArea {
type: Kirigami.Heading.Primary
text: sectionHeader.section
elide: Text.ElideRight
color: 'white'
color: Kirigami.Theme.textColor
// we override the Primary type's font weight (DemiBold) for Bold for contrast with small text
font.weight: Font.Bold
@ -176,7 +185,7 @@ MouseArea {
Rectangle {
anchors.fill: parent
radius: Kirigami.Units.cornerRadius
color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.3) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.1) : "transparent")
color: delegate.pressed ? root.resultPressedColor : (delegate.containsMouse ? root.resultHoverColor : "transparent")
}
RowLayout {
@ -211,7 +220,7 @@ MouseArea {
maximumLineCount: 1
elide: Text.ElideRight
text: typeof modelData !== "undefined" ? modelData : model.display
color: "white"
color: Kirigami.Theme.textColor
font.pointSize: Kirigami.Theme.defaultFont.pointSize
}
@ -224,7 +233,7 @@ MouseArea {
maximumLineCount: 1
elide: Text.ElideRight
text: model.subtext || ""
color: "white"
color: Kirigami.Theme.textColor
opacity: 0.8
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 0.8)

View file

@ -32,9 +32,9 @@ Item {
implicitHeight: visible ? padding * 2 + contentHeight : 0
Behavior on implicitHeight {
NumberAnimation {
duration: implicitHeight == 0 ? 0 : Kirigami.Units.longDuration
easing.type: Easing.OutQuart
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.StandardDecel
duration: implicitHeight == 0 ? 0 : MobileShell.Motion.duration(type)
}
}

View file

@ -68,6 +68,8 @@ Item {
* The current drag offset for this notification.
*/
property real dragOffset: 0
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property int veryLongAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
signal tapped()
signal dismissRequested()
@ -84,10 +86,10 @@ Item {
implicitHeight: contentParent.implicitHeight
NumberAnimation on dragOffset {
MobileShell.MotionNumberAnimation on dragOffset {
id: dragAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
type: MobileShell.Motion.StandardDecel
duration: root.longAnimationDuration
onFinished: {
if (to !== 0) {
root.dismissRequested();
@ -112,9 +114,9 @@ Item {
implicitHeight: inPopupDrawer ? currentPopupHeight : contentParent.implicitHeight
Behavior on implicitHeight {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration
easing.type: Easing.OutExpo
MobileShell.MotionNumberAnimation {
duration: root.veryLongAnimationDuration
type: MobileShell.Motion.SpatialSlow
}
}
@ -129,9 +131,9 @@ Item {
opacity: closeTimerRunning ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.OutQuad
MobileShell.MotionNumberAnimation {
duration: root.longAnimationDuration
type: MobileShell.Motion.StandardDecel
}
}

View file

@ -10,12 +10,14 @@ import QtQuick.Layouts 1.1
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell
Item {
id: actionContainer
required property BaseNotificationItem notification
property bool popupNotification: false
readonly property int transitionDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
implicitHeight: Math.max(actionFlow.implicitHeight, replyLoader.height)
visible: actionRepeater.count > 0
@ -31,9 +33,9 @@ Item {
opacity: replyLoader.active ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
duration: actionContainer.transitionDuration
type: MobileShell.Motion.Standard
}
}
@ -94,15 +96,15 @@ Item {
property bool replying: false
Behavior on x {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
duration: actionContainer.transitionDuration
type: MobileShell.Motion.Standard
}
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
duration: actionContainer.transitionDuration
type: MobileShell.Motion.Standard
}
}

View file

@ -31,6 +31,7 @@ BaseNotificationItem {
property bool inLockScreen: false
property int panelType: MobileShell.PanelBackground.PanelType.Drawer
readonly property int popupFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
signal dragStart()
signal dragEnd()
@ -69,9 +70,9 @@ BaseNotificationItem {
opacity: notificationItem.inPopupDrawer ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.veryLongDuration
easing.type: Easing.OutExpo
MobileShell.MotionNumberAnimation {
duration: notificationItem.popupFadeDuration
type: MobileShell.Motion.SpatialSlow
}
}

View file

@ -14,7 +14,6 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.clock
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents3
@ -190,7 +189,7 @@ Item {
property NotificationItem pendingNotificationWithAction: null
readonly property int animationDuration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
readonly property int animationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
// If a screen overflow occurs, fix height in order to maintain tool buttons in place.
readonly property bool listOverflowing: listHeight + spacing >= root.height
@ -271,11 +270,11 @@ Item {
// Run every time an item is visually added to the list, thus when `Show n more` button is clicked as well.
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: list.animationDuration }
MobileShell.MotionNumberAnimation { property: "opacity"; from: 0; to: 1; duration: list.animationDuration; type: MobileShell.Motion.Standard }
}
// Run every time an item is displaced, such as when the order is scrambled due to a group expansion.
displaced: Transition {
NumberAnimation { properties: "y"; duration: list.animationDuration }
MobileShell.MotionNumberAnimation { properties: "y"; duration: list.animationDuration; type: MobileShell.Motion.Standard }
}
function isRowExpanded(row) {
@ -325,7 +324,7 @@ Item {
// We have to do this here in order to control the animation before the item is completely removed
ListView.onRemove: SequentialAnimation {
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: true }
NumberAnimation { target: delegateLoader; property: "opacity"; to: 0.0; duration: list.animationDuration }
MobileShell.MotionNumberAnimation { target: delegateLoader; property: "opacity"; to: 0.0; duration: list.animationDuration; type: MobileShell.Motion.Standard }
PropertyAction { target: delegateLoader; property: "ListView.delayRemove"; value: false }
}
@ -420,7 +419,7 @@ Item {
to: "VISIBLE"
SequentialAnimation {
PauseAnimation { duration: list.animationDuration * 2 }
NumberAnimation { properties: "opacity"; duration: list.animationDuration }
MobileShell.MotionNumberAnimation { properties: "opacity"; duration: list.animationDuration; type: MobileShell.Motion.Standard }
}
}

View file

@ -48,6 +48,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
Q_EMIT gamingDismissHintEnabledChanged();
Q_EMIT dynamicTilingEnabledChanged();
Q_EMIT dynamicTilingWindowRequestChanged();
Q_EMIT dynamicTilingWindowStateChanged();
Q_EMIT snapLayoutsEnabledChanged();
Q_EMIT allowLogoutChanged();
}
@ -326,6 +327,50 @@ void MobileShellSettings::requestDynamicTilingWindowAction(const QString &window
Q_EMIT dynamicTilingWindowRequestChanged();
}
QStringList MobileShellSettings::dynamicTilingMaximizedWindowIds() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("dynamicTilingMaximizedWindowIds", QStringList{});
}
int MobileShellSettings::dynamicTilingWindowStateSerial() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("dynamicTilingWindowStateSerial", 0);
}
bool MobileShellSettings::isDynamicTilingWindowMaximized(const QString &windowId) const
{
if (windowId.isEmpty()) {
return false;
}
return dynamicTilingMaximizedWindowIds().contains(windowId);
}
void MobileShellSettings::reportDynamicTilingWindowState(const QStringList &maximizedWindowIds)
{
QStringList normalizedIds;
for (const QString &windowId : maximizedWindowIds) {
if (!windowId.isEmpty() && !normalizedIds.contains(windowId)) {
normalizedIds.push_back(windowId);
}
}
normalizedIds.sort(Qt::CaseSensitive);
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
if (group.readEntry("dynamicTilingMaximizedWindowIds", QStringList{}) == normalizedIds) {
return;
}
const int serial = group.readEntry("dynamicTilingWindowStateSerial", 0) + 1;
group.writeEntry("dynamicTilingMaximizedWindowIds", normalizedIds, KConfigGroup::Notify);
group.writeEntry("dynamicTilingWindowStateSerial", serial, KConfigGroup::Notify);
m_config->sync();
Q_EMIT dynamicTilingWindowStateChanged();
}
bool MobileShellSettings::snapLayoutsEnabled() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};

View file

@ -11,6 +11,7 @@
#include <KSharedConfig>
#include <QDBusConnection>
#include <QObject>
#include <QStringList>
#include <qqmlregistration.h>
/**
@ -62,6 +63,8 @@ class MobileShellSettings : public QObject
Q_PROPERTY(QString dynamicTilingWindowRequestAction READ dynamicTilingWindowRequestAction NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(QString dynamicTilingWindowRequestId READ dynamicTilingWindowRequestId NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(int dynamicTilingWindowRequestSerial READ dynamicTilingWindowRequestSerial NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(QStringList dynamicTilingMaximizedWindowIds READ dynamicTilingMaximizedWindowIds NOTIFY dynamicTilingWindowStateChanged)
Q_PROPERTY(int dynamicTilingWindowStateSerial READ dynamicTilingWindowStateSerial NOTIFY dynamicTilingWindowStateChanged)
// Snap layout picker — only meaningful in convergence mode when dynamic tiling is off.
Q_PROPERTY(bool snapLayoutsEnabled READ snapLayoutsEnabled WRITE setSnapLayoutsEnabled NOTIFY snapLayoutsEnabledChanged)
@ -295,6 +298,10 @@ public:
QString dynamicTilingWindowRequestId() const;
int dynamicTilingWindowRequestSerial() const;
Q_INVOKABLE void requestDynamicTilingWindowAction(const QString &windowId, const QString &action);
QStringList dynamicTilingMaximizedWindowIds() const;
int dynamicTilingWindowStateSerial() const;
Q_INVOKABLE bool isDynamicTilingWindowMaximized(const QString &windowId) const;
Q_INVOKABLE void reportDynamicTilingWindowState(const QStringList &maximizedWindowIds);
/**
* Whether the SHIFT snap layout picker is enabled.
@ -354,6 +361,7 @@ Q_SIGNALS:
void gamingDismissHintEnabledChanged();
void dynamicTilingEnabledChanged();
void dynamicTilingWindowRequestChanged();
void dynamicTilingWindowStateChanged();
void snapLayoutsEnabledChanged();
void allowLogoutChanged();
void lockscreenLeftButtonActionChanged();

View file

@ -31,7 +31,9 @@ ApplicationListModel::ApplicationListModel(HomeScreen *parent)
m_reloadAppsTimer->setInterval(100ms);
connect(m_reloadAppsTimer, &QTimer::timeout, this, &ApplicationListModel::sycocaDbChanged);
connect(KSycoca::self(), &KSycoca::databaseChanged, m_reloadAppsTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
if (!qEnvironmentVariableIsSet("SHIFT_PREVIEW_DISABLE_SYCOCA_WATCH")) {
connect(KSycoca::self(), &KSycoca::databaseChanged, m_reloadAppsTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
}
// initialize wayland window checking
KWayland::Client::ConnectionThread *connection = KWayland::Client::ConnectionThread::fromApplication(this);

View file

@ -32,6 +32,7 @@ MobileShell.GridView {
property real headerHeight
readonly property int reservedSpaceForLabel: folio.HomeScreenState.pageDelegateLabelHeight
readonly property int scrollBarAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialExtended)
readonly property real effectiveContentWidth: width - leftMargin - rightMargin
readonly property real horizontalMargin: Math.round(width * 0.05)
@ -139,8 +140,8 @@ MobileShell.GridView {
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.longDuration * 2
easing.type: Easing.InOutQuad
duration: root.scrollBarAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Standard)
}
}

View file

@ -8,6 +8,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
import './delegate'
@ -64,7 +65,7 @@ Item {
Kirigami.Theme.textColor.b,
(searchField.hovered || searchField.focus) ? 0.2 : 0.1)
Behavior on color { ColorAnimation {} }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast } }
}
topPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing

View file

@ -22,6 +22,7 @@ Item {
height: folio.HomeScreenState.pageCellHeight
readonly property real dropAnimationRunning: dragXAnim.running || dragYAnim.running
readonly property int dropAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
// 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
@ -38,11 +39,11 @@ Item {
}
// animate drop x
NumberAnimation on x {
MobileShell.MotionNumberAnimation on x {
id: dragXAnim
type: MobileShell.Motion.EffectsDefault
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
duration: root.dropAnimationDuration
onFinished: {
root.visible = false;
root.setXBinding();
@ -50,11 +51,11 @@ Item {
}
// animate drop y
NumberAnimation on y {
MobileShell.MotionNumberAnimation on y {
id: dragYAnim
type: MobileShell.Motion.EffectsDefault
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
duration: root.dropAnimationDuration
onFinished: {
root.visible = false;
root.setYBinding();
@ -66,8 +67,8 @@ Item {
id: scaleAnim
to: 0
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutCubic
duration: root.dropAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
Connections {

View file

@ -35,20 +35,22 @@ MouseArea {
readonly property bool convergenceMode: ShellSettings.Settings.convergenceModeEnabled
readonly property bool showRunningTasks: convergenceMode && !suppressRunningTasks
readonly property int totalItemCount: repeater.count + (showRunningTasks ? taskRepeater.count : 0)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
// In convergence mode, size icons to fit the dock bar instead of using page grid cells
property real dockCellWidth: convergenceMode ? root.height : folio.HomeScreenState.pageCellWidth
property real dockCellHeight: convergenceMode ? root.height : folio.HomeScreenState.pageCellHeight
Behavior on dockCellWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on dockCellHeight { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on dockCellWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on dockCellHeight { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
// Navigation buttons width (used to offset center positioning)
property real navButtonWidth: convergenceMode ? root.height : 0
property real dockItemInset: convergenceMode ? Math.max(2, Kirigami.Units.smallSpacing / 2) : 0
property real dockIconSize: Math.min(root.height * 0.56, Kirigami.Units.iconSizes.large)
Behavior on navButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on dockItemInset { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on dockIconSize { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on navButtonWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on dockItemInset { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on dockIconSize { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
function dockItemColor(pressed, hovered, active) {
if (pressed) {
@ -67,7 +69,7 @@ MouseArea {
readonly property bool showSpacer: showRunningTasks && repeater.count > 0 && taskRepeater.count > 0
property real spacerWidth: showSpacer ? Kirigami.Units.largeSpacing * 2 : 0
Behavior on spacerWidth {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration }
}
// Thumbnail popup hover tracking
@ -102,10 +104,10 @@ MouseArea {
readonly property real dockCenterX: convergenceMode
? leftControlsWidth + (root.width - leftControlsWidth - rightControlsWidth) / 2
: root.width / 2
Behavior on pagerButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on desktopButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on trashButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on searchButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on pagerButtonWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on desktopButtonWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on trashButtonWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on searchButtonWidth { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
property Item pendingDockToolTipItem: null
property Item activeDockToolTipItem: null
@ -177,6 +179,27 @@ MouseArea {
return result
}
function desktopIndexForId(desktopId) {
let ids = virtualDesktopInfo.desktopIds
if (!ids) {
return -1
}
for (let i = 0; i < ids.length; ++i) {
if (String(ids[i]) === String(desktopId)) {
return i
}
}
return -1
}
function dynamicTilingMoveToDesktopAction(desktopId) {
let index = root.desktopIndexForId(desktopId)
if (index < 0) {
return ""
}
return "move-to-desktop:" + String(desktopId) + "|" + String(index + 1)
}
function taskActivities(taskModel) {
let activities = taskModel.Activities
return activities ? activities : []
@ -294,7 +317,7 @@ MouseArea {
color: "transparent"
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Accessible.role: Accessible.Button
@ -313,15 +336,13 @@ MouseArea {
visible: homeButton.activeFocus
}
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(homeMouseArea.containsPress, homeMouseArea.containsMouse, false)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
hovered: homeMouseArea.containsMouse
pressed: homeMouseArea.containsPress
pressedOpacity: 0.18
}
Kirigami.Icon {
@ -361,7 +382,7 @@ MouseArea {
}
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Accessible.role: Accessible.Button
@ -385,15 +406,14 @@ MouseArea {
visible: desktopButton.activeFocus
}
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(desktopMouseArea.containsPress, desktopMouseArea.containsMouse, WindowPlugin.WindowUtil.isShowingDesktop)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
hovered: desktopMouseArea.containsMouse
pressed: desktopMouseArea.containsPress
active: WindowPlugin.WindowUtil.isShowingDesktop
pressedOpacity: 0.18
}
Kirigami.Icon {
@ -476,7 +496,7 @@ MouseArea {
color: "transparent"
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Accessible.role: Accessible.Button
@ -495,15 +515,13 @@ MouseArea {
visible: overviewButton.activeFocus
}
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(overviewMouseArea.containsPress, overviewMouseArea.containsMouse, false)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
hovered: overviewMouseArea.containsMouse
pressed: overviewMouseArea.containsPress
pressedOpacity: 0.18
}
Kirigami.Icon {
@ -539,7 +557,7 @@ MouseArea {
color: "transparent"
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Accessible.role: Accessible.Button
@ -563,15 +581,13 @@ MouseArea {
visible: searchButton.activeFocus
}
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(searchMouseArea.containsPress, searchMouseArea.containsMouse, false)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
hovered: searchMouseArea.containsMouse
pressed: searchMouseArea.containsPress
pressedOpacity: 0.18
}
Kirigami.Icon {
@ -638,15 +654,16 @@ MouseArea {
width: root.pagerButtonWidth
height: root.height
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: leftDesktopBtn.isCurrent || leftDesktopBtn.isDragTarget
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b,
leftPagerHover.containsMouse || leftDesktopBtn.isDragTarget ? 0.25 : 0.18)
: root.dockItemColor(leftPagerHover.containsPress, leftPagerHover.containsMouse, false)
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } }
hovered: leftPagerHover.containsMouse
pressed: leftPagerHover.containsPress
active: leftDesktopBtn.isCurrent || leftDesktopBtn.isDragTarget
pressedOpacity: 0.18
activeOpacity: 0.18
activeHoverOpacity: 0.25
}
PC3.Label {
@ -746,15 +763,16 @@ MouseArea {
width: root.pagerButtonWidth
height: root.height
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: rightDesktopBtn.isCurrent || rightDesktopBtn.isDragTarget
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b,
rightPagerHover.containsMouse || rightDesktopBtn.isDragTarget ? 0.25 : 0.18)
: root.dockItemColor(rightPagerHover.containsPress, rightPagerHover.containsMouse, false)
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } }
hovered: rightPagerHover.containsMouse
pressed: rightPagerHover.containsPress
active: rightDesktopBtn.isCurrent || rightDesktopBtn.isDragTarget
pressedOpacity: 0.18
activeOpacity: 0.18
activeHoverOpacity: 0.25
}
PC3.Label {
@ -875,7 +893,7 @@ MouseArea {
color: "transparent"
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Accessible.role: Accessible.Button
@ -891,14 +909,13 @@ MouseArea {
visible: trashButton.activeFocus
}
Rectangle {
MobileShell.MotionStateLayer {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(trashMouseArea.containsPress, trashMouseArea.containsMouse, false)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
hovered: trashMouseArea.containsMouse
pressed: trashMouseArea.containsPress
pressedOpacity: 0.18
}
Kirigami.Icon {
@ -1049,7 +1066,7 @@ MouseArea {
// get the normalized index position value from the center so we can animate it
property double fromCenterValue: model.index - (root.totalItemCount / 2)
Behavior on fromCenterValue {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration }
}
// multiply the 'fromCenterValue' by the cell size to get the actual position
@ -1070,7 +1087,7 @@ MouseArea {
}
Behavior on dragVisualShift {
enabled: root.dragReorderIndex !== -1 && delegate.index !== root.dragReorderIndex
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration }
}
property real taskPinVisualShift: root.taskPinCanDrop && delegate.index >= root.taskPinTargetIndex ? root.dockCellWidth : 0
@ -1426,10 +1443,10 @@ MouseArea {
visible: showing || fadeAnim.running
opacity: showing ? 1 : 0
Behavior on opacity {
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: fadeAnim
duration: Kirigami.Units.shortDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.EffectsFast
duration: root.shortAnimationDuration
}
}
@ -1674,8 +1691,15 @@ MouseArea {
readonly property bool dynamicTilingActive: root.convergenceMode && ShellSettings.Settings.dynamicTilingEnabled
readonly property bool showFreeGeometryActions: !taskDelegate.isGroupParent && !taskDelegate.dynamicTilingActive
readonly property bool canRequestDynamicTiling: taskDelegate.dynamicTilingActive && !taskDelegate.isGroupParent && root.taskWindowId(taskDelegate.model) !== ""
readonly property int dynamicTilingWindowStateSerial: ShellSettings.Settings.dynamicTilingWindowStateSerial
readonly property bool dynamicTilingMaximized: taskDelegate.canRequestDynamicTiling
&& taskDelegate.dynamicTilingWindowStateSerial >= 0
&& ShellSettings.Settings.isDynamicTilingWindowMaximized(root.taskWindowId(taskDelegate.model))
readonly property bool canChangeVirtualDesktops: taskDelegate.model.IsVirtualDesktopsChangeable === true
readonly property bool canChangeActivities: activityInfo.numberOfRunningActivities > 1 && !taskDelegate.isGroupParent
readonly property bool dynamicTilingAllActivities: taskDelegate.canRequestDynamicTiling && root.taskActivities(taskDelegate.model).length === 0
readonly property bool canShowActivityScopeAction: taskDelegate.canChangeActivities && (!taskDelegate.canRequestDynamicTiling || taskDelegate.dynamicTilingAllActivities)
readonly property bool canShowActivityMoveActions: taskDelegate.canChangeActivities && !taskDelegate.canRequestDynamicTiling
Accessible.role: Accessible.Button
Accessible.name: taskDelegate.model.display || ""
@ -1699,6 +1723,25 @@ MouseArea {
}
}
function requestMoveToDesktop(desktopId) {
if (taskDelegate.canRequestDynamicTiling) {
let action = root.dynamicTilingMoveToDesktopAction(desktopId)
if (action !== "") {
ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), action)
return
}
}
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index), [desktopId])
}
function requestMoveToNewDesktop() {
if (taskDelegate.canRequestDynamicTiling) {
ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "move-to-new-desktop")
return
}
tasksModel.requestNewVirtualDesktop(tasksModel.makeModelIndex(taskDelegate.index))
}
Keys.onReturnPressed: taskDelegate.activateTask()
Keys.onEnterPressed: taskDelegate.activateTask()
Keys.onSpacePressed: taskDelegate.activateTask()
@ -1718,7 +1761,7 @@ MouseArea {
// Position after all favourites
property double fromCenterValue: (repeater.count + taskDelegate.index) - (root.totalItemCount / 2)
Behavior on fromCenterValue {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration }
}
readonly property int centerPosition: (isLocationBottom ? root.dockCellWidth : root.dockCellHeight) * fromCenterValue
@ -1740,7 +1783,7 @@ MouseArea {
color: root.dockItemColor(taskMouseArea.containsPress, taskMouseArea.containsMouse, taskDelegate.model.IsActive === true)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -1758,6 +1801,22 @@ MouseArea {
active: taskMouseArea.containsMouse
}
Rectangle {
visible: opacity > 0
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: Kirigami.Units.smallSpacing
width: Kirigami.Units.smallSpacing * 3
height: Math.max(2, Math.round(Kirigami.Units.devicePixelRatio))
radius: height / 2
color: Kirigami.Theme.highlightColor
opacity: taskDelegate.dynamicTilingMaximized ? 0.95 : 0
Behavior on opacity {
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
DragHandler {
id: taskDragHandler
target: null
@ -1782,7 +1841,7 @@ MouseArea {
let finalCenterX = root.taskBaseX(taskDelegate.index) + root.dockCellWidth / 2 + root.taskPinDragOffset
let pagerDesktop = root.pagerButtonDesktopAt(finalCenterX)
if (pagerDesktop && taskDelegate.model.IsVirtualDesktopsChangeable === true) {
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index), [pagerDesktop])
taskDelegate.requestMoveToDesktop(pagerDesktop)
} else if (root.taskPinCanDrop && !folio.FavouritesModel.containsApplication(root.taskPinStorageId)) {
folio.FavouritesModel.addApplicationAt(root.taskPinTargetIndex, root.taskPinStorageId)
}
@ -1825,7 +1884,7 @@ MouseArea {
opacity: taskDelegate.model.IsActive === true ? 1.0 : 0.45
Behavior on width {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
}
@ -1922,6 +1981,15 @@ MouseArea {
onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "tile")
}
PC3.MenuItem {
icon.name: taskDelegate.dynamicTilingMaximized ? "window-restore" : "window-maximize"
text: taskDelegate.dynamicTilingMaximized ? i18n("Restore") : i18n("Maximize")
visible: taskDelegate.canRequestDynamicTiling
height: visible ? implicitHeight : 0
enabled: taskDelegate.model.IsMaximizable === true
onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "maximize-toggle")
}
PC3.MenuItem {
icon.name: "transform-move"
text: i18n("Move")
@ -1992,10 +2060,18 @@ MouseArea {
PC3.MenuItem {
icon.name: "virtual-desktops"
text: taskDelegate.model.IsOnAllVirtualDesktops ? i18n("Show Only on Current Desktop") : i18n("Show on All Desktops")
visible: taskDelegate.canChangeVirtualDesktops && virtualDesktopInfo.numberOfDesktops > 1
visible: taskDelegate.canChangeVirtualDesktops
&& virtualDesktopInfo.numberOfDesktops > 1
&& (!taskDelegate.dynamicTilingActive || taskDelegate.model.IsOnAllVirtualDesktops === true)
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index),
taskDelegate.model.IsOnAllVirtualDesktops ? [virtualDesktopInfo.currentDesktop] : [])
onClicked: {
if (taskDelegate.dynamicTilingActive && taskDelegate.model.IsOnAllVirtualDesktops === true) {
taskDelegate.requestMoveToDesktop(virtualDesktopInfo.currentDesktop)
return
}
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index),
taskDelegate.model.IsOnAllVirtualDesktops ? [virtualDesktopInfo.currentDesktop] : [])
}
}
Instantiator {
@ -2003,8 +2079,7 @@ MouseArea {
delegate: PC3.MenuItem {
required property var modelData
text: i18n("Move to %1", root.pagerDesktopNameForId(modelData))
onTriggered: tasksModel.requestVirtualDesktops(
tasksModel.makeModelIndex(taskDelegate.index), [modelData])
onTriggered: taskDelegate.requestMoveToDesktop(modelData)
}
onObjectAdded: (idx, obj) => taskContextMenu.insertItem(taskContextMenu.count, obj)
onObjectRemoved: (idx, obj) => taskContextMenu.removeItem(obj)
@ -2014,25 +2089,25 @@ MouseArea {
text: i18n("Move to New Desktop")
visible: taskDelegate.canChangeVirtualDesktops
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestNewVirtualDesktop(tasksModel.makeModelIndex(taskDelegate.index))
onClicked: taskDelegate.requestMoveToNewDesktop()
}
Controls.MenuSeparator {
visible: taskDelegate.canChangeActivities
visible: taskDelegate.canShowActivityScopeAction || taskDelegate.canShowActivityMoveActions
height: visible ? implicitHeight : 0
}
PC3.MenuItem {
icon.name: "activities"
text: root.taskActivities(taskDelegate.model).length === 0 ? i18n("Show Only on Current Activity") : i18n("Show on All Activities")
visible: taskDelegate.canChangeActivities
visible: taskDelegate.canShowActivityScopeAction
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestActivities(tasksModel.makeModelIndex(taskDelegate.index),
root.taskActivities(taskDelegate.model).length === 0 ? [activityInfo.currentActivity] : [])
}
Instantiator {
model: taskDelegate.canChangeActivities ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : []
model: taskDelegate.canShowActivityMoveActions ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : []
delegate: PC3.MenuItem {
required property var modelData
icon.name: activityInfo.activityIcon(modelData)

View file

@ -25,6 +25,9 @@ Folio.DelegateTouchArea {
property real folderPositionY
property Folio.FolioApplicationFolder folder: folio.HomeScreenState.currentFolder
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property color folderFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.24)
MobileShell.HapticsEffect {
id: haptics
@ -83,7 +86,7 @@ Folio.DelegateTouchArea {
opacity: (root.opacity === 1) ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -177,7 +180,7 @@ Folio.DelegateTouchArea {
Rectangle {
id: folderBackground
color: Qt.rgba(255, 255, 255, 0.3)
color: root.folderFeedbackColor
radius: Kirigami.Units.gridUnit
readonly property int gridLength: folio.HomeScreenState.folderGridLength
@ -282,9 +285,9 @@ Folio.DelegateTouchArea {
property double rowValue: model.rowIndex
property double pageValue: model.pageIndex
Behavior on columnValue { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } }
Behavior on rowValue { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } }
Behavior on pageValue { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } }
Behavior on columnValue { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on rowValue { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
Behavior on pageValue { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.longAnimationDuration } }
// multiply the index values by the cell size to get the actual position
readonly property int columnPosition: cellWidth * columnValue

View file

@ -31,6 +31,7 @@ Item {
property real rightMargin: 0
property bool interactive: true
readonly property color favouritesBarScrimColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.14)
// non-widget drop animation
readonly property bool dropAnimationRunning: delegateDragItem.dropAnimationRunning || widgetDragItem.dropAnimationRunning
@ -350,7 +351,7 @@ Item {
Rectangle {
id: favouritesBarScrim
color: Qt.rgba(255, 255, 255, 0.2)
color: root.favouritesBarScrimColor
Component.onCompleted: maskManager.assignToMask(this)

View file

@ -24,6 +24,8 @@ Item {
property var pageModel
property var homeScreen
readonly property color editFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.24)
readonly property color dropFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
onActiveFocusChanged: {
if (activeFocus) {
@ -107,7 +109,7 @@ Item {
Rectangle {
id: settingsViewBackground
anchors.fill: parent
color: Qt.rgba(255, 255, 255, 0.2)
color: root.editFeedbackColor
opacity: folio.HomeScreenState.settingsOpenProgress
radius: Kirigami.Units.largeSpacing
}
@ -152,7 +154,7 @@ Item {
pageModel.canAddDelegate(dropPosition.pageRow, dropPosition.pageColumn, dropDelegate)
radius: Kirigami.Units.cornerRadius
color: Qt.rgba(255, 255, 255, 0.3)
color: root.dropFeedbackColor
x: dropPosition.pageColumn * folio.HomeScreenState.pageCellWidth
y: dropPosition.pageRow * folio.HomeScreenState.pageCellHeight

View file

@ -12,6 +12,7 @@ import "./delegate"
Item {
id: root
property Folio.HomeScreen folio
readonly property color placeholderColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
width: folio.HomeScreenState.pageCellWidth
height: folio.HomeScreenState.pageCellHeight
@ -24,7 +25,7 @@ Item {
// icon position placement
Rectangle {
id: loader
color: Qt.rgba(255, 255, 255, 0.3)
color: root.placeholderColor
radius: Kirigami.Units.cornerRadius
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom

View file

@ -6,6 +6,8 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.taskmanager as TaskManager
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
@ -16,6 +18,7 @@ Item {
required property var folio
readonly property bool hasTasks: allTasksModel.count > 0
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
property bool sortByName: false
property int dragTargetDesktopIndex: -1
property string pendingMoveTaskKey: ""
@ -44,6 +47,18 @@ Item {
return String(taskModel ? taskModel.AppId || "" : "") + "|" + String(taskModel ? taskModel.display || "" : "")
}
function taskWindowId(taskModel) {
const winIds = taskModel && taskModel.WinIdList ? taskModel.WinIdList : []
return winIds.length === 1 ? String(winIds[0]) : ""
}
function dynamicTilingMoveToDesktopAction(desktopId, desktopIndex) {
if (String(desktopId).length === 0 || desktopIndex < 0) {
return ""
}
return "move-to-desktop:" + String(desktopId) + "|" + String(desktopIndex + 1)
}
function markTaskMove(taskKey, desktopIndex) {
pendingMoveTaskKey = taskKey
pendingMoveTargetName = desktopName(desktopIndex)
@ -280,10 +295,10 @@ Item {
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.14)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Behavior on scale {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -371,11 +386,18 @@ Item {
readonly property int previewCount: Math.max(1, Math.min(2, winIds.length))
readonly property bool activeTask: model.IsActive === true
readonly property bool minimizedTask: model.IsMinimized === true
readonly property bool maximizedTask: model.IsMaximized === true
readonly property bool groupTask: model.IsGroupParent === true
readonly property bool desktopsChangeable: model.IsVirtualDesktopsChangeable === true
readonly property string storageId: root.taskStorageId(model)
readonly property string taskKey: root.taskKey(model)
readonly property string windowId: root.taskWindowId(model)
readonly property bool dynamicTilingActive: ShellSettings.Settings.convergenceModeEnabled && ShellSettings.Settings.dynamicTilingEnabled
readonly property bool canRequestDynamicTiling: dynamicTilingActive && !groupTask && windowId !== ""
readonly property int dynamicTilingWindowStateSerial: ShellSettings.Settings.dynamicTilingWindowStateSerial
readonly property bool dynamicTilingMaximized: canRequestDynamicTiling
&& dynamicTilingWindowStateSerial >= 0
&& ShellSettings.Settings.isDynamicTilingWindowMaximized(windowId)
readonly property bool maximizedTask: model.IsMaximized === true || dynamicTilingMaximized
readonly property bool pinned: storageId !== "" && root.folio.FavouritesModel.containsApplication(storageId)
readonly property bool pendingMove: root.pendingMoveTaskKey === taskKey
@ -403,6 +425,13 @@ Item {
}
root.markTaskMove(taskCard.taskKey, desktopIndex)
if (taskCard.canRequestDynamicTiling) {
const action = root.dynamicTilingMoveToDesktopAction(desktopId, desktopIndex)
if (action !== "") {
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, action)
return
}
}
tasksModel.requestVirtualDesktops(taskCard.modelIndex, [desktopId])
}
@ -509,7 +538,7 @@ Item {
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.12)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -663,7 +692,13 @@ Item {
iconName: taskCard.maximizedTask ? "window-restore" : "window-maximize"
toolTipText: taskCard.maximizedTask ? i18n("Restore") : i18n("Maximize")
enabled: !taskCard.groupTask
onTriggered: tasksModel.requestToggleMaximized(taskCard.modelIndex)
onTriggered: {
if (taskCard.canRequestDynamicTiling) {
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, "maximize-toggle")
return
}
tasksModel.requestToggleMaximized(taskCard.modelIndex)
}
}
RunningAppsPanelButton {

View file

@ -5,6 +5,7 @@ import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell
MouseArea {
id: button
@ -12,6 +13,7 @@ MouseArea {
property string iconName
property string toolTipText
property bool checked: false
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
signal triggered()
@ -43,7 +45,7 @@ MouseArea {
: "transparent"
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: button.shortAnimationDuration }
}
}

View file

@ -11,6 +11,7 @@ import org.kde.plasma.core as PlasmaCore
import org.kde.ksvg 1.0 as KSvg
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
import './delegate'
@ -31,6 +32,7 @@ Item {
&& folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
&& folio.HomeScreenState.dragState.dropDelegate.widget.visualApplet
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
readonly property int dropAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
visible: false
x: Math.round(folio.HomeScreenState.delegateDragX)
@ -52,8 +54,8 @@ Item {
XAnimator on x {
id: dragXAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
duration: root.dropAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
onFinished: {
root.visible = false;
root.widget = null;
@ -65,8 +67,8 @@ Item {
YAnimator on y {
id: dragYAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
duration: root.dropAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
onFinished: {
root.visible = false;
root.widget = null;

View file

@ -32,16 +32,19 @@ Folio.DelegateTouchArea {
// grow/shrink animation
property real scaleAmount: 1
property bool clickRequested: false
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property real pressedScale: MobileShell.Motion.pressScaleIn
function keyboardFocus() {
delegateWrapper.forceActiveFocus();
}
NumberAnimation on scaleAmount {
MobileShell.MotionNumberAnimation on scaleAmount {
id: shrinkAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
to: ShellSettings.Settings.animationsEnabled ? 0.8 : 1
duration: root.pressAnimationDuration
to: root.pressedScale
onFinished: {
if (!root.pressed) {
growAnim.restart();
@ -49,10 +52,11 @@ Folio.DelegateTouchArea {
}
}
NumberAnimation on scaleAmount {
MobileShell.MotionNumberAnimation on scaleAmount {
id: growAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
duration: root.pressAnimationDuration
to: 1
onFinished: {
if (root.clickRequested) {

View file

@ -26,6 +26,8 @@ AbstractDelegate {
property bool turnToFolder: false
property bool turnToFolderAnimEnabled: false
readonly property int turnToFolderAnimationDuration: root.turnToFolderAnimEnabled ? MobileShell.Motion.duration(MobileShell.Motion.Standard) : 0
readonly property color folderFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
function launchApp() {
if (!application) {
@ -59,7 +61,7 @@ AbstractDelegate {
Rectangle {
id: rect
radius: Kirigami.Units.cornerRadius
color: Qt.rgba(255, 255, 255, 0.3)
color: root.folderFeedbackColor
anchors.fill: parent
Component.onCompleted: {
@ -69,15 +71,15 @@ AbstractDelegate {
}
opacity: root.turnToFolder ? 1 : 0
property real scaleAmount: root.turnToFolder ? 1.2 : 1.0
property real scaleAmount: root.turnToFolder ? 1.08 : 1.0
Behavior on scaleAmount {
enabled: root.turnToFolderAnimEnabled
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Standard; duration: root.turnToFolderAnimationDuration }
}
Behavior on opacity {
enabled: root.turnToFolderAnimEnabled
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Standard; duration: root.turnToFolderAnimationDuration }
}
transform: Scale {
@ -95,10 +97,10 @@ AbstractDelegate {
anchors.fill: parent
source: root.application ? root.application.icon : ""
property real scaleAmount: root.turnToFolder ? 0.3 : 1.0
property real scaleAmount: root.turnToFolder ? 0.42 : 1.0
Behavior on scaleAmount {
enabled: root.turnToFolderAnimEnabled
NumberAnimation { duration: root.turnToFolderAnimEnabled ? Kirigami.Units.longDuration : 0; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Standard; duration: root.turnToFolderAnimationDuration }
}
transform: Scale {

View file

@ -19,6 +19,8 @@ Item {
property Folio.FolioApplicationFolder folder
property bool expandBackground: false
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
readonly property color folderFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
height: folio.FolioSettings.delegateIconSize
width: folio.FolioSettings.delegateIconSize
@ -26,7 +28,7 @@ Item {
Rectangle {
id: rect
radius: Kirigami.Units.cornerRadius
color: Qt.rgba(255, 255, 255, 0.3)
color: root.folderFeedbackColor
anchors.fill: parent
Component.onCompleted: {
@ -35,9 +37,9 @@ Item {
}
}
property real scaleAmount: root.expandBackground ? 1.2 : 1.0
property real scaleAmount: root.expandBackground ? 1.08 : 1.0
Behavior on scaleAmount { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } }
Behavior on scaleAmount { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Standard; duration: root.longAnimationDuration } }
transform: Scale {
origin.x: root.width / 2

View file

@ -28,6 +28,7 @@ Folio.WidgetContainer {
readonly property real bottomWidgetBackgroundPadding: widgetBackground.margins.bottom
readonly property real leftWidgetBackgroundPadding: widgetBackground.margins.left
readonly property real rightWidgetBackgroundPadding: widgetBackground.margins.right
readonly property color placeholderColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.28)
implicitWidth: (widget ? widget.gridWidth : 0) * folio.HomeScreenState.pageCellWidth
implicitHeight: (widget ? widget.gridHeight : 0) * folio.HomeScreenState.pageCellHeight
@ -94,7 +95,7 @@ Folio.WidgetContainer {
id: temporaryBackground
anchors.fill: parent
visible: root.widget && !root.widget.applet
color: Qt.rgba(255, 255, 255, 0.3)
color: root.placeholderColor
radius: Kirigami.Units.cornerRadius
}

View file

@ -8,6 +8,7 @@ import Qt5Compat.GraphicalEffects
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.ksvg 1.0 as KSvg
import org.kde.plasma.components 3.0 as PC3
@ -41,6 +42,7 @@ Item {
signal removeRequested()
signal closed()
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
function startOpen() {
// prevent config overlay if lock layout is enabled
@ -69,7 +71,7 @@ Item {
// in case this gets stuck open over the homescreen, just close on tap
onClicked: close()
NumberAnimation on opacity { id: configOverlayOpacityAnim; duration: Kirigami.Units.longDuration }
MobileShell.MotionNumberAnimation on opacity { id: configOverlayOpacityAnim; type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
function open() {
configOverlayOpacityAnim.to = 1;
@ -133,7 +135,7 @@ Item {
QQC2.Overlay.modal: Item {}
exit: Transition {
NumberAnimation { property: "opacity"; duration: Kirigami.Units.longDuration; from: 1.0; to: 0.0 }
MobileShell.MotionNumberAnimation { property: "opacity"; type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration; from: 1.0; to: 0.0 }
}
Connections {

View file

@ -37,6 +37,9 @@ Window {
readonly property string rightShoulderLabel: GamingShell.GamepadManager.buttonLabel(GamingShell.GamepadManager.ButtonRightShoulder)
readonly property string quickSettingsButtonLabel: GamingShell.GamepadManager.buttonLabel(GamingShell.GamepadManager.ButtonBack)
readonly property string searchButtonLabel: GamingShell.GamepadManager.buttonLabel(GamingShell.GamepadManager.ButtonStart)
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int launchFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.StandardAccel)
function pulsePrimaryGamepad(lowIntensity, highIntensity, durationMs) {
var pad = GamingShell.GamepadManager.primaryGamepad
@ -161,7 +164,7 @@ Window {
// Animate opacity on show/hide
opacity: visible ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
}
Connections {
@ -960,7 +963,7 @@ Window {
scale: parent.parent.parent.isCurrent ? 1.08 : 1.0
Behavior on scale {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -1116,7 +1119,7 @@ Window {
z: 100
Behavior on opacity {
NumberAnimation { duration: 250; easing.type: Easing.InQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.StandardAccel; duration: root.launchFadeDuration }
}
}

View file

@ -7,7 +7,7 @@ import QtQuick.Layouts
import QtQuick.Window
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.gamingshellplugin as GamingShell
import org.kde.layershell 1.0 as LayerShell
@ -23,6 +23,8 @@ Window {
property string toastMessage: ""
property bool toastError: false
readonly property bool toastActive: toastMessage.length > 0
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
// Most-recently-played game for quick resume. Populated from recentGames(1)
// and refreshed whenever the recent list changes.
@ -39,10 +41,10 @@ Window {
flags: Qt.FramelessWindowHint
Behavior on width {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
Behavior on height {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
LayerShell.Window.scope: "gaming-hud"
@ -57,7 +59,7 @@ Window {
opacity: showing ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
}
Timer {
@ -183,7 +185,7 @@ Window {
opacity: root.toastActive ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
RowLayout {

View file

@ -135,7 +135,7 @@ Item {
color: "black"
opacity: root.opened ? 0.4 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsDefault }
}
}
@ -150,7 +150,7 @@ Item {
x: root.opened ? root.width - width : root.width
Behavior on x {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault }
}
Kirigami.Theme.inherit: false

View file

@ -7,6 +7,7 @@ import QtQuick.Controls as QQC2
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.taskmanager as TaskManager
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
@ -17,6 +18,8 @@ Item {
implicitHeight: taskList.count > 0 ? column.implicitHeight : 0
readonly property bool hasTasks: taskList.count > 0
readonly property int taskCount: taskList.count
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Standard)
signal taskActivated()
signal moveDownRequested()
@ -59,7 +62,7 @@ Item {
}
Behavior on implicitHeight {
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Standard; duration: root.longAnimationDuration }
}
ColumnLayout {
@ -152,7 +155,7 @@ Item {
: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.06)
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
}
ColumnLayout {

View file

@ -34,6 +34,7 @@ import "./private"
ContainmentItem {
id: root
property var folio: root.plasmoid
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
// Tracks whether the Game Center grid is visible within gaming mode.
// If gaming mode is already enabled at startup, open it immediately so
@ -295,6 +296,8 @@ ContainmentItem {
// maximized. The reveal strip at the screen edge brings it back.
property real dockOffset: 0
readonly property real dockHeight: MobileShell.Constants.convergenceDockHeight
readonly property int dockAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int dockFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
// Height of the input-receive strip kept at the screen edge when
// the dock is hidden. Matches the navigation panel convention.
@ -365,14 +368,14 @@ ContainmentItem {
}
Behavior on dockOffset {
NumberAnimation {
easing.type: Easing.InOutCubic
duration: Kirigami.Units.longDuration
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.SpatialDefault
duration: dockOverlay.dockAnimationDuration
}
}
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: dockOverlay.dockFadeDuration }
}
Rectangle {
@ -847,7 +850,7 @@ ContainmentItem {
border.color: Qt.rgba(1, 1, 1, 0.2)
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
implicitWidth: hintText.implicitWidth + Kirigami.Units.gridUnit * 2

View file

@ -4,6 +4,7 @@
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import '../delegate'
@ -13,6 +14,8 @@ MouseArea {
width: 10 + touchPadding * 2
readonly property real touchPadding: 20
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow)
readonly property color resizeHandleColor: Kirigami.Theme.highlightColor
property int orientation
@ -79,14 +82,14 @@ MouseArea {
id: rect
anchors.fill: parent
anchors.margins: root.touchPadding
color: 'white'
color: root.resizeHandleColor
radius: width / 2
transform: Scale {
property real scaleFactor: root.pressed ? 1.2 : 1.0
property real scaleFactor: root.pressed ? MobileShell.Motion.pressScaleOut : 1.0
Behavior on scaleFactor {
NumberAnimation { duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutExpo }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsSlow; duration: root.pressAnimationDuration }
}
xScale: scaleFactor

View file

@ -7,6 +7,7 @@ import QtQuick.Controls as QQC2
import Qt5Compat.GraphicalEffects
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
import '../delegate'
@ -41,6 +42,8 @@ Item {
property int widgetGridHeightAfterDrag: 0
property var lockDrag: null
readonly property int resizeAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property color resizeAccentColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.85)
property alias handleContainer: handleContainer
@ -142,35 +145,35 @@ Item {
Item {
id: handleContainer
NumberAnimation on width {
MobileShell.MotionNumberAnimation on width {
id: widthAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.resizeAnimationDuration
}
NumberAnimation on height {
MobileShell.MotionNumberAnimation on height {
id: heightAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.resizeAnimationDuration
}
NumberAnimation on x {
MobileShell.MotionNumberAnimation on x {
id: xAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.resizeAnimationDuration
}
NumberAnimation on y {
MobileShell.MotionNumberAnimation on y {
id: yAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.resizeAnimationDuration
}
}
Rectangle {
id: resizeOutline
color: 'transparent'
border.color: 'white'
border.color: root.resizeAccentColor
radius: Kirigami.Units.cornerRadius
border.width: 1

View file

@ -18,8 +18,11 @@ Item {
property Folio.HomeScreen folio
readonly property string pluginName: model.pluginName
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property real pressedScale: MobileShell.Motion.pressScaleIn
readonly property color hoverColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.22)
property real zoomScale: (model.isSupported && mouseArea.pressed) ? 0.8 : 1
property real zoomScale: (model.isSupported && mouseArea.pressed) ? pressedScale : 1
transform: Scale {
origin.x: delegate.width / 2;
origin.y: delegate.height / 2;
@ -27,7 +30,7 @@ Item {
yScale: delegate.zoomScale
}
Behavior on zoomScale { NumberAnimation { duration: 80 } }
Behavior on zoomScale { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Press; duration: delegate.pressAnimationDuration } }
// Placeholder item used for implement drag & drop
Item {
@ -72,7 +75,7 @@ Item {
Rectangle {
id: background
color: Qt.rgba(255, 255, 255, 0.3)
color: root.hoverColor
visible: model.isSupported && mouseArea.containsMouse
radius: Kirigami.Units.cornerRadius
anchors.fill: parent

View file

@ -12,7 +12,6 @@ import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.plasmoid
@ -39,6 +38,9 @@ Item {
readonly property string applicationName: application ? application.name : ""
readonly property string applicationStorageId: application ? application.storageId : ""
readonly property string applicationIcon: application ? application.icon : ""
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property color pressFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.18)
readonly property color folderFeedbackColor: Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.24)
signal folderOpenRequested()
@ -142,11 +144,12 @@ Item {
property bool launchAppRequested: false
NumberAnimation on zoomScale {
MobileShell.MotionNumberAnimation on zoomScale {
id: shrinkAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
to: ShellSettings.Settings.animationsEnabled ? 0.95 : 1
duration: delegate.pressAnimationDuration
to: MobileShell.Motion.pressScaleIn
onFinished: {
if (!mouseArea.pressed) {
growAnim.restart();
@ -154,10 +157,11 @@ Item {
}
}
NumberAnimation on zoomScale {
MobileShell.MotionNumberAnimation on zoomScale {
id: growAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
duration: delegate.pressAnimationDuration
to: 1
onFinished: {
if (mouseArea.launchAppRequested) {
@ -188,7 +192,7 @@ Item {
Rectangle {
anchors.fill: parent
radius: height / 2
color: mouseArea.pressed ? Qt.rgba(255, 255, 255, 0.2) : "transparent"
color: mouseArea.pressed ? delegate.pressFeedbackColor : "transparent"
}
RowLayout {
@ -263,7 +267,7 @@ Item {
Rectangle {
anchors.fill: parent
anchors.margins: Kirigami.Units.smallSpacing
color: Qt.rgba(255, 255, 255, 0.2)
color: delegate.folderFeedbackColor
radius: Kirigami.Units.cornerRadius
opacity: delegate.dragFolderAnimationProgress
@ -317,7 +321,7 @@ Item {
id: rect
anchors.fill: parent
anchors.margins: Kirigami.Units.smallSpacing
color: Qt.rgba(255, 255, 255, 0.2)
color: delegate.folderFeedbackColor
radius: Kirigami.Units.cornerRadius
transform: Scale {

View file

@ -18,6 +18,7 @@ MobileShell.GridView {
id: root
property MobileShell.MaskManager maskManager
required property var searchWidget
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialFast)
// don't set anchors.margins since we want everywhere to be draggable
required property bool twoColumn
@ -198,11 +199,12 @@ MobileShell.GridView {
folderAnim.restart();
}
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: folderAnim
target: appDelegate
properties: "dragFolderAnimationProgress"
duration: Kirigami.Units.shortDuration
type: MobileShell.Motion.SpatialFast
duration: root.shortAnimationDuration
}
}
@ -253,10 +255,11 @@ MobileShell.GridView {
// animations
displaced: Transition {
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: transitionAnim
properties: "x,y"
easing.type: Easing.OutQuad
type: MobileShell.Motion.SpatialFast
duration: root.shortAnimationDuration
}
}

View file

@ -11,7 +11,6 @@ import org.kde.draganddrop 2.0 as DragDrop
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Item {
id: root
@ -26,6 +25,7 @@ Item {
readonly property real cellWidth: twoColumn ? (root.width - leftMargin - rightMargin) / 2 : (root.width - leftMargin - rightMargin)
readonly property real cellHeight: delegateHeight
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property real leftMargin: Math.round(width * 0.1)
readonly property real rightMargin: Math.round(width * 0.1)
@ -150,35 +150,35 @@ Item {
}
}
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: goToBeginningAnim
target: favoritesGrid
properties: 'contentY'
to: favoritesGrid.originY
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
}
SequentialAnimation {
id: openFolderAnim
ParallelAnimation {
NumberAnimation {
MobileShell.MotionNumberAnimation {
target: favoritesGrid
properties: 'openFolderProgress'
duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 1
easing.type: Easing.InOutQuad
}
}
ParallelAnimation {
NumberAnimation {
MobileShell.MotionNumberAnimation {
target: folderGrid
properties: 'openProgress'
duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 1
easing.type: Easing.InOutQuad
}
}
}
@ -187,22 +187,22 @@ Item {
id: closeFolderAnim
ParallelAnimation {
NumberAnimation {
MobileShell.MotionNumberAnimation {
target: folderGrid
properties: 'openProgress'
duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 0
easing.type: Easing.InOutQuad
}
}
ParallelAnimation {
NumberAnimation {
MobileShell.MotionNumberAnimation {
target: favoritesGrid
properties: 'openFolderProgress'
duration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
to: 0
easing.type: Easing.InOutQuad
}
}
}

View file

@ -17,6 +17,7 @@ import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
MobileShell.GridView {
id: root
property Halcyon.ApplicationFolder folder: null
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialFast)
property string folderName: folder ? folder.name : ""
property var folderModel: folder ? folder.applications : []
@ -223,9 +224,10 @@ MobileShell.GridView {
// animations
displaced: Transition {
NumberAnimation {
MobileShell.MotionNumberAnimation {
properties: "x,y"
easing.type: Easing.OutQuad
type: MobileShell.Motion.SpatialFast
duration: root.shortAnimationDuration
}
}
}

View file

@ -15,7 +15,6 @@ import org.kde.kquickcontrolsaddons
import org.kde.plasma.plasmoid
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
import org.kde.kirigami as Kirigami
@ -31,6 +30,8 @@ MouseArea {
property alias iconItem: icon
readonly property real margins: Math.floor(width * 0.2)
readonly property int pressAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
readonly property real pressedScale: MobileShell.Motion.pressScaleIn
signal launch(int x, int y, var source, string title, string storageId)
@ -82,11 +83,12 @@ MouseArea {
property bool launchAppRequested: false
NumberAnimation on zoomScale {
MobileShell.MotionNumberAnimation on zoomScale {
id: shrinkAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
to: ShellSettings.Settings.animationsEnabled ? 0.8 : 1
duration: delegate.pressAnimationDuration
to: delegate.pressedScale
onFinished: {
if (!delegate.pressed) {
growAnim.restart();
@ -94,10 +96,11 @@ MouseArea {
}
}
NumberAnimation on zoomScale {
MobileShell.MotionNumberAnimation on zoomScale {
id: growAnim
type: MobileShell.Motion.Press
running: false
duration: ShellSettings.Settings.animationsEnabled ? 80 : 1
duration: delegate.pressAnimationDuration
to: 1
onFinished: {
if (delegate.launchAppRequested) {

View file

@ -35,6 +35,7 @@ MobileShell.GridView {
readonly property int reservedSpaceForLabel: metrics.height
readonly property real effectiveContentWidth: width - leftMargin - rightMargin
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
cellWidth: gridView.effectiveContentWidth / Math.min(Math.floor(effectiveContentWidth / (Kirigami.Units.iconSizes.huge + Kirigami.Units.largeSpacing * 2)), 8)
cellHeight: cellWidth + reservedSpaceForLabel
@ -46,11 +47,11 @@ MobileShell.GridView {
goToBeginningAnim.restart();
}
NumberAnimation on contentY {
MobileShell.MotionNumberAnimation on contentY {
id: goToBeginningAnim
type: MobileShell.Motion.SpatialDefault
to: gridView.originY
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: gridView.longAnimationDuration
}
model: Halcyon.ApplicationListModel

View file

@ -20,6 +20,7 @@ import "settings" as Settings
Item {
id: root
property MobileShell.MaskManager maskManager
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
required property real topMargin
required property real bottomMargin
@ -37,7 +38,7 @@ Item {
signal wallpaperSelectorTriggered()
Behavior on settingsOpenFactor {
NumberAnimation { duration: Kirigami.Units.longDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
}
function triggerHomescreen() {

View file

@ -21,6 +21,7 @@ Item {
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() {
@ -110,10 +111,10 @@ Item {
}
}
NumberAnimation on contentY {
MobileShell.MotionNumberAnimation on contentY {
id: anim
duration: Kirigami.Units.longDuration
easing.type: Easing.OutQuad
type: MobileShell.Motion.SpatialDefault
duration: root.longAnimationDuration
running: false
onFinished: {
if (anim.to === flickable.openedContentY) {

View file

@ -17,6 +17,7 @@ import plasma.applet.org.kde.plasma.mobile.homescreen.halcyon as Halcyon
ContainmentItem {
id: root
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
Component.onCompleted: {
Plasmoid.settings.load();
@ -88,7 +89,7 @@ ContainmentItem {
property real darkenBackgroundFactor: halcyonHomeScreen.page == 1 ? 1 : 0
Behavior on darkenBackgroundFactor {
NumberAnimation { duration: Kirigami.Units.longDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
}
Rectangle {
@ -103,7 +104,7 @@ ContainmentItem {
opacity: halcyonHomeScreen.settingsOpenFactor
anchors.fill: parent
Behavior on color {
ColorAnimation { duration: Kirigami.Units.longDuration }
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }
}
}

View file

@ -27,6 +27,8 @@ Item {
// Request the panel itself to reapply settings (ex. for updating touch area).
signal updatePanelPropertiesRequested()
readonly property int panelAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
Kirigami.Theme.colorSet: forcedComplementary ? Kirigami.Theme.Complementary : Kirigami.Theme.Header
Kirigami.Theme.inherit: false
@ -60,6 +62,7 @@ Item {
State {
// Panel is forced to be visible and overlaid over content (will be automatically hidden after a duration).
name: "visible"
PropertyChanges {
target: root; offset: 0
}
@ -76,10 +79,10 @@ Item {
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
MobileShell.MotionNumberAnimation {
properties: "offset"
easing.type: root.state === "hidden" ? Easing.InExpo : Easing.OutExpo
duration: Kirigami.Units.longDuration
type: root.state === "hidden" ? MobileShell.Motion.EmphasizedAccel : MobileShell.Motion.SpatialDefault
duration: root.panelAnimationDuration
}
}
ScriptAction {

View file

@ -39,6 +39,8 @@ ContainmentItem {
readonly property bool inLandscape: MobileShell.Constants.navigationPanelOnSide(Screen.width, Screen.height)
readonly property bool gamingMode: ShellSettings.Settings.gamingModeEnabled
readonly property int navigationAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int resetAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault) * 1.5)
readonly property real navigationPanelHeight: gamingMode ? 0 : MobileShell.Constants.navigationPanelThickness
readonly property real convergenceWorkspaceFrameThickness: ShellSettings.Settings.convergenceModeEnabled && !gamingMode
@ -326,10 +328,10 @@ ContainmentItem {
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
MobileShell.MotionNumberAnimation {
properties: "offset"
easing.type: navigationPanel.state === "hidden" ? Easing.InExpo : Easing.OutExpo
duration: Kirigami.Units.longDuration
type: navigationPanel.state === "hidden" ? MobileShell.Motion.EmphasizedAccel : MobileShell.Motion.SpatialDefault
duration: root.navigationAnimationDuration
}
}
ScriptAction {
@ -377,14 +379,14 @@ ContainmentItem {
}
}
NumberAnimation {
MobileShell.MotionNumberAnimation {
id: resetAn
running: false
target: dragEffect
property: "offsetPoint"
to: 0
duration: Kirigami.Units.longDuration * 1.5
easing.type: Easing.OutExpo
type: MobileShell.Motion.SpatialDefault
duration: root.resetAnimationDuration
onRunningChanged: {
if (!running && navigationPanel.state == "hidden") {
root.setWindowProperties();

View file

@ -59,7 +59,9 @@ QMap<QString, QMap<QString, QVariant>> getKwinrcSettings(KSharedConfig::Ptr m_mo
{"convergentwindowsEnabled", true}, // enable our convergent window plugin
{"mobiletaskswitcherEnabled", !convergenceModeEnabled}, // mobile task switcher on phone only; convergence uses standard Alt-Tab tabbox
{"overviewEnabled", convergenceModeEnabled}, // enable KWin Overview effect in convergence mode for desktop-style task switching
{"screenedgeEnabled", convergenceModeEnabled} // enable screen edge visual feedback in convergence mode (mouse hot corners)
{"screenedgeEnabled", convergenceModeEnabled}, // enable screen edge visual feedback in convergence mode (mouse hot corners)
{"shift-tilingEnabled", convergenceModeEnabled},
{"shift-tile-previewEnabled", convergenceModeEnabled}
}},
{"Wayland",
{
@ -78,8 +80,8 @@ QMap<QString, QMap<QString, QVariant>> getKwinrcSettings(KSharedConfig::Ptr m_mo
// Have a separate list here because we need to trigger DBus calls to load/unload each effect/script.
// Make sure that the effect/script is added to the kwinrc "Plugins" section above!
const QList<QString> KWIN_EFFECTS = {"blur", "mobiletaskswitcher", "overview", "screenedge"};
const QList<QString> KWIN_SCRIPTS = {"convergentwindows"};
const QList<QString> KWIN_EFFECTS = {"blur", "mobiletaskswitcher", "overview", "screenedge", "shift-tile-preview"};
const QList<QString> KWIN_SCRIPTS = {"convergentwindows", "shift-tiling"};
// .config/plasma-mobile/ksmserver - immutable settings:
const QMap<QString, QMap<QString, QVariant>> KSMSERVER_SETTINGS = {{"General", {{"loginMode", "emptySession"}}}};

View file

@ -3,6 +3,7 @@
`org.shift.icons` is the icon theme selected by `lookandfeel/contents/defaults`.
It inherits only `hicolor`, so shell-owned glyphs used by the Shift UI need to exist in this theme or in the local hicolor source icon set.
The SVG glyphs are adapted from Phosphor Icons and licensed through the scoped REUSE metadata in `.reuse/dep5`.
The theme sets `FollowsColorScheme=true`; symbolic SVGs use `.ColorScheme-Text` and `currentColor` so KDE applications recolor them for both dark and light color schemes.
Theme paths used here:

View file

@ -2,6 +2,7 @@
Name=SHIFT
Comment=SHIFT icon theme
Inherits=hicolor
FollowsColorScheme=true
Example=folder
DisplayDepth=32
DesktopDefault=48

View file

@ -7,6 +7,7 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.mobileinitialstart.initialstart
import org.kde.plasma.mobileinitialstart.prepare 1.0 as Prepare
@ -14,9 +15,13 @@ import org.kde.plasma.mobileinitialstart.prepare 1.0 as Prepare
Item {
id: root
readonly property real scaleStart: 1.4
readonly property real scaleLanding: 1.2
readonly property real scaleStart: 1.16
readonly property real scaleLanding: 1.08
readonly property real scaleSteps: 1
readonly property int initialContentFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow) * 2
readonly property int returnContentFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int imageFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow)
readonly property int imageScaleDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialVerySlow)
signal requestNextPage()
@ -27,14 +32,15 @@ Item {
}
property real contentOpacity: 0
NumberAnimation on contentOpacity {
MobileShell.MotionNumberAnimation on contentOpacity {
id: contentOpacityAnim
type: MobileShell.Motion.EffectsSlow
running: true
duration: 1000
duration: root.initialContentFadeDuration
to: 1
// shorten animation after initial run
onFinished: duration = 200
onFinished: duration = root.returnContentFadeDuration
}
Image {
@ -62,11 +68,11 @@ Item {
opacity: 0
NumberAnimation on opacity {
MobileShell.MotionNumberAnimation on opacity {
type: MobileShell.Motion.EffectsSlow
running: true
duration: 400
duration: root.imageFadeDuration
to: 1
easing.type: Easing.InOutQuad
}
// zoom animation
@ -74,9 +80,9 @@ Item {
Component.onCompleted: scale = scaleLanding
Behavior on scale {
NumberAnimation {
duration: 2000
easing.type: Easing.OutExpo
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.SpatialVerySlow
duration: root.imageScaleDuration
}
}

View file

@ -8,6 +8,7 @@ import QtQuick.Layouts
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Item {
id: root
@ -20,7 +21,16 @@ Item {
property bool showBackground: true
property int fingerSize: 20
property int _endTimeout: 2000
readonly property bool animationsEnabled: ShellSettings.Settings.animationsEnabled
readonly property int longAnimationDuration: animationsEnabled ? Kirigami.Units.longDuration : 0
readonly property int switcherDragDuration: animationsEnabled ? Math.round(Kirigami.Units.veryLongDuration * 3.75) : 0
readonly property int switcherSlideDuration: animationsEnabled ? Math.round(Kirigami.Units.veryLongDuration * 1.25) : 0
readonly property int flickDragDuration: animationsEnabled ? Math.round(Kirigami.Units.veryLongDuration * 2.25) : 0
readonly property int scrubSettleDuration: animationsEnabled ? Math.round(Kirigami.Units.veryLongDuration * 1.75) : 0
readonly property int quickAnimationDuration: animationsEnabled ? Math.round(Kirigami.Units.longDuration * 1.2) : 0
readonly property int sequencePauseDuration: animationsEnabled ? Math.round(Kirigami.Units.veryLongDuration * 1.25) : 0
readonly property int scrubLeadInDelay: animationsEnabled ? Kirigami.Units.veryLongDuration : 0
readonly property int _endTimeout: animationsEnabled ? Kirigami.Units.veryLongDuration * 5 : 0
Rectangle {
id: phone
@ -213,7 +223,7 @@ Item {
root.touchOnAnim.start()
}
duration: 1500
duration: root.switcherDragDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -222,7 +232,7 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InQuad
},
NumberAnimation {
@ -236,7 +246,7 @@ Item {
touchPoint.yPosition = 2;
root.touchOnAnim.start()
}
duration: 500
duration: root.switcherSlideDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -245,14 +255,14 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InQuad
}
]
delays: [
500,
500,
-Kirigami.Units.longDuration * 2,
root.sequencePauseDuration,
root.sequencePauseDuration,
-root.longAnimationDuration * 2,
]
}
@ -288,7 +298,7 @@ Item {
to: 0.55
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -297,7 +307,7 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -339,7 +349,7 @@ Item {
root.touchOnAnim.start()
}
duration: 900
duration: root.flickDragDuration
easing.type: Easing.InQuart
},
NumberAnimation {
@ -348,12 +358,12 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InQuad
}
]
delays: [
-Kirigami.Units.longDuration,
-root.longAnimationDuration,
]
}
@ -390,7 +400,7 @@ Item {
to: 0.1
duration: 300
duration: root.quickAnimationDuration
easing.type: Easing.InQuad
},
NumberAnimation {
@ -399,7 +409,7 @@ Item {
to: 0
duration: 300
duration: root.quickAnimationDuration
easing.type: Easing.Linear
}
]
@ -433,7 +443,7 @@ Item {
root.touchOnAnim.start()
}
duration: 900
duration: root.flickDragDuration
easing.type: Easing.InOutQuart
},
NumberAnimation {
@ -443,7 +453,7 @@ Item {
from: 0
to: 1
duration: 1500
duration: root.switcherDragDuration
easing.type: Easing.InOutQuart
},
NumberAnimation {
@ -452,7 +462,7 @@ Item {
to: 0.5
duration: 700
duration: root.scrubSettleDuration
easing.type: Easing.InOutCubic
},
NumberAnimation {
@ -461,14 +471,14 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InQuad
}
]
delays: [
0,
0,
500
root.sequencePauseDuration
]
}
@ -505,7 +515,7 @@ Item {
to: 0.55
duration: 300
duration: root.quickAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -514,7 +524,7 @@ Item {
to: 0
duration: 300
duration: root.quickAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation {
@ -541,7 +551,7 @@ Item {
to: 1
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation { // move leftmost window out of the way, otherwise it overlaps
@ -550,7 +560,7 @@ Item {
to: 1.8
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InOutQuad
},
NumberAnimation { // move middle window (that's to be focused) a bit to the side to counteract moving of the first window
@ -559,7 +569,7 @@ Item {
to: 0.4
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.Linear
},
NumberAnimation { // move first (rightmost) window to get a bit more space between it and the middle one during the animation
@ -568,14 +578,14 @@ Item {
to: 1
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.Linear
}
]
delays: [
400,
root.scrubLeadInDelay,
immediate,
scrubAnimation.animations[0].duration - 300 - 400,
scrubAnimation.animations[0].duration - root.quickAnimationDuration - root.scrubLeadInDelay,
scrubAnimation.delays[1],
scrubAnimation.delays[2],
immediate,
@ -655,7 +665,7 @@ Item {
to: 0
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InQuad
}
@ -665,7 +675,7 @@ Item {
to: root.fingerSize
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.OutQuad
}
}

View file

@ -15,6 +15,7 @@ import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
KCM.SimpleKCM {
id: root
readonly property int longAnimationDuration: ShellSettings.Settings.animationsEnabled ? Kirigami.Units.longDuration : 0
title: i18n("Navigation")
@ -140,7 +141,7 @@ KCM.SimpleKCM {
to: -tutorialSwitcherInput.activeTutorialIndex * (tutorialContainer.phoneWidth + tutorialLayout.spacing)
duration: Kirigami.Units.longDuration
duration: root.longAnimationDuration
easing.type: Easing.InOutQuad
}
}

View file

@ -2,7 +2,10 @@
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
import QtQuick.Shapes
import org.kde.kwin.decoration
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Decoration {
id: root
@ -18,13 +21,19 @@ Decoration {
readonly property int btnSize: 16
readonly property int btnSpacing: 8
readonly property int btnSideMargin: 12
readonly property int cornerRadius: decoration.client.maximized ? 0 : 8
readonly property int normalCornerRadius: 8
readonly property int cornerRadius: decoration.client.maximized ? 0 : normalCornerRadius
readonly property int frameThickness: decoration.client.maximized ? 0 : normalCornerRadius
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property bool windowMenuAllowed: !ShellSettings.Settings.convergenceModeEnabled
|| ShellSettings.Settings.gamingModeEnabled
|| !ShellSettings.Settings.dynamicTilingEnabled
Component.onCompleted: {
borders.top = barHeight;
borders.left = 0;
borders.right = 0;
borders.bottom = 0;
borders.left = normalCornerRadius;
borders.right = normalCornerRadius;
borders.bottom = normalCornerRadius;
// Keep titlebar controls available for maximized windows in desktop
// convergence mode. Mobile mode uses noBorder=true and bypasses this.
@ -39,6 +48,36 @@ Decoration {
deco: decoration
}
readonly property color frameColor: decoration.client.active ? root.activeBar : root.inactiveBar
Shape {
anchors.fill: parent
visible: !decoration.client.maximized
ShapePath {
fillColor: root.frameColor
fillRule: ShapePath.OddEvenFill
strokeWidth: 0
startX: root.cornerRadius
startY: 0
PathLine { x: root.width - root.cornerRadius; y: 0 }
PathArc { x: root.width; y: root.cornerRadius; radiusX: root.cornerRadius; radiusY: root.cornerRadius }
PathLine { x: root.width; y: root.height - root.cornerRadius }
PathArc { x: root.width - root.cornerRadius; y: root.height; radiusX: root.cornerRadius; radiusY: root.cornerRadius }
PathLine { x: root.cornerRadius; y: root.height }
PathArc { x: 0; y: root.height - root.cornerRadius; radiusX: root.cornerRadius; radiusY: root.cornerRadius }
PathLine { x: 0; y: root.cornerRadius }
PathArc { x: root.cornerRadius; y: 0; radiusX: root.cornerRadius; radiusY: root.cornerRadius }
PathMove { x: root.frameThickness; y: root.barHeight }
PathLine { x: root.width - root.frameThickness; y: root.barHeight }
PathLine { x: root.width - root.frameThickness; y: root.height - root.frameThickness }
PathLine { x: root.frameThickness; y: root.height - root.frameThickness }
PathLine { x: root.frameThickness; y: root.barHeight }
}
}
// Faint window outline
Rectangle {
anchors.fill: parent
@ -55,7 +94,7 @@ Decoration {
height: root.barHeight
radius: root.cornerRadius
color: decoration.client.active ? root.activeBar : root.inactiveBar
Behavior on color { ColorAnimation { duration: 120 } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
// Square off bottom half only top corners are rounded
Rectangle {
@ -96,7 +135,7 @@ Decoration {
elide: Text.ElideMiddle
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
Behavior on color { ColorAnimation { duration: 120 } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
}
Row {
@ -113,6 +152,14 @@ Decoration {
}
}
MouseArea {
anchors.fill: parent
z: 1
enabled: !root.windowMenuAllowed
acceptedButtons: Qt.RightButton
onPressed: (mouse) => { mouse.accepted = true }
}
Component.onCompleted: decoration.installTitleItem(titleRow)
}
}
@ -127,9 +174,10 @@ Decoration {
case DecorationOptions.DecorationButtonClose:
case DecorationOptions.DecorationButtonMinimize:
case DecorationOptions.DecorationButtonMaximizeRestore:
return true;
case DecorationOptions.DecorationButtonMenu:
case DecorationOptions.DecorationButtonApplicationMenu:
return true;
return root.windowMenuAllowed;
default:
return false;
}
@ -195,7 +243,7 @@ Decoration {
color: parent.pressed ? Qt.darker(parent.hoverColor, 1.3)
: parent.hovered ? parent.hoverColor
: parent.normalColor
Behavior on color { ColorAnimation { duration: 100 } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
Text {
anchors.centerIn: parent
@ -204,7 +252,7 @@ Decoration {
font.pixelSize: Math.round(parent.width * 0.66)
font.weight: Font.Bold
opacity: 1.0
Behavior on opacity { NumberAnimation { duration: 100 } }
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
}
}
}

View file

@ -8,3 +8,4 @@ function(add_kwin_effect name source)
endfunction()
add_kwin_effect(shift-snap-assist shift-snap-assist)
add_kwin_effect(shift-tile-preview shift-tile-preview)

View file

@ -14,6 +14,7 @@
import QtQuick
import QtQuick.Layouts
import org.kde.kwin as KWinComponents
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
KWinComponents.SceneEffect {
@ -38,6 +39,7 @@ KWinComponents.SceneEffect {
readonly property int panelScreenMargin: 8
readonly property int panelCursorGap: 12
readonly property int panelCursorRightBias: 34
readonly property int hoverAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
property var hoverWindowId: null
property int hoverTicks: 0
property string hoverWindowStateKey: ""
@ -649,7 +651,7 @@ KWinComponents.SceneEffect {
property bool hovered: false
Behavior on color { ColorAnimation { duration: 80 } }
Behavior on color { MobileShell.MotionColorAnimation { type: MobileShell.Motion.Press; duration: effect.hoverAnimationDuration } }
Rectangle {
id: previewFrame

View file

@ -0,0 +1,331 @@
// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2
import QtQuick
import org.kde.kwin as KWinComponents
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
KWinComponents.SceneEffect {
id: effect
visible: false
readonly property int outerGap: 8
readonly property int floatEscapeMargin: 32
readonly property int previewAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int previewFadeDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
property var dragConnectedWindows: ({})
property var draggingWindow: null
property rect dragSourceGeometry: Qt.rect(0, 0, 0, 0)
property bool animatePreview: false
property bool previewVisible: false
property string previewMode: ""
property string previewScreenName: ""
property rect previewGeometry: Qt.rect(0, 0, 0, 0)
function isActive() {
return ShellSettings.Settings.convergenceModeEnabled
&& !ShellSettings.Settings.gamingModeEnabled
&& ShellSettings.Settings.dynamicTilingEnabled;
}
function windowKey(window) {
return window && window.internalId !== undefined ? String(window.internalId) : "";
}
function shouldIgnore(window) {
if (!window || window.deleted) {
return true;
}
if (!window.normalWindow || !window.maximizable || window.fullScreen) {
return true;
}
return window.resourceClass === "xwaylandvideobridge";
}
function validRect(geometry) {
return geometry && geometry.width > 0 && geometry.height > 0;
}
function rectContainsPoint(geometry, point) {
return validRect(geometry)
&& point.x >= geometry.x
&& point.x <= geometry.x + geometry.width
&& point.y >= geometry.y
&& point.y <= geometry.y + geometry.height;
}
function workRect(window) {
if (!window || !window.output || window.desktops.length === 0) {
return null;
}
return KWinComponents.Workspace.clientArea(
KWinComponents.Workspace.MaximizeArea,
window.output,
window.desktops[0]
);
}
function outsideWorkArea(window, cursor) {
const area = workRect(window);
if (!area) {
return false;
}
const expandedArea = Qt.rect(
area.x - floatEscapeMargin,
area.y - floatEscapeMargin,
area.width + floatEscapeMargin * 2,
area.height + floatEscapeMargin * 2
);
return !rectContainsPoint(expandedArea, cursor);
}
function findTileAtCursor(cursor, ignoredWindow) {
const ignoredKey = windowKey(ignoredWindow);
const windows = KWinComponents.Workspace.windows;
let bestWindow = null;
let bestGeometry = Qt.rect(0, 0, 0, 0);
let bestArea = 0;
for (let index = 0; index < windows.length; index++) {
const candidate = windows[index];
if (shouldIgnore(candidate) || windowKey(candidate) === ignoredKey) {
continue;
}
if (!ignoredWindow || !candidate.output || !ignoredWindow.output || candidate.output.name !== ignoredWindow.output.name) {
continue;
}
const geometry = candidate.frameGeometry;
if (!rectContainsPoint(geometry, cursor)) {
continue;
}
const area = geometry.width * geometry.height;
if (!bestWindow || area < bestArea) {
bestWindow = candidate;
bestGeometry = geometry;
bestArea = area;
}
}
return bestWindow ? bestGeometry : null;
}
function insetPreviewGeometry(geometry) {
const inset = Math.max(2, Math.round(outerGap / 2));
return Qt.rect(
geometry.x + inset,
geometry.y + inset,
Math.max(1, geometry.width - inset * 2),
Math.max(1, geometry.height - inset * 2)
);
}
function showPreview(mode, geometry, screenName) {
hidePreview();
}
function hidePreview() {
previewVisible = false;
draggingWindow = null;
dragSourceGeometry = Qt.rect(0, 0, 0, 0);
disableEffectTimer.restart();
}
function updatePreview(window, dragGeometry) {
if (!isActive() || draggingWindow !== window || !window.output) {
hidePreview();
return;
}
const cursor = KWinComponents.Workspace.cursorPos;
const targetGeometry = findTileAtCursor(cursor, window);
if (targetGeometry) {
showPreview("swap", targetGeometry, window.output.name);
return;
}
if (outsideWorkArea(window, cursor)) {
showPreview("float", validRect(dragGeometry) ? dragGeometry : window.frameGeometry, window.output.name);
return;
}
showPreview("restore", dragSourceGeometry, window.output.name);
}
function connectDragHandlers(window) {
const key = windowKey(window);
if (!key || dragConnectedWindows[key]) {
return;
}
dragConnectedWindows[key] = true;
window.interactiveMoveResizeStarted.connect(function() {
if (!isActive() || shouldIgnore(window)) {
return;
}
draggingWindow = window;
dragSourceGeometry = window.frameGeometry;
showPreview("restore", dragSourceGeometry, window.output ? window.output.name : "");
});
window.interactiveMoveResizeStepped.connect(function(geometry) {
updatePreview(window, geometry);
});
window.interactiveMoveResizeFinished.connect(function() {
if (draggingWindow === window) {
hidePreview();
}
});
}
function connectExistingWindows() {
const windows = KWinComponents.Workspace.windows;
for (let index = 0; index < windows.length; index++) {
connectDragHandlers(windows[index]);
}
}
function previewFillColor(mode) {
if (mode === "float") {
return Qt.rgba(1.0, 0.62, 0.24, 0.18);
}
if (mode === "restore") {
return Qt.rgba(1.0, 1.0, 1.0, 0.10);
}
return Qt.rgba(0.18, 0.72, 0.66, 0.22);
}
function previewBorderColor(mode) {
if (mode === "float") {
return Qt.rgba(1.0, 0.72, 0.36, 0.72);
}
if (mode === "restore") {
return Qt.rgba(1.0, 1.0, 1.0, 0.36);
}
return Qt.rgba(0.64, 0.90, 0.86, 0.82);
}
Timer {
id: enableAnimationTimer
interval: 1
repeat: false
onTriggered: effect.animatePreview = true
}
Timer {
id: disableEffectTimer
interval: effect.previewFadeDuration
repeat: false
onTriggered: {
if (!effect.previewVisible) {
effect.visible = false;
}
}
}
Connections {
target: KWinComponents.Workspace
function onWindowAdded(window) {
effect.connectDragHandlers(window);
}
function onWindowRemoved(window) {
const key = effect.windowKey(window);
if (key) {
delete effect.dragConnectedWindows[key];
}
if (effect.draggingWindow === window) {
effect.hidePreview();
}
}
}
Connections {
target: ShellSettings.Settings
function onConvergenceModeEnabledChanged() {
if (!effect.isActive()) {
effect.hidePreview();
}
}
function onGamingModeEnabledChanged() {
if (!effect.isActive()) {
effect.hidePreview();
}
}
function onDynamicTilingEnabledChanged() {
if (!effect.isActive()) {
effect.hidePreview();
}
}
}
delegate: Rectangle {
id: screenDelegate
readonly property var targetScreen: KWinComponents.SceneView.screen
readonly property bool previewOnScreen: effect.previewScreenName === targetScreen.name
color: "transparent"
Rectangle {
id: previewSurface
visible: opacity > 0
x: effect.previewGeometry.x - screenDelegate.targetScreen.geometry.x
y: effect.previewGeometry.y - screenDelegate.targetScreen.geometry.y
width: effect.previewGeometry.width
height: effect.previewGeometry.height
radius: 14
opacity: effect.previewVisible && screenDelegate.previewOnScreen ? 1 : 0
color: effect.previewFillColor(effect.previewMode)
border.width: 2
border.color: effect.previewBorderColor(effect.previewMode)
Behavior on x {
enabled: effect.animatePreview
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: effect.previewAnimationDuration }
}
Behavior on y {
enabled: effect.animatePreview
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: effect.previewAnimationDuration }
}
Behavior on width {
enabled: effect.animatePreview
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: effect.previewAnimationDuration }
}
Behavior on height {
enabled: effect.animatePreview
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: effect.previewAnimationDuration }
}
Behavior on opacity {
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: effect.previewFadeDuration }
}
Behavior on color {
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: effect.previewFadeDuration }
}
Behavior on border.color {
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: effect.previewFadeDuration }
}
Rectangle {
anchors.fill: parent
anchors.margins: 5
radius: Math.max(0, parent.radius - anchors.margins)
color: "transparent"
border.width: 1
border.color: Qt.rgba(1, 1, 1, 0.14)
opacity: effect.previewMode === "insert" ? 1 : 0.45
}
}
}
Component.onCompleted: connectExistingWindows()
}

View file

@ -0,0 +1,20 @@
{
"KPackageStructure": "KWin/Effect",
"KPlugin": {
"Authors": [
{
"Email": "marcoa@example.com",
"Name": "Marco Allegretti"
}
],
"Category": "Appearance",
"Description": "Animated drag preview for SHIFT dynamic tiling in convergence mode.",
"EnabledByDefault": false,
"Id": "shift-tile-preview",
"License": "EUPL-1.2",
"Name": "SHIFT Tile Preview",
"Version": "1.0"
},
"X-KDE-Ordering": 61,
"X-Plasma-API": "declarativescript"
}

View file

@ -12,6 +12,7 @@ import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kwin 3.0 as KWinComponents
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Item {
@ -30,6 +31,8 @@ Item {
readonly property real dragOffset: -control.y
readonly property int currentIndex: model.index
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
// whether this task is being interacted with
readonly property bool interactingActive: control.pressed && control.passedDragThreshold
@ -137,11 +140,11 @@ Item {
}
}
NumberAnimation on y {
MobileShell.MotionNumberAnimation on y {
id: yAnimator
type: MobileShell.Motion.Standard
running: !control.pressed
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: delegate.longAnimationDuration
to: 0
onFinished: {
if (to != 0) { // close app
@ -172,7 +175,7 @@ Item {
opacity: delegate.showHeader ? 1 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: delegate.shortAnimationDuration }
}
Kirigami.Icon {
@ -216,12 +219,9 @@ Item {
clip: true
// scale animation on press
property real zoomScale: control.pressed ? 0.95 : 1
property real zoomScale: control.pressed ? MobileShell.Motion.previewPressScale : 1
Behavior on zoomScale {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.OutExpo
}
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault }
}
transform: Scale {

View file

@ -9,6 +9,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.kwin 3.0 as KWinComponents
@ -105,7 +106,7 @@ MouseArea {
// dynamic task offset animation duration based off of the touch position and task scale
function dynamicDuration(left = true): int {
// if the close animation is running, use the standard long duration time for consistency
let duration = Kirigami.Units.longDuration * 1.75
let duration = root.taskSwitcherHelpers.longAnimationDuration * 1.75
if (!taskSwitcherHelpers.closeAnim.running && taskSwitcherHelpers.notHomeScreenState && taskSwitcherHelpers.gestureState != TaskSwitcherHelpers.GestureStates.HorizontalSwipe && !taskSwitcherHelpers.isInTaskScrubMode) {
// max out the scale at 1 so it is not too fast when opening the task drawer with the button
let taskScale = Math.min(taskSwitcherHelpers.currentScale, 1)
@ -170,16 +171,17 @@ MouseArea {
// this is the x-position with respect to the list
property real listX: root.taskSwitcherHelpers.xPositionFromTaskIndex(currentIndex)
Behavior on listX {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.Standard
duration: root.taskSwitcherHelpers.longAnimationDuration
}
}
// the animated task offset value (always will be 0 if it is the current task in the task drawer)
property real taskOffsetNormalized: (root.baseTaskOffset * ((root.taskSwitcherHelpers.taskDrawerOpened && isCurrentTask) ? 0 : 1))
Behavior on taskOffsetNormalized {
NumberAnimation {
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.Standard
duration: root.taskSwitcherHelpers.currentDisplayTask > task.currentIndex ? root.taskOffsetDurationRight : root.taskOffsetDurationLeft
easing.type: root.taskOffsetEasing
easing.overshoot: 0.85

View file

@ -38,6 +38,9 @@ FocusScope {
readonly property real bottomMargin: ShellSettings.Settings.autoHidePanelsEnabled ? 0 : navBottomMargin
readonly property real leftMargin: 0
readonly property real rightMargin: ShellSettings.Settings.autoHidePanelsEnabled ? 0 : navRightMargin
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
readonly property int veryLongAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow)
readonly property real disabledScrubArrowOpacity: 0.38
property var taskSwitcherHelpers: TaskSwitcherHelpers {
taskSwitcher: root
@ -64,7 +67,7 @@ FocusScope {
state.currentTaskIndex -= 1;
// animated at the same speed as the task x position in the TaskList so that the task appears not to move from the perspective of the user.
taskSwitcherHelpers.animateGoToTaskIndex(state.currentTaskIndex, Kirigami.Units.longDuration, Easing.InOutQuad);
taskSwitcherHelpers.animateGoToTaskIndex(state.currentTaskIndex, taskSwitcherHelpers.longAnimationDuration, Easing.InOutQuad);
taskSwitcherHelpers.lastClosedTask = -1;
}
@ -73,10 +76,10 @@ FocusScope {
} else if (tasksCount < oldTasksCount) {
if (state.currentTaskIndex < 0) {
// if the user is on the first task, and it is closed, scroll right
taskSwitcherHelpers.animateGoToTaskIndex(0, Kirigami.Units.longDuration);
taskSwitcherHelpers.animateGoToTaskIndex(0, taskSwitcherHelpers.longAnimationDuration);
} else if (state.currentTaskIndex >= tasksCount) {
// if the user is on the last task, and it is closed, scroll left
taskSwitcherHelpers.animateGoToTaskIndex(tasksCount - 1, Kirigami.Units.longDuration);
taskSwitcherHelpers.animateGoToTaskIndex(tasksCount - 1, taskSwitcherHelpers.longAnimationDuration);
}
}
@ -350,7 +353,7 @@ FocusScope {
if (!root.taskSwitcherHelpers.taskDrawerOpened && unmodifiedYposition < root.taskSwitcherHelpers.openedYPosition) {
// if in a app, switch it to the new task when it is under the openedYPosition
taskList.setTaskOffsetValue(0, unmodifiedYposition < root.taskSwitcherHelpers.openedYPosition && root.taskSwitcherHelpers.notHomeScreenState);
root.taskSwitcherHelpers.openApp(newIndex, Kirigami.Units.longDuration * 4, Easing.OutExpo);
root.taskSwitcherHelpers.openApp(newIndex, root.taskSwitcherHelpers.extendedAnimationDuration, Easing.OutExpo);
} else {
// if already in the task switcher or above the openedYPosition, only change the focus to the new task
root.taskSwitcherHelpers.animateGoToTaskIndex(newIndex);
@ -463,8 +466,9 @@ FocusScope {
property real backgroundColorOpacity: 1
Behavior on backgroundColorOpacity {
id: backgroundColorOpacityAn
NumberAnimation {
duration: Kirigami.Units.longDuration
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.SpatialDefault
duration: root.taskSwitcherHelpers.longAnimationDuration
}
}
@ -643,12 +647,12 @@ FocusScope {
anchors.bottomMargin: root.bottomMargin
anchors.topMargin: root.topMargin
NumberAnimation on opacity {
MobileShell.MotionNumberAnimation on opacity {
id: closeAnim
type: MobileShell.Motion.Standard
running: false
to: 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.taskSwitcherHelpers.longAnimationDuration
onFinished: {
closeAllButton.closeRequested = false;
@ -664,7 +668,7 @@ FocusScope {
let baseOpacity = ((root.tasksCount === 0 && !root.taskSwitcherHelpers.currentlyBeingClosed) ? 0.9 : 0);
return root.taskSwitcherHelpers.gestureState == TaskSwitcherHelpers.GestureStates.TaskSwitcher ? baseOpacity : 0;
}
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.veryLongDuration } }
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsSlow; duration: root.veryLongAnimationDuration } }
anchors.centerIn: container
@ -692,7 +696,7 @@ FocusScope {
RowLayout {
id: scrubIconList
opacity: root.taskSwitcherHelpers.isInTaskScrubMode ? 1 : 0
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.taskSwitcherHelpers.longAnimationDuration } }
anchors.bottom: container.bottom
anchors.right: container.horizontalCenter
@ -704,7 +708,8 @@ FocusScope {
return -offset;
}
Behavior on anchors.rightMargin {
NumberAnimation {
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.SpatialDefault
duration: root.taskSwitcherHelpers.xAnimDuration;
easing.type: root.taskSwitcherHelpers.xAnimEasingType;
}
@ -735,7 +740,7 @@ FocusScope {
RowLayout {
id: scrubIndicator
opacity: root.taskSwitcherHelpers.isInTaskScrubMode ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 200 } }
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialDefault; duration: root.taskSwitcherHelpers.longAnimationDuration } }
anchors.bottom: container.bottom
anchors.horizontalCenter: container.horizontalCenter
@ -743,8 +748,8 @@ FocusScope {
Kirigami.Icon {
id: iconScrubBack
opacity: root.state.currentTaskIndex == 0 ? 0.3 : 1
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration * 2; easing.type: Easing.OutExpo } }
opacity: root.state.currentTaskIndex == 0 ? root.disabledScrubArrowOpacity : 1
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialExtended; duration: root.taskSwitcherHelpers.taskScrubAnimationDuration } }
Layout.alignment: Qt.AlignHCenter
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
@ -758,8 +763,8 @@ FocusScope {
Kirigami.Icon {
id: iconScrubFront
opacity: root.state.currentTaskIndex == root.tasksCount - 1 ? 0.3 : 1
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration * 2; easing.type: Easing.OutExpo } }
opacity: root.state.currentTaskIndex == root.tasksCount - 1 ? root.disabledScrubArrowOpacity : 1
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.SpatialExtended; duration: root.taskSwitcherHelpers.taskScrubAnimationDuration } }
Layout.alignment: Qt.AlignHCenter
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
@ -809,7 +814,7 @@ FocusScope {
}
opacity: (root.taskSwitcherHelpers.currentlyBeingClosed || root.state.gestureInProgress || !root.taskSwitcherHelpers.taskDrawerOpened) ? 0.0 : 1.0
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
Behavior on opacity { MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration } }
icon.name: "edit-clear-history"
font.bold: true

View file

@ -7,6 +7,7 @@ pragma ComponentBehavior: Bound
import QtQuick 2.15
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.taskswitcherplugin as TaskSwitcherPlugin
import org.kde.kwin 3.0 as KWinComponents
@ -97,7 +98,13 @@ QtObject {
property bool reachedHeightThreshold: false
// made as variables to keep x anim in task list and task scrub icon list in sync
property int xAnimDuration: Kirigami.Units.longDuration * 2
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialFast)
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialDefault)
readonly property int primaryAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Emphasized)
readonly property int taskScrubAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialExtended)
readonly property int extendedAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialVerySlow)
readonly property real closeScaleOut: MobileShell.Motion.closeScaleOut
property int xAnimDuration: taskScrubAnimationDuration
property int xAnimEasingType: Easing.OutExpo
// ~~ measurement constants ~~
@ -232,12 +239,12 @@ QtObject {
closeFactorAnim.restart();
}
function openApp(index: int, duration = Kirigami.Units.shortDuration, horizontalEasing = Easing.OutBack): void {
function openApp(index: int, duration = root.shortAnimationDuration, horizontalEasing = Easing.OutCubic): void {
// cancel any opening animations ongoing
openAnim.stop();
cancelAnimations();
animateGoToTaskIndex(index, duration);
animateGoToTaskIndex(index, duration, horizontalEasing);
openAppAnim.restart();
KWinComponents.Workspace.activeWindow = taskList.getTaskAt(index).window;
}
@ -253,8 +260,8 @@ QtObject {
}
// go to the task index, animated
function animateGoToTaskIndex(index: int, duration = Kirigami.Units.longDuration * 2, easing = Easing.OutExpo): void {
xAnimDuration = duration;
function animateGoToTaskIndex(index: int, duration = root.taskScrubAnimationDuration, easing = Easing.OutExpo): void {
xAnimDuration = MobileShell.Motion.enabled ? duration : 0;
xAnimEasingType = easing;
xAnim.to = xPositionFromTaskIndex(index) - (gestureState == TaskSwitcherHelpers.GestureStates.HorizontalSwipe && !state.gestureInProgress && notHomeScreenState ? taskSpacing / 2 : 0);
xAnim.restart();
@ -309,19 +316,20 @@ QtObject {
// ~~ property animators ~~
property var xAnim: NumberAnimation {
property var xAnim: MobileShell.MotionNumberAnimation {
target: root.state
property: "xPosition"
type: MobileShell.Motion.SpatialDefault
duration: root.xAnimDuration
easing.type: root.xAnimEasingType
}
property var openAnim: NumberAnimation {
property var openAnim: MobileShell.MotionNumberAnimation {
target: root.state
property: "yPosition"
to: root.openedYPosition
duration: 250
easing.type: Easing.OutQuart
type: MobileShell.Motion.EmphasizedDecel
duration: root.primaryAnimationDuration
onFinished: {
if (!root.isInTaskScrubMode) {
@ -330,15 +338,13 @@ QtObject {
}
}
// TODO: This animation should ideally be replaced by some
// speed tracking to track finger movement better. Until then
// InBack at least pretends to go in the finger move direction
property var closeAnim: NumberAnimation {
// Mirror the opening deceleration with an accelerating exit, without overshooting the gesture path.
property var closeAnim: MobileShell.MotionNumberAnimation {
target: root.state
property: "yPosition"
to: 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InBack
type: MobileShell.Motion.EmphasizedAccel
duration: root.primaryAnimationDuration
onFinished: {
root.inLastFrame = true;
@ -347,32 +353,32 @@ QtObject {
}
}
property var closeScaleAnim: NumberAnimation {
property var closeScaleAnim: MobileShell.MotionNumberAnimation {
target: root
property: "closingScalingFactor"
to: 0.1
duration: Kirigami.Units.longDuration
easing.type: Easing.InQuad
to: root.closeScaleOut
type: MobileShell.Motion.EmphasizedAccel
duration: root.primaryAnimationDuration
onStopped: {
root.closingScalingFactor = 1;
}
}
property var closeFactorAnim: NumberAnimation {
property var closeFactorAnim: MobileShell.MotionNumberAnimation {
target: root
property: "closingFactor"
to: 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InQuad
type: MobileShell.Motion.EmphasizedAccel
duration: root.primaryAnimationDuration
}
property var openAppAnim: NumberAnimation {
property var openAppAnim: MobileShell.MotionNumberAnimation {
target: root.state
property: "yPosition"
to: 0
duration: 300
easing.type: Easing.OutQuint
type: MobileShell.Motion.Emphasized
duration: root.primaryAnimationDuration
onFinished: {
root.inLastFrame = true;
root.state.status = TaskSwitcherPlugin.MobileTaskSwitcherState.Inactive;

View file

@ -9,7 +9,7 @@ import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Loader {
id: root
property var currentWindow
property var currentWindow: null
// Windows awaiting geometry clamping after un-maximize in convergence
// mode. Using an array so concurrent un-maximizes are not lost.
@ -28,6 +28,7 @@ Loader {
root.pendingConstrainWindows = []
for (const window of windows) {
if (!window || window.deleted || !window.normalWindow) continue
if (root.dynamicTilingOwnsWindowPlacement()) continue
if (!ShellSettings.Settings.convergenceModeEnabled) continue
if (ShellSettings.Settings.gamingModeEnabled) continue
@ -52,11 +53,22 @@ Loader {
}
}
function dynamicTilingOwnsWindowPlacement() {
return ShellSettings.Settings.convergenceModeEnabled
&& ShellSettings.Settings.dynamicTilingEnabled
&& !ShellSettings.Settings.gamingModeEnabled;
}
function run(window) {
if (!window || window.deleted || !window.normalWindow) {
return;
}
if (root.dynamicTilingOwnsWindowPlacement()) {
window.noBorder = false;
return;
}
// HACK: don't maximize xwaylandvideobridge
// see: https://invent.kde.org/plasma/plasma-mobile/-/issues/324
if (window.resourceClass === 'xwaylandvideobridge') {
@ -97,7 +109,7 @@ Loader {
}
Connections {
target: currentWindow
target: root.currentWindow
function onFullScreenChanged() {
if (!currentWindow) {
@ -153,6 +165,16 @@ Loader {
}
}
}
function onDynamicTilingEnabledChanged() {
const windows = KWinComponents.Workspace.windows;
for (let i = 0; i < windows.length; i++) {
if (windows[i].normalWindow) {
root.run(windows[i]);
}
}
}
}
Connections {

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,7 @@ Item {
property alias circleOpacity: buttonRect.opacity
property alias circleVisiblity: buttonRect.visible
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
readonly property color buttonBorderColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.65)
signal clicked
@ -39,7 +40,7 @@ Item {
color: Kirigami.Theme.backgroundColor
opacity: mouseArea.containsPress ? 1 : 0.6
border {
color: Qt.rgba(255, 255, 255, 0.8)
color: root.buttonBorderColor
width: 1
}
}

View file

@ -15,10 +15,13 @@ import org.kde.kirigami as Kirigami
import org.kde.coreaddons 1.0 as KCoreAddons
import org.kde.plasma.private.sessions 2.0
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
Item {
id: root
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property real backgroundDimOpacity: 0.6
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
Kirigami.Theme.inherit: false
@ -71,15 +74,15 @@ Item {
target: buttons
from: 0
to: 1
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
OpacityAnimator {
target: background
from: 0
to: 0.6
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
to: root.backgroundDimOpacity
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
}
@ -98,22 +101,22 @@ Item {
target: buttons
from: 1
to: 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
OpacityAnimator {
target: background
from: 0.6
from: root.backgroundDimOpacity
to: 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
OpacityAnimator {
target: blackOverlay
from: 0
to: closeAnim.closeToBlack ? 1 : 0
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
}
ScriptAction {
@ -122,7 +125,7 @@ Item {
closeAnim.callback();
}
buttons.opacity = 1;
background.opacity = 0.6;
background.opacity = root.backgroundDimOpacity;
}
}
}

View file

@ -6,6 +6,7 @@
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
Rectangle {
id: root
@ -15,6 +16,9 @@ Rectangle {
property int stage
readonly property bool busy: stage > 1 && stage < 6
readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
readonly property int veryLongAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow)
readonly property int spinnerAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.EffectsSlow) * 3.5)
Item {
id: content
@ -25,8 +29,8 @@ Rectangle {
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.veryLongDuration
easing.type: Easing.InOutQuad
duration: root.veryLongAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsSlow)
}
}
@ -63,8 +67,8 @@ Rectangle {
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
duration: root.longAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
}
}
@ -89,9 +93,9 @@ Rectangle {
RotationAnimator on rotation {
from: 0
to: 360
duration: 1400
duration: root.spinnerAnimationDuration
loops: Animation.Infinite
running: root.busy && Kirigami.Units.longDuration > 1
running: root.busy && MobileShell.Motion.enabled
}
}
}

View file

@ -11,6 +11,7 @@ import org.kde.plasma.plasmoid
import org.kde.kirigami as Kirigami
import org.kde.plasma.configuration 2.0
import org.kde.kitemmodels 1.0 as KItemModels
import org.kde.plasma.private.mobileshell as MobileShell
import './private'
@ -28,6 +29,7 @@ Item {
property bool isContainment: false
property alias app: appLoader.item
property bool loadApp: true
readonly property int appAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
signal appLoaded()
@ -132,10 +134,10 @@ Item {
opacity: 0
scale: 0.7 + 0.3 * app.opacity
NumberAnimation on opacity {
MobileShell.MotionNumberAnimation on opacity {
id: opacityAnim
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
type: MobileShell.Motion.EffectsDefault
duration: root.appAnimationDuration
onFinished: {
if (app.opacity === 0) {
root.Window.window.close();

View file

@ -47,10 +47,10 @@ MobileShell.SwipeArea {
}
}
NumberAnimation on position {
MobileShell.MotionNumberAnimation on position {
id: positionAnim
type: MobileShell.Motion.SpatialSlow
duration: root.animationDuration
easing.type: Easing.OutExpo
onFinished: {
if (root.position === keypadHeight) {

View file

@ -17,6 +17,8 @@ Item {
id: root
required property real openProgress
required property var lockScreenState
readonly property int layoutAnimationDuration: openProgress > 0.5 ? MobileShell.Motion.duration(MobileShell.Motion.Emphasized) : 0
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
property alias passwordBar: passwordBar
@ -63,8 +65,8 @@ Item {
transitions: Transition {
AnchorAnimation {
easing.type: Easing.OutCirc
duration: openProgress > 0.5 ? 300 : 0
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
duration: root.layoutAnimationDuration
}
}
}
@ -102,8 +104,8 @@ Item {
transitions: Transition {
AnchorAnimation {
easing.type: Easing.OutCirc
duration: openProgress > 0.5 ? 300 : 0
easing.type: MobileShell.Motion.easing(MobileShell.Motion.Emphasized)
duration: root.layoutAnimationDuration
}
}
}
@ -126,7 +128,7 @@ Item {
Layout.topMargin: keypadVerticalContainer.visible ? Kirigami.Units.gridUnit * 3 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
@ -172,8 +174,8 @@ Item {
opacity: enabled
Behavior on opacity {
SequentialAnimation {
PauseAnimation { duration: 20 * index }
NumberAnimation { duration: 300 }
PauseAnimation { duration: MobileShell.Motion.enabled ? 20 * index : 0 }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Emphasized; duration: root.layoutAnimationDuration }
}
}

View file

@ -108,7 +108,7 @@ Item {
property alias passwordBar: keypad.passwordBar
// Speed up animation when passwordless
animationDuration: Kirigami.Units.veryLongDuration
animationDuration: MobileShell.Motion.duration(MobileShell.Motion.SpatialSlow)
// Distance to swipe to fully open keypad
keypadHeight: Kirigami.Units.gridUnit * 20

View file

@ -7,6 +7,7 @@ import QtQuick.Layouts
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.plasma.workspace.keyboardlayout 1.0 as Keyboards
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.kirigami as Kirigami
@ -23,9 +24,12 @@ Rectangle {
readonly property color headerTextColor: Qt.rgba(255, 255, 255, 1)
readonly property color headerTextInactiveColor: Qt.rgba(255, 255, 255, 0.4)
readonly property color passwordBarSurfaceColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.18)
readonly property int quickAnimationDuration: Math.round(MobileShell.Motion.duration(MobileShell.Motion.Press) * 2 / 3)
readonly property int previewAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.Press)
radius: Kirigami.Units.largeSpacing
color: Qt.rgba(255, 255, 255, 0.2)
color: root.passwordBarSurfaceColor
// model for shown dots
// we need to use a listmodel to avoid all delegates from reloading
@ -223,7 +227,7 @@ Rectangle {
model: dotDisplayModel
Behavior on implicitWidth {
NumberAnimation { duration: 50 }
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.Press; duration: root.quickAnimationDuration }
}
onImplicitWidthChanged: {
@ -242,7 +246,7 @@ Rectangle {
Component.onCompleted: {
if (showChar) {
charAnimation.to = 1;
charAnimation.duration = 75;
charAnimation.duration = root.previewAnimationDuration;
charAnimation.restart();
} else {
dotAnimation.to = 1;
@ -253,7 +257,7 @@ Rectangle {
onShowCharChanged: {
if (!showChar) {
charAnimation.to = 0;
charAnimation.duration = 50;
charAnimation.duration = root.quickAnimationDuration;
charAnimation.restart();
dotAnimation.to = 1;
dotAnimation.start();
@ -269,11 +273,12 @@ Rectangle {
radius: width
color: lockScreenState.waitingForAuth ? root.headerTextInactiveColor : root.headerTextColor // dim when waiting for auth
PropertyAnimation {
MobileShell.MotionNumberAnimation {
id: dotAnimation
target: dot;
property: "scale";
duration: 50
type: MobileShell.Motion.Press
duration: root.quickAnimationDuration
}
}
@ -285,10 +290,11 @@ Rectangle {
text: model.char
font.pointSize: 12
PropertyAnimation {
MobileShell.MotionNumberAnimation {
id: charAnimation
target: charLabel;
property: "scale";
type: MobileShell.Motion.Press
}
}
}

Some files were not shown because too many files have changed in this diff Show more