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 <QtWidgets/QStyleFactory>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <uxtheme.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
Q_DECLARE_METATYPE(QMargins);
|
||||
|
||||
namespace Ui {
|
||||
namespace Platform {
|
||||
|
|
@ -37,10 +39,6 @@ constexpr auto kDWMWA_TEXT_COLOR = DWORD(36);
|
|||
|
||||
UINT(__stdcall *GetDpiForWindow)(_In_ HWND hwnd);
|
||||
|
||||
int(__stdcall *GetSystemMetricsForDpi)(
|
||||
_In_ int nIndex,
|
||||
_In_ UINT dpi);
|
||||
|
||||
[[nodiscard]] bool GetDpiForWindowSupported() {
|
||||
static const auto Result = [&] {
|
||||
#define LOAD_SYMBOL(lib, name) base::Platform::LoadMethod(lib, #name, name)
|
||||
|
|
@ -51,16 +49,6 @@ int(__stdcall *GetSystemMetricsForDpi)(
|
|||
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() {
|
||||
auto result = BOOL(FALSE);
|
||||
const auto success = (DwmIsCompositionEnabled(&result) == S_OK);
|
||||
|
|
@ -119,11 +107,29 @@ int(__stdcall *GetSystemMetricsForDpi)(
|
|||
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
|
||||
|
||||
WindowHelper::WindowHelper(not_null<RpWidget*> window)
|
||||
: BasicWindowHelper(window)
|
||||
, _handle(GetWindowHandle(window))
|
||||
, _handle(ResolveWindowHandle(window))
|
||||
, _title(Ui::CreateChild<TitleWidget>(window.get()))
|
||||
, _body(Ui::CreateChild<RpWidget>(window.get()))
|
||||
, _shadow(std::in_place, window, st::windowShadowFg->c)
|
||||
|
|
@ -175,11 +181,10 @@ void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
|||
|
||||
void WindowHelper::setNativeFrame(bool enabled) {
|
||||
if (!::Platform::IsWindows8OrGreater()) {
|
||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
||||
SetWindowLongPtr(
|
||||
_handle,
|
||||
GWL_STYLE,
|
||||
enabled ? (style | WS_CAPTION) : (style & ~WS_CAPTION));
|
||||
window()->windowHandle()->setFlag(Qt::FramelessWindowHint, !enabled);
|
||||
if (!enabled) {
|
||||
FixAeroSnap(_handle);
|
||||
}
|
||||
}
|
||||
_title->setVisible(!enabled);
|
||||
if (enabled) {
|
||||
|
|
@ -189,7 +194,9 @@ void WindowHelper::setNativeFrame(bool enabled) {
|
|||
_shadow->setResizeEnabled(!fixedSize());
|
||||
initialShadowUpdate();
|
||||
}
|
||||
updateMargins();
|
||||
updateWindowFrameColors();
|
||||
fixMaximizedWindow();
|
||||
SetWindowPos(
|
||||
_handle,
|
||||
0,
|
||||
|
|
@ -246,6 +253,7 @@ void WindowHelper::setGeometry(QRect rect) {
|
|||
void WindowHelper::showFullScreen() {
|
||||
if (!_isFullScreen) {
|
||||
_isFullScreen = true;
|
||||
updateMargins();
|
||||
updateCornersRounding();
|
||||
}
|
||||
window()->showFullScreen();
|
||||
|
|
@ -255,6 +263,7 @@ void WindowHelper::showNormal() {
|
|||
window()->showNormal();
|
||||
if (_isFullScreen) {
|
||||
_isFullScreen = false;
|
||||
updateMargins();
|
||||
updateCornersRounding();
|
||||
}
|
||||
}
|
||||
|
|
@ -299,6 +308,8 @@ void WindowHelper::init() {
|
|||
size.height() - (titleShown ? titleHeight : 0));
|
||||
}, _body->lifetime());
|
||||
|
||||
updateMargins();
|
||||
|
||||
if (!::Platform::IsWindows8OrGreater()) {
|
||||
SetWindowTheme(_handle, L" ", L" ");
|
||||
QApplication::setStyle(QStyleFactory::create("Windows"));
|
||||
|
|
@ -372,7 +383,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
} return true;
|
||||
|
||||
case WM_NCCALCSIZE: {
|
||||
if (_title->isHidden() || window()->isFullScreen() || !wParam) {
|
||||
if (_title->isHidden() || !wParam) {
|
||||
return false;
|
||||
}
|
||||
WINDOWPLACEMENT wp;
|
||||
|
|
@ -380,38 +391,31 @@ bool WindowHelper::handleNativeEvent(
|
|||
if (GetWindowPlacement(_handle, &wp)
|
||||
&& (wp.showCmd == SW_SHOWMAXIMIZED)) {
|
||||
const auto r = &((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0];
|
||||
const auto dpi = _dpi.current();
|
||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
||||
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,
|
||||
const auto hMonitor = MonitorFromPoint(
|
||||
{ (r->left + r->right) / 2, (r->top + r->bottom) / 2 },
|
||||
MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
UINT uEdge = (UINT)-1;
|
||||
if (GetMonitorInfo(hMonitor, &mi)
|
||||
&& IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) {
|
||||
switch (uEdge) {
|
||||
case ABE_LEFT: r->left += 1; break;
|
||||
case ABE_RIGHT: r->right -= 1; break;
|
||||
case ABE_TOP: r->top += 1; break;
|
||||
case ABE_BOTTOM: r->bottom -= 1; break;
|
||||
if (hMonitor) {
|
||||
MONITORINFO mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfo(hMonitor, &mi)) {
|
||||
*r = mi.rcWork;
|
||||
UINT uEdge = (UINT)-1;
|
||||
if (IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) {
|
||||
switch (uEdge) {
|
||||
case ABE_LEFT: r->left += 1; break;
|
||||
case ABE_RIGHT: r->right -= 1; break;
|
||||
case ABE_TOP: r->top += 1; break;
|
||||
case ABE_BOTTOM: r->bottom -= 1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result) *result = 0;
|
||||
} else {
|
||||
if (result) *result = WVR_REDRAW;
|
||||
}
|
||||
} return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
case WM_NCRBUTTONUP: {
|
||||
if (_title->isHidden()) {
|
||||
|
|
@ -473,6 +477,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
}
|
||||
window()->windowHandle()->windowStateChanged(state);
|
||||
}
|
||||
updateMargins();
|
||||
if (_shadow) {
|
||||
_title->refreshAdditionalPaddings(_handle);
|
||||
const auto changes = (wParam == SIZE_MINIMIZED
|
||||
|
|
@ -486,27 +491,6 @@ bool WindowHelper::handleNativeEvent(
|
|||
} return false;
|
||||
|
||||
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) {
|
||||
const auto style = GetWindowLongPtr(_handle, GWL_STYLE);
|
||||
const auto changes = WindowShadow::Change::Resized
|
||||
|
|
@ -529,9 +513,12 @@ bool WindowHelper::handleNativeEvent(
|
|||
return false;
|
||||
}
|
||||
|
||||
POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
||||
ScreenToClient(_handle, &p);
|
||||
const auto mapped = QPoint(p.x, p.y) / window()->devicePixelRatioF();
|
||||
const auto p = MAKEPOINTS(lParam);
|
||||
auto r = RECT();
|
||||
GetWindowRect(_handle, &r);
|
||||
const auto mapped = QPoint(
|
||||
p.x - r.left + _marginsDelta.left(),
|
||||
p.y - r.top + _marginsDelta.top());
|
||||
*result = [&] {
|
||||
if (!window()->rect().contains(mapped)) {
|
||||
return HTTRANSPARENT;
|
||||
|
|
@ -691,6 +678,99 @@ void WindowHelper::updateWindowFrameColors(bool active) {
|
|||
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) {
|
||||
const auto toplevel = widget->window();
|
||||
toplevel->createWinId();
|
||||
|
|
|
|||
|
|
@ -51,10 +51,12 @@ public:
|
|||
|
||||
private:
|
||||
void init();
|
||||
void updateMargins();
|
||||
void updateWindowFrameColors();
|
||||
void updateWindowFrameColors(bool active);
|
||||
void initialShadowUpdate();
|
||||
void updateCornersRounding();
|
||||
void fixMaximizedWindow();
|
||||
[[nodiscard]] bool handleNativeEvent(
|
||||
UINT msg,
|
||||
WPARAM wParam,
|
||||
|
|
@ -79,6 +81,8 @@ private:
|
|||
rpl::event_stream<HitTestResult> _systemButtonDown;
|
||||
std::optional<WindowShadow> _shadow;
|
||||
rpl::variable<uint> _dpi;
|
||||
QMargins _marginsDelta;
|
||||
bool _updatingMargins = false;
|
||||
bool _isFullScreen = false;
|
||||
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue