Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package vte for openSUSE:Factory checked in at 2022-11-01 13:40:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/vte (Old) and /work/SRC/openSUSE:Factory/.vte.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "vte" Tue Nov 1 13:40:32 2022 rev:140 rq:1032382 version:0.70.1 Changes: -------- --- /work/SRC/openSUSE:Factory/vte/vte.changes 2022-09-21 14:41:53.721665587 +0200 +++ /work/SRC/openSUSE:Factory/.vte.new.2275/vte.changes 2022-11-01 13:40:36.679271463 +0100 @@ -1,0 +2,15 @@ +Thu Oct 27 11:08:00 UTC 2022 - bjorn....@gmail.com + +- Update to version 0.70.1: + + app: + - Disconnect signal handlers on dispose. + - Filter unwanted environment variables. + + build: + - Add define for darwin. + - Fix netbsd define. + + widget: + - Don't consume right clicks on gtk4. + - Implement clipboard for gtk4. + * Updated translations. + +------------------------------------------------------------------- Old: ---- vte-0.70.0.obscpio New: ---- vte-0.70.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ vte.spec ++++++ --- /var/tmp/diff_new_pack.ayj9Ci/_old 2022-11-01 13:40:37.919278060 +0100 +++ /var/tmp/diff_new_pack.ayj9Ci/_new 2022-11-01 13:40:37.919278060 +0100 @@ -27,7 +27,7 @@ %bcond_with glade_support Name: vte -Version: 0.70.0 +Version: 0.70.1 Release: 0 Summary: Terminal Emulator Library License: CC-BY-4.0 AND LGPL-3.0-or-later AND GPL-3.0-or-later AND MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.ayj9Ci/_old 2022-11-01 13:40:37.947278208 +0100 +++ /var/tmp/diff_new_pack.ayj9Ci/_new 2022-11-01 13:40:37.951278230 +0100 @@ -5,7 +5,7 @@ <param name="scm">git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> - <param name="revision">refs/tags/0.70.0</param> + <param name="revision">refs/tags/0.70.1</param> <param name="exclude">doc/vttest.*</param> </service> <service name="tar" mode="buildtime" /> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.ayj9Ci/_old 2022-11-01 13:40:37.967278316 +0100 +++ /var/tmp/diff_new_pack.ayj9Ci/_new 2022-11-01 13:40:37.971278336 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://gitlab.gnome.org/GNOME/vte.git</param> - <param name="changesrevision">ae4a5d7df9e32ab40ceca5e06240561e819db148</param></service></servicedata> + <param name="changesrevision">5bf476f1d7283bc805ac8ae6abe94f81ffd7be05</param></service></servicedata> (No newline at EOF) ++++++ vte-0.70.0.obscpio -> vte-0.70.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/meson.build new/vte-0.70.1/meson.build --- old/vte-0.70.0/meson.build 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/meson.build 2022-09-23 20:46:10.000000000 +0200 @@ -17,7 +17,7 @@ project( 'vte', ['c', 'cpp'], - version: '0.70.0', + version: '0.70.1', license: ['LGPL-3.0-or-later', 'GPL-3.0-or-later'], default_options: [ 'buildtype=release', @@ -229,9 +229,15 @@ libc_feature_defines = [] +elif system == 'darwin' + # See issue #2592 + libc_feature_defines += [ + ['_DARWIN_C_SOURCE', '1'], + ] + elif system == 'netbsd' libc_feature_defines += [ - '_NETBSD_SOURCE', + ['_NETBSD_SOURCE', '1'], ] endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/po/tr.po new/vte-0.70.1/po/tr.po --- old/vte-0.70.0/po/tr.po 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/po/tr.po 2022-09-23 20:46:10.000000000 +0200 @@ -1,5 +1,5 @@ # Turkish translation of vte. -# Copyright (C) 2003 vte's COPYRIGHT HOLDER +# Copyright (C) 2003-2022 vte's COPYRIGHT HOLDER # This file is distributed under the same license as the vte package. # # G??rkem ??etin <gor...@gelecek.com.tr>, 2003. @@ -14,7 +14,7 @@ msgstr "" "Project-Id-Version: vte master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/vte/issues\n" -"POT-Creation-Date: 2020-04-27 18:50+0000\n" +"POT-Creation-Date: 2022-08-06 12:19+0000\n" "PO-Revision-Date: 2020-04-28 15:36+0300\n" "Last-Translator: Emin Tufan ??etin <etce...@gmail.com>\n" "Language-Team: T??rk??e <gnome-t...@gnome.org>\n" @@ -25,115 +25,43 @@ "X-Generator: Poedit 2.3\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: src/vte.cc:7843 +#: src/vte.cc:7643 msgid "WARNING" msgstr "UYARI" -#: src/vte.cc:7845 +#: src/vte.cc:7645 msgid "GnuTLS not enabled; data will be written to disk unencrypted!" msgstr "GnuTLS etkin de??il; veriler diske ??ifrelenmemi?? olarak yaz??lacak!" -#: src/spawn.cc:104 +#: src/spawn.cc:124 #, c-format msgid "Failed to set pipe nonblocking: %s" msgstr "Boru nonblocking belirlenemedi. %s" -#: src/spawn.cc:148 +#: src/spawn.cc:169 #, c-format msgid "poll error: %s" msgstr "poll hatas??: %s" -#: src/spawn.cc:154 +#: src/spawn.cc:176 msgid "Operation timed out" msgstr "????lem zaman a????m??na u??rad??" -#: src/spawn.cc:164 +#: src/spawn.cc:186 msgid "Operation was cancelled" msgstr "????lem iptal edildi" -#: src/spawn.cc:182 +#: src/spawn.cc:204 #, c-format msgid "Failed to read from child pipe (%s)" msgstr "??ocuk borudan (%s) okunurken hata" -#: src/spawn.cc:576 +#: src/spawn.cc:639 #, c-format msgid "Failed to change to directory ???%s???: %s" msgstr "???%s??? dizinine de??i??tirme ba??ar??s??z: %s" -#: src/spawn.cc:645 +#: src/spawn.cc:708 #, c-format msgid "Failed to execute child process ???%s???: " msgstr "???%s??? ??ocuk s??reci ??al????t??r??lamad??: " - -#~ msgid "Unable to convert characters from %s to %s." -#~ msgstr "Karakterler %s??den %s??e d??n????t??r??lemiyor." - -#~ msgid "Error (%s) converting data for child, dropping." -#~ msgstr "??ocuk s??re?? i??in veriyi ??evirirken hata (%s), b??rak??l??yor." - -#~ msgid "Copy" -#~ msgstr "Kopyala" - -#~ msgid "Paste" -#~ msgstr "Yap????t??r" - -#~ msgid "Reset (use Ctrl to reset and clear)" -#~ msgstr "S??f??rla (S??f??rlamak ve temizlemek i??in Ctrl'yi kullan??n)" - -#~ msgid "Reset" -#~ msgstr "S??f??rla" - -#~ msgid "Toggle input enabled setting" -#~ msgstr "Giri??i a??/kapa" - -#~ msgid "Input" -#~ msgstr "Giri??" - -#~ msgid "Could not open console.\n" -#~ msgstr "Konsol a????lamad??.\n" - -#~ msgid "Could not parse the geometry spec passed to --geometry" -#~ msgstr "--geometry'de belirtilen geometri belirtimi ayr????t??r??lamad??" - -#~ msgid "Unable to send data to child, invalid charset convertor" -#~ msgstr "Alt s??rece veri g??nderilemedi, ge??ersiz karakter k??mesi ??evirici" - -#~ msgid "Error reading PTY size, using defaults: %s\n" -#~ msgstr "PTY boyutu okunurken hata, ??ntan??ml?? de??erler kullan??l??yor: %s\n" - -#~ msgid "Attempt to set invalid NRC map '%c'." -#~ msgstr "Ge??ersiz NRC haritas?? '%c' ayarlanmaya ??al??????ld??." - -#~ msgid "Unrecognized identified coding system." -#~ msgstr "An??msanmayan tan??mlanm???? kodlama sistemi." - -#~ msgid "Attempt to set invalid wide NRC map '%c'." -#~ msgstr "Ge??ersiz geni?? NRC haritas?? '%c' ayarlanmaya ??al??????ld??." - -#~ msgid "Duplicate (%s/%s)!" -#~ msgstr "??ift (%s/%s)!" - -#~ msgid "Error compiling regular expression \"%s\"." -#~ msgstr "D??zenli ifade derlenirken hata: \"%s\"." - -#~ msgid "_vte_conv_open() failed setting word characters" -#~ msgstr "_vte_iconv_open() kelime karakterlerini ayarlarken ba??ar??s??z oldu" - -#~ msgid "can not run %s" -#~ msgstr "%s ??al????t??r??lamad??" - -#~ msgid "Error creating signal pipe." -#~ msgstr "Sinyal borusu olu??tururken hata." - -#~ msgid "No handler for control sequence `%s' defined." -#~ msgstr "`%s' kontrol serisi i??in i??lemci tan??mlanmam????." - -#~ msgid "Error setting PTY size: %s." -#~ msgstr "PTY boyutu ayarlan??rken hata: %s." - -#~ msgid "Got unexpected (key?) sequence `%s'." -#~ msgstr "Beklenmeyen (tu???) serisi `%s' al??nd??." - -#~ msgid "Unknown pixel mode %d.\n" -#~ msgstr "Bilinmeyen benek kipi %d.\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/app/app.cc new/vte-0.70.1/src/app/app.cc --- old/vte-0.70.0/src/app/app.cc 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/app/app.cc 2022-09-23 20:46:10.000000000 +0200 @@ -157,6 +157,86 @@ return m_map_fds; } + auto environment_for_spawn() const noexcept + { + auto envv = g_get_environ(); + + // Merge in extra variables + if (environment) { + for (auto i = 0; environment[i]; ++i) { + auto const eq = strchr(environment[i], '='); + if (eq) { + auto const var = vte::glib::take_string(g_strndup(environment[i], eq - environment[i])); + envv = g_environ_setenv(envv, var.get(), eq + 1, true); + } else { + envv = g_environ_unsetenv(envv, environment[i]); + } + } + } + + // Cleanup environment + // List of variables and prefixes copied from gnome-terminal. + for (auto const& var : {"COLORTERM", + "COLUMNS", + "DESKTOP_STARTUP_ID", + "EXIT_CODE", + "EXIT_STATUS", + "GIO_LAUNCHED_DESKTOP_FILE", + "GIO_LAUNCHED_DESKTOP_FILE_PID", + "GJS_DEBUG_OUTPUT", + "GJS_DEBUG_TOPICS", + "GNOME_DESKTOP_ICON", + "INVOCATION_ID", + "JOURNAL_STREAM", + "LINES", + "LISTEN_FDNAMES", + "LISTEN_FDS", + "LISTEN_PID", + "MAINPID", + "MANAGERPID", + "NOTIFY_SOCKET", + "NOTIFY_SOCKET", + "PIDFILE", + "PWD", + "REMOTE_ADDR", + "REMOTE_PORT", + "SERVICE_RESULT", + "SHLVL", + "TERM", + "VTE_VERSION", + "WATCHDOG_PID", + "WATCHDOG_USEC", + "WINDOWID"}) { + envv = g_environ_unsetenv(envv, var); + } + + for (auto const& prefix : {"GNOME_TERMINAL_", + + // other terminals + "FOOT_", + "ITERM2_", + "MC_", + "MINTTY_", + "PUTTY_", + "RXVT_", + "TERM_", + "URXVT_", + "WEZTERM_", + "XTERM_"}) { + for (auto i = 0; envv[i]; ++i) { + if (!g_str_has_prefix (envv[i], prefix)) + continue; + + auto const eq = strchr(envv[i], '='); + g_assert(eq); + auto const var = vte::glib::take_string(g_strndup(envv[i], eq - envv[i])); + envv = g_environ_unsetenv(envv, var.get()); + } + } + + return vte::glib::take_strv(envv); + } + private: std::vector<vte::libc::FD> m_fds{}; @@ -732,7 +812,7 @@ return rv; } -}; +}; // class Options Options options{}; /* global */ @@ -1684,6 +1764,7 @@ GError** error) { auto const spawn_flags = GSpawnFlags(G_SPAWN_SEARCH_PATH_FROM_ENVP | + VTE_SPAWN_NO_PARENT_ENVV | (options.no_systemd_scope ? VTE_SPAWN_NO_SYSTEMD_SCOPE : 0) | (options.require_systemd_scope ? VTE_SPAWN_REQUIRE_SYSTEMD_SCOPE : 0)); auto fds = options.fds(); @@ -1692,7 +1773,7 @@ VTE_PTY_DEFAULT, options.working_directory, argv, - options.environment, + options.environment_for_spawn().get(), fds.data(), fds.size(), map_fds.data(), map_fds.size(), spawn_flags, @@ -2623,6 +2704,15 @@ window->search_popover = nullptr; } + // Disconnect all signal handlers from the terminal + g_signal_handlers_disconnect_matched(window->terminal, + GSignalMatchType(G_SIGNAL_MATCH_DATA), + 0, // signal id + 0, // detail quark + nullptr, // closure + nullptr, // func + window); + G_OBJECT_CLASS(vteapp_window_parent_class)->dispose(object); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/clipboard-gtk.cc new/vte-0.70.1/src/clipboard-gtk.cc --- old/vte-0.70.0/src/clipboard-gtk.cc 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/clipboard-gtk.cc 2022-09-23 20:46:10.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright ?? 2020 Christian Persch + * Copyright ?? 2020, 2022 Christian Persch * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -18,6 +18,7 @@ #include "config.h" #include "clipboard-gtk.hh" +#include "glib-glue.hh" #include "gtk-glue.hh" #include "widget.hh" #include "vteinternal.hh" @@ -26,6 +27,9 @@ #include <stdexcept> #include <utility> +#define MIME_TYPE_TEXT_PLAIN_UTF8 "text/plain;charset=utf-8" +#define MIME_TYPE_TEXT_HTML_UTF16 "text/html" + namespace vte::platform { // Note: @@ -64,9 +68,10 @@ throw std::runtime_error{"Failed to create clipboard"}; } -#if VTE_GTK == 3 - class Clipboard::Offer { +#if VTE_GTK == 4 + friend class ContentProvider; +#endif public: Offer(Clipboard& clipboard, OfferGetCallback get_callback, @@ -82,30 +87,15 @@ auto& clipboard() const noexcept { return *m_clipboard; } static void run(std::unique_ptr<Offer> offer, - ClipboardFormat format) noexcept - { - auto [targets, n_targets] = targets_for_format(format); - - // Transfers ownership of *offer to the clipboard. If setting succeeds, - // the clipboard will own *offer until the clipboard_data_clear_cb - // callback is called. - // If setting the clipboard fails, the clear callback will never be - // called. - if (gtk_clipboard_set_with_data(offer->clipboard().platform(), - targets, n_targets, - clipboard_get_cb, - clipboard_clear_cb, - offer.get())) { - gtk_clipboard_set_can_store(offer->clipboard().platform(), targets, n_targets); - offer.release(); // transferred to clipboard above - } - } + ClipboardFormat format) noexcept; private: std::shared_ptr<Clipboard> m_clipboard; OfferGetCallback m_get_callback; OfferClearCallback m_clear_callback; +#if VTE_GTK == 3 + void dispatch_get(ClipboardFormat format, GtkSelectionData* data) noexcept try @@ -219,6 +209,7 @@ } } +#endif /* VTE_GTK == 3 */ static std::pair<vte::glib::StringPtr, size_t> text_to_utf16_mozilla(std::string_view const& str) noexcept @@ -237,7 +228,462 @@ }; // class Clipboard::Offer -#endif /* VTE_GTK == 3 */ + +#if VTE_GTK == 4 + +static void* task_tag; + +using VteContentProvider = GdkContentProvider; + +class ContentProvider { +public: + ContentProvider(VteContentProvider* native) + : m_native{native} + { + } + + ContentProvider() = default; + ~ContentProvider() = default; + + ContentProvider(ContentProvider const&) = delete; + ContentProvider(ContentProvider&&) = delete; + + ContentProvider& operator=(ContentProvider const&) = delete; + ContentProvider& operator=(ContentProvider&&) = delete; + + void take_offer(std::unique_ptr<Clipboard::Offer> offer) + { + m_offer = std::move(offer); + } + + void set_format(ClipboardFormat format) + { + m_format = format; + m_content_formats = format_to_content_formats(format); + } + + void content_changed() + { + } + + void attach_clipboard(GdkClipboard* gdk_clipboard) + { + } + + void + detach_clipboard(GdkClipboard* gdk_clipboard) + { + if (auto const delegate = m_offer->clipboard().m_delegate.lock()) { + (*delegate.*m_offer->m_clear_callback)(m_offer->clipboard()); + } + } + + GdkContentFormats* + ref_formats() + { + return m_content_formats ? gdk_content_formats_ref(m_content_formats.get()) : nullptr; + } + + GdkContentFormats* + ref_storable_formats() + { + return format_to_content_formats(ClipboardFormat::TEXT).release(); + } + + void + write_mime_type_async(char const* mime_type, + GOutputStream* stream, + int io_priority, + GCancellable* cancellable, + GAsyncReadyCallback callback, + void* user_data) + { + auto task = vte::glib::take_ref(g_task_new(m_native, cancellable, callback, user_data)); + g_task_set_priority(task.get(), io_priority); + g_task_set_source_tag(task.get(), &task_tag); + g_task_set_name(task.get(), "vte-content-provider-write-async"); + + auto const format = format_from_mime_type(mime_type); + if (format == ClipboardFormat::INVALID) + return g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Unknown format"); + + if (auto const delegate = m_offer->clipboard().m_delegate.lock()) { + auto str = (*delegate.*m_offer->m_get_callback)(m_offer->clipboard(), format); + if (!str) + return g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Nothing on offer"); + + auto bytes = vte::Freeable<GBytes>{}; + switch (format_from_mime_type(mime_type)) { + case ClipboardFormat::TEXT: { + bytes = vte::take_freeable(g_bytes_new_with_free_func(g_strndup(str->data(), str->size()), + str->size(), + g_free, nullptr)); + break; + } + + case ClipboardFormat::HTML: { + auto [html, len] = m_offer->text_to_utf16_mozilla(*str); + + // This makes yet another copy of the data... :( + if (html) { + bytes = vte::take_freeable(g_bytes_new_with_free_func(html.release(), len, g_free, nullptr)); + break; + } else { + return g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "Invalid data"); + } + + break; + } + case ClipboardFormat::INVALID: + default: + break; + } + + if (bytes) { + auto provider = vte::glib::take_ref(gdk_content_provider_new_for_bytes(mime_type, bytes.release())); + return gdk_content_provider_write_mime_type_async(provider.get(), + mime_type, + stream, + io_priority, + cancellable, + write_mime_type_async_done_cb, + task.release()); // transfer + } + } + + return g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Offer expired"); + } + + bool + write_mime_type_finish(GAsyncResult* result, + GError** error) + { + auto const task = G_TASK(result); + return g_task_propagate_boolean(task, error); + } + + bool + get_value(GValue* value, + GError** error) + { + if (G_VALUE_HOLDS(value, G_TYPE_STRING)) { + if (auto const delegate = m_offer->clipboard().m_delegate.lock()) { + auto const str = (*delegate.*m_offer->m_get_callback)(m_offer->clipboard(), ClipboardFormat::TEXT); + if (!str) + return false; + + g_value_take_string(value, g_strndup(str->data(), str->size())); + return true; + } + } + + return false; + } + + void + offer() noexcept + { + gdk_clipboard_set_content(m_offer->clipboard().platform(), m_native); + } + + +private: + VteContentProvider* m_native{nullptr}; /* unowned */ + + std::unique_ptr<Clipboard::Offer> m_offer; + + ClipboardFormat m_format{ClipboardFormat::INVALID}; + vte::Freeable<GdkContentFormats> m_content_formats; + + vte::Freeable<GdkContentFormats> + format_to_content_formats(ClipboardFormat format) noexcept + { + auto builder = vte::take_freeable(gdk_content_formats_builder_new()); + + switch (format) { + case ClipboardFormat::TEXT: + gdk_content_formats_builder_add_mime_type(builder.get(), + MIME_TYPE_TEXT_PLAIN_UTF8); + break; + case ClipboardFormat::HTML: + gdk_content_formats_builder_add_mime_type(builder.get(), + MIME_TYPE_TEXT_HTML_UTF16); + break; + case ClipboardFormat::INVALID: + default: + __builtin_unreachable(); + } + + return vte::take_freeable(gdk_content_formats_builder_to_formats(builder.release())); + } + + ClipboardFormat + format_from_mime_type(std::string_view const& mime_type) noexcept + { + if (mime_type == MIME_TYPE_TEXT_PLAIN_UTF8) + return ClipboardFormat::TEXT; + else if (mime_type == MIME_TYPE_TEXT_HTML_UTF16) + return ClipboardFormat::HTML; + else + return ClipboardFormat::INVALID; + } + + static void + write_mime_type_async_done_cb(GObject* source, + GAsyncResult* result, + void* user_data) noexcept + try + { + auto const provider = GDK_CONTENT_PROVIDER(source); + auto const task = vte::glib::take_ref(reinterpret_cast<GTask*>(user_data)); // ref added on ::write_mime_type_async + + auto error = vte::glib::Error{}; + if (!gdk_content_provider_write_mime_type_finish(provider, result, error)) { + return g_task_return_error(task.get(), error.release()); + } + + return g_task_return_boolean(task.get(), true); + } + catch (...) + { + vte::log_exception(); + } + +}; // class ContentProvider + +#define VTE_TYPE_CONTENT_PROVIDER (vte_content_provider_get_type()) +#define VTE_CONTENT_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), VTE_TYPE_CONTENT_PROVIDER, VteContentProvider)) +#define VTE_CONTENT_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), VTE_TYPE_CONTENT_PROVIDER, VteContentProviderClass)) +#define VTE_IS_CONTENT_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), VTE_TYPE_CONTENT_PROVIDER)) +#define VTE_IS_CONTENT_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), VTE_TYPE_CONTENT_PROVIDER)) +#define VTE_CONTENT_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), VTE_TYPE_CONTENT_PROVIDER, VteContentProviderClass)) + +using VteContentProviderClass = GdkContentProviderClass; + +static GType vte_content_provider_get_type(void); + +G_DEFINE_TYPE_WITH_CODE(VteContentProvider, vte_content_provider, GDK_TYPE_CONTENT_PROVIDER, + { + VteContentProvider_private_offset = + g_type_add_instance_private(g_define_type_id, sizeof(ContentProvider)); + }); + +template<typename T> +static inline auto +IMPL(T* that) +{ + auto const pthat = reinterpret_cast<VteContentProvider*>(that); + return std::launder(reinterpret_cast<ContentProvider*>(vte_content_provider_get_instance_private(pthat))); +} + +static void +vte_content_provider_content_changed(GdkContentProvider* provider) noexcept +try +{ + GDK_CONTENT_PROVIDER_CLASS(vte_content_provider_parent_class)->content_changed(provider); + + IMPL(provider)->content_changed(); +} +catch (...) +{ + vte::log_exception(); +} + +static void +vte_content_provider_attach_clipboard(GdkContentProvider* provider, + GdkClipboard* clipboard) noexcept +try +{ + GDK_CONTENT_PROVIDER_CLASS(vte_content_provider_parent_class)->attach_clipboard(provider, + clipboard); + + IMPL(provider)->attach_clipboard(clipboard); +} +catch (...) +{ + vte::log_exception(); +} + +static void +vte_content_provider_detach_clipboard(GdkContentProvider* provider, + GdkClipboard* clipboard) noexcept +try +{ + GDK_CONTENT_PROVIDER_CLASS(vte_content_provider_parent_class)->detach_clipboard(provider, + clipboard); + + IMPL(provider)->detach_clipboard(clipboard); +} +catch (...) +{ + vte::log_exception(); +} + +static GdkContentFormats* +vte_content_provider_ref_formats(GdkContentProvider* provider) noexcept +try +{ + return IMPL(provider)->ref_formats(); +} +catch (...) +{ + vte::log_exception(); + return nullptr; +} + +static GdkContentFormats* +vte_content_provider_ref_storable_formats(GdkContentProvider* provider) noexcept +try +{ + return IMPL(provider)->ref_storable_formats(); +} +catch (...) +{ + vte::log_exception(); + return nullptr; +} + +static void +vte_content_provider_write_mime_type_async(GdkContentProvider* provider, + char const* mime_type, + GOutputStream* stream, + int io_priority, + GCancellable* cancellable, + GAsyncReadyCallback callback, + void* user_data) noexcept +try +{ + return IMPL(provider)->write_mime_type_async(mime_type, + stream, + io_priority, + cancellable, + callback, user_data); +} +catch (...) +{ + vte::log_exception(); +} + +static gboolean +vte_content_provider_write_mime_type_finish(GdkContentProvider* provider, + GAsyncResult* result, + GError** error) noexcept +try +{ + assert(g_task_is_valid(result, provider)); + assert(g_task_get_source_tag(G_TASK(result)) == &task_tag); + + return IMPL(provider)->write_mime_type_finish(result, error); +} +catch (...) +{ + vte::glib::set_error_from_exception(error); + return false; +} + +static gboolean +vte_content_provider_get_value(GdkContentProvider* provider, + GValue* value, + GError** error) noexcept +try +{ + if (IMPL(provider)->get_value(value, error)) + return true; + + return GDK_CONTENT_PROVIDER_CLASS(vte_content_provider_parent_class)->get_value(provider, + value, + error); +} +catch (...) +{ + vte::glib::set_error_from_exception(error); + return false; +} + +static void +vte_content_provider_init(VteContentProvider* provider) +try +{ + auto place = vte_content_provider_get_instance_private(provider); + new (place) ContentProvider{provider}; +} +catch (...) +{ + vte::log_exception(); + g_error("Failed to create ContentProvider\n"); +} + +static void +vte_content_provider_finalize(GObject* object) noexcept +{ + IMPL(object)->~ContentProvider(); + + G_OBJECT_CLASS(vte_content_provider_parent_class)->finalize(object); +} + +static void +vte_content_provider_class_init(VteContentProviderClass *klass) +{ + auto gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = vte_content_provider_finalize; + + auto provider_class = GDK_CONTENT_PROVIDER_CLASS(klass); + provider_class->content_changed = vte_content_provider_content_changed; + provider_class->attach_clipboard = vte_content_provider_attach_clipboard; + provider_class->detach_clipboard = vte_content_provider_detach_clipboard; + provider_class->ref_formats = vte_content_provider_ref_formats; + provider_class->ref_storable_formats = vte_content_provider_ref_storable_formats; + provider_class->write_mime_type_async = vte_content_provider_write_mime_type_async; + provider_class->write_mime_type_finish = vte_content_provider_write_mime_type_finish; + provider_class->get_value = vte_content_provider_get_value; +} + +static auto +vte_content_provider_new(void) noexcept +{ + return reinterpret_cast<VteContentProvider*> + (g_object_new(VTE_TYPE_CONTENT_PROVIDER, nullptr)); +} + +#endif /* VTE_GTK == 4 */ + +void +Clipboard::Offer::run(std::unique_ptr<Offer> offer, + ClipboardFormat format) noexcept +{ +#if VTE_GTK == 3 + auto [targets, n_targets] = targets_for_format(format); + + // Transfers ownership of *offer to the clipboard. If setting succeeds, + // the clipboard will own *offer until the clipboard_data_clear_cb + // callback is called. + // If setting the clipboard fails, the clear callback will never be + // called. + if (gtk_clipboard_set_with_data(offer->clipboard().platform(), + targets, n_targets, + clipboard_get_cb, + clipboard_clear_cb, + offer.get())) { + gtk_clipboard_set_can_store(offer->clipboard().platform(), targets, n_targets); + offer.release(); // transferred to clipboard above + } +#elif VTE_GTK == 4 + // It seems that to make the content available lazily (i.e. only + // generate it when the clipboard contents are requested), or + // receive a notification when said content no longer owns the + // clipboard, one has to write a new GdkContentProvider implementation. + auto const provider = vte::glib::take_ref(vte_content_provider_new()); + // Transfers ownership of *offer to the provider. + auto const impl = IMPL(provider.get()); + impl->take_offer(std::move(offer)); + impl->set_format(format); + impl->offer(); +#endif /* VTE_GTK */ +} class Clipboard::Request { public: @@ -256,11 +702,16 @@ static void run(std::unique_ptr<Request> request) noexcept { + auto const platform = request->clipboard().platform(); #if VTE_GTK == 3 - auto platform = request->clipboard().platform(); gtk_clipboard_request_text(platform, text_received_cb, request.release()); +#elif VTE_GTK == 4 + gdk_clipboard_read_text_async(platform, + nullptr, // cancellable + GAsyncReadyCallback(text_received_cb), + request.release()); #endif /* VTE_GTK */ } @@ -273,7 +724,7 @@ void dispatch(char const *text) noexcept try { - if (auto delegate = clipboard().m_delegate.lock()) { + if (auto const delegate = clipboard().m_delegate.lock()) { if (text) (*delegate.*m_done_callback)(clipboard(), {text, strlen(text)}); else @@ -289,10 +740,42 @@ char const* text, gpointer data) noexcept { - auto request = std::unique_ptr<Request>{reinterpret_cast<Request*>(data)}; + auto const request = std::unique_ptr<Request>{reinterpret_cast<Request*>(data)}; request->dispatch(text); } +#elif VTE_GTK == 4 + + void dispatch(GObject* source, + GAsyncResult* result) noexcept + try + { + // Well done gtk4 to not simply tell us also the length of the received text! + auto const text = vte::glib::take_string + (gdk_clipboard_read_text_finish(GDK_CLIPBOARD(source), + result, + nullptr)); + + if (auto const delegate = clipboard().m_delegate.lock()) { + if (text) + (*delegate.*m_done_callback)(clipboard(), {text.get(), strlen(text.get())}); + else + (*delegate.*m_failed_callback)(clipboard()); + } + } + catch (...) + { + vte::log_exception(); + } + + static void text_received_cb(GObject* source, + GAsyncResult* result, + gpointer data) noexcept + { + auto const request = std::unique_ptr<Request>{reinterpret_cast<Request*>(data)}; + request->dispatch(source, result); + } + #endif /* VTE_GTK */ }; // class Clipboard::Request @@ -302,17 +785,19 @@ OfferGetCallback get_callback, OfferClearCallback clear_callback) /* throws */ { -#if VTE_GTK == 3 Offer::run(std::make_unique<Offer>(*this, get_callback, clear_callback), format); -#endif } void -Clipboard::set_text(std::string_view const& text) noexcept +Clipboard::set_text(char const* text, + size_t size) noexcept { #if VTE_GTK == 3 - gtk_clipboard_set_text(platform(), text.data(), text.size()); -#endif + gtk_clipboard_set_text(platform(), text, size); +#elif VTE_GTK == 4 + // This API sucks + gdk_clipboard_set_text(platform(), text); +#endif /* VTE_GTK */ } void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/clipboard-gtk.hh new/vte-0.70.1/src/clipboard-gtk.hh --- old/vte-0.70.0/src/clipboard-gtk.hh 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/clipboard-gtk.hh 2022-09-23 20:46:10.000000000 +0200 @@ -31,7 +31,10 @@ enum class ClipboardFormat { TEXT, - HTML + HTML, +#if VTE_GTK == 4 + INVALID = -1 +#endif }; enum class ClipboardType { @@ -39,7 +42,14 @@ PRIMARY = 1 }; +#if VTE_GTK == 4 +class ContentProvider; +#endif + class Clipboard : public std::enable_shared_from_this<Clipboard> { +#if VTE_GTK == 4 + friend class ContentProvider; +#endif public: Clipboard(Widget& delegate, ClipboardType type) /* throws */; @@ -69,7 +79,8 @@ OfferGetCallback get_callback, OfferClearCallback clear_callback) /* throws */; - void set_text(std::string_view const& text) noexcept; + void set_text(char const* text, + size_t size) noexcept; void request_text(RequestDoneCallback done_callback, RequestFailedCallback failed_callback) /* throws */; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/glib-glue.hh new/vte-0.70.1/src/glib-glue.hh --- old/vte-0.70.0/src/glib-glue.hh 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/glib-glue.hh 2022-09-23 20:46:10.000000000 +0200 @@ -278,6 +278,7 @@ namespace vte { +VTE_DECLARE_FREEABLE(GBytes, g_bytes_unref); VTE_DECLARE_FREEABLE(GOptionContext, g_option_context_free); VTE_DECLARE_FREEABLE(GVariant, g_variant_unref); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/gtk-glue.hh new/vte-0.70.1/src/gtk-glue.hh --- old/vte-0.70.0/src/gtk-glue.hh 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/gtk-glue.hh 2022-09-23 20:46:10.000000000 +0200 @@ -31,6 +31,7 @@ #if VTE_GTK == 4 VTE_DECLARE_FREEABLE(GdkContentFormats, gdk_content_formats_unref); +VTE_DECLARE_FREEABLE(GdkContentFormatsBuilder, gdk_content_formats_builder_unref); #endif /* VTE_GTK == 4 */ } // namespace vte diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/vte.cc new/vte-0.70.1/src/vte.cc --- old/vte-0.70.0/src/vte.cc 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/vte.cc 2022-09-23 20:46:10.000000000 +0200 @@ -4932,15 +4932,6 @@ return true; } -#if VTE_GTK == 4 - if (!handled && - event.matches(GDK_KEY_Menu, 0)) { - _vte_debug_print(VTE_DEBUG_EVENTS, "Showing context menu\n"); - // FIXMEgtk4 do context menu - handled = true; - } -#endif - return false; } @@ -6800,16 +6791,6 @@ break; } -#if VTE_GTK == 4 - if (!handled && - ((event.button() == vte::platform::MouseEvent::Button::eRIGHT) || - !(event.modifiers() & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))) { - _vte_debug_print(VTE_DEBUG_EVENTS, "Showing context menu\n"); - // FIXMEgtk4 context menu - handled = true; - } -#endif /* VTE_GTK == 4 */ - /* Save the pointer state for later use. */ if (event.button_value() >= 1 && event.button_value() <= 3) m_mouse_pressed_buttons |= (1 << (event.button_value() - 1)); @@ -7863,8 +7844,8 @@ // FIXMEchpe we should check m_selection_format[sel] // and also put text/html on if it's HTML format widget()->clipboard_set_text(sel_type, - {m_selection[sel]->str, - m_selection[sel]->len}); + m_selection[sel]->str, + m_selection[sel]->len); } g_string_free(m_selection[sel], TRUE); m_selection[sel] = nullptr; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/widget.cc new/vte-0.70.1/src/widget.cc --- old/vte-0.70.0/src/widget.cc 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/widget.cc 2022-09-23 20:46:10.000000000 +0200 @@ -628,9 +628,10 @@ void Widget::clipboard_set_text(ClipboardType type, - std::string_view const& str) noexcept + char const* str, + size_t size) noexcept { - clipboard_get(type).set_text(str); + clipboard_get(type).set_text(str, size); } #if VTE_GTK == 4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vte-0.70.0/src/widget.hh new/vte-0.70.1/src/widget.hh --- old/vte-0.70.0/src/widget.hh 2022-09-03 18:50:59.000000000 +0200 +++ new/vte-0.70.1/src/widget.hh 2022-09-23 20:46:10.000000000 +0200 @@ -383,7 +383,8 @@ ClipboardFormat format) noexcept; void clipboard_request_text(ClipboardType type) noexcept; void clipboard_set_text(ClipboardType type, - std::string_view const& str) noexcept; + char const* str, + size_t size) noexcept; void paste_text(std::string_view const& text) { m_terminal->widget_paste(text); } void paste(vte::platform::ClipboardType type) { clipboard_request_text(type); } ++++++ vte.obsinfo ++++++ --- /var/tmp/diff_new_pack.ayj9Ci/_old 2022-11-01 13:40:38.167279379 +0100 +++ /var/tmp/diff_new_pack.ayj9Ci/_new 2022-11-01 13:40:38.171279400 +0100 @@ -1,5 +1,5 @@ name: vte -version: 0.70.0 -mtime: 1662223859 -commit: ae4a5d7df9e32ab40ceca5e06240561e819db148 +version: 0.70.1 +mtime: 1663958770 +commit: 5bf476f1d7283bc805ac8ae6abe94f81ffd7be05