wf-kill: cancel a pending selection when the output is inhibited (session lock) and restore the cursor when the last grabbed output is removed. - grab_interface becomes a member of wf_kill_view with a .cancel handler. output_t::set_inhibited(true) (session lock) calls cancel_active_plugins(); previously wf-kill had no cancel callback, so its grab and activation survived the lock and the first left click after unlock closed (and with -k SIGKILLed) the window under the pointer. - New wf_kill_view::cancel_grab(): release all grabs, drop the pending pirate-cursor idle call, restore the default cursor, send cancel to the requester. Used by the cancel handler and by the output pre-remove path, which previously did not restore the cursor. diff --git a/src/plugin/wayfire-kill-view.cpp b/src/plugin/wayfire-kill-view.cpp index 3c657b7..64fb13b 100644 --- a/src/plugin/wayfire-kill-view.cpp +++ b/src/plugin/wayfire-kill-view.cpp @@ -38,11 +38,6 @@ #include "wayfire-kill-view.hpp" #include "wayfire-kill-view-server-protocol.h" -wf::plugin_activation_data_t grab_interface{ - .name = "wf-kill", - .capabilities = wf::CAPABILITY_GRAB_INPUT, -}; - static void bind_manager(wl_client *client, void *data, uint32_t version, uint32_t id); @@ -101,6 +96,24 @@ void wf_kill_view::release_grabs() grab_active = false; } +/* Abort a live selection without closing anything (lock, output loss). */ +void wf_kill_view::cancel_grab() +{ + if (!grab_active) + { + return; + } + + release_grabs(); + idle_set_cursor.disconnect(); + wf::get_core().set_cursor("default"); + if (requester) + { + send_cancel(requester); + requester = nullptr; + } +} + void wf_kill_view::start_grab(wl_resource *resource) { /* One selection at a time; replacing a live grab orphans its scene node. */ @@ -196,6 +209,13 @@ void wf_kill_view::set_base_ptr(wf::pointer_interaction_t *base) wf_kill_view::wf_kill_view() { + /* Output inhibition (session lock) cancels active plugins; without this + * the selection would survive the lock and fire on the next click. */ + grab_interface.cancel = [=] () + { + cancel_grab(); + }; + manager = wl_global_create(wf::get_core().display, &wf_kill_view_base_interface, 1, this, bind_manager); @@ -216,15 +236,9 @@ wf_kill_view::wf_kill_view() it->second->ungrab_input(); ev->output->deactivate_plugin(&grab_interface); input_grabs.erase(it); - if (input_grabs.empty() && grab_active) + if (input_grabs.empty()) { - grab_active = false; - idle_set_cursor.disconnect(); - if (requester) - { - send_cancel(requester); - requester = nullptr; - } + cancel_grab(); } }; wf::get_core().output_layout->connect(&on_output_pre_remove); diff --git a/src/plugin/wayfire-kill-view.hpp b/src/plugin/wayfire-kill-view.hpp index b7e5696..8e8210c 100644 --- a/src/plugin/wayfire-kill-view.hpp +++ b/src/plugin/wayfire-kill-view.hpp @@ -27,12 +27,17 @@ #include #include #include +#include class wf_kill_view { wl_global *manager; public: + wf::plugin_activation_data_t grab_interface{ + .name = "wf-kill", + .capabilities = wf::CAPABILITY_GRAB_INPUT, + }; wf::pointer_interaction_t *base; void set_base_ptr(wf::pointer_interaction_t *base); std::vector client_resources; @@ -41,6 +46,7 @@ class wf_kill_view bool grab_active = false; void start_grab(wl_resource *resource); void release_grabs(); + void cancel_grab(); void client_destroyed(wl_resource *resource); void close_view(wayfire_view view, wl_resource *resource); void send_view_info(wl_resource *resource);