Add Windows 11 snap layouts to custom TitleControls.

This commit is contained in:
John Preston 2022-01-18 18:37:35 +03:00
parent d5d2ccb467
commit 47aed59fe9
10 changed files with 200 additions and 76 deletions

View file

@ -33,6 +33,9 @@ BasicWindowHelper::BasicWindowHelper(not_null<RpWidget*> window)
_window->setWindowFlag(Qt::Window); _window->setWindowFlag(Qt::Window);
} }
void BasicWindowHelper::initInWindow(not_null<RpWindow*> window) {
}
not_null<RpWidget*> BasicWindowHelper::body() { not_null<RpWidget*> BasicWindowHelper::body() {
return _window; return _window;
} }
@ -49,6 +52,19 @@ rpl::producer<int> BasicWindowHelper::additionalContentPaddingValue() const {
return rpl::single(0); return rpl::single(0);
} }
auto BasicWindowHelper::hitTestRequests() const
-> rpl::producer<not_null<HitTestRequest*>> {
return rpl::never<not_null<HitTestRequest*>>();
}
rpl::producer<HitTestResult> BasicWindowHelper::systemButtonOver() const {
return rpl::never<HitTestResult>();
}
rpl::producer<HitTestResult> BasicWindowHelper::systemButtonDown() const {
return rpl::never<HitTestResult>();
}
void BasicWindowHelper::setTitle(const QString &title) { void BasicWindowHelper::setTitle(const QString &title) {
_window->setWindowTitle(title); _window->setWindowTitle(title);
} }

View file

@ -15,11 +15,14 @@ struct WindowTitle;
namespace Ui { namespace Ui {
class RpWidget; class RpWidget;
class RpWindow;
enum class WindowTitleHitTestFlag; enum class WindowTitleHitTestFlag;
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>; using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
namespace Platform { namespace Platform {
struct HitTestRequest;
enum class HitTestResult;
class DefaultTitleWidget; class DefaultTitleWidget;
class BasicWindowHelper { class BasicWindowHelper {
@ -27,11 +30,22 @@ public:
explicit BasicWindowHelper(not_null<RpWidget*> window); explicit BasicWindowHelper(not_null<RpWidget*> window);
virtual ~BasicWindowHelper() = default; virtual ~BasicWindowHelper() = default;
[[nodiscard]] not_null<RpWidget*> window() const {
return _window;
}
[[nodiscard]] virtual void initInWindow(not_null<RpWindow*> window);
[[nodiscard]] virtual not_null<RpWidget*> body(); [[nodiscard]] virtual not_null<RpWidget*> body();
[[nodiscard]] virtual QMargins frameMargins(); [[nodiscard]] virtual QMargins frameMargins();
[[nodiscard]] virtual int additionalContentPadding() const; [[nodiscard]] virtual int additionalContentPadding() const;
[[nodiscard]] virtual auto additionalContentPaddingValue() const [[nodiscard]] virtual auto additionalContentPaddingValue() const
-> rpl::producer<int>; -> rpl::producer<int>;
[[nodiscard]] virtual auto hitTestRequests() const
-> rpl::producer<not_null<HitTestRequest*>>;
[[nodiscard]] virtual auto systemButtonOver() const
-> rpl::producer<HitTestResult>;
[[nodiscard]] virtual auto systemButtonDown() const
-> rpl::producer<HitTestResult>;
virtual void setTitle(const QString &title); virtual void setTitle(const QString &title);
virtual void setTitleStyle(const style::WindowTitle &st); virtual void setTitleStyle(const style::WindowTitle &st);
virtual void setNativeFrame(bool enabled); virtual void setNativeFrame(bool enabled);
@ -46,9 +60,6 @@ public:
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod); void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
protected: protected:
[[nodiscard]] not_null<RpWidget*> window() const {
return _window;
}
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit( [[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
QPoint point) const { QPoint point) const {
return _bodyTitleAreaTestMethod return _bodyTitleAreaTestMethod
@ -111,7 +122,7 @@ private:
return std::make_unique<DefaultWindowHelper>(window); return std::make_unique<DefaultWindowHelper>(window);
} }
bool NativeWindowFrameSupported(); [[nodiscard]] bool NativeWindowFrameSupported();
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -15,6 +15,7 @@
#include "styles/palette.h" #include "styles/palette.h"
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/event_filter.h" #include "base/event_filter.h"
#include "base/platform/base_platform_info.h"
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <QtGui/QtEvents> #include <QtGui/QtEvents>
@ -36,6 +37,34 @@ void RemoveDuplicates(std::vector<T> &v) {
} // namespace } // namespace
bool SemiNativeSystemButtonProcessing() {
return ::Platform::IsWindows11OrGreater();
}
void SetupSemiNativeSystemButtons(
not_null<TitleControls*> controls,
not_null<RpWindow*> window,
rpl::lifetime &lifetime,
Fn<bool()> filter) {
if (!SemiNativeSystemButtonProcessing()) {
return;
}
window->systemButtonOver(
) | rpl::filter([=](HitTestResult button) {
return !filter || filter() || (button == HitTestResult::None);
}) | rpl::start_with_next([=](HitTestResult button) {
controls->buttonOver(button);
}, lifetime);
window->systemButtonDown(
) | rpl::filter([=](HitTestResult button) {
return !filter || filter() || (button == HitTestResult::None);
}) | rpl::start_with_next([=](HitTestResult button) {
controls->buttonDown(button);
}, lifetime);
}
class TitleControls::Button final : public IconButton { class TitleControls::Button final : public IconButton {
public: public:
using IconButton::IconButton; using IconButton::IconButton;
@ -216,12 +245,12 @@ void TitleControls::buttonOver(HitTestResult testResult) {
update(_close, HitTestResult::Close); update(_close, HitTestResult::Close);
} }
void TitleControls::buttonDown(HitTestResult testResult, bool down) { void TitleControls::buttonDown(HitTestResult testResult) {
const auto update = [&]( const auto update = [&](
const object_ptr<Button> &button, const object_ptr<Button> &button,
HitTestResult buttonTestResult) { HitTestResult buttonTestResult) {
if (const auto raw = button.data()) { if (const auto raw = button.data()) {
raw->setDown(testResult == buttonTestResult && down); raw->setDown(testResult == buttonTestResult);
} }
}; };
update(_minimize, HitTestResult::Minimize); update(_minimize, HitTestResult::Minimize);
@ -456,16 +485,30 @@ std::unique_ptr<SeparateTitleControls> SetupSeparateTitleControls(
st, st,
std::move(maximize)); std::move(maximize));
const auto raw = result.get();
auto &lifetime = raw->wrap.lifetime();
rpl::combine( rpl::combine(
window->body()->widthValue(), window->body()->widthValue(),
window->additionalContentPaddingValue() window->additionalContentPaddingValue()
) | rpl::start_with_next([raw = result.get()](int width, int padding) { ) | rpl::start_with_next([=](int width, int padding) {
raw->wrap.setGeometry( raw->wrap.setGeometry(
padding, padding,
0, 0,
width - 2 * padding, width - 2 * padding,
raw->controls.geometry().height()); raw->controls.geometry().height());
}, result->wrap.lifetime()); }, lifetime);
window->hitTestRequests(
) | rpl::start_with_next([=](not_null<HitTestRequest*> request) {
const auto origin = raw->wrap.pos();
const auto relative = request->point - origin;
const auto controlsResult = raw->controls.hitTest(relative);
if (controlsResult != HitTestResult::None) {
request->result = controlsResult;
}
}, lifetime);
SetupSemiNativeSystemButtons(&raw->controls, window, lifetime);
return result; return result;
} }

View file

@ -24,6 +24,8 @@ class RpWindow;
namespace Platform { namespace Platform {
class TitleControls;
enum class HitTestResult { enum class HitTestResult {
None = 0, None = 0,
Client, Client,
@ -41,6 +43,18 @@ enum class HitTestResult {
TopLeft, TopLeft,
}; };
struct HitTestRequest {
QPoint point;
HitTestResult result = HitTestResult::Client;
};
[[nodiscard]] bool SemiNativeSystemButtonProcessing();
void SetupSemiNativeSystemButtons(
not_null<TitleControls*> controls,
not_null<RpWindow*> window,
rpl::lifetime &lifetime,
Fn<bool()> filter = nullptr);
class TitleControls final { class TitleControls final {
public: public:
TitleControls( TitleControls(
@ -57,7 +71,7 @@ public:
[[nodiscard]] HitTestResult hitTest(QPoint point) const; [[nodiscard]] HitTestResult hitTest(QPoint point) const;
void buttonOver(HitTestResult testResult); void buttonOver(HitTestResult testResult);
void buttonDown(HitTestResult testResult, bool down); void buttonDown(HitTestResult testResult);
enum class Control { enum class Control {
Unknown, Unknown,

View file

@ -9,6 +9,7 @@
#include "ui/platform/win/ui_window_win.h" #include "ui/platform/win/ui_window_win.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
#include "ui/widgets/rp_window.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/platform/win/base_windows_safe_library.h" #include "base/platform/win/base_windows_safe_library.h"
@ -68,6 +69,19 @@ TitleWidget::TitleWidget(not_null<RpWidget*> parent)
}, lifetime()); }, lifetime());
} }
void TitleWidget::initInWindow(not_null<RpWindow*> window) {
window->hitTestRequests(
) | rpl::filter([=](not_null<HitTestRequest*> request) {
return !isHidden() && geometry().contains(request->point);
}) | rpl::start_with_next([=](not_null<HitTestRequest*> request) {
request->result = hitTest(request->point);
}, lifetime());
SetupSemiNativeSystemButtons(&_controls, window, lifetime(), [=] {
return !isHidden() && (_controls.st()->height > 0);
});
}
TitleWidget::~TitleWidget() = default; TitleWidget::~TitleWidget() = default;
void TitleWidget::setText(const QString &text) { void TitleWidget::setText(const QString &text) {
@ -113,27 +127,19 @@ void TitleWidget::resizeEvent(QResizeEvent *e) {
} }
HitTestResult TitleWidget::hitTest(QPoint point) const { HitTestResult TitleWidget::hitTest(QPoint point) const {
const auto titleResult = _controls.hitTest(point); const auto origin = _paddingHelper
if (titleResult != HitTestResult::None) { ? _paddingHelper->controlsParent.pos()
return titleResult; : QPoint();
} else if (rect().contains(point)) { const auto controlsResult = _controls.hitTest(point - origin);
return HitTestResult::Caption; return (controlsResult != HitTestResult::None)
} ? controlsResult
return HitTestResult::None; : HitTestResult::Caption;
} }
bool TitleWidget::additionalPaddingRequired() const { bool TitleWidget::additionalPaddingRequired() const {
return _paddingHelper && !isHidden(); return _paddingHelper && !isHidden();
} }
void TitleWidget::sysButtonOver(HitTestResult testResult) {
_controls.buttonOver(testResult);
}
void TitleWidget::sysButtonDown(HitTestResult testResult, bool down) {
_controls.buttonDown(testResult, down);
}
void TitleWidget::refreshAdditionalPaddings() { void TitleWidget::refreshAdditionalPaddings() {
if (!additionalPaddingRequired()) { if (!additionalPaddingRequired()) {
return; return;

View file

@ -21,6 +21,7 @@ struct WindowTitle;
namespace Ui { namespace Ui {
class RpWindow;
class IconButton; class IconButton;
class PlainShadow; class PlainShadow;
@ -31,10 +32,10 @@ public:
explicit TitleWidget(not_null<RpWidget*> parent); explicit TitleWidget(not_null<RpWidget*> parent);
~TitleWidget(); ~TitleWidget();
void initInWindow(not_null<RpWindow*> window);
void setText(const QString &text); void setText(const QString &text);
void setStyle(const style::WindowTitle &st); void setStyle(const style::WindowTitle &st);
[[nodiscard]] not_null<const style::WindowTitle*> st() const; [[nodiscard]] not_null<const style::WindowTitle*> st() const;
[[nodiscard]] HitTestResult hitTest(QPoint point) const;
void setResizeEnabled(bool enabled); void setResizeEnabled(bool enabled);
void refreshAdditionalPaddings(); void refreshAdditionalPaddings();
@ -45,9 +46,6 @@ public:
[[nodiscard]] int additionalPadding() const; [[nodiscard]] int additionalPadding() const;
[[nodiscard]] rpl::producer<int> additionalPaddingValue() const; [[nodiscard]] rpl::producer<int> additionalPaddingValue() const;
void sysButtonOver(HitTestResult testResult);
void sysButtonDown(HitTestResult testResult, bool down);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@ -57,6 +55,7 @@ protected:
private: private:
struct PaddingHelper; struct PaddingHelper;
[[nodiscard]] HitTestResult hitTest(QPoint point) const;
[[nodiscard]] bool additionalPaddingRequired() const; [[nodiscard]] bool additionalPaddingRequired() const;
void refreshGeometryWithWidth(int width); void refreshGeometryWithWidth(int width);
void setAdditionalPadding(int padding); void setAdditionalPadding(int padding);

View file

@ -8,6 +8,7 @@
#include "ui/inactive_press.h" #include "ui/inactive_press.h"
#include "ui/platform/win/ui_window_title_win.h" #include "ui/platform/win/ui_window_title_win.h"
#include "ui/widgets/rp_window.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/integration.h" #include "base/integration.h"
#include "base/debug_log.h" #include "base/debug_log.h"
@ -170,6 +171,10 @@ WindowHelper::~WindowHelper() {
GetNativeFilter()->unregisterWindow(_handle); GetNativeFilter()->unregisterWindow(_handle);
} }
void WindowHelper::initInWindow(not_null<RpWindow*> window) {
_title->initInWindow(window);
}
not_null<RpWidget*> WindowHelper::body() { not_null<RpWidget*> WindowHelper::body() {
return _body; return _body;
} }
@ -280,6 +285,19 @@ void WindowHelper::showNormal() {
} }
} }
auto WindowHelper::hitTestRequests() const
-> rpl::producer<not_null<HitTestRequest*>> {
return _hitTestRequests.events();
}
rpl::producer<HitTestResult> WindowHelper::systemButtonOver() const {
return _systemButtonOver.events();
}
rpl::producer<HitTestResult> WindowHelper::systemButtonDown() const {
return _systemButtonDown.events();
}
void WindowHelper::init() { void WindowHelper::init() {
_title->show(); _title->show();
GetNativeFilter()->registerWindow(_handle, this); GetNativeFilter()->registerWindow(_handle, this);
@ -341,7 +359,7 @@ bool WindowHelper::handleNativeEvent(
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
LRESULT *result) { LRESULT *result) {
if (handleSysButtonEvent(msg, wParam, lParam, result)) { if (handleSystemButtonEvent(msg, wParam, lParam, result)) {
return true; return true;
} }
@ -406,16 +424,6 @@ bool WindowHelper::handleNativeEvent(
return true; return true;
} }
case WM_NCLBUTTONDBLCLK:
case WM_NCMBUTTONDBLCLK:
case WM_NCRBUTTONDBLCLK:
case WM_NCXBUTTONDBLCLK: {
if (!fixedSize()) {
return false;
}
if (result) *result = 0;
} return true;
case WM_NCRBUTTONUP: { case WM_NCRBUTTONUP: {
if (_title->isHidden()) { if (_title->isHidden()) {
return false; return false;
@ -518,14 +526,13 @@ bool WindowHelper::handleNativeEvent(
*result = [&] { *result = [&] {
if (!window()->rect().contains(mapped)) { if (!window()->rect().contains(mapped)) {
return HTTRANSPARENT; return HTTRANSPARENT;
} else if (_title->isHidden() }
|| !_title->geometry().contains(mapped)) { auto request = HitTestRequest{
return HTCLIENT; .point = mapped,
} else switch (const auto test = _title->hitTest(mapped)) { };
_hitTestRequests.fire(&request);
switch (const auto result = request.result) {
case HitTestResult::Client: return HTCLIENT; case HitTestResult::Client: return HTCLIENT;
case HitTestResult::Minimize:
case HitTestResult::MaximizeRestore:
case HitTestResult::Close: return sysButtonHitTest(test);
case HitTestResult::Caption: return HTCAPTION; case HitTestResult::Caption: return HTCAPTION;
case HitTestResult::Top: return HTTOP; case HitTestResult::Top: return HTTOP;
case HitTestResult::TopRight: return HTTOPRIGHT; case HitTestResult::TopRight: return HTTOPRIGHT;
@ -535,13 +542,16 @@ bool WindowHelper::handleNativeEvent(
case HitTestResult::BottomLeft: return HTBOTTOMLEFT; case HitTestResult::BottomLeft: return HTBOTTOMLEFT;
case HitTestResult::Left: return HTLEFT; case HitTestResult::Left: return HTLEFT;
case HitTestResult::TopLeft: return HTTOPLEFT; case HitTestResult::TopLeft: return HTTOPLEFT;
case HitTestResult::Minimize:
case HitTestResult::MaximizeRestore:
case HitTestResult::Close: return systemButtonHitTest(result);
case HitTestResult::None: case HitTestResult::None:
default: return HTTRANSPARENT; default: return HTTRANSPARENT;
}; };
}(); }();
if (complexSysButtonProcessing()) { _systemButtonOver.fire(systemButtonHitTest(*result));
_title->sysButtonOver(sysButtonHitTest(*result));
}
} return true; } return true;
case WM_SYSCOMMAND: { case WM_SYSCOMMAND: {
@ -591,12 +601,12 @@ bool WindowHelper::fixedSize() const {
return window()->minimumSize() == window()->maximumSize(); return window()->minimumSize() == window()->maximumSize();
} }
bool WindowHelper::handleSysButtonEvent( bool WindowHelper::handleSystemButtonEvent(
UINT msg, UINT msg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
LRESULT *result) { LRESULT *result) {
if (!complexSysButtonProcessing()) { if (_title->isHidden()) {
return false; return false;
} }
const auto testResult = LOWORD(wParam); const auto testResult = LOWORD(wParam);
@ -616,9 +626,9 @@ bool WindowHelper::handleSysButtonEvent(
case WM_NCLBUTTONDOWN: case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP: case WM_NCLBUTTONUP:
_title->sysButtonDown( _systemButtonDown.fire((msg == WM_NCLBUTTONDOWN)
sysButtonHitTest(testResult), ? systemButtonHitTest(testResult)
(msg == WM_NCLBUTTONDOWN)); : HitTestResult::None);
if (overSysButton) { if (overSysButton) {
if (result) *result = 0; if (result) *result = 0;
} }
@ -636,20 +646,20 @@ bool WindowHelper::handleSysButtonEvent(
return true; return true;
case WM_NCMOUSEHOVER: case WM_NCMOUSEHOVER:
case WM_NCMOUSEMOVE: case WM_NCMOUSEMOVE:
_title->sysButtonOver(sysButtonHitTest(testResult)); _systemButtonOver.fire(systemButtonHitTest(testResult));
if (overSysButton) { if (overSysButton) {
if (result) *result = 0; if (result) *result = 0;
} }
return overSysButton; return overSysButton;
case WM_NCMOUSELEAVE: case WM_NCMOUSELEAVE:
_title->sysButtonOver(HitTestResult::None); _systemButtonOver.fire(HitTestResult::None);
return false; return false;
} }
return false; return false;
} }
int WindowHelper::sysButtonHitTest(HitTestResult result) const { int WindowHelper::systemButtonHitTest(HitTestResult result) const {
if (!complexSysButtonProcessing()) { if (!SemiNativeSystemButtonProcessing()) {
return HTCLIENT; return HTCLIENT;
} }
switch (result) { switch (result) {
@ -660,9 +670,9 @@ int WindowHelper::sysButtonHitTest(HitTestResult result) const {
return HTTRANSPARENT; return HTTRANSPARENT;
} }
HitTestResult WindowHelper::sysButtonHitTest(int result) const { HitTestResult WindowHelper::systemButtonHitTest(int result) const {
if (!complexSysButtonProcessing()) { if (!SemiNativeSystemButtonProcessing()) {
return HitTestResult::Client; return HitTestResult::None;
} }
switch (result) { switch (result) {
case HTMINBUTTON: return HitTestResult::Minimize; case HTMINBUTTON: return HitTestResult::Minimize;
@ -672,15 +682,6 @@ HitTestResult WindowHelper::sysButtonHitTest(int result) const {
return HitTestResult::None; return HitTestResult::None;
} }
bool WindowHelper::complexSysButtonProcessing() const {
if (_title->isHidden()) {
return false;
} else if (!::Platform::IsWindows11OrGreater()) {
return false;
}
return true;
}
int WindowHelper::titleHeight() const { int WindowHelper::titleHeight() const {
return _title->isHidden() ? 0 : _title->height(); return _title->isHidden() ? 0 : _title->height();
} }

View file

@ -15,6 +15,7 @@ namespace Ui {
namespace Platform { namespace Platform {
class TitleWidget; class TitleWidget;
struct HitTestRequest;
enum class HitTestResult; enum class HitTestResult;
class WindowHelper final : public BasicWindowHelper { class WindowHelper final : public BasicWindowHelper {
@ -22,6 +23,7 @@ public:
explicit WindowHelper(not_null<RpWidget*> window); explicit WindowHelper(not_null<RpWidget*> window);
~WindowHelper(); ~WindowHelper();
void initInWindow(not_null<RpWindow*> window) override;
not_null<RpWidget*> body() override; not_null<RpWidget*> body() override;
QMargins frameMargins() override; QMargins frameMargins() override;
int additionalContentPadding() const override; int additionalContentPadding() const override;
@ -35,6 +37,13 @@ public:
void showFullScreen() override; void showFullScreen() override;
void showNormal() override; void showNormal() override;
[[nodiscard]] auto hitTestRequests() const
-> rpl::producer<not_null<HitTestRequest*>> override;
[[nodiscard]] auto systemButtonOver() const
-> rpl::producer<HitTestResult> override;
[[nodiscard]] auto systemButtonDown() const
-> rpl::producer<HitTestResult> override;
private: private:
class NativeFilter; class NativeFilter;
friend class NativeFilter; friend class NativeFilter;
@ -53,15 +62,14 @@ private:
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
LRESULT *result); LRESULT *result);
[[nodiscard]] bool handleSysButtonEvent( [[nodiscard]] bool handleSystemButtonEvent(
UINT msg, UINT msg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
LRESULT *result); LRESULT *result);
[[nodiscard]] bool fixedSize() const; [[nodiscard]] bool fixedSize() const;
[[nodiscard]] bool complexSysButtonProcessing() const; [[nodiscard]] int systemButtonHitTest(HitTestResult result) const;
[[nodiscard]] int sysButtonHitTest(HitTestResult result) const; [[nodiscard]] HitTestResult systemButtonHitTest(int result) const;
[[nodiscard]] HitTestResult sysButtonHitTest(int result) const;
[[nodiscard]] int titleHeight() const; [[nodiscard]] int titleHeight() const;
static not_null<NativeFilter*> GetNativeFilter(); static not_null<NativeFilter*> GetNativeFilter();
@ -69,10 +77,13 @@ private:
const HWND _handle = nullptr; const HWND _handle = nullptr;
const not_null<TitleWidget*> _title; const not_null<TitleWidget*> _title;
const not_null<RpWidget*> _body; const not_null<RpWidget*> _body;
rpl::event_stream<not_null<HitTestRequest*>> _hitTestRequests;
rpl::event_stream<HitTestResult> _systemButtonOver;
rpl::event_stream<HitTestResult> _systemButtonDown;
std::optional<WindowShadow> _shadow; std::optional<WindowShadow> _shadow;
bool _updatingMargins = false;
QMargins _marginsDelta; QMargins _marginsDelta;
HMENU _menu = nullptr; HMENU _menu = nullptr;
bool _updatingMargins = false;
bool _isFullScreen = false; bool _isFullScreen = false;
}; };

View file

@ -15,6 +15,7 @@ RpWindow::RpWindow(QWidget *parent)
, _helper(Platform::CreateWindowHelper(this)) { , _helper(Platform::CreateWindowHelper(this)) {
Expects(_helper != nullptr); Expects(_helper != nullptr);
_helper->initInWindow(this);
hide(); hide();
} }
@ -40,6 +41,19 @@ rpl::producer<int> RpWindow::additionalContentPaddingValue() const {
return _helper->additionalContentPaddingValue(); return _helper->additionalContentPaddingValue();
} }
auto RpWindow::hitTestRequests() const
-> rpl::producer<not_null<Platform::HitTestRequest*>> {
return _helper->hitTestRequests();
}
rpl::producer<Platform::HitTestResult> RpWindow::systemButtonOver() const {
return _helper->systemButtonOver();
}
rpl::producer<Platform::HitTestResult> RpWindow::systemButtonDown() const {
return _helper->systemButtonDown();
}
void RpWindow::setTitle(const QString &title) { void RpWindow::setTitle(const QString &title) {
_helper->setTitle(title); _helper->setTitle(title);
} }

View file

@ -16,6 +16,8 @@ struct WindowTitle;
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
class BasicWindowHelper; class BasicWindowHelper;
struct HitTestRequest;
enum class HitTestResult;
} // namespace Platform } // namespace Platform
enum class WindowTitleHitTestFlag { enum class WindowTitleHitTestFlag {
@ -46,6 +48,13 @@ public:
[[nodiscard]] int additionalContentPadding() const; [[nodiscard]] int additionalContentPadding() const;
[[nodiscard]] rpl::producer<int> additionalContentPaddingValue() const; [[nodiscard]] rpl::producer<int> additionalContentPaddingValue() const;
[[nodiscard]] auto hitTestRequests() const
-> rpl::producer<not_null<Platform::HitTestRequest*>>;
[[nodiscard]] auto systemButtonOver() const
-> rpl::producer<Platform::HitTestResult>;
[[nodiscard]] auto systemButtonDown() const
-> rpl::producer<Platform::HitTestResult>;
void setTitle(const QString &title); void setTitle(const QString &title);
void setTitleStyle(const style::WindowTitle &st); void setTitleStyle(const style::WindowTitle &st);
void setNativeFrame(bool enabled); void setNativeFrame(bool enabled);