Skip to content

Commit

Permalink
Add Windows 11 snap layouts to custom TitleControls.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-preston committed Jan 18, 2022
1 parent d5d2ccb commit 47aed59
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 76 deletions.
16 changes: 16 additions & 0 deletions ui/platform/ui_platform_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ BasicWindowHelper::BasicWindowHelper(not_null<RpWidget*> window)
_window->setWindowFlag(Qt::Window);
}

void BasicWindowHelper::initInWindow(not_null<RpWindow*> window) {
}

not_null<RpWidget*> BasicWindowHelper::body() {
return _window;
}
Expand All @@ -49,6 +52,19 @@ rpl::producer<int> BasicWindowHelper::additionalContentPaddingValue() const {
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) {
_window->setWindowTitle(title);
}
Expand Down
19 changes: 15 additions & 4 deletions ui/platform/ui_platform_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,37 @@ struct WindowTitle;
namespace Ui {

class RpWidget;
class RpWindow;
enum class WindowTitleHitTestFlag;
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;

namespace Platform {

struct HitTestRequest;
enum class HitTestResult;
class DefaultTitleWidget;

class BasicWindowHelper {
public:
explicit BasicWindowHelper(not_null<RpWidget*> window);
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 QMargins frameMargins();
[[nodiscard]] virtual int additionalContentPadding() const;
[[nodiscard]] virtual auto additionalContentPaddingValue() const
-> 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 setTitleStyle(const style::WindowTitle &st);
virtual void setNativeFrame(bool enabled);
Expand All @@ -46,9 +60,6 @@ class BasicWindowHelper {
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);

protected:
[[nodiscard]] not_null<RpWidget*> window() const {
return _window;
}
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
QPoint point) const {
return _bodyTitleAreaTestMethod
Expand Down Expand Up @@ -111,7 +122,7 @@ class DefaultWindowHelper final : public QObject, public BasicWindowHelper {
return std::make_unique<DefaultWindowHelper>(window);
}

bool NativeWindowFrameSupported();
[[nodiscard]] bool NativeWindowFrameSupported();

} // namespace Platform
} // namespace Ui
51 changes: 47 additions & 4 deletions ui/platform/ui_platform_window_title.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "styles/palette.h"
#include "base/algorithm.h"
#include "base/event_filter.h"
#include "base/platform/base_platform_info.h"

#include <QtGui/QPainter>
#include <QtGui/QtEvents>
Expand All @@ -36,6 +37,34 @@ void RemoveDuplicates(std::vector<T> &v) {

} // 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 {
public:
using IconButton::IconButton;
Expand Down Expand Up @@ -216,12 +245,12 @@ void TitleControls::buttonOver(HitTestResult testResult) {
update(_close, HitTestResult::Close);
}

void TitleControls::buttonDown(HitTestResult testResult, bool down) {
void TitleControls::buttonDown(HitTestResult testResult) {
const auto update = [&](
const object_ptr<Button> &button,
HitTestResult buttonTestResult) {
if (const auto raw = button.data()) {
raw->setDown(testResult == buttonTestResult && down);
raw->setDown(testResult == buttonTestResult);
}
};
update(_minimize, HitTestResult::Minimize);
Expand Down Expand Up @@ -456,16 +485,30 @@ std::unique_ptr<SeparateTitleControls> SetupSeparateTitleControls(
st,
std::move(maximize));

const auto raw = result.get();
auto &lifetime = raw->wrap.lifetime();
rpl::combine(
window->body()->widthValue(),
window->additionalContentPaddingValue()
) | rpl::start_with_next([raw = result.get()](int width, int padding) {
) | rpl::start_with_next([=](int width, int padding) {
raw->wrap.setGeometry(
padding,
0,
width - 2 * padding,
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;
}
Expand Down
16 changes: 15 additions & 1 deletion ui/platform/ui_platform_window_title.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class RpWindow;

namespace Platform {

class TitleControls;

enum class HitTestResult {
None = 0,
Client,
Expand All @@ -41,6 +43,18 @@ enum class HitTestResult {
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 {
public:
TitleControls(
Expand All @@ -57,7 +71,7 @@ class TitleControls final {
[[nodiscard]] HitTestResult hitTest(QPoint point) const;

void buttonOver(HitTestResult testResult);
void buttonDown(HitTestResult testResult, bool down);
void buttonDown(HitTestResult testResult);

enum class Control {
Unknown,
Expand Down
36 changes: 21 additions & 15 deletions ui/platform/win/ui_window_title_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "ui/platform/win/ui_window_win.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/rp_window.h"
#include "ui/ui_utility.h"
#include "base/platform/base_platform_info.h"
#include "base/platform/win/base_windows_safe_library.h"
Expand Down Expand Up @@ -68,6 +69,19 @@ TitleWidget::TitleWidget(not_null<RpWidget*> parent)
}, 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;

void TitleWidget::setText(const QString &text) {
Expand Down Expand Up @@ -113,27 +127,19 @@ void TitleWidget::resizeEvent(QResizeEvent *e) {
}

HitTestResult TitleWidget::hitTest(QPoint point) const {
const auto titleResult = _controls.hitTest(point);
if (titleResult != HitTestResult::None) {
return titleResult;
} else if (rect().contains(point)) {
return HitTestResult::Caption;
}
return HitTestResult::None;
const auto origin = _paddingHelper
? _paddingHelper->controlsParent.pos()
: QPoint();
const auto controlsResult = _controls.hitTest(point - origin);
return (controlsResult != HitTestResult::None)
? controlsResult
: HitTestResult::Caption;
}

bool TitleWidget::additionalPaddingRequired() const {
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() {
if (!additionalPaddingRequired()) {
return;
Expand Down
7 changes: 3 additions & 4 deletions ui/platform/win/ui_window_title_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct WindowTitle;

namespace Ui {

class RpWindow;
class IconButton;
class PlainShadow;

Expand All @@ -31,10 +32,10 @@ class TitleWidget : public RpWidget {
explicit TitleWidget(not_null<RpWidget*> parent);
~TitleWidget();

void initInWindow(not_null<RpWindow*> window);
void setText(const QString &text);
void setStyle(const style::WindowTitle &st);
[[nodiscard]] not_null<const style::WindowTitle*> st() const;
[[nodiscard]] HitTestResult hitTest(QPoint point) const;
void setResizeEnabled(bool enabled);

void refreshAdditionalPaddings();
Expand All @@ -45,9 +46,6 @@ class TitleWidget : public RpWidget {
[[nodiscard]] int additionalPadding() const;
[[nodiscard]] rpl::producer<int> additionalPaddingValue() const;

void sysButtonOver(HitTestResult testResult);
void sysButtonDown(HitTestResult testResult, bool down);

protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
Expand All @@ -57,6 +55,7 @@ class TitleWidget : public RpWidget {
private:
struct PaddingHelper;

[[nodiscard]] HitTestResult hitTest(QPoint point) const;
[[nodiscard]] bool additionalPaddingRequired() const;
void refreshGeometryWithWidth(int width);
void setAdditionalPadding(int padding);
Expand Down
Loading

0 comments on commit 47aed59

Please sign in to comment.