Skip to content

Commit d87d5f7

Browse files
committed
fix: fixed #2635
1 parent ab1aa15 commit d87d5f7

File tree

7 files changed

+59
-24
lines changed

7 files changed

+59
-24
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## [Unreleased]
2+
3+
### Issues Resolved
4+
5+
- **#2635** In Chrome (and Firefox), clicking on the padding area of the
6+
mathfield would not result in the focus getting into a zombie state and
7+
keyboard event no longer being dispatched.
8+
19
## 0.104.2 _2025-03-23_
210

311
### Issues Resolved

css/mathfield.less

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
);
111111
}
112112

113-
// prevent pointer-down event on touch devices if the host isn't focused
113+
// Prevent pointer-down event on touch devices if the host isn't focused
114114
// this allows scrolling if you touch unfocused fields
115115
@media (hover: none) and (pointer: coarse) {
116116
:host(:not(:focus)) .ML__container {

package.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
"module": "./dist/mathlive.min.mjs",
1515
"main": "./dist/mathlive.min.js",
1616
"exports": {
17+
"./vue": "./dist/vue-mathlive.mjs",
18+
"./fonts.css": "./dist/mathlive-fonts.css",
19+
"./static.css": "./dist/mathlive-static.css",
20+
"./fonts/*": "./dist/fonts/*",
21+
"./sounds/*": "./dist/sounds/*",
22+
"./fonts/": "./dist/fonts/",
23+
"./sounds/": "./dist/sounds/",
1724
".": {
1825
"browser": {
1926
"production": {
@@ -40,14 +47,7 @@
4047
"./ssr": {
4148
"types": "./dist/types/mathlive-ssr.d.ts",
4249
"import": "./dist/mathlive-ssr.min.mjs"
43-
},
44-
"./vue": "./dist/vue-mathlive.mjs",
45-
"./fonts.css": "./dist/mathlive-fonts.css",
46-
"./static.css": "./dist/mathlive-static.css",
47-
"./fonts/*": "./dist/fonts/*",
48-
"./sounds/*": "./dist/sounds/*",
49-
"./fonts/": "./dist/fonts/",
50-
"./sounds/": "./dist/sounds/"
50+
}
5151
},
5252
"repository": {
5353
"type": "git",

src/editor-mathfield/mathfield-private.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1308,9 +1308,8 @@ If you are using Vue, this may be because you are using the runtime-only build o
13081308
}
13091309

13101310
focus(options?: FocusOptions): void {
1311+
if (this.focusBlurInProgress) return;
13111312
if (!this.hasFocus()) {
1312-
this.keyboardDelegate.focus();
1313-
this.connectToVirtualKeyboard();
13141313
this.onFocus();
13151314
this.model.announce('line');
13161315
}
@@ -1650,14 +1649,8 @@ If you are using Vue, this may be because you are using the runtime-only build o
16501649
this.focusBlurInProgress = true;
16511650
this.blurred = false;
16521651

1653-
// As a side effect, a `focus` and `focusin` events will be dispatched
1654-
// @fixme: this call might not be necessary. There is a keyboardDelegate.focus() call in the focus() handler.
1655-
this.keyboardDelegate.focus();
1656-
16571652
this.stopCoalescingUndo();
16581653

1659-
render(this, { interactive: true });
1660-
16611654
// Save the current value.
16621655
// It will be compared in `onBlur()` to see if the
16631656
// `change` event needs to be dispatched. This
@@ -1672,7 +1665,14 @@ If you are using Vue, this may be because you are using the runtime-only build o
16721665
)
16731666
this.executeCommand('moveToNextPlaceholder');
16741667

1675-
this.focusBlurInProgress = false;
1668+
render(this, { interactive: true });
1669+
1670+
setTimeout(() => {
1671+
this.keyboardDelegate.blur();
1672+
this.keyboardDelegate.focus();
1673+
this.connectToVirtualKeyboard();
1674+
this.focusBlurInProgress = false;
1675+
}, 60);
16761676
}
16771677

16781678
onBlur(): void {

src/editor/keyboard.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,19 @@ export function delegateKeyboardEvents(
309309
},
310310

311311
blur: (): void => {
312-
if (typeof keyboardSink.blur === 'function') keyboardSink.blur();
312+
if (typeof keyboardSink.blur === 'function') {
313+
blurInProgress = true;
314+
keyboardSink.blur();
315+
blurInProgress = false;
316+
}
313317
},
314318

315319
focus: (): void => {
316-
if (!focusInProgress && typeof keyboardSink.focus === 'function')
320+
if (!focusInProgress && typeof keyboardSink.focus === 'function') {
321+
focusInProgress = true;
317322
keyboardSink.focus({ preventScroll: true });
323+
focusInProgress = false;
324+
}
318325
},
319326

320327
hasFocus: (): boolean => {

src/public/mathfield-element.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -1916,13 +1916,22 @@ import "https://unpkg.com/@cortex-js/compute-engine?module";
19161916
handleEvent(evt: Event): void {
19171917
// If the scrim for the variant panel or the menu is
19181918
// open, ignore events.
1919-
// Otherwise we may end up disconecting from the VK
1919+
// Otherwise we may end up disconnecting from the VK
19201920
if (Scrim.state !== 'closed') return;
19211921

19221922
// Also, if the menu is open
19231923
if (this._mathfield?.menu?.state !== 'closed') return;
19241924

1925-
if (evt.type === 'pointerdown') this.onPointerDown();
1925+
if (evt.type === 'pointerdown') {
1926+
this.onPointerDown();
1927+
// Some browsers (Firefox, Chrome) will get into a zombie focus state
1928+
// if the padding area is clicked on when the mathfield was already
1929+
// focused. We force the keyboard delegate to blur and refocus to
1930+
// prevent this.
1931+
const kbdDelegate = this._mathfield?.keyboardDelegate;
1932+
kbdDelegate?.blur();
1933+
kbdDelegate?.focus();
1934+
}
19261935
if (evt.type === 'focus') this._mathfield?.focus();
19271936

19281937
// Ignore blur events if the scrim is open (case where the variant panel
@@ -1958,6 +1967,15 @@ import "https://unpkg.com/@cortex-js/compute-engine?module";
19581967
host.addEventListener('focus', this, true);
19591968
host.addEventListener('blur', this, true);
19601969

1970+
shadowRoot.addEventListener('pointerdown', (evt) => {
1971+
console.log('blue', evt);
1972+
evt.preventDefault();
1973+
1974+
// console.log('current target', deepActiveElement());
1975+
1976+
// if (evt.target === this) this.focus();
1977+
});
1978+
19611979
// Create an observer instance to detect when the innerHTML or textContent
19621980
// of the element is modified
19631981
this._observer = new MutationObserver(() => {

test/smoke/index.html

+4-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ <h1>Smoke Test</h1>
4444
</header>
4545
<main>
4646

47-
<math-field id="mf">\sqrt{a+1}</math-field>
47+
<math-field id="mf" contenteditable="true" tabindex="0">\sqrt{a+1}</math-field>
4848

4949
<!-- <math-field id="mf">\begin{align}\sqrt{a} +
5050
1 & b + 234 \\ \sqrt{c} + 1234 & d + 12345\end{align}
@@ -127,6 +127,7 @@ <h2>MathML</h2>
127127
version,
128128
} from "https://esm.run/@cortex-js/compute-engine";
129129

130+
// MathfieldElement.fontsDirectory = "https://unpkg.com/mathlive/dist/fonts";
130131

131132

132133
const MAX_LINE_LENGTH = 74;
@@ -259,6 +260,8 @@ <h2>MathML</h2>
259260

260261

261262
mf.addEventListener('mount', () => {
263+
// MathfieldElement.fontsDirectory = "https://cdn.jsdelivr.net/npm/mathlive/dist/fonts";
264+
262265
mf.macros = {
263266
...mf.macros,
264267
atomic: { args: 1, def: '\\class{my-class}{#1}', captureSelection: true },
@@ -269,7 +272,6 @@ <h2>MathML</h2>
269272
// First time update
270273
updateContent(mf);
271274
mf.addEventListener("input", (ev) => {
272-
console.log(ev);
273275
updateContent(mf)
274276
});
275277

0 commit comments

Comments
 (0)