feat(window):解决全屏切换闪烁问题

This commit is contained in:
qiqi49 2024-03-04 17:42:57 +08:00
parent 2f8d48b481
commit f7b4b23a1f
8 changed files with 156 additions and 193 deletions

View File

@ -271,6 +271,7 @@ ListView {
Extension.FavoriteDelegate {
anchors.fill: parent
anchors.margins: 12
isFullScreen: true
visualIndex: container.DelegateModel.itemsIndex
delegateLayout.anchors.topMargin: 16

View File

@ -24,9 +24,8 @@ FocusScope {
fullScreenUI.focus = true;
}
UkuiItems.StyleBackground {
Item {
anchors.fill: parent
paletteRole: Platform.Theme.Dark
MouseArea {
anchors.fill: parent

View File

@ -42,11 +42,18 @@ Item {
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignHCenter
ToolTip.delay: 500
ToolTip.text: mainWindow.isFullScreen ? qsTr("Contract") : qsTr("Expand")
ToolTip.visible: containsMouse
UkuiItems.ToolTip.text: mainWindow.isFullScreen ? qsTr("Contract") : qsTr("Expand")
onEntered: {
UkuiItems.ToolTip.show(fullScreenButton.mapToGlobal(0, fullScreenButton.height));
}
onExited: {
UkuiItems.ToolTip.hide();
}
onClicked: {
UkuiItems.ToolTip.hide();
if (mainWindow.isFullScreen) {
mainWindow.exitFullScreen();
} else {
@ -86,9 +93,15 @@ Item {
icon.width: 24
icon.height: 24
ToolTip.delay: 500
ToolTip.text: totalUtils.realName
ToolTip.visible: containsMouse
UkuiItems.ToolTip.text: totalUtils.realName
onEntered: {
UkuiItems.ToolTip.show(userInfoButton.mapToGlobal(0, userInfoButton.height));
}
onExited: {
UkuiItems.ToolTip.hide();
}
onClicked: totalUtils.openUserCenter()
Keys.onPressed: {
@ -109,9 +122,15 @@ Item {
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignHCenter
ToolTip.delay: 500
ToolTip.text: qsTr("Computer")
ToolTip.visible: containsMouse
UkuiItems.ToolTip.text: qsTr("Computer")
onEntered: {
UkuiItems.ToolTip.show(computerButton.mapToGlobal(0, computerButton.height));
}
onExited: {
UkuiItems.ToolTip.hide();
}
onClicked: {
totalUtils.openPeonyComputer();
@ -134,9 +153,15 @@ Item {
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignHCenter
ToolTip.delay: 500
ToolTip.text: qsTr("Applications System")
ToolTip.visible: containsMouse
UkuiItems.ToolTip.text: qsTr("Applications System")
onEntered: {
UkuiItems.ToolTip.show(setButton.mapToGlobal(0, setButton.height));
}
onExited: {
UkuiItems.ToolTip.hide();
}
onClicked: {
totalUtils.openControlCenter();
@ -159,9 +184,7 @@ Item {
Layout.preferredHeight: 36
Layout.alignment: Qt.AlignHCenter
ToolTip.delay: 500
ToolTip.visible: containsMouse
ToolTip.text: powerButtonBase.toolTip
UkuiItems.ToolTip.text: powerButtonBase.toolTip
PowerButton {
id: powerButtonBase
@ -176,6 +199,14 @@ Item {
}
}
onEntered: {
UkuiItems.ToolTip.show(powerButton.mapToGlobal(0, powerButton.height));
}
onExited: {
UkuiItems.ToolTip.hide();
}
onClicked: {
var buttonPosition = mapToGlobal(width, height);
powerButtonBase.clicked(mouse.button === Qt.LeftButton, buttonPosition.x + spacingFromMenu, buttonPosition.y + spacingFromMenu, mainWindow.isFullScreen);

View File

@ -12,6 +12,7 @@ UkuiItems.StyleBackground {
property bool hold: false
property alias delegateLayout: itemLayout
property alias mergePrompt: mergePrompt
property bool isFullScreen: false
radius: 8
useStyleTransparency: false
paletteRole: Platform.Theme.Text
@ -90,7 +91,7 @@ UkuiItems.StyleBackground {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mainWindow.isFullScreen) {
if (isFullScreen) {
fullScreenUI.focus =false;
} else {
normalUI.focus = false;
@ -100,7 +101,7 @@ UkuiItems.StyleBackground {
}
onPressAndHold: {
if (mouse.button === Qt.LeftButton) {
if (mainWindow.isFullScreen) {
if (isFullScreen) {
fullScreenUI.focus =false;
} else {
normalUI.focus = false;
@ -264,11 +265,11 @@ UkuiItems.StyleBackground {
icons: icon
columns: rows
width: mainWindow.isFullScreen ? 84: 40
rows: mainWindow.isFullScreen ? 4 : 2
spacing: mainWindow.isFullScreen ? 4 : 2
padding: mainWindow.isFullScreen ? 8 : 2
radius: mainWindow.isFullScreen ? Platform.Theme.maxRadius : Platform.Theme.normalRadius
width: isFullScreen ? 84: 40
rows: isFullScreen ? 4 : 2
spacing: isFullScreen ? 4 : 2
padding: isFullScreen ? 8 : 2
radius: isFullScreen ? Platform.Theme.maxRadius : Platform.Theme.normalRadius
}
function itemClicked(mouseButton) {
if (mouseButton === Qt.RightButton) {

View File

@ -142,6 +142,7 @@ GridView {
id: iconItem
anchors.fill: parent
anchors.margins: 2
isFullScreen: false
visualIndex: container.DelegateModel.itemsIndex
mergePrompt.anchors.topMargin: 6

View File

@ -27,14 +27,12 @@ Item {
id: root
clip: true
property int animationDuration: menuSetting.get("animationDuration")
property double transparency: mainWindow.transparency
property bool onComlpeted: false
property var normalGeometry: mainWindow.normalRect
Component.onCompleted: {
mainWindow.fullScreenChanged.connect(enterFullScreen);
mainWindow.beforeFullScreenExited.connect(exitFullScreen);
menuSetting.changed.connect(updateAnimationDuration);
onComlpeted = true;
}
function enterFullScreen() {
@ -42,9 +40,6 @@ Item {
normalHide.start();
fullShow.start();
enterFullScreenAnimation.start();
if (root.transparency <= 0.6) {
maskHide.start();
}
}
}
@ -52,9 +47,6 @@ Item {
normalShow.start();
fullHide.start();
exitFullScreenAnimation.start();
if (root.transparency <= 0.6) {
maskShow.start();
}
}
function updateAnimationDuration(key) {
@ -63,121 +55,51 @@ Item {
}
}
onTransparencyChanged: {
if (transparency > 0.6) {
backgroundMask.opacity = 1;
}
}
QtObject {
id: normalScreenGeometry
property var normalGeometry: mainWindow.normalScreenSize()
property int normalScreenX: normalScreenMargin
property int normalScreenY: root.height - normalGeometry.height - normalScreenMargin
property int normalScreenMargin: 8
property bool isFullScreen: mainWindow.isFullScreen
onIsFullScreenChanged: {
switch (mainWindow.panelPos) {
case 0 :
normalScreenX = normalScreenMargin;
normalScreenY = root.height - normalGeometry.height - normalScreenMargin;
break;
case 1 :
normalScreenX = normalScreenMargin;
normalScreenY = normalScreenMargin;
break;
case 2 :
normalScreenX = normalScreenMargin;
normalScreenY = normalScreenMargin;
break;
case 3 :
normalScreenX = root.width - normalGeometry.width - normalScreenMargin;
normalScreenY = normalScreenMargin;
break;
default :
normalScreenX = normalScreenMargin;
normalScreenY = root.height - normalGeometry.height - normalScreenMargin;
break;
}
}
}
UkuiItems.StyleBackground {
id: backgroundMask
// normalScreen
x: 0; y: 0
height: normalScreenGeometry.normalGeometry.height
width: normalScreenGeometry.normalGeometry.width
radius: Platform.Theme.windowRadius
x: normalGeometry.x
y: normalGeometry.y
height: normalGeometry.height
width: normalGeometry.width
radius: mainWindow.isFullScreen ? 0 : Platform.Theme.windowRadius
onHeightChanged: {
if (root.transparency <= 0.6 && root.onComlpeted) {
switch (mainWindow.panelPos) {
case 0 :
mainWindow.changeWindowBlurRegion(0, root.height - height, width, height);
break;
case 1 :
mainWindow.changeWindowBlurRegion(0, 0, width, height);
break;
case 2:
mainWindow.changeWindowBlurRegion(0, 0, width, height);
break;
case 3 :
mainWindow.changeWindowBlurRegion(root.width - width, 0, width, height);
break;
default :
mainWindow.changeWindowBlurRegion(0, root.height - height, width, height);
break;
}
}
}
border.width: 1
borderColor: Platform.Theme.Text
borderAlpha: 0.15
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
}
Component.onCompleted: mainWindow.changeWindowBlurRegion(x, y, width, height, radius)
onRadiusChanged: mainWindow.changeWindowBlurRegion(x, y, width, height, radius)
onWidthChanged: mainWindow.changeWindowBlurRegion(x, y, width, height, radius)
ParallelAnimation {
id: enterFullScreenAnimation
PropertyAnimation {
target: backgroundMask; property: "x"
from: normalScreenGeometry.normalScreenX; to: 0
from: normalGeometry.x; to: 0
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "y"
from: normalScreenGeometry.normalScreenY; to: 0
from: normalGeometry.y; to: 0
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "height"
from: normalScreenGeometry.normalGeometry.height; to: root.height
from: normalGeometry.height; to: root.height
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "width"
from: normalScreenGeometry.normalGeometry.width; to: root.width
from: normalGeometry.width; to: root.width
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
onStarted: {
fullScreenLoader.active = true;
normalScreenLoader.x = normalScreenGeometry.normalScreenX;
normalScreenLoader.y = normalScreenGeometry.normalScreenY;
}
onFinished: {
normalScreenLoader.active = false;
mainWindow.enableWindowBlur(true);
}
}
@ -185,35 +107,29 @@ Item {
id: exitFullScreenAnimation
PropertyAnimation {
target: backgroundMask; property: "x"
from: 0; to: normalScreenGeometry.normalScreenX
from: 0; to: normalGeometry.x
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "y"
from: 0; to: normalScreenGeometry.normalScreenY
from: 0; to: normalGeometry.y
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "height"
from: root.height; to: normalScreenGeometry.normalGeometry.height
from: root.height; to: normalGeometry.height
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: backgroundMask; property: "width"
from: root.width; to: normalScreenGeometry.normalGeometry.width
from: root.width; to: normalGeometry.width
duration: root.animationDuration; easing.type: Easing.InOutQuad
}
onStarted: {
normalScreenLoader.active = true;
mainWindow.enableWindowBlur(false);
}
onFinished: {
normalScreenLoader.x = 0;
normalScreenLoader.y = 0;
backgroundMask.x = 0;
backgroundMask.y = 0;
fullScreenLoader.active = false;
mainWindow.isFullScreen = false;
}
@ -224,7 +140,10 @@ Item {
id: normalScreenLoader
focus: !mainWindow.isFullScreen
active: false
height: normalScreenGeometry.normalGeometry.height; width: normalScreenGeometry.normalGeometry.width
x: normalGeometry.x
y: normalGeometry.y
height: normalGeometry.height
width: normalGeometry.width
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 }
@ -239,10 +158,15 @@ Item {
Loader {
id: fullScreenLoader
anchors.fill: parent
x: 0; y: 0
width: parent.width; height: parent.height
focus: mainWindow.isFullScreen
sourceComponent: fullSceenComponent
NumberAnimation { id: fullShow; target: fullScreenLoader; properties: "opacity"; from: 0; to: 1; duration: root.animationDuration; easing.type: Easing.InQuint }
ParallelAnimation {
id: fullShow
NumberAnimation { target: fullScreenLoader; properties: "opacity"; from: 0; to: 1; duration: root.animationDuration; easing.type: Easing.InQuint }
NumberAnimation { target: fullScreenLoader; properties: "y"; from: -100; to: 0; duration: root.animationDuration; easing.type: Easing.InOutQuad }
}
NumberAnimation { id: fullHide; target: fullScreenLoader; properties: "opacity"; from: 1; to: 0; duration: root.animationDuration; easing.type: Easing.OutQuint }
Component.onCompleted: {

View File

@ -28,6 +28,7 @@
#include <QPoint>
#include <KWindowSystem>
#include <KWindowEffects>
#include <QPainterPath>
#include <QTimer>
// kysdk
@ -133,7 +134,15 @@ void WindowHelper::windowBlur(QWindow *window, bool enable, const QRegion &regio
return;
}
//use KWindowEffects
KWindowEffects::enableBlurBehind(window->winId(), enable, region);
KWindowEffects::enableBlurBehind(window, enable, region);
}
void WindowHelper::setRegion(QWindow *window, qreal x, qreal y, qreal w, qreal h, qreal radius)
{
QPainterPath path;
path.addRoundedRect(x, y, w, h, radius, radius);
windowBlur(window, true, QRegion(path.toFillPolygon().toPolygon()));
}
// ====== WindowGeometryHelper ====== //
@ -155,7 +164,7 @@ void WindowGeometryHelper::updateGeometry()
if (!m_primaryScreen) {
return;
}
QRect screenRect = m_primaryScreen->geometry(), normalRect, fullRect;
QRect screenRect = m_primaryScreen->geometry(), normalMaskRect, fullRect;
int width = MenuSetting::instance()->get(MENU_WIDTH).toInt();
int height = MenuSetting::instance()->get(MENU_HEIGHT).toInt();
@ -168,62 +177,55 @@ void WindowGeometryHelper::updateGeometry()
height = screenRect.height();
}
//上: 1, 下: 0, 左: 2, 右: 3
switch (m_panelPos) {
case 0: {
QPoint topLeft;
topLeft.setX(screenRect.x() + margin);
topLeft.setY(screenRect.y() + screenRect.height() - height - margin - m_panelSize);
normalRect.setTopLeft(topLeft);
normalRect.setSize({width, height});
fullRect.setTopLeft(screenRect.topLeft());
fullRect.setSize({screenRect.width(), screenRect.height() - m_panelSize});
normalMaskRect.setTopLeft({margin, screenRect.height() - height - margin - m_panelSize});
normalMaskRect.setSize({width, height});
break;
}
case 1: {
normalRect.setTopLeft({screenRect.x() + margin, screenRect.y() + margin + m_panelSize});
normalRect.setSize({width, height});
fullRect.setTopLeft({screenRect.x(), screenRect.y() + m_panelSize});
fullRect.setSize({screenRect.width(), screenRect.height() - m_panelSize});
normalMaskRect.setTopLeft({margin, margin});
normalMaskRect.setSize({width, height});
break;
}
case 2: {
normalRect.setTopLeft({screenRect.x() + margin + m_panelSize, screenRect.y() + margin});
normalRect.setSize({width, height});
fullRect.setTopLeft({screenRect.x() + m_panelSize, screenRect.y()});
fullRect.setSize({screenRect.width() - m_panelSize, screenRect.height()});
normalMaskRect.setTopLeft({margin, margin});
normalMaskRect.setSize({width, height});
break;
}
case 3: {
QPoint topLeft;
topLeft.setX(screenRect.x() + screenRect.width() - width - margin - m_panelSize);
topLeft.setY(screenRect.y() + margin);
normalRect.setTopLeft(topLeft);
normalRect.setSize({width, height});
fullRect.setTopLeft(screenRect.topLeft());
fullRect.setSize({screenRect.width() - m_panelSize, screenRect.height()});
normalMaskRect.setTopLeft({screenRect.width() - width - margin - m_panelSize, margin});
normalMaskRect.setSize({width, height});
break;
}
default: {
normalRect.setTopLeft({screenRect.x() + margin, screenRect.y() + screenRect.height() - height - margin});
normalRect.setSize({width, height});
fullRect.setTopLeft({screenRect.x(), screenRect.y()});
fullRect.setSize({screenRect.width(), screenRect.height()});
normalMaskRect.setTopLeft({margin, screenRect.height() - height - margin - m_panelSize});
normalMaskRect.setSize({width, height});
break;
}
}
m_normalGeometry = normalRect;
m_normalGeometry = normalMaskRect;
m_fullScreenGeometry = fullRect;
Q_EMIT geometryChanged();
@ -317,7 +319,6 @@ void MenuWindow::init()
setFlags(Qt::Window);
WindowHelper::setWindowAttribute(this);
WindowHelper::removeHeaderBar(this);
WindowHelper::windowBlur(this, true);
// 访问窗口api
rootContext()->setContextProperty("mainWindow", this);
@ -326,6 +327,7 @@ void MenuWindow::init()
QEvent event(QEvent::Move);
QCoreApplication::sendEvent(this, &event);
Q_EMIT panelPosChanged();
Q_EMIT normalRectChanged();
});
rootContext()->setContextProperty("isLiteMode", GlobalSetting::instance()->get(GlobalSetting::IsLiteMode));
@ -346,20 +348,15 @@ void MenuWindow::init()
void MenuWindow::updateGeometry()
{
QRect rect = m_isFullScreen ? m_geometryHelper->fullScreenGeometry() : m_geometryHelper->normalGeometry();
if (rect == geometry()) {
return;
}
if (m_isFullScreen) {
setMaximumSize(rect.size());
} else {
setMinimumSize(rect.size());
}
QRect rect = m_geometryHelper->fullScreenGeometry();
if (rect != geometry()) {
WindowHelper::setWindowGeometry(this, rect);
setMinimumSize(geometry().size());
setMaximumSize(geometry().size());
}
updateGeometryOfMask();
WindowHelper::setRegion(this, m_maskGeometry.x(), m_maskGeometry.y(), m_maskGeometry.width(), m_maskGeometry.height(), 16);
}
bool MenuWindow::isFullScreen() const
@ -367,11 +364,6 @@ bool MenuWindow::isFullScreen() const
return m_isFullScreen;
}
QRect MenuWindow::normalScreenSize()
{
return m_geometryHelper->normalGeometry();
}
/**
* beforeFullScreenChanged -> (qml)onWidthChanged -> fullScreenChanged
* @param isFullScreen
@ -384,9 +376,7 @@ void MenuWindow::setFullScreen(bool isFullScreen)
m_isFullScreen = isFullScreen;
WindowHelper::windowBlur(this, !m_isFullScreen);
updateGeometry();
updateGeometryOfMask();
// 更新contentItem尺寸
QEvent event(QEvent::Resize);
@ -395,10 +385,9 @@ void MenuWindow::setFullScreen(bool isFullScreen)
Q_EMIT fullScreenChanged();
}
void MenuWindow::changeWindowBlurRegion(int x, int y, int width, int height)
void MenuWindow::changeWindowBlurRegion(qreal x, qreal y, qreal w, qreal h, qreal radius)
{
QRegion region(x, y, width, height);
WindowHelper::windowBlur(this, true, region);
WindowHelper::setRegion(this, x, y, w, h, radius);
}
void MenuWindow::exitFullScreen()
@ -406,11 +395,6 @@ void MenuWindow::exitFullScreen()
Q_EMIT beforeFullScreenExited();
}
void MenuWindow::enableWindowBlur(bool enable)
{
WindowHelper::windowBlur(this, enable);
}
void MenuWindow::exposeEvent(QExposeEvent *event)
{
if (isExposed()) {
@ -485,4 +469,20 @@ void MenuWindow::setEditMode(bool mode)
Q_EMIT editModeChanged();
}
void MenuWindow::updateGeometryOfMask()
{
if (m_isFullScreen) {
m_maskGeometry = QRect(0, 0, m_geometryHelper->fullScreenGeometry().width(), m_geometryHelper->fullScreenGeometry().height());
} else {
m_maskGeometry = m_geometryHelper->normalGeometry();
}
setMask(m_maskGeometry);
}
QRect MenuWindow::normalRect() const
{
return m_geometryHelper->normalGeometry();
}
} // UkuiMenu

View File

@ -40,6 +40,7 @@ public:
static void setWindowAttribute(QWindow *window);
static void removeHeaderBar(QWindow *window);
static void windowBlur(QWindow *window, bool enable, const QRegion &region = QRegion());
static void setRegion(QWindow *window, qreal x, qreal y, qreal w, qreal h, qreal radius);
};
class WindowGeometryHelper final : public QObject
@ -81,23 +82,25 @@ class MenuWindow : public QQuickView
Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged)
Q_PROPERTY(double transparency READ transparency NOTIFY transparencyChanged)
Q_PROPERTY(int panelPos READ panelPos NOTIFY panelPosChanged)
Q_PROPERTY(QRect normalRect READ normalRect NOTIFY normalRectChanged)
public:
explicit MenuWindow(QWindow *parent = nullptr);
MenuWindow(QQmlEngine* engine, QWindow *parent);
bool effectEnabled() const;
bool isFullScreen() const;
double transparency() const;
void setFullScreen(bool isFullScreen);
int panelPos() const;
bool editMode() const;
void setEditMode(bool mode);
Q_INVOKABLE void changeWindowBlurRegion(int x, int y, int width, int height);
Q_INVOKABLE QRect normalScreenSize();
bool effectEnabled() const;
double transparency() const;
int panelPos() const;
QRect normalRect() const;
Q_INVOKABLE void changeWindowBlurRegion(qreal x, qreal y, qreal w, qreal h, qreal radius = 8);
Q_INVOKABLE void exitFullScreen();
Q_INVOKABLE void enableWindowBlur(bool enable);
Q_SIGNALS:
void effectEnabledChanged();
@ -107,6 +110,7 @@ Q_SIGNALS:
void beforeFullScreenExited();
void panelPosChanged();
void editModeChanged();
void normalRectChanged();
protected:
void exposeEvent(QExposeEvent *event) override;
@ -117,11 +121,13 @@ protected:
private:
void init();
void updateGeometry();
void updateGeometryOfMask();
private:
bool m_editMode {false};
bool m_isFullScreen{false};
WindowGeometryHelper *m_geometryHelper{nullptr};
QRect m_maskGeometry = QRect(0,0,0,0);
};
} // UkuiMenu