summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2023-03-05 12:58:01 +0100
committerChristian Persch <chpe@src.gnome.org>2023-03-05 12:58:01 +0100
commit563abe431ab9e090323086b71851cf3641248f6e (patch)
treea5053cf7d077445f9a8d477ec09ff493c5d34d4b
parentf34ed513db717e4b2dd5e3c38a77574aad874eec (diff)
downloadgnome-terminal-wip/schema-resource.tar.gz
all: Embed reference schemas as resourcewip/schema-resource
-rw-r--r--src/client.gresource.xml22
-rw-r--r--src/meson.build73
-rw-r--r--src/prefs.gresource.xml1
-rw-r--r--src/server.cc2
-rw-r--r--src/terminal-app.cc2
-rw-r--r--src/terminal-app.hh2
-rw-r--r--src/terminal-defines.hh3
-rw-r--r--src/terminal-libgsystem.hh2
-rw-r--r--src/terminal-options.cc2
-rw-r--r--src/terminal-settings-utils.cc175
-rw-r--r--src/terminal-settings-utils.hh2
-rw-r--r--src/terminal.gresource.xml1
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>