添加切换全屏动画

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.Layouts 1.12
import QtQuick.Controls 2.5

View File

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

View File

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

View File

@ -1,6 +1,11 @@
import QtQuick 2.0
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 {
anchors.fill: parent
anchors.leftMargin: 35

View File

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

View File

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

View File

@ -17,8 +17,6 @@
*/
import QtQuick 2.12
import QtQml 2.12
import AppUI 1.0 as AppUI
import AppControls2 1.0 as AppControls2
import org.ukui.menu.core 1.0
@ -26,35 +24,48 @@ import org.ukui.menu.core 1.0
Item {
id: root
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: {
loader.reloadUI();
mainWindow.beforeFullScreenChanged.connect(beforeFullScreenSlot);
mainWindow.fullScreenChanged.connect(fullScreenChangedSlot);
mainWindow.fullScreenChanged.connect(enterFullScreen);
mainWindow.beforeFullScreenExited.connect(exitFullScreen);
menuSetting.changed.connect(updateAnimationDuration);
onComlpeted = true;
}
function fullScreenChangedSlot() {
loader.opacity = 0;
fullScreenAnimation.start();
}
function beforeFullScreenSlot(status) {
if (!status) {
loader.sourceComponent = undefined;
function enterFullScreen() {
if (mainWindow.isFullScreen) {
normalHide.start();
fullShow.start();
backgroundMask.state = "fullScreen";
if (root.transparency <= 0.6) {
maskHide.start();
}
}
backgroundMask.alpha = status ? 0.5 : 0
backgroundMask.enableSizeChange = false;
}
ParallelAnimation {
id: fullScreenAnimation
NumberAnimation { target: backgroundMask; property: "width"; to: root.width; duration: root.animationDuration }
NumberAnimation { target: backgroundMask; property: "height"; to: root.height; duration: root.animationDuration }
function exitFullScreen() {
normalShow.start();
fullHide.start();
backgroundMask.state = "normalScreen";
if (root.transparency <= 0.6) {
maskShow.start();
}
}
onFinished: {
backgroundMask.enableSizeChange = true;
loader.reloadUI();
function updateAnimationDuration(key) {
if (key === "animationDuration") {
root.animationDuration = menuSetting.get("animationDuration");
}
}
onTransparencyChanged: {
if (transparency > 0.6) {
backgroundMask.opacity = 1;
}
}
@ -62,44 +73,101 @@ Item {
id: backgroundMask
anchors.left: parent.left
anchors.bottom: parent.bottom
alpha: 0
useStyleTransparent: false
paletteRole: Palette.Dark
radius: 12
state: "normalScreen"
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: [
State {
name: "disableSizeChange"
when: !backgroundMask.enableSizeChange
AnchorChanges {
target: backgroundMask
anchors.top: undefined
anchors.right: undefined
}
name: "normalScreen"
PropertyChanges { target: backgroundMask; height: root.normalGeometry.height; width: root.normalGeometry.width }
},
State {
name: "enableSizeChange"
when: backgroundMask.enableSizeChange
AnchorChanges {
target: backgroundMask
anchors.top: parent.top
anchors.right: parent.right
}
name: "fullScreen"
PropertyChanges { target: backgroundMask; height: root.height; width: root.width }
PropertyChanges { target: normalScreenLoader; anchors.margins: 8 }
AnchorChanges { target: normalScreenLoader; anchors.bottom: root.bottom; anchors.left: root.left }
}
]
Loader {
id: loader
anchors.fill: parent
Behavior on opacity {
NumberAnimation { duration: root.animationDuration }
transitions: [
Transition {
to: "fullScreen"
SequentialAnimation {
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 {

View File

@ -25,6 +25,7 @@
#define UKUI_MENU_SCHEMA "org.ukui.menu.settings"
#define CONTROL_CENTER_SETTING "org.ukui.control-center.personalise"
#define CONTROL_CENTER_TRANSPARENCY_KEY "transparency"
#define CONTROL_CENTER_EFFECT_KEY "effect"
#define UKUI_STYLE_SCHEMA "org.ukui.style"
#define UKUI_STYLE_NAME_KEY "styleName"
@ -54,6 +55,7 @@ void GlobalSetting::initStyleSetting()
m_cache.insert(StyleName, UKUI_STYLE_VALUE_LIGHT);
m_cache.insert(ThemeColor, UKUI_STYLE_THEME_COLOR_KEY);
m_cache.insert(Transparency, 1);
m_cache.insert(EffectEnabled, false);
if (QGSettings::isSchemaInstalled(UKUI_STYLE_SCHEMA)) {
QGSettings *settings = new QGSettings(UKUI_STYLE_SCHEMA, {}, this);
@ -84,12 +86,19 @@ void GlobalSetting::initStyleSetting()
if (keys.contains(CONTROL_CENTER_TRANSPARENCY_KEY)) {
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) {
if (key == CONTROL_CENTER_TRANSPARENCY_KEY) {
updateData(Transparency, settings->get(key).toReal());
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,
StyleName,
ThemeColor,
Transparency
Transparency,
EffectEnabled
};
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) {
return;
}
//use KWindowEffects
KWindowEffects::enableBlurBehind(window->winId(), enable);
KWindowEffects::enableBlurBehind(window->winId(), enable, region);
}
//======MenuMainWindow======//
@ -396,6 +396,15 @@ void MenuWindow::init()
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();
}
@ -414,6 +423,11 @@ bool MenuWindow::isFullScreen() const
return m_isFullScreen;
}
QRect MenuWindow::normalScreenSize()
{
return m_geometryHelper->normalGeometry();
}
/**
* beforeFullScreenChanged -> (qml)onWidthChanged -> fullScreenChanged
* @param isFullScreen
@ -424,9 +438,8 @@ void MenuWindow::setFullScreen(bool isFullScreen)
return;
}
Q_EMIT beforeFullScreenChanged(isFullScreen);
m_isFullScreen = isFullScreen;
WindowHelper::windowBlur(this, !m_isFullScreen);
updateGeometry();
@ -438,6 +451,22 @@ void MenuWindow::setFullScreen(bool isFullScreen)
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)
{
if (isExposed()) {
@ -471,4 +500,14 @@ void MenuWindow::onActiveFocusItemChanged()
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

View File

@ -39,7 +39,7 @@ public:
static void setWindowGeometry(QWindow *window, const QRect &rect);
static void setWindowAttribute(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
@ -105,17 +105,29 @@ class MenuWindow : public QQuickView
{
Q_OBJECT
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:
explicit MenuWindow(QWindow *parent = nullptr);
MenuWindow(QQmlEngine* engine, QWindow *parent);
bool effectEnabled() const;
bool isFullScreen() const;
double transparency() const;
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:
void effectEnabledChanged();
void transparencyChanged();
void fullScreenChanged();
void beforeFullScreenChanged(bool isToFullScreen);
void beforeFullScreenChanged();
void beforeFullScreenExited();
private Q_SLOTS:
void onActiveFocusItemChanged();