From d63b6e341aa0613553e642bdbf45de0aab54a752 Mon Sep 17 00:00:00 2001 From: Tarek Ismail Date: Thu, 23 Jan 2025 18:22:21 +0200 Subject: [PATCH] Pass `XDG_ACTIVATION_TOKEN` and `DESKTOP_STARTUP_ID` to launched apps Refactored the parameters of `launch_app_env` to use `std::optional` instead of `mir::optional_value` --- src/include/server/mir/frontend/connector.h | 4 +- src/include/server/mir/server.h | 6 +- src/miral/external_client.cpp | 7 +- src/miral/launch_app.cpp | 68 +++++++++---------- src/miral/launch_app.h | 5 +- src/miral/runner.cpp | 14 +++- src/miral/x11_support.cpp | 1 + .../frontend_wayland/wayland_connector.cpp | 3 +- .../frontend_wayland/wayland_connector.h | 2 +- .../frontend_xwayland/xwayland_connector.cpp | 4 +- .../frontend_xwayland/xwayland_connector.h | 2 +- .../xwayland_default_configuration.cpp | 5 +- src/server/server.cpp | 8 +-- 13 files changed, 71 insertions(+), 58 deletions(-) diff --git a/src/include/server/mir/frontend/connector.h b/src/include/server/mir/frontend/connector.h index d742b63eec1..436917938bb 100644 --- a/src/include/server/mir/frontend/connector.h +++ b/src/include/server/mir/frontend/connector.h @@ -17,9 +17,9 @@ #ifndef MIR_FRONTEND_CONNECTOR_H_ #define MIR_FRONTEND_CONNECTOR_H_ -#include #include #include +#include #include namespace mir @@ -41,7 +41,7 @@ class Connector virtual int client_socket_fd(std::function const& session)> const& connect_handler) const = 0; - virtual auto socket_name() const -> optional_value = 0; + virtual auto socket_name() const -> std::optional = 0; protected: Connector() = default; diff --git a/src/include/server/mir/server.h b/src/include/server/mir/server.h index 16684d43a61..6cad0f1c1cb 100644 --- a/src/include/server/mir/server.h +++ b/src/include/server/mir/server.h @@ -18,11 +18,11 @@ #define MIR_SERVER_H_ #include "mir/shell/window_manager_builder.h" -#include "mir/optional_value.h" #include "mir_toolkit/common.h" #include #include +#include #include struct wl_display; @@ -471,10 +471,10 @@ class Server std::function const&, char const*)> const& extension_filter); /// Get the name of the Wayland endpoint (if any) usable as a $WAYLAND_DISPLAY value - auto wayland_display() const -> optional_value; + auto wayland_display() const -> std::optional; /// Get the name of the X11 display usable as a $DISPLAY value - auto x11_display() const -> optional_value; + auto x11_display() const -> std::optional; auto get_activation_token() const -> std::string; diff --git a/src/miral/external_client.cpp b/src/miral/external_client.cpp index 792b96221bd..cbeb430f498 100644 --- a/src/miral/external_client.cpp +++ b/src/miral/external_client.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -117,8 +118,9 @@ auto miral::ExternalClientLauncher::launch(std::vector const& comma auto const wayland_display = self->server->wayland_display(); auto const x11_display = self->server->x11_display(); + auto const activation_token = self->server->get_activation_token(); - return launch_app_env(command_line, wayland_display, x11_display, self->env); + return launch_app_env(command_line, wayland_display, x11_display, activation_token, self->env); } miral::ExternalClientLauncher::ExternalClientLauncher() : self{std::make_shared()} {} @@ -133,7 +135,8 @@ auto miral::ExternalClientLauncher::launch_using_x11(std::vector c if (auto const x11_display = self->server->x11_display()) { auto const wayland_display = self->server->wayland_display(); - return launch_app_env(command_line, wayland_display, x11_display, self->x11_env); + return launch_app_env( + command_line, wayland_display, x11_display, self->server->get_activation_token(), self->x11_env); } return -1; diff --git a/src/miral/launch_app.cpp b/src/miral/launch_app.cpp index 5d827df7734..a4ab0e0ba9f 100644 --- a/src/miral/launch_app.cpp +++ b/src/miral/launch_app.cpp @@ -19,11 +19,11 @@ #include +#include #include #include #include -#include #include #include @@ -93,46 +93,21 @@ auto Environment::exec_env() const & -> std::vector result.push_back(nullptr); return result; } -} // namespace -auto miral::launch_app_env( - std::vector const& app, - mir::optional_value const& wayland_display, - mir::optional_value const& x11_display, - miral::AppEnvironment const& app_env) -> pid_t +void assign_or_unset(Environment& env, std::string const& key, auto optional_value) { - Environment application_environment; - - for (auto const& [key, value]: app_env) - { - if (value) - { - application_environment.setenv(key, value.value()); - } - else - { - application_environment.unsetenv(key); - } - } - - if (wayland_display) + if (optional_value) { - application_environment.setenv("WAYLAND_DISPLAY", wayland_display.value()); // configure Wayland socket + env.setenv(key, optional_value.value()); } else { - application_environment.unsetenv("WAYLAND_DISPLAY"); - } - - if (x11_display) - { - application_environment.setenv("DISPLAY", x11_display.value()); // configure X11 socket - } - else - { - application_environment.unsetenv("DISPLAY"); + env.unsetenv(key); } +} +auto execute_with_environment(std::vector const app, Environment& application_environment) -> pid_t +{ auto const exec_env = application_environment.exec_env(); std::vector exec_args; @@ -155,8 +130,9 @@ auto miral::launch_app_env( sigfillset(&all_signals); pthread_sigmask(SIG_UNBLOCK, &all_signals, nullptr); - // execvpe() isn't listed as being async-signal-safe, but the implementation looks fine and rewriting seems unnecessary - execvpe(exec_args[0], const_cast(exec_args.data()), const_cast(exec_env.data())); + // execvpe() isn't listed as being async-signal-safe, but the implementation looks fine and rewriting seems + // unnecessary + execvpe(exec_args[0], const_cast(exec_args.data()), const_cast(exec_env.data())); mir::log_warning("Failed to execute client (\"%s\") error: %s", exec_args[0], strerror(errno)); exit(EXIT_FAILURE); @@ -164,3 +140,25 @@ auto miral::launch_app_env( return pid; } +} // namespace + + +auto miral::launch_app_env( + std::vector const& app, + std::optional const& wayland_display, + std::optional const& x11_display, + std::optional const& xdg_activation_token, + miral::AppEnvironment const& app_env) -> pid_t +{ + Environment application_environment; + + for (auto const& [key, value]: app_env) + assign_or_unset(application_environment, key, value); + + assign_or_unset(application_environment, "WAYLAND_DISPLAY", wayland_display); // configure Wayland socket + assign_or_unset(application_environment, "DISPLAY", x11_display); // configure X11 socket + assign_or_unset(application_environment, "XDG_ACTIVATION_TOKEN", xdg_activation_token); + assign_or_unset(application_environment, "DESKTOP_STARTUP_ID", xdg_activation_token); + + return execute_with_environment(app, application_environment); +} diff --git a/src/miral/launch_app.h b/src/miral/launch_app.h index b3a9a367289..2106e0269fe 100644 --- a/src/miral/launch_app.h +++ b/src/miral/launch_app.h @@ -32,8 +32,9 @@ namespace miral using AppEnvironment = std::map>; auto launch_app_env(std::vector const& app, - mir::optional_value const& wayland_display, - mir::optional_value const& x11_display, + std::optional const& wayland_display, + std::optional const& x11_display, + std::optional const& xdg_activation_token, AppEnvironment const& app_env) -> pid_t; } diff --git a/src/miral/runner.cpp b/src/miral/runner.cpp index 5b04036e168..e8101a358db 100644 --- a/src/miral/runner.cpp +++ b/src/miral/runner.cpp @@ -274,13 +274,23 @@ auto miral::MirRunner::display_config_file() const -> std::string return self->display_config_file; } +namespace +{ +auto optional_to_mir_optional(std::optional const& opt) -> mir::optional_value +{ + if (!opt) + return {}; + return mir::optional_value{*opt}; +} +} + auto miral::MirRunner::wayland_display() const -> mir::optional_value { std::lock_guard lock{self->mutex}; if (auto const server = self->weak_server.lock()) { - return server->wayland_display(); + return optional_to_mir_optional(server->wayland_display()); } return {}; @@ -292,7 +302,7 @@ auto miral::MirRunner::x11_display() const -> mir::optional_value if (auto const server = self->weak_server.lock()) { - return server->x11_display(); + return optional_to_mir_optional(server->x11_display()); } return {}; diff --git a/src/miral/x11_support.cpp b/src/miral/x11_support.cpp index b06de63a197..f204f6d0d1f 100644 --- a/src/miral/x11_support.cpp +++ b/src/miral/x11_support.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace mo = mir::options; diff --git a/src/server/frontend_wayland/wayland_connector.cpp b/src/server/frontend_wayland/wayland_connector.cpp index 2d3f0a9ac9c..5c7a90e45d7 100644 --- a/src/server/frontend_wayland/wayland_connector.cpp +++ b/src/server/frontend_wayland/wayland_connector.cpp @@ -37,6 +37,7 @@ #include "mir/graphics/graphic_buffer_allocator.h" #include "mir/frontend/wayland.h" +#include #include #include #include @@ -525,7 +526,7 @@ void mf::WaylandConnector::on_surface_created( compositor_global->on_surface_created(client, id, callback); } -auto mf::WaylandConnector::socket_name() const -> optional_value +auto mf::WaylandConnector::socket_name() const -> std::optional { return wayland_display; } diff --git a/src/server/frontend_wayland/wayland_connector.h b/src/server/frontend_wayland/wayland_connector.h index 875ec6f0064..f2b3fc634bf 100644 --- a/src/server/frontend_wayland/wayland_connector.h +++ b/src/server/frontend_wayland/wayland_connector.h @@ -190,7 +190,7 @@ class WaylandConnector : public Connector /// Callback is never called if a wl_surface with the id is never created void on_surface_created(wl_client* client, uint32_t id, std::function const& callback); - auto socket_name() const -> optional_value override; + auto socket_name() const -> std::optional override; auto get_extension(std::string const& name) const -> std::shared_ptr; diff --git a/src/server/frontend_xwayland/xwayland_connector.cpp b/src/server/frontend_xwayland/xwayland_connector.cpp index 3a1b06cc7bd..0c973ce1b24 100644 --- a/src/server/frontend_xwayland/xwayland_connector.cpp +++ b/src/server/frontend_xwayland/xwayland_connector.cpp @@ -101,7 +101,7 @@ int mf::XWaylandConnector::client_socket_fd( return -1; } -auto mf::XWaylandConnector::socket_name() const -> optional_value +auto mf::XWaylandConnector::socket_name() const -> std::optional { std::lock_guard lock{mutex}; @@ -111,7 +111,7 @@ auto mf::XWaylandConnector::socket_name() const -> optional_value } else { - return optional_value(); + return std::nullopt; } } diff --git a/src/server/frontend_xwayland/xwayland_connector.h b/src/server/frontend_xwayland/xwayland_connector.h index 6b908bc459f..a8fc6cd93e1 100644 --- a/src/server/frontend_xwayland/xwayland_connector.h +++ b/src/server/frontend_xwayland/xwayland_connector.h @@ -60,7 +60,7 @@ class XWaylandConnector : public Connector, public std::enable_shared_from_this< int client_socket_fd( std::function const& session)> const& connect_handler) const override; - auto socket_name() const -> optional_value override; + auto socket_name() const -> std::optional override; private: std::shared_ptr const main_loop; diff --git a/src/server/frontend_xwayland/xwayland_default_configuration.cpp b/src/server/frontend_xwayland/xwayland_default_configuration.cpp index cb87f06e806..83eb3ccf704 100644 --- a/src/server/frontend_xwayland/xwayland_default_configuration.cpp +++ b/src/server/frontend_xwayland/xwayland_default_configuration.cpp @@ -24,6 +24,7 @@ #include +#include #include #include @@ -53,9 +54,9 @@ struct NullConnector : mf::Connector return -1; } - mir::optional_value socket_name() const override + std::optional socket_name() const override { - return mir::optional_value(); + return std::optional(); } }; } diff --git a/src/server/server.cpp b/src/server/server.cpp index d3aac499746..b2cede8b226 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -37,10 +37,8 @@ #include "mir/renderer/renderer_factory.h" #include "frontend_wayland/wayland_connector.h" - #include -#include - +#include namespace mo = mir::options; namespace mi = mir::input; @@ -465,7 +463,7 @@ auto mir::Server::open_wayland_client_socket() -> Fd BOOST_THROW_EXCEPTION(std::logic_error("Cannot open connection when not running")); } -auto mir::Server::wayland_display() const -> optional_value +auto mir::Server::wayland_display() const -> std::optional { if (auto const config = self->server_config) return config->the_wayland_connector()->socket_name(); @@ -473,7 +471,7 @@ auto mir::Server::wayland_display() const -> optional_value BOOST_THROW_EXCEPTION(std::logic_error("Cannot open connection when not running")); } -auto mir::Server::x11_display() const -> mir::optional_value +auto mir::Server::x11_display() const -> std::optional { if (auto const config = self->server_config) return config->the_xwayland_connector()->socket_name();