From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- snap/local/filedialog-native.patch | 385 ++++++++++++++++++++++++++++++++++ snap/local/glib-spawn-no-close.patch | 16 ++ snap/local/print-inkscape-version.cpp | 42 ++++ snap/local/scripts/inkscape-variables | 30 +++ snap/local/scripts/private-fontcache | 42 ++++ 5 files changed, 515 insertions(+) create mode 100644 snap/local/filedialog-native.patch create mode 100644 snap/local/glib-spawn-no-close.patch create mode 100644 snap/local/print-inkscape-version.cpp create mode 100755 snap/local/scripts/inkscape-variables create mode 100755 snap/local/scripts/private-fontcache (limited to 'snap/local') diff --git a/snap/local/filedialog-native.patch b/snap/local/filedialog-native.patch new file mode 100644 index 0000000..ce82d92 --- /dev/null +++ b/snap/local/filedialog-native.patch @@ -0,0 +1,385 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Taken from: https://gitlab.com/inkscape/inkscape/-/merge_requests/4237 +# And used only for the snap currently. +diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp +index c3aba062dd963e72ec775bd9a2e3a753bf08ee0f..19203350bb3bae36e9157e538a0889b4c1de5a78 100644 +--- a/src/ui/dialog/filedialogimpl-gtkmm.cpp ++++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp +@@ -78,41 +78,26 @@ void fileDialogExtensionToPattern(Glib::ustring &pattern, Glib::ustring &extensi + } + } + ++/*######################################################################### ++### F I L E D I A L O G B A S E C L A S S ++#########################################################################*/ + +-void findEntryWidgets(Gtk::Container *parent, std::vector &result) ++// Small function so the translatable strings stay out of the header ++const char * FileDialogBaseGtk::accept_label(Gtk::FileChooserAction dialogType) + { +- if (!parent) { +- return; +- } +- std::vector children = parent->get_children(); +- for (auto child : children) { +- GtkWidget *wid = child->gobj(); +- if (GTK_IS_ENTRY(wid)) +- result.push_back(dynamic_cast(child)); +- else if (GTK_IS_CONTAINER(wid)) +- findEntryWidgets(dynamic_cast(child), result); ++ if (dialogType == Gtk::FILE_CHOOSER_ACTION_OPEN) { ++ return _("_Open"); ++ } else { ++ return _("_Save"); + } + } + +-void findExpanderWidgets(Gtk::Container *parent, std::vector &result) ++// Small function so the translatable strings stay out of the header ++const char * FileDialogBaseGtk::cancel_label() + { +- if (!parent) +- return; +- std::vector children = parent->get_children(); +- for (auto child : children) { +- GtkWidget *wid = child->gobj(); +- if (GTK_IS_EXPANDER(wid)) +- result.push_back(dynamic_cast(child)); +- else if (GTK_IS_CONTAINER(wid)) +- findExpanderWidgets(dynamic_cast(child), result); +- } ++ return _("_Cancel"); + } + +- +-/*######################################################################### +-### F I L E D I A L O G B A S E C L A S S +-#########################################################################*/ +- + void FileDialogBaseGtk::internalSetup() + { + // Open executable file dialogs don't need the preview panel +@@ -126,11 +111,15 @@ void FileDialogBaseGtk::internalSetup() + + previewCheckbox.signal_toggled().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback)); + ++ previewCheckbox.show(); ++ + svgexportCheckbox.set_label(Glib::ustring(_("Export as SVG 1.1 per settings in Preferences dialog"))); + svgexportCheckbox.set_active(enableSVGExport); + + svgexportCheckbox.signal_toggled().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_svgexportEnabledCB)); + ++ svgexportCheckbox.show(); ++ + // Catch selection-changed events, so we can adjust the text widget + signal_update_preview().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback)); + +@@ -220,7 +209,7 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window &parentWindow, const Gl + + + /* Set the pwd and/or the filename */ +- if (dir.size() > 0) { ++ if (dir.size() > 0 && Glib::getenv("GTK_USE_PORTAL").empty()) { + Glib::ustring udir(dir); + Glib::ustring::size_type len = udir.length(); + // leaving a trailing backslash on the directory name leads to the infamous +@@ -241,9 +230,6 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window &parentWindow, const Gl + //###### Add the file types menu + createFilterMenu(); + +- add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); +- set_default(*add_button(_("_Open"), Gtk::RESPONSE_OK)); +- + //###### Allow easy access to our examples folder + + using namespace Inkscape::IO::Resource; +@@ -372,12 +358,11 @@ void FileOpenDialogImplGtk::createFilterMenu() + bool FileOpenDialogImplGtk::show() + { + set_modal(TRUE); // Window +- sp_transientize(GTK_WIDGET(gobj())); // Make transient + gint b = run(); // Dialog + svgPreview.showNoPreview(); + hide(); + +- if (b == Gtk::RESPONSE_OK) { ++ if (b == Gtk::RESPONSE_ACCEPT) { + // This is a hack, to avoid the warning messages that + // Gtk::FileChooser::get_filter() returns + // should be: Gtk::FileFilter *filter = get_filter(); +@@ -511,37 +496,18 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Gl + + childBox.pack_start(checksBox); + childBox.pack_end(fileTypeComboBox); ++ childBox.show(); ++ + checksBox.pack_start(fileTypeCheckbox); + checksBox.pack_start(previewCheckbox); + checksBox.pack_start(svgexportCheckbox); ++ checksBox.show(); + + set_extra_widget(childBox); + +- // Let's do some customization +- fileNameEntry = nullptr; +- Gtk::Container *cont = get_toplevel(); +- std::vector entries; +- findEntryWidgets(cont, entries); +- // g_message("Found %d entry widgets\n", entries.size()); +- if (!entries.empty()) { +- // Catch when user hits [return] on the text field +- fileNameEntry = entries[0]; +- fileNameEntry->signal_activate().connect( +- sigc::mem_fun(*this, &FileSaveDialogImplGtk::fileNameEntryChangedCallback)); +- } + signal_selection_changed().connect( + sigc::mem_fun(*this, &FileSaveDialogImplGtk::fileNameChanged)); + +- // Let's do more customization +- std::vector expanders; +- findExpanderWidgets(cont, expanders); +- // g_message("Found %d expander widgets\n", expanders.size()); +- if (!expanders.empty()) { +- // Always show the file list +- Gtk::Expander *expander = expanders[0]; +- expander->set_expanded(true); +- } +- + // allow easy access to the user's own templates folder + using namespace Inkscape::IO::Resource; + char const *templates = Inkscape::IO::Resource::get_path(USER, TEMPLATES); +@@ -549,14 +515,6 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Gl + Inkscape::IO::file_test(templates, G_FILE_TEST_IS_DIR) && g_path_is_absolute(templates)) { + add_shortcut_folder(templates); + } +- +- // if (extension == NULL) +- // checkbox.set_sensitive(FALSE); +- +- add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); +- set_default(*add_button(_("_Save"), Gtk::RESPONSE_OK)); +- +- show_all_children(); + } + + /** +@@ -566,44 +524,7 @@ FileSaveDialogImplGtk::~FileSaveDialogImplGtk() + = default; + + /** +- * Callback for fileNameEntry widget +- */ +-void FileSaveDialogImplGtk::fileNameEntryChangedCallback() +-{ +- if (!fileNameEntry) +- return; +- +- Glib::ustring fileName = fileNameEntry->get_text(); +- if (!Glib::get_charset()) // If we are not utf8 +- fileName = Glib::filename_to_utf8(fileName); +- +- // g_message("User hit return. Text is '%s'\n", fileName.c_str()); +- +- if (!Glib::path_is_absolute(fileName)) { +- // try appending to the current path +- // not this way: fileName = get_current_folder() + "/" + fileName; +- std::vector pathSegments; +- pathSegments.emplace_back(get_current_folder()); +- pathSegments.push_back(fileName); +- fileName = Glib::build_filename(pathSegments); +- } +- +- // g_message("path:'%s'\n", fileName.c_str()); +- +- if (Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) { +- set_current_folder(fileName); +- } else if (/*Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR)*/ true) { +- // dialog with either (1) select a regular file or (2) cd to dir +- // simulate an 'OK' +- set_filename(fileName); +- response(Gtk::RESPONSE_OK); +- } +-} +- +- +- +-/** +- * Callback for fileNameEntry widget ++ * Callback for fileType widget changing + */ + void FileSaveDialogImplGtk::fileTypeChangedCallback() + { +@@ -649,6 +570,10 @@ void FileSaveDialogImplGtk::addFileType(Glib::ustring name, Glib::ustring patter + fileTypeComboBox.append(guessType.name); + fileTypes.push_back(guessType); + ++ auto filter = Gtk::FileFilter::create(); ++ filter->set_name(guessType.name); ++ filter->add_pattern(guessType.pattern); ++ add_filter(filter); + + fileTypeComboBox.set_active(0); + fileTypeChangedCallback(); // call at least once to set the filter +@@ -656,8 +581,13 @@ void FileSaveDialogImplGtk::addFileType(Glib::ustring name, Glib::ustring patter + + void FileSaveDialogImplGtk::createFilterMenu() + { ++ if (_dialogType == CUSTOM_TYPE) { ++ return; ++ } ++ + Inkscape::Extension::DB::OutputList extension_list; + Inkscape::Extension::db.get_output_list(extension_list); ++ + knownExtensions.clear(); + + bool is_raster = _dialogType == RASTER_TYPES; +@@ -680,6 +610,11 @@ void FileSaveDialogImplGtk::createFilterMenu() + type.extension = omod; + fileTypeComboBox.append(type.name); + fileTypes.push_back(type); ++ ++ auto filter = Gtk::FileFilter::create(); ++ filter->set_name(type.name); ++ filter->add_pattern(type.pattern); ++ add_filter(filter); + } + + //#Let user choose +@@ -690,6 +625,10 @@ void FileSaveDialogImplGtk::createFilterMenu() + fileTypeComboBox.append(guessType.name); + fileTypes.push_back(guessType); + ++ auto filter = Gtk::FileFilter::create(); ++ filter->set_name(guessType.name); ++ filter->add_pattern(guessType.pattern); ++ add_filter(filter); + + fileTypeComboBox.set_active(0); + fileTypeChangedCallback(); // call at least once to set the filter +@@ -704,13 +643,12 @@ bool FileSaveDialogImplGtk::show() + { + change_path(myFilename); + set_modal(TRUE); // Window +- sp_transientize(GTK_WIDGET(gobj())); // Make transient + gint b = run(); // Dialog + svgPreview.showNoPreview(); + set_preview_widget_active(false); + hide(); + +- if (b == Gtk::RESPONSE_OK) { ++ if (b == Gtk::RESPONSE_ACCEPT) { + updateNameAndExtension(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + +@@ -799,6 +737,11 @@ FileSaveDialogImplGtk::change_title(const Glib::ustring& title) + */ + void FileSaveDialogImplGtk::change_path(const Glib::ustring &path) + { ++ if (!Glib::getenv("GTK_USE_PORTAL").empty()) { ++ // If we're using the portal we can't control the path ++ return; ++ } ++ + myFilename = path; + + if (Glib::file_test(myFilename, Glib::FILE_TEST_IS_DIR)) { +@@ -842,6 +785,27 @@ void FileSaveDialogImplGtk::updateNameAndExtension() + myFilename = tmp; + } + ++ if (!Glib::getenv("GTK_USE_PORTAL").empty()) { ++ // If we're using the portal we can't change the filename ++ // and we need to use the filter to find the extension ++ GtkFileChooser *gtkFileChooser = Gtk::FileChooser::gobj(); ++ GtkFileFilter *filter = gtk_file_chooser_get_filter(gtkFileChooser); ++ ++ extension = nullptr; ++ if (filter) { ++ auto name = gtk_file_filter_get_name(filter); ++ ++ for (auto type : fileTypes) { ++ if (type.name == name) { ++ extension = type.extension; ++ break; ++ } ++ } ++ } ++ ++ return; ++ } ++ + Inkscape::Extension::Output *newOut = extension ? dynamic_cast(extension) : nullptr; + if (fileTypeCheckbox.get_active() && newOut) { + // Append the file extension if it's not already present and display it in the file name entry field +diff --git a/src/ui/dialog/filedialogimpl-gtkmm.h b/src/ui/dialog/filedialogimpl-gtkmm.h +index b16d36285c300d1c423e1e75f3260baaf8276b2b..8fde5824ab79f04115441bded47550aebab2ebea 100644 +--- a/src/ui/dialog/filedialogimpl-gtkmm.h ++++ b/src/ui/dialog/filedialogimpl-gtkmm.h +@@ -49,14 +49,6 @@ void + fileDialogExtensionToPattern(Glib::ustring &pattern, + Glib::ustring &extension); + +-void +-findEntryWidgets(Gtk::Container *parent, +- std::vector &result); +- +-void +-findExpanderWidgets(Gtk::Container *parent, +- std::vector &result); +- + class FileType + { + public: +@@ -75,7 +67,7 @@ class FileType + * This class is the base implementation for the others. This + * reduces redundancies and bugs. + */ +-class FileDialogBaseGtk : public Gtk::FileChooserDialog ++class FileDialogBaseGtk : public Gtk::FileChooserNative + { + public: + +@@ -84,19 +76,7 @@ public: + */ + FileDialogBaseGtk(Gtk::Window& parentWindow, const Glib::ustring &title, + Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) : +- Gtk::FileChooserDialog(parentWindow, title, dialogType), +- preferenceBase(preferenceBase ? preferenceBase : "unknown"), +- _dialogType(type) +- { +- internalSetup(); +- } +- +- /** +- * +- */ +- FileDialogBaseGtk(Gtk::Window& parentWindow, const char *title, +- Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) : +- Gtk::FileChooserDialog(parentWindow, title, dialogType), ++ Gtk::FileChooserNative(title, parentWindow, dialogType, accept_label(dialogType), cancel_label()), + preferenceBase(preferenceBase ? preferenceBase : "unknown"), + _dialogType(type) + { +@@ -130,6 +110,9 @@ protected: + Gtk::CheckButton svgexportCheckbox; + + private: ++ const char * accept_label(Gtk::FileChooserAction dialogType); ++ const char * cancel_label(); ++ + void internalSetup(); + + /** +@@ -281,9 +264,8 @@ private: + Inkscape::Extension::Extension *extension; + + /** +- * Callback for user input into fileNameEntry ++ * Callback for file name changed + */ +- void fileNameEntryChangedCallback(); + void fileNameChanged(); + bool fromCB; + }; diff --git a/snap/local/glib-spawn-no-close.patch b/snap/local/glib-spawn-no-close.patch new file mode 100644 index 0000000..c17900e --- /dev/null +++ b/snap/local/glib-spawn-no-close.patch @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Disable closing file descriptors because the snap confinement has some +# that it doesn't want us to close +diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp +index 0d0a07e4b4..d94774868e 100644 +--- a/src/extension/implementation/script.cpp ++++ b/src/extension/implementation/script.cpp +@@ -904,7 +904,7 @@ int Script::execute (const std::list &in_command, + try { + Glib::spawn_async_with_pipes(working_directory, // working directory + argv, // arg v +- static_cast(0), // no flags ++ Glib::SPAWN_LEAVE_DESCRIPTORS_OPEN, + sigc::slot(), + &_pid, // Pid + nullptr, // STDIN diff --git a/snap/local/print-inkscape-version.cpp b/snap/local/print-inkscape-version.cpp new file mode 100644 index 0000000..17d0c17 --- /dev/null +++ b/snap/local/print-inkscape-version.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Use the Inkscape compiled version identifier and print it out with +// the Snap restrictions on versions. Only a few characters allowed +// and a limit of 32 characters. +#include "inkscape-version.h" + +#include +#include + +int main (int argc, char ** argv) { + std::string outstr; + + for (const auto& c : std::string{Inkscape::version_string}) { + if (outstr.length() == 32) { + break; + } + + if (std::isalpha(c) || std::isdigit(c)) { + outstr.append(1, c); + continue; + } + + if (c == '(' || c == ')' || c == ',') { + continue; + } + + if (c == '.' || c == '-') { + outstr.append(1, c); + continue; + } + + outstr.append(1, '-'); + } + + while (outstr.length() > 0 && !std::isalpha(outstr.back()) && !std::isdigit(outstr.back())) { + outstr.pop_back(); + } + + std::cout << outstr << std::endl; + + return 0; +} diff --git a/snap/local/scripts/inkscape-variables b/snap/local/scripts/inkscape-variables new file mode 100755 index 0000000..1c8d456 --- /dev/null +++ b/snap/local/scripts/inkscape-variables @@ -0,0 +1,30 @@ +#!/bin/bash +# Set all the Inkscape specific environment variables +# SPDX-License-Identifier: GPL-2.0-or-later + +# If we're on an older snapd that doesn't have SNAP_REAL_HOME try +# to fake it +if [ -z $SNAP_REAL_HOME ]; then +SNAP_REAL_HOME=`getent passwd $UID | cut -d ':' -f 6` +# fallback to pre-1.2 behaviour in case getent doesn't work due to apparmor +# could suggest to install unscd to proxy requests to blocked nss module +SNAP_REAL_HOME=${SNAP_REAL_HOME:-${SNAP_USER_DATA}/../../..} +fi + +export INKSCAPE_PROFILE_DIR=${SNAP_REAL_HOME}/.config/inkscape +export INKSCAPE_LOCALEDIR=${SNAP}/share/locale +export INKSCAPE_DATADIR=${SNAP}/share +export INKSCAPE_EXTENSIONS_DIR=${SNAP_USER_COMMON}/extensions/ + +export GTK_USE_PORTAL=1 + +export GS_LIB=${SNAP}/usr/share/ghostscript/9.55.0/Resource/Init/ +if [ ! -x ${GS_LIB} ]; then + echo "WARN: Ghostscript library not executable: $GS_LIB" +fi + +export PYTHONPATH=/usr/lib/python3.10:/usr/lib/python3.10/lib-dynload:${SNAP}/lib/python3.10/site-packages:${SNAP}/usr/lib/python3/dist-packages + +cd $SNAP_REAL_HOME + +exec "$@" diff --git a/snap/local/scripts/private-fontcache b/snap/local/scripts/private-fontcache new file mode 100755 index 0000000..e85623d --- /dev/null +++ b/snap/local/scripts/private-fontcache @@ -0,0 +1,42 @@ +#!/bin/bash +# Ensure that we prioritize using the private font cache +# SPDX-License-Identifier: GPL-2.0-or-later + +# ensure_dir_exists calls `mkdir -p` if the given path is not a directory. +# This speeds up execution time by avoiding unnecessary calls to mkdir. +# +# Usage: ensure_dir_exists []... +function ensure_dir_exists() { + [ -d "$1" ] || mkdir -p "$@" +} + +# Set $REALHOME to the users real home directory +REALHOME=$(getent passwd $UID | cut -d ':' -f 6) +# fallback to pre-1.2 behaviour in case getent doesn't work due to apparmor +# could suggest to install unscd to proxy requests to blocked nss module +REALHOME=${REALHOME:-${SNAP_USER_DATA}/../../..} + +# Set config folder to local path +export XDG_CONFIG_HOME="$SNAP_USER_DATA/.config" +ensure_dir_exists "$XDG_CONFIG_HOME" +chmod 700 "$XDG_CONFIG_HOME" + +function make_user_fontconfig { + echo "" + echo " $REALHOME/.local/share/fonts" + echo " $REALHOME/.fonts" + echo " fontconfig" + echo " $SNAP_DATA/fontconfig" + echo " /etc/fonts/fonts.conf" + if [ ! -z $SNAP_DESKTOP_RUNTIME ]; then + echo " ${SNAP_DESKTOP_RUNTIME}/etc/fonts/fonts.conf" + fi + echo "" +} + +ensure_dir_exists "$XDG_CONFIG_HOME/fontconfig" +make_user_fontconfig > "$XDG_CONFIG_HOME/fontconfig/fonts.conf" + +export FONTCONFIG_FILE=${XDG_CONFIG_HOME}/fontconfig/fonts.conf + +exec "$@" -- cgit v1.2.3