forked from github_mirror/framelesshelper
parent
f68665298b
commit
d46ec0c1b6
|
@ -13,6 +13,14 @@ if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug") AND NOT DEFINED CMAKE_INTERPROCEDURAL
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
|
||||||
|
if(WIN32)
|
||||||
|
set(CMAKE_DEBUG_POSTFIX d)
|
||||||
|
else()
|
||||||
|
set(CMAKE_DEBUG_POSTFIX _debug)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>518</width>
|
<width>800</width>
|
||||||
<height>368</height>
|
<height>600</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
|
|
@ -61,7 +61,7 @@ void MainWindow::changeEvent(QEvent *event)
|
||||||
bool shouldUpdate = false;
|
bool shouldUpdate = false;
|
||||||
if (event->type() == QEvent::WindowStateChange) {
|
if (event->type() == QEvent::WindowStateChange) {
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
if (isMaximized() || isFullScreen()) {
|
if (isMaximized() || isFullScreen()) {
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
} else if (!isMinimized()) {
|
} else if (!isMinimized()) {
|
||||||
|
@ -91,7 +91,7 @@ void MainWindow::initFramelessHelperOnce()
|
||||||
void MainWindow::resetContentsMargins()
|
void MainWindow::resetContentsMargins()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
setContentsMargins(0, 1, 0, 0);
|
setContentsMargins(0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,7 +101,7 @@ void MainWindow::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QMainWindow::paintEvent(event);
|
QMainWindow::paintEvent(event);
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if ((windowState() == Qt::WindowNoState) && Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater()) {
|
if ((windowState() == Qt::WindowNoState) && Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater()) {
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.save();
|
painter.save();
|
||||||
QPen pen = {};
|
QPen pen = {};
|
||||||
|
|
|
@ -111,7 +111,7 @@ void Widget::changeEvent(QEvent *event)
|
||||||
bool shouldUpdate = false;
|
bool shouldUpdate = false;
|
||||||
if (event->type() == QEvent::WindowStateChange) {
|
if (event->type() == QEvent::WindowStateChange) {
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
if (isMaximized() || isFullScreen()) {
|
if (isMaximized() || isFullScreen()) {
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
} else if (!isMinimized()) {
|
} else if (!isMinimized()) {
|
||||||
|
@ -133,7 +133,7 @@ void Widget::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::paintEvent(event);
|
QWidget::paintEvent(event);
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if ((windowState() == Qt::WindowNoState) && Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater()) {
|
if ((windowState() == Qt::WindowNoState) && Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater()) {
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.save();
|
painter.save();
|
||||||
QPen pen = {};
|
QPen pen = {};
|
||||||
|
@ -333,7 +333,7 @@ void Widget::updateSystemButtonIcons()
|
||||||
void Widget::resetContentsMargins()
|
void Widget::resetContentsMargins()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
setContentsMargins(0, 1, 0, 0);
|
setContentsMargins(0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,12 +23,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "framelesshelper.h"
|
#include "framelesshelper.h"
|
||||||
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
struct UnixHelper
|
||||||
|
{
|
||||||
|
QMutex mutex = {};
|
||||||
|
QWindowList acceptableWindows = {};
|
||||||
|
|
||||||
|
explicit UnixHelper() = default;
|
||||||
|
~UnixHelper() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY_MOVE(UnixHelper)
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC(UnixHelper, g_unixHelper)
|
||||||
|
|
||||||
FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {}
|
FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
FramelessHelper::~FramelessHelper() = default;
|
FramelessHelper::~FramelessHelper() = default;
|
||||||
|
@ -39,6 +54,13 @@ void FramelessHelper::addWindow(QWindow *window)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
g_unixHelper()->mutex.lock();
|
||||||
|
if (g_unixHelper()->acceptableWindows.contains(window)) {
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_unixHelper()->acceptableWindows.append(window);
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
window->setFlags(window->flags() | Qt::FramelessWindowHint);
|
window->setFlags(window->flags() | Qt::FramelessWindowHint);
|
||||||
window->installEventFilter(this);
|
window->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +71,13 @@ void FramelessHelper::removeWindow(QWindow *window)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
g_unixHelper()->mutex.lock();
|
||||||
|
if (!g_unixHelper()->acceptableWindows.contains(window)) {
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_unixHelper()->acceptableWindows.removeAll(window);
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
window->removeEventFilter(this);
|
window->removeEventFilter(this);
|
||||||
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
|
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +99,12 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto window = qobject_cast<QWindow *>(object);
|
const auto window = qobject_cast<QWindow *>(object);
|
||||||
|
g_unixHelper()->mutex.lock();
|
||||||
|
if (!g_unixHelper()->acceptableWindows.contains(window)) {
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
g_unixHelper()->mutex.unlock();
|
||||||
if (Utilities::isWindowFixedSize(window)) {
|
if (Utilities::isWindowFixedSize(window)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,19 +95,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_NAMESPACE_EXPORT(FRAMELESSHELPER_API)
|
Q_NAMESPACE_EXPORT(FRAMELESSHELPER_API)
|
||||||
|
|
||||||
[[maybe_unused]] static constexpr const int kDefaultResizeBorderThicknessClassic = 4;
|
[[maybe_unused]] static constexpr const int kDefaultResizeBorderThickness = 8;
|
||||||
[[maybe_unused]] static constexpr const int kDefaultResizeBorderThicknessAero = 8;
|
|
||||||
[[maybe_unused]] static constexpr const int kDefaultCaptionHeight = 23;
|
[[maybe_unused]] static constexpr const int kDefaultCaptionHeight = 23;
|
||||||
[[maybe_unused]] static constexpr const int kDefaultTitleBarHeight = 30;
|
[[maybe_unused]] static constexpr const int kDefaultTitleBarHeight = 30;
|
||||||
[[maybe_unused]] static constexpr const int kDefaultWindowFrameBorderThickness = 1;
|
[[maybe_unused]] static constexpr const int kDefaultWindowFrameBorderThickness = 1;
|
||||||
|
|
||||||
enum class DwmColorizationArea : int
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
StartMenu_TaskBar_ActionCenter = 1,
|
|
||||||
TitleBar_WindowBorder = 2,
|
|
||||||
All = 3
|
|
||||||
};
|
|
||||||
Q_ENUM_NS(DwmColorizationArea)
|
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -30,37 +30,37 @@
|
||||||
#include <QtCore/qcoreapplication.h>
|
#include <QtCore/qcoreapplication.h>
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include "framelesswindowsmanager.h"
|
#include "framelesswindowsmanager.h"
|
||||||
#include "framelesswindowsmanager_p.h"
|
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "framelesshelper_windows.h"
|
#include "framelesshelper_windows.h"
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct FramelessHelperWinData
|
struct Win32Helper
|
||||||
{
|
{
|
||||||
QMutex mutex = {};
|
QMutex mutex = {};
|
||||||
QScopedPointer<FramelessHelperWin> instance;
|
QScopedPointer<FramelessHelperWin> nativeEventFilter;
|
||||||
QList<WId> acceptableWinIds = {};
|
QWindowList acceptableWindows = {};
|
||||||
|
QHash<WId, QWindow *> windowMapping = {};
|
||||||
QHash<HWND, WNDPROC> qtWindowProcs = {};
|
QHash<HWND, WNDPROC> qtWindowProcs = {};
|
||||||
|
|
||||||
explicit FramelessHelperWinData() = default;
|
explicit Win32Helper() = default;
|
||||||
~FramelessHelperWinData() = default;
|
~Win32Helper() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY_MOVE(FramelessHelperWinData)
|
Q_DISABLE_COPY_MOVE(Win32Helper)
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
|
||||||
|
|
||||||
[[nodiscard]] static inline LRESULT CALLBACK HookWindowProc
|
[[nodiscard]] static inline LRESULT CALLBACK HookWindowProc
|
||||||
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
||||||
{
|
{
|
||||||
g_helper()->mutex.lock();
|
g_win32Helper()->mutex.lock();
|
||||||
if (!g_helper()->qtWindowProcs.contains(hWnd)) {
|
if (!g_win32Helper()->qtWindowProcs.contains(hWnd)) {
|
||||||
g_helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
g_helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
const auto winId = reinterpret_cast<WId>(hWnd);
|
const auto winId = reinterpret_cast<WId>(hWnd);
|
||||||
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
|
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
|
||||||
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
|
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
|
||||||
|
@ -75,7 +75,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
|
||||||
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
||||||
const int titleBarHeight = Utilities::getTitleBarHeight(winId, true);
|
const int titleBarHeight = Utilities::getTitleBarHeight(winId, true);
|
||||||
const int horizontalOffset = ((maxOrFull || !Utilities::isWin10OrGreater()) ? 0 : frameSizeX);
|
const int horizontalOffset = ((maxOrFull || !Utilities::isWindowFrameBorderVisible()) ? 0 : frameSizeX);
|
||||||
const int verticalOffset = (maxOrFull ? titleBarHeight : (titleBarHeight - frameSizeY));
|
const int verticalOffset = (maxOrFull ? titleBarHeight : (titleBarHeight - frameSizeY));
|
||||||
return {qreal(rect.left + horizontalOffset), qreal(rect.top + verticalOffset)};
|
return {qreal(rect.left + horizontalOffset), qreal(rect.top + verticalOffset)};
|
||||||
};
|
};
|
||||||
|
@ -108,9 +108,9 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
// entering Qt's own handling logic.
|
// entering Qt's own handling logic.
|
||||||
return 0; // Return 0 means we have handled this event.
|
return 0; // Return 0 means we have handled this event.
|
||||||
}
|
}
|
||||||
g_helper()->mutex.lock();
|
g_win32Helper()->mutex.lock();
|
||||||
const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hWnd);
|
const WNDPROC originalWindowProc = g_win32Helper()->qtWindowProcs.value(hWnd);
|
||||||
g_helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
Q_ASSERT(originalWindowProc);
|
Q_ASSERT(originalWindowProc);
|
||||||
if (originalWindowProc) {
|
if (originalWindowProc) {
|
||||||
// Hand over to Qt's original window proc function for events we are not
|
// Hand over to Qt's original window proc function for events we are not
|
||||||
|
@ -128,8 +128,8 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(winId);
|
||||||
QMutexLocker locker(&g_helper()->mutex);
|
QMutexLocker locker(&g_win32Helper()->mutex);
|
||||||
if (g_helper()->qtWindowProcs.contains(hwnd)) {
|
if (g_win32Helper()->qtWindowProcs.contains(hwnd)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SetLastError(ERROR_SUCCESS);
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
@ -144,7 +144,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
|
g_win32Helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +155,11 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto hwnd = reinterpret_cast<HWND>(winId);
|
const auto hwnd = reinterpret_cast<HWND>(winId);
|
||||||
QMutexLocker locker(&g_helper()->mutex);
|
QMutexLocker locker(&g_win32Helper()->mutex);
|
||||||
if (!g_helper()->qtWindowProcs.contains(hwnd)) {
|
if (!g_win32Helper()->qtWindowProcs.contains(hwnd)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hwnd);
|
const WNDPROC originalWindowProc = g_win32Helper()->qtWindowProcs.value(hwnd);
|
||||||
Q_ASSERT(originalWindowProc);
|
Q_ASSERT(originalWindowProc);
|
||||||
if (!originalWindowProc) {
|
if (!originalWindowProc) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -169,7 +169,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_helper()->qtWindowProcs.remove(hwnd);
|
g_win32Helper()->qtWindowProcs.remove(hwnd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,18 +186,19 @@ void FramelessHelperWin::addWindow(QWindow *window)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const WId winId = window->winId();
|
g_win32Helper()->mutex.lock();
|
||||||
g_helper()->mutex.lock();
|
if (g_win32Helper()->acceptableWindows.contains(window)) {
|
||||||
if (g_helper()->acceptableWinIds.contains(winId)) {
|
g_win32Helper()->mutex.unlock();
|
||||||
g_helper()->mutex.unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_helper()->acceptableWinIds.append(winId);
|
g_win32Helper()->acceptableWindows.append(window);
|
||||||
if (g_helper()->instance.isNull()) {
|
const WId winId = window->winId();
|
||||||
g_helper()->instance.reset(new FramelessHelperWin);
|
g_win32Helper()->windowMapping.insert(winId, window);
|
||||||
qApp->installNativeEventFilter(g_helper()->instance.data());
|
if (g_win32Helper()->nativeEventFilter.isNull()) {
|
||||||
|
g_win32Helper()->nativeEventFilter.reset(new FramelessHelperWin);
|
||||||
|
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
||||||
}
|
}
|
||||||
g_helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
Utilities::fixupQtInternals(winId);
|
Utilities::fixupQtInternals(winId);
|
||||||
Utilities::updateInternalWindowFrameMargins(window, true);
|
Utilities::updateInternalWindowFrameMargins(window, true);
|
||||||
Utilities::updateWindowFrameMargins(winId, false);
|
Utilities::updateWindowFrameMargins(winId, false);
|
||||||
|
@ -214,14 +215,15 @@ void FramelessHelperWin::removeWindow(QWindow *window)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const WId winId = window->winId();
|
g_win32Helper()->mutex.lock();
|
||||||
g_helper()->mutex.lock();
|
if (!g_win32Helper()->acceptableWindows.contains(window)) {
|
||||||
if (!g_helper()->acceptableWinIds.contains(winId)) {
|
g_win32Helper()->mutex.unlock();
|
||||||
g_helper()->mutex.unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_helper()->acceptableWinIds.removeAll(winId);
|
g_win32Helper()->acceptableWindows.removeAll(window);
|
||||||
g_helper()->mutex.unlock();
|
const WId winId = window->winId();
|
||||||
|
g_win32Helper()->windowMapping.remove(winId);
|
||||||
|
g_win32Helper()->mutex.unlock();
|
||||||
if (!uninstallWindowHook(winId)) {
|
if (!uninstallWindowHook(winId)) {
|
||||||
qWarning() << "Failed to un-hook the window proc function.";
|
qWarning() << "Failed to un-hook the window proc function.";
|
||||||
}
|
}
|
||||||
|
@ -250,19 +252,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const WId winId = reinterpret_cast<WId>(msg->hwnd);
|
const WId winId = reinterpret_cast<WId>(msg->hwnd);
|
||||||
g_helper()->mutex.lock();
|
g_win32Helper()->mutex.lock();
|
||||||
if (!g_helper()->acceptableWinIds.contains(winId)) {
|
if (!g_win32Helper()->windowMapping.contains(winId)) {
|
||||||
g_helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_helper()->mutex.unlock();
|
QWindow * const window = g_win32Helper()->windowMapping.value(winId);
|
||||||
const FramelessManagerPrivate * const manager = FramelessManagerPrivate::instance();
|
g_win32Helper()->mutex.unlock();
|
||||||
const QUuid id = manager->findIdByWinId(winId);
|
|
||||||
Q_ASSERT(!id.isNull());
|
|
||||||
if (id.isNull()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QWindow * const window = manager->findWindowById(id);
|
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,7 +355,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
const auto clientRect = ((static_cast<BOOL>(msg->wParam) == FALSE)
|
const auto clientRect = ((static_cast<BOOL>(msg->wParam) == FALSE)
|
||||||
? reinterpret_cast<LPRECT>(msg->lParam)
|
? reinterpret_cast<LPRECT>(msg->lParam)
|
||||||
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam))->rgrc[0]);
|
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam))->rgrc[0]);
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
// Store the original top before the default window proc applies the default frame.
|
// Store the original top before the default window proc applies the default frame.
|
||||||
const LONG originalTop = clientRect->top;
|
const LONG originalTop = clientRect->top;
|
||||||
// Apply the default frame.
|
// Apply the default frame.
|
||||||
|
@ -385,7 +381,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// a window when it's maximized unless you restore it).
|
// a window when it's maximized unless you restore it).
|
||||||
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
||||||
clientRect->top += frameSizeY;
|
clientRect->top += frameSizeY;
|
||||||
if (!Utilities::isWin10OrGreater()) {
|
if (!Utilities::isWindowFrameBorderVisible()) {
|
||||||
clientRect->bottom -= frameSizeY;
|
clientRect->bottom -= frameSizeY;
|
||||||
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
|
||||||
clientRect->left += frameSizeX;
|
clientRect->left += frameSizeX;
|
||||||
|
@ -598,8 +594,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
const bool full = Utilities::isFullScreen(winId);
|
const bool full = Utilities::isFullScreen(winId);
|
||||||
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
|
||||||
const bool isTop = (localPos.y < frameSizeY);
|
const bool isTop = (localPos.y < frameSizeY);
|
||||||
const bool isTitleBar = false; // ### TODO
|
static constexpr const bool isTitleBar = false;
|
||||||
if (Utilities::isWin10OrGreater()) {
|
if (Utilities::isWindowFrameBorderVisible()) {
|
||||||
// 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.
|
||||||
const LRESULT originalRet = DefWindowProcW(msg->hwnd, WM_NCHITTEST, 0, msg->lParam);
|
const LRESULT originalRet = DefWindowProcW(msg->hwnd, WM_NCHITTEST, 0, msg->lParam);
|
||||||
|
@ -712,7 +708,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!Utilities::isWin10OrGreater()) {
|
if (!Utilities::isWindowFrameBorderVisible()) {
|
||||||
switch (msg->message) {
|
switch (msg->message) {
|
||||||
case WM_NCUAHDRAWCAPTION:
|
case WM_NCUAHDRAWCAPTION:
|
||||||
case WM_NCUAHDRAWFRAME: {
|
case WM_NCUAHDRAWFRAME: {
|
||||||
|
|
|
@ -78,7 +78,7 @@ qreal FramelessQuickUtils::titleBarHeight()
|
||||||
bool FramelessQuickUtils::frameBorderVisible()
|
bool FramelessQuickUtils::frameBorderVisible()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
return (Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater());
|
return (Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater());
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,6 +41,9 @@ class FRAMELESSHELPER_API FramelessQuickHelper : public QObject
|
||||||
#ifdef QML_NAMED_ELEMENT
|
#ifdef QML_NAMED_ELEMENT
|
||||||
QML_NAMED_ELEMENT(FramelessHelper)
|
QML_NAMED_ELEMENT(FramelessHelper)
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef QML_SINGLETON
|
||||||
|
QML_SINGLETON
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickHelper(QObject *parent = nullptr);
|
explicit FramelessQuickHelper(QObject *parent = nullptr);
|
||||||
|
@ -56,6 +59,9 @@ class FRAMELESSHELPER_API FramelessQuickUtils : public QObject
|
||||||
Q_DISABLE_COPY_MOVE(FramelessQuickUtils)
|
Q_DISABLE_COPY_MOVE(FramelessQuickUtils)
|
||||||
#ifdef QML_NAMED_ELEMENT
|
#ifdef QML_NAMED_ELEMENT
|
||||||
QML_NAMED_ELEMENT(FramelessUtils)
|
QML_NAMED_ELEMENT(FramelessUtils)
|
||||||
|
#endif
|
||||||
|
#ifdef QML_SINGLETON
|
||||||
|
QML_SINGLETON
|
||||||
#endif
|
#endif
|
||||||
Q_PROPERTY(qreal titleBarHeight READ titleBarHeight CONSTANT FINAL)
|
Q_PROPERTY(qreal titleBarHeight READ titleBarHeight CONSTANT FINAL)
|
||||||
Q_PROPERTY(bool frameBorderVisible READ frameBorderVisible CONSTANT FINAL)
|
Q_PROPERTY(bool frameBorderVisible READ frameBorderVisible CONSTANT FINAL)
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
static constexpr const int g_resizeBorderThickness = kDefaultResizeBorderThicknessAero;
|
|
||||||
|
|
||||||
Qt::CursorShape Utilities::calculateCursorShape(const QWindow *window, const QPointF &pos)
|
Qt::CursorShape Utilities::calculateCursorShape(const QWindow *window, const QPointF &pos)
|
||||||
{
|
{
|
||||||
Q_ASSERT(window);
|
Q_ASSERT(window);
|
||||||
|
@ -37,18 +35,18 @@ Qt::CursorShape Utilities::calculateCursorShape(const QWindow *window, const QPo
|
||||||
if (window->visibility() != QWindow::Windowed) {
|
if (window->visibility() != QWindow::Windowed) {
|
||||||
return Qt::ArrowCursor;
|
return Qt::ArrowCursor;
|
||||||
}
|
}
|
||||||
if (((pos.x() < g_resizeBorderThickness) && (pos.y() < g_resizeBorderThickness))
|
if (((pos.x() < kDefaultResizeBorderThickness) && (pos.y() < kDefaultResizeBorderThickness))
|
||||||
|| ((pos.x() >= (window->width() - g_resizeBorderThickness)) && (pos.y() >= (window->height() - g_resizeBorderThickness)))) {
|
|| ((pos.x() >= (window->width() - kDefaultResizeBorderThickness)) && (pos.y() >= (window->height() - kDefaultResizeBorderThickness)))) {
|
||||||
return Qt::SizeFDiagCursor;
|
return Qt::SizeFDiagCursor;
|
||||||
}
|
}
|
||||||
if (((pos.x() >= (window->width() - g_resizeBorderThickness)) && (pos.y() < g_resizeBorderThickness))
|
if (((pos.x() >= (window->width() - kDefaultResizeBorderThickness)) && (pos.y() < kDefaultResizeBorderThickness))
|
||||||
|| ((pos.x() < g_resizeBorderThickness) && (pos.y() >= (window->height() - g_resizeBorderThickness)))) {
|
|| ((pos.x() < kDefaultResizeBorderThickness) && (pos.y() >= (window->height() - kDefaultResizeBorderThickness)))) {
|
||||||
return Qt::SizeBDiagCursor;
|
return Qt::SizeBDiagCursor;
|
||||||
}
|
}
|
||||||
if ((pos.x() < g_resizeBorderThickness) || (pos.x() >= (window->width() - g_resizeBorderThickness))) {
|
if ((pos.x() < kDefaultResizeBorderThickness) || (pos.x() >= (window->width() - kDefaultResizeBorderThickness))) {
|
||||||
return Qt::SizeHorCursor;
|
return Qt::SizeHorCursor;
|
||||||
}
|
}
|
||||||
if ((pos.y() < g_resizeBorderThickness) || (pos.y() >= (window->height() - g_resizeBorderThickness))) {
|
if ((pos.y() < kDefaultResizeBorderThickness) || (pos.y() >= (window->height() - kDefaultResizeBorderThickness))) {
|
||||||
return Qt::SizeVerCursor;
|
return Qt::SizeVerCursor;
|
||||||
}
|
}
|
||||||
return Qt::ArrowCursor;
|
return Qt::ArrowCursor;
|
||||||
|
@ -64,16 +62,16 @@ Qt::Edges Utilities::calculateWindowEdges(const QWindow *window, const QPointF &
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
Qt::Edges edges = {};
|
Qt::Edges edges = {};
|
||||||
if (pos.x() < g_resizeBorderThickness) {
|
if (pos.x() < kDefaultResizeBorderThickness) {
|
||||||
edges |= Qt::LeftEdge;
|
edges |= Qt::LeftEdge;
|
||||||
}
|
}
|
||||||
if (pos.x() >= (window->width() - g_resizeBorderThickness)) {
|
if (pos.x() >= (window->width() - kDefaultResizeBorderThickness)) {
|
||||||
edges |= Qt::RightEdge;
|
edges |= Qt::RightEdge;
|
||||||
}
|
}
|
||||||
if (pos.y() < g_resizeBorderThickness) {
|
if (pos.y() < kDefaultResizeBorderThickness) {
|
||||||
edges |= Qt::TopEdge;
|
edges |= Qt::TopEdge;
|
||||||
}
|
}
|
||||||
if (pos.y() >= (window->height() - g_resizeBorderThickness)) {
|
if (pos.y() >= (window->height() - kDefaultResizeBorderThickness)) {
|
||||||
edges |= Qt::BottomEdge;
|
edges |= Qt::BottomEdge;
|
||||||
}
|
}
|
||||||
return edges;
|
return edges;
|
||||||
|
|
12
utilities.h
12
utilities.h
|
@ -29,6 +29,17 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
enum class DwmColorizationArea : int
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
StartMenu_TaskBar_ActionCenter = 1,
|
||||||
|
TitleBar_WindowBorder = 2,
|
||||||
|
All = 3
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(DwmColorizationArea)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Utilities
|
namespace Utilities
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -66,6 +77,7 @@ FRAMELESSHELPER_API void showSystemMenu(const WId winId, const QPointF &pos);
|
||||||
[[nodiscard]] FRAMELESSHELPER_API QColor getFrameBorderColor(const bool active);
|
[[nodiscard]] FRAMELESSHELPER_API QColor getFrameBorderColor(const bool active);
|
||||||
FRAMELESSHELPER_API void updateWindowFrameBorderColor(const WId winId, const bool dark);
|
FRAMELESSHELPER_API void updateWindowFrameBorderColor(const WId winId, const bool dark);
|
||||||
FRAMELESSHELPER_API void fixupQtInternals(const WId winId);
|
FRAMELESSHELPER_API void fixupQtInternals(const WId winId);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_API bool isWindowFrameBorderVisible();
|
||||||
#endif // Q_OS_WINDOWS
|
#endif // Q_OS_WINDOWS
|
||||||
|
|
||||||
} // namespace Utilities
|
} // namespace Utilities
|
||||||
|
|
|
@ -46,6 +46,8 @@ Q_DECLARE_METATYPE(QMargins)
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
static const QString successErrorText = QStringLiteral("The operation completed successfully.");
|
||||||
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
|
||||||
[[nodiscard]] static inline bool isWindowsVersionOrGreater(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild)
|
[[nodiscard]] static inline bool isWindowsVersionOrGreater(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild)
|
||||||
{
|
{
|
||||||
|
@ -71,17 +73,21 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (code == ERROR_SUCCESS) {
|
if (code == ERROR_SUCCESS) {
|
||||||
return {};
|
return successErrorText;
|
||||||
}
|
}
|
||||||
LPWSTR buf = nullptr;
|
LPWSTR buf = nullptr;
|
||||||
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&buf), 0, nullptr) == 0) {
|
nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&buf), 0, nullptr) == 0) {
|
||||||
return {};
|
return QStringLiteral("FormatMessageW() returned empty string.");
|
||||||
}
|
}
|
||||||
const QString message = QStringLiteral("Function %1() failed with error code %2: %3.")
|
QString errorText = QString::fromWCharArray(buf);
|
||||||
.arg(function, QString::number(code), QString::fromWCharArray(buf));
|
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
return message;
|
buf = nullptr;
|
||||||
|
errorText = errorText.trimmed();
|
||||||
|
errorText.remove(QStringLiteral("\\r"));
|
||||||
|
errorText.replace(QStringLiteral("\\n"), QStringLiteral("\n"));
|
||||||
|
return QStringLiteral("Function \"%1()\" failed with error code %2: %3.")
|
||||||
|
.arg(function, QString::number(code), errorText);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static inline QString __getSystemErrorMessage(const QString &function, const HRESULT hr)
|
[[nodiscard]] static inline QString __getSystemErrorMessage(const QString &function, const HRESULT hr)
|
||||||
|
@ -91,7 +97,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
return {};
|
return successErrorText;
|
||||||
}
|
}
|
||||||
const DWORD dwError = HRESULT_CODE(hr);
|
const DWORD dwError = HRESULT_CODE(hr);
|
||||||
return __getSystemErrorMessage(function, dwError);
|
return __getSystemErrorMessage(function, dwError);
|
||||||
|
@ -248,7 +254,7 @@ void Utilities::updateWindowFrameMargins(const WId winId, const bool reset)
|
||||||
if (reset) {
|
if (reset) {
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
if (isWin10OrGreater()) {
|
if (isWindowFrameBorderVisible()) {
|
||||||
return {0, static_cast<int>(getTitleBarHeight(winId, true)), 0, 0};
|
return {0, static_cast<int>(getTitleBarHeight(winId, true)), 0, 0};
|
||||||
} else {
|
} else {
|
||||||
return {1, 1, 1, 1};
|
return {1, 1, 1, 1};
|
||||||
|
@ -275,7 +281,7 @@ void Utilities::updateInternalWindowFrameMargins(QWindow *window, const bool ena
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const int titleBarHeight = getTitleBarHeight(winId, true);
|
const int titleBarHeight = getTitleBarHeight(winId, true);
|
||||||
if (isWin10OrGreater()) {
|
if (isWindowFrameBorderVisible()) {
|
||||||
return {0, -titleBarHeight, 0, 0};
|
return {0, -titleBarHeight, 0, 0};
|
||||||
} else {
|
} else {
|
||||||
const int frameSizeX = getResizeBorderThickness(winId, true, true);
|
const int frameSizeX = getResizeBorderThickness(winId, true, true);
|
||||||
|
@ -286,17 +292,14 @@ void Utilities::updateInternalWindowFrameMargins(QWindow *window, const bool ena
|
||||||
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))
|
||||||
QPlatformWindow *platformWindow = window->handle();
|
if (QPlatformWindow *platformWindow = window->handle()) {
|
||||||
if (platformWindow) {
|
|
||||||
QGuiApplication::platformNativeInterface()->setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"), marginsVar);
|
QGuiApplication::platformNativeInterface()->setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"), marginsVar);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to retrieve the platform window.";
|
qWarning() << "Failed to retrieve the platform window.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
auto *platformWindow = dynamic_cast<QNativeInterface::Private::QWindowsWindow *>(
|
if (const auto platformWindow = dynamic_cast<QNativeInterface::Private::QWindowsWindow *>(window->handle())) {
|
||||||
window->handle());
|
|
||||||
if (platformWindow) {
|
|
||||||
platformWindow->setCustomMargins(margins);
|
platformWindow->setCustomMargins(margins);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to retrieve the platform window.";
|
qWarning() << "Failed to retrieve the platform window.";
|
||||||
|
@ -866,4 +869,20 @@ void Utilities::startSystemResize(QWindow *window, const Qt::Edges edges)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Utilities::isWindowFrameBorderVisible()
|
||||||
|
{
|
||||||
|
static const bool result = []() -> bool {
|
||||||
|
// If we preserve the window frame border on systems before Windows 10,
|
||||||
|
// the window will look rather ugly and I guess no one would like to see
|
||||||
|
// such weired windows. If you really want to know what the window look
|
||||||
|
// like in such situations, just comment out the following IF statement
|
||||||
|
// and run your application on Windows 7/8/8.1.
|
||||||
|
if (!isWin10OrGreater()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !qEnvironmentVariableIsSet("FRAMELESSHELPER_HIDE_FRAME_BORDER");
|
||||||
|
}();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue