Fix topmost input element check with labels (#2667)

Fix topmost input element check with labels
This commit is contained in:
Sami Vänttinen 2025-09-02 15:14:48 +03:00 committed by GitHub
parent 7f062de937
commit 345b5e0bc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 7 deletions

View file

@ -124,6 +124,7 @@
"IMPROVED_DETECTION_PREDEFINED_SITELIST": "readonly",
"initColorTheme": "readonly",
"isEdge": "readonly",
"isElementInside": "readonly",
"isFirefox": "readonly",
"keepass": "readonly",
"keepassClient": "readonly",

View file

@ -182,11 +182,13 @@ const getCurrentTab = async function() {
return tabs?.length > 0 ? tabs[0] : undefined;
};
// Check if element b is inside a
const isElementInside = (a, b) => (b.x >= a.x || b.right <= a.right) && (b.y >= a.y || b.bottom <= a.bottom);
// Check if two elements overlap
const elementsOverlap = function(rect1, rect2) {
const isInside = (a, b) => (b.x >= a.x || b.right <= a.right) && (b.y >= a.y || b.bottom <= a.bottom);
const overlaps = (a, b) => !(a.right < b.left || a.left > b.right || a.bottom < b.top || a.top > b.bottom);
return isInside(rect1, rect2) || overlaps(rect1, rect2);
return isElementInside(rect1, rect2) || overlaps(rect1, rect2);
};
// Exports for tests

View file

@ -416,13 +416,24 @@ kpxcFields.isTopElement = function(elem, rect) {
return false;
}
// Check topmost element from three points inside the input
const verticalMiddle = rect.top + (rect.height / 2);
const rootNode = elem.getRootNode() ?? document;
// Returns the topmost element from point x, height/2
// If the input has a label as the top element and it's inside the input, allow it.
const getTopmostElement = (element, x, elementRect) => {
const topElement = rootNode.elementFromPoint(x, elementRect.top + (elementRect.height / 2));
return element?.labels &&
element.labels[0] === topElement &&
isElementInside(elementRect, topElement.getBoundingClientRect())
? element
: topElement;
};
// Check topmost element from three points inside the input
if (matchesWithNodeName(elem, 'INPUT') && [
rootNode.elementFromPoint(rect.left + (rect.width / 4), verticalMiddle), // First third
rootNode.elementFromPoint(rect.left + (rect.width / 2), verticalMiddle), // Middle
rootNode.elementFromPoint(rect.left + (rect.width / 1.33), verticalMiddle), // Last third
getTopmostElement(elem, rect.left + (rect.width / 4), rect), // First third
getTopmostElement(elem, rect.left + (rect.width / 2), rect), // Middle
getTopmostElement(elem, rect.left + (rect.width / 1.33), rect), // Last third
].some((e) => e !== elem)) {
return false;
}