finish the linux implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
859912ae25
commit
2c0ec868ab
|
@ -36,17 +36,7 @@ MainWindow::MainWindow(QWidget *parent, const Qt::WindowFlags flags) : Frameless
|
|||
setupUi();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if (titleBar) {
|
||||
delete titleBar;
|
||||
titleBar = nullptr;
|
||||
}
|
||||
if (mainWindow) {
|
||||
delete mainWindow;
|
||||
mainWindow = nullptr;
|
||||
}
|
||||
}
|
||||
MainWindow::~MainWindow() = default;
|
||||
|
||||
void MainWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
|
@ -58,11 +48,11 @@ void MainWindow::changeEvent(QEvent *event)
|
|||
|
||||
void MainWindow::setupUi()
|
||||
{
|
||||
mainWindow = new Ui::MainWindow;
|
||||
mainWindow.reset(new Ui::MainWindow);
|
||||
mainWindow->setupUi(this);
|
||||
|
||||
const auto titleBarWidget = new QWidget(this);
|
||||
titleBar = new Ui::TitleBar;
|
||||
titleBar.reset(new Ui::TitleBar);
|
||||
titleBar->setupUi(titleBarWidget);
|
||||
|
||||
const SystemTheme theme = SystemTheme::Light;
|
||||
|
|
|
@ -51,6 +51,6 @@ Q_SIGNALS:
|
|||
void windowStateChanged();
|
||||
|
||||
private:
|
||||
Ui::TitleBar *titleBar = nullptr;
|
||||
Ui::MainWindow *mainWindow = nullptr;
|
||||
QScopedPointer<Ui::TitleBar> titleBar;
|
||||
QScopedPointer<Ui::MainWindow> mainWindow;
|
||||
};
|
||||
|
|
|
@ -55,7 +55,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
// Don't forget to register our custom QML types!
|
||||
// Don't forget to register our own custom QML types!
|
||||
FramelessHelper::Quick::registerTypes(&engine);
|
||||
|
||||
// This line is not relevant to FramelessHelper, we change the default
|
||||
|
|
|
@ -66,7 +66,7 @@ void Widget::setupUi()
|
|||
{
|
||||
setWindowTitle(tr("Hello, World! - Qt Widgets"));
|
||||
resize(800, 600);
|
||||
m_clockLabel = new QLabel(this);
|
||||
m_clockLabel.reset(new QLabel(this));
|
||||
m_clockLabel->setFrameShape(QFrame::NoFrame);
|
||||
QFont clockFont = font();
|
||||
clockFont.setBold(true);
|
||||
|
@ -78,7 +78,7 @@ void Widget::setupUi()
|
|||
contentLayout->setContentsMargins(0, 0, 0, 0);
|
||||
contentLayout->setSpacing(0);
|
||||
contentLayout->addStretch();
|
||||
contentLayout->addWidget(m_clockLabel);
|
||||
contentLayout->addWidget(m_clockLabel.data());
|
||||
contentLayout->addStretch();
|
||||
widget->setLayout(contentLayout);
|
||||
setContentWidget(widget);
|
||||
|
|
|
@ -49,5 +49,5 @@ private Q_SLOTS:
|
|||
void updateStyleSheet();
|
||||
|
||||
private:
|
||||
QLabel *m_clockLabel = nullptr;
|
||||
QScopedPointer<QLabel> m_clockLabel;
|
||||
};
|
||||
|
|
|
@ -55,6 +55,7 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
|
|||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isThemeChangeEvent(const QEvent * const event);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor calculateSystemButtonBackgroundColor(
|
||||
const Global::SystemButtonType button, const Global::ButtonState state);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode();
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8OrGreater();
|
||||
|
@ -79,7 +80,6 @@ FRAMELESSHELPER_CORE_API void showSystemMenu(
|
|||
const Global::Options options,
|
||||
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::DwmColorizationArea getDwmColorizationArea();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isHighContrastModeEnabled();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getPrimaryScreenDpi(const bool horizontal);
|
||||
|
|
|
@ -49,6 +49,9 @@ public:
|
|||
explicit FramelessWidgetsHelper(QWidget *q, const Global::UserSettings &settings = {});
|
||||
~FramelessWidgetsHelper() override;
|
||||
|
||||
Q_NODISCARD static FramelessWidgetsHelper *get(QWidget *pub);
|
||||
Q_NODISCARD static const FramelessWidgetsHelper *get(const QWidget *pub);
|
||||
|
||||
Q_NODISCARD Q_INVOKABLE bool isNormal() const;
|
||||
Q_NODISCARD Q_INVOKABLE bool isZoomed() const;
|
||||
Q_NODISCARD Q_INVOKABLE bool isFixedSize() const;
|
||||
|
@ -97,21 +100,21 @@ private Q_SLOTS:
|
|||
void updateSystemMaximizeButton();
|
||||
|
||||
private:
|
||||
QWidget *q = nullptr;
|
||||
QPointer<QWidget> q = nullptr;
|
||||
bool m_initialized = false;
|
||||
QWidget *m_systemTitleBarWidget = nullptr;
|
||||
QLabel *m_systemWindowTitleLabel = nullptr;
|
||||
StandardSystemButton *m_systemMinimizeButton = nullptr;
|
||||
StandardSystemButton *m_systemMaximizeButton = nullptr;
|
||||
StandardSystemButton *m_systemCloseButton = nullptr;
|
||||
QWidget *m_userTitleBarWidget = nullptr;
|
||||
QWidget *m_userContentWidget = nullptr;
|
||||
QVBoxLayout *m_mainLayout = nullptr;
|
||||
QScopedPointer<QWidget> m_systemTitleBarWidget;
|
||||
QScopedPointer<QLabel> m_systemWindowTitleLabel;
|
||||
QScopedPointer<StandardSystemButton> m_systemMinimizeButton;
|
||||
QScopedPointer<StandardSystemButton> m_systemMaximizeButton;
|
||||
QScopedPointer<StandardSystemButton> m_systemCloseButton;
|
||||
QPointer<QWidget> m_userTitleBarWidget = nullptr;
|
||||
QPointer<QWidget> m_userContentWidget = nullptr;
|
||||
QScopedPointer<QVBoxLayout> m_mainLayout;
|
||||
QWidgetList m_hitTestVisibleWidgets = {};
|
||||
QWidget *m_userContentContainerWidget = nullptr;
|
||||
QVBoxLayout *m_userContentContainerLayout = nullptr;
|
||||
QScopedPointer<QWidget> m_userContentContainerWidget;
|
||||
QScopedPointer<QVBoxLayout> m_userContentContainerLayout;
|
||||
Qt::WindowState m_savedWindowState = {};
|
||||
QWindow *m_window = nullptr;
|
||||
QPointer<QWindow> m_window = nullptr;
|
||||
Global::UserSettings m_settings = {};
|
||||
Global::SystemParameters m_params = {};
|
||||
bool m_windowExposed = false;
|
||||
|
|
|
@ -100,10 +100,10 @@ void FramelessWindowsManager::addWindow(const UserSettings &settings, const Syst
|
|||
g_helper()->windowIds.append(params.windowId);
|
||||
g_helper()->mutex.unlock();
|
||||
static const bool pureQt = usePureQtImplementation();
|
||||
QWindow *window = params.getWindowHandle();
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (!pureQt) {
|
||||
// Work-around Win32 multi-monitor artifacts.
|
||||
QWindow *window = params.getWindowHandle();
|
||||
connect(window, &QWindow::screenChanged, window, [¶ms, window](QScreen *screen){
|
||||
Q_UNUSED(screen);
|
||||
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
|
||||
# include <QtGui/qpa/qplatformtheme.h>
|
||||
# include <QtGui/private/qguiapplication_p.h>
|
||||
#endif
|
||||
|
||||
// The "Q_INIT_RESOURCE()" macro can't be used within a namespace,
|
||||
// so we wrap it into a separate function outside of the namespace and
|
||||
|
@ -53,6 +57,16 @@ FRAMELESSHELPER_STRING_CONSTANT(light)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(dark)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(highcontrast)
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
[[nodiscard]] extern bool shouldAppsUseDarkMode_windows();
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
[[nodiscard]] extern bool shouldAppsUseDarkMode_linux();
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
[[nodiscard]] extern bool shouldAppsUseDarkMode_macos();
|
||||
#endif
|
||||
|
||||
Qt::CursorShape Utils::calculateCursorShape(const QWindow *window, const QPoint &pos)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
|
@ -247,4 +261,24 @@ QColor Utils::calculateSystemButtonBackgroundColor(const SystemButtonType button
|
|||
return ((state == ButtonState::Hovered) ? result.lighter(110) : result.lighter(105));
|
||||
}
|
||||
|
||||
bool Utils::shouldAppsUseDarkMode()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
|
||||
if (const QPlatformTheme * const theme = QGuiApplicationPrivate::platformTheme()) {
|
||||
return (theme->appearance() == QPlatformTheme::Appearance::Dark);
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
# ifdef Q_OS_WINDOWS
|
||||
return shouldAppsUseDarkMode_windows();
|
||||
# elif defined(Q_OS_LINUX)
|
||||
return shouldAppsUseDarkMode_linux();
|
||||
# elif defined(Q_OS_MACOS)
|
||||
return shouldAppsUseDarkMode_macos();
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -23,9 +23,389 @@
|
|||
*/
|
||||
|
||||
#include "utils.h"
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qregularexpression.h>
|
||||
#include <QtGui/qcursor.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||
#if ((QT_VERSION >= QT_VERSION_CHECK(5, 9, 1)) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
||||
# include <QtPlatformHeaders/qxcbscreenfunctions.h>
|
||||
#endif
|
||||
//#include <gtk/gtk.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Global;
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_SIZE_LEFT = 7;
|
||||
static constexpr const auto _NET_WM_MOVERESIZE_MOVE = 8;
|
||||
#endif
|
||||
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT(display)
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT(x11screen)
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT(rootwindow)
|
||||
|
||||
#if 0
|
||||
template<typename T>
|
||||
[[nodiscard]] static inline T gtkSetting(const gchar *propertyName)
|
||||
{
|
||||
Q_ASSERT(propertyName);
|
||||
if (!propertyName) {
|
||||
return {};
|
||||
}
|
||||
GtkSettings * const settings = gtk_settings_get_default();
|
||||
Q_ASSERT(settings);
|
||||
if (!settings) {
|
||||
return {};
|
||||
}
|
||||
T result = {};
|
||||
g_object_get(settings, propertyName, &result, nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline QString gtkSetting(const gchar *propertyName)
|
||||
{
|
||||
Q_ASSERT(propertyName);
|
||||
if (!propertyName) {
|
||||
return {};
|
||||
}
|
||||
const auto value = gtkSetting<gchararray>(propertyName);
|
||||
const QString result = QString::fromUtf8(value);
|
||||
g_free(value);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
||||
[[nodiscard]] static inline Qt::WindowFrameSection qtEdgesToQtWindowFrameSection(const Qt::Edges edges)
|
||||
{
|
||||
if (edges == Qt::Edges{}) {
|
||||
return Qt::NoSection;
|
||||
}
|
||||
if (edges & Qt::TopEdge) {
|
||||
if (edges & Qt::LeftEdge) {
|
||||
return Qt::TopLeftSection;
|
||||
}
|
||||
if (edges & Qt::RightEdge) {
|
||||
return Qt::TopRightSection;
|
||||
}
|
||||
return Qt::TopSection;
|
||||
}
|
||||
if (edges & Qt::BottomEdge) {
|
||||
if (edges & Qt::LeftEdge) {
|
||||
return Qt::BottomLeftSection;
|
||||
}
|
||||
if (edges & Qt::RightEdge) {
|
||||
return Qt::BottomRightSection;
|
||||
}
|
||||
return Qt::BottomSection;
|
||||
}
|
||||
if (edges & Qt::LeftEdge) {
|
||||
return Qt::LeftSection;
|
||||
}
|
||||
if (edges & Qt::RightEdge) {
|
||||
return Qt::RightSection;
|
||||
}
|
||||
return Qt::NoSection;
|
||||
}
|
||||
#endif
|
||||
|
||||
[[nodiscard]] bool shouldAppsUseDarkMode_linux()
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
https://docs.gtk.org/gtk3/running.html
|
||||
|
||||
It's possible to set a theme variant after the theme name when using GTK_THEME:
|
||||
|
||||
GTK_THEME=Adwaita:dark
|
||||
|
||||
Some themes also have "-dark" as part of their name.
|
||||
|
||||
We test this environment variable first because the documentation says
|
||||
it's mainly used for easy debugging, so it should be possible to use it
|
||||
to override any other settings.
|
||||
*/
|
||||
QString themeName = qEnvironmentVariable("GTK_THEME");
|
||||
const QRegularExpression darkRegex(QStringLiteral("[:-]dark"), QRegularExpression::CaseInsensitiveOption);
|
||||
if (!themeName.isEmpty()) {
|
||||
return darkRegex.match(themeName).hasMatch();
|
||||
}
|
||||
|
||||
/*
|
||||
https://docs.gtk.org/gtk3/property.Settings.gtk-application-prefer-dark-theme.html
|
||||
|
||||
This setting controls which theme is used when the theme specified by
|
||||
gtk-theme-name provides both light and dark variants. We can save a
|
||||
regex check by testing this property first.
|
||||
*/
|
||||
const auto preferDark = gtkSetting<bool>("gtk-application-prefer-dark-theme");
|
||||
if (preferDark) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
https://docs.gtk.org/gtk3/property.Settings.gtk-theme-name.html
|
||||
*/
|
||||
themeName = gtkSetting("gtk-theme-name");
|
||||
if (!themeName.isEmpty()) {
|
||||
return darkRegex.match(themeName).hasMatch();
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline Display *x11_get_display()
|
||||
{
|
||||
if (!qGuiApp) {
|
||||
return nullptr;
|
||||
}
|
||||
QPlatformNativeInterface * const iface = qGuiApp->platformNativeInterface();
|
||||
if (!iface) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto display = iface->nativeResourceForIntegration(kdisplay);
|
||||
if (!display) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<Display *>(display);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline qintptr x11_get_desktop()
|
||||
{
|
||||
if (!qGuiApp) {
|
||||
return 0;
|
||||
}
|
||||
QPlatformNativeInterface * const iface = qGuiApp->platformNativeInterface();
|
||||
if (!iface) {
|
||||
return 0;
|
||||
}
|
||||
const auto screen = iface->nativeResourceForIntegration(kx11screen);
|
||||
if (!screen) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<qintptr>(screen);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline QScreen *x11_getScreenForVirtualDesktop(const int virtualDesktopNumber)
|
||||
{
|
||||
#if ((QT_VERSION >= QT_VERSION_CHECK(5, 9, 1)) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
||||
if (virtualDesktopNumber == -1) {
|
||||
return QGuiApplication::primaryScreen();
|
||||
}
|
||||
const QList<QScreen *> screens = QGuiApplication::screens();
|
||||
if (screens.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
for (auto &&screen : qAsConst(screens)) {
|
||||
if (QXcbScreenFunctions::virtualDesktopNumber(screen) == virtualDesktopNumber) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
#else
|
||||
Q_UNUSED(virtualDesktopNumber);
|
||||
return QGuiApplication::primaryScreen();
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline quintptr x11_get_window(const int desktop)
|
||||
{
|
||||
if (!qGuiApp) {
|
||||
return 0;
|
||||
}
|
||||
QPlatformNativeInterface * const iface = qGuiApp->platformNativeInterface();
|
||||
if (!iface) {
|
||||
return 0;
|
||||
}
|
||||
QScreen * const screen = x11_getScreenForVirtualDesktop(desktop);
|
||||
if (!screen) {
|
||||
return 0;
|
||||
}
|
||||
const auto rootWindow = iface->nativeResourceForScreen(krootwindow, screen);
|
||||
if (!rootWindow) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<quintptr>(rootWindow);
|
||||
}
|
||||
|
||||
static inline void x11_emulateButtonRelease(const WId windowId, const QPoint &globalPos, const QPoint &localPos)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
const Window window = windowId;
|
||||
Display * const display = x11_get_display();
|
||||
XEvent event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.xbutton.button = 0;
|
||||
event.xbutton.same_screen = True;
|
||||
event.xbutton.send_event = True;
|
||||
event.xbutton.window = window;
|
||||
event.xbutton.root = x11_get_window(x11_get_desktop());
|
||||
event.xbutton.x_root = globalPos.x();
|
||||
event.xbutton.y_root = globalPos.y();
|
||||
event.xbutton.x = localPos.x();
|
||||
event.xbutton.y = localPos.y();
|
||||
event.xbutton.type = ButtonRelease;
|
||||
event.xbutton.time = CurrentTime;
|
||||
if (XSendEvent(display, window, True, ButtonReleaseMask, &event) == 0) {
|
||||
qWarning() << "Failed to send ButtonRelease event for native dragging.";
|
||||
}
|
||||
XFlush(display);
|
||||
}
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
||||
static inline void x11_moveOrResizeWindow(const WId windowId, const QPoint &pos, const int section)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display * const display = x11_get_display();
|
||||
static const Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
|
||||
|
||||
// First we need to ungrab the pointer that may have been
|
||||
// automatically grabbed by Qt on ButtonPressEvent
|
||||
XUngrabPointer(display, CurrentTime);
|
||||
|
||||
XEvent event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.window = windowId;
|
||||
event.xclient.message_type = netMoveResize;
|
||||
event.xclient.serial = 0;
|
||||
event.xclient.display = display;
|
||||
event.xclient.send_event = True;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = pos.x();
|
||||
event.xclient.data.l[1] = pos.y();
|
||||
event.xclient.data.l[2] = section;
|
||||
event.xclient.data.l[3] = Button1;
|
||||
event.xclient.data.l[4] = 0; // unused
|
||||
if (XSendEvent(display, x11_get_window(x11_get_desktop()),
|
||||
False, (SubstructureRedirectMask | SubstructureNotifyMask), &event) == 0) {
|
||||
qWarning() << "Failed to send _NET_WM_MOVERESIZE event for native dragging.";
|
||||
}
|
||||
XFlush(display);
|
||||
}
|
||||
|
||||
static inline void x11_windowStartNativeDrag(const WId windowId, const QPoint &globalPos, const QPoint &localPos, const Qt::WindowFrameSection frameSection)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
int nativeSection = -1;
|
||||
switch (frameSection)
|
||||
{
|
||||
case Qt::LeftSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_LEFT;
|
||||
break;
|
||||
case Qt::TopLeftSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
|
||||
break;
|
||||
case Qt::TopSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_TOP;
|
||||
break;
|
||||
case Qt::TopRightSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
|
||||
break;
|
||||
case Qt::RightSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_RIGHT;
|
||||
break;
|
||||
case Qt::BottomRightSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
|
||||
break;
|
||||
case Qt::BottomSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
|
||||
break;
|
||||
case Qt::BottomLeftSection:
|
||||
nativeSection = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
|
||||
break;
|
||||
case Qt::TitleBarArea:
|
||||
nativeSection = _NET_WM_MOVERESIZE_MOVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (nativeSection == -1) {
|
||||
return;
|
||||
}
|
||||
// Before start the drag we need to tell Qt that the mouse is Released!
|
||||
x11_emulateButtonRelease(windowId, globalPos, localPos);
|
||||
x11_moveOrResizeWindow(windowId, globalPos, nativeSection);
|
||||
}
|
||||
#endif
|
||||
|
||||
SystemTheme Utils::getSystemTheme()
|
||||
{
|
||||
// ### TODO: how to detect high contrast mode on Linux?
|
||||
return (shouldAppsUseDarkMode() ? SystemTheme::Dark : SystemTheme::Light);
|
||||
}
|
||||
|
||||
void Utils::startSystemMove(QWindow *window)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
window->startSystemMove();
|
||||
#else
|
||||
const qreal dpr = window->devicePixelRatio();
|
||||
const QPoint globalPos = QPointF(QPointF(QCursor::pos(window->screen())) * dpr).toPoint();
|
||||
const QPoint localPos = QPointF(QPointF(window->mapFromGlobal(globalPos)) * dpr).toPoint();
|
||||
x11_windowStartNativeDrag(window->winId(), globalPos, localPos, Qt::TitleBarArea);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Utils::startSystemResize(QWindow *window, const Qt::Edges edges)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
if (edges == Qt::Edges{}) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
window->startSystemResize(edges);
|
||||
#else
|
||||
const qreal dpr = window->devicePixelRatio();
|
||||
const QPoint globalPos = QPointF(QPointF(QCursor::pos(window->screen())) * dpr).toPoint();
|
||||
const QPoint localPos = QPointF(QPointF(window->mapFromGlobal(globalPos)) * dpr).toPoint();
|
||||
x11_windowStartNativeDrag(window->winId(), globalPos, localPos, qtEdgesToQtWindowFrameSection(edges));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Utils::sendMouseReleaseEvent()
|
||||
{
|
||||
const QWindow * const window = QGuiApplication::focusWindow();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
const qreal dpr = window->devicePixelRatio();
|
||||
const QPoint globalPos = QPointF(QPointF(QCursor::pos(window->screen())) * dpr).toPoint();
|
||||
const QPoint localPos = QPointF(QPointF(window->mapFromGlobal(globalPos)) * dpr).toPoint();
|
||||
x11_emulateButtonRelease(window->winId(), globalPos, localPos);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -214,6 +214,24 @@ FRAMELESSHELPER_STRING_CONSTANT(ReleaseCapture)
|
|||
}
|
||||
#endif
|
||||
|
||||
[[nodiscard]] bool shouldAppsUseDarkMode_windows()
|
||||
{
|
||||
// The global dark mode was first introduced in Windows 10 1607.
|
||||
if (!Utils::isWin101607OrGreater()) {
|
||||
return false;
|
||||
}
|
||||
const auto resultFromRegistry = []() -> bool {
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, qPersonalizeRegistryKey);
|
||||
const auto result = registry.dwordValue(kAppsUseLightTheme);
|
||||
return (result.second && (result.first == 0));
|
||||
};
|
||||
// Starting from Windows 10 1903, ShouldAppsUseDarkMode() always return "TRUE"
|
||||
// (actually, a random non-zero number at runtime), so we can't use it due to
|
||||
// this unreliability. In this case, we just simply read the user's setting from
|
||||
// the registry instead, it's not elegant but at least it works well.
|
||||
return resultFromRegistry();
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline LRESULT CALLBACK SystemMenuHookWindowProc
|
||||
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
|
||||
{
|
||||
|
@ -495,24 +513,6 @@ QColor Utils::getDwmColorizationColor()
|
|||
return QColor::fromRgba(color);
|
||||
}
|
||||
|
||||
bool Utils::shouldAppsUseDarkMode()
|
||||
{
|
||||
// The global dark mode was first introduced in Windows 10 1607.
|
||||
if (!isWin101607OrGreater()) {
|
||||
return false;
|
||||
}
|
||||
const auto resultFromRegistry = []() -> bool {
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, qPersonalizeRegistryKey);
|
||||
const auto result = registry.dwordValue(kAppsUseLightTheme);
|
||||
return (result.second && (result.first == 0));
|
||||
};
|
||||
// Starting from Windows 10 1903, ShouldAppsUseDarkMode() always return "TRUE"
|
||||
// (actually, a random non-zero number at runtime), so we can't use it due to
|
||||
// this unreliability. In this case, we just simply read the user's setting from
|
||||
// the registry instead, it's not elegant but at least it works well.
|
||||
return resultFromRegistry();
|
||||
}
|
||||
|
||||
DwmColorizationArea Utils::getDwmColorizationArea()
|
||||
{
|
||||
// It's a Win10 only feature. (TO BE VERIFIED)
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
*/
|
||||
|
||||
#include "framelessquickutils.h"
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
|
||||
# include <QtGui/qpa/qplatformtheme.h>
|
||||
# include <QtGui/private/qguiapplication_p.h>
|
||||
#endif
|
||||
#include <framelesswindowsmanager.h>
|
||||
#include <utils.h>
|
||||
|
||||
|
@ -68,23 +64,16 @@ bool FramelessQuickUtils::frameBorderVisible()
|
|||
|
||||
qreal FramelessQuickUtils::frameBorderThickness()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return 1.0;
|
||||
#else
|
||||
return 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FramelessQuickUtils::darkModeEnabled()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))
|
||||
if (const QPlatformTheme * const theme = QGuiApplicationPrivate::platformTheme()) {
|
||||
return (theme->appearance() == QPlatformTheme::Appearance::Dark);
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
# ifdef Q_OS_WINDOWS
|
||||
return Utils::shouldAppsUseDarkMode();
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
QColor FramelessQuickUtils::systemAccentColor()
|
||||
|
|
|
@ -365,6 +365,8 @@ void FramelessQuickWindowPrivate::showSystemMenu(const QPoint &pos)
|
|||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.systemMenuOffset,
|
||||
false, m_settings.options, m_params.isWindowFixedSize);
|
||||
#else
|
||||
Q_UNUSED(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -448,6 +450,7 @@ void FramelessQuickWindowPrivate::initialize()
|
|||
return (Utils::isWindowFrameBorderVisible() && !Utils::isWin11OrGreater()
|
||||
&& !(m_settings.options & Option::DontDrawTopWindowFrameBorder));
|
||||
#else
|
||||
Q_UNUSED(this);
|
||||
return false;
|
||||
#endif
|
||||
}();
|
||||
|
@ -562,11 +565,19 @@ bool FramelessQuickWindowPrivate::isInTitleBarDraggableArea(const QPoint &pos) c
|
|||
bool FramelessQuickWindowPrivate::shouldIgnoreMouseEvents(const QPoint &pos) const
|
||||
{
|
||||
Q_Q(const FramelessQuickWindow);
|
||||
return (isNormal()
|
||||
&& ((pos.y() < kDefaultResizeBorderThickness)
|
||||
|| (Utils::isWindowFrameBorderVisible()
|
||||
? false : ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness))))));
|
||||
const bool withinFrameBorder = [&pos, q]() -> bool {
|
||||
if (pos.y() < kDefaultResizeBorderThickness) {
|
||||
return true;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (Utils::isWindowFrameBorderVisible()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness)));
|
||||
}();
|
||||
return (isNormal() && withinFrameBorder);
|
||||
}
|
||||
|
||||
void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event)
|
||||
|
|
|
@ -107,7 +107,7 @@ private:
|
|||
Global::UserSettings m_settings = {};
|
||||
Global::SystemParameters m_params = {};
|
||||
bool m_windowExposed = false;
|
||||
QQuickItem *m_titleBarItem = nullptr;
|
||||
QPointer<QQuickItem> m_titleBarItem = nullptr;
|
||||
QList<QQuickItem *> m_hitTestVisibleItems = {};
|
||||
};
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
|
|||
|
||||
using namespace Global;
|
||||
|
||||
static constexpr const char FRAMELESSHELPER_PROP_NAME[] = "__wwx190_FramelessWidgetsHelper_instance";
|
||||
static constexpr const char QT_MAINWINDOW_CLASS_NAME[] = "QMainWindow";
|
||||
|
||||
FRAMELESSHELPER_STRING_CONSTANT2(StyleSheetColorTemplate, "color: %1;")
|
||||
|
@ -55,6 +56,24 @@ FramelessWidgetsHelper::FramelessWidgetsHelper(QWidget *q, const UserSettings &s
|
|||
|
||||
FramelessWidgetsHelper::~FramelessWidgetsHelper() = default;
|
||||
|
||||
FramelessWidgetsHelper *FramelessWidgetsHelper::get(QWidget *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return qvariant_cast<FramelessWidgetsHelper *>(pub->property(FRAMELESSHELPER_PROP_NAME));
|
||||
}
|
||||
|
||||
const FramelessWidgetsHelper *FramelessWidgetsHelper::get(const QWidget *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return qvariant_cast<const FramelessWidgetsHelper *>(pub->property(FRAMELESSHELPER_PROP_NAME));
|
||||
}
|
||||
|
||||
bool FramelessWidgetsHelper::isNormal() const
|
||||
{
|
||||
return (m_params.getWindowState() == Qt::WindowNoState);
|
||||
|
@ -114,7 +133,7 @@ void FramelessWidgetsHelper::setTitleBarWidget(QWidget *widget)
|
|||
}
|
||||
if (m_settings.options & Option::CreateStandardWindowLayout) {
|
||||
if (m_systemTitleBarWidget && m_systemTitleBarWidget->isVisible()) {
|
||||
m_mainLayout->removeWidget(m_systemTitleBarWidget);
|
||||
m_mainLayout->removeWidget(m_systemTitleBarWidget.data());
|
||||
m_systemTitleBarWidget->hide();
|
||||
}
|
||||
if (m_userTitleBarWidget) {
|
||||
|
@ -226,6 +245,7 @@ void FramelessWidgetsHelper::changeEventHandler(QEvent *event)
|
|||
|
||||
void FramelessWidgetsHelper::paintEventHandler(QPaintEvent *event)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
Q_ASSERT(event);
|
||||
if (!event) {
|
||||
return;
|
||||
|
@ -241,6 +261,9 @@ void FramelessWidgetsHelper::paintEventHandler(QPaintEvent *event)
|
|||
painter.setPen(pen);
|
||||
painter.drawLine(0, 0, (q->width() - 1), 0);
|
||||
painter.restore();
|
||||
#else
|
||||
Q_UNUSED(event);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::mouseMoveEventHandler(QMouseEvent *event)
|
||||
|
@ -324,6 +347,8 @@ void FramelessWidgetsHelper::initialize()
|
|||
return;
|
||||
}
|
||||
m_initialized = true;
|
||||
// Let the user be able to get the helper class instance from outside.
|
||||
q->setProperty(FRAMELESSHELPER_PROP_NAME, QVariant::fromValue(this));
|
||||
// Without this flag, Qt will always create an invisible native parent window
|
||||
// for any native widgets which will intercept some win32 messages and confuse
|
||||
// our own native event filter, so to prevent some weired bugs from happening,
|
||||
|
@ -395,18 +420,18 @@ void FramelessWidgetsHelper::initialize()
|
|||
switch (button) {
|
||||
case SystemButtonType::Minimize: {
|
||||
if (m_systemMinimizeButton) {
|
||||
updateSystemButtonState(m_systemMinimizeButton);
|
||||
updateSystemButtonState(m_systemMinimizeButton.data());
|
||||
}
|
||||
} break;
|
||||
case SystemButtonType::Maximize:
|
||||
case SystemButtonType::Restore: {
|
||||
if (m_systemMaximizeButton) {
|
||||
updateSystemButtonState(m_systemMaximizeButton);
|
||||
updateSystemButtonState(m_systemMaximizeButton.data());
|
||||
}
|
||||
} break;
|
||||
case SystemButtonType::Close: {
|
||||
if (m_systemCloseButton) {
|
||||
updateSystemButtonState(m_systemCloseButton);
|
||||
updateSystemButtonState(m_systemCloseButton.data());
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
|
@ -422,16 +447,20 @@ void FramelessWidgetsHelper::initialize()
|
|||
" Enabling this option will mess up with your main window's layout.";
|
||||
}
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (m_settings.options & Option::TransparentWindowBackground) {
|
||||
m_settings.options |= Option::BeCompatibleWithQtFramelessWindowHint;
|
||||
}
|
||||
#endif
|
||||
if (m_settings.options & Option::DisableResizing) {
|
||||
setFixedSize(true, true);
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (m_settings.options & Option::BeCompatibleWithQtFramelessWindowHint) {
|
||||
Utils::tryToBeCompatibleWithQtFramelessWindowHint(windowId, m_params.getWindowFlags,
|
||||
m_params.setWindowFlags, true);
|
||||
}
|
||||
#endif
|
||||
if (m_settings.options & Option::TransparentWindowBackground) {
|
||||
q->setAttribute(Qt::WA_NoSystemBackground);
|
||||
q->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
@ -453,9 +482,9 @@ void FramelessWidgetsHelper::initialize()
|
|||
});
|
||||
setupInitialUi();
|
||||
if (m_settings.options & Option::CreateStandardWindowLayout) {
|
||||
m_settings.minimizeButton = m_systemMinimizeButton;
|
||||
m_settings.maximizeButton = m_systemMaximizeButton;
|
||||
m_settings.closeButton = m_systemCloseButton;
|
||||
m_settings.minimizeButton = m_systemMinimizeButton.data();
|
||||
m_settings.maximizeButton = m_systemMaximizeButton.data();
|
||||
m_settings.closeButton = m_systemCloseButton.data();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,40 +493,40 @@ void FramelessWidgetsHelper::createSystemTitleBar()
|
|||
if (!(m_settings.options & Option::CreateStandardWindowLayout)) {
|
||||
return;
|
||||
}
|
||||
m_systemTitleBarWidget = new QWidget(q);
|
||||
m_systemTitleBarWidget.reset(new QWidget(q));
|
||||
m_systemTitleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_systemTitleBarWidget->setFixedHeight(kDefaultTitleBarHeight);
|
||||
m_systemWindowTitleLabel = new QLabel(m_systemTitleBarWidget);
|
||||
m_systemWindowTitleLabel.reset(new QLabel(m_systemTitleBarWidget.data()));
|
||||
m_systemWindowTitleLabel->setFrameShape(QFrame::NoFrame);
|
||||
QFont windowTitleFont = q->font();
|
||||
windowTitleFont.setPointSize(11);
|
||||
windowTitleFont.setPointSize(kDefaultTitleBarFontPointSize);
|
||||
m_systemWindowTitleLabel->setFont(windowTitleFont);
|
||||
m_systemWindowTitleLabel->setText(q->windowTitle());
|
||||
connect(q, &QWidget::windowTitleChanged, m_systemWindowTitleLabel, &QLabel::setText);
|
||||
m_systemMinimizeButton = new StandardSystemButton(SystemButtonType::Minimize, m_systemTitleBarWidget);
|
||||
connect(q, &QWidget::windowTitleChanged, m_systemWindowTitleLabel.data(), &QLabel::setText);
|
||||
m_systemMinimizeButton.reset(new StandardSystemButton(SystemButtonType::Minimize, m_systemTitleBarWidget.data()));
|
||||
m_systemMinimizeButton->setFixedSize(kDefaultSystemButtonSize);
|
||||
m_systemMinimizeButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||
m_systemMinimizeButton->setToolTip(tr("Minimize"));
|
||||
connect(m_systemMinimizeButton, &StandardSystemButton::clicked, q, &QWidget::showMinimized);
|
||||
m_systemMaximizeButton = new StandardSystemButton(SystemButtonType::Maximize, m_systemTitleBarWidget);
|
||||
connect(m_systemMinimizeButton.data(), &StandardSystemButton::clicked, q, &QWidget::showMinimized);
|
||||
m_systemMaximizeButton.reset(new StandardSystemButton(SystemButtonType::Maximize, m_systemTitleBarWidget.data()));
|
||||
m_systemMaximizeButton->setFixedSize(kDefaultSystemButtonSize);
|
||||
m_systemMaximizeButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||
connect(m_systemMaximizeButton, &StandardSystemButton::clicked, this, &FramelessWidgetsHelper::toggleMaximized);
|
||||
m_systemCloseButton = new StandardSystemButton(SystemButtonType::Close, m_systemTitleBarWidget);
|
||||
connect(m_systemMaximizeButton.data(), &StandardSystemButton::clicked, this, &FramelessWidgetsHelper::toggleMaximized);
|
||||
m_systemCloseButton.reset(new StandardSystemButton(SystemButtonType::Close, m_systemTitleBarWidget.data()));
|
||||
m_systemCloseButton->setFixedSize(kDefaultSystemButtonSize);
|
||||
m_systemCloseButton->setIconSize(kDefaultSystemButtonIconSize);
|
||||
m_systemCloseButton->setToolTip(tr("Close"));
|
||||
connect(m_systemCloseButton, &StandardSystemButton::clicked, q, &QWidget::close);
|
||||
connect(m_systemCloseButton.data(), &StandardSystemButton::clicked, q, &QWidget::close);
|
||||
updateSystemMaximizeButton();
|
||||
const auto systemTitleBarLayout = new QHBoxLayout(m_systemTitleBarWidget);
|
||||
const auto systemTitleBarLayout = new QHBoxLayout(m_systemTitleBarWidget.data());
|
||||
systemTitleBarLayout->setContentsMargins(0, 0, 0, 0);
|
||||
systemTitleBarLayout->setSpacing(0);
|
||||
systemTitleBarLayout->addSpacerItem(new QSpacerItem(10, 10));
|
||||
systemTitleBarLayout->addWidget(m_systemWindowTitleLabel);
|
||||
systemTitleBarLayout->addWidget(m_systemWindowTitleLabel.data());
|
||||
systemTitleBarLayout->addStretch();
|
||||
systemTitleBarLayout->addWidget(m_systemMinimizeButton);
|
||||
systemTitleBarLayout->addWidget(m_systemMaximizeButton);
|
||||
systemTitleBarLayout->addWidget(m_systemCloseButton);
|
||||
systemTitleBarLayout->addWidget(m_systemMinimizeButton.data());
|
||||
systemTitleBarLayout->addWidget(m_systemMaximizeButton.data());
|
||||
systemTitleBarLayout->addWidget(m_systemCloseButton.data());
|
||||
m_systemTitleBarWidget->setLayout(systemTitleBarLayout);
|
||||
}
|
||||
|
||||
|
@ -506,12 +535,12 @@ void FramelessWidgetsHelper::createUserContentContainer()
|
|||
if (!(m_settings.options & Option::CreateStandardWindowLayout)) {
|
||||
return;
|
||||
}
|
||||
m_userContentContainerWidget = new QWidget(q);
|
||||
m_userContentContainerWidget.reset(new QWidget(q));
|
||||
m_userContentContainerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_userContentContainerLayout = new QVBoxLayout(m_userContentContainerWidget);
|
||||
m_userContentContainerLayout.reset(new QVBoxLayout(m_userContentContainerWidget.data()));
|
||||
m_userContentContainerLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_userContentContainerLayout->setSpacing(0);
|
||||
m_userContentContainerWidget->setLayout(m_userContentContainerLayout);
|
||||
m_userContentContainerWidget->setLayout(m_userContentContainerLayout.data());
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::setupInitialUi()
|
||||
|
@ -519,12 +548,12 @@ void FramelessWidgetsHelper::setupInitialUi()
|
|||
if (m_settings.options & Option::CreateStandardWindowLayout) {
|
||||
createSystemTitleBar();
|
||||
createUserContentContainer();
|
||||
m_mainLayout = new QVBoxLayout(q);
|
||||
m_mainLayout.reset(new QVBoxLayout(q));
|
||||
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_mainLayout->setSpacing(0);
|
||||
m_mainLayout->addWidget(m_systemTitleBarWidget);
|
||||
m_mainLayout->addWidget(m_userContentContainerWidget);
|
||||
q->setLayout(m_mainLayout);
|
||||
m_mainLayout->addWidget(m_systemTitleBarWidget.data());
|
||||
m_mainLayout->addWidget(m_userContentContainerWidget.data());
|
||||
q->setLayout(m_mainLayout.data());
|
||||
updateSystemTitleBarStyleSheet();
|
||||
q->update();
|
||||
}
|
||||
|
@ -603,10 +632,10 @@ bool FramelessWidgetsHelper::isInTitleBarDraggableArea(const QPoint &pos) const
|
|||
return region;
|
||||
}
|
||||
if (m_settings.options & Option::CreateStandardWindowLayout) {
|
||||
QRegion region = mapWidgetGeometryToScene(m_systemTitleBarWidget);
|
||||
region -= mapWidgetGeometryToScene(m_systemMinimizeButton);
|
||||
region -= mapWidgetGeometryToScene(m_systemMaximizeButton);
|
||||
region -= mapWidgetGeometryToScene(m_systemCloseButton);
|
||||
QRegion region = mapWidgetGeometryToScene(m_systemTitleBarWidget.data());
|
||||
region -= mapWidgetGeometryToScene(m_systemMinimizeButton.data());
|
||||
region -= mapWidgetGeometryToScene(m_systemMaximizeButton.data());
|
||||
region -= mapWidgetGeometryToScene(m_systemCloseButton.data());
|
||||
return region;
|
||||
}
|
||||
return {};
|
||||
|
@ -626,11 +655,19 @@ bool FramelessWidgetsHelper::shouldDrawFrameBorder() const
|
|||
|
||||
bool FramelessWidgetsHelper::shouldIgnoreMouseEvents(const QPoint &pos) const
|
||||
{
|
||||
return (isNormal()
|
||||
&& ((pos.y() < kDefaultResizeBorderThickness)
|
||||
|| (Utils::isWindowFrameBorderVisible()
|
||||
? false : ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness))))));
|
||||
const bool withinFrameBorder = [&pos, this]() -> bool {
|
||||
if (pos.y() < kDefaultResizeBorderThickness) {
|
||||
return true;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (Utils::isWindowFrameBorderVisible()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return ((pos.x() < kDefaultResizeBorderThickness)
|
||||
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness)));
|
||||
}();
|
||||
return (isNormal() && withinFrameBorder);
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelper::updateContentsMargins()
|
||||
|
@ -647,18 +684,29 @@ void FramelessWidgetsHelper::updateSystemTitleBarStyleSheet()
|
|||
}
|
||||
const bool active = q->isActiveWindow();
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
#ifdef Q_OS_WINDOWS
|
||||
const bool colorizedTitleBar = Utils::isTitleBarColorized();
|
||||
#else
|
||||
constexpr const bool colorizedTitleBar = false;
|
||||
#endif
|
||||
const QColor systemTitleBarWidgetBackgroundColor = [active, colorizedTitleBar, dark]() -> QColor {
|
||||
#ifndef Q_OS_WINDOWS
|
||||
Q_UNUSED(colorizedTitleBar);
|
||||
#endif
|
||||
if (active) {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (colorizedTitleBar) {
|
||||
return Utils::getDwmColorizationColor();
|
||||
} else {
|
||||
#endif
|
||||
if (dark) {
|
||||
return kDefaultBlackColor;
|
||||
} else {
|
||||
return kDefaultWhiteColor;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (dark) {
|
||||
return kDefaultSystemDarkColor;
|
||||
|
@ -733,6 +781,8 @@ void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos)
|
|||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.systemMenuOffset,
|
||||
false, m_settings.options, m_params.isWindowFixedSize);
|
||||
#else
|
||||
Q_UNUSED(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -73,9 +73,11 @@ void StandardSystemButtonPrivate::refreshButtonTheme(const bool force)
|
|||
return;
|
||||
}
|
||||
const SystemTheme systemTheme = []() -> SystemTheme {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (Utils::isTitleBarColorized()) {
|
||||
return SystemTheme::Dark;
|
||||
}
|
||||
#endif
|
||||
return Utils::getSystemTheme();
|
||||
}();
|
||||
if ((m_buttonTheme == systemTheme) && !force) {
|
||||
|
|
|
@ -77,7 +77,7 @@ private:
|
|||
void initialize();
|
||||
|
||||
private:
|
||||
StandardSystemButton *q_ptr;
|
||||
StandardSystemButton *q_ptr = nullptr;
|
||||
Global::SystemTheme m_buttonTheme = Global::SystemTheme::Unknown;
|
||||
Global::SystemButtonType m_buttonType = Global::SystemButtonType::Unknown;
|
||||
QPixmap m_icon = {};
|
||||
|
|
Loading…
Reference in New Issue