--- a/src/core/seat/keyboard.cpp +++ b/src/core/seat/keyboard.cpp @@ -46,6 +46,26 @@ if ((is_im_sent || !handle_keyboard_key(ev->keycode, ev->state)) && (mode == input_event_processing_mode_t::FULL)) { + // wlroots grabs keyboard input during DnD and does not forward + // Escape to clients. Cancel here so every source gets cancelled, + // including a foreign app or one whose original tab is now hidden. + if (seat->priv->active_drag && ev->keycode == KEY_ESC && + ev->state == WL_KEYBOARD_KEY_STATE_PRESSED) + { + auto drag = seat->priv->active_drag; + if (drag->source) + { + wlr_data_source_destroy(drag->source); + } else + { + drag->keyboard_grab.interface->cancel(&drag->keyboard_grab); + } + + // Do not record the press: its release must not reach a client + // which never received the corresponding press. + return emit_device_post_event_signal(ev, &handle->base); + } + if (!is_im_sent && wf::get_core_impl().im_relay->handle_key(handle, ev->time_msec, ev->keycode, ev->state)) {