Skip to content

Commit

Permalink
[gtk] Split the libadwaita/libhandy code into a separate file.
Browse files Browse the repository at this point in the history
pfn_adwaita.c handles all of the dlopen() functionality and uses
either adw_* or hdy_* depending on the GTK version in use.

It's built for GTK3 and GTK4, but not for GTK2.

Effectively no user-visible changes.
  • Loading branch information
GerbilSoft committed Jan 2, 2025
1 parent 6162805 commit 68c2082
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 64 deletions.
10 changes: 9 additions & 1 deletion src/gtk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,15 @@ SET(${PROJECT_NAME}_GTK3MAX_H
gtk3/sort_funcs.h
)

# Sources and headers (GTK4+ only)
# Sources and headers (GTK3+)
SET(${PROJECT_NAME}_GTK3MIN_SRCS
pfn_adwaita.c
)
SET(${PROJECT_NAME}_GTK3MIN_H
pfn_adwaita.h
)

# Sources and headers (GTK4+)
SET(${PROJECT_NAME}_GTK4MIN_SRCS
LanguageComboBox_gtk4.cpp
LanguageComboBoxItem.c
Expand Down
81 changes: 20 additions & 61 deletions src/gtk/RomDataView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* ROM Properties Page shell extension. (GTK+ common) *
* RomDataView.cpp: RomData viewer widget. *
* *
* Copyright (c) 2017-2024 by David Korth. *
* Copyright (c) 2017-2025 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/

Expand All @@ -15,6 +15,9 @@
#include "is-supported.hpp"
#include "rp-gtk-enums.h"

// libadwaita/libhandy function pointers
#include "pfn_adwaita.h"

// Custom widgets
#include "DragImage.hpp"
#include "LanguageComboBox.hpp"
Expand All @@ -25,16 +28,6 @@ using namespace LibRpBase;
using namespace LibRpText;
using namespace LibRpTexture;

// libdl
#ifdef HAVE_DLVSYM
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif /* _GNU_SOURCE */
#else /* !HAVE_DLVSYM */
# define dlvsym(handle, symbol, version) dlsym((handle), (symbol))
#endif /* HAVE_DLVSYM */
#include <dlfcn.h>

// C++ STL classes
using std::set;
using std::string;
Expand Down Expand Up @@ -92,21 +85,6 @@ static void cboLanguage_notify_selected_lc_handler(RpLanguageComboBox *widget,
GParamSpec *pspec,
RpRomDataView *page);

#if GTK_CHECK_VERSION(3,0,0)
// libadwaita/libhandy function pointers.
// Only initialized if libadwaita/libhandy is linked into the process.
// NOTE: The function pointers are essentially the same, but
// libhandy was renamed to libadwaita for the GTK4 conversion.
// We'll use libadwaita terminology everywhere.
struct AdwHeaderBar;
typedef GType (*pfnGlibGetType_t)(void);
typedef GType (*pfnAdwHeaderBarPackEnd_t)(AdwHeaderBar *self, GtkWidget *child);
static bool has_checked_adw = false;
static pfnGlibGetType_t pfn_adw_deck_get_type = nullptr;
static pfnGlibGetType_t pfn_adw_header_bar_get_type = nullptr;
static pfnAdwHeaderBarPackEnd_t pfn_adw_header_bar_pack_end = nullptr;
#endif /* GTK_CHECK_VERSION(3,0,0) */

// NOTE: G_DEFINE_TYPE() doesn't work in C++ mode with gcc-6.2
// due to an implicit int to GTypeFlags conversion.
G_DEFINE_TYPE_EXTENDED(RpRomDataView, rp_rom_data_view,
Expand Down Expand Up @@ -150,32 +128,8 @@ rp_rom_data_view_class_init(RpRomDataViewClass *klass)
// Install the properties.
g_object_class_install_properties(gobject_class, PROP_LAST, props);

#if GTK_CHECK_VERSION(3,0,0)
/** libadwaita/libhandy **/

// Check if libadwaita-1 is loaded in the process.
// TODO: Verify that it is in fact 1.x if symbol versioning isn't available.
if (!has_checked_adw) {
has_checked_adw = true;
# if GTK_CHECK_VERSION(4,0,0)
// GTK4: libadwaita
# define ADW_SYM_PREFIX "adw_"
# define ADW_SYM_VERSION "LIBADWAITA_1_0"
# else /* !GTK_CHECK_VERSION(4,0,0) */
// GTK3: libhandy
# define ADW_SYM_PREFIX "hdy_"
# define ADW_SYM_VERSION "LIBHANDY_1_0"
# endif
pfn_adw_deck_get_type = (pfnGlibGetType_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "deck_get_type", ADW_SYM_VERSION);
if (pfn_adw_deck_get_type) {
pfn_adw_header_bar_get_type = (pfnGlibGetType_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "header_bar_get_type", ADW_SYM_VERSION);
pfn_adw_header_bar_pack_end = (pfnAdwHeaderBarPackEnd_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "header_bar_pack_end", ADW_SYM_VERSION);
}
}
#endif /* GTK_CHECK_VERSION(3,0,0) */
// Initialize libadwaita/libhandy function pointers.
rp_init_pfn_adwaita();
}

/**
Expand Down Expand Up @@ -1127,8 +1081,9 @@ static void
rp_rom_data_view_create_options_button(RpRomDataView *page)
{
assert(!page->btnOptions);
if (page->btnOptions != nullptr)
if (page->btnOptions != nullptr) {
return;
}

GtkWidget *parent = gtk_widget_get_parent(GTK_WIDGET(page));
if (page->desc_format_type == RP_DFT_XFCE) {
Expand Down Expand Up @@ -1169,12 +1124,14 @@ rp_rom_data_view_create_options_button(RpRomDataView *page)
parent = gtk_widget_get_parent(parent);
#if GTK_CHECK_VERSION(3,0,0)
assert(GTK_IS_BOX(parent));
if (!GTK_IS_BOX(parent))
if (!GTK_IS_BOX(parent)) {
return;
}
#else /* !GTK_CHECK_VERSION(3,0,0) */
assert(GTK_IS_VBOX(parent));
if (!GTK_IS_VBOX(parent))
if (!GTK_IS_VBOX(parent)) {
return;
}
#endif /* GTK_CHECK_VERSION(3,0,0) */

// Next: GtkDialog subclass.
Expand All @@ -1191,7 +1148,7 @@ rp_rom_data_view_create_options_button(RpRomDataView *page)
}
#endif /* GTK_CHECK_VERSION(4,0,0) */

#if GTK_CHECK_VERSION(3,0,0)
#ifdef RP_MAY_HAVE_ADWAITA
bool isLibAdwaita = false;
if (!GTK_IS_DIALOG(parent)) {
// NOTE: As of Nautilus 40, there may be an AdwDeck/HdyDeck here.
Expand All @@ -1206,15 +1163,17 @@ rp_rom_data_view_create_options_button(RpRomDataView *page)
// Main window is based on AdwWindow/HdyWindow, which is derived from
// GtkWindow, not GtkDialog.
assert(GTK_IS_WINDOW(parent));
if (!GTK_IS_WINDOW(parent))
if (!GTK_IS_WINDOW(parent)) {
return;
}
} else
#endif /* GTK_CHECK_VERSION(3,0,0) */
#endif /* RP_MAY_HAVE_ADWAITA */
{
// Main window is derived from GtkDialog.
assert(GTK_IS_DIALOG(parent));
if (!GTK_IS_DIALOG(parent))
if (!GTK_IS_DIALOG(parent)) {
return;
}
}

// Create the RpOptionsMenuButton.
Expand All @@ -1225,11 +1184,11 @@ rp_rom_data_view_create_options_button(RpRomDataView *page)
// (Normally not mapped in a properties dialog; but it *is* mapped in the test program.)
gtk_widget_set_visible(page->btnOptions, gtk_widget_get_mapped(GTK_WIDGET(page)));

#if GTK_CHECK_VERSION(3,0,0)
#ifdef RP_MAY_HAVE_ADWAITA
if (isLibAdwaita) {
// LibAdwaita/LibHandy version doesn't use GtkDialog.
} else
#endif /* GTK_CHECK_VERSION(3,0,0) */
#endif /* RP_MAY_HAVE_ADWAITA */
{
// Not using LibAdwaita/LibHandy, so add the widget to the GtkDialog.
gtk_dialog_add_action_widget(GTK_DIALOG(parent), page->btnOptions, GTK_RESPONSE_NONE);
Expand Down
3 changes: 1 addition & 2 deletions src/gtk/RomDataView_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
* ROM Properties Page shell extension. (GTK+ common) *
* RomDataView.cpp: RomData viewer widget. (Private functions) *
* *
* Copyright (c) 2017-2024 by David Korth. *
* Copyright (c) 2017-2025 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/

#pragma once

#include "config.gtk.h"
#include <gtk/gtk.h>

#include "OptionsMenuButton.hpp"
Expand Down
6 changes: 6 additions & 0 deletions src/gtk/gtk3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_H "${rom-properties-g
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MAX_SRCS "${rom-properties-gtk_GTK3MAX_SRCS}")
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MAX_H "${rom-properties-gtk_GTK3MAX_H}")

# Sources and headers (GTK3 minimum)
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MIN_SRCS "${rom-properties-gtk_GTK3MIN_SRCS}")
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MIN_H "${rom-properties-gtk_GTK3MIN_H}")

# CairoImageConv (GTK+ 3.x)
SET(${PROJECT_NAME}_SRCS ${${PROJECT_NAME}_SRCS} CairoImageConv.cpp)
SET(${PROJECT_NAME}_H ${${PROJECT_NAME}_H} CairoImageConv.hpp)
Expand All @@ -93,6 +97,7 @@ CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.caja-extension.in" "
SET(${PROJECT_NAME}_SRCS
${${PROJECT_NAME}_SRCS}
${${PROJECT_NAME}_GTK3MAX_SRCS}
${${PROJECT_NAME}_GTK3MIN_SRCS}
${${PROJECT_NAME}-notify_SRCS}
${${PROJECT_NAME}_IFUNC_SRCS}
NautilusPlugin.cpp
Expand All @@ -108,6 +113,7 @@ SET(${PROJECT_NAME}_SRCS
SET(${PROJECT_NAME}_H
${${PROJECT_NAME}_H}
${${PROJECT_NAME}_GTK3MAX_H}
${${PROJECT_NAME}_GTK3MIN_H}
${${PROJECT_NAME}-notify_H}
../plugin-helper.h
NautilusPlugin.hpp
Expand Down
6 changes: 6 additions & 0 deletions src/gtk/gtk4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ ADD_DEFINITIONS(-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_66 -DGLIB_VERSION_MAX
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_SRCS "${rom-properties-gtk_SRCS}")
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_H "${rom-properties-gtk_H}")

# Sources and headers (GTK3 minimum)
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MIN_SRCS "${rom-properties-gtk_GTK3MIN_SRCS}")
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK3MIN_H "${rom-properties-gtk_GTK3MIN_H}")

