Skip to content

Commit aef6758

Browse files
Pass XDG_ACTIVATION_TOKEN to apps launched via launch_app_env
1 parent 40c93fe commit aef6758

File tree

8 files changed

+189
-125
lines changed

8 files changed

+189
-125
lines changed

src/include/server/mir/server.h

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <functional>
2525
#include <memory>
26+
#include <optional>
2627
#include <vector>
2728

2829
struct wl_display;
@@ -473,6 +474,8 @@ class Server
473474
/// Get the name of the X11 display usable as a $DISPLAY value
474475
auto x11_display() const -> optional_value<std::string>;
475476

477+
auto get_activation_token() const -> std::optional<std::string>;
478+
476479
/// Overrides the standard set of Wayland extensions (mir::frontend::get_standard_extensions()) with a new list
477480
void set_enabled_wayland_extensions(std::vector<std::string> const& extensions);
478481
/** @} */

src/miral/external_client.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ auto miral::ExternalClientLauncher::launch(std::vector<std::string> const& comma
118118
auto const wayland_display = self->server->wayland_display();
119119
auto const x11_display = self->server->x11_display();
120120

121-
return launch_app_env(command_line, wayland_display, x11_display, self->env);
121+
return launch_app_env(command_line, wayland_display, x11_display, self->server->get_activation_token(), self->env);
122122
}
123123

124124
miral::ExternalClientLauncher::ExternalClientLauncher() : self{std::make_shared<Self>()} {}
@@ -133,7 +133,8 @@ auto miral::ExternalClientLauncher::launch_using_x11(std::vector<std::string> c
133133
if (auto const x11_display = self->server->x11_display())
134134
{
135135
auto const wayland_display = self->server->wayland_display();
136-
return launch_app_env(command_line, wayland_display, x11_display, self->x11_env);
136+
return launch_app_env(
137+
command_line, wayland_display, x11_display, self->server->get_activation_token(), self->x11_env);
137138
}
138139

139140
return -1;

src/miral/launch_app.cpp

+48-35
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919

2020
#include <boost/throw_exception.hpp>
2121

22+
#include <string>
2223
#include <unistd.h>
2324
#include <signal.h>
2425

2526
#include <cstring>
26-
#include <stdexcept>
2727
#include <system_error>
2828
#include <vector>
2929

@@ -93,46 +93,21 @@ auto Environment::exec_env() const & -> std::vector<char const*>
9393
result.push_back(nullptr);
9494
return result;
9595
}
96-
} // namespace
9796

98-
auto miral::launch_app_env(
99-
std::vector<std::string> const& app,
100-
mir::optional_value<std::string> const& wayland_display,
101-
mir::optional_value<std::string> const& x11_display,
102-
miral::AppEnvironment const& app_env) -> pid_t
97+
void assign_or_unset(Environment& env, std::string const& key, auto optional_value)
10398
{
104-
Environment application_environment;
105-
106-
for (auto const& [key, value]: app_env)
107-
{
108-
if (value)
109-
{
110-
application_environment.setenv(key, value.value());
111-
}
112-
else
113-
{
114-
application_environment.unsetenv(key);
115-
}
116-
}
117-
118-
if (wayland_display)
99+
if (optional_value)
119100
{
120-
application_environment.setenv("WAYLAND_DISPLAY", wayland_display.value()); // configure Wayland socket
101+
env.setenv(key, optional_value.value());
121102
}
122103
else
123104
{
124-
application_environment.unsetenv("WAYLAND_DISPLAY");
125-
}
126-
127-
if (x11_display)
128-
{
129-
application_environment.setenv("DISPLAY", x11_display.value()); // configure X11 socket
130-
}
131-
else
132-
{
133-
application_environment.unsetenv("DISPLAY");
105+
env.unsetenv(key);
134106
}
107+
}
135108

109+
auto execute_with_environment(std::vector<std::string> const app, Environment& application_environment) -> pid_t
110+
{
136111
auto const exec_env = application_environment.exec_env();
137112

138113
std::vector<char const*> exec_args;
@@ -155,12 +130,50 @@ auto miral::launch_app_env(
155130
sigfillset(&all_signals);
156131
pthread_sigmask(SIG_UNBLOCK, &all_signals, nullptr);
157132

158-
// execvpe() isn't listed as being async-signal-safe, but the implementation looks fine and rewriting seems unnecessary
159-
execvpe(exec_args[0], const_cast<char*const*>(exec_args.data()), const_cast<char*const*>(exec_env.data()));
133+
// execvpe() isn't listed as being async-signal-safe, but the implementation looks fine and rewriting seems
134+
// unnecessary
135+
execvpe(exec_args[0], const_cast<char* const*>(exec_args.data()), const_cast<char* const*>(exec_env.data()));
160136

161137
mir::log_warning("Failed to execute client (\"%s\") error: %s", exec_args[0], strerror(errno));
162138
exit(EXIT_FAILURE);
163139
}
164140

165141
return pid;
166142
}
143+
} // namespace
144+
145+
auto miral::launch_app_env(
146+
std::vector<std::string> const& app,
147+
mir::optional_value<std::string> const& wayland_display,
148+
mir::optional_value<std::string> const& x11_display,
149+
miral::AppEnvironment const& app_env) -> pid_t
150+
{
151+
Environment application_environment;
152+
153+
for (auto const& [key, value]: app_env)
154+
assign_or_unset(application_environment, key, value);
155+
156+
assign_or_unset(application_environment, "WAYLAND_DISPLAY", wayland_display); // configure Wayland socket
157+
assign_or_unset(application_environment, "DISPLAY", x11_display); // configure X11 socket
158+
159+
return execute_with_environment(app, application_environment);
160+
}
161+
162+
auto miral::launch_app_env(
163+
std::vector<std::string> const& app,
164+
mir::optional_value<std::string> const& wayland_display,
165+
mir::optional_value<std::string> const& x11_display,
166+
std::optional<std::string> const& xdg_activation_token,
167+
miral::AppEnvironment const& app_env) -> pid_t
168+
{
169+
Environment application_environment;
170+
171+
for (auto const& [key, value]: app_env)
172+
assign_or_unset(application_environment, key, value);
173+
174+
assign_or_unset(application_environment, "WAYLAND_DISPLAY", wayland_display); // configure Wayland socket
175+
assign_or_unset(application_environment, "DISPLAY", x11_display); // configure X11 socket
176+
assign_or_unset(application_environment, "XDG_ACTIVATION_TOKEN", xdg_activation_token);
177+
178+
return execute_with_environment(app, application_environment);
179+
}

src/miral/launch_app.h

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ auto launch_app_env(std::vector<std::string> const& app,
3535
mir::optional_value<std::string> const& wayland_display,
3636
mir::optional_value<std::string> const& x11_display,
3737
AppEnvironment const& app_env) -> pid_t;
38+
39+
auto launch_app_env(std::vector<std::string> const& app,
40+
mir::optional_value<std::string> const& wayland_display,
41+
mir::optional_value<std::string> const& x11_display,
42+
std::optional<std::string> const& xdg_activation_token,
43+
AppEnvironment const& app_env) -> pid_t;
3844
}
3945

4046
#endif //MIRAL_LAUNCH_APP_H

src/server/frontend_wayland/xdg_activation_v1.cpp

+15-85
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include "mir/shell/shell.h"
2727
#include "mir/wayland/protocol_error.h"
2828
#include "mir/log.h"
29-
#include <random>
3029
#include <chrono>
3130
#include <uuid.h>
3231
#include <mir/events/keyboard_event.h>
@@ -76,90 +75,6 @@ struct XdgActivationTokenData
7675
};
7776

7877

79-
class XdgActivationV1 : public wayland::XdgActivationV1::Global
80-
{
81-
public:
82-
XdgActivationV1(
83-
struct wl_display* display,
84-
std::shared_ptr<msh::Shell> const& shell,
85-
std::shared_ptr<ms::SessionCoordinator> const& session_coordinator,
86-
std::shared_ptr<MainLoop> const& main_loop,
87-
std::shared_ptr<ObserverRegistrar<input::KeyboardObserver>> const& keyboard_observer_registrar,
88-
Executor& wayland_executor);
89-
~XdgActivationV1();
90-
91-
std::shared_ptr<XdgActivationTokenData> const& create_token(std::shared_ptr<ms::Session> const& session);
92-
std::shared_ptr<XdgActivationTokenData> try_consume_token(std::string const& token);
93-
void invalidate_all();
94-
void invalidate_if_not_from_session(std::shared_ptr<ms::Session> const&);
95-
96-
private:
97-
class Instance : public wayland::XdgActivationV1
98-
{
99-
public:
100-
Instance(
101-
struct wl_resource* resource,
102-
mf::XdgActivationV1* xdg_activation_v1,
103-
std::shared_ptr<msh::Shell> const& shell,
104-
std::shared_ptr<ms::SessionCoordinator> const& session_coordinator,
105-
std::shared_ptr<MainLoop> const& main_loop);
106-
107-
private:
108-
void get_activation_token(struct wl_resource* id) override;
109-
110-
void activate(std::string const& token, struct wl_resource* surface) override;
111-
112-
mf::XdgActivationV1* xdg_activation_v1;
113-
std::shared_ptr<msh::Shell> shell;
114-
std::shared_ptr<ms::SessionCoordinator> const session_coordinator;
115-
std::shared_ptr<MainLoop> main_loop;
116-
};
117-
118-
class KeyboardObserver: public input::KeyboardObserver
119-
{
120-
public:
121-
KeyboardObserver(XdgActivationV1* xdg_activation_v1);
122-
void keyboard_event(std::shared_ptr<MirEvent const> const& event) override;
123-
void keyboard_focus_set(std::shared_ptr<mi::Surface> const& surface) override;
124-
125-
private:
126-
XdgActivationV1* xdg_activation_v1;
127-
};
128-
129-
class SessionListener : public ms::SessionListener
130-
{
131-
public:
132-
SessionListener(XdgActivationV1* xdg_activation_v1);
133-
void starting(std::shared_ptr<ms::Session> const&) override {}
134-
void stopping(std::shared_ptr<ms::Session> const&) override {}
135-
void focused(std::shared_ptr<ms::Session> const& session) override;
136-
void unfocused() override {}
137-
138-
void surface_created(ms::Session&, std::shared_ptr<ms::Surface> const&) override {}
139-
void destroying_surface(ms::Session&, std::shared_ptr<ms::Surface> const&) override {}
140-
141-
void buffer_stream_created(
142-
ms::Session&,
143-
std::shared_ptr<mf::BufferStream> const&) override {}
144-
void buffer_stream_destroyed(
145-
ms::Session&,
146-
std::shared_ptr<mf::BufferStream> const&) override {}
147-
148-
private:
149-
XdgActivationV1* xdg_activation_v1;
150-
};
151-
152-
void bind(wl_resource* resource) override;
153-
154-
std::shared_ptr<msh::Shell> shell;
155-
std::shared_ptr<ms::SessionCoordinator> const session_coordinator;
156-
std::shared_ptr<MainLoop> main_loop;
157-
std::shared_ptr<ObserverRegistrar<input::KeyboardObserver>> keyboard_observer_registrar;
158-
std::shared_ptr<KeyboardObserver> keyboard_observer;
159-
std::vector<std::shared_ptr<XdgActivationTokenData>> pending_tokens;
160-
std::mutex pending_tokens_mutex;
161-
};
162-
16378
class XdgActivationTokenV1 : public wayland::XdgActivationTokenV1
16479
{
16580
public:
@@ -231,6 +146,21 @@ std::shared_ptr<mf::XdgActivationTokenData> const& mf::XdgActivationV1::create_t
231146
}
232147
}
233148

149+
std::string mf::XdgActivationV1::create_token_string()
150+
{
151+
auto generated = generate_token();
152+
auto token = std::make_shared<XdgActivationTokenData>(generated, main_loop->create_alarm([this, generated]()
153+
{
154+
try_consume_token(generated);
155+
}), nullptr);
156+
157+
{
158+
std::lock_guard guard(pending_tokens_mutex);
159+
pending_tokens.emplace_back(std::move(token));
160+
return pending_tokens.back()->token;
161+
}
162+
}
163+
234164
std::shared_ptr<mf::XdgActivationTokenData> mf::XdgActivationV1::try_consume_token(std::string const& token)
235165
{
236166
{

0 commit comments

Comments
 (0)