diff options
Diffstat (limited to 'gtk3-stackrpms/gtk3-nocsd')
5 files changed, 408 insertions, 0 deletions
diff --git a/gtk3-stackrpms/gtk3-nocsd/30-gtk3-nocsd.sh b/gtk3-stackrpms/gtk3-nocsd/30-gtk3-nocsd.sh new file mode 100644 index 0000000..086823a --- /dev/null +++ b/gtk3-stackrpms/gtk3-nocsd/30-gtk3-nocsd.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ -n "${GNOME_DESKTOP_SESSION_ID-}" ]; then + # just in case DESKTOP_SESSION wasn't properly set + _check=gnome +else + _check="${DESKTOP_SESSION-}" +fi + +case "${_check}" in + + gnome|gnome-*|*/gnome|*/gnome-*) + unset GTK_CSD + ;; + + *) + export GTK_CSD=0 + export LD_PRELOAD="/usr/\${LIB}/libgtk3-nocsd.so.0${LD_PRELOAD:+:$LD_PRELOAD}" + ;; +esac + +unset _check diff --git a/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-82ff5a0da54aa6da27232b55eb93e5f4b5de22f2.patch b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-82ff5a0da54aa6da27232b55eb93e5f4b5de22f2.patch new file mode 100644 index 0000000..c01529d --- /dev/null +++ b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-82ff5a0da54aa6da27232b55eb93e5f4b5de22f2.patch @@ -0,0 +1,193 @@ +From 82ff5a0da54aa6da27232b55eb93e5f4b5de22f2 Mon Sep 17 00:00:00 2001 +From: Christian Seiler <christian@iwakd.de> +Date: Fri, 17 Jun 2016 17:27:27 +0200 +Subject: [PATCH] Properly handle the case when both gtk2 and gtk3 are loaded + +In case both gtk2 and gtk3 are loaded, but only gtk2 is used (which can +happen if a piece of software is linked against neither, but has +different plugins, some of which link against gtk2, others against +gtk3, all loaded at the same time, but only one of the variants used), +make sure that gtk3-nocsd detects that, doesn't actually inject any +code and calls all the gtk2 functions, instead of the gtk3 variants. +(Because they are incompatible and mixing calls will lead to crashes.) + +Fixes Github issue #18. +--- + ChangeLog | 2 ++ + gtk3-nocsd.c | 74 +++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 66 insertions(+), 10 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 53cbd33..3e93cba 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -7,6 +7,8 @@ New in version 4 (unreleased) + * Support python-gi again by not caching the result of the version + check if Gtk is not yet loaded. (python-gi loads Glib before it + loads Gtk.) ++ * Handle the case when both Gtk+3 and Gtk+2 are loaded (e.g. via ++ different plugins), but Gtk+2 is used. + + New in version 3 + ---------------- +diff --git a/gtk3-nocsd.c b/gtk3-nocsd.c +index 804fbd5..f9c0d70 100644 +--- a/gtk3-nocsd.c ++++ b/gtk3-nocsd.c +@@ -22,6 +22,7 @@ + + #define _GNU_SOURCE + #include <dlfcn.h> ++#include <link.h> + #include <unistd.h> + #include <string.h> + #include <stdlib.h> +@@ -111,6 +112,12 @@ static void * volatile library_handles[NUM_LIBRARIES * 2] = { + static pthread_key_t key_tls; + static pthread_once_t key_tls_once = PTHREAD_ONCE_INIT; + ++/* Marking both as volatile here saves the trouble of caring about ++ * memory barriers. */ ++static volatile gboolean is_compatible_gtk_version_cached = FALSE; ++static volatile gboolean is_compatible_gtk_version_checked = FALSE; ++static volatile int gtk2_active; ++ + typedef struct gtk3_nocsd_tls_data_t { + // When set to true, this override gdk_screen_is_composited() and let it + // return FALSE temporarily. Then, client-side decoration (CSD) cannot be initialized. +@@ -140,6 +147,12 @@ static void *find_orig_function(int try_gtk2, int library_id, const char *symbol + void *handle; + void *symptr; + ++ /* Ok, so in case both gtk2 + gtk3 are loaded, but we are using ++ * gtk2, we don't know what RTLD_NEXT is going to choose - so we ++ * must explicitly pick up the gtk2 versions... */ ++ if (try_gtk2 && gtk2_active) ++ goto try_gtk2_version; ++ + /* This will work in most cases, and is completely thread-safe. */ + handle = dlsym(RTLD_NEXT, symbol); + if (handle) +@@ -374,6 +387,42 @@ static void static_g_log(const gchar *log_domain, GLogLevelFlags log_level, cons + va_end (args); + } + ++int check_gtk2_callback(struct dl_phdr_info *info, size_t size, void *pointer) ++{ ++ ElfW(Half) n; ++ ++ if (G_UNLIKELY(strstr(info->dlpi_name, GDK_LIBRARY_SONAME_V2))) { ++ for (n = 0; n < info->dlpi_phnum; n++) { ++ uintptr_t start = (uintptr_t) (info->dlpi_addr + info->dlpi_phdr[n].p_vaddr); ++ uintptr_t end = start + (uintptr_t) info->dlpi_phdr[n].p_memsz; ++ if ((uintptr_t) pointer >= start && (uintptr_t) pointer < end) { ++ gtk2_active = 1; ++ /* The gtk version check could have already been cached ++ * before we were able to determine that gtk2 is in ++ * use, so force this to FALSE. (Regardless of the ++ * _checked value.) */ ++ is_compatible_gtk_version_cached = FALSE; ++ return 0; ++ } ++ } ++ } ++ return 0; ++} ++ ++static void detect_gtk2(void *pointer) ++{ ++ if (gtk2_active) ++ return; ++ /* There is a corner case where a program with plugins loads ++ * multiple plugins, some of which are linked against gtk2, while ++ * others are linked against gtk3. If the gtk2 plugins are used, ++ * this causes problems if we detect gtk3 just on the fact of ++ * whether gtk3 is loaded. Hence we iterate over all loaded ++ * libraries and if the pointer passed to us is within the memory ++ * region of gtk2, we set a global flag. */ ++ dl_iterate_phdr(check_gtk2_callback, pointer); ++} ++ + static gboolean is_gtk_version_larger_or_equal2(guint major, guint minor, guint micro, int* gtk_loaded) { + static gtk_check_version_t orig_func = NULL; + if(!orig_func) +@@ -414,18 +463,16 @@ static gboolean are_csd_disabled() { + } + + static gboolean is_compatible_gtk_version() { +- /* Marking both as volatile here saves the trouble of caring about +- * memory barriers. */ +- static volatile gboolean checked = FALSE; +- static volatile gboolean compatible = FALSE; + int gtk_loaded = FALSE; + +- if(G_UNLIKELY(!checked)) { +- if (!is_gtk_version_larger_or_equal2(3, 10, 0, >k_loaded)) { ++ if(G_UNLIKELY(!is_compatible_gtk_version_checked)) { ++ if (gtk2_active) { ++ is_compatible_gtk_version_cached = FALSE; ++ } else if (!is_gtk_version_larger_or_equal2(3, 10, 0, >k_loaded)) { + /* CSD was introduced there */ +- compatible = FALSE; ++ is_compatible_gtk_version_cached = FALSE; + } else { +- compatible = TRUE; ++ is_compatible_gtk_version_cached = TRUE; + } + /* If in a dynamical program (e.g. using python-gi) Glib is loaded before + * Gtk, then the Gtk version check is executed before Gtk is even loaded, +@@ -433,10 +480,10 @@ static gboolean is_compatible_gtk_version() { + * loaded later. To circumvent this, cache the value only if we know that + * Gtk is loaded. */ + if (gtk_loaded) +- checked = TRUE; ++ is_compatible_gtk_version_checked = TRUE; + } + +- return compatible; ++ return is_compatible_gtk_version_cached; + } + + static void set_has_custom_title(GtkWindow* window, gboolean set) { +@@ -1023,6 +1070,7 @@ GType g_type_register_static_simple (GType parent_type, const gchar *type_name, + if(type_name && G_UNLIKELY(strcmp(type_name, "GtkWindow") == 0)) { + // override GtkWindowClass + orig_gtk_window_class_init = class_init; ++ detect_gtk2((void *) class_init); + if(is_compatible_gtk_version() && are_csd_disabled()) { + class_init = (GClassInitFunc)fake_gtk_window_class_init; + save_type = >k_window_type; +@@ -1035,6 +1083,7 @@ GType g_type_register_static_simple (GType parent_type, const gchar *type_name, + if(type_name && G_UNLIKELY(strcmp(type_name, "GtkDialog") == 0)) { + // override GtkDialogClass + orig_gtk_dialog_class_init = class_init; ++ detect_gtk2((void *) class_init); + if(is_compatible_gtk_version() && are_csd_disabled()) { + class_init = (GClassInitFunc)fake_gtk_dialog_class_init; + save_type = >k_dialog_type; +@@ -1047,6 +1096,7 @@ GType g_type_register_static_simple (GType parent_type, const gchar *type_name, + if(type_name && G_UNLIKELY(strcmp(type_name, "GtkHeaderBar") == 0)) { + // override GtkHeaderBarClass + orig_gtk_header_bar_class_init = class_init; ++ detect_gtk2((void *) class_init); + if(is_compatible_gtk_version() && are_csd_disabled()) { + class_init = (GClassInitFunc)fake_gtk_header_bar_class_init; + save_type = >k_header_bar_type; +@@ -1059,6 +1109,7 @@ GType g_type_register_static_simple (GType parent_type, const gchar *type_name, + if(type_name && G_UNLIKELY(strcmp(type_name, "GtkShortcutsWindow") == 0)) { + // override GtkShortcutsWindowClass + orig_gtk_shortcuts_window_init = instance_init; ++ detect_gtk2((void *) instance_init); + if(is_compatible_gtk_version() && are_csd_disabled()) { + instance_init = (GInstanceInitFunc) fake_gtk_shortcuts_window_init; + goto out; +@@ -1112,6 +1163,9 @@ static void fake_gtk_dialog_buildable_interface_init (GtkBuildableIface *iface, + } + + void g_type_add_interface_static (GType instance_type, GType interface_type, const GInterfaceInfo *info) { ++ if (info && info->interface_init) ++ detect_gtk2((void *) info->interface_init); ++ + if(is_compatible_gtk_version() && are_csd_disabled() && (instance_type == gtk_window_type || instance_type == gtk_dialog_type)) { + if(interface_type == GTK_TYPE_BUILDABLE) { + // register GtkBuildable interface for GtkWindow/GtkDialog class diff --git a/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-c64505268575e60322de682ea751660eba8d0e71.patch b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-c64505268575e60322de682ea751660eba8d0e71.patch new file mode 100644 index 0000000..782699f --- /dev/null +++ b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-gh-c64505268575e60322de682ea751660eba8d0e71.patch @@ -0,0 +1,95 @@ +From c64505268575e60322de682ea751660eba8d0e71 Mon Sep 17 00:00:00 2001 +From: Christian Seiler <christian@iwakd.de> +Date: Wed, 1 Jun 2016 07:50:38 +0000 +Subject: [PATCH] Only cache gtk version check result if Gtk is loaded + +If in a dynamical program (e.g. using python-gi) Glib is loaded before +Gtk, then the Gtk version check is executed before Gtk is even loaded, +returning FALSE and caching it. This will not disable CSD if Gtk is +loaded later. To circumvent this, cache the value only if we know that +Gtk is loaded. + +Fixes github issue #16. +--- + ChangeLog | 7 +++++++ + gtk3-nocsd.c | 27 ++++++++++++++++++++++----- + 2 files changed, 29 insertions(+), 5 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 2f98771..53cbd33 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,6 +1,13 @@ + gtk3-nocsd ChangeLog + ==================== + ++New in version 4 (unreleased) ++----------------------------- ++ ++ * Support python-gi again by not caching the result of the version ++ check if Gtk is not yet loaded. (python-gi loads Glib before it ++ loads Gtk.) ++ + New in version 3 + ---------------- + +diff --git a/gtk3-nocsd.c b/gtk3-nocsd.c +index 08844c6..804fbd5 100644 +--- a/gtk3-nocsd.c ++++ b/gtk3-nocsd.c +@@ -374,7 +374,7 @@ static void static_g_log(const gchar *log_domain, GLogLevelFlags log_level, cons + va_end (args); + } + +-static gboolean is_gtk_version_larger_or_equal(guint major, guint minor, guint micro) { ++static gboolean is_gtk_version_larger_or_equal2(guint major, guint minor, guint micro, int* gtk_loaded) { + static gtk_check_version_t orig_func = NULL; + if(!orig_func) + orig_func = (gtk_check_version_t)find_orig_function(0, GTK_LIBRARY, "gtk_check_version"); +@@ -388,9 +388,19 @@ static gboolean is_gtk_version_larger_or_equal(guint major, guint minor, guint m + * will give us a reference to gtk_check_version. But since + * that symbol is compatible with gtk3, this doesn't hurt. + */ +- if (orig_func) ++ if (orig_func) { ++ if (gtk_loaded) ++ *gtk_loaded = TRUE; + return (orig_func(major, minor, micro) == NULL); +- return FALSE; ++ } else { ++ if (gtk_loaded) ++ *gtk_loaded = FALSE; ++ return FALSE; ++ } ++} ++ ++static gboolean is_gtk_version_larger_or_equal(guint major, guint minor, guint micro) { ++ return is_gtk_version_larger_or_equal2(major, minor, micro, NULL); + } + + static gboolean are_csd_disabled() { +@@ -408,15 +418,22 @@ static gboolean is_compatible_gtk_version() { + * memory barriers. */ + static volatile gboolean checked = FALSE; + static volatile gboolean compatible = FALSE; ++ int gtk_loaded = FALSE; + + if(G_UNLIKELY(!checked)) { +- if (!is_gtk_version_larger_or_equal(3, 10, 0)) { ++ if (!is_gtk_version_larger_or_equal2(3, 10, 0, >k_loaded)) { + /* CSD was introduced there */ + compatible = FALSE; + } else { + compatible = TRUE; + } +- checked = TRUE; ++ /* If in a dynamical program (e.g. using python-gi) Glib is loaded before ++ * Gtk, then the Gtk version check is executed before Gtk is even loaded, ++ * returning FALSE and caching it. This will not disable CSD if Gtk is ++ * loaded later. To circumvent this, cache the value only if we know that ++ * Gtk is loaded. */ ++ if (gtk_loaded) ++ checked = TRUE; + } + + return compatible; diff --git a/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-multilib.patch b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-multilib.patch new file mode 100644 index 0000000..2e3d7fd --- /dev/null +++ b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd-multilib.patch @@ -0,0 +1,15 @@ +diff -up gtk3-nocsd-3/gtk3-nocsd.in.multilib gtk3-nocsd-3/gtk3-nocsd.in +--- gtk3-nocsd-3/gtk3-nocsd.in.multilib 2017-02-19 10:23:41.771000847 -0300 ++++ gtk3-nocsd-3/gtk3-nocsd.in 2017-02-19 10:24:37.730157463 -0300 +@@ -41,10 +41,9 @@ if [ $IN_SYSTEM_PATH -eq 0 ] ; then + # Figure out where the library is installed. First try the path + # that was used when building gtk3-nocsd, then try the directory + # the binary is installed. +- INSTALLED_PATH="@@libdir@@" + BINARY_PATH="${GTK3_NOCSD_BINARY%/*}" + GTK3_NOCSD="" +- for _path in "$INSTALLED_PATH" "$BINARY_PATH" "${BINARY_PATH%/bin}/lib" ; do ++ for _path in "/usr/lib64" "/usr/lib" "$BINARY_PATH" "${BINARY_PATH%/bin}/lib" ; do + if [ -e "${_path}/${GTK3_NOCSD_NAME}" ] ; then + GTK3_NOCSD="${_path}/${GTK3_NOCSD_NAME}" + break diff --git a/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd.spec b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd.spec new file mode 100644 index 0000000..9681030 --- /dev/null +++ b/gtk3-stackrpms/gtk3-nocsd/gtk3-nocsd.spec @@ -0,0 +1,83 @@ +Name: gtk3-nocsd +Version: 3 +Release: 13%{?dist} +Summary: Disables the client side decoration of Gtk+ 3 + +License: LGPLv2.1 +URL: https://github.com/PCMan/%{name} +Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz +# AUR - Marco Kundt +Source1: https://aur.archlinux.org/cgit/aur.git/plain/30-%{name}.sh?h=%{name}-git#/30-%{name}.sh + +Patch0: %{name}-multilib.patch +Patch1: %{url}/commit/c64505268575e60322de682ea751660eba8d0e71.patch#/%{name}-gh-c64505268575e60322de682ea751660eba8d0e71.patch +Patch2: %{url}/commit/82ff5a0da54aa6da27232b55eb93e5f4b5de22f2.patch#/%{name}-gh-82ff5a0da54aa6da27232b55eb93e5f4b5de22f2.patch + +BuildRequires: make +BuildRequires: gcc +BuildRequires: pkgconfig(gobject-introspection-1.0) +BuildRequires: pkgconfig(gtk+-3.0) + +%description +%{name} is a small module used to disable the client side decoration of +Gtk+ 3. + +%prep +%autosetup -p1 + +cp -p %{SOURCE1} %{name}.sh + +sed \ + -e "/x\"$GTK_CSD\"x/s,\],\0 \&\& echo \$LD_PRELOAD | grep -v -q -F \'/usr/\${LIB}/libgtk3-nocsd.so.0\'," \ + -i %{name}.sh + +sed -e 's|$(LDFLAGS_LIB)|\0 $(LDFLAGS)|g' -i Makefile + +%build + +%set_build_flags +export prefix=%{_prefix} +export libdir=%{_libdir} +export bindir=%{_bindir} +export datadir=%{_datadir} +export mandir=%{_mandir} + +%make_build + +%install + +export prefix=%{_prefix} +export libdir=%{_libdir} +export bindir=%{_bindir} +export datadir=%{_datadir} +export mandir=%{_mandir} + +%make_install + +chmod +x %{buildroot}%{_libdir}/lib%{name}.so.0 + +mkdir -p %{buildroot}%{_sysconfdir}/profile.d +install -pm0644 %{name}.sh %{buildroot}%{_sysconfdir}/profile.d/%{name}.sh + +%files +%license COPYING +%doc ChangeLog README.md +%{_sysconfdir}/profile.d/%{name}.sh +%{_bindir}/%{name} +%{_libdir}/lib%{name}.so.0 +%{_datadir}/bash-completion/completions/%{name} +%{_mandir}/man1/%{name}.1* + +%changelog +* Thu May 27 2021 B. Stack <bgstack15@gmail.com> - 3-13 +- fork to stackrpms + +* Mon Feb 20 2017 Phantom X <megaphantomx at bol dot com dot br> - 3-3 +- Tweak profile script +- Drop %%config from profile script + +* Sun Feb 19 2017 Phantom X <megaphantomx at bol dot com dot br> - 3-2 +- Fix multilib + +* Fri Feb 10 2017 Phantom X <megaphantomx at bol dot com dot br> - 3-1 +- Initial spec |