@@ -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,26 @@ 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 = token->surface ? wf::wl_surface_to_wayfire_view (
129+ token->surface ->resource ) : nullptr ;
130+ if (view)
131+ {
132+ last_view = wf::toplevel_cast (view); // might return nullptr
133+ if (last_view)
134+ {
135+ last_view->connect (&on_view_unmapped);
136+ last_view->connect (&on_view_deactivated);
137+ }
138+ }
139+
103140 // update our token and connect its destroy signal
104141 last_token = token;
105142 xdg_activation_token_destroy.disconnect ();
@@ -125,14 +162,43 @@ class wayfire_xdg_activation_protocol_impl : public wf::plugin_interface_t
125162 }
126163 };
127164
165+ wf::signal::connection_t <wf::view_unmapped_signal> on_view_unmapped = [this ] (auto )
166+ {
167+ last_view->disconnect (&on_view_unmapped);
168+ last_view->disconnect (&on_view_deactivated);
169+ // handle the case when last_view was a dialog that is closed by user interaction
170+ last_view = last_view->parent ;
171+ if (last_view)
172+ {
173+ last_view->connect (&on_view_unmapped);
174+ last_view->connect (&on_view_deactivated);
175+ }
176+ };
177+
178+ wf::signal::connection_t <wf::view_activated_state_signal> on_view_deactivated = [this ] (auto )
179+ {
180+ if (last_view->activated )
181+ {
182+ // could be a spurious event, e.g. activating the parent
183+ // view after closing a dialog
184+ return ;
185+ }
186+
187+ last_view->disconnect (&on_view_unmapped);
188+ last_view->disconnect (&on_view_deactivated);
189+ last_view = nullptr ;
190+ };
191+
128192 struct wlr_xdg_activation_v1 *xdg_activation;
129193 wf::wl_listener_wrapper xdg_activation_request_activate;
130194 wf::wl_listener_wrapper xdg_activation_new_token;
131195 wf::wl_listener_wrapper xdg_activation_token_destroy;
132196 struct wlr_xdg_activation_token_v1 *last_token = nullptr ;
197+ wayfire_toplevel_view last_view = nullptr ; // view that created the token
133198
134199 wf::option_wrapper_t <bool > check_surface{" xdg-activation/check_surface" };
135200 wf::option_wrapper_t <bool > only_last_token{" xdg-activation/only_last_request" };
201+ wf::option_wrapper_t <bool > prevent_focus_stealing{" xdg-activation/focus_stealing_prevention" };
136202 wf::option_wrapper_t <int > timeout{" xdg-activation/timeout" };
137203};
138204
0 commit comments