linux: remove the build-time dependency of libxcb and libgtk

We can load them dynamically at run-time.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-12-12 17:46:44 +08:00
parent 8683a14a3c
commit 34ba90376b
9 changed files with 675 additions and 94 deletions

View File

@ -127,8 +127,6 @@ cmake --build . --config Release --target all --parallel
cmake --install . --config Release --strip
```
**IMPORTANT NOTE**: On Linux you need to install the _GTK3_ and _X11_ development packages first.
Once the compilation and installation is done, you will be able to use the `find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets Quick)` command to find and link to the FramelessHelper library. But before doing that, please make sure CMake knows where to find FramelessHelper, by passing the `CMAKE_PREFIX_PATH` variable to it. For example: `-DCMAKE_PREFIX_PATH=C:/my-cmake-packages;C:/my-toolchain;etc...`. Build FramelessHelper as a sub-directory of your CMake project is of course also supported. The supported FramelessHelper target names are `FramelessHelper::FramelessHelperCore`, `FramelessHelper::FramelessHelperWidgets` and `FramelessHelper::FramelessHelperQuick`.
## Use

View File

@ -0,0 +1 @@
#include <framelesshelper_linux.h>

View File

@ -0,0 +1,350 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <framelesshelpercore_global.h>
/*
* Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the authors or their
* institutions shall not be used in advertising or otherwise to promote the
* sale, use or other dealings in this Software without prior written
* authorization from the authors.
*/
using Display = struct _XDisplay;
using xcb_connection_t = struct xcb_connection_t;
using xcb_button_t = uint8_t;
using xcb_window_t = uint32_t;
using xcb_timestamp_t = uint32_t;
using xcb_atom_t = uint32_t;
using xcb_generic_error_t = struct xcb_generic_error_t
{
uint8_t response_type;
uint8_t error_code;
uint16_t sequence;
uint32_t resource_id;
uint16_t minor_code;
uint8_t major_code;
uint8_t pad0;
uint32_t pad[5];
uint32_t full_sequence;
};
using xcb_client_message_data_t = union xcb_client_message_data_t
{
uint8_t data8[20];
uint16_t data16[10];
uint32_t data32[5];
};
using xcb_button_press_event_t = struct xcb_button_press_event_t
{
uint8_t response_type;
xcb_button_t detail;
uint16_t sequence;
xcb_timestamp_t time;
xcb_window_t root;
xcb_window_t event;
xcb_window_t child;
int16_t root_x;
int16_t root_y;
int16_t event_x;
int16_t event_y;
uint16_t state;
uint8_t same_screen;
uint8_t pad0;
};
using xcb_button_release_event_t = xcb_button_press_event_t;
using xcb_void_cookie_t = struct xcb_void_cookie_t
{
unsigned int sequence;
};
using xcb_intern_atom_cookie_t = struct xcb_intern_atom_cookie_t
{
unsigned int sequence;
};
using xcb_intern_atom_reply_t = struct xcb_intern_atom_reply_t
{
uint8_t response_type;
uint8_t pad0;
uint16_t sequence;
uint32_t length;
xcb_atom_t atom;
};
using xcb_client_message_event_t = struct xcb_client_message_event_t
{
uint8_t response_type;
uint8_t format;
uint16_t sequence;
xcb_window_t window;
xcb_atom_t type;
xcb_client_message_data_t data;
};
[[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_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_SUBSTRUCTURE_REDIRECT = 1048576;
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 524288;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_LEFT = 7;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_MOVE = 8;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_KEYBOARD = 9;
[[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 char _NET_WM_MOVERESIZE_ATOM_NAME[] = "_NET_WM_MOVERESIZE";
extern "C"
{
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_send_event(
xcb_connection_t *connection,
uint8_t propagate,
xcb_window_t destination,
uint32_t event_mask,
const char *event
);
FRAMELESSHELPER_CORE_API int
xcb_flush(
xcb_connection_t *connection
);
FRAMELESSHELPER_CORE_API xcb_intern_atom_cookie_t
xcb_intern_atom(
xcb_connection_t *connection,
uint8_t only_if_exists,
uint16_t name_len,
const char *name
);
FRAMELESSHELPER_CORE_API xcb_intern_atom_reply_t *
xcb_intern_atom_reply(
xcb_connection_t *connection,
xcb_intern_atom_cookie_t cookie,
xcb_generic_error_t **error
);
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_ungrab_pointer(
xcb_connection_t *connection,
xcb_timestamp_t time
);
} // extern "C"
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#define G_VALUE_INIT { 0, { { 0 } } }
#define g_signal_connect(instance, detailed_signal, c_handler, data) \
g_signal_connect_data((instance), (detailed_signal), (c_handler), (data), nullptr, G_CONNECT_DEFAULT)
using gint = int;
using glong = long;
using gshort = short;
using gboolean = int;
using gushort = unsigned short;
using guint = unsigned int;
using gulong = unsigned long;
using gfloat = float;
using gdouble = double;
using gchar = char;
using guchar = unsigned char;
using gchararray = char *;
using gpointer = void *;
using gint64 = int64_t;
using guint64 = uint64_t;
using gsize = unsigned long;
using GType = gsize;
using GValue = struct _GValue;
using GObject = struct _GObject;
using GClosure = struct _GClosure;
using GtkSettings = struct _GtkSettings;
using GConnectFlags = enum GConnectFlags
{
G_CONNECT_DEFAULT = 0,
G_CONNECT_AFTER = 1 << 0,
G_CONNECT_SWAPPED = 1 << 1
};
using GCallback = void(*)(void);
using GClosureNotify = void(*)(gpointer data, GClosure *closure);
struct _GValue
{
GType g_type;
union
{
gint v_int;
guint v_uint;
glong v_long;
gulong v_ulong;
gint64 v_int64;
guint64 v_uint64;
gfloat v_float;
gdouble v_double;
gpointer v_pointer;
} data[2];
};
[[maybe_unused]] inline constexpr const char GTK_THEME_NAME_ENV_VAR[] = "GTK_THEME";
[[maybe_unused]] inline constexpr const char GTK_THEME_NAME_PROP[] = "gtk-theme-name";
[[maybe_unused]] inline constexpr const char GTK_THEME_PREFER_DARK_PROP[] = "gtk-application-prefer-dark-theme";
extern "C"
{
FRAMELESSHELPER_CORE_API void
gtk_init(
int *argc,
char ***argv
);
FRAMELESSHELPER_CORE_API GValue *
g_value_init(
GValue *value,
GType g_type
);
FRAMELESSHELPER_CORE_API GValue *
g_value_reset(
GValue *value
);
FRAMELESSHELPER_CORE_API void
g_value_unset(
GValue *value
);
FRAMELESSHELPER_CORE_API gboolean
g_value_get_boolean(
const GValue *value
);
FRAMELESSHELPER_CORE_API const gchar *
g_value_get_string(
const GValue *value
);
FRAMELESSHELPER_CORE_API GtkSettings *
gtk_settings_get_default(
void
);
FRAMELESSHELPER_CORE_API void
g_object_get_property(
GObject *object,
const gchar *property_name,
GValue *value
);
FRAMELESSHELPER_CORE_API gulong
g_signal_connect_data(
gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags
);
FRAMELESSHELPER_CORE_API void
g_free(
gpointer mem
);
FRAMELESSHELPER_CORE_API void
g_object_unref(
GObject *object
);
FRAMELESSHELPER_CORE_API void
g_clear_object(
GObject **object_ptr
);
} // extern "C"

View File

@ -58,17 +58,8 @@ FRAMELESSHELPER_END_NAMESPACE
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(SysApiLoader))
#ifdef Q_OS_WINDOWS
# define API_WIN_AVAILABLE(lib, func) \
#define API_AVAILABLE(lib, func) \
(FRAMELESSHELPER_PREPEND_NAMESPACE(SysApiLoader)::instance()->isAvailable(k##lib, k##func))
# define API_USER_AVAILABLE(func) API_WIN_AVAILABLE(user32, func)
# define API_THEME_AVAILABLE(func) API_WIN_AVAILABLE(uxtheme, func)
# define API_DWM_AVAILABLE(func) API_WIN_AVAILABLE(dwmapi, func)
# define API_SHCORE_AVAILABLE(func) API_WIN_AVAILABLE(shcore, func)
# define API_WINMM_AVAILABLE(func) API_WIN_AVAILABLE(winmm, func)
# define API_D2D_AVAILABLE(func) API_WIN_AVAILABLE(d2d1, func)
# define API_NT_AVAILABLE(func) API_WIN_AVAILABLE(ntdll, func)
#endif
#define API_CALL_FUNCTION(func, ...) \
((FRAMELESSHELPER_PREPEND_NAMESPACE(SysApiLoader)::instance()->get<decltype(&func)>(k##func))(__VA_ARGS__))
@ -82,3 +73,18 @@ Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(SysApiLoader))
#define API_CALL_FUNCTION4(func, ...) API_CALL_FUNCTION3(_##func, func, __VA_ARGS__)
#define API_CALL_FUNCTION5(func, ...) API_CALL_FUNCTION3(func##2, func, __VA_ARGS__)
#ifdef Q_OS_WINDOWS
# define API_USER_AVAILABLE(func) API_AVAILABLE(user32, func)
# define API_THEME_AVAILABLE(func) API_AVAILABLE(uxtheme, func)
# define API_DWM_AVAILABLE(func) API_AVAILABLE(dwmapi, func)
# define API_SHCORE_AVAILABLE(func) API_AVAILABLE(shcore, func)
# define API_WINMM_AVAILABLE(func) API_AVAILABLE(winmm, func)
# define API_D2D_AVAILABLE(func) API_AVAILABLE(d2d1, func)
# define API_NT_AVAILABLE(func) API_AVAILABLE(ntdll, func)
#endif // Q_OS_WINDOWS
#ifdef Q_OS_LINUX
# define API_XCB_AVAILABLE(func) API_AVAILABLE(libxcb, func)
# define API_GTK_AVAILABLE(func) API_AVAILABLE(libgtk, func)
#endif // Q_OS_LINUX

View File

@ -64,10 +64,11 @@ win32 {
}
unix:!macx {
CONFIG += link_pkgconfig
PKGCONFIG += gtk+-3.0 xcb
DEFINES += GDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_6
SOURCES += $$CORE_SRC_DIR/utils_linux.cpp
HEADERS += \
$$CORE_PUB_INC_DIR/framelesshelper_linux.h
SOURCES += \
$$CORE_SRC_DIR/utils_linux.cpp \
$$CORE_SRC_DIR/platformsupport_linux.cpp
}
macx {

View File

@ -22,12 +22,6 @@
SOFTWARE.
]]
if(UNIX AND NOT APPLE)
find_package(PkgConfig REQUIRED)
find_package(X11 REQUIRED)
pkg_search_module(GTK3 REQUIRED gtk+-3.0)
endif()
set(SUB_MOD_NAME Core)
set(SUB_PROJ_NAME ${PROJECT_NAME}${SUB_MOD_NAME})
set(SUB_PROJ_PATH ${PROJECT_NAME}/${SUB_MOD_NAME})
@ -102,7 +96,16 @@ if(WIN32)
elseif(APPLE)
list(APPEND SOURCES utils_mac.mm)
elseif(UNIX)
list(APPEND SOURCES utils_linux.cpp)
list(APPEND PUBLIC_HEADERS
${INCLUDE_PREFIX}/framelesshelper_linux.h
)
list(APPEND PUBLIC_HEADERS_ALIAS
${INCLUDE_PREFIX}/FramelessHelper_Linux
)
list(APPEND SOURCES
utils_linux.cpp
platformsupport_linux.cpp
)
endif()
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
@ -175,17 +178,6 @@ if(APPLE)
"-framework Cocoa"
"-framework AppKit"
)
elseif(UNIX)
target_compile_definitions(${SUB_PROJ_NAME} PRIVATE
GDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_6
)
target_link_libraries(${SUB_PROJ_NAME} PRIVATE
${GTK3_LIBRARIES}
X11::xcb
)
target_include_directories(${SUB_PROJ_NAME} PRIVATE
${GTK3_INCLUDE_DIRS}
)
endif()
if(FRAMELESSHELPER_NO_PRIVATE)

View File

@ -25,9 +25,6 @@
#include "framelesshelpercore_global.h"
#include "utils.h"
#include "framelessmanager.h"
#ifdef Q_OS_WINDOWS
# include "framelesshelper_win.h"
#endif
#include "framelesshelper_qt.h"
#include "chromepalette.h"
#include "micamaterial.h"
@ -39,10 +36,11 @@
#include "micamaterial_p.h"
#include "windowborderpainter_p.h"
#ifdef Q_OS_WINDOWS
# include "framelesshelper_win.h"
# include "registrykey_p.h"
#endif
#ifdef Q_OS_LINUX
# include <gtk/gtk.h>
# include "framelesshelper_linux.h"
#endif
#include <QtCore/qmutex.h>
#include <QtCore/qiodevice.h>

View File

@ -0,0 +1,282 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "sysapiloader_p.h"
#include "framelesshelper_linux.h"
#define GTK_SETTINGS(Name, Type, ...) \
Type Name(const gchar *property) \
{ \
Q_ASSERT(property); \
if (!property) { \
return {}; \
} \
GtkSettings *settings = gtk_settings_get_default(); \
Q_ASSERT(settings); \
if (!settings) { \
return {}; \
} \
GValue value = G_VALUE_INIT; \
g_object_get_property(reinterpret_cast<GObject *>(settings), property, &value); \
__VA_ARGS__ \
g_value_unset(&value); \
return result; \
}
FRAMELESSHELPER_STRING_CONSTANT(libxcb)
FRAMELESSHELPER_STRING_CONSTANT2(libgtk, "libgtk-3")
FRAMELESSHELPER_STRING_CONSTANT(xcb_send_event)
FRAMELESSHELPER_STRING_CONSTANT(xcb_flush)
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom)
FRAMELESSHELPER_STRING_CONSTANT(xcb_intern_atom_reply)
FRAMELESSHELPER_STRING_CONSTANT(xcb_ungrab_pointer)
FRAMELESSHELPER_STRING_CONSTANT(gtk_init)
FRAMELESSHELPER_STRING_CONSTANT(g_value_init)
FRAMELESSHELPER_STRING_CONSTANT(g_value_reset)
FRAMELESSHELPER_STRING_CONSTANT(g_value_unset)
FRAMELESSHELPER_STRING_CONSTANT(g_value_get_boolean)
FRAMELESSHELPER_STRING_CONSTANT(g_value_get_string)
FRAMELESSHELPER_STRING_CONSTANT(gtk_settings_get_default)
FRAMELESSHELPER_STRING_CONSTANT(g_object_get_property)
FRAMELESSHELPER_STRING_CONSTANT(g_signal_connect_data)
FRAMELESSHELPER_STRING_CONSTANT(g_free)
FRAMELESSHELPER_STRING_CONSTANT(g_object_unref)
FRAMELESSHELPER_STRING_CONSTANT(g_clear_object)
//////////////////////////////////////////////
// XCB
extern "C" xcb_void_cookie_t
xcb_send_event(
xcb_connection_t *connection,
uint8_t propagate,
xcb_window_t destination,
uint32_t event_mask,
const char *event
)
{
if (!API_XCB_AVAILABLE(xcb_send_event)) {
return {};
}
return API_CALL_FUNCTION(xcb_send_event, connection, propagate, destination, event_mask, event);
}
extern "C" int
xcb_flush(
xcb_connection_t *connection
)
{
if (!API_XCB_AVAILABLE(xcb_flush)) {
return 0;
}
return API_CALL_FUNCTION(xcb_flush, connection);
}
extern "C" xcb_intern_atom_cookie_t
xcb_intern_atom(
xcb_connection_t *connection,
uint8_t only_if_exists,
uint16_t name_len,
const char *name
)
{
if (!API_XCB_AVAILABLE(xcb_intern_atom)) {
return {};
}
return API_CALL_FUNCTION(xcb_intern_atom, connection, only_if_exists, name_len, name);
}
extern "C" xcb_intern_atom_reply_t *
xcb_intern_atom_reply(
xcb_connection_t *connection,
xcb_intern_atom_cookie_t cookie,
xcb_generic_error_t **error
)
{
if (!API_XCB_AVAILABLE(xcb_intern_atom_reply)) {
return nullptr;
}
return API_CALL_FUNCTION(xcb_intern_atom_reply, connection, cookie, error);
}
extern "C" xcb_void_cookie_t
xcb_ungrab_pointer(
xcb_connection_t *connection,
xcb_timestamp_t time
)
{
if (!API_XCB_AVAILABLE(xcb_ungrab_pointer)) {
return {};
}
return API_CALL_FUNCTION(xcb_ungrab_pointer, connection, time);
}
///////////////////////////////////////////////////
// GTK
extern "C" void
gtk_init(
int *argc,
char ***argv
)
{
if (!API_GTK_AVAILABLE(gtk_init)) {
return;
}
API_CALL_FUNCTION(gtk_init, argc, argv);
}
extern "C" GValue *
g_value_init(
GValue *value,
GType g_type
)
{
if (!API_GTK_AVAILABLE(g_value_init)) {
return nullptr;
}
return API_CALL_FUNCTION(g_value_init, value, g_type);
}
extern "C" GValue *
g_value_reset(
GValue *value
)
{
if (!API_GTK_AVAILABLE(g_value_reset)) {
return nullptr;
}
return API_CALL_FUNCTION(g_value_reset, value);
}
extern "C" void
g_value_unset(
GValue *value
)
{
if (!API_GTK_AVAILABLE(g_value_unset)) {
return;
}
API_CALL_FUNCTION(g_value_unset, value);
}
extern "C" gboolean
g_value_get_boolean(
const GValue *value
)
{
if (!API_GTK_AVAILABLE(g_value_get_boolean)) {
return false;
}
return API_CALL_FUNCTION(g_value_get_boolean, value);
}
extern "C" const gchar *
g_value_get_string(
const GValue *value
)
{
if (!API_GTK_AVAILABLE(g_value_get_string)) {
return nullptr;
}
return API_CALL_FUNCTION(g_value_get_string, value);
}
extern "C" GtkSettings *
gtk_settings_get_default(
void
)
{
if (!API_GTK_AVAILABLE(gtk_settings_get_default)) {
return nullptr;
}
return API_CALL_FUNCTION(gtk_settings_get_default);
}
extern "C" void
g_object_get_property(
GObject *object,
const gchar *property_name,
GValue *value
)
{
if (!API_GTK_AVAILABLE(g_object_get_property)) {
return;
}
API_CALL_FUNCTION(g_object_get_property, object, property_name, value);
}
extern "C" gulong
g_signal_connect_data(
gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags
)
{
if (!API_GTK_AVAILABLE(g_signal_connect_data)) {
return 0;
}
return API_CALL_FUNCTION(g_signal_connect_data, instance, detailed_signal, c_handler, data, destroy_data, connect_flags);
}
extern "C" void
g_free(
gpointer mem
)
{
if (!API_GTK_AVAILABLE(g_free)) {
return;
}
API_CALL_FUNCTION(g_free, mem);
}
extern "C" void
g_object_unref(
GObject *object
)
{
if (!API_GTK_AVAILABLE(g_object_unref)) {
return;
}
API_CALL_FUNCTION(g_object_unref, object);
}
extern "C" void
g_clear_object(
GObject **object_ptr
)
{
if (!API_GTK_AVAILABLE(g_clear_object)) {
return;
}
API_CALL_FUNCTION(g_clear_object, object_ptr);
}
GTK_SETTINGS(GTK_bool, bool, const bool result = g_value_get_boolean(&value);)
GTK_SETTINGS(GTK_str, QString, const QString result = QUtf8String(g_value_get_string(&value));)

View File

@ -23,6 +23,7 @@
*/
#include "utils.h"
#include "framelesshelper_linux.h"
#include "framelessconfig_p.h"
#include "framelessmanager.h"
#include "framelessmanager_p.h"
@ -39,8 +40,9 @@
# include <QtPlatformHeaders/qxcbscreenfunctions.h>
# endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#endif // FRAMELESSHELPER_CORE_NO_PRIVATE
#include <gtk/gtk.h>
#include <xcb/xcb.h>
extern bool GTK_bool(const gchar *);
extern QString GTK_str(const gchar *);
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -60,27 +62,6 @@ Q_LOGGING_CATEGORY(lcUtilsLinux, "wangwenx190.framelesshelper.core.utils.linux")
using namespace Global;
using Display = struct _XDisplay;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_SIZE_LEFT = 7;
[[maybe_unused]] static constexpr const auto _NET_WM_MOVERESIZE_MOVE = 8;
[[maybe_unused]] static constexpr const char _NET_WM_MOVERESIZE_ATOM_NAME[] = "_NET_WM_MOVERESIZE";
[[maybe_unused]] static constexpr const auto _NET_WM_SENDEVENT_MASK =
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
[[maybe_unused]] static constexpr const char GTK_THEME_NAME_ENV_VAR[] = "GTK_THEME";
[[maybe_unused]] static constexpr const char GTK_THEME_NAME_PROP[] = "gtk-theme-name";
[[maybe_unused]] static constexpr const char GTK_THEME_PREFER_DARK_PROP[] = "gtk-application-prefer-dark-theme";
FRAMELESSHELPER_STRING_CONSTANT(dark)
FRAMELESSHELPER_BYTEARRAY_CONSTANT(rootwindow)
@ -92,35 +73,6 @@ FRAMELESSHELPER_BYTEARRAY_CONSTANT(startupid)
FRAMELESSHELPER_BYTEARRAY_CONSTANT(display)
FRAMELESSHELPER_BYTEARRAY_CONSTANT(connection)
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 propertyValue = gtkSetting<gchararray>(propertyName);
const QString result = QUtf8String(propertyValue);
g_free(propertyValue);
return result;
}
[[maybe_unused]] [[nodiscard]] static inline int
qtEdgesToWmMoveOrResizeOperation(const Qt::Edges edges)
{
@ -415,8 +367,9 @@ static inline void
// 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, _NET_WM_SENDEVENT_MASK,
reinterpret_cast<const char *>(&xev));
xcb_send_event(connection, false, rootWindow,
(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY),
reinterpret_cast<const char *>(&xev));
xcb_flush(connection);
}
@ -525,7 +478,7 @@ bool Utils::shouldAppsUseDarkMode_linux()
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_THEME_PREFER_DARK_PROP);
const bool preferDark = GTK_bool(GTK_THEME_PREFER_DARK_PROP);
if (preferDark) {
return true;
}
@ -533,7 +486,7 @@ bool Utils::shouldAppsUseDarkMode_linux()
/*
https://docs.gtk.org/gtk3/property.Settings.gtk-theme-name.html
*/
const QString curThemeName = gtkSetting(GTK_THEME_NAME_PROP);
const QString curThemeName = GTK_str(GTK_THEME_NAME_PROP);
if (!curThemeName.isEmpty()) {
return curThemeName.contains(kdark, Qt::CaseInsensitive);
}