88#include < wayfire/nonstd/wlroots-full.hpp>
99#include < wayfire/window-manager.hpp>
1010#include < wayfire/util.hpp>
11+ #include < wayfire/seat.hpp>
1112#include " config.h"
1213
1314class wayfire_xdg_activation_protocol_impl : public wf ::plugin_interface_t
@@ -28,13 +29,15 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
2829
2930 xdg_activation_request_activate.connect (&xdg_activation->events .request_activate );
3031 xdg_activation_new_token.connect (&xdg_activation->events .new_token );
32+ wf::get_core ().connect (&on_run_command);
3133 }
3234
3335 void fini () override
3436 {
3537 xdg_activation_request_activate.disconnect ();
3638 xdg_activation_new_token.disconnect ();
3739 xdg_activation_token_destroy.disconnect ();
40+ xdg_activation_token_self_destroy.disconnect ();
3841 on_view_mapped.disconnect ();
3942 last_token = nullptr ;
4043 if (last_view)
@@ -43,6 +46,8 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
4346 last_view->disconnect (&on_view_deactivated);
4447 last_view = nullptr ;
4548 }
49+
50+ wf::get_core ().disconnect (&on_run_command);
4651 }
4752
4853 bool is_unloadable () override
@@ -57,19 +62,23 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
5762 {
5863 auto event = static_cast <const struct wlr_xdg_activation_v1_request_activate_event *>(data);
5964
60- if (! event->token -> seat )
65+ if (event->token != last_self_token )
6166 {
62- LOGI (" Denying focus request, token was rejected at creation" );
63- return ;
64- }
67+ if (!event->token ->seat )
68+ {
69+ LOGI (" Denying focus request, token was rejected at creation" );
70+ return ;
71+ }
6572
66- if (only_last_token && (event->token != last_token))
67- {
68- LOGI (" Denying focus request, token is expired" );
69- return ;
73+ if (only_last_token && (event->token != last_token))
74+ {
75+ LOGI (" Denying focus request, token is expired" );
76+ return ;
77+ }
7078 }
7179
7280 last_token = nullptr ; // avoid reusing the same token
81+ last_self_token = nullptr ;
7382
7483 if (prevent_focus_stealing && !last_view)
7584 {
@@ -167,6 +176,13 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
167176 xdg_activation_token_destroy.disconnect ();
168177 });
169178
179+ xdg_activation_token_self_destroy.set_callback ([this ] (void *data)
180+ {
181+ last_self_token = nullptr ;
182+
183+ xdg_activation_token_self_destroy.disconnect ();
184+ });
185+
170186 timeout.set_callback (timeout_changed);
171187 }
172188
@@ -226,11 +242,59 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
226242 wf::get_core ().default_wm ->focus_request (signal->view );
227243 };
228244
245+ wf::signal::connection_t <wf::command_run_signal> on_run_command = [this ] (auto signal)
246+ {
247+ if (wf::get_core ().default_wm ->focus_on_map )
248+ {
249+ // no need to do anything if views are focused anyway
250+ return ;
251+ }
252+
253+ if (last_self_token)
254+ {
255+ // TODO: invalidate our last token !
256+ last_self_token = nullptr ;
257+ }
258+
259+ auto active_view = wf::get_core ().seat ->get_active_view ();
260+ if (active_view && (active_view->role == wf::VIEW_ROLE_DESKTOP_ENVIRONMENT ))
261+ {
262+ active_view = nullptr ;
263+ }
264+
265+ auto active_toplevel = active_view ? wf::toplevel_cast (active_view) : nullptr ;
266+
267+ if (!active_toplevel)
268+ {
269+ // if there is no active view, we don't need a token
270+ return ;
271+ }
272+
273+ if (last_view)
274+ {
275+ // TODO: we need a separate last_view actually !
276+ last_view->disconnect (&on_view_unmapped);
277+ last_view->disconnect (&on_view_deactivated);
278+ }
279+
280+ last_view = active_toplevel;
281+ last_view->connect (&on_view_unmapped);
282+ last_view->connect (&on_view_deactivated);
283+ last_self_token = wlr_xdg_activation_token_v1_create (xdg_activation);
284+ xdg_activation_token_self_destroy.disconnect ();
285+ xdg_activation_token_self_destroy.connect (&last_self_token->events .destroy );
286+ const char *token_id = wlr_xdg_activation_token_v1_get_name (last_self_token);
287+ signal->env .emplace_back (" XDG_ACTIVATION_TOKEN" , token_id);
288+ signal->env .emplace_back (" DESKTOP_STARTUP_ID" , token_id);
289+ };
290+
229291 struct wlr_xdg_activation_v1 *xdg_activation;
230292 wf::wl_listener_wrapper xdg_activation_request_activate;
231293 wf::wl_listener_wrapper xdg_activation_new_token;
232294 wf::wl_listener_wrapper xdg_activation_token_destroy;
295+ wf::wl_listener_wrapper xdg_activation_token_self_destroy;
233296 struct wlr_xdg_activation_token_v1 *last_token = nullptr ;
297+ struct wlr_xdg_activation_token_v1 *last_self_token = nullptr ;
234298 wayfire_toplevel_view last_view = nullptr ; // view that created the token
235299
236300 wf::option_wrapper_t <bool > check_surface{" xdg-activation/check_surface" };
0 commit comments