Fix QTerminalWidget key interception and font size propagation
ober
bfe3fe0f127e7ab2c9ab98d19b0f783de735b92d
--- a/lib/jerboa-emacs/qt/app.sls +++ b/lib/jerboa-emacs/qt/app.sls @@ -752,7 +752,8 @@ "commands registered: " (number->string (hash-length *all-commands*)) " total") - (let ([image-key-installed (make-hash-table-eq)]) + (let ([image-key-installed (make-hash-table-eq)] + [terminal-key-installed (make-hash-table-eq)]) (add-hook! 'post-buffer-attach-hook (lambda (editor buf) @@ -771,11 +772,15 @@ (let* ([container (qt-edit-window-container win)] [count (qt-stacked-widget-count - container)]) + container)] + [tw (qt-terminal-widget term)]) (qt-stacked-widget-set-current-index! container (- count 1)) - (qt-terminal-focus! term)))))] + (unless (hash-get terminal-key-installed tw) + ((app-state-key-handler app) tw) + (hash-put! terminal-key-installed tw #t)) + (qt-widget-set-focus! tw)))))] [(image-buffer? buf) (qt-show-image-buffer! editor buf) (let ([win (hash-get *editor-window-map* editor)]) --- a/lib/jerboa-emacs/qt/commands-config.sls +++ b/lib/jerboa-emacs/qt/commands-config.sls @@ -19,10 +19,10 @@ *profiler-data* cmd-profiler-start cmd-profiler-stop cmd-show-tab-count cmd-show-trailing-whitespace-count *SCI_SETCODEPAGE* *SC_CP_UTF8* qt-insert-prompt! - terminal-buffer-counter *terminal-widget-map* cmd-term - cmd-terminal-send cmd-term-interrupt cmd-term-send-eof - cmd-term-send-tab cmd-multi-vterm *terminal-copy-mode* - cmd-vterm-copy-mode cmd-vterm-copy-done get-terminal-buffers + terminal-buffer-counter cmd-term cmd-terminal-send + cmd-term-interrupt cmd-term-send-eof cmd-term-send-tab + cmd-multi-vterm *terminal-copy-mode* cmd-vterm-copy-mode + cmd-vterm-copy-done get-terminal-buffers qt-switch-to-terminal! cmd-term-list cmd-term-next cmd-term-prev cmd-ediff-files cmd-comment-dwim) (import @@ -223,6 +223,13 @@ (loop (+ i 1)))) (restore-margin-colors! ed))) (qt-frame-windows fr))) + (hash-for-each + (lambda (_buf term) + (qt-terminal-set-font! + term + *default-font-family* + *default-font-size*)) + *terminal-widget-map*) (when *qt-app-ptr* (qt-app-set-style-sheet! *qt-app-ptr* (theme-stylesheet)))) (def (cmd-set-frame-font app) @@ -893,8 +900,6 @@ (sci-send ed SCI_SETSTYLING text-len style)) (loop (cdr segs) (+ pos text-len))))))) (define terminal-buffer-counter--cell (vector 0)) - (define *terminal-widget-map*--cell - (vector (make-hash-table-eq))) (def (cmd-term app) "Open a QTerminalWidget-backed terminal buffer.\n Uses libvterm for proper VT100 terminal emulation with full color support." (verbose-log! "cmd-term: begin (QTerminalWidget)") @@ -933,6 +938,7 @@ (qt-terminal-widget term))]) (qt-stacked-widget-set-current-index! container idx)) (hash-put! *terminal-widget-map* buf term) + ((app-state-key-handler app) (qt-terminal-widget term)) (qt-terminal-spawn! term "") (qt-terminal-focus! term) (verbose-log! "cmd-term: QTerminalWidget spawned") @@ -1410,13 +1416,6 @@ terminal-buffer-counter--cell 0 val)])) - (define-syntax *terminal-widget-map* - (identifier-syntax - [id (vector-ref *terminal-widget-map*--cell 0)] - [(set! id val) (vector-set! - *terminal-widget-map*--cell - 0 - val)])) (define-syntax *terminal-copy-mode* (identifier-syntax [id (vector-ref *terminal-copy-mode*--cell 0)] --- a/lib/jerboa-emacs/qt/commands-shell.sls +++ b/lib/jerboa-emacs/qt/commands-shell.sls @@ -3,30 +3,31 @@ ;;; Source: src/jerboa-emacs/qt/commands-shell.ss (library (jerboa-emacs qt commands-shell) - (export directory-exists? apply-font-size-to-all-editors! - cmd-increase-font-size cmd-decrease-font-size - cmd-reset-font-size cmd-goto-first-non-blank - cmd-goto-last-non-blank cmd-move-to-window-top - cmd-move-to-window-middle cmd-move-to-window-bottom - cmd-scroll-left cmd-scroll-right cmd-insert-let - cmd-insert-lambda cmd-insert-defun cmd-insert-cond - cmd-insert-when cmd-insert-unless cmd-insert-match - cmd-insert-import cmd-insert-export cmd-insert-include - cmd-insert-file-header cmd-insert-header-guard - cmd-insert-box-comment cmd-insert-file-contents - cmd-insert-register-string *auto-indent* *backup-files* - *version-control* *debug-mode* *debug-on-quit* - *visible-bell* *transient-mark* *electric-indent* - cmd-toggle-auto-indent cmd-toggle-backup-files - cmd-toggle-version-control cmd-toggle-debug-mode - cmd-toggle-debug-on-quit cmd-toggle-visible-bell - cmd-toggle-transient-mark cmd-toggle-electric-indent - cmd-toggle-auto-revert cmd-toggle-auto-revert-global - cmd-auto-revert-tail-mode *view-mode-buffers* cmd-view-mode - *so-long-threshold* *so-long-buffers* check-so-long! - cmd-so-long-mode *follow-mode* cmd-follow-mode - *command-history-file* savehist-save! savehist-load! - auto-fill-check! qt-aggressive-indent-line! + (export directory-exists? *terminal-widget-map* + apply-font-size-to-all-editors! cmd-increase-font-size + cmd-decrease-font-size cmd-reset-font-size + cmd-goto-first-non-blank cmd-goto-last-non-blank + cmd-move-to-window-top cmd-move-to-window-middle + cmd-move-to-window-bottom cmd-scroll-left cmd-scroll-right + cmd-insert-let cmd-insert-lambda cmd-insert-defun + cmd-insert-cond cmd-insert-when cmd-insert-unless + cmd-insert-match cmd-insert-import cmd-insert-export + cmd-insert-include cmd-insert-file-header + cmd-insert-header-guard cmd-insert-box-comment + cmd-insert-file-contents cmd-insert-register-string + *auto-indent* *backup-files* *version-control* *debug-mode* + *debug-on-quit* *visible-bell* *transient-mark* + *electric-indent* cmd-toggle-auto-indent + cmd-toggle-backup-files cmd-toggle-version-control + cmd-toggle-debug-mode cmd-toggle-debug-on-quit + cmd-toggle-visible-bell cmd-toggle-transient-mark + cmd-toggle-electric-indent cmd-toggle-auto-revert + cmd-toggle-auto-revert-global cmd-auto-revert-tail-mode + *view-mode-buffers* cmd-view-mode *so-long-threshold* + *so-long-buffers* check-so-long! cmd-so-long-mode + *follow-mode* cmd-follow-mode *command-history-file* + savehist-save! savehist-load! auto-fill-check! + qt-aggressive-indent-line! cmd-toggle-delete-trailing-whitespace-on-save uniquify-parent-suffix uniquify-buffer-name! cmd-recentf-open-files cmd-toggle-frame-fullscreen @@ -115,6 +116,8 @@ (jerboa runtime)) (def (directory-exists? path) (and (file-exists? path) (file-directory? path))) + (define *terminal-widget-map*--cell + (vector (make-hash-table-eq))) (def (apply-font-size-to-all-editors! app) "Apply the current global font size to all open editors." (let ([fr (app-state-frame app)] @@ -131,6 +134,13 @@ (sci-send ed SCI_SETMARGINWIDTHN 0 margin-w) (qt-apply-editor-theme! ed))) (qt-frame-windows fr))) + (hash-for-each + (lambda (_buf term) + (qt-terminal-set-font! + term + *default-font-family* + *default-font-size*)) + *terminal-widget-map*) (when *qt-app-ptr* (qt-app-set-style-sheet! *qt-app-ptr* (theme-stylesheet)))) (def (cmd-increase-font-size app) @@ -2263,6 +2273,13 @@ (or (char=? (string-ref str i) #\q) (char=? (string-ref str i) (integer->char 3)) (scan (+ i 1))))))) + (define-syntax *terminal-widget-map* + (identifier-syntax + [id (vector-ref *terminal-widget-map*--cell 0)] + [(set! id val) (vector-set! + *terminal-widget-map*--cell + 0 + val)])) (define-syntax *auto-indent* (identifier-syntax [id (vector-ref *auto-indent*--cell 0)] --- a/src/jerboa-emacs/qt/app.ss +++ b/src/jerboa-emacs/qt/app.ss @@ -815,7 +815,8 @@ ;; When showing an image, install key handler on the scroll area and ;; set focus there — the Scintilla editor is hidden by QStackedWidget ;; so it can't receive key events. - (let ((image-key-installed (make-hash-table-eq))) + (let ((image-key-installed (make-hash-table-eq)) + (terminal-key-installed (make-hash-table-eq))) (add-hook! 'post-buffer-attach-hook (lambda (editor buf) (with-catch @@ -830,12 +831,16 @@ (let ((win (hash-get *editor-window-map* editor))) (when win (let* ((container (qt-edit-window-container win)) - ;; Find the terminal widget's index in the stacked widget - ;; It was added after the editor (0) and possibly image (1) - (count (qt-stacked-widget-count container))) + (count (qt-stacked-widget-count container)) + (tw (qt-terminal-widget term))) ;; Switch to the last index (terminal) (qt-stacked-widget-set-current-index! container (- count 1)) - (qt-terminal-focus! term)))))) + ;; Install consuming key filter on terminal widget if not yet done + ;; (guards against double-install which would double-fire events) + (unless (hash-get terminal-key-installed tw) + ((app-state-key-handler app) tw) + (hash-put! terminal-key-installed tw #t)) + (qt-widget-set-focus! tw)))))) ;; Image buffers ((image-buffer? buf) (qt-show-image-buffer! editor buf) --- a/src/jerboa-emacs/qt/commands-config.ss +++ b/src/jerboa-emacs/qt/commands-config.ss @@ -194,6 +194,11 @@ ;; Restore margin and default colors (font loop may have corrupted them) (restore-margin-colors! ed))) (qt-frame-windows fr))) + ;; Apply font to QTerminalWidget buffers + (hash-for-each + (lambda (_buf term) + (qt-terminal-set-font! term *default-font-family* *default-font-size*)) + *terminal-widget-map*) ;; Update Qt stylesheet so chrome widgets match (when *qt-app-ptr* (qt-app-set-style-sheet! *qt-app-ptr* (theme-stylesheet)))) @@ -749,8 +754,7 @@ modified so the next save uses the new encoding." (def terminal-buffer-counter 0) -;; Map buffer → QTerminalWidget pointer for the libvterm-based terminal -(def *terminal-widget-map* (make-hash-table-eq)) +;; *terminal-widget-map* is defined in commands-shell (which this module imports) (def (cmd-term app) "Open a QTerminalWidget-backed terminal buffer. @@ -791,6 +795,10 @@ modified so the next save uses the new encoding." (qt-stacked-widget-set-current-index! container idx)) ;; Store widget mapping for key forwarding and buffer switching (hash-put! *terminal-widget-map* buf term) + ;; Install consuming key filter so all keys go through Scheme first + ;; (same pattern as image scroll widgets — without this, Qt sends keys + ;; directly to QTerminalWidget::keyPressEvent, bypassing jemacs entirely) + ((app-state-key-handler app) (qt-terminal-widget term)) ;; Spawn the user's shell (qt-terminal-spawn! term "") ;; Focus the terminal widget --- a/src/jerboa-emacs/qt/commands-shell.ss +++ b/src/jerboa-emacs/qt/commands-shell.ss @@ -60,6 +60,11 @@ ;;; Batch 8: Remaining missing commands ;;;============================================================================ +;; Map buffer → QTerminalWidget pointer for the libvterm-based terminal +;; Defined here (commands-shell) because commands-config imports commands-shell, +;; so moving it here makes it visible to both without circular dependency. +(def *terminal-widget-map* (make-hash-table-eq)) + ;; --- Font size --- ;; Note: Font size state is now in face.ss (*default-font-size*) @@ -77,6 +82,11 @@ ;; Re-apply theme (STYLECLEARALL resets colors) (qt-apply-editor-theme! ed))) (qt-frame-windows fr))) + ;; Apply font size to QTerminalWidget buffers + (hash-for-each + (lambda (_buf term) + (qt-terminal-set-font! term *default-font-family* *default-font-size*)) + *terminal-widget-map*) ;; Update Qt stylesheet so chrome widgets match (when *qt-app-ptr* (qt-app-set-style-sheet! *qt-app-ptr* (theme-stylesheet))))