From fd15a7551f95b4c9f13a0c1ff994b09e5cb550f3 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 21 Dec 2022 08:22:55 +0100 Subject: [PATCH] Backported mozbz#1804877 - set XDG_ACTIVATION_TOKEN when launch external application under Wayland --- D165150.diff | 163 +++++++++++++++++++++++++++++++++++++++++++++++ D165152.diff | 117 ++++++++++++++++++++++++++++++++++ thunderbird.spec | 11 +++- 3 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 D165150.diff create mode 100644 D165152.diff diff --git a/D165150.diff b/D165150.diff new file mode 100644 index 0000000..fc9a9f7 --- /dev/null +++ b/D165150.diff @@ -0,0 +1,163 @@ +diff -up thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.cpp.D165150 thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.cpp +--- thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.cpp.D165150 2022-12-12 22:37:39.000000000 +0100 ++++ thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.cpp 2022-12-20 14:43:29.742482848 +0100 +@@ -9,11 +9,20 @@ + #include "mozilla/UniquePtr.h" + #include "nsReadableUtils.h" + #include "nsWindow.h" ++#include "nsGtkKeyUtils.h" + + #include + #include + #include + ++#ifdef MOZ_LOGGING ++# include "mozilla/Logging.h" ++extern mozilla::LazyLogModule gWidgetLog; ++# define LOGW(...) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) ++#else ++# define LOGW(...) ++#endif /* MOZ_LOGGING */ ++ + namespace mozilla::widget { + + int32_t WidgetUtilsGTK::IsTouchDeviceSupportPresent() { +@@ -165,4 +174,108 @@ nsTArray ParseTextURIList(con + return result; + } + ++#ifdef MOZ_WAYLAND ++static gboolean token_failed(gpointer aData); ++ ++class XDGTokenRequest { ++ public: ++ void SetTokenID(const char* aTokenID) { ++ mTransferPromise->Resolve(aTokenID, __func__); ++ } ++ void Cancel() { ++ mTransferPromise->Reject(false, __func__); ++ mActivationTimeoutID = 0; ++ } ++ ++ XDGTokenRequest(xdg_activation_token_v1* aXdgToken, ++ RefPtr aTransferPromise) ++ : mXdgToken(aXdgToken), mTransferPromise(aTransferPromise) { ++ mActivationTimeoutID = ++ g_timeout_add(sActivationTimeout, token_failed, this); ++ } ++ ~XDGTokenRequest() { ++ if (mXdgToken) { ++ xdg_activation_token_v1_destroy(mXdgToken); ++ } ++ if (mActivationTimeoutID) { ++ g_source_remove(mActivationTimeoutID); ++ } ++ } ++ ++ private: ++ xdg_activation_token_v1* mXdgToken; ++ RefPtr mTransferPromise; ++ guint mActivationTimeoutID; ++ // Reject FocusRequestPromise if we don't get XDG token in 0.5 sec. ++ const int sActivationTimeout = 500; ++}; ++ ++// Failed to get token in time ++static gboolean token_failed(gpointer data) { ++ UniquePtr request(static_cast(data)); ++ request->Cancel(); ++ return false; ++} ++ ++// We've got activation token from Wayland compositor so it's time to use it. ++static void token_done(gpointer data, struct xdg_activation_token_v1* provider, ++ const char* tokenID) { ++ UniquePtr request(static_cast(data)); ++ request->SetTokenID(tokenID); ++} ++ ++static const struct xdg_activation_token_v1_listener token_listener = { ++ token_done, ++}; ++ ++RefPtr RequestWaylandFocus() { ++ RefPtr sourceWindow = nsWindow::GetFocusedWindow(); ++ if (!sourceWindow) { ++ return nullptr; ++ } ++ ++ RefPtr display = WaylandDisplayGet(); ++ xdg_activation_v1* xdg_activation = display->GetXdgActivation(); ++ if (!xdg_activation) { ++ return nullptr; ++ } ++ ++ wl_surface* focusSurface; ++ uint32_t focusSerial; ++ KeymapWrapper::GetFocusInfo(&focusSurface, &focusSerial); ++ if (!focusSurface) { ++ return nullptr; ++ } ++ ++ GdkWindow* gdkWindow = gtk_widget_get_window(sourceWindow->GetGtkWidget()); ++ if (!gdkWindow) { ++ return nullptr; ++ } ++ wl_surface* surface = gdk_wayland_window_get_wl_surface(gdkWindow); ++ if (focusSurface != surface) { ++ return nullptr; ++ } ++ ++ RefPtr transferPromise = ++ new FocusRequestPromise::Private(__func__); ++ ++ xdg_activation_token_v1* aXdgToken = ++ xdg_activation_v1_get_activation_token(xdg_activation); ++ xdg_activation_token_v1_add_listener( ++ aXdgToken, &token_listener, ++ new XDGTokenRequest(aXdgToken, transferPromise)); ++ xdg_activation_token_v1_set_serial(aXdgToken, focusSerial, ++ KeymapWrapper::GetSeat()); ++ xdg_activation_token_v1_set_surface(aXdgToken, focusSurface); ++ xdg_activation_token_v1_commit(aXdgToken); ++ ++ return transferPromise.forget(); ++} ++ ++bool CanTransferWaylandFocus() { ++ return GdkIsWaylandDisplay() && nsWindow::GetFocusedWindow() && ++ !nsWindow::GetFocusedWindow()->IsDestroyed(); ++} ++#endif ++ + } // namespace mozilla::widget +diff -up thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.h.D165150 thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.h +--- thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.h.D165150 2022-12-12 22:37:41.000000000 +0100 ++++ thunderbird-102.6.0/widget/gtk/WidgetUtilsGtk.h 2022-12-20 13:44:15.343638003 +0100 +@@ -8,11 +8,13 @@ + + #include "nsString.h" + #include "nsTArray.h" ++#include "mozilla/MozPromise.h" + + #include + + typedef struct _GdkDisplay GdkDisplay; + typedef struct _GdkDevice GdkDevice; ++class nsWindow; + + namespace mozilla::widget { + +@@ -51,6 +53,12 @@ bool ShouldUsePortal(PortalKind); + // Parse text/uri-list + nsTArray ParseTextURIList(const nsACString& data); + ++#ifdef MOZ_WAYLAND ++using FocusRequestPromise = mozilla::MozPromise; ++bool CanTransferWaylandFocus(); ++RefPtr RequestWaylandFocus(); ++#endif ++ + } // namespace mozilla::widget + + #endif // WidgetUtilsGtk_h__ diff --git a/D165152.diff b/D165152.diff new file mode 100644 index 0000000..96350e9 --- /dev/null +++ b/D165152.diff @@ -0,0 +1,117 @@ +diff -up thunderbird-102.6.0/toolkit/system/gnome/nsGIOService.cpp.D165152 thunderbird-102.6.0/toolkit/system/gnome/nsGIOService.cpp +--- thunderbird-102.6.0/toolkit/system/gnome/nsGIOService.cpp.D165152 2022-12-12 22:37:40.000000000 +0100 ++++ thunderbird-102.6.0/toolkit/system/gnome/nsGIOService.cpp 2022-12-20 13:41:17.337477022 +0100 +@@ -19,6 +19,7 @@ + #include "mozilla/WidgetUtilsGtk.h" + #include "mozilla/StaticPrefs_widget.h" + #include "mozilla/net/DNS.h" ++#include "prenv.h" + + #include + #include +@@ -224,9 +225,7 @@ static RefPtr GetLaun + return context; + } + +-NS_IMETHODIMP +-nsGIOMimeApp::LaunchWithURI(nsIURI* aUri, +- mozilla::dom::BrowsingContext* aBrowsingContext) { ++static NS_IMETHODIMP LaunchWithURIImpl(RefPtr aInfo, nsIURI* aUri) { + GList uris = {0}; + nsCString spec; + aUri->GetSpec(spec); +@@ -235,7 +234,7 @@ nsGIOMimeApp::LaunchWithURI(nsIURI* aUri + + GUniquePtr error; + gboolean result = g_app_info_launch_uris( +- mApp, &uris, GetLaunchContext().get(), getter_Transfers(error)); ++ aInfo, &uris, GetLaunchContext().get(), getter_Transfers(error)); + if (!result) { + g_warning("Cannot launch application: %s", error->message); + return NS_ERROR_FAILURE; +@@ -244,6 +243,27 @@ nsGIOMimeApp::LaunchWithURI(nsIURI* aUri + return NS_OK; + } + ++NS_IMETHODIMP ++nsGIOMimeApp::LaunchWithURI(nsIURI* aUri, ++ mozilla::dom::BrowsingContext* aBrowsingContext) { ++ if (mozilla::widget::CanTransferWaylandFocus()) { ++ mozilla::widget::RequestWaylandFocus()->Then( ++ GetMainThreadSerialEventTarget(), __func__, ++ /* resolve */ ++ [app = RefPtr{mApp}, uri = RefPtr{aUri}](nsCString token) { ++ PR_SetEnv(ToNewCString("XDG_ACTIVATION_TOKEN="_ns + token)); ++ LaunchWithURIImpl(app, uri); ++ }, ++ /* reject */ ++ [app = RefPtr{mApp}, uri = RefPtr{aUri}](bool state) { ++ LaunchWithURIImpl(app, uri); ++ }); ++ return NS_OK; ++ } ++ ++ return LaunchWithURIImpl(mApp, aUri); ++} ++ + class GIOUTF8StringEnumerator final : public nsStringEnumeratorBase { + ~GIOUTF8StringEnumerator() = default; + +@@ -531,7 +551,7 @@ nsGIOService::GetDescriptionForMimeType( + return NS_OK; + } + +-nsresult nsGIOService::ShowURI(nsIURI* aURI) { ++static nsresult ShowURIImpl(nsIURI* aURI) { + nsAutoCString spec; + MOZ_TRY(aURI->GetSpec(spec)); + GUniquePtr error; +@@ -544,7 +564,24 @@ nsresult nsGIOService::ShowURI(nsIURI* a + return NS_OK; + } + +-static nsresult LaunchPath(const nsACString& aPath) { ++nsresult nsGIOService::ShowURI(nsIURI* aURI) { ++ if (mozilla::widget::CanTransferWaylandFocus()) { ++ mozilla::widget::RequestWaylandFocus()->Then( ++ GetMainThreadSerialEventTarget(), __func__, ++ /* resolve */ ++ [uri = RefPtr{aURI}](nsCString token) { ++ PR_SetEnv(ToNewCString("XDG_ACTIVATION_TOKEN="_ns + token)); ++ ShowURIImpl(uri); ++ }, ++ /* reject */ ++ [uri = RefPtr{aURI}](bool state) { ShowURIImpl(uri); }); ++ return NS_OK; ++ } ++ ++ return ShowURIImpl(aURI); ++} ++ ++static nsresult LaunchPathImpl(const nsACString& aPath) { + RefPtr file = dont_AddRef( + g_file_new_for_commandline_arg(PromiseFlatCString(aPath).get())); + GUniquePtr spec(g_file_get_uri(file)); +@@ -558,6 +595,22 @@ static nsresult LaunchPath(const nsACStr + return NS_OK; + } + ++static nsresult LaunchPath(const nsACString& aPath) { ++ if (mozilla::widget::CanTransferWaylandFocus()) { ++ mozilla::widget::RequestWaylandFocus()->Then( ++ GetMainThreadSerialEventTarget(), __func__, ++ /* resolve */ ++ [path = nsCString{aPath}](nsCString token) { ++ PR_SetEnv(ToNewCString("XDG_ACTIVATION_TOKEN="_ns + token)); ++ LaunchPathImpl(path); ++ }, ++ /* reject */ ++ [path = nsCString{aPath}](bool state) { LaunchPathImpl(path); }); ++ return NS_OK; ++ } ++ return LaunchPathImpl(aPath); ++} ++ + nsresult nsGIOService::LaunchFile(const nsACString& aPath) { + return LaunchPath(aPath); + } diff --git a/thunderbird.spec b/thunderbird.spec index a2cb11d..cc6dbc4 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -100,7 +100,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 102.6.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPL-2.0 OR GPL-2.0-or-later OR LGPL-2.0-or-later Source0: https://archive.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -144,6 +144,8 @@ Patch304: mozilla-1245783.patch Patch402: mozilla-526293.patch Patch406: mozilla-1170092.patch Patch407: D147721-python-ru.diff +Patch408: D165150.diff +Patch409: D165152.diff # Bundled expat backported patches Patch501: expat-CVE-2022-25235.patch @@ -316,6 +318,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch402 -p1 -b .526293 %patch406 -p1 -b .1170092-etc-conf %patch407 -p1 -b .D147721-python-ru.diff +%patch408 -p1 -b .D165150 +%patch409 -p1 -b .D165152 + pushd comm popd @@ -756,6 +761,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Dec 21 2020 Martin Stransky - 102.6.0-2 +- Backported mozbz#1804877 - set XDG_ACTIVATION_TOKEN when launch + external application. + * Tue Dec 13 2022 Eike Rathke - 102.6.0-1 - Update to 102.6.0