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
|
// calls
|
||||||
callBg: #26282cf2; // old phone call popup background
|
callBg: #26282cf2; // old phone call popup background
|
||||||
callBgOpaque: #1b1f23 | callBg; // 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
|
callNameFg: #ffffff; // phone call popup name text
|
||||||
callFingerprintBg: #00000066; // phone call popup emoji fingerprint background
|
callFingerprintBg: #00000066; // phone call popup emoji fingerprint background
|
||||||
callStatusFg: #aaabac; // phone call popup status text
|
callStatusFg: #aaabac; // phone call popup status text
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
//
|
//
|
||||||
#include "ui/platform/ui_platform_window.h"
|
#include "ui/platform/ui_platform_window.h"
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/widgets/window.h"
|
||||||
|
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#include <QtGui/QtEvents>
|
#include <QtGui/QtEvents>
|
||||||
|
|
@ -41,34 +41,74 @@ void BasicWindowHelper::setGeometry(QRect rect) {
|
||||||
_window->setGeometry(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);
|
Expects(!_bodyTitleAreaTestMethod);
|
||||||
|
|
||||||
if (!testMethod) {
|
if (!testMethod) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_bodyTitleAreaTestMethod = std::move(testMethod);
|
_bodyTitleAreaTestMethod = std::move(testMethod);
|
||||||
if (customBodyTitleAreaHandling()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
body()->events() | rpl::start_with_next([=](not_null<QEvent*> e) {
|
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 (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();
|
const auto state = _window->windowState();
|
||||||
if (state & Qt::WindowMaximized) {
|
if (state & Qt::WindowMaximized) {
|
||||||
_window->setWindowState(state & ~Qt::WindowMaximized);
|
_window->setWindowState(state & ~Qt::WindowMaximized);
|
||||||
} else {
|
} else {
|
||||||
_window->setWindowState(state | Qt::WindowMaximized);
|
_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) {
|
} else if (e->type() == QEvent::MouseMove) {
|
||||||
const auto mouseEvent = static_cast<QMouseEvent*>(e.get());
|
const auto mouseEvent = static_cast<QMouseEvent*>(e.get());
|
||||||
if (bodyTitleAreaHit(mouseEvent->pos())
|
if (_mousePressed
|
||||||
&& (mouseEvent->buttons() & Qt::LeftButton)) {
|
#ifndef Q_OS_WIN // We handle fullscreen startSystemMove() only on Windows.
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
|
&& !_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();
|
_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());
|
}, body()->lifetime());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/flags.h"
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct WindowTitle;
|
struct WindowTitle;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
@ -13,12 +15,15 @@ struct WindowTitle;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
class RpWidget;
|
class RpWidget;
|
||||||
|
enum class WindowTitleHitTestFlag;
|
||||||
|
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
class BasicWindowHelper {
|
class BasicWindowHelper {
|
||||||
public:
|
public:
|
||||||
explicit BasicWindowHelper(not_null<RpWidget*> window);
|
explicit BasicWindowHelper(not_null<RpWidget*> window);
|
||||||
|
virtual ~BasicWindowHelper() = default;
|
||||||
|
|
||||||
[[nodiscard]] virtual not_null<RpWidget*> body();
|
[[nodiscard]] virtual not_null<RpWidget*> body();
|
||||||
virtual void setTitle(const QString &title);
|
virtual void setTitle(const QString &title);
|
||||||
|
|
@ -26,24 +31,26 @@ public:
|
||||||
virtual void setMinimumSize(QSize size);
|
virtual void setMinimumSize(QSize size);
|
||||||
virtual void setFixedSize(QSize size);
|
virtual void setFixedSize(QSize size);
|
||||||
virtual void setGeometry(QRect rect);
|
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:
|
protected:
|
||||||
[[nodiscard]] not_null<RpWidget*> window() const {
|
[[nodiscard]] not_null<RpWidget*> window() const {
|
||||||
return _window;
|
return _window;
|
||||||
}
|
}
|
||||||
[[nodiscard]] bool bodyTitleAreaHit(QPoint point) const {
|
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
|
||||||
return _bodyTitleAreaTestMethod && _bodyTitleAreaTestMethod(point);
|
QPoint point) const {
|
||||||
}
|
return _bodyTitleAreaTestMethod
|
||||||
[[nodiscard]] virtual bool customBodyTitleAreaHandling() {
|
? _bodyTitleAreaTestMethod(point)
|
||||||
return false;
|
: WindowTitleHitTestFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const not_null<RpWidget*> _window;
|
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 }));
|
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() {
|
void WindowHelper::init() {
|
||||||
style::PaletteChanged(
|
style::PaletteChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
|
@ -313,9 +329,7 @@ bool WindowHelper::handleNativeEvent(
|
||||||
if (!window()->rect().contains(mapped)) {
|
if (!window()->rect().contains(mapped)) {
|
||||||
*result = HTTRANSPARENT;
|
*result = HTTRANSPARENT;
|
||||||
} else if (!_title->geometry().contains(mapped)) {
|
} else if (!_title->geometry().contains(mapped)) {
|
||||||
*result = bodyTitleAreaHit(mapped - QPoint(0, _title->height()))
|
*result = HTCLIENT;
|
||||||
? HTCAPTION
|
|
||||||
: HTCLIENT;
|
|
||||||
} else switch (_title->hitTest(_title->pos() + mapped)) {
|
} else switch (_title->hitTest(_title->pos() + mapped)) {
|
||||||
case HitTestResult::Client:
|
case HitTestResult::Client:
|
||||||
case HitTestResult::SysButton: *result = HTCLIENT; break;
|
case HitTestResult::SysButton: *result = HTCLIENT; break;
|
||||||
|
|
@ -444,6 +458,9 @@ void WindowHelper::updateMargins() {
|
||||||
_marginsDelta = QMargins();
|
_marginsDelta = QMargins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_isFullScreen) {
|
||||||
|
margins = QMargins();
|
||||||
|
}
|
||||||
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
||||||
native->setWindowProperty(
|
native->setWindowProperty(
|
||||||
window()->windowHandle()->handle(),
|
window()->windowHandle()->handle(),
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,13 @@ public:
|
||||||
void setMinimumSize(QSize size) override;
|
void setMinimumSize(QSize size) override;
|
||||||
void setFixedSize(QSize size) override;
|
void setFixedSize(QSize size) override;
|
||||||
void setGeometry(QRect rect) override;
|
void setGeometry(QRect rect) override;
|
||||||
|
void showFullScreen() override;
|
||||||
|
void showNormal() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class NativeFilter;
|
class NativeFilter;
|
||||||
friend class NativeFilter;
|
friend class NativeFilter;
|
||||||
|
|
||||||
bool customBodyTitleAreaHandling() override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void updateMargins();
|
void updateMargins();
|
||||||
void updateSystemMenu();
|
void updateSystemMenu();
|
||||||
|
|
@ -56,6 +54,7 @@ private:
|
||||||
bool _updatingMargins = false;
|
bool _updatingMargins = false;
|
||||||
QMargins _marginsDelta;
|
QMargins _marginsDelta;
|
||||||
HMENU _menu = nullptr;
|
HMENU _menu = nullptr;
|
||||||
|
bool _isFullScreen = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,16 @@ void Window::setGeometry(QRect rect) {
|
||||||
_helper->setGeometry(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));
|
_helper->setBodyTitleArea(std::move(testMethod));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
#include "base/flags.h"
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct WindowTitle;
|
struct WindowTitle;
|
||||||
|
|
@ -17,6 +18,17 @@ namespace Platform {
|
||||||
class BasicWindowHelper;
|
class BasicWindowHelper;
|
||||||
} // namespace Platform
|
} // 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 {
|
class Window : public RpWidget {
|
||||||
public:
|
public:
|
||||||
explicit Window(QWidget *parent = nullptr);
|
explicit Window(QWidget *parent = nullptr);
|
||||||
|
|
@ -30,7 +42,9 @@ public:
|
||||||
void setMinimumSize(QSize size);
|
void setMinimumSize(QSize size);
|
||||||
void setFixedSize(QSize size);
|
void setFixedSize(QSize size);
|
||||||
void setGeometry(QRect rect);
|
void setGeometry(QRect rect);
|
||||||
void setBodyTitleArea(Fn<bool(QPoint)> testMethod);
|
void showFullScreen();
|
||||||
|
void showNormal();
|
||||||
|
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue