Revert "Make maximized geometry handling less bugged on Windows"
This reverts commit b05b7bd502.
This commit is contained in:
parent
74cd53e1d1
commit
30810032dc
2 changed files with 155 additions and 71 deletions
|
|
@ -20,10 +20,12 @@
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#include <QtWidgets/QStyleFactory>
|
#include <QtWidgets/QStyleFactory>
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <uxtheme.h>
|
#include <uxtheme.h>
|
||||||
#include <windowsx.h>
|
|
||||||
|
Q_DECLARE_METATYPE(QMargins);
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
@ -37,10 +39,6 @@ constexpr auto kDWMWA_TEXT_COLOR = DWORD(36);
|
||||||
|
|
||||||
UINT(__stdcall *GetDpiForWindow)(_In_ HWND hwnd);
|
UINT(__stdcall *GetDpiForWindow)(_In_ HWND hwnd);
|
||||||
|
|
||||||
int(__stdcall *GetSystemMetricsForDpi)(
|
|
||||||
_In_ int nIndex,
|
|
||||||
_In_ UINT dpi);
|
|
||||||
|
|
||||||
[[nodiscard]] bool GetDpiForWindowSupported() {
|
[[nodiscard]] bool GetDpiForWindowSupported() {
|
||||||
static const auto Result = [&] {
|
static const auto Result = [&] {
|
||||||
#define LOAD_SYMBOL(lib, name) base::Platform::LoadMethod(lib, #name, name)
|
#define LOAD_SYMBOL(lib, name) base::Platform::LoadMethod(lib, #name, name)
|
||||||
|
|
@ -51,16 +49,6 @@ int(__stdcall *GetSystemMetricsForDpi)(
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool GetSystemMetricsForDpiSupported() {
|
|
||||||
static const auto Result = [&] {
|
|
||||||
#define LOAD_SYMBOL(lib, name) base::Platform::LoadMethod(lib, #name, name)
|
|
||||||
const auto user32 = base::Platform::SafeLoadLibrary(L"User32.dll");
|
|
||||||
return LOAD_SYMBOL(user32, GetSystemMetricsForDpi);
|
|
||||||
#undef LOAD_SYMBOL
|
|
||||||
}();
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsCompositionEnabled() {
|
[[nodiscard]] bool IsCompositionEnabled() {
|
||||||
auto result = BOOL(FALSE);
|
auto result = BOOL(FALSE);
|
||||||
const auto success = (DwmIsCompositionEnabled(&result) == S_OK);
|
const auto success = (DwmIsCompositionEnabled(&result) == S_OK);
|
||||||
|
|
@ -119,11 +107,29 @@ int(__stdcall *GetSystemMetricsForDpi)(
|
||||||
return bAutoHidden;
|
return bAutoHidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixAeroSnap(HWND handle) {
|
||||||
|
SetWindowLongPtr(
|
||||||
|
handle,
|
||||||
|
GWL_STYLE,
|
||||||
|
GetWindowLongPtr(handle, GWL_STYLE) | WS_CAPTION | WS_THICKFRAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] HWND ResolveWindowHandle(not_null<QWidget*> widget) {
|
||||||
|
if (!::Platform::IsWindows8OrGreater()) {
|
||||||
|
widget->setWindowFlag(Qt::FramelessWindowHint);
|
||||||
|
}
|
||||||
|
const auto result = GetWindowHandle(widget);
|
||||||
|
if (!::Platform::IsWindows8OrGreater()) {
|
||||||
|
FixAeroSnap(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WindowHelper::WindowHelper(not_null<RpWidget*> window)
|
WindowHelper::WindowHelper(not_null<RpWidget*> window)
|
||||||
: BasicWindowHelper(window)
|
: BasicWindowHelper(window)
|
||||||
, _handle(GetWindowHandle(window))
|
, _handle(ResolveWindowHandle(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(std::in_place, window, st::windowShadowFg->c)
|
, _shadow(std::in_place, window, st::windowShadowFg->c)
|
||||||
|
|
@ -175,11 +181,10 @@ void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
||||||
|
|
||||||
void WindowHelper::setNativeFrame(bool enabled) {
|
void WindowHelper::setNativeFrame(bool enabled) {
|
||||||
if (!::Platform::IsWindows8OrGreater()) {
|
if (!::Platform::IsWindows8OrGreater()) {
|
||||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
window()->windowHandle()->setFlag(Qt::FramelessWindowHint, !enabled);
|
||||||
SetWindowLongPtr(
|
if (!enabled) {
|
||||||
_handle,
|
FixAeroSnap(_handle);
|
||||||
GWL_STYLE,
|
}
|
||||||
enabled ? (style | WS_CAPTION) : (style & ~WS_CAPTION));
|
|
||||||
}
|
}
|
||||||
_title->setVisible(!enabled);
|
_title->setVisible(!enabled);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
|
@ -189,7 +194,9 @@ void WindowHelper::setNativeFrame(bool enabled) {
|
||||||
_shadow->setResizeEnabled(!fixedSize());
|
_shadow->setResizeEnabled(!fixedSize());
|
||||||
initialShadowUpdate();
|
initialShadowUpdate();
|
||||||
}
|
}
|
||||||
|
updateMargins();
|
||||||
updateWindowFrameColors();
|
updateWindowFrameColors();
|
||||||
|
fixMaximizedWindow();
|
||||||
SetWindowPos(
|
SetWindowPos(
|
||||||
_handle,
|
_handle,
|
||||||
0,
|
0,
|
||||||
|
|
@ -246,6 +253,7 @@ void WindowHelper::setGeometry(QRect rect) {
|
||||||
void WindowHelper::showFullScreen() {
|
void WindowHelper::showFullScreen() {
|
||||||
if (!_isFullScreen) {
|
if (!_isFullScreen) {
|
||||||
_isFullScreen = true;
|
_isFullScreen = true;
|
||||||
|
updateMargins();
|
||||||
updateCornersRounding();
|
updateCornersRounding();
|
||||||
}
|
}
|
||||||
window()->showFullScreen();
|
window()->showFullScreen();
|
||||||
|
|
@ -255,6 +263,7 @@ void WindowHelper::showNormal() {
|
||||||
window()->showNormal();
|
window()->showNormal();
|
||||||
if (_isFullScreen) {
|
if (_isFullScreen) {
|
||||||
_isFullScreen = false;
|
_isFullScreen = false;
|
||||||
|
updateMargins();
|
||||||
updateCornersRounding();
|
updateCornersRounding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -299,6 +308,8 @@ void WindowHelper::init() {
|
||||||
size.height() - (titleShown ? titleHeight : 0));
|
size.height() - (titleShown ? titleHeight : 0));
|
||||||
}, _body->lifetime());
|
}, _body->lifetime());
|
||||||
|
|
||||||
|
updateMargins();
|
||||||
|
|
||||||
if (!::Platform::IsWindows8OrGreater()) {
|
if (!::Platform::IsWindows8OrGreater()) {
|
||||||
SetWindowTheme(_handle, L" ", L" ");
|
SetWindowTheme(_handle, L" ", L" ");
|
||||||
QApplication::setStyle(QStyleFactory::create("Windows"));
|
QApplication::setStyle(QStyleFactory::create("Windows"));
|
||||||
|
|
@ -372,7 +383,7 @@ bool WindowHelper::handleNativeEvent(
|
||||||
} return true;
|
} return true;
|
||||||
|
|
||||||
case WM_NCCALCSIZE: {
|
case WM_NCCALCSIZE: {
|
||||||
if (_title->isHidden() || window()->isFullScreen() || !wParam) {
|
if (_title->isHidden() || !wParam) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
WINDOWPLACEMENT wp;
|
WINDOWPLACEMENT wp;
|
||||||
|
|
@ -380,26 +391,16 @@ bool WindowHelper::handleNativeEvent(
|
||||||
if (GetWindowPlacement(_handle, &wp)
|
if (GetWindowPlacement(_handle, &wp)
|
||||||
&& (wp.showCmd == SW_SHOWMAXIMIZED)) {
|
&& (wp.showCmd == SW_SHOWMAXIMIZED)) {
|
||||||
const auto r = &((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0];
|
const auto r = &((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0];
|
||||||
const auto dpi = _dpi.current();
|
const auto hMonitor = MonitorFromPoint(
|
||||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
{ (r->left + r->right) / 2, (r->top + r->bottom) / 2 },
|
||||||
const auto borderWidth = ((GetSystemMetricsForDpiSupported() && dpi)
|
|
||||||
? GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
|
||||||
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
|
|
||||||
: GetSystemMetrics(SM_CXSIZEFRAME)
|
|
||||||
+ GetSystemMetrics(SM_CXPADDEDBORDER))
|
|
||||||
- ((style & WS_CAPTION) ? 0 : 1);
|
|
||||||
r->left += borderWidth;
|
|
||||||
r->right -= borderWidth;
|
|
||||||
r->top += borderWidth;
|
|
||||||
r->bottom -= borderWidth;
|
|
||||||
const auto hMonitor = MonitorFromWindow(
|
|
||||||
_handle,
|
|
||||||
MONITOR_DEFAULTTONEAREST);
|
MONITOR_DEFAULTTONEAREST);
|
||||||
|
if (hMonitor) {
|
||||||
MONITORINFO mi;
|
MONITORINFO mi;
|
||||||
mi.cbSize = sizeof(mi);
|
mi.cbSize = sizeof(mi);
|
||||||
|
if (GetMonitorInfo(hMonitor, &mi)) {
|
||||||
|
*r = mi.rcWork;
|
||||||
UINT uEdge = (UINT)-1;
|
UINT uEdge = (UINT)-1;
|
||||||
if (GetMonitorInfo(hMonitor, &mi)
|
if (IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) {
|
||||||
&& IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) {
|
|
||||||
switch (uEdge) {
|
switch (uEdge) {
|
||||||
case ABE_LEFT: r->left += 1; break;
|
case ABE_LEFT: r->left += 1; break;
|
||||||
case ABE_RIGHT: r->right -= 1; break;
|
case ABE_RIGHT: r->right -= 1; break;
|
||||||
|
|
@ -407,11 +408,14 @@ bool WindowHelper::handleNativeEvent(
|
||||||
case ABE_BOTTOM: r->bottom -= 1; break;
|
case ABE_BOTTOM: r->bottom -= 1; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result) *result = 0;
|
if (result) *result = 0;
|
||||||
} else {
|
} else {
|
||||||
if (result) *result = WVR_REDRAW;
|
if (result) *result = WVR_REDRAW;
|
||||||
}
|
}
|
||||||
} return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_NCRBUTTONUP: {
|
case WM_NCRBUTTONUP: {
|
||||||
if (_title->isHidden()) {
|
if (_title->isHidden()) {
|
||||||
|
|
@ -473,6 +477,7 @@ bool WindowHelper::handleNativeEvent(
|
||||||
}
|
}
|
||||||
window()->windowHandle()->windowStateChanged(state);
|
window()->windowHandle()->windowStateChanged(state);
|
||||||
}
|
}
|
||||||
|
updateMargins();
|
||||||
if (_shadow) {
|
if (_shadow) {
|
||||||
_title->refreshAdditionalPaddings(_handle);
|
_title->refreshAdditionalPaddings(_handle);
|
||||||
const auto changes = (wParam == SIZE_MINIMIZED
|
const auto changes = (wParam == SIZE_MINIMIZED
|
||||||
|
|
@ -486,27 +491,6 @@ bool WindowHelper::handleNativeEvent(
|
||||||
} return false;
|
} return false;
|
||||||
|
|
||||||
case WM_SHOWWINDOW: {
|
case WM_SHOWWINDOW: {
|
||||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
|
||||||
if (!::Platform::IsWindows8OrGreater()
|
|
||||||
&& !_title->isHidden()
|
|
||||||
&& (style & WS_CAPTION)) {
|
|
||||||
SetWindowLongPtr(
|
|
||||||
_handle,
|
|
||||||
GWL_STYLE,
|
|
||||||
style & ~WS_CAPTION);
|
|
||||||
SetWindowPos(
|
|
||||||
_handle,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
SWP_FRAMECHANGED
|
|
||||||
| SWP_NOMOVE
|
|
||||||
| SWP_NOSIZE
|
|
||||||
| SWP_NOZORDER
|
|
||||||
| SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
if (_shadow) {
|
if (_shadow) {
|
||||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
||||||
const auto changes = WindowShadow::Change::Resized
|
const auto changes = WindowShadow::Change::Resized
|
||||||
|
|
@ -529,9 +513,12 @@ bool WindowHelper::handleNativeEvent(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
const auto p = MAKEPOINTS(lParam);
|
||||||
ScreenToClient(_handle, &p);
|
auto r = RECT();
|
||||||
const auto mapped = QPoint(p.x, p.y) / window()->devicePixelRatioF();
|
GetWindowRect(_handle, &r);
|
||||||
|
const auto mapped = QPoint(
|
||||||
|
p.x - r.left + _marginsDelta.left(),
|
||||||
|
p.y - r.top + _marginsDelta.top());
|
||||||
*result = [&] {
|
*result = [&] {
|
||||||
if (!window()->rect().contains(mapped)) {
|
if (!window()->rect().contains(mapped)) {
|
||||||
return HTTRANSPARENT;
|
return HTTRANSPARENT;
|
||||||
|
|
@ -691,6 +678,99 @@ void WindowHelper::updateWindowFrameColors(bool active) {
|
||||||
sizeof(COLORREF));
|
sizeof(COLORREF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowHelper::updateMargins() {
|
||||||
|
if (_updatingMargins) return;
|
||||||
|
|
||||||
|
_updatingMargins = true;
|
||||||
|
const auto guard = gsl::finally([&] { _updatingMargins = false; });
|
||||||
|
|
||||||
|
RECT r, a;
|
||||||
|
|
||||||
|
GetClientRect(_handle, &r);
|
||||||
|
a = r;
|
||||||
|
|
||||||
|
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
||||||
|
const auto styleEx = GetWindowLongPtr(_handle, GWL_EXSTYLE);
|
||||||
|
AdjustWindowRectEx(&a, style, false, styleEx);
|
||||||
|
auto margins = QMargins(
|
||||||
|
a.left - r.left,
|
||||||
|
a.top - r.top,
|
||||||
|
r.right - a.right,
|
||||||
|
r.bottom - a.bottom);
|
||||||
|
if (style & WS_MAXIMIZE) {
|
||||||
|
RECT w, m;
|
||||||
|
GetWindowRect(_handle , &w);
|
||||||
|
m = w;
|
||||||
|
|
||||||
|
HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST);
|
||||||
|
if (hMonitor) {
|
||||||
|
MONITORINFO mi;
|
||||||
|
mi.cbSize = sizeof(mi);
|
||||||
|
GetMonitorInfo(hMonitor, &mi);
|
||||||
|
m = mi.rcWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
_marginsDelta = QMargins(
|
||||||
|
w.left - m.left,
|
||||||
|
w.top - m.top,
|
||||||
|
m.right - w.right,
|
||||||
|
m.bottom - w.bottom);
|
||||||
|
|
||||||
|
margins.setLeft(margins.left() - _marginsDelta.left());
|
||||||
|
margins.setRight(margins.right() - _marginsDelta.right());
|
||||||
|
margins.setBottom(margins.bottom() - _marginsDelta.bottom());
|
||||||
|
margins.setTop(margins.top() - _marginsDelta.top());
|
||||||
|
} else if (!_marginsDelta.isNull()) {
|
||||||
|
RECT w;
|
||||||
|
GetWindowRect(_handle, &w);
|
||||||
|
SetWindowPos(
|
||||||
|
_handle,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
w.right - w.left - _marginsDelta.left() - _marginsDelta.right(),
|
||||||
|
w.bottom - w.top - _marginsDelta.top() - _marginsDelta.bottom(),
|
||||||
|
(SWP_NOMOVE
|
||||||
|
| SWP_NOSENDCHANGING
|
||||||
|
| SWP_NOZORDER
|
||||||
|
| SWP_NOACTIVATE
|
||||||
|
| SWP_NOREPOSITION));
|
||||||
|
_marginsDelta = QMargins();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isFullScreen || _title->isHidden()) {
|
||||||
|
margins = QMargins();
|
||||||
|
if (_title->isHidden()) {
|
||||||
|
_marginsDelta = QMargins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
||||||
|
native->setWindowProperty(
|
||||||
|
window()->windowHandle()->handle(),
|
||||||
|
"WindowsCustomMargins",
|
||||||
|
QVariant::fromValue<QMargins>(margins));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HWND GetWindowHandle(not_null<QWidget*> widget) {
|
HWND GetWindowHandle(not_null<QWidget*> widget) {
|
||||||
const auto toplevel = widget->window();
|
const auto toplevel = widget->window();
|
||||||
toplevel->createWinId();
|
toplevel->createWinId();
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
void updateMargins();
|
||||||
void updateWindowFrameColors();
|
void updateWindowFrameColors();
|
||||||
void updateWindowFrameColors(bool active);
|
void updateWindowFrameColors(bool active);
|
||||||
void initialShadowUpdate();
|
void initialShadowUpdate();
|
||||||
void updateCornersRounding();
|
void updateCornersRounding();
|
||||||
|
void fixMaximizedWindow();
|
||||||
[[nodiscard]] bool handleNativeEvent(
|
[[nodiscard]] bool handleNativeEvent(
|
||||||
UINT msg,
|
UINT msg,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
|
|
@ -79,6 +81,8 @@ private:
|
||||||
rpl::event_stream<HitTestResult> _systemButtonDown;
|
rpl::event_stream<HitTestResult> _systemButtonDown;
|
||||||
std::optional<WindowShadow> _shadow;
|
std::optional<WindowShadow> _shadow;
|
||||||
rpl::variable<uint> _dpi;
|
rpl::variable<uint> _dpi;
|
||||||
|
QMargins _marginsDelta;
|
||||||
|
bool _updatingMargins = false;
|
||||||
bool _isFullScreen = false;
|
bool _isFullScreen = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue