Add possibility to enable native window frame to Ui::Window

This commit is contained in:
Ilya Fedin 2021-07-28 00:07:09 +04:00 committed by John Preston
parent 95cafc5064
commit 7a71876124
12 changed files with 229 additions and 54 deletions

View file

@ -253,6 +253,7 @@ elseif(LINUX)
target_link_libraries(lib_ui target_link_libraries(lib_ui
PUBLIC PUBLIC
desktop-app::lib_waylandshells desktop-app::lib_waylandshells
desktop-app::external_kwayland
) )
endif() endif()

View file

@ -24,23 +24,71 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <private/qwaylandwindow_p.h> #include <private/qwaylandwindow_p.h>
#include <private/qwaylandshellsurface_p.h> #include <private/qwaylandshellsurface_p.h>
#include <connection_thread.h>
#include <registry.h>
Q_DECLARE_METATYPE(QMargins); Q_DECLARE_METATYPE(QMargins);
using QtWaylandClient::QWaylandIntegration; using QtWaylandClient::QWaylandIntegration;
using QtWaylandClient::QWaylandWindow; using QtWaylandClient::QWaylandWindow;
using namespace KWayland::Client;
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
WaylandIntegration::WaylandIntegration() { struct WaylandIntegration::Private {
std::unique_ptr<ConnectionThread> connection;
Registry registry;
QEventLoop interfacesLoop;
bool interfacesAnnounced = false;
};
WaylandIntegration::WaylandIntegration()
: _private(std::make_unique<Private>()) {
_private->connection = std::unique_ptr<ConnectionThread>{
ConnectionThread::fromApplication(),
};
_private->registry.create(_private->connection.get());
_private->registry.setup();
QObject::connect(
_private->connection.get(),
&ConnectionThread::connectionDied,
&_private->registry,
&Registry::destroy);
QObject::connect(
&_private->registry,
&Registry::interfacesAnnounced,
[=] {
_private->interfacesAnnounced = true;
if (_private->interfacesLoop.isRunning()) {
_private->interfacesLoop.quit();
}
});
} }
WaylandIntegration::~WaylandIntegration() = default;
WaylandIntegration *WaylandIntegration::Instance() { WaylandIntegration *WaylandIntegration::Instance() {
if (!::Platform::IsWayland()) return nullptr; if (!::Platform::IsWayland()) return nullptr;
static WaylandIntegration instance; static WaylandIntegration instance;
return &instance; return &instance;
} }
void WaylandIntegration::waitForInterfaceAnnounce() {
Expects(!_private->interfacesLoop.isRunning());
if (!_private->interfacesAnnounced) {
_private->interfacesLoop.exec();
}
}
bool WaylandIntegration::xdgDecorationSupported() {
return _private->registry.hasInterface(
Registry::Interface::XdgDecorationUnstableV1);
}
bool WaylandIntegration::windowExtentsSupported() { bool WaylandIntegration::windowExtentsSupported() {
// initialize shell integration before querying // initialize shell integration before querying
if (const auto integration = static_cast<QWaylandIntegration*>( if (const auto integration = static_cast<QWaylandIntegration*>(

View file

@ -14,15 +14,21 @@ namespace Platform {
class WaylandIntegration { class WaylandIntegration {
public: public:
static WaylandIntegration *Instance(); [[nodiscard]] static WaylandIntegration *Instance();
bool windowExtentsSupported(); void waitForInterfaceAnnounce();
[[nodiscard]] bool xdgDecorationSupported();
[[nodiscard]] bool windowExtentsSupported();
void setWindowExtents(QWindow *window, const QMargins &extents); void setWindowExtents(QWindow *window, const QMargins &extents);
void unsetWindowExtents(QWindow *window); void unsetWindowExtents(QWindow *window);
bool showWindowMenu(QWindow *window); bool showWindowMenu(QWindow *window);
private: private:
WaylandIntegration(); WaylandIntegration();
~WaylandIntegration();
struct Private;
const std::unique_ptr<Private> _private;
}; };
} // namespace Platform } // namespace Platform

View file

@ -12,6 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
struct WaylandIntegration::Private {
};
WaylandIntegration::WaylandIntegration() { WaylandIntegration::WaylandIntegration() {
} }
@ -21,6 +24,13 @@ WaylandIntegration *WaylandIntegration::Instance() {
return &instance; return &instance;
} }
void WaylandIntegration::waitForInterfaceAnnounce() {
}
bool WaylandIntegration::xdgDecorationSupported() {
return false;
}
bool WaylandIntegration::windowExtentsSupported() { bool WaylandIntegration::windowExtentsSupported() {
return false; return false;
} }

View file

@ -6,6 +6,8 @@
// //
#include "ui/platform/linux/ui_window_linux.h" #include "ui/platform/linux/ui_window_linux.h"
#include "ui/platform/linux/ui_linux_wayland_integration.h"
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
@ -14,5 +16,11 @@ std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
return nullptr; return nullptr;
} }
bool NativeWindowFrameSupported() {
const auto waylandIntegration = WaylandIntegration::Instance();
return !waylandIntegration
|| waylandIntegration->xdgDecorationSupported();
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -412,5 +412,9 @@ std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
return std::make_unique<WindowHelper>(window); return std::make_unique<WindowHelper>(window);
} }
bool NativeWindowFrameSupported() {
return false;
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -44,6 +44,9 @@ void BasicWindowHelper::setTitle(const QString &title) {
void BasicWindowHelper::setTitleStyle(const style::WindowTitle &st) { void BasicWindowHelper::setTitleStyle(const style::WindowTitle &st) {
} }
void BasicWindowHelper::setNativeFrame(bool enabled) {
}
void BasicWindowHelper::setMinimumSize(QSize size) { void BasicWindowHelper::setMinimumSize(QSize size) {
_window->setMinimumSize(size); _window->setMinimumSize(size);
} }
@ -161,17 +164,21 @@ void DefaultWindowHelper::init() {
rpl::combine( rpl::combine(
window()->sizeValue(), window()->sizeValue(),
_title->heightValue() _title->heightValue(),
) | rpl::start_with_next([=](QSize size, int titleHeight) { _title->shownValue()
) | rpl::start_with_next([=](
QSize size,
int titleHeight,
bool titleShown) {
const auto area = resizeArea(); const auto area = resizeArea();
const auto sizeWithoutMargins = size const auto sizeWithoutMargins = size
.shrunkBy({ 0, titleHeight, 0, 0 }) .shrunkBy({ 0, titleShown ? titleHeight : 0, 0, 0 })
.shrunkBy(area); .shrunkBy(area);
const auto topLeft = QPoint( const auto topLeft = QPoint(
area.left(), area.left(),
area.top() + titleHeight); area.top() + (titleShown ? titleHeight : 0));
_body->setGeometry(QRect(topLeft, sizeWithoutMargins)); _body->setGeometry(QRect(topLeft, sizeWithoutMargins));
}, _body->lifetime()); }, _body->lifetime());
@ -233,7 +240,9 @@ bool DefaultWindowHelper::hasShadow() const {
} }
QMargins DefaultWindowHelper::resizeArea() const { QMargins DefaultWindowHelper::resizeArea() const {
if (window()->isMaximized() || window()->isFullScreen()) { if (window()->isMaximized()
|| window()->isFullScreen()
|| _nativeFrame) {
return QMargins(); return QMargins();
} }
@ -310,16 +319,23 @@ void DefaultWindowHelper::setTitleStyle(const style::WindowTitle &st) {
_title->st()->height); _title->st()->height);
} }
void DefaultWindowHelper::setNativeFrame(bool enabled) {
_nativeFrame = enabled;
window()->windowHandle()->setFlag(Qt::FramelessWindowHint, !enabled);
_title->setVisible(!enabled);
updateWindowExtents();
}
void DefaultWindowHelper::setMinimumSize(QSize size) { void DefaultWindowHelper::setMinimumSize(QSize size) {
const auto sizeWithMargins = size const auto sizeWithMargins = size
.grownBy({ 0, _title->height(), 0, 0 }) .grownBy({ 0, _title->isVisible() ? _title->height() : 0, 0, 0 })
.grownBy(resizeArea()); .grownBy(resizeArea());
window()->setMinimumSize(sizeWithMargins); window()->setMinimumSize(sizeWithMargins);
} }
void DefaultWindowHelper::setFixedSize(QSize size) { void DefaultWindowHelper::setFixedSize(QSize size) {
const auto sizeWithMargins = size const auto sizeWithMargins = size
.grownBy({ 0, _title->height(), 0, 0 }) .grownBy({ 0, _title->isVisible() ? _title->height() : 0, 0, 0 })
.grownBy(resizeArea()); .grownBy(resizeArea());
window()->setFixedSize(sizeWithMargins); window()->setFixedSize(sizeWithMargins);
_title->setResizeEnabled(false); _title->setResizeEnabled(false);
@ -327,7 +343,7 @@ void DefaultWindowHelper::setFixedSize(QSize size) {
void DefaultWindowHelper::setGeometry(QRect rect) { void DefaultWindowHelper::setGeometry(QRect rect) {
window()->setGeometry(rect window()->setGeometry(rect
.marginsAdded({ 0, _title->height(), 0, 0 }) .marginsAdded({ 0, _title->isVisible() ? _title->height() : 0, 0, 0 })
.marginsAdded(resizeArea())); .marginsAdded(resizeArea()));
} }
@ -376,7 +392,7 @@ void DefaultWindowHelper::paintBorders(QPainter &p) {
} }
void DefaultWindowHelper::updateWindowExtents() { void DefaultWindowHelper::updateWindowExtents() {
if (hasShadow()) { if (hasShadow() && !_nativeFrame) {
Platform::SetWindowExtents( Platform::SetWindowExtents(
window()->windowHandle(), window()->windowHandle(),
resizeArea()); resizeArea());

View file

@ -30,6 +30,7 @@ public:
[[nodiscard]] virtual not_null<RpWidget*> body(); [[nodiscard]] virtual not_null<RpWidget*> body();
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 setMinimumSize(QSize size); virtual void setMinimumSize(QSize size);
virtual void setFixedSize(QSize size); virtual void setFixedSize(QSize size);
virtual void setStaysOnTop(bool enabled); virtual void setStaysOnTop(bool enabled);
@ -67,6 +68,7 @@ public:
not_null<RpWidget*> body() override; not_null<RpWidget*> body() override;
void setTitle(const QString &title) override; void setTitle(const QString &title) override;
void setTitleStyle(const style::WindowTitle &st) override; void setTitleStyle(const style::WindowTitle &st) override;
void setNativeFrame(bool enabled) override;
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;
@ -86,6 +88,7 @@ private:
const not_null<DefaultTitleWidget*> _title; const not_null<DefaultTitleWidget*> _title;
const not_null<RpWidget*> _body; const not_null<RpWidget*> _body;
bool _extentsSet = false; bool _extentsSet = false;
bool _nativeFrame = false;
}; };
@ -100,5 +103,7 @@ private:
return std::make_unique<DefaultWindowHelper>(window); return std::make_unique<DefaultWindowHelper>(window);
} }
bool NativeWindowFrameSupported();
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -148,7 +148,7 @@ WindowHelper::WindowHelper(not_null<RpWidget*> window)
, _handle(GetWindowHandle(window)) , _handle(GetWindowHandle(window))
, _title(Ui::CreateChild<TitleWidget>(window.get())) , _title(Ui::CreateChild<TitleWidget>(window.get()))
, _body(Ui::CreateChild<RpWidget>(window.get())) , _body(Ui::CreateChild<RpWidget>(window.get()))
, _shadow(window, st::windowShadowFg->c) { , _shadow(std::in_place, window, st::windowShadowFg->c) {
Expects(_handle != nullptr); Expects(_handle != nullptr);
GetNativeFilter()->registerWindow(_handle, this); GetNativeFilter()->registerWindow(_handle, this);
@ -172,18 +172,36 @@ void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
_title->setStyle(st); _title->setStyle(st);
} }
void WindowHelper::setNativeFrame(bool enabled) {
_nativeFrame = enabled;
_title->setVisible(!enabled);
if (enabled) {
_shadow.reset();
} else {
_shadow.emplace(window(), st::windowShadowFg->c);
_shadow->setResizeEnabled(!fixedSize());
}
updateMargins();
fixMaximizedWindow();
}
void WindowHelper::setMinimumSize(QSize size) { void WindowHelper::setMinimumSize(QSize size) {
window()->setMinimumSize(size.width(), _title->height() + size.height()); const auto titleHeight = _title->isVisible() ? _title->height() : 0;
window()->setMinimumSize(size.width(), titleHeight + size.height());
} }
void WindowHelper::setFixedSize(QSize size) { void WindowHelper::setFixedSize(QSize size) {
window()->setFixedSize(size.width(), _title->height() + size.height()); const auto titleHeight = _title->isVisible() ? _title->height() : 0;
window()->setFixedSize(size.width(), titleHeight + size.height());
_title->setResizeEnabled(false); _title->setResizeEnabled(false);
_shadow.setResizeEnabled(false); if (_shadow) {
_shadow->setResizeEnabled(false);
}
} }
void WindowHelper::setGeometry(QRect rect) { void WindowHelper::setGeometry(QRect rect) {
window()->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 })); const auto titleHeight = _title->isVisible() ? _title->height() : 0;
window()->setGeometry(rect.marginsAdded({ 0, titleHeight, 0, 0 }));
} }
void WindowHelper::showFullScreen() { void WindowHelper::showFullScreen() {
@ -205,19 +223,25 @@ void WindowHelper::showNormal() {
void WindowHelper::init() { void WindowHelper::init() {
style::PaletteChanged( style::PaletteChanged(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
_shadow.setColor(st::windowShadowFg->c); if (_shadow) {
_shadow->setColor(st::windowShadowFg->c);
}
Ui::ForceFullRepaint(window()); Ui::ForceFullRepaint(window());
}, window()->lifetime()); }, window()->lifetime());
rpl::combine( rpl::combine(
window()->sizeValue(), window()->sizeValue(),
_title->heightValue() _title->heightValue(),
) | rpl::start_with_next([=](QSize size, int titleHeight) { _title->shownValue()
) | rpl::start_with_next([=](
QSize size,
int titleHeight,
bool titleShown) {
_body->setGeometry( _body->setGeometry(
0, 0,
titleHeight, titleShown ? titleHeight : 0,
size.width(), size.width(),
size.height() - titleHeight); size.height() - (titleShown ? titleHeight : 0));
}, _body->lifetime()); }, _body->lifetime());
updateMargins(); updateMargins();
@ -256,22 +280,27 @@ bool WindowHelper::handleNativeEvent(
if (LOWORD(wParam) == WA_CLICKACTIVE) { if (LOWORD(wParam) == WA_CLICKACTIVE) {
Ui::MarkInactivePress(window(), true); Ui::MarkInactivePress(window(), true);
} }
if (LOWORD(wParam) != WA_INACTIVE) { if (_shadow) {
_shadow.update(WindowShadow::Change::Activate); if (LOWORD(wParam) != WA_INACTIVE) {
} else { _shadow->update(WindowShadow::Change::Activate);
_shadow.update(WindowShadow::Change::Deactivate); } else {
_shadow->update(WindowShadow::Change::Deactivate);
}
} }
window()->update(); window()->update();
} return false; } return false;
case WM_NCPAINT: { case WM_NCPAINT: {
if (::Platform::IsWindows8OrGreater()) { if (::Platform::IsWindows8OrGreater() || _nativeFrame) {
return false; return false;
} }
if (result) *result = 0; if (result) *result = 0;
} return true; } return true;
case WM_NCCALCSIZE: { case WM_NCCALCSIZE: {
if (_nativeFrame) {
return false;
}
WINDOWPLACEMENT wp; WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT); wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(_handle, &wp) if (GetWindowPlacement(_handle, &wp)
@ -315,6 +344,9 @@ bool WindowHelper::handleNativeEvent(
} return true; } return true;
case WM_NCACTIVATE: { case WM_NCACTIVATE: {
if (_nativeFrame) {
return false;
}
if (IsCompositionEnabled()) { if (IsCompositionEnabled()) {
const auto res = DefWindowProc(_handle, msg, wParam, -1); const auto res = DefWindowProc(_handle, msg, wParam, -1);
if (result) *result = res; if (result) *result = res;
@ -326,16 +358,18 @@ bool WindowHelper::handleNativeEvent(
case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED: { case WM_WINDOWPOSCHANGED: {
WINDOWPLACEMENT wp; if (_shadow) {
wp.length = sizeof(WINDOWPLACEMENT); WINDOWPLACEMENT wp;
if (GetWindowPlacement(_handle, &wp) wp.length = sizeof(WINDOWPLACEMENT);
&& (wp.showCmd == SW_SHOWMAXIMIZED if (GetWindowPlacement(_handle, &wp)
|| wp.showCmd == SW_SHOWMINIMIZED)) { && (wp.showCmd == SW_SHOWMAXIMIZED
_shadow.update(WindowShadow::Change::Hidden); || wp.showCmd == SW_SHOWMINIMIZED)) {
} else { _shadow->update(WindowShadow::Change::Hidden);
_shadow.update( } else {
WindowShadow::Change::Moved | WindowShadow::Change::Resized, _shadow->update(
(WINDOWPOS*)lParam); WindowShadow::Change::Moved | WindowShadow::Change::Resized,
(WINDOWPOS*)lParam);
}
} }
} return false; } return false;
@ -354,30 +388,36 @@ bool WindowHelper::handleNativeEvent(
window()->windowHandle()->windowStateChanged(state); window()->windowHandle()->windowStateChanged(state);
} }
updateMargins(); updateMargins();
const auto changes = (wParam == SIZE_MINIMIZED if (_shadow) {
|| wParam == SIZE_MAXIMIZED) const auto changes = (wParam == SIZE_MINIMIZED
? WindowShadow::Change::Hidden || wParam == SIZE_MAXIMIZED)
: (WindowShadow::Change::Resized ? WindowShadow::Change::Hidden
| WindowShadow::Change::Shown); : (WindowShadow::Change::Resized
_shadow.update(changes); | WindowShadow::Change::Shown);
_shadow->update(changes);
}
} }
} return false; } return false;
case WM_SHOWWINDOW: { case WM_SHOWWINDOW: {
const auto style = GetWindowLongPtr(_handle, GWL_STYLE); if (_shadow) {
const auto changes = WindowShadow::Change::Resized const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
| ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) const auto changes = WindowShadow::Change::Resized
? WindowShadow::Change::Shown | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE)))
: WindowShadow::Change::Hidden); ? WindowShadow::Change::Shown
_shadow.update(changes); : WindowShadow::Change::Hidden);
_shadow->update(changes);
}
} return false; } return false;
case WM_MOVE: { case WM_MOVE: {
_shadow.update(WindowShadow::Change::Moved); if (_shadow) {
_shadow->update(WindowShadow::Change::Moved);
}
} return false; } return false;
case WM_NCHITTEST: { case WM_NCHITTEST: {
if (!result) { if (!result || _nativeFrame) {
return false; return false;
} }
@ -389,7 +429,7 @@ bool WindowHelper::handleNativeEvent(
p.y - r.top + _marginsDelta.top()); p.y - r.top + _marginsDelta.top());
if (!window()->rect().contains(mapped)) { if (!window()->rect().contains(mapped)) {
*result = HTTRANSPARENT; *result = HTTRANSPARENT;
} else if (!_title->geometry().contains(mapped)) { } else if (!_title->isVisible() || !_title->geometry().contains(mapped)) {
*result = HTCLIENT; *result = HTCLIENT;
} else switch (_title->hitTest(_title->pos() + mapped)) { } else switch (_title->hitTest(_title->pos() + mapped)) {
case HitTestResult::Client: case HitTestResult::Client:
@ -409,6 +449,9 @@ bool WindowHelper::handleNativeEvent(
} return true; } return true;
case WM_NCRBUTTONUP: { case WM_NCRBUTTONUP: {
if (_nativeFrame) {
return false;
}
SendMessage(_handle, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); SendMessage(_handle, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
} return true; } return true;
@ -519,8 +562,11 @@ void WindowHelper::updateMargins() {
_marginsDelta = QMargins(); _marginsDelta = QMargins();
} }
if (_isFullScreen) { if (_isFullScreen || _nativeFrame) {
margins = QMargins(); margins = QMargins();
if (_nativeFrame) {
_marginsDelta = QMargins();
}
} }
if (const auto native = QGuiApplication::platformNativeInterface()) { if (const auto native = QGuiApplication::platformNativeInterface()) {
native->setWindowProperty( native->setWindowProperty(
@ -573,6 +619,25 @@ void WindowHelper::updateSystemMenu(Qt::WindowState state) {
} }
} }
void WindowHelper::fixMaximizedWindow() {
auto r = RECT();
GetClientRect(_handle, &r);
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
const auto styleEx = GetWindowLongPtr(_handle, GWL_EXSTYLE);
AdjustWindowRectEx(&r, style, false, styleEx);
if (style & WS_MAXIMIZE) {
auto w = RECT();
GetWindowRect(_handle, &w);
if (const auto hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST)) {
MONITORINFO mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
const auto m = mi.rcWork;
SetWindowPos(_handle, 0, 0, 0, m.right - m.left - _marginsDelta.left() - _marginsDelta.right(), m.bottom - m.top - _marginsDelta.top() - _marginsDelta.bottom(), SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
}
}
}
not_null<WindowHelper::NativeFilter*> WindowHelper::GetNativeFilter() { not_null<WindowHelper::NativeFilter*> WindowHelper::GetNativeFilter() {
Expects(QCoreApplication::instance() != nullptr); Expects(QCoreApplication::instance() != nullptr);
@ -619,5 +684,9 @@ std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
return std::make_unique<WindowHelper>(window); return std::make_unique<WindowHelper>(window);
} }
bool NativeWindowFrameSupported() {
return true;
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -24,6 +24,7 @@ public:
not_null<RpWidget*> body() override; not_null<RpWidget*> body() override;
void setTitle(const QString &title) override; void setTitle(const QString &title) override;
void setTitleStyle(const style::WindowTitle &st) override; void setTitleStyle(const style::WindowTitle &st) override;
void setNativeFrame(bool enabled) override;
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;
@ -38,6 +39,7 @@ private:
void updateMargins(); void updateMargins();
void updateSystemMenu(); void updateSystemMenu();
void updateSystemMenu(Qt::WindowState state); void updateSystemMenu(Qt::WindowState state);
void fixMaximizedWindow();
[[nodiscard]] bool handleNativeEvent( [[nodiscard]] bool handleNativeEvent(
UINT msg, UINT msg,
WPARAM wParam, WPARAM wParam,
@ -50,11 +52,12 @@ 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;
WindowShadow _shadow; std::optional<WindowShadow> _shadow;
bool _updatingMargins = false; bool _updatingMargins = false;
QMargins _marginsDelta; QMargins _marginsDelta;
HMENU _menu = nullptr; HMENU _menu = nullptr;
bool _isFullScreen = false; bool _isFullScreen = false;
bool _nativeFrame = false;
}; };

View file

@ -36,6 +36,10 @@ void Window::setTitleStyle(const style::WindowTitle &st) {
_helper->setTitleStyle(st); _helper->setTitleStyle(st);
} }
void Window::setNativeFrame(bool enabled) {
_helper->setNativeFrame(enabled);
}
void Window::setMinimumSize(QSize size) { void Window::setMinimumSize(QSize size) {
_helper->setMinimumSize(size); _helper->setMinimumSize(size);
} }

View file

@ -39,6 +39,7 @@ public:
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 setMinimumSize(QSize size); void setMinimumSize(QSize size);
void setFixedSize(QSize size); void setFixedSize(QSize size);
void setStaysOnTop(bool enabled); void setStaysOnTop(bool enabled);