diff options
author | Christian Persch <chpe@src.gnome.org> | 2023-03-05 12:58:01 +0100 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2023-03-05 12:58:01 +0100 |
commit | 563abe431ab9e090323086b71851cf3641248f6e (patch) | |
tree | a5053cf7d077445f9a8d477ec09ff493c5d34d4b | |
parent | f34ed513db717e4b2dd5e3c38a77574aad874eec (diff) | |
download | gnome-terminal-wip/schema-resource.tar.gz |
all: Embed reference schemas as resourcewip/schema-resource
-rw-r--r-- | src/client.gresource.xml | 22 | ||||
-rw-r--r-- | src/meson.build | 73 | ||||
-rw-r--r-- | src/prefs.gresource.xml | 1 | ||||
-rw-r--r-- | src/server.cc | 2 | ||||
-rw-r--r-- | src/terminal-app.cc | 2 | ||||
-rw-r--r-- | src/terminal-app.hh | 2 | ||||
-rw-r--r-- | src/terminal-defines.hh | 3 | ||||
-rw-r--r-- | src/terminal-libgsystem.hh | 2 | ||||
-rw-r--r-- | src/terminal-options.cc | 2 | ||||
-rw-r--r-- | src/terminal-settings-utils.cc | 175 | ||||
-rw-r--r-- | src/terminal-settings-utils.hh | 2 | ||||
-rw-r--r-- | src/terminal.gresource.xml | 1 |
12 files changed, 238 insertions, 49 deletions
diff --git a/src/client.gresource.xml b/src/client.gresource.xml new file mode 100644 index 00000000..9e682f7a --- /dev/null +++ b/src/client.gresource.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright © 2012 Christian Persch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope conf it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +--> +<gresources> + <gresource prefix="/org/gnome/terminal"> + <file alias="schemas/compiled" compressed="false">gschemas.compiled</file> + </gresource> +</gresources> diff --git a/src/meson.build b/src/meson.build index 50eee2e0..cf80cbbf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -46,6 +46,33 @@ menubar_ui_nomnemonics = custom_target( output: 'terminal-menubar-without-mnemonics.ui', ) +# Settings schemas + +install_data( + gt_dns_name + '.gschema.xml', + install_dir: gt_prefix / gt_schemadir, + install_tag: 'runtime', +) + +meson.add_install_script( + 'meson_compileschemas.py', + gt_prefix / gt_schemadir, +) + +reference_schemas = custom_target( + 'gschemas.compiled', + command: [ + glib_compile_schemas, + '--targetdir', meson.current_build_dir(), + '--schema-file', files(gt_dns_name + '.gschema.xml'), + '--schema-file', files('external.gschema.xml'), + ], + install: glib_dep.version().version_compare('< 2.75.90'), # FIXME + install_dir: gt_prefix / gt_pkglibdir, + install_tag: 'runtime', + output: 'gschemas.compiled', +) + # Common sources app_sources = files( @@ -181,6 +208,7 @@ server_resources_sources = gnome.compile_resources( 'terminal.gresource.xml', c_name: 'terminal', dependencies: [ + reference_schemas, menubar_ui_mnemonics, menubar_ui_nomnemonics, ], @@ -318,6 +346,9 @@ prefs_resources_sources = gnome.compile_resources( 'terminal-prefs-resources', 'prefs.gresource.xml', c_name: 'terminal', + dependencies: [ + reference_schemas, + ], export: false, install: false, ) @@ -358,6 +389,20 @@ client_sources = client_util_sources + debug_sources + dbus_sources + i18n_sourc 'terminal.cc', ) +client_sources += gnome.compile_resources( + 'terminal-client-resources', + 'client.gresource.xml', + c_name: 'terminal', + dependencies: [ + reference_schemas, + menubar_ui_mnemonics, + menubar_ui_nomnemonics, + ], + export: false, + install: false, +) + + client_incs = [ top_inc, src_inc, @@ -377,6 +422,7 @@ client_deps = [ gio_unix_dep, glib_dep, gtk_dep, + libdl_dep, x11_dep, uuid_dep, vte_dep, @@ -392,33 +438,6 @@ client = executable( sources: client_sources, ) -# Settings schemas - -install_data( - gt_dns_name + '.gschema.xml', - install_dir: gt_prefix / gt_schemadir, - install_tag: 'runtime', -) - -meson.add_install_script( - 'meson_compileschemas.py', - gt_prefix / gt_schemadir, -) - -reference_schemas = custom_target( - 'gschemas.compiled', - command: [ - glib_compile_schemas, - '--targetdir', meson.current_build_dir(), - '--schema-file', files(gt_dns_name + '.gschema.xml'), - '--schema-file', files('external.gschema.xml'), - ], - install: true, - install_dir: gt_prefix / gt_pkglibdir, - install_tag: 'runtime', - output: 'gschemas.compiled', -) - # Nautilus extension if get_option('nautilus_extension') diff --git a/src/prefs.gresource.xml b/src/prefs.gresource.xml index db489765..a4306f93 100644 --- a/src/prefs.gresource.xml +++ b/src/prefs.gresource.xml @@ -19,5 +19,6 @@ <gresource prefix="/org/gnome/terminal"> <file alias="css/terminal.css" compressed="true">terminal.common.css</file> <file alias="ui/preferences.ui" compressed="true" preprocess="xml-stripblanks">preferences.ui</file> + <file alias="schemas/compiled" compressed="false">gschemas.compiled</file> </gresource> </gresources> diff --git a/src/server.cc b/src/server.cc index 718fbc16..3942a1f0 100644 --- a/src/server.cc +++ b/src/server.cc @@ -63,7 +63,7 @@ GModule* g_module_open (char const* file_name, GModuleFlags flags) { - static decltype(&g_module_open) _g_module_open; + static decltype(&g_module_open) _g_module_open = nullptr; if (!_g_module_open) _g_module_open = reinterpret_cast<decltype(_g_module_open)>(dlsym(RTLD_NEXT, "g_module_open")); diff --git a/src/terminal-app.cc b/src/terminal-app.cc index b6740e3c..e0b8c76c 100644 --- a/src/terminal-app.cc +++ b/src/terminal-app.cc @@ -953,7 +953,7 @@ terminal_app_constructed(GObject *object) if (app->settings_backend == nullptr) app->settings_backend = g_settings_backend_get_default (); - app->schema_source = terminal_g_settings_schema_source_get_default(); + app->schema_source = terminal_g_settings_schema_source_get_default(g_application_get_resource_base_path(G_APPLICATION(app))); /* Desktop proxy settings */ app->system_proxy_settings = terminal_g_settings_new(app->settings_backend, diff --git a/src/terminal-app.hh b/src/terminal-app.hh index 94098649..6e2c2aca 100644 --- a/src/terminal-app.hh +++ b/src/terminal-app.hh @@ -28,8 +28,6 @@ G_BEGIN_DECLS #define GNOME_TERMINAL_ICON_NAME "org.gnome.Terminal" -#define TERMINAL_RESOURCES_PATH_PREFIX "/org/gnome/terminal" - #define MONOSPACE_FONT_KEY_NAME "monospace-font-name" /* TerminalApp */ diff --git a/src/terminal-defines.hh b/src/terminal-defines.hh index cd85d60c..c1c1951a 100644 --- a/src/terminal-defines.hh +++ b/src/terminal-defines.hh @@ -51,6 +51,9 @@ enum { #define TERMINAL_PREFERENCES_BINARY_NAME "gnome-terminal-preferences" +#define TERMINAL_RESOURCES_PATH_PREFIX "/org/gnome/terminal" + + G_END_DECLS #endif /* !TERMINAL_DEFINES_H */ diff --git a/src/terminal-libgsystem.hh b/src/terminal-libgsystem.hh index 370cb286..82d31371 100644 --- a/src/terminal-libgsystem.hh +++ b/src/terminal-libgsystem.hh @@ -304,7 +304,7 @@ static inline void gs_local_fd_close (void *v) } /** - * gs_free_close: + * gs_close_fd: * * Call close() on a variable location when it goes out of * scope. diff --git a/src/terminal-options.cc b/src/terminal-options.cc index 6c13955b..207f89e0 100644 --- a/src/terminal-options.cc +++ b/src/terminal-options.cc @@ -126,7 +126,7 @@ terminal_options_ensure_schema_source(TerminalOptions* options) if (options->schema_source) return; - options->schema_source = terminal_g_settings_schema_source_get_default(); + options->schema_source = terminal_g_settings_schema_source_get_default(nullptr); } static TerminalSettingsList * diff --git a/src/terminal-settings-utils.cc b/src/terminal-settings-utils.cc index a40ab5e7..89aef6ed 100644 --- a/src/terminal-settings-utils.cc +++ b/src/terminal-settings-utils.cc @@ -18,13 +18,120 @@ #include "config.h" #define G_SETTINGS_ENABLE_BACKEND +#include <cassert> #include <gio/gsettingsbackend.h> #include "terminal-settings-utils.hh" #include "terminal-client-utils.hh" #include "terminal-debug.hh" +#include "terminal-defines.hh" #include "terminal-libgsystem.hh" + +#ifdef __linux__ + +// We want to load a schema from a built-in compiled schema source. +// However, glib offers no public API to do so (see +// https://gitlab.gnome.org/GNOME/glib/-/issues/499). +// +// This is the simplest and 'least' hacky work-around I could think of. +// Using the knowledge of how g_settings_schema_source_new_from_directory() +// works internally by using g_mapped_file_new() on the gschemas.compiled +// file in the passed directory, we interpose g_mapped_file_new() (which +// works despite -Bsymbolic_functions since libgio and libglib are distinct +// libraries) and when passed the correct (fake) file path, instead of +// creating the mapped file normally, we instead load the gschemas.compiled +// from resources, create a memfd, write the data to it, and then return +// g_mapped_file_new_from_fd() on the memfd. +// +// Then we can use g_settings_schema_source_lookup() to find our schema, +// and g_settings_new_full() to create a GSettings for our build-in schema. + +#include <dlfcn.h> +#include <sys/mman.h> + +#define GSCHEMAS_DOT_COMPILED "gschemas.compiled" +#define RESOURCE_SCHEMA_DIR "/.a69bd5bd-36fd-4cc2-839f-d198d78f56b6" +#define RESOURCE_SCHEMA_FILE RESOURCE_SCHEMA_DIR G_DIR_SEPARATOR_S GSCHEMAS_DOT_COMPILED +#define SCHEMA_RESOURCE_PATH TERMINAL_RESOURCES_PATH_PREFIX "/schemas/compiled" + +extern "C" __attribute__((__visibility__("default"))) +GMappedFile* g_mapped_file_new(char const* filename, + gboolean writable, + GError** error); + + +static GMappedFile* +_g_mapped_file_new_from_resource(char const* resource_path, + char const* memfd_basename, + gboolean writable, + GError** error) +{ + if (writable) { + g_set_error(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cannot create writable resource mapping"); + return nullptr; + } + + gs_unref_bytes auto bytes = g_resources_lookup_data(resource_path, + GResourceLookupFlags(0), + error); + if (!bytes) + return nullptr; + + gs_close_fd auto fd = memfd_create(memfd_basename, MFD_CLOEXEC); + if (fd == -1) { + auto const errsv = errno; + g_set_error(error, G_IO_ERROR, g_io_error_from_errno(errsv), + "memfd_create failed: %s", g_strerror(errsv)); + return nullptr; + } + + auto size = gsize{}; + auto const data = g_bytes_get_data(bytes, &size); + auto const r = write(fd, data, size); + if (r == -1) { + auto const errsv = errno; + g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to write all data to memfd: %s", g_strerror(errsv)); + return nullptr; + } + + return g_mapped_file_new_from_fd(fd, writable, error); +} + +static struct MapResourceEntry { + char const* filename; + char const* resource_path; + char const* memfd_basename; +} const filename_to_resource_maps[] = { + { RESOURCE_SCHEMA_FILE, SCHEMA_RESOURCE_PATH, GSCHEMAS_DOT_COMPILED }, + { nullptr, nullptr }, +}; + +GMappedFile* +g_mapped_file_new(char const* filename, + gboolean writable, + GError** error) +{ + static decltype(&g_mapped_file_new) _g_mapped_file_new = nullptr; + if (!_g_mapped_file_new) + _g_mapped_file_new = reinterpret_cast<decltype(&g_mapped_file_new)>(dlsym(RTLD_NEXT, "g_mapped_file_new")); + assert(_g_mapped_file_new); + + for (auto i = 0; filename_to_resource_maps[i].filename; ++i) { + if (strcmp(filename, filename_to_resource_maps[i].filename) == 0) + return _g_mapped_file_new_from_resource(filename_to_resource_maps[i].resource_path, + filename_to_resource_maps[i].memfd_basename, + writable, + error); + } + + return _g_mapped_file_new(filename, writable, error); +} + +#endif // __linux__ + #ifdef ENABLE_DEBUG static gboolean @@ -552,31 +659,69 @@ schemas_source_verify(GSettingsSchemaSource* source, } GSettingsSchemaSource* -terminal_g_settings_schema_source_get_default(void) +terminal_g_settings_schema_source_get_default(char const* base_path) { GSettingsSchemaSource* default_source = g_settings_schema_source_get_default(); + GSettingsSchemaSource* reference_source = nullptr; + + gs_free_error GError* error = nullptr; + +#if 0 // GLIB_CHECK_VERSION(2, ?, 0) + gs_free auto schema_path = g_strjoin("/", + base_path ? base_path : TERMINAL_RESOURCES_PATH_PREFIX, + "schemas", + "compiled", + nullptr); + reference_source = + g_settings_schema_source_new_from_resource(schemas_path, + G_RESOURCE_LOOKUP_FLAGS_NONE, + nullptr /* parent source */, + true /* trusted */, + &error); + +#else + +#ifdef __linux__ + + reference_source = + g_settings_schema_source_new_from_directory(RESOURCE_SCHEMA_DIR, + nullptr, // parent source, + true, // trusted, + &error); + if (!reference_source) { + g_printerr("Failed to load built-in schema source from resource: %s\n", + error->message); + g_clear_error(&error); + + // fall back to the installed file + } - gs_free auto schema_dir = - terminal_client_get_directory_uninstalled( +#endif // __linux__ + + if (!reference_source) { + gs_free auto schema_dir = + terminal_client_get_directory_uninstalled( #if defined(TERMINAL_SERVER) - TERM_LIBEXECDIR, + TERM_LIBEXECDIR, #elif defined(TERMINAL_PREFERENCES) - TERM_LIBEXECDIR, + TERM_LIBEXECDIR, #elif defined(TERMINAL_CLIENT) - TERM_BINDIR, + TERM_BINDIR, #else #error Need to define installed location #endif - TERM_PKGLIBDIR, - "gschemas.compiled", - GFileTest(0)); + TERM_PKGLIBDIR, + "gschemas.compiled", + GFileTest(0)); + + reference_source = + g_settings_schema_source_new_from_directory(schema_dir, + nullptr /* parent source */, + FALSE /* trusted */, + &error); + } +#endif // glib 2.? - gs_free_error GError* error = nullptr; - GSettingsSchemaSource* reference_source = - g_settings_schema_source_new_from_directory(schema_dir, - nullptr /* parent source */, - FALSE /* trusted */, - &error); if (!reference_source) { /* Can only use the installed schemas, or abort here. */ g_printerr("Failed to load reference schemas: %s\n" diff --git a/src/terminal-settings-utils.hh b/src/terminal-settings-utils.hh index b34afb33..ed3e5301 100644 --- a/src/terminal-settings-utils.hh +++ b/src/terminal-settings-utils.hh @@ -44,7 +44,7 @@ GTree* terminal_g_settings_backend_create_tree(void); void terminal_g_settings_backend_print_tree(GTree* tree); -GSettingsSchemaSource* terminal_g_settings_schema_source_get_default(void); +GSettingsSchemaSource* terminal_g_settings_schema_source_get_default(char const* base_path); GTree* terminal_g_settings_backend_create_tree(void); diff --git a/src/terminal.gresource.xml b/src/terminal.gresource.xml index dfa8f5c6..5ff5763d 100644 --- a/src/terminal.gresource.xml +++ b/src/terminal.gresource.xml @@ -26,5 +26,6 @@ <file alias="ui/search-popover.ui" compressed="true" preprocess="xml-stripblanks">search-popover.ui</file> <file alias="ui/terminal.about" compressed="true">terminal.about</file> <file alias="ui/window.ui" compressed="true" preprocess="xml-stripblanks">terminal-window.ui</file> + <file alias="schemas/compiled" compressed="false">gschemas.compiled</file> </gresource> </gresources> |