# Sources and headers (GTK4 minimum)
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK4MIN_SRCS "${rom-properties-gtk_GTK4MIN_SRCS}")
STRING(REGEX REPLACE "([^;]+)" "../\\1" ${PROJECT_NAME}_GTK4MIN_H "${rom-properties-gtk_GTK4MIN_H}")
Expand All @@ -70,6 +74,7 @@ ENDIF(ENABLE_ACHIEVEMENTS)
# Sources and headers (GTK4-specific)
SET(${PROJECT_NAME}_SRCS
${${PROJECT_NAME}_SRCS}
${${PROJECT_NAME}_GTK3MIN_SRCS}
${${PROJECT_NAME}_GTK4MIN_SRCS}
${${PROJECT_NAME}-notify_SRCS}
${${PROJECT_NAME}_IFUNC_SRCS}
Expand All @@ -87,6 +92,7 @@ SET(${PROJECT_NAME}_SRCS
)
SET(${PROJECT_NAME}_H
${${PROJECT_NAME}_H}
${${PROJECT_NAME}_GTK3MIN_H}
${${PROJECT_NAME}_GTK4MIN_H}
${${PROJECT_NAME}-notify_H}
../plugin-helper.h
Expand Down
66 changes: 66 additions & 0 deletions src/gtk/pfn_adwaita.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/***************************************************************************
* ROM Properties Page shell extension. (GTK+ common) *
* pfn_adwaita.c: libadwaita/libhandy function pointer handling. *
* *
* Copyright (c) 2017-2025 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/

#include "stdafx.h"
#include "config.gtk.h"
#include "pfn_adwaita.h"

// libdl
#ifdef HAVE_DLVSYM
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif /* _GNU_SOURCE */
#else /* !HAVE_DLVSYM */
# define dlvsym(handle, symbol, version) dlsym((handle), (symbol))
#endif /* HAVE_DLVSYM */
#include <dlfcn.h>

// libadwaita/libhandy function pointers.
// Only initialized if libadwaita/libhandy is linked into the process.
// NOTE: The function pointers are essentially the same, but
// libhandy was renamed to libadwaita for the GTK4 conversion.
// We'll use libadwaita terminology everywhere.

static gsize has_checked_adw = 0;
pfnGlibGetType_t pfn_adw_deck_get_type = NULL;
pfnGlibGetType_t pfn_adw_header_bar_get_type = NULL;
pfnAdwHeaderBarPackEnd_t pfn_adw_header_bar_pack_end = NULL;

#if GTK_CHECK_VERSION(4,0,0)
// GTK4: libadwaita
# define ADW_SYM_PREFIX "adw_"
# define ADW_SYM_VERSION "LIBADWAITA_1_0"
#else /* !GTK_CHECK_VERSION(4,0,0) */
// GTK3: libhandy
# define ADW_SYM_PREFIX "hdy_"
# define ADW_SYM_VERSION "LIBHANDY_1_0"
#endif

/**
* Initialize libadwaita/libhandy function pointers.
* @return TRUE on success; FALSE on failure.
*/
gboolean rp_init_pfn_adwaita(void)
{
if (g_once_init_enter(&has_checked_adw)) {
// Check if libadwaita-1 is loaded in the process.
// TODO: Verify that it is in fact 1.x if symbol versioning isn't available.
pfn_adw_deck_get_type = (pfnGlibGetType_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "deck_get_type", ADW_SYM_VERSION);
if (pfn_adw_deck_get_type) {
pfn_adw_header_bar_get_type = (pfnGlibGetType_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "header_bar_get_type", ADW_SYM_VERSION);
pfn_adw_header_bar_pack_end = (pfnAdwHeaderBarPackEnd_t)dlvsym(
RTLD_DEFAULT, ADW_SYM_PREFIX "header_bar_pack_end", ADW_SYM_VERSION);
}

g_once_init_leave(&has_checked_adw, 1);
}

return (pfn_adw_deck_get_type != NULL);
}
65 changes: 65 additions & 0 deletions src/gtk/pfn_adwaita.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/***************************************************************************
* ROM Properties Page shell extension. (GTK+ common) *
* pfn_adwaita.h: libadwaita/libhandy function pointer handling. *
* *
* Copyright (c) 2017-2025 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/

#pragma once

#include "gtk-compat.h"

G_BEGIN_DECLS

// libadwaita/libhandy function pointers.
// Only initialized if libadwaita/libhandy is linked into the process.
// NOTE: The function pointers are essentially the same, but
// libhandy was renamed to libadwaita for the GTK4 conversion.
// We'll use libadwaita terminology everywhere.
typedef struct _AdwHeaderBar AdwHeaderBar;
typedef GType (*pfnGlibGetType_t)(void);
typedef void (*pfnAdwHeaderBarPackEnd_t)(AdwHeaderBar *self, GtkWidget *child);

#if GTK_CHECK_VERSION(3,0,0)
# define RP_MAY_HAVE_ADWAITA 1

extern pfnGlibGetType_t pfn_adw_deck_get_type;
extern pfnGlibGetType_t pfn_adw_header_bar_get_type;
extern pfnAdwHeaderBarPackEnd_t pfn_adw_header_bar_pack_end;

/**
* Initialize libadwaita/libhandy function pointers.
* @return TRUE on success; FALSE on failure.
*/
gboolean rp_init_pfn_adwaita(void);

#else /* !GTK_CHECK_VERSION(3,0,0) */

// GTK2: No libadwaita/libhandy.
static inline GType pfn_adw_deck_get_type(void)
{
return 0;
}
static inline GType pfn_adw_header_bar_get_type(void)
{
return 0;
}
static inline void pfn_adw_header_bar_pack_end(AdwHeaderBar *self, GtkWidget *child)
{
((void)self);
((void)child);
}

/**
* Initialize libadwaita/libhandy function pointers.
* @return TRUE on success; FALSE on failure.
*/
static inline gboolean rp_init_pfn_adwaita(void)
{
return FALSE;
}

#endif /* GTK_CHECK_VERSION(3,0,0) */

G_END_DECLS

0 comments on commit 68c2082

Please sign in to comment.