@@ -36,6 +36,12 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
3636 xdg_activation_new_token.disconnect ();
3737 xdg_activation_token_destroy.disconnect ();
3838 last_token = nullptr ;
39+ if (last_view)
40+ {
41+ last_view->disconnect (&on_view_unmapped);
42+ last_view->disconnect (&on_view_deactivated);
43+ last_view = nullptr ;
44+ }
3945 }
4046
4147 bool is_unloadable () override
@@ -64,6 +70,17 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
6470
6571 last_token = nullptr ; // avoid reusing the same token
6672
73+ if (last_view)
74+ {
75+ last_view->disconnect (&on_view_unmapped);
76+ last_view->disconnect (&on_view_deactivated);
77+ last_view = nullptr ;
78+ } else if (prevent_focus_stealing)
79+ {
80+ LOGI (" Denying focus request, requesting view has been deactivated" );
81+ return ;
82+ }
83+
6784 wayfire_view view = wf::wl_surface_to_wayfire_view (event->surface ->resource );
6885 if (!view)
6986 {
@@ -100,6 +117,25 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
100117 return ;
101118 }
102119
120+ // unset any previously saved view
121+ if (last_view)
122+ {
123+ last_view->disconnect (&on_view_unmapped);
124+ last_view->disconnect (&on_view_deactivated);
125+ last_view = nullptr ;
126+ }
127+
128+ wayfire_view view = wf::wl_surface_to_wayfire_view (token->surface ->resource );
129+ if (view)
130+ {
131+ last_view = wf::toplevel_cast (view); // might return nullptr
132+ if (last_view)
133+ {
134+ last_view->connect (&on_view_unmapped);
135+ last_view->connect (&on_view_deactivated);
136+ }
137+ }
138+
103139 // update our token and connect its destroy signal
104140 last_token = token;
105141 xdg_activation_token_destroy.disconnect ();
@@ -125,14 +161,43 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
125161 }
126162 };
127163
164+ wf::signal::connection_t <wf::view_unmapped_signal> on_view_unmapped = [this ] (auto )
165+ {
166+ last_view->disconnect (&on_view_unmapped);
167+ last_view->disconnect (&on_view_deactivated);
168+ // handle the case when last_view was a dialog that is closed by user interaction
169+ last_view = last_view->parent ;
170+ if (last_view)
171+ {
172+ last_view->connect (&on_view_unmapped);
173+ last_view->connect (&on_view_deactivated);
174+ }
175+ };
176+
177+ wf::signal::connection_t <wf::view_activated_state_signal> on_view_deactivated = [this ] (auto )
178+ {
179+ if (last_view->activated )
180+ {
181+ // could be a spurious event, e.g. activating the parent
182+ // view after closing a dialog
183+ return ;
184+ }
185+
186+ last_view->disconnect (&on_view_unmapped);
187+ last_view->disconnect (&on_view_deactivated);
188+ last_view = nullptr ;
189+ };
190+
128191 struct wlr_xdg_activation_v1 *xdg_activation;
129192 wf::wl_listener_wrapper xdg_activation_request_activate;
130193 wf::wl_listener_wrapper xdg_activation_new_token;
131194 wf::wl_listener_wrapper xdg_activation_token_destroy;
132195 struct wlr_xdg_activation_token_v1 *last_token = nullptr ;
196+ wayfire_toplevel_view last_view = nullptr ; // view that created the token
133197
134198 wf::option_wrapper_t <bool > check_surface{" xdg-activation/check_surface" };
135199 wf::option_wrapper_t <bool > only_last_token{" xdg-activation/only_last_request" };
200+ wf::option_wrapper_t <bool > prevent_focus_stealing{" xdg-activation/focus_stealing_prevention" };
136201 wf::option_wrapper_t <int > timeout{" xdg-activation/timeout" };
137202};
138203
0 commit comments