添加切换全屏动画

This commit is contained in:
qiqi 2023-03-20 15:33:32 +08:00 committed by hewenfei
parent e1cee053cc
commit 0f0170801b
11 changed files with 225 additions and 80 deletions

View File

@ -1,3 +1,21 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5 import QtQuick.Controls 2.5

View File

@ -2,7 +2,6 @@ import QtQuick 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import QtQml.Models 2.12 import QtQml.Models 2.12
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
import AppControls2 1.0 as AppControls2 import AppControls2 1.0 as AppControls2

View File

@ -1,7 +1,6 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import AppControls2 1.0 as AppControls2 import AppControls2 1.0 as AppControls2
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
@ -23,10 +22,7 @@ Item {
width: 48 width: 48
height: 48 height: 48
buttonIcon: "image://appicon/view-restore-symbolic" buttonIcon: "image://appicon/view-restore-symbolic"
onClicked: { onClicked: mainWindow.exitFullScreen()
mainWindow.isFullScreen = false;
}
} }
} }

View File

@ -1,6 +1,11 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
Item { import AppControls2 1.0 as AppControls2
import org.ukui.menu.core 1.0
AppControls2.StyleBackground {
paletteRole: Palette.Dark
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 35 anchors.leftMargin: 35

View File

@ -3,9 +3,7 @@ import QtQuick.Controls 2.0 as QQC2
import AppControls2 1.0 as AppControls2 import AppControls2 1.0 as AppControls2
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
AppControls2.StyleBackground { Item {
paletteRole: Palette.Window
radius: 12
Row { Row {
anchors.fill: parent; anchors.fill: parent;

View File

@ -58,20 +58,20 @@ Item {
} }
} }
Item { AppControls2.StyleBackground {
width: 34 width: 34; height: width
height: 34 radius: 4
Rectangle { useStyleTransparent: false
anchors.fill: parent alpha: buttonMouseArea.containsPress ? 0.65 : buttonMouseArea.containsMouse ? 0.40 : 0.00
radius: height / 2 Image {
color: "lightblue" anchors.centerIn: parent
width: parent.width / 2; height: width
source: "image://appicon/view-fullscreen-symbolic"
MouseArea { MouseArea {
id: buttonMouseArea
hoverEnabled: true
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: mainWindow.isFullScreen = true
//
console.log("==开始全屏==")
mainWindow.isFullScreen = true;
}
} }
} }
} }

View File

@ -17,8 +17,6 @@
*/ */
import QtQuick 2.12 import QtQuick 2.12
import QtQml 2.12
import AppUI 1.0 as AppUI import AppUI 1.0 as AppUI
import AppControls2 1.0 as AppControls2 import AppControls2 1.0 as AppControls2
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
@ -26,35 +24,48 @@ import org.ukui.menu.core 1.0
Item { Item {
id: root id: root
clip: true clip: true
property int animationDuration: 150
property int animationDuration: menuSetting.get("animationDuration")
property var normalGeometry: mainWindow.normalScreenSize()
property double transparency: mainWindow.transparency
property bool onComlpeted: false
Component.onCompleted: { Component.onCompleted: {
loader.reloadUI(); mainWindow.fullScreenChanged.connect(enterFullScreen);
mainWindow.beforeFullScreenChanged.connect(beforeFullScreenSlot); mainWindow.beforeFullScreenExited.connect(exitFullScreen);
mainWindow.fullScreenChanged.connect(fullScreenChangedSlot); menuSetting.changed.connect(updateAnimationDuration);
onComlpeted = true;
} }
function fullScreenChangedSlot() { function enterFullScreen() {
loader.opacity = 0; if (mainWindow.isFullScreen) {
fullScreenAnimation.start(); normalHide.start();
} fullShow.start();
backgroundMask.state = "fullScreen";
function beforeFullScreenSlot(status) { if (root.transparency <= 0.6) {
if (!status) { maskHide.start();
loader.sourceComponent = undefined; }
} }
backgroundMask.alpha = status ? 0.5 : 0
backgroundMask.enableSizeChange = false;
} }
ParallelAnimation { function exitFullScreen() {
id: fullScreenAnimation normalShow.start();
NumberAnimation { target: backgroundMask; property: "width"; to: root.width; duration: root.animationDuration } fullHide.start();
NumberAnimation { target: backgroundMask; property: "height"; to: root.height; duration: root.animationDuration } backgroundMask.state = "normalScreen";
if (root.transparency <= 0.6) {
maskShow.start();
}
}
onFinished: { function updateAnimationDuration(key) {
backgroundMask.enableSizeChange = true; if (key === "animationDuration") {
loader.reloadUI(); root.animationDuration = menuSetting.get("animationDuration");
}
}
onTransparencyChanged: {
if (transparency > 0.6) {
backgroundMask.opacity = 1;
} }
} }
@ -62,44 +73,101 @@ Item {
id: backgroundMask id: backgroundMask
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
alpha: 0 radius: 12
useStyleTransparent: false state: "normalScreen"
paletteRole: Palette.Dark
property bool enableSizeChange: true onHeightChanged: {
if (root.transparency <= 0.6 && root.onComlpeted) {
mainWindow.changeWindowBlurRegion(0, root.height - height, width, height)
}
}
NumberAnimation {
id: maskHide
target: backgroundMask; property: "opacity"
from: 1.0; to: 0;
duration: root.animationDuration / 4; easing.type: Easing.InOutQuad
}
NumberAnimation {
id: maskShow
target: backgroundMask; property: "opacity"
from: 0; to: 1.0;
duration: root.animationDuration * 2; easing.type: Easing.InOutExpo
}
states: [ states: [
State { State {
name: "disableSizeChange" name: "normalScreen"
when: !backgroundMask.enableSizeChange PropertyChanges { target: backgroundMask; height: root.normalGeometry.height; width: root.normalGeometry.width }
AnchorChanges {
target: backgroundMask
anchors.top: undefined
anchors.right: undefined
}
}, },
State { State {
name: "enableSizeChange" name: "fullScreen"
when: backgroundMask.enableSizeChange PropertyChanges { target: backgroundMask; height: root.height; width: root.width }
AnchorChanges { PropertyChanges { target: normalScreenLoader; anchors.margins: 8 }
target: backgroundMask AnchorChanges { target: normalScreenLoader; anchors.bottom: root.bottom; anchors.left: root.left }
anchors.top: parent.top
anchors.right: parent.right
}
} }
] ]
Loader { transitions: [
id: loader Transition {
anchors.fill: parent to: "fullScreen"
Behavior on opacity { SequentialAnimation {
NumberAnimation { duration: root.animationDuration } ScriptAction {
script: {
normalScreenLoader.anchors.left = root.left;
normalScreenLoader.anchors.bottom = root.bottom;
normalScreenLoader.anchors.margins = 8;
fullScreenLoader.active = true;
}
}
NumberAnimation { properties: "height,width"; duration: root.animationDuration; easing.type: Easing.InOutQuad }
ScriptAction {
script: {
normalScreenLoader.active = false;
mainWindow.enableWindowBlur(true);
}
}
}
},
Transition {
to: "normalScreen"
SequentialAnimation {
ScriptAction {
script: {
normalScreenLoader.active = true;
mainWindow.enableWindowBlur(false);
}
}
NumberAnimation { properties: "height,width"; duration: root.animationDuration; easing.type: Easing.InOutQuad }
ScriptAction {
script: {
fullScreenLoader.active = false;
mainWindow.isFullScreen = false;
}
}
}
} }
function reloadUI() { ]
loader.sourceComponent = mainWindow.isFullScreen ? fullSceenComponent : normalComponent; }
loader.opacity = 1;
} Loader {
} id: normalScreenLoader
height: root.normalGeometry.height; width: root.normalGeometry.width
anchors.bottom: root.bottom
anchors.left: root.left
sourceComponent: normalComponent
NumberAnimation { id: normalShow; target: normalScreenLoader; properties: "opacity"; from: 0; to: 1; duration: root.animationDuration; easing.type: Easing.InQuint }
NumberAnimation { id: normalHide; target: normalScreenLoader; properties: "opacity"; from: 1; to: 0; duration: root.animationDuration; easing.type: Easing.OutQuint }
}
Loader {
id: fullScreenLoader
anchors.fill: parent
sourceComponent: fullSceenComponent
opacity: 0
NumberAnimation { id: fullShow; target: fullScreenLoader; properties: "opacity"; from: 0; to: 1; duration: root.animationDuration; easing.type: Easing.InQuint }
NumberAnimation { id: fullHide; target: fullScreenLoader; properties: "opacity"; from: 1; to: 0; duration: root.animationDuration; easing.type: Easing.OutQuint }
} }
Component { Component {

View File

@ -25,6 +25,7 @@
#define UKUI_MENU_SCHEMA "org.ukui.menu.settings" #define UKUI_MENU_SCHEMA "org.ukui.menu.settings"
#define CONTROL_CENTER_SETTING "org.ukui.control-center.personalise" #define CONTROL_CENTER_SETTING "org.ukui.control-center.personalise"
#define CONTROL_CENTER_TRANSPARENCY_KEY "transparency" #define CONTROL_CENTER_TRANSPARENCY_KEY "transparency"
#define CONTROL_CENTER_EFFECT_KEY "effect"
#define UKUI_STYLE_SCHEMA "org.ukui.style" #define UKUI_STYLE_SCHEMA "org.ukui.style"
#define UKUI_STYLE_NAME_KEY "styleName" #define UKUI_STYLE_NAME_KEY "styleName"
@ -54,6 +55,7 @@ void GlobalSetting::initStyleSetting()
m_cache.insert(StyleName, UKUI_STYLE_VALUE_LIGHT); m_cache.insert(StyleName, UKUI_STYLE_VALUE_LIGHT);
m_cache.insert(ThemeColor, UKUI_STYLE_THEME_COLOR_KEY); m_cache.insert(ThemeColor, UKUI_STYLE_THEME_COLOR_KEY);
m_cache.insert(Transparency, 1); m_cache.insert(Transparency, 1);
m_cache.insert(EffectEnabled, false);
if (QGSettings::isSchemaInstalled(UKUI_STYLE_SCHEMA)) { if (QGSettings::isSchemaInstalled(UKUI_STYLE_SCHEMA)) {
QGSettings *settings = new QGSettings(UKUI_STYLE_SCHEMA, {}, this); QGSettings *settings = new QGSettings(UKUI_STYLE_SCHEMA, {}, this);
@ -84,12 +86,19 @@ void GlobalSetting::initStyleSetting()
if (keys.contains(CONTROL_CENTER_TRANSPARENCY_KEY)) { if (keys.contains(CONTROL_CENTER_TRANSPARENCY_KEY)) {
m_cache.insert(Transparency, settings->get(CONTROL_CENTER_TRANSPARENCY_KEY).toReal()); m_cache.insert(Transparency, settings->get(CONTROL_CENTER_TRANSPARENCY_KEY).toReal());
} }
if (keys.contains(CONTROL_CENTER_EFFECT_KEY)) {
m_cache.insert(EffectEnabled, settings->get(CONTROL_CENTER_EFFECT_KEY).toBool());
}
connect(settings, &QGSettings::changed, this, [this, settings] (const QString &key) { connect(settings, &QGSettings::changed, this, [this, settings] (const QString &key) {
if (key == CONTROL_CENTER_TRANSPARENCY_KEY) { if (key == CONTROL_CENTER_TRANSPARENCY_KEY) {
updateData(Transparency, settings->get(key).toReal()); updateData(Transparency, settings->get(key).toReal());
Q_EMIT styleChanged(Transparency); Q_EMIT styleChanged(Transparency);
} }
if (key == CONTROL_CENTER_EFFECT_KEY) {
updateData(EffectEnabled, settings->get(key).toReal());
Q_EMIT styleChanged(EffectEnabled);
}
}); });
} }
} }

View File

@ -52,7 +52,8 @@ public:
UnKnowKey = 0, UnKnowKey = 0,
StyleName, StyleName,
ThemeColor, ThemeColor,
Transparency Transparency,
EffectEnabled
}; };
Q_ENUM(Key) Q_ENUM(Key)

View File

@ -129,13 +129,13 @@ void WindowHelper::removeHeaderBar(QWindow *window)
} }
} }
void WindowHelper::windowBlur(QWindow *window, bool enable) void WindowHelper::windowBlur(QWindow *window, bool enable, const QRegion &region)
{ {
if (!window) { if (!window) {
return; return;
} }
//use KWindowEffects //use KWindowEffects
KWindowEffects::enableBlurBehind(window->winId(), enable); KWindowEffects::enableBlurBehind(window->winId(), enable, region);
} }
//======MenuMainWindow======// //======MenuMainWindow======//
@ -396,6 +396,15 @@ void MenuWindow::init()
QCoreApplication::sendEvent(this, &event); QCoreApplication::sendEvent(this, &event);
}); });
connect(GlobalSetting::instance(), &GlobalSetting::styleChanged, this , [this] (const GlobalSetting::Key& key) {
if (key == GlobalSetting::EffectEnabled) {
Q_EMIT effectEnabledChanged();
}
if (key == GlobalSetting::Transparency) {
Q_EMIT transparencyChanged();
}
});
updateGeometry(); updateGeometry();
} }
@ -414,6 +423,11 @@ bool MenuWindow::isFullScreen() const
return m_isFullScreen; return m_isFullScreen;
} }
QRect MenuWindow::normalScreenSize()
{
return m_geometryHelper->normalGeometry();
}
/** /**
* beforeFullScreenChanged -> (qml)onWidthChanged -> fullScreenChanged * beforeFullScreenChanged -> (qml)onWidthChanged -> fullScreenChanged
* @param isFullScreen * @param isFullScreen
@ -424,9 +438,8 @@ void MenuWindow::setFullScreen(bool isFullScreen)
return; return;
} }
Q_EMIT beforeFullScreenChanged(isFullScreen);
m_isFullScreen = isFullScreen; m_isFullScreen = isFullScreen;
WindowHelper::windowBlur(this, !m_isFullScreen); WindowHelper::windowBlur(this, !m_isFullScreen);
updateGeometry(); updateGeometry();
@ -438,6 +451,22 @@ void MenuWindow::setFullScreen(bool isFullScreen)
Q_EMIT fullScreenChanged(); Q_EMIT fullScreenChanged();
} }
void MenuWindow::changeWindowBlurRegion(int x, int y, int width, int height)
{
QRegion region(x, y, width, height);
WindowHelper::windowBlur(this, true, region);
}
void MenuWindow::exitFullScreen()
{
Q_EMIT beforeFullScreenExited();
}
void MenuWindow::enableWindowBlur(bool enable)
{
WindowHelper::windowBlur(this, enable);
}
void MenuWindow::exposeEvent(QExposeEvent *event) void MenuWindow::exposeEvent(QExposeEvent *event)
{ {
if (isExposed()) { if (isExposed()) {
@ -471,4 +500,14 @@ void MenuWindow::onActiveFocusItemChanged()
setVisible(false); setVisible(false);
} }
bool MenuWindow::effectEnabled() const
{
return GlobalSetting::instance()->get(GlobalSetting::EffectEnabled).toBool();
}
double MenuWindow::transparency() const
{
return GlobalSetting::instance()->get(GlobalSetting::Transparency).toDouble();
}
} // UkuiMenu } // UkuiMenu

View File

@ -39,7 +39,7 @@ public:
static void setWindowGeometry(QWindow *window, const QRect &rect); static void setWindowGeometry(QWindow *window, const QRect &rect);
static void setWindowAttribute(QWindow *window); static void setWindowAttribute(QWindow *window);
static void removeHeaderBar(QWindow *window); static void removeHeaderBar(QWindow *window);
static void windowBlur(QWindow *window, bool enable); static void windowBlur(QWindow *window, bool enable, const QRegion &region = QRegion());
}; };
class WindowGeometryHelper final : public QObject class WindowGeometryHelper final : public QObject
@ -105,17 +105,29 @@ class MenuWindow : public QQuickView
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isFullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged) Q_PROPERTY(bool isFullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged)
Q_PROPERTY(bool effectEnabled READ effectEnabled NOTIFY effectEnabledChanged)
Q_PROPERTY(double transparency READ transparency NOTIFY transparencyChanged)
public: public:
explicit MenuWindow(QWindow *parent = nullptr); explicit MenuWindow(QWindow *parent = nullptr);
MenuWindow(QQmlEngine* engine, QWindow *parent); MenuWindow(QQmlEngine* engine, QWindow *parent);
bool effectEnabled() const;
bool isFullScreen() const; bool isFullScreen() const;
double transparency() const;
void setFullScreen(bool isFullScreen); void setFullScreen(bool isFullScreen);
Q_INVOKABLE void changeWindowBlurRegion(int x, int y, int width, int height);
Q_INVOKABLE QRect normalScreenSize();
Q_INVOKABLE void exitFullScreen();
Q_INVOKABLE void enableWindowBlur(bool enable);
Q_SIGNALS: Q_SIGNALS:
void effectEnabledChanged();
void transparencyChanged();
void fullScreenChanged(); void fullScreenChanged();
void beforeFullScreenChanged(bool isToFullScreen); void beforeFullScreenChanged();
void beforeFullScreenExited();
private Q_SLOTS: private Q_SLOTS:
void onActiveFocusItemChanged(); void onActiveFocusItemChanged();