@@ -34,6 +34,10 @@ import {
3434 removeActionStackEntries ,
3535 shouldCaptureModifierInput ,
3636} from "./quickToolsState" ;
37+ import {
38+ captureReadOnlyQuickToolsKey ,
39+ createReadOnlyQuickToolsCaptureSession ,
40+ } from "./readOnlyQuickToolsCapture" ;
3741
3842export let quickToolUsed = false ;
3943
@@ -44,6 +48,8 @@ let quickToolUsedTimeout = null;
4448let activeSearchState = null ;
4549/** @type {MutationObserver | null } */
4650let searchCloseVisibilityObserver = null ;
51+ /** @type {import("./readOnlyQuickToolsCapture").ReadOnlyQuickToolsCaptureSession<EditorView> | null } */
52+ let readOnlyCaptureSession = null ;
4753
4854const state = {
4955 shift : false ,
@@ -66,7 +72,16 @@ setQuickToolsModifierInputHandler(handleCodeMirrorQuickToolsTextInput);
6672 * @typedef {(value: boolean)=>void } QuickToolsEventListener
6773 */
6874
75+ quickTools . $input . addEventListener ( "beforeinput" , ( event ) => {
76+ handleReadOnlyQuickToolsCaptureEvent ( event ) ;
77+ } ) ;
78+
79+ quickTools . $input . addEventListener ( "compositionend" , ( event ) => {
80+ handleReadOnlyQuickToolsCaptureEvent ( event ) ;
81+ } ) ;
82+
6983quickTools . $input . addEventListener ( "input" , ( e ) => {
84+ if ( handleReadOnlyQuickToolsCaptureEvent ( e ) ) return ;
7085 const key = e . target . value . toUpperCase ( ) ;
7186 quickTools . $input . value = "" ;
7287 if ( ! key || key . length > 1 ) return ;
@@ -98,6 +113,7 @@ quickTools.$input.addEventListener("input", (e) => {
98113} ) ;
99114
100115quickTools . $input . addEventListener ( "keydown" , ( e ) => {
116+ if ( handleReadOnlyQuickToolsCaptureEvent ( e ) ) return ;
101117 const { keyCode, key, which } = e ;
102118 const keyCombination = getKeys ( { keyCode, key, which } ) ;
103119
@@ -245,11 +261,15 @@ export const key = {
245261
246262export function clearQuickToolsModifierState ( { restoreFocus = false } = { } ) {
247263 const changed = clearModifierState ( state , events ) ;
264+ if ( ! restoreFocus || ! readOnlyCaptureSession ?. consumed ) {
265+ clearReadOnlyCaptureSession ( ) ;
266+ }
248267 if ( restoreFocus ) restoreQuickToolsTargetFocus ( ) ;
249268 return changed ;
250269}
251270
252271export function cancelQuickToolsModifierInput ( ) {
272+ clearReadOnlyCaptureSession ( ) ;
253273 const changed = clearQuickToolsModifierState ( ) ;
254274 quickTools . $input . value = "" ;
255275 quickTools . $input . blur ( ) ;
@@ -284,14 +304,21 @@ export default function actions(action, value) {
284304 if ( shouldCapture ) {
285305 $input . value = "" ;
286306 if ( codeMirrorView ?. state . readOnly ) {
307+ readOnlyCaptureSession = createReadOnlyQuickToolsCaptureSession (
308+ codeMirrorView ,
309+ getQuickToolsModifierSnapshot ( ) ,
310+ ) ;
287311 focusQuickToolsModifierInput ( codeMirrorView , $input ) ;
288312 } else {
313+ clearReadOnlyCaptureSession ( ) ;
289314 $input . focus ( ) ;
290315 }
291316 } else {
317+ clearReadOnlyCaptureSession ( ) ;
292318 if ( codeMirrorView ) focusEditorIfEditable ( codeMirrorView ) ;
293319 }
294320 } else {
321+ clearReadOnlyCaptureSession ( ) ;
295322 restoreQuickToolsTargetFocus ( ) ;
296323 }
297324
@@ -440,6 +467,67 @@ function getCodeMirrorInputView(target) {
440467 : null ;
441468}
442469
470+ function handleReadOnlyQuickToolsCaptureEvent ( event ) {
471+ const session = readOnlyCaptureSession ;
472+ if ( ! session ) return false ;
473+
474+ const view = session . target ;
475+ if (
476+ ! view ?. state ?. readOnly ||
477+ ! view . contentDOM ?. isConnected ||
478+ ! view . dom ?. isConnected
479+ ) {
480+ cancelQuickToolsModifierInput ( ) ;
481+ preventCaptureInput ( event ) ;
482+ return true ;
483+ }
484+
485+ const result = captureReadOnlyQuickToolsKey ( session , {
486+ type : event . type ,
487+ key : event . key ,
488+ data : event . data ,
489+ value : quickTools . $input . value ,
490+ inputType : event . inputType ,
491+ isComposing : event . isComposing ,
492+ } ) ;
493+ readOnlyCaptureSession = result . session ;
494+
495+ if ( result . outcome . kind === "pass" ) return false ;
496+ if ( result . outcome . kind === "pending" ) {
497+ if ( ! event . isComposing ) {
498+ quickTools . $input . value = "" ;
499+ if ( event . type === "beforeinput" ) preventCaptureInput ( event ) ;
500+ }
501+ return true ;
502+ }
503+
504+ quickTools . $input . value = "" ;
505+ preventCaptureInput ( event ) ;
506+ if ( result . outcome . kind === "duplicate" ) return true ;
507+
508+ const key = result . outcome . key . toUpperCase ( ) ;
509+ const keyCombination = { key, ...session . modifiers } ;
510+ runCodeMirrorQuickToolsTextKey ( view , key , keyCombination ) ;
511+ return true ;
512+ }
513+
514+ function preventCaptureInput ( event ) {
515+ if ( event . cancelable ) event . preventDefault ( ) ;
516+ }
517+
518+ function getQuickToolsModifierSnapshot ( ) {
519+ return {
520+ shiftKey : state . shift ,
521+ altKey : state . alt ,
522+ ctrlKey : state . ctrl ,
523+ metaKey : state . meta ,
524+ } ;
525+ }
526+
527+ function clearReadOnlyCaptureSession ( ) {
528+ readOnlyCaptureSession = null ;
529+ }
530+
443531function runCodeMirrorQuickToolKey ( keyCode , keyCombination ) {
444532 const view = getCodeMirrorInputView ( input ) ;
445533 return view ? runQuickToolKey ( view , keyCode , keyCombination ) : false ;
0 commit comments