forked from github_mirror/framelesshelper
linux: further improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
840cf3060d
commit
a381836ef7
|
@ -129,9 +129,51 @@ using xcb_client_message_event_t = struct xcb_client_message_event_t
|
||||||
xcb_client_message_data_t data;
|
xcb_client_message_data_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using xcb_get_property_reply_t = struct xcb_get_property_reply_t
|
||||||
|
{
|
||||||
|
uint8_t response_type;
|
||||||
|
uint8_t format;
|
||||||
|
uint16_t sequence;
|
||||||
|
uint32_t length;
|
||||||
|
xcb_atom_t type;
|
||||||
|
uint32_t bytes_after;
|
||||||
|
uint32_t value_len;
|
||||||
|
uint8_t pad0[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
using xcb_get_property_cookie_t = struct xcb_get_property_cookie_t
|
||||||
|
{
|
||||||
|
unsigned int sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
using xcb_list_properties_cookie_t = struct xcb_list_properties_cookie_t
|
||||||
|
{
|
||||||
|
unsigned int sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
using xcb_list_properties_reply_t = struct xcb_list_properties_reply_t
|
||||||
|
{
|
||||||
|
uint8_t response_type;
|
||||||
|
uint8_t pad0;
|
||||||
|
uint16_t sequence;
|
||||||
|
uint32_t length;
|
||||||
|
uint16_t atoms_len;
|
||||||
|
uint8_t pad1[22];
|
||||||
|
};
|
||||||
|
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_NONE = 0;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_WINDOW_NONE = 0;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_CURRENT_TIME = 0;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_PROP_MODE_REPLACE = 0;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_ATOM_ATOM = 4;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_ATOM_CARDINAL = 6;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_ATOM_WINDOW = 33;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_ANY = 0;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_1 = 1;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_2 = 2;
|
||||||
|
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_3 = 3;
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_RELEASE = 5;
|
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_RELEASE = 5;
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_CLIENT_MESSAGE = 33;
|
[[maybe_unused]] inline constexpr const auto XCB_CLIENT_MESSAGE = 33;
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_1 = 1;
|
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_STRUCTURE_NOTIFY = 131072;
|
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_STRUCTURE_NOTIFY = 131072;
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT = 1048576;
|
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT = 1048576;
|
||||||
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 524288;
|
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 524288;
|
||||||
|
@ -149,7 +191,18 @@ using xcb_client_message_event_t = struct xcb_client_message_event_t
|
||||||
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_MOVE_KEYBOARD = 10;
|
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_MOVE_KEYBOARD = 10;
|
||||||
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_CANCEL = 11;
|
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_CANCEL = 11;
|
||||||
|
|
||||||
[[maybe_unused]] inline constexpr const char _NET_WM_MOVERESIZE_ATOM_NAME[] = "_NET_WM_MOVERESIZE";
|
[[maybe_unused]] inline constexpr const char ATOM_NET_SUPPORTED[] = "_NET_SUPPORTED";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_NAME[] = "_NET_WM_NAME";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_MOVERESIZE[] = "_NET_WM_MOVERESIZE";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_SUPPORTING_WM_CHECK[] = "_NET_SUPPORTING_WM_CHECK";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_KDE_COMPOSITE_TOGGLING[] = "_NET_KDE_COMPOSITE_TOGGLING";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_KDE_NET_WM_BLUR_BEHIND_REGION[] = "_KDE_NET_WM_BLUR_BEHIND_REGION";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_GTK_SHOW_WINDOW_MENU[] = "_GTK_SHOW_WINDOW_MENU";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_DEEPIN_NO_TITLEBAR[] = "_DEEPIN_NO_TITLEBAR";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_DEEPIN_FORCE_DECORATE[] = "_DEEPIN_FORCE_DECORATE";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_DEEPIN_BLUR_REGION_MASK[] = "_NET_WM_DEEPIN_BLUR_REGION_MASK";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_DEEPIN_BLUR_REGION_ROUNDED[] = "_NET_WM_DEEPIN_BLUR_REGION_ROUNDED";
|
||||||
|
[[maybe_unused]] inline constexpr const char ATOM_UTF8_STRING[] = "UTF8_STRING";
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -189,6 +242,87 @@ xcb_ungrab_pointer(
|
||||||
xcb_timestamp_t time
|
xcb_timestamp_t time
|
||||||
);
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
|
||||||
|
xcb_change_property(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t mode,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint8_t format,
|
||||||
|
uint32_t data_len,
|
||||||
|
const void *data
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
|
||||||
|
xcb_delete_property_checked(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_get_property_cookie_t
|
||||||
|
xcb_get_property(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t _delete,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint32_t long_offset,
|
||||||
|
uint32_t long_length
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_get_property_reply_t *
|
||||||
|
xcb_get_property_reply(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_get_property_cookie_t cookie,
|
||||||
|
xcb_generic_error_t **error
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API void *
|
||||||
|
xcb_get_property_value(
|
||||||
|
const xcb_get_property_reply_t *reply
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API int
|
||||||
|
xcb_get_property_value_length(
|
||||||
|
const xcb_get_property_reply_t *reply
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_list_properties_cookie_t
|
||||||
|
xcb_list_properties(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_window_t window
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_list_properties_reply_t *
|
||||||
|
xcb_list_properties_reply(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_list_properties_cookie_t cookie,
|
||||||
|
xcb_generic_error_t **error
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API int
|
||||||
|
xcb_list_properties_atoms_length(
|
||||||
|
const xcb_list_properties_reply_t *atom
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_atom_t *
|
||||||
|
xcb_list_properties_atoms(
|
||||||
|
const xcb_list_properties_reply_t *atom
|
||||||
|
);
|
||||||
|
|
||||||
|
FRAMELESSHELPER_CORE_API xcb_get_property_cookie_t
|
||||||
|
xcb_get_property_unchecked(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t _delete,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint32_t long_offset,
|
||||||
|
uint32_t long_length
|
||||||
|
);
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "framelesshelpercore_global.h"
|
#include "framelesshelpercore_global.h"
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
# include "framelesshelper_linux.h"
|
||||||
|
#endif // Q_OS_LINUX
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
@ -139,8 +142,37 @@ FRAMELESSHELPER_CORE_API void bringWindowToFront(const WId windowId);
|
||||||
#endif // Q_OS_WINDOWS
|
#endif // Q_OS_WINDOWS
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QScreen *x11_findScreenForVirtualDesktop
|
||||||
|
(const int virtualDesktopNumber);
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API unsigned long x11_appRootWindow(const int screen);
|
||||||
|
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 x11_appRootWindow(const int screen);
|
||||||
|
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API int x11_appScreen();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 x11_appTime();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 x11_appUserTime();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 x11_getTimestamp();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QByteArray x11_nextStartupId();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API Display *x11_display();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API xcb_connection_t *x11_connection();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QByteArray getWindowProperty
|
||||||
|
(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const quint32 data_len);
|
||||||
|
FRAMELESSHELPER_CORE_API void setWindowProperty
|
||||||
|
(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type,
|
||||||
|
const void *data, const quint32 data_len = 1, const uint8_t format = 8);
|
||||||
|
FRAMELESSHELPER_CORE_API void clearWindowProperty(const WId windowId, const xcb_atom_t prop);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API xcb_atom_t internAtom(const char *name);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QString getWindowManagerName();
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isSupportedByWindowManager(const xcb_atom_t atom);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isSupportedByRootWindow(const xcb_atom_t atom);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool tryHideSystemTitleBar(const WId windowId, const bool hide = true);
|
||||||
|
FRAMELESSHELPER_CORE_API void openSystemMenu(const WId windowId, const QPoint &globalPos);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_linux();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_linux();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getWmThemeColor();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getWmThemeColor();
|
||||||
|
FRAMELESSHELPER_CORE_API void sendMoveResizeMessage
|
||||||
|
(const WId windowId, const uint32_t action, const QPoint &globalPos, const Qt::MouseButton button = Qt::LeftButton);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isCustomDecorationSupported();
|
||||||
#endif // Q_OS_LINUX
|
#endif // Q_OS_LINUX
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
|
|
|
@ -91,24 +91,28 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms)
|
||||||
const auto shouldApplyFramelessFlag = [¶ms]() -> bool {
|
const auto shouldApplyFramelessFlag = [¶ms]() -> bool {
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
const auto widget = params.getWidgetHandle();
|
const auto widget = params.getWidgetHandle();
|
||||||
if (!(widget && widget->isWidgetType())) {
|
return (widget && widget->isWidgetType());
|
||||||
return false;
|
#elif defined(Q_OS_LINUX)
|
||||||
}
|
Q_UNUSED(params);
|
||||||
#else
|
return !Utils::isCustomDecorationSupported();
|
||||||
|
#else // Windows
|
||||||
Q_UNUSED(params);
|
Q_UNUSED(params);
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
|
#endif // Q_OS_MACOS
|
||||||
}();
|
}();
|
||||||
|
#if (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
||||||
|
window->setProperty("_q_mac_wantsLayer", 1);
|
||||||
|
#endif // (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
||||||
if (shouldApplyFramelessFlag) {
|
if (shouldApplyFramelessFlag) {
|
||||||
params.setWindowFlags(params.getWindowFlags() | Qt::FramelessWindowHint);
|
params.setWindowFlags(params.getWindowFlags() | Qt::FramelessWindowHint);
|
||||||
|
} else {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
Q_UNUSED(Utils::tryHideSystemTitleBar(windowId, true));
|
||||||
|
#elif defined(Q_OS_MACOS)
|
||||||
|
Utils::setSystemTitleBarVisible(windowId, false);
|
||||||
|
#endif // Q_OS_LINUX
|
||||||
}
|
}
|
||||||
window->installEventFilter(data.eventFilter);
|
window->installEventFilter(data.eventFilter);
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
# if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
window->setProperty("_q_mac_wantsLayer", 1);
|
|
||||||
# endif
|
|
||||||
Utils::setSystemTitleBarVisible(windowId, false);
|
|
||||||
#endif
|
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware();
|
FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,10 +167,6 @@ void initialize()
|
||||||
|
|
||||||
outputLogo();
|
outputLogo();
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
gtk_init(nullptr, nullptr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// Qt's Wayland experience is not good, so we force the XCB backend here.
|
// Qt's Wayland experience is not good, so we force the XCB backend here.
|
||||||
// TODO: Remove this hack once Qt's Wayland implementation is good enough.
|
// TODO: Remove this hack once Qt's Wayland implementation is good enough.
|
||||||
|
@ -178,6 +174,7 @@ void initialize()
|
||||||
// enough, that is, before the construction of any Q(Gui)Application
|
// enough, that is, before the construction of any Q(Gui)Application
|
||||||
// instances. QCoreApplication won't instantiate the platform plugin.
|
// instances. QCoreApplication won't instantiate the platform plugin.
|
||||||
qputenv(QT_QPA_ENV_VAR, kxcb);
|
qputenv(QT_QPA_ENV_VAR, kxcb);
|
||||||
|
gtk_init(nullptr, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
#if (defined(Q_OS_MACOS) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)))
|
||||||
|
|
|
@ -52,6 +52,17 @@ FRAMELESSHELPER_STRING_CONSTANT(xcb_flush)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom)
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom_reply)
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom_reply)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(xcb_ungrab_pointer)
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_ungrab_pointer)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_change_property)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_delete_property_checked)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_get_property)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_get_property_reply)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_get_property_value)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_get_property_value_length)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_list_properties)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_list_properties_reply)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_list_properties_atoms_length)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_list_properties_atoms)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(xcb_get_property_unchecked)
|
||||||
|
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(gtk_init)
|
FRAMELESSHELPER_STRING_CONSTANT(gtk_init)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(g_value_init)
|
FRAMELESSHELPER_STRING_CONSTANT(g_value_init)
|
||||||
|
@ -134,6 +145,156 @@ xcb_ungrab_pointer(
|
||||||
return API_CALL_FUNCTION(xcb_ungrab_pointer, connection, time);
|
return API_CALL_FUNCTION(xcb_ungrab_pointer, connection, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_void_cookie_t
|
||||||
|
xcb_change_property(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t mode,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint8_t format,
|
||||||
|
uint32_t data_len,
|
||||||
|
const void *data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_change_property)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_change_property, connection,
|
||||||
|
mode, window, property, type, format, data_len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_void_cookie_t
|
||||||
|
xcb_delete_property_checked(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_delete_property_checked)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_delete_property_checked, connection, window, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_get_property_cookie_t
|
||||||
|
xcb_get_property(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t _delete,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint32_t long_offset,
|
||||||
|
uint32_t long_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_get_property)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_get_property, connection,
|
||||||
|
_delete, window, property, type, long_offset, long_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_get_property_reply_t *
|
||||||
|
xcb_get_property_reply(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_get_property_cookie_t cookie,
|
||||||
|
xcb_generic_error_t **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_get_property_reply)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_get_property_reply, connection, cookie, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void *
|
||||||
|
xcb_get_property_value(
|
||||||
|
const xcb_get_property_reply_t *reply
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_get_property_value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_get_property_value, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
xcb_get_property_value_length(
|
||||||
|
const xcb_get_property_reply_t *reply
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_get_property_value_length)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_get_property_value_length, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_list_properties_cookie_t
|
||||||
|
xcb_list_properties(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_window_t window
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_list_properties)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_list_properties, connection, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_list_properties_reply_t *
|
||||||
|
xcb_list_properties_reply(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
xcb_list_properties_cookie_t cookie,
|
||||||
|
xcb_generic_error_t **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_list_properties_reply)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_list_properties_reply, connection, cookie, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
xcb_list_properties_atoms_length(
|
||||||
|
const xcb_list_properties_reply_t *atom
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_list_properties_atoms_length)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_list_properties_atoms_length, atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_atom_t *
|
||||||
|
xcb_list_properties_atoms(
|
||||||
|
const xcb_list_properties_reply_t *atom
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_list_properties_atoms)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_list_properties_atoms, atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" xcb_get_property_cookie_t
|
||||||
|
xcb_get_property_unchecked(
|
||||||
|
xcb_connection_t *connection,
|
||||||
|
uint8_t _delete,
|
||||||
|
xcb_window_t window,
|
||||||
|
xcb_atom_t property,
|
||||||
|
xcb_atom_t type,
|
||||||
|
uint32_t long_offset,
|
||||||
|
uint32_t long_length
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!API_XCB_AVAILABLE(xcb_get_property_unchecked)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return API_CALL_FUNCTION(xcb_get_property_unchecked, connection,
|
||||||
|
_delete, window, property, type, long_offset, long_length);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
// GTK
|
// GTK
|
||||||
|
|
||||||
|
|
|
@ -73,11 +73,14 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(startupid)
|
||||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT(display)
|
FRAMELESSHELPER_BYTEARRAY_CONSTANT(display)
|
||||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
|
|
||||||
|
static constexpr const auto _XCB_SEND_EVENT_MASK =
|
||||||
|
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline int
|
[[maybe_unused]] [[nodiscard]] static inline int
|
||||||
qtEdgesToWmMoveOrResizeOperation(const Qt::Edges edges)
|
qtEdgesToWmMoveOrResizeOperation(const Qt::Edges edges)
|
||||||
{
|
{
|
||||||
if (edges == Qt::Edges{}) {
|
if (edges == Qt::Edges{}) {
|
||||||
return -1;
|
return _NET_WM_MOVERESIZE_CANCEL;
|
||||||
}
|
}
|
||||||
if (edges & Qt::TopEdge) {
|
if (edges & Qt::TopEdge) {
|
||||||
if (edges & Qt::LeftEdge) {
|
if (edges & Qt::LeftEdge) {
|
||||||
|
@ -103,11 +106,10 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
if (edges & Qt::RightEdge) {
|
if (edges & Qt::RightEdge) {
|
||||||
return _NET_WM_MOVERESIZE_SIZE_RIGHT;
|
return _NET_WM_MOVERESIZE_SIZE_RIGHT;
|
||||||
}
|
}
|
||||||
return -1;
|
return _NET_WM_MOVERESIZE_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline
|
QScreen *Utils::x11_findScreenForVirtualDesktop(const int virtualDesktopNumber)
|
||||||
QScreen *x11_findScreenForVirtualDesktop(const int virtualDesktopNumber)
|
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
Q_UNUSED(virtualDesktopNumber);
|
Q_UNUSED(virtualDesktopNumber);
|
||||||
|
@ -137,11 +139,9 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
[[maybe_unused]] [[nodiscard]] static inline
|
unsigned long Utils::x11_appRootWindow(const int screen)
|
||||||
unsigned long x11_appRootWindow(const int screen)
|
|
||||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
[[maybe_unused]] [[nodiscard]] static inline
|
quint32 Utils::x11_appRootWindow(const int screen)
|
||||||
quint32 x11_appRootWindow(const int screen)
|
|
||||||
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
|
@ -163,7 +163,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline int x11_appScreen()
|
int Utils::x11_appScreen()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -179,7 +179,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_appTime()
|
quint32 Utils::x11_appTime()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -199,7 +199,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_appUserTime()
|
quint32 Utils::x11_appUserTime()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -219,7 +219,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline quint32 x11_getTimestamp()
|
quint32 Utils::x11_getTimestamp()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -239,7 +239,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline QByteArray x11_nextStartupId()
|
QByteArray Utils::x11_nextStartupId()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return {};
|
return {};
|
||||||
|
@ -255,7 +255,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline Display *x11_display()
|
Display *Utils::x11_display()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -280,7 +280,7 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] [[nodiscard]] static inline xcb_connection_t *x11_connection()
|
xcb_connection_t *Utils::x11_connection()
|
||||||
{
|
{
|
||||||
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifdef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -305,87 +305,6 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
emulateMouseButtonRelease(const WId windowId, const QPoint &globalPos, const QPoint &localPos)
|
|
||||||
{
|
|
||||||
Q_ASSERT(windowId);
|
|
||||||
if (!windowId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xcb_connection_t * const connection = x11_connection();
|
|
||||||
Q_ASSERT(connection);
|
|
||||||
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
|
||||||
Q_ASSERT(rootWindow);
|
|
||||||
xcb_button_release_event_t xev;
|
|
||||||
memset(&xev, 0, sizeof(xev));
|
|
||||||
xev.response_type = XCB_BUTTON_RELEASE;
|
|
||||||
xev.time = x11_appTime();
|
|
||||||
xev.root = rootWindow;
|
|
||||||
xev.root_x = globalPos.x();
|
|
||||||
xev.root_y = globalPos.y();
|
|
||||||
xev.event = windowId;
|
|
||||||
xev.event_x = localPos.x();
|
|
||||||
xev.event_y = localPos.y();
|
|
||||||
xev.same_screen = true;
|
|
||||||
xcb_send_event(connection, false, rootWindow, XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
|
||||||
reinterpret_cast<const char *>(&xev));
|
|
||||||
xcb_flush(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]] static inline void
|
|
||||||
doStartSystemMoveResize(const WId windowId, const QPoint &globalPos, const int edges)
|
|
||||||
{
|
|
||||||
Q_ASSERT(windowId);
|
|
||||||
Q_ASSERT(edges >= 0);
|
|
||||||
if (!windowId || (edges < 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xcb_connection_t * const connection = x11_connection();
|
|
||||||
Q_ASSERT(connection);
|
|
||||||
static const auto netMoveResize = [connection]() -> xcb_atom_t {
|
|
||||||
const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false,
|
|
||||||
qstrlen(_NET_WM_MOVERESIZE_ATOM_NAME), _NET_WM_MOVERESIZE_ATOM_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 = x11_appRootWindow(x11_appScreen());
|
|
||||||
Q_ASSERT(rootWindow);
|
|
||||||
xcb_client_message_event_t xev;
|
|
||||||
memset(&xev, 0, sizeof(xev));
|
|
||||||
xev.response_type = XCB_CLIENT_MESSAGE;
|
|
||||||
xev.type = netMoveResize;
|
|
||||||
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;
|
|
||||||
// First we need to ungrab the pointer that may have been
|
|
||||||
// automatically grabbed by Qt on ButtonPressEvent.
|
|
||||||
xcb_ungrab_pointer(connection, x11_appTime());
|
|
||||||
xcb_send_event(connection, false, rootWindow,
|
|
||||||
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY),
|
|
||||||
reinterpret_cast<const char *>(&xev));
|
|
||||||
xcb_flush(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]] static inline void
|
|
||||||
sendMouseReleaseEvent(QWindow *window, const QPoint &globalPos)
|
|
||||||
{
|
|
||||||
Q_ASSERT(window);
|
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
|
|
||||||
const QPoint logicalLocalPos = window->mapFromGlobal(globalPos);
|
|
||||||
const QPoint nativeLocalPos = Utils::toNativePixels(window, logicalLocalPos);
|
|
||||||
emulateMouseButtonRelease(window->winId(), nativeGlobalPos, nativeLocalPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemTheme Utils::getSystemTheme()
|
SystemTheme Utils::getSystemTheme()
|
||||||
{
|
{
|
||||||
// ### TODO: how to detect high contrast mode on Linux?
|
// ### TODO: how to detect high contrast mode on Linux?
|
||||||
|
@ -398,18 +317,13 @@ void Utils::startSystemMove(QWindow *window, const QPoint &globalPos)
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
|
|
||||||
// Before we start the dragging we need to tell Qt that the mouse is released.
|
|
||||||
sendMouseReleaseEvent(window, globalPos);
|
|
||||||
#else
|
|
||||||
Q_UNUSED(globalPos);
|
|
||||||
#endif
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
|
Q_UNUSED(globalPos);
|
||||||
window->startSystemMove();
|
window->startSystemMove();
|
||||||
#else
|
#else // (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
||||||
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
|
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
|
||||||
doStartSystemMoveResize(window->winId(), nativeGlobalPos, _NET_WM_MOVERESIZE_MOVE);
|
sendMoveResizeMessage(window->winId(), _NET_WM_MOVERESIZE_MOVE, nativeGlobalPos);
|
||||||
#endif
|
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos)
|
void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoint &globalPos)
|
||||||
|
@ -421,22 +335,14 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges, const QPoi
|
||||||
if (edges == Qt::Edges{}) {
|
if (edges == Qt::Edges{}) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
|
|
||||||
// Before we start the resizing we need to tell Qt that the mouse is released.
|
|
||||||
sendMouseReleaseEvent(window, globalPos);
|
|
||||||
#else
|
|
||||||
Q_UNUSED(globalPos);
|
|
||||||
#endif
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
|
Q_UNUSED(globalPos);
|
||||||
window->startSystemResize(edges);
|
window->startSystemResize(edges);
|
||||||
#else
|
#else // (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
||||||
const int section = qtEdgesToWmMoveOrResizeOperation(edges);
|
|
||||||
if (section < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
|
const QPoint nativeGlobalPos = Utils::toNativePixels(window, globalPos);
|
||||||
doStartSystemMoveResize(window->winId(), nativeGlobalPos, section);
|
const int netWmOperation = qtEdgesToWmMoveOrResizeOperation(edges);
|
||||||
#endif
|
sendMoveResizeMessage(window->winId(), netWmOperation, nativeGlobalPos);
|
||||||
|
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Utils::isTitleBarColorized()
|
bool Utils::isTitleBarColorized()
|
||||||
|
@ -496,10 +402,34 @@ bool Utils::shouldAppsUseDarkMode_linux()
|
||||||
|
|
||||||
bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, const QColor &color)
|
bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, const QColor &color)
|
||||||
{
|
{
|
||||||
Q_UNUSED(windowId);
|
|
||||||
Q_UNUSED(mode);
|
|
||||||
Q_UNUSED(color);
|
Q_UNUSED(color);
|
||||||
return false;
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_KDE_NET_WM_BLUR_BEHIND_REGION);
|
||||||
|
if ((atom == XCB_NONE) || !isSupportedByRootWindow(atom)) {
|
||||||
|
WARNING << "Current window manager doesn't support blur behind window.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static const xcb_atom_t deepinAtom = internAtom(ATOM_NET_WM_DEEPIN_BLUR_REGION_MASK);
|
||||||
|
if (deepinAtom != XCB_NONE) {
|
||||||
|
clearWindowProperty(windowId, deepinAtom);
|
||||||
|
}
|
||||||
|
const auto blurMode = [mode]() -> BlurMode {
|
||||||
|
if ((mode == BlurMode::Disable) || (mode == BlurMode::Default)) {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
WARNING << "The BlurMode::Windows_* enum values are not supported on Linux.";
|
||||||
|
return BlurMode::Default;
|
||||||
|
}();
|
||||||
|
if (blurMode == BlurMode::Disable) {
|
||||||
|
clearWindowProperty(windowId, atom);
|
||||||
|
} else {
|
||||||
|
const quint32 value = true;
|
||||||
|
setWindowProperty(windowId, atom, XCB_ATOM_CARDINAL, &value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Utils::getWallpaperFilePath()
|
QString Utils::getWallpaperFilePath()
|
||||||
|
@ -520,7 +450,18 @@ bool Utils::isBlurBehindWindowSupported()
|
||||||
if (FramelessConfig::instance()->isSet(Option::ForceNonNativeBackgroundBlur)) {
|
if (FramelessConfig::instance()->isSet(Option::ForceNonNativeBackgroundBlur)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Currently not supported due to the desktop environments vary too much.
|
return false; // FIXME: check what's wrong.
|
||||||
|
static const QString windowManager = getWindowManagerName();
|
||||||
|
static const bool isDeepinV15 = (windowManager == FRAMELESSHELPER_STRING_LITERAL("Mutter(DeepinGala)"));
|
||||||
|
if (isDeepinV15) {
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_NET_WM_DEEPIN_BLUR_REGION_ROUNDED);
|
||||||
|
return ((atom != XCB_NONE) && isSupportedByWindowManager(atom));
|
||||||
|
}
|
||||||
|
static const bool isKWin = (windowManager == FRAMELESSHELPER_STRING_LITERAL("KWin"));
|
||||||
|
if (isKWin) {
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_KDE_NET_WM_BLUR_BEHIND_REGION);
|
||||||
|
return ((atom != XCB_NONE) && isSupportedByRootWindow(atom));
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
return result;
|
return result;
|
||||||
|
@ -552,4 +493,349 @@ QColor Utils::getFrameBorderColor(const bool active)
|
||||||
return (active ? getWmThemeColor() : kDefaultDarkGrayColor);
|
return (active ? getWmThemeColor() : kDefaultDarkGrayColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_atom_t Utils::internAtom(const char *name)
|
||||||
|
{
|
||||||
|
Q_ASSERT(name);
|
||||||
|
Q_ASSERT(*name != '\0');
|
||||||
|
if (!name || (*name == '\0')) {
|
||||||
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false, qstrlen(name), name);
|
||||||
|
xcb_intern_atom_reply_t * const reply = xcb_intern_atom_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
const xcb_atom_t atom = reply->atom;
|
||||||
|
std::free(reply);
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Utils::getWindowManagerName()
|
||||||
|
{
|
||||||
|
static const auto result = []() -> QString {
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
|
Q_ASSERT(rootWindow);
|
||||||
|
if (!rootWindow) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
static const xcb_atom_t wmCheckAtom = internAtom(ATOM_NET_SUPPORTING_WM_CHECK);
|
||||||
|
if (wmCheckAtom == XCB_NONE) {
|
||||||
|
WARNING << "Failed to retrieve the atom of _NET_SUPPORTING_WM_CHECK.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(connection, false, rootWindow, wmCheckAtom, XCB_ATOM_WINDOW, 0, 1024);
|
||||||
|
xcb_get_property_reply_t * const reply = xcb_get_property_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!((reply->format == 32) && (reply->type == XCB_ATOM_WINDOW))) {
|
||||||
|
std::free(reply);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto windowManager = *static_cast<xcb_window_t *>(xcb_get_property_value(reply));
|
||||||
|
if (windowManager == XCB_WINDOW_NONE) {
|
||||||
|
std::free(reply);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
static const xcb_atom_t wmNameAtom = internAtom(ATOM_NET_WM_NAME);
|
||||||
|
if (wmNameAtom == XCB_NONE) {
|
||||||
|
WARNING << "Failed to retrieve the atom of _NET_WM_NAME.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
static const xcb_atom_t strAtom = internAtom(ATOM_UTF8_STRING);
|
||||||
|
if (strAtom == XCB_NONE) {
|
||||||
|
WARNING << "Failed to retrieve the atom of UTF8_STRING.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const xcb_get_property_cookie_t wmCookie = xcb_get_property_unchecked(connection, false, windowManager, wmNameAtom, strAtom, 0, 1024);
|
||||||
|
xcb_get_property_reply_t * const wmReply = xcb_get_property_reply(connection, wmCookie, nullptr);
|
||||||
|
if (!wmReply) {
|
||||||
|
std::free(reply);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!((wmReply->format == 8) && (wmReply->type == strAtom))) {
|
||||||
|
std::free(wmReply);
|
||||||
|
std::free(reply);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto data = static_cast<const char *>(xcb_get_property_value(wmReply));
|
||||||
|
const int len = xcb_get_property_value_length(wmReply);
|
||||||
|
const QString wmName = QString::fromUtf8(data, len);
|
||||||
|
std::free(wmReply);
|
||||||
|
std::free(reply);
|
||||||
|
return wmName;
|
||||||
|
}();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Utils::openSystemMenu(const WId windowId, const QPoint &globalPos)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
|
Q_ASSERT(rootWindow);
|
||||||
|
if (!rootWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_GTK_SHOW_WINDOW_MENU);
|
||||||
|
if ((atom == XCB_NONE) || !isSupportedByWindowManager(atom)) {
|
||||||
|
WARNING << "Current window manager doesn't support showing window menu.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_client_message_event_t xev;
|
||||||
|
memset(&xev, 0, sizeof(xev));
|
||||||
|
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
xev.type = atom;
|
||||||
|
xev.window = windowId;
|
||||||
|
xev.format = 32;
|
||||||
|
xev.data.data32[1] = globalPos.x();
|
||||||
|
xev.data.data32[2] = globalPos.y();
|
||||||
|
|
||||||
|
xcb_ungrab_pointer(connection, XCB_CURRENT_TIME);
|
||||||
|
xcb_send_event(connection, false, rootWindow, _XCB_SEND_EVENT_MASK, reinterpret_cast<const char *>(&xev));
|
||||||
|
xcb_flush(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Utils::getWindowProperty(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const quint32 data_len)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
Q_ASSERT(prop != XCB_NONE);
|
||||||
|
Q_ASSERT(type != XCB_NONE);
|
||||||
|
if (!windowId || (prop == XCB_NONE) || (type == XCB_NONE)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const xcb_get_property_cookie_t cookie = xcb_get_property(connection, false, windowId, prop, type, 0, data_len);
|
||||||
|
xcb_get_property_reply_t * const reply = xcb_get_property_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
QByteArray data = {};
|
||||||
|
const int len = xcb_get_property_value_length(reply);
|
||||||
|
const auto buf = static_cast<const char *>(xcb_get_property_value(reply));
|
||||||
|
data.append(buf, len);
|
||||||
|
std::free(reply);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Utils::setWindowProperty(const WId windowId, const xcb_atom_t prop, const xcb_atom_t type, const void *data, const quint32 data_len, const uint8_t format)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
Q_ASSERT(prop != XCB_NONE);
|
||||||
|
Q_ASSERT(type != XCB_NONE);
|
||||||
|
if (!windowId || (prop == XCB_NONE) || (type == XCB_NONE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, windowId, prop, type, format, data_len, data);
|
||||||
|
xcb_flush(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Utils::clearWindowProperty(const WId windowId, const xcb_atom_t prop)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
Q_ASSERT(prop != XCB_NONE);
|
||||||
|
if (!windowId || (prop == XCB_NONE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_delete_property_checked(connection, windowId, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Utils::isSupportedByWindowManager(const xcb_atom_t atom)
|
||||||
|
{
|
||||||
|
Q_ASSERT(atom != XCB_NONE);
|
||||||
|
if (atom == XCB_NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static const auto netWmAtoms = []() -> QList<xcb_atom_t> {
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
|
Q_ASSERT(rootWindow);
|
||||||
|
if (!rootWindow) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
static const xcb_atom_t netSupportedAtom = internAtom(ATOM_NET_SUPPORTED);
|
||||||
|
if (netSupportedAtom == XCB_NONE) {
|
||||||
|
WARNING << "Failed to retrieve the atom of _NET_SUPPORTED.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
QList<xcb_atom_t> result = {};
|
||||||
|
int offset = 0;
|
||||||
|
int remaining = 0;
|
||||||
|
do {
|
||||||
|
const xcb_get_property_cookie_t cookie = xcb_get_property(connection, false, rootWindow, netSupportedAtom, XCB_ATOM_ATOM, offset, 1024);
|
||||||
|
xcb_get_property_reply_t * const reply = xcb_get_property_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
remaining = 0;
|
||||||
|
if ((reply->type == XCB_ATOM_ATOM) && (reply->format == 32)) {
|
||||||
|
const int len = (xcb_get_property_value_length(reply) / sizeof(xcb_atom_t));
|
||||||
|
const auto atoms = static_cast<xcb_atom_t *>(xcb_get_property_value(reply));
|
||||||
|
const int size = result.size();
|
||||||
|
result.resize(size + len);
|
||||||
|
std::memcpy(result.data() + size, atoms, len * sizeof(xcb_atom_t));
|
||||||
|
remaining = reply->bytes_after;
|
||||||
|
offset += len;
|
||||||
|
}
|
||||||
|
std::free(reply);
|
||||||
|
} while (remaining > 0);
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
return netWmAtoms.contains(atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Utils::isSupportedByRootWindow(const xcb_atom_t atom)
|
||||||
|
{
|
||||||
|
Q_ASSERT(atom != XCB_NONE);
|
||||||
|
if (atom == XCB_NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static const auto rootWindowProperties = []() -> QList<xcb_atom_t> {
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
|
Q_ASSERT(rootWindow);
|
||||||
|
if (!rootWindow) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
QList<xcb_atom_t> result = {};
|
||||||
|
const xcb_list_properties_cookie_t cookie = xcb_list_properties(connection, rootWindow);
|
||||||
|
xcb_list_properties_reply_t * const reply = xcb_list_properties_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const int len = xcb_list_properties_atoms_length(reply);
|
||||||
|
const auto atoms = static_cast<xcb_atom_t *>(xcb_list_properties_atoms(reply));
|
||||||
|
result.resize(len);
|
||||||
|
std::memcpy(result.data(), atoms, len * sizeof(xcb_atom_t));
|
||||||
|
std::free(reply);
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
return rootWindowProperties.contains(atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Utils::tryHideSystemTitleBar(const WId windowId, const bool hide)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static const xcb_atom_t deepinNoTitleBarAtom = internAtom(ATOM_DEEPIN_NO_TITLEBAR);
|
||||||
|
if ((deepinNoTitleBarAtom == XCB_NONE) || !isSupportedByWindowManager(deepinNoTitleBarAtom)) {
|
||||||
|
WARNING << "Current window manager doesn't support hiding title bar natively.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const quint32 value = hide;
|
||||||
|
setWindowProperty(windowId, deepinNoTitleBarAtom, XCB_ATOM_CARDINAL, &value);
|
||||||
|
static const xcb_atom_t deepinForceDecorateAtom = internAtom(ATOM_DEEPIN_FORCE_DECORATE);
|
||||||
|
if ((deepinForceDecorateAtom == XCB_NONE) || !isSupportedByWindowManager(deepinForceDecorateAtom)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (hide) {
|
||||||
|
setWindowProperty(windowId, deepinForceDecorateAtom, XCB_ATOM_CARDINAL, &value);
|
||||||
|
} else {
|
||||||
|
clearWindowProperty(windowId, deepinForceDecorateAtom);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Utils::sendMoveResizeMessage(const WId windowId, const uint32_t action, const QPoint &globalPos, const Qt::MouseButton button)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_connection_t * const connection = x11_connection();
|
||||||
|
Q_ASSERT(connection);
|
||||||
|
if (!connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const quint32 rootWindow = x11_appRootWindow(x11_appScreen());
|
||||||
|
Q_ASSERT(rootWindow);
|
||||||
|
if (!rootWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_NET_WM_MOVERESIZE);
|
||||||
|
if ((atom == XCB_NONE) || !isSupportedByWindowManager(atom)) {
|
||||||
|
WARNING << "Current window manager doesn't support move resize operation.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_client_message_event_t xev;
|
||||||
|
memset(&xev, 0, sizeof(xev));
|
||||||
|
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
xev.type = atom;
|
||||||
|
xev.window = windowId;
|
||||||
|
xev.format = 32;
|
||||||
|
xev.data.data32[0] = globalPos.x();
|
||||||
|
xev.data.data32[1] = globalPos.y();
|
||||||
|
xev.data.data32[2] = action;
|
||||||
|
xev.data.data32[3] = [button]() -> int {
|
||||||
|
if (button == Qt::LeftButton) {
|
||||||
|
return XCB_BUTTON_INDEX_1;
|
||||||
|
}
|
||||||
|
if (button == Qt::RightButton) {
|
||||||
|
return XCB_BUTTON_INDEX_3;
|
||||||
|
}
|
||||||
|
return XCB_BUTTON_INDEX_ANY;
|
||||||
|
}();
|
||||||
|
xev.data.data32[4] = 0;
|
||||||
|
|
||||||
|
if (action != _NET_WM_MOVERESIZE_CANCEL) {
|
||||||
|
xcb_ungrab_pointer(connection, XCB_CURRENT_TIME);
|
||||||
|
}
|
||||||
|
xcb_send_event(connection, false, rootWindow, _XCB_SEND_EVENT_MASK, reinterpret_cast<const char *>(&xev));
|
||||||
|
xcb_flush(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Utils::isCustomDecorationSupported()
|
||||||
|
{
|
||||||
|
static const xcb_atom_t atom = internAtom(ATOM_DEEPIN_NO_TITLEBAR);
|
||||||
|
return ((atom != XCB_NONE) && isSupportedByWindowManager(atom));
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -352,17 +352,21 @@ void FramelessQuickHelperPrivate::setHitTestVisible(QObject *object, const bool
|
||||||
|
|
||||||
void FramelessQuickHelperPrivate::showSystemMenu(const QPoint &pos)
|
void FramelessQuickHelperPrivate::showSystemMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
|
||||||
Q_Q(FramelessQuickHelper);
|
Q_Q(FramelessQuickHelper);
|
||||||
const QQuickWindow * const window = q->window();
|
const QQuickWindow * const window = q->window();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const WId windowId = window->winId();
|
||||||
const QPoint globalPos = window->mapToGlobal(pos);
|
const QPoint globalPos = window->mapToGlobal(pos);
|
||||||
const QPoint nativePos = Utils::toNativePixels(window, globalPos);
|
const QPoint nativePos = Utils::toNativePixels(window, globalPos);
|
||||||
Utils::showSystemMenu(window->winId(), nativePos, false, [this]() -> bool { return isWindowFixedSize(); });
|
#ifdef Q_OS_WINDOWS
|
||||||
|
Utils::showSystemMenu(windowId, nativePos, false, [this]() -> bool { return isWindowFixedSize(); });
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
Utils::openSystemMenu(windowId, nativePos);
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(pos);
|
Q_UNUSED(windowId);
|
||||||
|
Q_UNUSED(nativePos);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,23 +189,18 @@ void FramelessWidgetsHelperPrivate::setBlurBehindWindowEnabled(const bool enable
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Utils::isBlurBehindWindowSupported()) {
|
if (Utils::isBlurBehindWindowSupported()) {
|
||||||
BlurMode mode = BlurMode::Disable;
|
#ifdef Q_OS_WINDOWS
|
||||||
QPalette palette = m_window->palette();
|
QPalette palette = m_window->palette();
|
||||||
if (enable) {
|
if (enable) {
|
||||||
if (!m_savedWindowBackgroundColor.isValid()) {
|
m_savedWindowBackgroundColor = palette.color(QPalette::Window);
|
||||||
m_savedWindowBackgroundColor = palette.color(QPalette::Window);
|
|
||||||
}
|
|
||||||
palette.setColor(QPalette::Window, kDefaultTransparentColor);
|
|
||||||
mode = BlurMode::Default;
|
|
||||||
} else {
|
|
||||||
if (m_savedWindowBackgroundColor.isValid()) {
|
|
||||||
palette.setColor(QPalette::Window, m_savedWindowBackgroundColor);
|
|
||||||
m_savedWindowBackgroundColor = {};
|
|
||||||
}
|
|
||||||
mode = BlurMode::Disable;
|
|
||||||
}
|
}
|
||||||
|
palette.setColor(QPalette::Window, (enable ? kDefaultTransparentColor : m_savedWindowBackgroundColor));
|
||||||
m_window->setPalette(palette);
|
m_window->setPalette(palette);
|
||||||
if (Utils::setBlurBehindWindowEnabled(m_window->winId(), mode, color)) {
|
#else // !Q_OS_WINDOWS
|
||||||
|
m_window->setAttribute(Qt::WA_TranslucentBackground, enable);
|
||||||
|
#endif // Q_OS_WINDOWS
|
||||||
|
if (Utils::setBlurBehindWindowEnabled(m_window->winId(),
|
||||||
|
(enable ? BlurMode::Default : BlurMode::Disable), color)) {
|
||||||
m_blurBehindWindowEnabled = enable;
|
m_blurBehindWindowEnabled = enable;
|
||||||
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("blurBehindWindowEnabledChanged"));
|
emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("blurBehindWindowEnabledChanged"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -804,16 +799,19 @@ void FramelessWidgetsHelperPrivate::bringWindowToFront()
|
||||||
|
|
||||||
void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos)
|
void FramelessWidgetsHelperPrivate::showSystemMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WINDOWS
|
|
||||||
if (!m_window) {
|
if (!m_window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const WId windowId = m_window->winId();
|
||||||
const QPoint globalPos = m_window->mapToGlobal(pos);
|
const QPoint globalPos = m_window->mapToGlobal(pos);
|
||||||
const QPoint nativePos = Utils::toNativePixels(m_window->windowHandle(), globalPos);
|
const QPoint nativePos = Utils::toNativePixels(m_window->windowHandle(), globalPos);
|
||||||
Utils::showSystemMenu(m_window->winId(), nativePos, false, [this]() -> bool { return isWindowFixedSize(); });
|
#ifdef Q_OS_WINDOWS
|
||||||
|
Utils::showSystemMenu(windowId, nativePos, false, [this]() -> bool { return isWindowFixedSize(); });
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
Utils::openSystemMenu(windowId, nativePos);
|
||||||
#else
|
#else
|
||||||
// ### TODO
|
Q_UNUSED(windowId);
|
||||||
Q_UNUSED(pos);
|
Q_UNUSED(nativePos);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue