From a887235a1e80fb016c3d28ed796061cc82f2d773 Mon Sep 17 00:00:00 2001 From: Christian Seiler Date: Thu, 1 Oct 2015 00:42:08 +0200 Subject: [PATCH] Also override GObject introspection called functions Some functions that we need to override may also be called via GObject introspection (e.g. when calling them from Python and other scripting languages), so we need to make sure that also this method of calling these functions causes our overrides to be called. To this end, override the g_function_info_prep_invoker method to replace the function pointers if necessary. --- Makefile | 2 +- gtk3-nocsd.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5b9fdcf..210ea64 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PKG_CONFIG ?= pkg-config CFLAGS ?= -O2 -g -CFLAGS += $(shell ${PKG_CONFIG} --cflags gtk+-3.0) -pthread -Wall -fPIC +CFLAGS += $(shell ${PKG_CONFIG} --cflags gtk+-3.0) $(shell ${PKG_CONFIG} --cflags gobject-introspection-1.0) -pthread -Wall -fPIC LDLIBS = -ldl libdir ?= /usr/lib diff --git a/gtk3-nocsd.c b/gtk3-nocsd.c index 13592f4..6488c16 100644 --- a/gtk3-nocsd.c +++ b/gtk3-nocsd.c @@ -32,6 +32,8 @@ #include #include +#include + typedef void (*gtk_window_buildable_add_child_t) (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const gchar *type); typedef GObject* (*gtk_dialog_constructor_t) (GType type, guint n_construct_properties, GObjectConstructParam *construct_params); typedef char *(*gtk_check_version_t) (guint required_major, guint required_minor, guint required_micro); @@ -42,6 +44,7 @@ enum { GDK_LIBRARY, GOBJECT_LIBRARY, GLIB_LIBRARY, + GIREPOSITORY_LIBRARY, NUM_LIBRARIES }; @@ -61,17 +64,23 @@ enum { #define GLIB_LIBRARY_SONAME "libglib-2.0.so" #endif +#ifndef GIREPOSITORY_LIBRARY_SONAME +#define GIREPOSITORY_LIBRARY_SONAME "libgirepository-1.0.so.1" +#endif + static const char *library_sonames[NUM_LIBRARIES] = { GTK_LIBRARY_SONAME, GDK_LIBRARY_SONAME, GOBJECT_LIBRARY_SONAME, - GLIB_LIBRARY_SONAME + GLIB_LIBRARY_SONAME, + GIREPOSITORY_LIBRARY_SONAME }; static void * volatile library_handles[NUM_LIBRARIES] = { NULL, NULL, NULL, + NULL, NULL }; @@ -171,6 +180,7 @@ RUNTIME_IMPORT_FUNCTION(GOBJECT_LIBRARY, g_type_instance_get_private, gpointer, RUNTIME_IMPORT_FUNCTION(GOBJECT_LIBRARY, g_signal_connect_data, gulong, (gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags), (instance, detailed_signal, c_handler, data, destroy_data, connect_flags)) RUNTIME_IMPORT_FUNCTION(GLIB_LIBRARY, g_getenv, gchar *, (const char *name), (name)) RUNTIME_IMPORT_FUNCTION(GLIB_LIBRARY, g_logv, void, (const gchar *log_domain, GLogLevelFlags log_level, const gchar *format, va_list args), (log_domain, log_level, format, args)) +RUNTIME_IMPORT_FUNCTION(GIREPOSITORY_LIBRARY, g_function_info_prep_invoker, gboolean, (GIFunctionInfo *info, GIFunctionInvoker *invoker, GError **error), (info, invoker, error)) /* All methods that we want to overwrite are named orig_, all methods * that we just want to call (either directly or indirectrly) @@ -209,6 +219,7 @@ RUNTIME_IMPORT_FUNCTION(GLIB_LIBRARY, g_logv, void, (const gchar *log_domain, GL #define g_getenv rtlookup_g_getenv #define g_logv rtlookup_g_logv #define g_log static_g_log +#define orig_g_function_info_prep_invoker rtlookup_g_function_info_prep_invoker /* Forwarding of varadic functions is tricky. */ static void static_g_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *format, ...) @@ -679,3 +690,24 @@ static gtk_window_private_info_t gtk_window_private_info () } return info; } + +gboolean g_function_info_prep_invoker (GIFunctionInfo *info, GIFunctionInvoker *invoker, GError **error) +{ + static gpointer orig_set_titlebar = NULL, orig_set_show_close_button = NULL; + gboolean result; + + if (!orig_set_titlebar) + orig_set_titlebar = (gpointer) find_orig_function (GTK_LIBRARY, "gtk_window_set_titlebar"); + if (!orig_set_show_close_button) + orig_set_show_close_button = (gpointer) find_orig_function (GTK_LIBRARY, "gtk_header_bar_set_show_close_button"); + + result = orig_g_function_info_prep_invoker (info, invoker, error); + if (result) { + if (G_UNLIKELY (invoker->native_address == orig_set_titlebar)) + invoker->native_address = gtk_window_set_titlebar; + if (G_UNLIKELY (invoker->native_address == orig_set_show_close_button)) + invoker->native_address = gtk_header_bar_set_show_close_button; + } + + return result; +}