Fix select-all-kill-region and cx0-removes-current-window behavioral test failures
ober
6f617fd119f607243b4d412f6b5fe9ed8c5f952b
--- a/src/jerboa-emacs/qt/automation.ss +++ b/src/jerboa-emacs/qt/automation.ss @@ -206,13 +206,20 @@ (def (send-one-key! app key-str drain?) (let-values (((code mods text) (emacs-key->qt-event key-str))) (let* ((fr (app-state-frame app)) - (target (if *minibuffer-active?* - (and *mb-input* *mb-input*) - (qt-current-editor fr)))) + (get-target (lambda () + (if *minibuffer-active?* + (and *mb-input* *mb-input*) + (qt-current-editor fr)))) + (target (get-target))) (when target (qt-send-key-press! target code mods text) (when drain? (qt-drain-pending-callbacks!)) - (qt-send-key-release! target code mods text) + ;; Re-fetch target after drain: the key handler may have destroyed the + ;; pressed window (e.g. C-x 0). Sending key release to a destroyed + ;; widget causes a segfault via Qt's sendPostedEvents / event dispatch. + (let ((release-target (get-target))) + (when release-target + (qt-send-key-release! release-target code mods text))) (when drain? (qt-drain-pending-callbacks!)))))) ;;;============================================================================ --- a/src/jerboa-emacs/qt/commands-core.ss +++ b/src/jerboa-emacs/qt/commands-core.ss @@ -1187,8 +1187,15 @@ Returns (path . line) or #f. Handles file:line format." ;;;============================================================================ (def (cmd-select-all app) - (qt-plain-text-edit-select-all! (current-qt-editor app)) - (echo-message! (app-state-echo app) "Mark set (whole buffer)")) + (let* ((ed (current-qt-editor app)) + (buf (current-qt-buffer app)) + (len (qt-plain-text-edit-text-length ed))) + ;; SCI_SELECTALL sets caret=0, anchor=length (caret at start). + ;; Use set-selection! to place anchor=0, caret=len (caret at end) + ;; so that kill-region/copy-region see mark=0 and pos=len correctly. + (qt-plain-text-edit-set-selection! ed 0 len) + (set! (buffer-mark buf) 0) + (echo-message! (app-state-echo app) "Mark set (whole buffer)"))) ;;;============================================================================ ;;; Goto line --- a/vendor/qt_shim.cpp +++ b/vendor/qt_shim.cpp @@ -907,8 +907,12 @@ static void qt_cleanup_extra_selections(void* w); extern "C" void qt_widget_destroy(qt_widget_t w) { QT_NULL_CHECK_VOID(w); // H1: null guard QT_VOID( + QWidget* widget = static_cast<QWidget*>(w); qt_cleanup_extra_selections(w); // L1: clean up extra selections - delete static_cast<QWidget*>(w) + // Use deleteLater() instead of delete to avoid use-after-free: + // pending Qt events (resize, paint, focus) may still reference this + // widget and will crash if processed after synchronous deletion. + widget->deleteLater() ); }