forked from github_mirror/framelesshelper
Win32: Fix window content will be cut-off for some pixels when window is fullscreened
1. Fix that bug 2. Some adjustments of the variable names to make them more clear 3. Some tweaks to the title bar height value TODO: Add a button to switch between fullscreen and windowed mode for the widget example TODO: Add a title text to the widget example Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
2c106ffef9
commit
bc8a70dbb2
|
@ -1,3 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
|
@ -21,7 +23,6 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import QtQuick.Window 2.0
|
import QtQuick.Window 2.0
|
||||||
import QtQuick.Controls 2.0
|
import QtQuick.Controls 2.0
|
||||||
|
@ -35,7 +36,10 @@ Window {
|
||||||
title: qsTr("Hello, World!")
|
title: qsTr("Hello, World!")
|
||||||
color: "#f0f0f0"
|
color: "#f0f0f0"
|
||||||
|
|
||||||
property real _flh_margin: ((window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen)) ? 0.0 : (1.0 / Screen.devicePixelRatio)
|
property real _flh_margin: ((window.visibility === Window.Maximized)
|
||||||
|
|| (window.visibility
|
||||||
|
=== Window.FullScreen)) ? 0.0 : (1.0 / Screen.devicePixelRatio)
|
||||||
|
property var _win_prev_state: null
|
||||||
|
|
||||||
FramelessHelper {
|
FramelessHelper {
|
||||||
id: framelessHelper
|
id: framelessHelper
|
||||||
|
@ -51,7 +55,7 @@ Window {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: titleBar
|
id: titleBar
|
||||||
height: framelessHelper.titleBarHeight + framelessHelper.resizeBorderHeight
|
height: framelessHelper.titleBarHeight
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
|
@ -79,12 +83,14 @@ Window {
|
||||||
MinimizeButton {
|
MinimizeButton {
|
||||||
id: minimizeButton
|
id: minimizeButton
|
||||||
onClicked: window.showMinimized()
|
onClicked: window.showMinimized()
|
||||||
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(minimizeButton, true)
|
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
|
||||||
|
minimizeButton, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
MaximizeButton {
|
MaximizeButton {
|
||||||
id: maximizeButton
|
id: maximizeButton
|
||||||
maximized: ((window.visibility === Window.Maximized) || (window.visibility === Window.FullScreen))
|
maximized: ((window.visibility === Window.Maximized)
|
||||||
|
|| (window.visibility === Window.FullScreen))
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (maximized) {
|
if (maximized) {
|
||||||
window.showNormal()
|
window.showNormal()
|
||||||
|
@ -92,13 +98,15 @@ Window {
|
||||||
window.showMaximized()
|
window.showMaximized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(maximizeButton, true)
|
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
|
||||||
|
maximizeButton, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseButton {
|
CloseButton {
|
||||||
id: closeButton
|
id: closeButton
|
||||||
onClicked: window.close()
|
onClicked: window.close()
|
||||||
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(closeButton, true)
|
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
|
||||||
|
closeButton, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +120,28 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
top: label.bottom
|
||||||
|
topMargin: 15
|
||||||
|
}
|
||||||
|
property bool _full: window.visibility === Window.FullScreen
|
||||||
|
text: _full ? qsTr("Exit FullScreen") : qsTr("Enter FullScreen")
|
||||||
|
onClicked: {
|
||||||
|
if (_full) {
|
||||||
|
if (_win_prev_state == Window.Maximized) {
|
||||||
|
window.showMaximized()
|
||||||
|
} else if (_win_prev_state == Window.Windowed) {
|
||||||
|
window.showNormal()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_win_prev_state = window.visibility
|
||||||
|
window.showFullScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: windowFrame
|
id: windowFrame
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
|
@ -116,10 +116,8 @@ void Widget::setupUi()
|
||||||
setWindowTitle(tr("Hello, World!"));
|
setWindowTitle(tr("Hello, World!"));
|
||||||
resize(800, 600);
|
resize(800, 600);
|
||||||
const QWindow *win = windowHandle();
|
const QWindow *win = windowHandle();
|
||||||
const int resizeBorderThickness = Utilities::getSystemMetric(win, SystemMetric::ResizeBorderThickness, false);
|
|
||||||
const int titleBarHeight = Utilities::getSystemMetric(win, SystemMetric::TitleBarHeight, false);
|
const int titleBarHeight = Utilities::getSystemMetric(win, SystemMetric::TitleBarHeight, false);
|
||||||
const int systemButtonHeight = titleBarHeight + resizeBorderThickness;
|
const QSize systemButtonSize = {qRound(static_cast<qreal>(titleBarHeight) * 1.5), titleBarHeight};
|
||||||
const QSize systemButtonSize = {qRound(static_cast<qreal>(systemButtonHeight) * 1.5), systemButtonHeight};
|
|
||||||
m_minimizeButton = new QPushButton(this);
|
m_minimizeButton = new QPushButton(this);
|
||||||
m_minimizeButton->setObjectName(QStringLiteral("MinimizeButton"));
|
m_minimizeButton->setObjectName(QStringLiteral("MinimizeButton"));
|
||||||
m_minimizeButton->setFixedSize(systemButtonSize);
|
m_minimizeButton->setFixedSize(systemButtonSize);
|
||||||
|
|
|
@ -71,7 +71,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
|
||||||
}
|
}
|
||||||
const QEvent::Type type = event->type();
|
const QEvent::Type type = event->type();
|
||||||
// We are only interested in mouse events.
|
// We are only interested in mouse events.
|
||||||
if ((type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseButtonPress) && (type != QEvent::MouseMove)) {
|
if ((type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseButtonPress)
|
||||||
|
&& (type != QEvent::MouseMove)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto window = qobject_cast<QWindow *>(object);
|
const auto window = qobject_cast<QWindow *>(object);
|
||||||
|
@ -125,7 +126,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
|
||||||
}
|
}
|
||||||
if (window->windowState() == Qt::WindowNoState) {
|
if (window->windowState() == Qt::WindowNoState) {
|
||||||
isInTitlebarArea = (localMousePosition.y() > resizeBorderThickness)
|
isInTitlebarArea = (localMousePosition.y() > resizeBorderThickness)
|
||||||
&& (localMousePosition.y() <= (titleBarHeight + resizeBorderThickness))
|
&& (localMousePosition.y() <= titleBarHeight)
|
||||||
&& (localMousePosition.x() > resizeBorderThickness)
|
&& (localMousePosition.x() > resizeBorderThickness)
|
||||||
&& (localMousePosition.x() < (windowWidth - resizeBorderThickness))
|
&& (localMousePosition.x() < (windowWidth - resizeBorderThickness))
|
||||||
&& !hitTestVisible;
|
&& !hitTestVisible;
|
||||||
|
|
|
@ -90,6 +90,7 @@ namespace Constants
|
||||||
|
|
||||||
[[maybe_unused]] constexpr char kFramelessModeFlag[] = "_FRAMELESSHELPER_FRAMELESS_MODE";
|
[[maybe_unused]] constexpr char kFramelessModeFlag[] = "_FRAMELESSHELPER_FRAMELESS_MODE";
|
||||||
[[maybe_unused]] constexpr char kResizeBorderThicknessFlag[] = "_FRAMELESSHELPER_RESIZE_BORDER_THICKNESS";
|
[[maybe_unused]] constexpr char kResizeBorderThicknessFlag[] = "_FRAMELESSHELPER_RESIZE_BORDER_THICKNESS";
|
||||||
|
[[maybe_unused]] constexpr char kCaptionHeightFlag[] = "_FRAMELESSHELPER_CAPTION_HEIGHT";
|
||||||
[[maybe_unused]] constexpr char kTitleBarHeightFlag[] = "_FRAMELESSHELPER_TITLE_BAR_HEIGHT";
|
[[maybe_unused]] constexpr char kTitleBarHeightFlag[] = "_FRAMELESSHELPER_TITLE_BAR_HEIGHT";
|
||||||
[[maybe_unused]] constexpr char kHitTestVisibleInChromeFlag[] = "_FRAMELESSHELPER_HIT_TEST_VISIBLE_IN_CHROME";
|
[[maybe_unused]] constexpr char kHitTestVisibleInChromeFlag[] = "_FRAMELESSHELPER_HIT_TEST_VISIBLE_IN_CHROME";
|
||||||
[[maybe_unused]] constexpr char kUseNativeTitleBarFlag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR";
|
[[maybe_unused]] constexpr char kUseNativeTitleBarFlag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR";
|
||||||
|
|
|
@ -589,21 +589,21 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
qWarning() << "Failed to retrieve the client rect of the current window.";
|
qWarning() << "Failed to retrieve the client rect of the current window.";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const LONG ww = clientRect.right;
|
const LONG windowWidth = clientRect.right;
|
||||||
const int rbt = Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, true);
|
const int resizeBorderThickness = Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, true);
|
||||||
const int tbh = Utilities::getSystemMetric(window, SystemMetric::TitleBarHeight, true);
|
const int titleBarHeight = Utilities::getSystemMetric(window, SystemMetric::TitleBarHeight, true);
|
||||||
bool isTitleBar = false;
|
bool isTitleBar = false;
|
||||||
if (IsMaximized(msg->hwnd) || (window->windowState() == Qt::WindowFullScreen)) {
|
if (IsMaximized(msg->hwnd) || (window->windowState() == Qt::WindowFullScreen)) {
|
||||||
isTitleBar = (localMouse.y() >= 0) && (localMouse.y() <= tbh)
|
isTitleBar = (localMouse.y() >= 0) && (localMouse.y() <= titleBarHeight)
|
||||||
&& (localMouse.x() >= 0) && (localMouse.x() <= ww)
|
&& (localMouse.x() >= 0) && (localMouse.x() <= windowWidth)
|
||||||
&& !Utilities::isHitTestVisibleInChrome(window);
|
&& !Utilities::isHitTestVisibleInChrome(window);
|
||||||
}
|
}
|
||||||
if (window->windowState() == Qt::WindowNoState) {
|
if (window->windowState() == Qt::WindowNoState) {
|
||||||
isTitleBar = (localMouse.y() > rbt) && (localMouse.y() <= (rbt + tbh))
|
isTitleBar = (localMouse.y() > resizeBorderThickness) && (localMouse.y() <= titleBarHeight)
|
||||||
&& (localMouse.x() > rbt) && (localMouse.x() < (ww - rbt))
|
&& (localMouse.x() > resizeBorderThickness) && (localMouse.x() < (windowWidth - resizeBorderThickness))
|
||||||
&& !Utilities::isHitTestVisibleInChrome(window);
|
&& !Utilities::isHitTestVisibleInChrome(window);
|
||||||
}
|
}
|
||||||
const bool isTop = localMouse.y() <= rbt;
|
const bool isTop = localMouse.y() <= resizeBorderThickness;
|
||||||
if (shouldHaveWindowFrame()) {
|
if (shouldHaveWindowFrame()) {
|
||||||
// This will handle the left, right and bottom parts of the frame
|
// This will handle the left, right and bottom parts of the frame
|
||||||
// because we didn't change them.
|
// because we didn't change them.
|
||||||
|
@ -628,19 +628,19 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
*result = HTCLIENT;
|
*result = HTCLIENT;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
const LRESULT hitTestResult = [clientRect, msg, isTitleBar, &localMouse, rbt, ww, isTop, window]{
|
const LRESULT hitTestResult = [clientRect, msg, isTitleBar, &localMouse, resizeBorderThickness, windowWidth, isTop, window]{
|
||||||
if (IsMaximized(msg->hwnd)) {
|
if (IsMaximized(msg->hwnd)) {
|
||||||
if (isTitleBar) {
|
if (isTitleBar) {
|
||||||
return HTCAPTION;
|
return HTCAPTION;
|
||||||
}
|
}
|
||||||
return HTCLIENT;
|
return HTCLIENT;
|
||||||
}
|
}
|
||||||
const LONG wh = clientRect.bottom;
|
const LONG windowHeight = clientRect.bottom;
|
||||||
const bool isBottom = (localMouse.y() >= (wh - rbt));
|
const bool isBottom = (localMouse.y() >= (windowHeight - resizeBorderThickness));
|
||||||
// Make the border a little wider to let the user easy to resize on corners.
|
// Make the border a little wider to let the user easy to resize on corners.
|
||||||
const qreal factor = (isTop || isBottom) ? 2.0 : 1.0;
|
const qreal factor = (isTop || isBottom) ? 2.0 : 1.0;
|
||||||
const bool isLeft = (localMouse.x() <= qRound(static_cast<qreal>(rbt) * factor));
|
const bool isLeft = (localMouse.x() <= qRound(static_cast<qreal>(resizeBorderThickness) * factor));
|
||||||
const bool isRight = (localMouse.x() >= (ww - qRound(static_cast<qreal>(rbt) * factor)));
|
const bool isRight = (localMouse.x() >= (windowWidth - qRound(static_cast<qreal>(resizeBorderThickness) * factor)));
|
||||||
const bool fixedSize = Utilities::isWindowFixedSize(window);
|
const bool fixedSize = Utilities::isWindowFixedSize(window);
|
||||||
const auto getBorderValue = [fixedSize](int value) -> int {
|
const auto getBorderValue = [fixedSize](int value) -> int {
|
||||||
return fixedSize ? HTCLIENT : value;
|
return fixedSize ? HTCLIENT : value;
|
||||||
|
@ -689,15 +689,32 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
const auto oldStyle = GetWindowLongPtrW(msg->hwnd, GWL_STYLE);
|
const auto oldStyle = GetWindowLongPtrW(msg->hwnd, GWL_STYLE);
|
||||||
// Prevent Windows from drawing the default title bar by temporarily
|
// Prevent Windows from drawing the default title bar by temporarily
|
||||||
// toggling the WS_VISIBLE style.
|
// toggling the WS_VISIBLE style.
|
||||||
SetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle & ~WS_VISIBLE);
|
if (SetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle & ~WS_VISIBLE) == 0) {
|
||||||
|
qWarning() << "SetWindowLongPtrW() failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
const auto winId = reinterpret_cast<WId>(msg->hwnd);
|
const auto winId = reinterpret_cast<WId>(msg->hwnd);
|
||||||
Utilities::triggerFrameChange(winId);
|
Utilities::triggerFrameChange(winId);
|
||||||
const LRESULT ret = DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
const LRESULT ret = DefWindowProcW(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
||||||
SetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle);
|
if (SetWindowLongPtrW(msg->hwnd, GWL_STYLE, oldStyle) == 0) {
|
||||||
|
qWarning() << "SetWindowLongPtrW() failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
Utilities::triggerFrameChange(winId);
|
Utilities::triggerFrameChange(winId);
|
||||||
*result = ret;
|
*result = ret;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
case WM_SIZE: {
|
||||||
|
const bool normal = (msg->wParam == SIZE_RESTORED);
|
||||||
|
const bool max = (msg->wParam == SIZE_MAXIMIZED);
|
||||||
|
const bool full = (window->windowState() == Qt::WindowFullScreen);
|
||||||
|
if (normal || max || full) {
|
||||||
|
Utilities::updateFrameMargins(reinterpret_cast<WId>(msg->hwnd), (max || full));
|
||||||
|
Utilities::updateQtFrameMargins(const_cast<QWindow *>(window), true);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,15 @@ void FramelessWindowsManager::addWindow(QWindow *window)
|
||||||
framelessHelperUnix()->removeWindowFrame(window);
|
framelessHelperUnix()->removeWindowFrame(window);
|
||||||
#else
|
#else
|
||||||
FramelessHelperWin::addFramelessWindow(window);
|
FramelessHelperWin::addFramelessWindow(window);
|
||||||
|
QObject::connect(window, &QWindow::windowStateChanged, [window](Qt::WindowState state){
|
||||||
|
const bool normal = (state == Qt::WindowNoState);
|
||||||
|
const bool max = (state == Qt::WindowMaximized);
|
||||||
|
const bool full = (state == Qt::WindowFullScreen);
|
||||||
|
if (normal || max || full) {
|
||||||
|
Utilities::updateFrameMargins(window->winId(), (max || full));
|
||||||
|
Utilities::updateQtFrameMargins(window, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
// Work-around a Win32 multi-monitor bug.
|
// Work-around a Win32 multi-monitor bug.
|
||||||
QObject::connect(window, &QWindow::screenChanged, [window](QScreen *screen){
|
QObject::connect(window, &QWindow::screenChanged, [window](QScreen *screen){
|
||||||
Q_UNUSED(screen);
|
Q_UNUSED(screen);
|
||||||
|
|
|
@ -32,6 +32,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
enum class SystemMetric : int
|
enum class SystemMetric : int
|
||||||
{
|
{
|
||||||
ResizeBorderThickness = 0,
|
ResizeBorderThickness = 0,
|
||||||
|
CaptionHeight,
|
||||||
TitleBarHeight
|
TitleBarHeight
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,11 +50,10 @@ Q_DECLARE_METATYPE(QMargins)
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
static constexpr char kDwmRegistryKey[] = R"(Software\Microsoft\Windows\DWM)";
|
static constexpr char kDwmRegistryKey[] = R"(Software\Microsoft\Windows\DWM)";
|
||||||
static constexpr char kDwmCompositionRegistryKey[] = "Composition";
|
|
||||||
|
|
||||||
static constexpr int kDefaultResizeBorderThickness = 8;
|
|
||||||
static constexpr int kDefaultResizeBorderThicknessClassic = 4;
|
static constexpr int kDefaultResizeBorderThicknessClassic = 4;
|
||||||
static constexpr int kDefaultTitleBarHeight = 23;
|
static constexpr int kDefaultResizeBorderThicknessAero = 8;
|
||||||
|
static constexpr int kDefaultCaptionHeight = 23;
|
||||||
|
|
||||||
bool Utilities::isDwmCompositionAvailable()
|
bool Utilities::isDwmCompositionAvailable()
|
||||||
{
|
{
|
||||||
|
@ -68,7 +67,7 @@ bool Utilities::isDwmCompositionAvailable()
|
||||||
}
|
}
|
||||||
const QSettings registry(QString::fromUtf8(kDwmRegistryKey), QSettings::NativeFormat);
|
const QSettings registry(QString::fromUtf8(kDwmRegistryKey), QSettings::NativeFormat);
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const int value = registry.value(QString::fromUtf8(kDwmCompositionRegistryKey), 0).toInt(&ok);
|
const int value = registry.value(QStringLiteral("Composition"), 0).toInt(&ok);
|
||||||
return (ok && (value != 0));
|
return (ok && (value != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,51 +77,67 @@ int Utilities::getSystemMetric(const QWindow *window, const SystemMetric metric,
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
const qreal devicePixelRatio = window->devicePixelRatio();
|
||||||
|
const qreal scaleFactor = (dpiScale ? devicePixelRatio : 1.0);
|
||||||
switch (metric) {
|
switch (metric) {
|
||||||
case SystemMetric::ResizeBorderThickness: {
|
case SystemMetric::ResizeBorderThickness: {
|
||||||
const int rbt = window->property(Constants::kResizeBorderThicknessFlag).toInt();
|
const int resizeBorderThickness = window->property(Constants::kResizeBorderThicknessFlag).toInt();
|
||||||
if ((rbt > 0) && !forceSystemValue) {
|
if ((resizeBorderThickness > 0) && !forceSystemValue) {
|
||||||
return qRound(static_cast<qreal>(rbt) * (dpiScale ? window->devicePixelRatio() : 1.0));
|
return qRound(static_cast<qreal>(resizeBorderThickness) * scaleFactor);
|
||||||
} else {
|
} else {
|
||||||
const int result = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
const int result = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
if (dpiScale) {
|
if (dpiScale) {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return qRound(static_cast<qreal>(result) / window->devicePixelRatio());
|
return qRound(static_cast<qreal>(result) / devicePixelRatio);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The padded border will disappear if DWM composition is disabled.
|
// The padded border will disappear if DWM composition is disabled.
|
||||||
const int defaultRBT = (isDwmCompositionAvailable() ? kDefaultResizeBorderThickness : kDefaultResizeBorderThicknessClassic);
|
const int defaultResizeBorderThickness = (isDwmCompositionAvailable() ? kDefaultResizeBorderThicknessAero : kDefaultResizeBorderThicknessClassic);
|
||||||
if (dpiScale) {
|
if (dpiScale) {
|
||||||
return qRound(static_cast<qreal>(defaultRBT) * window->devicePixelRatio());
|
return qRound(static_cast<qreal>(defaultResizeBorderThickness) * devicePixelRatio);
|
||||||
} else {
|
} else {
|
||||||
return defaultRBT;
|
return defaultResizeBorderThickness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SystemMetric::TitleBarHeight: {
|
case SystemMetric::CaptionHeight: {
|
||||||
const int tbh = window->property(Constants::kTitleBarHeightFlag).toInt();
|
const int captionHeight = window->property(Constants::kCaptionHeightFlag).toInt();
|
||||||
if ((tbh > 0) && !forceSystemValue) {
|
if ((captionHeight > 0) && !forceSystemValue) {
|
||||||
return qRound(static_cast<qreal>(tbh) * (dpiScale ? window->devicePixelRatio() : 1.0));
|
return qRound(static_cast<qreal>(captionHeight) * scaleFactor);
|
||||||
} else {
|
} else {
|
||||||
const int result = GetSystemMetrics(SM_CYCAPTION);
|
const int result = GetSystemMetrics(SM_CYCAPTION);
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
if (dpiScale) {
|
if (dpiScale) {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return qRound(static_cast<qreal>(result) / window->devicePixelRatio());
|
return qRound(static_cast<qreal>(result) / devicePixelRatio);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dpiScale) {
|
if (dpiScale) {
|
||||||
return qRound(static_cast<qreal>(kDefaultTitleBarHeight) * window->devicePixelRatio());
|
return qRound(static_cast<qreal>(kDefaultCaptionHeight) * devicePixelRatio);
|
||||||
} else {
|
} else {
|
||||||
return kDefaultTitleBarHeight;
|
return kDefaultCaptionHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case SystemMetric::TitleBarHeight: {
|
||||||
|
const int titleBarHeight = window->property(Constants::kTitleBarHeightFlag).toInt();
|
||||||
|
if ((titleBarHeight > 0) && !forceSystemValue) {
|
||||||
|
return qRound(static_cast<qreal>(titleBarHeight) * scaleFactor);
|
||||||
|
} else {
|
||||||
|
const int captionHeight = getSystemMetric(window,SystemMetric::CaptionHeight,
|
||||||
|
dpiScale, forceSystemValue);
|
||||||
|
const int resizeBorderThickness = getSystemMetric(window, SystemMetric::ResizeBorderThickness,
|
||||||
|
dpiScale, forceSystemValue);
|
||||||
|
return (((window->windowState() == Qt::WindowMaximized)
|
||||||
|
|| (window->windowState() == Qt::WindowFullScreen))
|
||||||
|
? captionHeight : (captionHeight + resizeBorderThickness));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -134,14 +149,15 @@ void Utilities::triggerFrameChange(const WId winId)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(winId);
|
||||||
if (SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER) == FALSE) {
|
constexpr UINT flags = (SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||||
|
if (SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, flags) == FALSE) {
|
||||||
qWarning() << "SetWindowPos() failed.";
|
qWarning() << "SetWindowPos() failed.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utilities::updateFrameMargins(const WId winId, const bool reset)
|
void Utilities::updateFrameMargins(const WId winId, const bool reset)
|
||||||
{
|
{
|
||||||
// DwmExtendFrameIntoClientArea() will always fail if DWM Composition is disabled.
|
// DwmExtendFrameIntoClientArea() will always fail if DWM composition is disabled.
|
||||||
// No need to try in this case.
|
// No need to try in this case.
|
||||||
if (!isDwmCompositionAvailable()) {
|
if (!isDwmCompositionAvailable()) {
|
||||||
return;
|
return;
|
||||||
|
@ -163,9 +179,12 @@ void Utilities::updateQtFrameMargins(QWindow *window, const bool enable)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const int rbt = enable ? Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, true, true) : 0;
|
const bool shouldApplyCustomFrameMargins = (enable
|
||||||
const int tbh = enable ? Utilities::getSystemMetric(window, SystemMetric::TitleBarHeight, true, true) : 0;
|
&& (window->windowState() != Qt::WindowMaximized)
|
||||||
const QMargins margins = {-rbt, -(rbt + tbh), -rbt, -rbt}; // left, top, right, bottom
|
&& (window->windowState() != Qt::WindowFullScreen));
|
||||||
|
const int resizeBorderThickness = shouldApplyCustomFrameMargins ? Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, true, true) : 0;
|
||||||
|
const int titleBarHeight = shouldApplyCustomFrameMargins ? Utilities::getSystemMetric(window, SystemMetric::TitleBarHeight, true, true) : 0;
|
||||||
|
const QMargins margins = {-resizeBorderThickness, -titleBarHeight, -resizeBorderThickness, -resizeBorderThickness}; // left, top, right, bottom
|
||||||
const QVariant marginsVar = QVariant::fromValue(margins);
|
const QVariant marginsVar = QVariant::fromValue(margins);
|
||||||
window->setProperty("_q_windowsCustomMargins", marginsVar);
|
window->setProperty("_q_windowsCustomMargins", marginsVar);
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
@ -185,28 +204,31 @@ void Utilities::updateQtFrameMargins(QWindow *window, const bool enable)
|
||||||
bool Utilities::isWin8OrGreater()
|
bool Utilities::isWin8OrGreater()
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8;
|
static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8);
|
||||||
#else
|
#else
|
||||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8;
|
static const bool result = (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8);
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utilities::isWin8Point1OrGreater()
|
bool Utilities::isWin8Point1OrGreater()
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1;
|
static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1);
|
||||||
#else
|
#else
|
||||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8_1;
|
static const bool result = (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8_1);
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utilities::isWin10OrGreater()
|
bool Utilities::isWin10OrGreater()
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
static const bool result = (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10);
|
||||||
#else
|
#else
|
||||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10;
|
static const bool result = (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10);
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue