Add Windows 11 snap layouts to custom TitleControls.
This commit is contained in:
parent
d5d2ccb467
commit
47aed59fe9
10 changed files with 200 additions and 76 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue