general improvement

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-04-19 15:33:37 +08:00
parent 68296cc1ae
commit d86e9144a2
16 changed files with 268 additions and 319 deletions

View File

@ -38,6 +38,7 @@ class FRAMELESSHELPER_CORE_API FramelessWindowsManager : public QObject
Q_DISABLE_COPY_MOVE(FramelessWindowsManager)
Q_PROPERTY(bool usePureQtImplementation READ usePureQtImplementation CONSTANT FINAL)
Q_PROPERTY(Global::SystemTheme systemTheme READ systemTheme NOTIFY systemThemeChanged FINAL)
Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemThemeChanged FINAL)
public:
explicit FramelessWindowsManager(QObject *parent = nullptr);
@ -47,6 +48,7 @@ public:
Q_NODISCARD bool usePureQtImplementation() const;
Q_NODISCARD Global::SystemTheme systemTheme() const;
Q_NODISCARD QColor systemAccentColor() const;
public Q_SLOTS:
void addWindow(const Global::UserSettings &settings, const Global::SystemParameters &params);

View File

@ -55,6 +55,7 @@ FRAMELESSHELPER_CORE_API void moveWindowToDesktopCenter(
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor calculateSystemButtonBackgroundColor(
const Global::SystemButtonType button, const Global::ButtonState state);
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode();
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
#ifdef Q_OS_WINDOWS
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWin8OrGreater();
@ -95,7 +96,6 @@ FRAMELESSHELPER_CORE_API void showSystemMenu(
FRAMELESSHELPER_CORE_API void updateWindowFrameBorderColor(const WId windowId, const bool dark);
FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId windowId);
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
FRAMELESSHELPER_CORE_API void installSystemMenuHook(
const WId windowId,
@ -114,9 +114,8 @@ FRAMELESSHELPER_CORE_API void updateGlobalWin32ControlsTheme(const WId windowId,
#endif // Q_OS_WINDOWS
#ifdef Q_OS_MACOS
FRAMELESSHELPER_CORE_API void setWindowHook(const WId windowId);
FRAMELESSHELPER_CORE_API void unsetWindowHook(const WId windowId);
FRAMELESSHELPER_CORE_API void removeWindowFrame(const WId windowId);
FRAMELESSHELPER_CORE_API void setSystemTitleBarVisible(const WId windowId, const bool visible);
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getControlsAccentColor();
#endif // Q_OS_MACOS
} // namespace Utils

View File

@ -67,6 +67,7 @@ public:
Q_INVOKABLE void changeEventHandler(QEvent *event);
Q_INVOKABLE void paintEventHandler(QPaintEvent *event);
Q_INVOKABLE void mouseMoveEventHandler(QMouseEvent *event);
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseReleaseEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseDoubleClickEventHandler(QMouseEvent *event);
@ -93,6 +94,7 @@ private:
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
Q_NODISCARD bool shouldDrawFrameBorder() const;
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
void doStartSystemMove2(QMouseEvent *event);
private Q_SLOTS:
void updateContentsMargins();

View File

@ -107,6 +107,11 @@ SystemTheme FramelessWindowsManagerPrivate::systemTheme() const
return m_systemTheme;
}
QColor FramelessWindowsManagerPrivate::systemAccentColor() const
{
return m_accentColor;
}
void FramelessWindowsManagerPrivate::addWindow(const UserSettings &settings, const SystemParameters &params)
{
Q_ASSERT(params.isValid());
@ -160,21 +165,27 @@ void FramelessWindowsManagerPrivate::notifySystemThemeHasChangedOrNot()
#ifdef Q_OS_WINDOWS
const DwmColorizationArea currentColorizationArea = Utils::getDwmColorizationArea();
const QColor currentAccentColor = Utils::getDwmColorizationColor();
#endif
#ifdef Q_OS_LINUX
const QColor currentAccentColor = {}; // ### TODO
#endif
#ifdef Q_OS_MACOS
const QColor currentAccentColor = Utils::getControlsAccentColor();
#endif
bool notify = false;
if (m_systemTheme != currentSystemTheme) {
m_systemTheme = currentSystemTheme;
notify = true;
}
if (m_accentColor != currentAccentColor) {
m_accentColor = currentAccentColor;
notify = true;
}
#ifdef Q_OS_WINDOWS
if (m_colorizationArea != currentColorizationArea) {
m_colorizationArea = currentColorizationArea;
notify = true;
}
if (m_accentColor != currentAccentColor) {
m_accentColor = currentAccentColor;
notify = true;
}
#endif
if (notify) {
Q_EMIT q->systemThemeChanged();
@ -188,6 +199,9 @@ void FramelessWindowsManagerPrivate::initialize()
m_colorizationArea = Utils::getDwmColorizationArea();
m_accentColor = Utils::getDwmColorizationColor();
#endif
#ifdef Q_OS_MACOS
m_accentColor = Utils::getControlsAccentColor();
#endif
}
FramelessWindowsManager::FramelessWindowsManager(QObject *parent) : QObject(parent), d_ptr(new FramelessWindowsManagerPrivate(this))
@ -213,6 +227,12 @@ SystemTheme FramelessWindowsManager::systemTheme() const
return d->systemTheme();
}
QColor FramelessWindowsManager::systemAccentColor() const
{
Q_D(const FramelessWindowsManager);
return d->systemAccentColor();
}
void FramelessWindowsManager::addWindow(const UserSettings &settings, const SystemParameters &params)
{
Q_D(FramelessWindowsManager);

View File

@ -46,6 +46,7 @@ public:
Q_NODISCARD static bool usePureQtImplementation();
Q_NODISCARD Global::SystemTheme systemTheme() const;
Q_NODISCARD QColor systemAccentColor() const;
public Q_SLOTS:
static void addWindow(const Global::UserSettings &settings, const Global::SystemParameters &params);
@ -57,9 +58,9 @@ private:
private:
FramelessWindowsManager *q_ptr = nullptr;
Global::SystemTheme m_systemTheme = Global::SystemTheme::Unknown;
QColor m_accentColor = {};
#ifdef Q_OS_WINDOWS
Global::DwmColorizationArea m_colorizationArea = Global::DwmColorizationArea::None_;
QColor m_accentColor = {};
#endif
};

View File

@ -251,11 +251,17 @@ QColor Utils::calculateSystemButtonBackgroundColor(const SystemButtonType button
if (button == SystemButtonType::Close) {
return kDefaultSystemCloseButtonBackgroundColor;
}
#ifdef Q_OS_WINDOWS
if (isTitleBarColorized()) {
#ifdef Q_OS_WINDOWS
return getDwmColorizationColor();
}
#endif
#ifdef Q_OS_LINUX
return {};
#endif
#ifdef Q_OS_MACOS
return getControlsAccentColor();
#endif
}
return kDefaultSystemButtonBackgroundColor;
}();
return ((state == ButtonState::Hovered) ? result.lighter(110) : result.lighter(105));

View File

@ -25,12 +25,11 @@
#include "utils.h"
#include <QtCore/qdebug.h>
#include <QtCore/qregularexpression.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>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include <QtGui/private/qtx11extras_p.h>
#else
# include <QX11Extras/qx11info.h>
#endif
#include <gtk/gtk.h>
#include <X11/Xlib.h>
@ -52,11 +51,6 @@ static constexpr const auto _NET_WM_MOVERESIZE_MOVE = 8;
static constexpr const char GTK_THEME_NAME_ENV_VAR[] = "GTK_THEME";
static constexpr const char GTK_THEME_NAME_PROP[] = "gtk-theme-name";
static constexpr const char GTK_THEME_PREFER_DARK_PROP[] = "gtk-application-prefer-dark-theme";
FRAMELESSHELPER_BYTEARRAY_CONSTANT(display)
FRAMELESSHELPER_BYTEARRAY_CONSTANT(x11screen)
FRAMELESSHELPER_BYTEARRAY_CONSTANT(rootwindow)
FRAMELESSHELPER_STRING_CONSTANT2(GTK_THEME_DARK_REGEX, "[:-]dark")
static constexpr const char WM_MOVERESIZE_OPERATION_NAME[] = "_NET_WM_MOVERESIZE";
@ -166,168 +160,41 @@ template<typename T>
return false;
}
[[nodiscard]] static inline Display *x11_get_display()
{
if (!qGuiApp) {
return nullptr;
}
QPlatformNativeInterface * const iface = qGuiApp->platformNativeInterface();
Q_ASSERT(iface);
if (!iface) {
return nullptr;
}
const auto display = iface->nativeResourceForIntegration(kdisplay);
Q_ASSERT(display);
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();
Q_ASSERT(iface);
if (!iface) {
return 0;
}
const auto screen = iface->nativeResourceForIntegration(kx11screen);
//Q_ASSERT(screen); // Always zero on both X11 and Wayland. Why? Is zero a valid value?
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();
Q_ASSERT(iface);
if (!iface) {
return 0;
}
QScreen * const screen = x11_getScreenForVirtualDesktop(desktop);
Q_ASSERT(screen);
if (!screen) {
return 0;
}
const auto window = iface->nativeResourceForScreen(krootwindow, screen);
Q_ASSERT(window); // Always zero on Wayland, non-zero on X11.
if (!window) {
return 0;
}
return reinterpret_cast<quintptr>(window);
}
static inline void x11_emulateButtonRelease(const WId windowId, const QPoint &globalPos, const QPoint &localPos)
static inline void doStartSystemMoveResize(const WId windowId, const QPoint &globalPos, const int edges)
{
Q_ASSERT(windowId);
if (!windowId) {
Q_ASSERT(edges >= 0);
if (!windowId || (edges < 0)) {
return;
}
Display * const display = x11_get_display();
Q_ASSERT(display);
if (!display) {
return;
}
const Window window = windowId;
XEvent event;
memset(&event, 0, sizeof(event));
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);
}
static inline void x11_moveOrResizeWindow(const WId windowId, const QPoint &pos, const int section)
{
Q_ASSERT(windowId);
Q_ASSERT(section >= 0);
if (!windowId || (section < 0)) {
return;
}
Display * const display = x11_get_display();
Q_ASSERT(display);
if (!display) {
return;
}
static const Atom netMoveResize = XInternAtom(display, WM_MOVERESIZE_OPERATION_NAME, False);
Q_ASSERT(netMoveResize);
if (!netMoveResize) {
return;
}
// 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.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;
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 int section)
{
Q_ASSERT(windowId);
if (!windowId) {
return;
}
if (section < 0) {
return;
}
// Before we start dragging we need to tell Qt that the mouse is released.
x11_emulateButtonRelease(windowId, globalPos, localPos);
x11_moveOrResizeWindow(windowId, globalPos, section);
xcb_connection_t * const connection = QX11Info::connection();
Q_ASSERT(connection);
static const xcb_atom_t moveResize = [connection]() -> xcb_atom_t {
const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false,
qstrlen(WM_MOVERESIZE_OPERATION_NAME), WM_MOVERESIZE_OPERATION_NAME);
xcb_intern_atom_reply_t * const reply = xcb_intern_atom_reply(connection, cookie, nullptr);
Q_ASSERT(reply);
const xcb_atom_t atom = reply->atom;
Q_ASSERT(atom);
std::free(reply);
return atom;
}();
const quint32 rootWindow = QX11Info::appRootWindow(QX11Info::appScreen());
Q_ASSERT(rootWindow);
xcb_client_message_event_t xev;
memset(&xev, 0, sizeof(xev));
xev.response_type = XCB_CLIENT_MESSAGE;
xev.type = moveResize;
xev.window = windowId;
xev.format = 32;
xev.data.data32[0] = globalPos.x();
xev.data.data32[1] = globalPos.y();
xev.data.data32[2] = edges;
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
xcb_ungrab_pointer(connection, XCB_CURRENT_TIME);
xcb_send_event(connection, false, rootWindow,
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY),
reinterpret_cast<const char *>(&xev));
}
SystemTheme Utils::getSystemTheme()
@ -346,8 +213,7 @@ void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
// are expecting device coordinates.
const qreal dpr = window->devicePixelRatio();
const QPoint globalPos2 = QPointF(QPointF(globalPos) * dpr).toPoint();
const QPoint localPos2 = QPointF(QPointF(window->mapFromGlobal(globalPos)) * dpr).toPoint();
x11_windowStartNativeDrag(window->winId(), globalPos2, localPos2, _NET_WM_MOVERESIZE_MOVE);
doStartSystemMoveResize(window->winId(), globalPos2, _NET_WM_MOVERESIZE_MOVE);
}
void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos)
@ -367,8 +233,12 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi
// are expecting device coordinates.
const qreal dpr = window->devicePixelRatio();
const QPoint globalPos2 = QPointF(QPointF(globalPos) * dpr).toPoint();
const QPoint localPos2 = QPointF(QPointF(window->mapFromGlobal(globalPos)) * dpr).toPoint();
x11_windowStartNativeDrag(window->winId(), globalPos2, localPos2, section);
doStartSystemMoveResize(window->winId(), globalPos2, section);
}
bool Utils::isTitleBarColorized()
{
return false;
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -26,6 +26,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
#include <QtGui/qwindow.h>
#include <QtGui/private/qcoregraphics_p.h>
#include <objc/runtime.h>
#include <Cocoa/Cocoa.h>
@ -94,39 +95,42 @@ public:
[nswindow standardWindowButton:NSWindowZoomButton].hidden = !oldZoomButtonVisible;
}
void removeWindowFrame()
void setSystemTitleBarVisible(const bool visible)
{
NSView *nsview = [nswindow contentView];
NSView * const nsview = [nswindow contentView];
Q_ASSERT(nsview);
if (!nsview) {
return;
}
nsview.wantsLayer = YES;
if (visible) {
nswindow.styleMask &= ~NSWindowStyleMaskFullSizeContentView;
} else {
nswindow.styleMask |= NSWindowStyleMaskFullSizeContentView;
nswindow.titlebarAppearsTransparent = true;
nswindow.titleVisibility = NSWindowTitleHidden;
nswindow.hasShadow = true;
nswindow.showsToolbarButton = false;
nswindow.movableByWindowBackground = false;
nswindow.movable = false;
[nswindow standardWindowButton:NSWindowCloseButton].hidden = true;
[nswindow standardWindowButton:NSWindowMiniaturizeButton].hidden = true;
[nswindow standardWindowButton:NSWindowZoomButton].hidden = true;
}
nswindow.titlebarAppearsTransparent = (visible ? NO : YES);
nswindow.titleVisibility = (visible ? NSWindowTitleVisible : NSWindowTitleHidden);
nswindow.hasShadow = YES;
nswindow.showsToolbarButton = NO;
nswindow.movableByWindowBackground = NO;
nswindow.movable = NO;
[nswindow standardWindowButton:NSWindowCloseButton].hidden = (visible ? NO : YES);
[nswindow standardWindowButton:NSWindowMiniaturizeButton].hidden = (visible ? NO : YES);
[nswindow standardWindowButton:NSWindowZoomButton].hidden = (visible ? NO : YES);
}
private:
NSWindow *nswindow;
NSWindowStyleMask oldStyleMask;
BOOL oldTitlebarAppearsTransparent;
BOOL oldHasShadow;
BOOL oldShowsToolbarButton;
BOOL oldMovableByWindowBackground;
BOOL oldMovable;
BOOL oldCloseButtonVisible;
BOOL oldMiniaturizeButtonVisible;
BOOL oldZoomButtonVisible;
NSWindowTitleVisibility oldTitleVisibility;
NSWindow *nswindow = nullptr;
NSWindowStyleMask oldStyleMask = 0;
BOOL oldTitlebarAppearsTransparent = NO;
BOOL oldHasShadow = NO;
BOOL oldShowsToolbarButton = NO;
BOOL oldMovableByWindowBackground = NO;
BOOL oldMovable = NO;
BOOL oldCloseButtonVisible = NO;
BOOL oldMiniaturizeButtonVisible = NO;
BOOL oldZoomButtonVisible = NO;
NSWindowTitleVisibility oldTitleVisibility = NSWindowTitleVisible;
};
using NSWindowProxyHash = QHash<WId, NSWindowProxy *>;
@ -153,6 +157,7 @@ static inline void mac_windowStartNativeDrag(const WId windowId, const QPoint &g
return;
}
const NSWindow * const nswindow = mac_getNSWindow(windowId);
Q_ASSERT(nswindow);
if (!nswindow) {
return;
}
@ -174,56 +179,27 @@ SystemTheme Utils::getSystemTheme()
return (shouldAppsUseDarkMode() ? SystemTheme::Dark : SystemTheme::Light);
}
void Utils::setWindowHook(const WId windowId)
void Utils::setSystemTitleBarVisible(const WId windowId, const bool visible)
{
Q_ASSERT(windowId);
if (!windowId) {
return;
}
if (g_nswindowOverrideHash()->contains(windowId)) {
return;
}
if (!g_nswindowOverrideHash()->contains(windowId)) {
NSWindow * const nswindow = mac_getNSWindow(windowId);
Q_ASSERT(nswindow);
if (!nswindow) {
return;
}
const auto proxy = new NSWindowProxy(nswindow);
g_nswindowOverrideHash()->insert(windowId, proxy);
}
void Utils::unsetWindowHook(const WId windowId)
{
Q_ASSERT(windowId);
if (!windowId) {
return;
}
if (!g_nswindowOverrideHash()->contains(windowId)) {
return;
}
const NSWindowProxy * const proxy = g_nswindowOverrideHash()->value(windowId);
g_nswindowOverrideHash()->remove(windowId);
Q_ASSERT(proxy);
if (!proxy) {
return;
}
delete proxy;
}
void Utils::removeWindowFrame(const WId windowId)
{
Q_ASSERT(windowId);
if (!windowId) {
return;
}
if (!g_nswindowOverrideHash()->contains(windowId)) {
return;
}
NSWindowProxy * const proxy = g_nswindowOverrideHash()->value(windowId);
Q_ASSERT(proxy);
if (!proxy) {
return;
}
proxy->removeWindowFrame();
proxy->setSystemTitleBarVisible(visible);
}
void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
@ -237,14 +213,19 @@ void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos)
{
Q_ASSERT(window);
if (!window) {
return;
}
if (edges == Qt::Edges{}) {
return;
}
mac_windowStartNativeDrag(window->winId(), globalPos);
Q_UNUSED(window);
Q_UNUSED(edges);
Q_UNUSED(globalPos);
}
QColor Utils::getControlsAccentColor()
{
return qt_mac_toQColor([NSColor controlAccentColor]);
}
bool Utils::isTitleBarColorized()
{
return false;
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -50,7 +50,7 @@ FramelessQuickUtils *FramelessQuickUtils::instance()
qreal FramelessQuickUtils::titleBarHeight()
{
return 30.0;
return kDefaultTitleBarHeight;
}
bool FramelessQuickUtils::frameBorderVisible()
@ -65,9 +65,9 @@ bool FramelessQuickUtils::frameBorderVisible()
qreal FramelessQuickUtils::frameBorderThickness()
{
#ifdef Q_OS_WINDOWS
return 1.0;
return kDefaultWindowFrameBorderThickness;
#else
return 0.0;
return 0;
#endif
}
@ -80,18 +80,18 @@ QColor FramelessQuickUtils::systemAccentColor()
{
#ifdef Q_OS_WINDOWS
return Utils::getDwmColorizationColor();
#else
#endif
#ifdef Q_OS_LINUX
return {};
#endif
#ifdef Q_OS_MACOS
return Utils::getControlsAccentColor();
#endif
}
bool FramelessQuickUtils::titleBarColorized()
{
#ifdef Q_OS_WINDOWS
return Utils::isTitleBarColorized();
#else
return false;
#endif
}
QColor FramelessQuickUtils::defaultSystemLightColor()

View File

@ -298,10 +298,17 @@ bool FramelessQuickWindowPrivate::eventFilter(QObject *object, QEvent *event)
const auto showEvent = static_cast<QShowEvent *>(event);
showEventHandler(showEvent);
} break;
#ifdef Q_OS_WINDOWS
case QEvent::MouseMove: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mouseMoveEventHandler(mouseEvent);
} break;
#else
case QEvent::MouseButtonPress: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mousePressEventHandler(mouseEvent);
} break;
#endif
case QEvent::MouseButtonRelease: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mouseReleaseEventHandler(mouseEvent);
@ -570,6 +577,31 @@ bool FramelessQuickWindowPrivate::shouldIgnoreMouseEvents(const QPoint &pos) con
return (isNormal() && withinFrameBorder);
}
void FramelessQuickWindowPrivate::doStartSystemMove2(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
if (m_settings.options & Option::DisableDragging) {
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPoint scenePos = event->scenePosition().toPoint();
const QPoint globalPos = event->globalPosition().toPoint();
#else
const QPoint scenePos = event->windowPos().toPoint();
const QPoint globalPos = event->screenPos().toPoint();
#endif
if (shouldIgnoreMouseEvents(scenePos)) {
return;
}
if (!isInTitleBarDraggableArea(scenePos)) {
return;
}
startSystemMove2(globalPos);
}
void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event)
{
Q_ASSERT(event);
@ -597,27 +629,28 @@ void FramelessQuickWindowPrivate::showEventHandler(QShowEvent *event)
void FramelessQuickWindowPrivate::mouseMoveEventHandler(QMouseEvent *event)
{
#ifdef Q_OS_WINDOWS
Q_ASSERT(event);
if (!event) {
return;
}
if (m_settings.options & Option::DisableDragging) {
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPoint scenePos = event->scenePosition().toPoint();
const QPoint globalPos = event->globalPosition().toPoint();
doStartSystemMove2(event);
#else
const QPoint scenePos = event->windowPos().toPoint();
const QPoint globalPos = event->screenPos().toPoint();
Q_UNUSED(event);
#endif
if (shouldIgnoreMouseEvents(scenePos)) {
}
void FramelessQuickWindowPrivate::mousePressEventHandler(QMouseEvent *event)
{
#ifdef Q_OS_WINDOWS
Q_UNUSED(event);
#else
Q_ASSERT(event);
if (!event) {
return;
}
if (!isInTitleBarDraggableArea(scenePos)) {
return;
}
startSystemMove2(globalPos);
doStartSystemMove2(event);
#endif
}
void FramelessQuickWindowPrivate::mouseReleaseEventHandler(QMouseEvent *event)

View File

@ -67,6 +67,7 @@ public:
Q_INVOKABLE void showEventHandler(QShowEvent *event);
Q_INVOKABLE void mouseMoveEventHandler(QMouseEvent *event);
Q_INVOKABLE void mousePressEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseReleaseEventHandler(QMouseEvent *event);
Q_INVOKABLE void mouseDoubleClickEventHandler(QMouseEvent *event);
@ -93,6 +94,7 @@ private:
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
Q_NODISCARD bool isInTitleBarDraggableArea(const QPoint &pos) const;
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
void doStartSystemMove2(QMouseEvent *event);
private Q_SLOTS:
void updateTopBorderColor();

View File

@ -23,7 +23,8 @@
*/
#include "quickstandardclosebutton_p.h"
#include "framelessquickutils.h"
#include <framelesswindowsmanager.h>
#include <utils.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qstylehints.h>
#include <QtQuick/private/qquickimage_p.h>
@ -51,7 +52,7 @@ QuickStandardCloseButton::~QuickStandardCloseButton() = default;
void QuickStandardCloseButton::updateForeground()
{
const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized());
const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized());
const auto url = QUrl((dark || isHovered() || isPressed()) ? kDarkUrl : kLightUrl);
initResource();
m_image->setSource(url);
@ -62,7 +63,7 @@ void QuickStandardCloseButton::updateBackground()
static constexpr const auto button = SystemButtonType::Close;
const ButtonState state = (isPressed() ? ButtonState::Pressed : ButtonState::Hovered);
const bool visible = (isHovered() || isPressed());
m_backgroundItem->setColor(FramelessQuickUtils::getSystemButtonBackgroundColor(button, state));
m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, state));
m_backgroundItem->setVisible(visible);
}
@ -87,9 +88,7 @@ void QuickStandardCloseButton::initialize()
imageAnchors->setCenterIn(m_contentItem.data());
connect(this, &QuickStandardCloseButton::hoveredChanged, this, &QuickStandardCloseButton::updateForeground);
connect(this, &QuickStandardCloseButton::pressedChanged, this, &QuickStandardCloseButton::updateForeground);
const FramelessQuickUtils * const utils = FramelessQuickUtils::instance();
connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardCloseButton::updateForeground);
connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardCloseButton::updateForeground);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardCloseButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));
QQuickPen * const border = m_backgroundItem->border();
@ -100,7 +99,7 @@ void QuickStandardCloseButton::initialize()
m_tooltip = qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(this));
m_tooltip->setText(tr("Close"));
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](const int interval){
Q_UNUSED(interval);
updateToolTip();
});

View File

@ -23,7 +23,8 @@
*/
#include "quickstandardmaximizebutton_p.h"
#include "framelessquickutils.h"
#include <framelesswindowsmanager.h>
#include <utils.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qstylehints.h>
#include <QtQuick/private/qquickimage_p.h>
@ -67,7 +68,7 @@ void QuickStandardMaximizeButton::setMaximized(const bool max)
void QuickStandardMaximizeButton::updateForeground()
{
const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized());
const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized());
const auto url = QUrl(dark ? (m_max ? kDarkRestoreUrl : kDarkMaxUrl) : (m_max ? kLightRestoreUrl : kLightMaxUrl));
initResource();
m_image->setSource(url);
@ -78,7 +79,7 @@ void QuickStandardMaximizeButton::updateBackground()
const SystemButtonType button = (m_max ? SystemButtonType::Restore : SystemButtonType::Maximize);
const ButtonState state = (isPressed() ? ButtonState::Pressed : ButtonState::Hovered);
const bool visible = (isHovered() || isPressed());
m_backgroundItem->setColor(FramelessQuickUtils::getSystemButtonBackgroundColor(button, state));
m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, state));
m_backgroundItem->setVisible(visible);
}
@ -103,9 +104,7 @@ void QuickStandardMaximizeButton::initialize()
m_image.reset(new QQuickImage(m_contentItem.data()));
const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data());
imageAnchors->setCenterIn(m_contentItem.data());
const FramelessQuickUtils * const utils = FramelessQuickUtils::instance();
connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardMaximizeButton::updateForeground);
connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardMaximizeButton::updateForeground);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardMaximizeButton::updateForeground);
connect(this, &QuickStandardMaximizeButton::maximizedChanged, this, &QuickStandardMaximizeButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));
@ -116,7 +115,7 @@ void QuickStandardMaximizeButton::initialize()
connect(this, &QuickStandardMaximizeButton::pressedChanged, this, &QuickStandardMaximizeButton::updateBackground);
m_tooltip = qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(this));
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](const int interval){
Q_UNUSED(interval);
updateToolTip();
});

View File

@ -23,7 +23,8 @@
*/
#include "quickstandardminimizebutton_p.h"
#include "framelessquickutils.h"
#include <framelesswindowsmanager.h>
#include <utils.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qstylehints.h>
#include <QtQuick/private/qquickimage_p.h>
@ -51,7 +52,7 @@ QuickStandardMinimizeButton::~QuickStandardMinimizeButton() = default;
void QuickStandardMinimizeButton::updateForeground()
{
const bool dark = (FramelessQuickUtils::darkModeEnabled() || FramelessQuickUtils::titleBarColorized());
const bool dark = (Utils::shouldAppsUseDarkMode() || Utils::isTitleBarColorized());
const auto url = QUrl(dark ? kDarkUrl : kLightUrl);
initResource();
m_image->setSource(url);
@ -62,7 +63,7 @@ void QuickStandardMinimizeButton::updateBackground()
static constexpr const auto button = SystemButtonType::Minimize;
const ButtonState state = (isPressed() ? ButtonState::Pressed : ButtonState::Hovered);
const bool visible = (isHovered() || isPressed());
m_backgroundItem->setColor(FramelessQuickUtils::getSystemButtonBackgroundColor(button, state));
m_backgroundItem->setColor(Utils::calculateSystemButtonBackgroundColor(button, state));
m_backgroundItem->setVisible(visible);
}
@ -85,9 +86,7 @@ void QuickStandardMinimizeButton::initialize()
m_image.reset(new QQuickImage(m_contentItem.data()));
const auto imageAnchors = new QQuickAnchors(m_image.data(), m_image.data());
imageAnchors->setCenterIn(m_contentItem.data());
const FramelessQuickUtils * const utils = FramelessQuickUtils::instance();
connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardMinimizeButton::updateForeground);
connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardMinimizeButton::updateForeground);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardMinimizeButton::updateForeground);
m_backgroundItem.reset(new QQuickRectangle(this));
QQuickPen * const border = m_backgroundItem->border();
@ -98,7 +97,7 @@ void QuickStandardMinimizeButton::initialize()
m_tooltip = qobject_cast<QQuickToolTipAttached *>(qmlAttachedPropertiesObject<QQuickToolTip>(this));
m_tooltip->setText(tr("Minimize"));
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](int interval){
connect(QGuiApplication::styleHints(), &QStyleHints::mousePressAndHoldIntervalChanged, this, [this](const int interval){
Q_UNUSED(interval);
updateToolTip();
});

View File

@ -26,7 +26,8 @@
#include "quickstandardminimizebutton_p.h"
#include "quickstandardmaximizebutton_p.h"
#include "quickstandardclosebutton_p.h"
#include "framelessquickutils.h"
#include <framelesswindowsmanager.h>
#include <utils.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickanchors_p.h>
#include <QtQuick/private/qquickanchors_p_p.h>
@ -140,11 +141,16 @@ void QuickStandardTitleBar::updateTitleBarColor()
QColor backgroundColor = {};
QColor foregroundColor = {};
if (m_active) {
if (FramelessQuickUtils::titleBarColorized()) {
backgroundColor = FramelessQuickUtils::systemAccentColor();
if (Utils::isTitleBarColorized()) {
#ifdef Q_OS_WINDOWS
backgroundColor = Utils::getDwmColorizationColor();
#endif
#ifdef Q_OS_MACOS
backgroundColor = Utils::getControlsAccentColor();
#endif
foregroundColor = kDefaultWhiteColor;
} else {
if (FramelessQuickUtils::darkModeEnabled()) {
if (Utils::shouldAppsUseDarkMode()) {
backgroundColor = kDefaultBlackColor;
foregroundColor = kDefaultWhiteColor;
} else {
@ -153,8 +159,8 @@ void QuickStandardTitleBar::updateTitleBarColor()
}
}
} else {
if (FramelessQuickUtils::darkModeEnabled()) {
backgroundColor = FramelessQuickUtils::defaultSystemDarkColor();
if (Utils::shouldAppsUseDarkMode()) {
backgroundColor = kDefaultSystemDarkColor;
} else {
backgroundColor = kDefaultWhiteColor;
}
@ -169,7 +175,7 @@ void QuickStandardTitleBar::initialize()
QQuickPen * const _border = border();
_border->setWidth(0.0);
_border->setColor(kDefaultTransparentColor);
setHeight(FramelessQuickUtils::titleBarHeight());
setHeight(kDefaultTitleBarHeight);
m_label.reset(new QQuickLabel(this));
QFont f = m_label->font();
@ -185,10 +191,7 @@ void QuickStandardTitleBar::initialize()
m_maxBtn.reset(new QuickStandardMaximizeButton(m_row.data()));
m_closeBtn.reset(new QuickStandardCloseButton(m_row.data()));
const FramelessQuickUtils * const utils = FramelessQuickUtils::instance();
connect(utils, &FramelessQuickUtils::darkModeEnabledChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(utils, &FramelessQuickUtils::systemAccentColorChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(utils, &FramelessQuickUtils::titleBarColorizedChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(FramelessWindowsManager::instance(), &FramelessWindowsManager::systemThemeChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(this, &QuickStandardTitleBar::activeChanged, this, &QuickStandardTitleBar::updateTitleBarColor);
connect(m_label.data(), &QQuickLabel::textChanged, this, &QuickStandardTitleBar::titleChanged);
connect(m_maxBtn.data(), &QuickStandardMaximizeButton::maximizedChanged, this, &QuickStandardTitleBar::maximizedChanged);

View File

@ -267,27 +267,28 @@ void FramelessWidgetsHelper::paintEventHandler(QPaintEvent *event)
void FramelessWidgetsHelper::mouseMoveEventHandler(QMouseEvent *event)
{
#ifdef Q_OS_WINDOWS
Q_ASSERT(event);
if (!event) {
return;
}
if (m_settings.options & Option::DisableDragging) {
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPoint scenePos = event->scenePosition().toPoint();
const QPoint globalPos = event->globalPosition().toPoint();
doStartSystemMove2(event);
#else
const QPoint scenePos = event->windowPos().toPoint();
const QPoint globalPos = event->screenPos().toPoint();
Q_UNUSED(event);
#endif
if (shouldIgnoreMouseEvents(scenePos)) {
}
void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
{
#ifdef Q_OS_WINDOWS
Q_UNUSED(event);
#else
Q_ASSERT(event);
if (!event) {
return;
}
if (!isInTitleBarDraggableArea(scenePos)) {
return;
}
startSystemMove2(globalPos);
doStartSystemMove2(event);
#endif
}
void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
@ -661,6 +662,31 @@ bool FramelessWidgetsHelper::shouldIgnoreMouseEvents(const QPoint &pos) const
return (isNormal() && withinFrameBorder);
}
void FramelessWidgetsHelper::doStartSystemMove2(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
if (m_settings.options & Option::DisableDragging) {
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
const QPoint scenePos = event->scenePosition().toPoint();
const QPoint globalPos = event->globalPosition().toPoint();
#else
const QPoint scenePos = event->windowPos().toPoint();
const QPoint globalPos = event->screenPos().toPoint();
#endif
if (shouldIgnoreMouseEvents(scenePos)) {
return;
}
if (!isInTitleBarDraggableArea(scenePos)) {
return;
}
startSystemMove2(globalPos);
}
void FramelessWidgetsHelper::updateContentsMargins()
{
#ifdef Q_OS_WINDOWS
@ -810,10 +836,17 @@ bool FramelessWidgetsHelper::eventFilter(QObject *object, QEvent *event)
const auto paintEvent = static_cast<QPaintEvent *>(event);
paintEventHandler(paintEvent);
} break;
#ifdef Q_OS_WINDOWS
case QEvent::MouseMove: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mouseMoveEventHandler(mouseEvent);
} break;
#else
case QEvent::MouseButtonPress: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mousePressEventHandler(mouseEvent);
} break;
#endif
case QEvent::MouseButtonRelease: {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mouseReleaseEventHandler(mouseEvent);