Allow Ui::Window to become fullscreen.
This commit is contained in:
parent
608b25bd32
commit
3d5108a878
7 changed files with 114 additions and 27 deletions
|
|
@ -538,6 +538,7 @@ notificationBg: windowBg; // custom notification window background
|
|||
// calls
|
||||
callBg: #26282cf2; // old phone call popup background
|
||||
callBgOpaque: #1b1f23 | callBg; // phone call popup background
|
||||
callBgButton: #1b1f2356 | callBg; // phone call window control buttons bg
|
||||
callNameFg: #ffffff; // phone call popup name text
|
||||
callFingerprintBg: #00000066; // phone call popup emoji fingerprint background
|
||||
callStatusFg: #aaabac; // phone call popup status text
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/widgets/window.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QtEvents>
|
||||
|
|
@ -41,34 +41,74 @@ void BasicWindowHelper::setGeometry(QRect rect) {
|
|||
_window->setGeometry(rect);
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setBodyTitleArea(Fn<bool(QPoint)> testMethod) {
|
||||
void BasicWindowHelper::showFullScreen() {
|
||||
_window->showFullScreen();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::showNormal() {
|
||||
_window->showNormal();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setBodyTitleArea(
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> testMethod) {
|
||||
Expects(!_bodyTitleAreaTestMethod);
|
||||
|
||||
if (!testMethod) {
|
||||
return;
|
||||
}
|
||||
_bodyTitleAreaTestMethod = std::move(testMethod);
|
||||
if (customBodyTitleAreaHandling()) {
|
||||
return;
|
||||
}
|
||||
body()->events() | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
const auto hitTest = [&] {
|
||||
return bodyTitleAreaHit(
|
||||
static_cast<QMouseEvent*>(e.get())->pos());
|
||||
};
|
||||
if (e->type() == QEvent::MouseButtonDblClick) {
|
||||
if (bodyTitleAreaHit(static_cast<QMouseEvent*>(e.get())->pos())) {
|
||||
_mousePressed = false;
|
||||
const auto hit = hitTest();
|
||||
if (hit & WindowTitleHitTestFlag::Maximize) {
|
||||
const auto state = _window->windowState();
|
||||
if (state & Qt::WindowMaximized) {
|
||||
_window->setWindowState(state & ~Qt::WindowMaximized);
|
||||
} else {
|
||||
_window->setWindowState(state | Qt::WindowMaximized);
|
||||
}
|
||||
} else if (hit & WindowTitleHitTestFlag::FullScreen) {
|
||||
if (_window->isFullScreen()) {
|
||||
showNormal();
|
||||
} else {
|
||||
showFullScreen();
|
||||
}
|
||||
}
|
||||
} else if (e->type() == QEvent::MouseButtonRelease) {
|
||||
_mousePressed = false;
|
||||
} else if (e->type() == QEvent::MouseButtonPress
|
||||
&& (static_cast<QMouseEvent*>(e.get())->button()
|
||||
== Qt::LeftButton)) {
|
||||
_mousePressed = true;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
|
||||
#ifndef Q_OS_MAC // On macOS startSystemMove() doesn't work from here.
|
||||
} else if (e->type() == QEvent::MouseMove) {
|
||||
const auto mouseEvent = static_cast<QMouseEvent*>(e.get());
|
||||
if (bodyTitleAreaHit(mouseEvent->pos())
|
||||
&& (mouseEvent->buttons() & Qt::LeftButton)) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
|
||||
if (_mousePressed
|
||||
#ifndef Q_OS_WIN // We handle fullscreen startSystemMove() only on Windows.
|
||||
&& !_window->isFullScreen()
|
||||
#endif // !Q_OS_WIN
|
||||
&& (hitTest() & WindowTitleHitTestFlag::Move)) {
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (_window->isFullScreen()) {
|
||||
// On Windows we just jump out of fullscreen
|
||||
// like we do automatically for dragging a window
|
||||
// by title bar in a maximized state.
|
||||
showNormal();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
_mousePressed = false;
|
||||
_window->windowHandle()->startSystemMove();
|
||||
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
|
||||
}
|
||||
#endif // !Q_OS_MAC
|
||||
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
|
||||
}
|
||||
}, body()->lifetime());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include "base/flags.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
} // namespace style
|
||||
|
|
@ -13,12 +15,15 @@ struct WindowTitle;
|
|||
namespace Ui {
|
||||
|
||||
class RpWidget;
|
||||
enum class WindowTitleHitTestFlag;
|
||||
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class BasicWindowHelper {
|
||||
public:
|
||||
explicit BasicWindowHelper(not_null<RpWidget*> window);
|
||||
virtual ~BasicWindowHelper() = default;
|
||||
|
||||
[[nodiscard]] virtual not_null<RpWidget*> body();
|
||||
virtual void setTitle(const QString &title);
|
||||
|
|
@ -26,24 +31,26 @@ public:
|
|||
virtual void setMinimumSize(QSize size);
|
||||
virtual void setFixedSize(QSize size);
|
||||
virtual void setGeometry(QRect rect);
|
||||
virtual ~BasicWindowHelper() = default;
|
||||
virtual void showFullScreen();
|
||||
virtual void showNormal();
|
||||
|
||||
void setBodyTitleArea(Fn<bool(QPoint)> testMethod);
|
||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||
|
||||
protected:
|
||||
[[nodiscard]] not_null<RpWidget*> window() const {
|
||||
return _window;
|
||||
}
|
||||
[[nodiscard]] bool bodyTitleAreaHit(QPoint point) const {
|
||||
return _bodyTitleAreaTestMethod && _bodyTitleAreaTestMethod(point);
|
||||
}
|
||||
[[nodiscard]] virtual bool customBodyTitleAreaHandling() {
|
||||
return false;
|
||||
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
|
||||
QPoint point) const {
|
||||
return _bodyTitleAreaTestMethod
|
||||
? _bodyTitleAreaTestMethod(point)
|
||||
: WindowTitleHitTestFlag();
|
||||
}
|
||||
|
||||
private:
|
||||
const not_null<RpWidget*> _window;
|
||||
Fn<bool(QPoint)> _bodyTitleAreaTestMethod;
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> _bodyTitleAreaTestMethod;
|
||||
bool _mousePressed = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,22 @@ void WindowHelper::setGeometry(QRect rect) {
|
|||
window()->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 }));
|
||||
}
|
||||
|
||||
void WindowHelper::showFullScreen() {
|
||||
if (!_isFullScreen) {
|
||||
_isFullScreen = true;
|
||||
updateMargins();
|
||||
}
|
||||
window()->showFullScreen();
|
||||
}
|
||||
|
||||
void WindowHelper::showNormal() {
|
||||
window()->showNormal();
|
||||
if (_isFullScreen) {
|
||||
_isFullScreen = false;
|
||||
updateMargins();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowHelper::init() {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
|
|
@ -313,9 +329,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
if (!window()->rect().contains(mapped)) {
|
||||
*result = HTTRANSPARENT;
|
||||
} else if (!_title->geometry().contains(mapped)) {
|
||||
*result = bodyTitleAreaHit(mapped - QPoint(0, _title->height()))
|
||||
? HTCAPTION
|
||||
: HTCLIENT;
|
||||
*result = HTCLIENT;
|
||||
} else switch (_title->hitTest(_title->pos() + mapped)) {
|
||||
case HitTestResult::Client:
|
||||
case HitTestResult::SysButton: *result = HTCLIENT; break;
|
||||
|
|
@ -444,6 +458,9 @@ void WindowHelper::updateMargins() {
|
|||
_marginsDelta = QMargins();
|
||||
}
|
||||
|
||||
if (_isFullScreen) {
|
||||
margins = QMargins();
|
||||
}
|
||||
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
||||
native->setWindowProperty(
|
||||
window()->windowHandle()->handle(),
|
||||
|
|
|
|||
|
|
@ -27,15 +27,13 @@ public:
|
|||
void setMinimumSize(QSize size) override;
|
||||
void setFixedSize(QSize size) override;
|
||||
void setGeometry(QRect rect) override;
|
||||
void showFullScreen() override;
|
||||
void showNormal() override;
|
||||
|
||||
private:
|
||||
class NativeFilter;
|
||||
friend class NativeFilter;
|
||||
|
||||
bool customBodyTitleAreaHandling() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
void init();
|
||||
void updateMargins();
|
||||
void updateSystemMenu();
|
||||
|
|
@ -56,6 +54,7 @@ private:
|
|||
bool _updatingMargins = false;
|
||||
QMargins _marginsDelta;
|
||||
HMENU _menu = nullptr;
|
||||
bool _isFullScreen = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,16 @@ void Window::setGeometry(QRect rect) {
|
|||
_helper->setGeometry(rect);
|
||||
}
|
||||
|
||||
void Window::setBodyTitleArea(Fn<bool(QPoint)> testMethod) {
|
||||
void Window::showFullScreen() {
|
||||
_helper->showFullScreen();
|
||||
}
|
||||
|
||||
void Window::showNormal() {
|
||||
_helper->showNormal();
|
||||
}
|
||||
|
||||
void Window::setBodyTitleArea(
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> testMethod) {
|
||||
_helper->setBodyTitleArea(std::move(testMethod));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "base/flags.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
|
|
@ -17,6 +18,17 @@ namespace Platform {
|
|||
class BasicWindowHelper;
|
||||
} // namespace Platform
|
||||
|
||||
enum class WindowTitleHitTestFlag {
|
||||
None = 0x00,
|
||||
Move = 0x01,
|
||||
Maximize = 0x02,
|
||||
FullScreen = 0x04,
|
||||
};
|
||||
inline constexpr bool is_flag_type(WindowTitleHitTestFlag) {
|
||||
return true;
|
||||
}
|
||||
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
|
||||
|
||||
class Window : public RpWidget {
|
||||
public:
|
||||
explicit Window(QWidget *parent = nullptr);
|
||||
|
|
@ -30,7 +42,9 @@ public:
|
|||
void setMinimumSize(QSize size);
|
||||
void setFixedSize(QSize size);
|
||||
void setGeometry(QRect rect);
|
||||
void setBodyTitleArea(Fn<bool(QPoint)> testMethod);
|
||||
void showFullScreen();
|
||||
void showNormal();
|
||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue