forked from github_mirror/framelesshelper
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:
parent
8683a14a3c
commit
34ba90376b
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include <framelesshelper_linux.h>
|
|
@ -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"
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));)
|
|
@ -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,7 +367,8 @@ 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,
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue