forked from Shinonome/dots-hyprland
taskbar: window previews
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m4.21 4.387.083-.094a1 1 0 0 1 1.32-.083l.094.083L12 10.585l6.293-6.292a1 1 0 1 1 1.414 1.414L13.415 12l6.292 6.293a1 1 0 0 1 .083 1.32l-.083.094a1 1 0 0 1-1.32.083l-.094-.083L12 13.415l-6.293 6.292a1 1 0 0 1-1.414-1.414L10.585 12 4.293 5.707a1 1 0 0 1-.083-1.32l.083-.094-.083.094Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 410 B |
@@ -10,8 +10,16 @@ BarButton {
|
||||
|
||||
required property string iconName
|
||||
property bool separateLightDark: false
|
||||
leftInset: 2
|
||||
rightInset: 2
|
||||
implicitWidth: height - topInset - bottomInset + leftInset + rightInset
|
||||
|
||||
onDownChanged: {
|
||||
scaleAnim.duration = root.down ? 150 : 200
|
||||
scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
|
||||
contentItem.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
id: contentItem
|
||||
anchors.centerIn: root.background
|
||||
@@ -19,12 +27,10 @@ BarButton {
|
||||
implicitHeight: iconWidget.implicitHeight
|
||||
implicitWidth: iconWidget.implicitWidth
|
||||
|
||||
scale: root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 90
|
||||
id: scaleAnim
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +38,7 @@ BarButton {
|
||||
id: iconWidget
|
||||
anchors.centerIn: parent
|
||||
iconName: root.iconName
|
||||
separateLightDark: root.separateLightDark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Kirigami.Icon {
|
||||
id: iconWidget
|
||||
id: root
|
||||
required property string iconName
|
||||
property bool separateLightDark: false
|
||||
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
property real implicitSize: 26
|
||||
implicitWidth: implicitSize
|
||||
implicitHeight: implicitSize
|
||||
roundToIconSize: false
|
||||
source: `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg`
|
||||
fallback: root.iconName
|
||||
|
||||
@@ -11,17 +11,9 @@ Button {
|
||||
Layout.fillHeight: true
|
||||
topInset: 4
|
||||
bottomInset: 4
|
||||
|
||||
property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, ((root.hovered && !root.down) || root.checked) ? Looks.fluentContentTransparency : 1)
|
||||
Behavior on borderColor {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
onBorderColorChanged: {
|
||||
borderCanvas.requestPaint();
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
background: AcrylicRectangle {
|
||||
shiny: ((root.hovered && !root.down) || root.checked)
|
||||
color: {
|
||||
if (root.down) {
|
||||
return Looks.colors.bg1Active
|
||||
@@ -31,48 +23,5 @@ Button {
|
||||
return ColorUtils.transparentize(Looks.colors.bg1)
|
||||
}
|
||||
}
|
||||
radius: Looks.radius.medium
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
|
||||
// Top 1px border with color
|
||||
Canvas {
|
||||
id: borderCanvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
var borderColor = root.borderColor;
|
||||
|
||||
var r = background.radius;
|
||||
var fadeLength = Math.max(1, r);
|
||||
var fadeLengthPercent = fadeLength / width;
|
||||
|
||||
// Compute normalized stops
|
||||
var leftFadeStop = fadeLengthPercent;
|
||||
var rightFadeStop = 1 - fadeLengthPercent;
|
||||
|
||||
var grad = ctx.createLinearGradient(0, 0, width, 0);
|
||||
grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
grad.addColorStop(leftFadeStop, borderColor);
|
||||
grad.addColorStop(rightFadeStop, borderColor);
|
||||
grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
|
||||
ctx.strokeStyle = grad;
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(r, 0.5);
|
||||
ctx.lineTo(width - r, 0.5);
|
||||
// Top-right curve
|
||||
ctx.arcTo(width, 0.5, width, r + 0.5, r);
|
||||
// Top-left curve
|
||||
ctx.moveTo(width - r, 0.5);
|
||||
ctx.arcTo(0, 0.5, 0, r + 0.5, r);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,23 @@ import QtQuick.Layouts
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
import Quickshell
|
||||
|
||||
AppButton {
|
||||
id: root
|
||||
|
||||
required property var toplevel
|
||||
readonly property bool isSeparator: toplevel.appId === "SEPARATOR"
|
||||
readonly property var desktopEntry: DesktopEntries.heuristicLookup(toplevel.appId)
|
||||
required property var appEntry
|
||||
readonly property bool isSeparator: appEntry.appId === "SEPARATOR"
|
||||
readonly property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId)
|
||||
|
||||
Layout.fillHeight: true
|
||||
signal hoverPreviewRequested()
|
||||
|
||||
iconName: toplevel.appId
|
||||
iconName: AppSearch.guessIcon(appEntry.appId)
|
||||
Timer {
|
||||
running: root.hovered
|
||||
interval: 250
|
||||
onTriggered: {
|
||||
root.hoverPreviewRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
import Quickshell
|
||||
|
||||
PopupWindow {
|
||||
id: root
|
||||
|
||||
///////////////////// Properties ////////////////////
|
||||
required property bool tasksHovered
|
||||
property var appEntry
|
||||
property Item anchorItem
|
||||
|
||||
//////////////////// Functions ////////////////////
|
||||
function close() {
|
||||
marginBehavior.enabled = false;
|
||||
root.visible = false;
|
||||
}
|
||||
|
||||
function open() {
|
||||
marginBehavior.enabled = true;
|
||||
root.visible = true;
|
||||
}
|
||||
|
||||
function show(appEntry: var, button: Item) {
|
||||
root.appEntry = appEntry;
|
||||
root.anchorItem = button;
|
||||
root.anchor.updateAnchor();
|
||||
root.open();
|
||||
}
|
||||
|
||||
///////////////////// Internals /////////////////////
|
||||
readonly property bool bottom: Config.options.waffles.bar.bottom
|
||||
property real visualMargin: 12
|
||||
property alias ambientShadowWidth: ambientShadow.border.width
|
||||
|
||||
visible: false
|
||||
color: "transparent"
|
||||
implicitWidth: contentItem.implicitWidth + ambientShadowWidth + (visualMargin * 2)
|
||||
implicitHeight: contentItem.implicitHeight + ambientShadowWidth + (visualMargin * 2)
|
||||
anchor {
|
||||
adjustment: PopupAdjustment.Slide
|
||||
item: root.anchorItem
|
||||
gravity: bottom ? Edges.Top : Edges.Bottom
|
||||
edges: bottom ? Edges.Top : Edges.Bottom
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 250
|
||||
running: root.visible && !hoverChecker.containsMouse && !root.tasksHovered
|
||||
onTriggered: {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
MouseArea {
|
||||
id: hoverChecker
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
// Shadow
|
||||
Rectangle {
|
||||
id: ambientShadow
|
||||
anchors {
|
||||
fill: contentItem
|
||||
margins: -border.width
|
||||
}
|
||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.contentTransparency)
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: Looks.radius.large + border.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contentItem
|
||||
property real sourceEdgeMargin: root.visible ? (root.ambientShadowWidth + root.visualMargin) : -root.implicitHeight
|
||||
Behavior on sourceEdgeMargin {
|
||||
id: marginBehavior
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: root.bottom ? undefined : parent.top
|
||||
bottom: root.bottom ? parent.bottom : undefined
|
||||
margins: root.ambientShadowWidth + root.visualMargin
|
||||
// Opening anim
|
||||
bottomMargin: root.bottom ? sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin)
|
||||
topMargin: root.bottom ? (root.ambientShadowWidth + root.visualMargin) : sourceEdgeMargin
|
||||
}
|
||||
color: Looks.colors.bg1
|
||||
radius: Looks.radius.large
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
width: contentItem.width
|
||||
height: contentItem.height
|
||||
radius: contentItem.radius
|
||||
}
|
||||
}
|
||||
|
||||
// Testing
|
||||
implicitHeight: Math.min(158, windowsRow.implicitHeight)
|
||||
implicitWidth: windowsRow.implicitWidth
|
||||
|
||||
RowLayout {
|
||||
id: windowsRow
|
||||
anchors.fill: parent
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: root.appEntry?.toplevels ?? []
|
||||
}
|
||||
delegate: WindowPreview {
|
||||
required property var modelData
|
||||
toplevel: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,30 +5,41 @@ import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Item {
|
||||
MouseArea {
|
||||
id: root
|
||||
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: row.implicitHeight
|
||||
implicitWidth: row.implicitWidth
|
||||
hoverEnabled: true
|
||||
|
||||
// Apps row
|
||||
RowLayout {
|
||||
id: row
|
||||
anchors.fill: parent
|
||||
spacing: 4
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
// TODO: Include only apps (and windows) in current workspace only
|
||||
model: ScriptModel {
|
||||
objectProp: "appId"
|
||||
values: TaskbarApps.apps.filter(app => app.appId !== "SEPARATOR")
|
||||
}
|
||||
delegate: TaskAppButton {
|
||||
required property var modelData
|
||||
toplevel: modelData
|
||||
appEntry: modelData
|
||||
|
||||
onHoverPreviewRequested: {
|
||||
previewPopup.show(appEntry, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Previews popup
|
||||
// Previews popup
|
||||
TaskPreview {
|
||||
id: previewPopup
|
||||
tasksHovered: root.containsMouse
|
||||
anchor.window: root.QsWindow.window
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ Rectangle {
|
||||
|
||||
BarGroupRow {
|
||||
id: appsRow
|
||||
spacing: 4
|
||||
anchors.left: undefined
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
|
||||
Button {
|
||||
id: root
|
||||
|
||||
required property var toplevel
|
||||
property real previewWidthConstraint: 200
|
||||
property real previewHeightConstraint: 110
|
||||
padding: 5
|
||||
Layout.fillHeight: true
|
||||
|
||||
onClicked: {
|
||||
root.toplevel.activate(); // TODO: make this work with those who disable focus on activate because telegram is abusive
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
radius: Looks.radius.medium
|
||||
color: root.down ? Looks.colors.bg2Active : (root.hovered ? Looks.colors.bg2Hover : ColorUtils.transparentize(Looks.colors.bg2))
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: contentItem
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.padding
|
||||
spacing: 5
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: false
|
||||
spacing: 8
|
||||
|
||||
AppIcon {
|
||||
id: appIcon
|
||||
Layout.leftMargin: Looks.radius.large - root.padding + 2
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
iconName: AppSearch.guessIcon(root.toplevel.appId)
|
||||
implicitSize: 16
|
||||
}
|
||||
|
||||
Item {
|
||||
id: appTitleContainer
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: closeButton.implicitHeight // Enforce height, because closeButton doesn't contribute when it's invisible
|
||||
WText {
|
||||
id: appTitleText
|
||||
anchors.fill: parent
|
||||
text: root.toplevel.title
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
font.weight: Looks.font.weight.thin
|
||||
color: Looks.colors.fg1
|
||||
}
|
||||
}
|
||||
|
||||
CloseButton {
|
||||
id: closeButton
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.margins: Looks.radius.large - root.padding
|
||||
Layout.topMargin: 0
|
||||
implicitWidth: Math.max(screencopyView.implicitWidth, 80)
|
||||
implicitHeight: screencopyView.implicitHeight
|
||||
|
||||
ScreencopyView {
|
||||
id: screencopyView
|
||||
anchors.centerIn: parent
|
||||
captureSource: root.toplevel
|
||||
live: true
|
||||
paintCursor: true
|
||||
constraintSize: Qt.size(root.previewWidthConstraint, root.previewHeightConstraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component CloseButton: Button {
|
||||
id: reusableCloseButton
|
||||
visible: root.hovered
|
||||
Layout.leftMargin: 4
|
||||
implicitHeight: 30
|
||||
implicitWidth: 30
|
||||
onClicked: {
|
||||
root.toplevel.close();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: 0
|
||||
color: "transparent"
|
||||
anchors.fill: closeButtonBg
|
||||
anchors.margins: -1
|
||||
opacity: closeButtonBg.opacity
|
||||
border.width: 1
|
||||
radius: closeButtonBg.radius + 1
|
||||
border.color: Looks.colors.bg2Border
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: closeButtonBg
|
||||
z: 1
|
||||
opacity: reusableCloseButton.hovered ? 1 : 0
|
||||
radius: Looks.radius.large - root.padding
|
||||
color: reusableCloseButton.pressed ? Looks.colors.dangerActive : Looks.colors.danger
|
||||
Behavior on opacity {
|
||||
animation: Looks.transition.opacity.createObject(this)
|
||||
}
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: FluentIcon {
|
||||
z: 2
|
||||
anchors.centerIn: parent
|
||||
icon: "dismiss"
|
||||
implicitSize: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool shiny: true // Top border
|
||||
property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, shiny ? Looks.contentTransparency : 1)
|
||||
color: Looks.colors.bg1Hover
|
||||
radius: Looks.radius.medium
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
Behavior on borderColor {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
onBorderColorChanged: {
|
||||
borderCanvas.requestPaint();
|
||||
}
|
||||
|
||||
// Top 1px border with color
|
||||
Canvas {
|
||||
id: borderCanvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
var borderColor = root.borderColor;
|
||||
|
||||
var r = root.radius;
|
||||
var fadeLength = Math.max(1, r);
|
||||
var fadeLengthPercent = fadeLength / width;
|
||||
|
||||
// Compute normalized stops
|
||||
var leftFadeStop = fadeLengthPercent;
|
||||
var rightFadeStop = 1 - fadeLengthPercent;
|
||||
|
||||
var grad = ctx.createLinearGradient(0, 0, width, 0);
|
||||
grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
grad.addColorStop(leftFadeStop, borderColor);
|
||||
grad.addColorStop(rightFadeStop, borderColor);
|
||||
grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
|
||||
|
||||
ctx.strokeStyle = grad;
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(r, 0.5);
|
||||
ctx.lineTo(width - r, 0.5);
|
||||
// Top-right curve
|
||||
ctx.arcTo(width, 0.5, width, r + 0.5, r);
|
||||
// Top-left curve
|
||||
ctx.moveTo(width - r, 0.5);
|
||||
ctx.arcTo(0, 0.5, 0, r + 0.5, r);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,24 @@ Singleton {
|
||||
property string iconsPath: `${Directories.assetsPath}/icons/fluent`
|
||||
property bool dark: Appearance.m3colors.darkmode
|
||||
|
||||
property real fluentBackgroundTransparency: 0.17
|
||||
property real fluentContentTransparency: 0.3
|
||||
property real backgroundTransparency: 0.17
|
||||
property real contentTransparency: 0.25
|
||||
colors: QtObject {
|
||||
id: colors
|
||||
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
|
||||
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
|
||||
property color bg1: root.dark ? "#2E2E2E" : "#F7F7F7"
|
||||
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
|
||||
property color bg1Hover: root.dark ? "#292929" : "#F7F7F7"
|
||||
property color bg1Active: root.dark ? "#252525" : "#F3F3F3"
|
||||
property color bg1Border: root.dark ? "#333333" : "#E9E9E9"
|
||||
property color bg2: root.dark ? "#313131" : "#FBFBFB"
|
||||
property color bg2Hover: root.dark ? "#383838" : "#FDFDFD"
|
||||
property color bg2Active: root.dark ? "#333333" : "#FDFDFD"
|
||||
property color bg2Border: root.dark ? "#464646" : "#EEEEEE"
|
||||
property color fg: root.dark ? "#FFFFFF" : "#000000"
|
||||
property color fg1: root.dark ? "#D1D1D1" : "#626262"
|
||||
property color danger: "#C42B1C"
|
||||
property color dangerActive: "#B62D1F"
|
||||
property color brand: Appearance.m3colors.m3primary
|
||||
}
|
||||
|
||||
@@ -44,12 +51,14 @@ Singleton {
|
||||
property string ui: "Noto Sans"
|
||||
}
|
||||
property QtObject weight: QtObject { // Noto is not Segoe, so we might use slightly different weights
|
||||
property int thin: Font.Normal
|
||||
property int regular: Font.Medium
|
||||
property int strong: Font.DemiBold
|
||||
property int stronger: Font.Bold
|
||||
}
|
||||
property QtObject pixelSize: QtObject {
|
||||
property real normal: 11
|
||||
property real large: 15
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,15 +66,15 @@ Singleton {
|
||||
id: transition
|
||||
property QtObject easing: QtObject {
|
||||
property QtObject bezierCurve: QtObject {
|
||||
readonly property list<real> easeInOut: [0.42,0.00,0.58,1.00]
|
||||
readonly property list<real> easeIn: [0,1,1,1]
|
||||
readonly property list<real> easeOut: [1,0,1,1]
|
||||
readonly property list<real> easeInOut: [0.42,0.00,0.58,1.00,1,1]
|
||||
readonly property list<real> easeIn: [0,1,1,1,1,1]
|
||||
readonly property list<real> easeOut: [1,0,1,1,1,1]
|
||||
}
|
||||
}
|
||||
|
||||
property Component color: Component {
|
||||
ColorAnimation {
|
||||
duration: 80
|
||||
duration: 120
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
@@ -73,7 +82,7 @@ Singleton {
|
||||
|
||||
property Component opacity: Component {
|
||||
NumberAnimation{
|
||||
duration: 80
|
||||
duration: 120
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
|
||||
@@ -151,6 +151,6 @@ Singleton {
|
||||
|
||||
|
||||
// Give up
|
||||
return str;
|
||||
return "application-x-executable";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user