Cursor and autocomplete disappearing when moving to new window

Hi there,

I have a React app where I have a CM code editor (built into an interface) that has the option to window.open the whole thing to a new window. This works well except the CM cursor disappears (until popped back into its original window) and auto complete stops working until its moved onto a new screen. I see in the past there was the .refresh() function. Is there something similar in CM 6 in state or view?

Or is there a better way to do this? Creating a new CM instance and moving that into the window seems to be missing the cursor/suggestions as well.

Thanks in advance!

Do I understand correctly that you’re taking the existing DOM element and moving that to a new window?

Hi Marijn,

Yes, that’s correct - using React’s createPortal which leaves it linked to the current React app so it still shares reactivity, state, js, etc.

With the patch below, EditorView.setRoot can be called when an editor is moved to a new window or shadow root, which will make sure view.root returns the right thing and event handlers are moved to the proper window.

Amazing! Thanks for pushing a fix so quickly.

Hi @marijn

I spent some time testing the patched EditorView with setRoot today and unfortunately, it didn’t fix my issue with React’s createPortal using window.open() (setRoot works well though). But I figured out how it can be fixed (and I believe it should be easy). The issue is that hasFocus doesn’t get set to true, even when CM has focus in the new window. This leads to the cursor being set to display: none and I’m sure other problems I haven’t encountered yet.

The fix:

In view.js in the hasFocus() getter on line 6698:

return (document.hasFocus() || browser.safari && ((_a = this.inputState) === null || _a === void 0 ? void 0 : _a.lastContextMenu) > Date.now() - 3e4) &&
            this.root.activeElement == this.contentDOM;

document.hasFocus() should be changed to this.root.hasFocus() (and whatever the safari equivalent is, if necessary). I realize only the document has access to the hasFocus() method but since you use this.root.activeElement (which is also only available on the document), I think it’s okay. Maybe a check needs to be done before the return statement to see if this.root is a document and if it isn’t, check this.root.ownerDocument.hasFocus() and this.root.ownerDocument.activeElement == this.contentDOM instead.

I did some testing and definitely got my cursor back and it seemed like everything was still working.

Please let me know if I didn’t explain any of that well enough and thank you in advance!

Good point — I checked all references to window, but missed some to document. Does this patch solve your issue?

Yep, that did it! Thank you @marijn - I’m not sure I’ve ever seen a developer be so responsive to an issue so quickly.