fix: Ensure widget divs restore focus correctly.

This avoids reintroducing #9203.
This commit is contained in:
Ben Henning
2025-07-07 22:15:53 +00:00
parent 3aa3238454
commit 0363d67c18
2 changed files with 33 additions and 6 deletions

View File

@@ -146,6 +146,18 @@ export function hide() {
const div = containerDiv;
if (!div) return;
(common.getMainWorkspace() as WorkspaceSvg).markFocused();
if (returnEphemeralFocus) {
returnEphemeralFocus();
returnEphemeralFocus = null;
}
// Content must be cleared after returning ephemeral focus since otherwise it
// may force focus changes which could desynchronize the focus manager and
// make it think the user directed focus away from the widget div (which will
// then notify it to not restore focus back to any previously focused node).
div.style.display = 'none';
div.style.left = '';
div.style.top = '';
@@ -163,12 +175,6 @@ export function hide() {
dom.removeClass(div, themeClassName);
themeClassName = '';
}
(common.getMainWorkspace() as WorkspaceSvg).markFocused();
if (returnEphemeralFocus) {
returnEphemeralFocus();
returnEphemeralFocus = null;
}
}
/**

View File

@@ -423,5 +423,26 @@ suite('WidgetDiv', function () {
assert.strictEqual(Blockly.getFocusManager().getFocusedNode(), block);
assert.strictEqual(document.activeElement, blockFocusableElem);
});
test('for showing nested div with ephemeral focus restores DOM focus', function () {
const block = this.setUpBlockWithField();
const field = Array.from(block.getFields())[0];
Blockly.getFocusManager().focusNode(block);
const nestedDiv = document.createElement('div');
nestedDiv.tabIndex = -1;
Blockly.WidgetDiv.getDiv().appendChild(nestedDiv);
Blockly.WidgetDiv.show(field, false, () => {}, null, true);
nestedDiv.focus(); // It's valid to focus this during ephemeral focus.
// Hiding will cause the now focused child div to be removed, leading to
// ephemeral focus being lost if the implementation doesn't handle
// returning ephemeral focus correctly.
Blockly.WidgetDiv.hide();
// Hiding the div should restore focus back to the block.
const blockFocusableElem = block.getFocusableElement();
assert.strictEqual(Blockly.getFocusManager().getFocusedNode(), block);
assert.strictEqual(document.activeElement, blockFocusableElem);
});
});
});