diff --git a/examples/quick/MainWindow.qml b/examples/quick/MainWindow.qml index 95ffbbe..80c1a73 100644 --- a/examples/quick/MainWindow.qml +++ b/examples/quick/MainWindow.qml @@ -28,6 +28,17 @@ import org.wangwenx190.FramelessHelper import Demo FramelessWindow { + property int __savedWindowState: Window.Windowed + + function toggleFullScreen() { + if (window.visibility === Window.FullScreen) { + window.visibility = window.__savedWindowState; + } else { + window.__savedWindowState = window.visibility; + window.showFullScreen(); + } + } + id: window visible: false // Hide the window before we sets up it's correct size and position. width: 800 @@ -60,6 +71,22 @@ FramelessWindow { window.visible = true; } + Shortcut { + sequences: [ StandardKey.Cancel, StandardKey.Close, StandardKey.Quit ] + onActivated: { + if (window.visibility === Window.FullScreen) { + window.toggleFullScreen(); + } else { + window.close(); + } + } + } + + Shortcut { + sequences: [ StandardKey.FullScreen, "ALT+RETURN" ] + onActivated: window.toggleFullScreen() + } + Timer { interval: 500 running: true diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp index 8840ccc..728d713 100644 --- a/examples/widget/widget.cpp +++ b/examples/widget/widget.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,26 @@ void Widget::initialize() setLayout(mainLayout); updateStyleSheet(); + m_cancelShortcut.reset(new QShortcut(this)); + m_cancelShortcut->setKey(FRAMELESSHELPER_STRING_LITERAL("ESC")); + connect(m_cancelShortcut.data(), &QShortcut::activated, this, [this](){ + if (isFullScreen()) { + Q_EMIT m_fullScreenShortcut->activated(); + } else { + close(); + } + }); + + m_fullScreenShortcut.reset(new QShortcut(this)); + m_fullScreenShortcut->setKey(FRAMELESSHELPER_STRING_LITERAL("ALT+RETURN")); + connect(m_fullScreenShortcut.data(), &QShortcut::activated, this, [this](){ + if (isFullScreen()) { + setWindowState(windowState() & ~Qt::WindowFullScreen); + } else { + showFullScreen(); + } + }); + FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this); helper->setTitleBarWidget(m_titleBar.data()); helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize); diff --git a/examples/widget/widget.h b/examples/widget/widget.h index 550771c..132f0bf 100644 --- a/examples/widget/widget.h +++ b/examples/widget/widget.h @@ -28,6 +28,7 @@ QT_BEGIN_NAMESPACE class QLabel; +class QShortcut; QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE @@ -56,4 +57,6 @@ private Q_SLOTS: private: QScopedPointer m_clockLabel; QScopedPointer m_titleBar; + QScopedPointer m_fullScreenShortcut; + QScopedPointer m_cancelShortcut; }; diff --git a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h index cae4d03..2ffc6ab 100644 --- a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h @@ -71,6 +71,9 @@ public: Q_NODISCARD bool isBlurBehindWindowEnabled() const; void setBlurBehindWindowEnabled(const bool value, const QColor &color); +protected: + Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; + private: Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const; Q_NODISCARD bool isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const; diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 2344b3d..a6b5731 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -163,6 +163,8 @@ void FramelessQuickHelperPrivate::attachToWindow() return; } + window->installEventFilter(this); + SystemParameters params = {}; params.getWindowId = [window]() -> WId { return window->winId(); }; params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); }; @@ -335,7 +337,11 @@ void FramelessQuickHelperPrivate::bringWindowToFront() window->show(); } if (window->visibility() == QQuickWindow::Minimized) { - window->showNormal(); // ### FIXME: we should not show normal, we should restore the previous state. +#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) + window->setWindowStates(window->windowStates() & ~Qt::WindowMinimized); +#else + window->showNormal(); +#endif } window->raise(); window->requestActivate(); @@ -448,6 +454,29 @@ void FramelessQuickHelperPrivate::setBlurBehindWindowEnabled(const bool value, c } } +bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event) +{ + Q_ASSERT(object); + Q_ASSERT(event); + if (!object || !event) { + return false; + } +#ifdef Q_OS_WINDOWS + if (!object->isWindowType()) { + return QObject::eventFilter(object, event); + } + if (event->type() != QEvent::WindowStateChange) { + return QObject::eventFilter(object, event); + } + const auto changeEvent = static_cast(event); + if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) { + const auto window = qobject_cast(object); + Utils::fixupQtInternals(window->winId()); + } +#endif + return QObject::eventFilter(object, event); +} + QRect FramelessQuickHelperPrivate::mapItemGeometryToScene(const QQuickItem * const item) const { Q_ASSERT(item); diff --git a/src/widgets/widgetssharedhelper.cpp b/src/widgets/widgetssharedhelper.cpp index 6c8eaac..5bb51fc 100644 --- a/src/widgets/widgetssharedhelper.cpp +++ b/src/widgets/widgetssharedhelper.cpp @@ -148,6 +148,12 @@ void WidgetsSharedHelper::changeEventHandler(QEvent *event) QMetaObject::invokeMethod(m_targetWidget, "hiddenChanged"); QMetaObject::invokeMethod(m_targetWidget, "normalChanged"); QMetaObject::invokeMethod(m_targetWidget, "zoomedChanged"); +#ifdef Q_OS_WINDOWS + const auto changeEvent = static_cast(event); + if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) { + Utils::fixupQtInternals(m_targetWidget->winId()); + } +#endif } void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)