Add glib helper to make it optional for Qt
This commit is contained in:
parent
c390b046f0
commit
aa5afd0a41
4 changed files with 438 additions and 1 deletions
|
|
@ -10,6 +10,9 @@ if (LINUX
|
||||||
AND Qt5WaylandClient_FOUND)
|
AND Qt5WaylandClient_FOUND)
|
||||||
add_subdirectory(linux_wayland_helper)
|
add_subdirectory(linux_wayland_helper)
|
||||||
endif()
|
endif()
|
||||||
|
if (LINUX AND NOT DESKTOP_APP_USE_PACKAGED)
|
||||||
|
add_subdirectory(linux_glib_helper)
|
||||||
|
endif()
|
||||||
if (LINUX AND NOT DESKTOP_APP_USE_PACKAGED)
|
if (LINUX AND NOT DESKTOP_APP_USE_PACKAGED)
|
||||||
add_subdirectory(linux_gtk_helper)
|
add_subdirectory(linux_gtk_helper)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
3
external/qt/CMakeLists.txt
vendored
3
external/qt/CMakeLists.txt
vendored
|
|
@ -290,12 +290,13 @@ else()
|
||||||
INTERFACE
|
INTERFACE
|
||||||
desktop-app::linux_gtk_helper
|
desktop-app::linux_gtk_helper
|
||||||
$<TARGET_FILE:desktop-app::linux_gtk_helper>
|
$<TARGET_FILE:desktop-app::linux_gtk_helper>
|
||||||
|
desktop-app::linux_glib_helper
|
||||||
|
$<TARGET_FILE:desktop-app::linux_glib_helper>
|
||||||
fontconfig
|
fontconfig
|
||||||
freetype
|
freetype
|
||||||
xcb
|
xcb
|
||||||
X11
|
X11
|
||||||
X11-xcb
|
X11-xcb
|
||||||
glib-2.0
|
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
pthread
|
pthread
|
||||||
)
|
)
|
||||||
|
|
|
||||||
28
linux_glib_helper/CMakeLists.txt
Normal file
28
linux_glib_helper/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# This file is part of Desktop App Toolkit,
|
||||||
|
# a set of libraries for developing nice desktop applications.
|
||||||
|
#
|
||||||
|
# For license and copyright information please follow this link:
|
||||||
|
# https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
|
||||||
|
add_library(linux_glib_helper STATIC)
|
||||||
|
add_library(desktop-app::linux_glib_helper ALIAS linux_glib_helper)
|
||||||
|
|
||||||
|
nice_target_sources(linux_glib_helper ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
PRIVATE
|
||||||
|
linux_glib_helper.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(linux_glib_helper
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_DL_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GLIB2 REQUIRED glib-2.0)
|
||||||
|
pkg_check_modules(GOBJECT REQUIRED gobject-2.0)
|
||||||
|
|
||||||
|
target_include_directories(linux_glib_helper SYSTEM
|
||||||
|
PRIVATE
|
||||||
|
${GLIB2_INCLUDE_DIRS}
|
||||||
|
${GOBJECT_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
405
linux_glib_helper/linux_glib_helper.cpp
Normal file
405
linux_glib_helper/linux_glib_helper.cpp
Normal file
|
|
@ -0,0 +1,405 @@
|
||||||
|
// This file is part of Desktop App Toolkit,
|
||||||
|
// a set of libraries for developing nice desktop applications.
|
||||||
|
//
|
||||||
|
// For license and copyright information please follow this link:
|
||||||
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
//
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define LOAD_SYMBOL(handle, func) LoadSymbol(handle, #func, func)
|
||||||
|
|
||||||
|
namespace GlibHelper {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void (*g_free)(gpointer mem);
|
||||||
|
void (*g_log_default_handler)(
|
||||||
|
const gchar* log_domain,
|
||||||
|
GLogLevelFlags log_level,
|
||||||
|
const gchar* message,
|
||||||
|
gpointer unused_data);
|
||||||
|
guint (*g_log_set_handler)(
|
||||||
|
const gchar* log_domain,
|
||||||
|
GLogLevelFlags log_levels,
|
||||||
|
GLogFunc log_func,
|
||||||
|
gpointer user_data);
|
||||||
|
GMainContext* (*g_main_context_default)(void);
|
||||||
|
gboolean (*g_main_context_iteration)(GMainContext* context, gboolean may_block);
|
||||||
|
GMainContext* (*g_main_context_new)(void);
|
||||||
|
gboolean (*g_main_context_pending)(GMainContext* context);
|
||||||
|
void (*g_main_context_pop_thread_default)(GMainContext* context);
|
||||||
|
void (*g_main_context_push_thread_default)(GMainContext* context);
|
||||||
|
GMainContext* (*g_main_context_ref)(GMainContext* context);
|
||||||
|
void (*g_main_context_unref)(GMainContext* context);
|
||||||
|
void (*g_main_context_wakeup)(GMainContext* context);
|
||||||
|
void (*g_return_if_fail_warning)(
|
||||||
|
const char* log_domain,
|
||||||
|
const char* pretty_function,
|
||||||
|
const char* expression);
|
||||||
|
void (*g_slist_free)(GSList* list);
|
||||||
|
void (*g_source_add_poll)(GSource* source, GPollFD* fd);
|
||||||
|
guint (*g_source_attach)(GSource* source, GMainContext* context);
|
||||||
|
void (*g_source_destroy)(GSource* source);
|
||||||
|
GSource* (*g_source_new)(GSourceFuncs* source_funcs, guint struct_size);
|
||||||
|
void (*g_source_remove_poll)(GSource* source, GPollFD* fd);
|
||||||
|
void (*g_source_set_can_recurse)(GSource* source, gboolean can_recurse);
|
||||||
|
void (*g_source_unref)(GSource* source);
|
||||||
|
int (*g_strcmp0)(const char* str1, const char* str2);
|
||||||
|
|
||||||
|
GParamSpec* (*g_object_class_find_property)(
|
||||||
|
GObjectClass* oclass,
|
||||||
|
const gchar* property_name);
|
||||||
|
void (*g_object_get_valist)(
|
||||||
|
GObject* object,
|
||||||
|
const gchar* first_property_name,
|
||||||
|
va_list var_args);
|
||||||
|
GObject* (*g_object_new_with_properties)(
|
||||||
|
GType object_type,
|
||||||
|
guint n_properties,
|
||||||
|
const char** names,
|
||||||
|
const GValue* values);
|
||||||
|
GObject* (*g_object_new_valist)(
|
||||||
|
GType object_type,
|
||||||
|
const gchar* first_property_name,
|
||||||
|
va_list var_args);
|
||||||
|
void (*g_object_set_valist)(
|
||||||
|
GObject* object,
|
||||||
|
const gchar* first_property_name,
|
||||||
|
va_list var_args);
|
||||||
|
void (*g_object_unref)(gpointer object);
|
||||||
|
gulong (*g_signal_connect_data)(
|
||||||
|
gpointer instance,
|
||||||
|
const gchar* detailed_signal,
|
||||||
|
GCallback c_handler,
|
||||||
|
gpointer data,
|
||||||
|
GClosureNotify destroy_data,
|
||||||
|
GConnectFlags connect_flags);
|
||||||
|
GTypeInstance* (*g_type_check_instance_cast)(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType iface_type);
|
||||||
|
gboolean (*g_type_check_instance_is_a)(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType iface_type);
|
||||||
|
gboolean (*g_type_check_instance_is_fundamentally_a)(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType fundamental_type);
|
||||||
|
void (*g_type_ensure)(GType type);
|
||||||
|
|
||||||
|
struct HandleDeleter {
|
||||||
|
void operator()(void *handle) {
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Handle = std::unique_ptr<void, HandleDeleter>;
|
||||||
|
|
||||||
|
bool LoadLibrary(Handle &handle, const char *name) {
|
||||||
|
handle = Handle(dlopen(name, RTLD_LAZY | RTLD_NODELETE));
|
||||||
|
if (handle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::cerr << dlerror() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
inline bool LoadSymbol(const Handle &handle, const char *name, Function &func) {
|
||||||
|
func = handle
|
||||||
|
? reinterpret_cast<Function>(dlsym(handle.get(), name))
|
||||||
|
: nullptr;
|
||||||
|
if (const auto error = dlerror()) {
|
||||||
|
std::cerr << error << std::endl;
|
||||||
|
}
|
||||||
|
return (func != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Resolve() {
|
||||||
|
static const auto loaded = [&] {
|
||||||
|
auto lib = Handle();
|
||||||
|
return LoadLibrary(lib, "libglib-2.0.so.0")
|
||||||
|
&& LOAD_SYMBOL(lib, g_free)
|
||||||
|
&& LOAD_SYMBOL(lib, g_log_default_handler)
|
||||||
|
&& LOAD_SYMBOL(lib, g_log_set_handler)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_default)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_iteration)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_new)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_pending)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_pop_thread_default)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_push_thread_default)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_ref)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_unref)
|
||||||
|
&& LOAD_SYMBOL(lib, g_main_context_wakeup)
|
||||||
|
&& LOAD_SYMBOL(lib, g_return_if_fail_warning)
|
||||||
|
&& LOAD_SYMBOL(lib, g_slist_free)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_add_poll)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_attach)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_destroy)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_new)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_remove_poll)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_set_can_recurse)
|
||||||
|
&& LOAD_SYMBOL(lib, g_source_unref)
|
||||||
|
&& LOAD_SYMBOL(lib, g_strcmp0)
|
||||||
|
&& LoadLibrary(lib, "libgobject-2.0.so.0")
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_class_find_property)
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_get_valist)
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_new_valist)
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_new_with_properties)
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_set_valist)
|
||||||
|
&& LOAD_SYMBOL(lib, g_object_unref)
|
||||||
|
&& LOAD_SYMBOL(lib, g_signal_connect_data)
|
||||||
|
&& LOAD_SYMBOL(lib, g_type_check_instance_cast)
|
||||||
|
&& LOAD_SYMBOL(lib, g_type_check_instance_is_a)
|
||||||
|
&& LOAD_SYMBOL(lib, g_type_check_instance_is_fundamentally_a)
|
||||||
|
&& LOAD_SYMBOL(lib, g_type_ensure);
|
||||||
|
}();
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace GlibHelper
|
||||||
|
|
||||||
|
void g_free(gpointer mem) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_log_default_handler(
|
||||||
|
const gchar* log_domain,
|
||||||
|
GLogLevelFlags log_level,
|
||||||
|
const gchar* message,
|
||||||
|
gpointer unused_data) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_log_default_handler(
|
||||||
|
log_domain,
|
||||||
|
log_level,
|
||||||
|
message,
|
||||||
|
unused_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint g_log_set_handler(
|
||||||
|
const gchar* log_domain,
|
||||||
|
GLogLevelFlags log_levels,
|
||||||
|
GLogFunc log_func,
|
||||||
|
gpointer user_data) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_log_set_handler(
|
||||||
|
log_domain,
|
||||||
|
log_levels,
|
||||||
|
log_func,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GMainContext* g_main_context_default(void) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_main_context_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean g_main_context_iteration(GMainContext* context, gboolean may_block) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_main_context_iteration(context, may_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
GMainContext* g_main_context_new(void) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_main_context_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean g_main_context_pending(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_main_context_pending(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_main_context_pop_thread_default(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_main_context_pop_thread_default(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_main_context_push_thread_default(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_main_context_push_thread_default(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
GMainContext* g_main_context_ref(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_main_context_ref(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_main_context_unref(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_main_context_unref(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_main_context_wakeup(GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_main_context_wakeup(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_return_if_fail_warning(
|
||||||
|
const char* log_domain,
|
||||||
|
const char* pretty_function,
|
||||||
|
const char* expression) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_return_if_fail_warning(
|
||||||
|
log_domain,
|
||||||
|
pretty_function,
|
||||||
|
expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_slist_free(GSList* list) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_slist_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_source_add_poll(GSource* source, GPollFD* fd) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_source_add_poll(source, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint g_source_attach(GSource* source, GMainContext* context) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_source_attach(source, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_source_destroy(GSource* source) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_source_destroy(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSource* g_source_new(GSourceFuncs* source_funcs, guint struct_size) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_source_new(source_funcs, struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_source_remove_poll(GSource* source, GPollFD* fd) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_source_remove_poll(source, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_source_set_can_recurse(GSource* source, gboolean can_recurse) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_source_set_can_recurse(source, can_recurse);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_source_unref(GSource* source) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_source_unref(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
int g_strcmp0(const char* str1, const char* str2) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_strcmp0(str1, str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
GParamSpec* g_object_class_find_property(
|
||||||
|
GObjectClass* oclass,
|
||||||
|
const gchar* property_name) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_object_class_find_property(
|
||||||
|
oclass,
|
||||||
|
property_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_object_get(
|
||||||
|
gpointer _object,
|
||||||
|
const gchar *first_property_name,
|
||||||
|
...) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
|
||||||
|
GObject *object = (GObject*) _object;
|
||||||
|
va_list var_args;
|
||||||
|
|
||||||
|
g_return_if_fail(G_IS_OBJECT(object));
|
||||||
|
|
||||||
|
va_start(var_args, first_property_name);
|
||||||
|
GlibHelper::g_object_get_valist(object, first_property_name, var_args);
|
||||||
|
va_end(var_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer g_object_new(
|
||||||
|
GType object_type,
|
||||||
|
const gchar *first_property_name,
|
||||||
|
...) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
|
||||||
|
GObject *object;
|
||||||
|
va_list var_args;
|
||||||
|
|
||||||
|
/* short circuit for calls supplying no properties */
|
||||||
|
if (!first_property_name)
|
||||||
|
return GlibHelper::g_object_new_with_properties(object_type, 0, NULL, NULL);
|
||||||
|
|
||||||
|
va_start(var_args, first_property_name);
|
||||||
|
object = GlibHelper::g_object_new_valist(object_type, first_property_name, var_args);
|
||||||
|
va_end(var_args);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_object_set(
|
||||||
|
gpointer _object,
|
||||||
|
const gchar *first_property_name,
|
||||||
|
...) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
|
||||||
|
GObject *object = (GObject*) _object;
|
||||||
|
va_list var_args;
|
||||||
|
|
||||||
|
g_return_if_fail(G_IS_OBJECT(object));
|
||||||
|
|
||||||
|
va_start(var_args, first_property_name);
|
||||||
|
GlibHelper::g_object_set_valist(object, first_property_name, var_args);
|
||||||
|
va_end(var_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_object_unref(gpointer object) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_object_unref(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong g_signal_connect_data(
|
||||||
|
gpointer instance,
|
||||||
|
const gchar* detailed_signal,
|
||||||
|
GCallback c_handler,
|
||||||
|
gpointer data,
|
||||||
|
GClosureNotify destroy_data,
|
||||||
|
GConnectFlags connect_flags) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_signal_connect_data(
|
||||||
|
instance,
|
||||||
|
detailed_signal,
|
||||||
|
c_handler,
|
||||||
|
data,
|
||||||
|
destroy_data,
|
||||||
|
connect_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
GTypeInstance* g_type_check_instance_cast(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType iface_type) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_type_check_instance_cast(instance, iface_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean g_type_check_instance_is_a(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType iface_type) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_type_check_instance_is_a(instance, iface_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean g_type_check_instance_is_fundamentally_a(
|
||||||
|
GTypeInstance* instance,
|
||||||
|
GType fundamental_type) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
return GlibHelper::g_type_check_instance_is_fundamentally_a(
|
||||||
|
instance,
|
||||||
|
fundamental_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_type_ensure(GType type) {
|
||||||
|
GlibHelper::Resolve();
|
||||||
|
GlibHelper::g_type_ensure(type);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue