Summary: | :focus-within pseudo class doesn't get invalidated when frame loses focus | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | Ryosuke Niwa <rniwa> | ||||||||
Component: | CSS | Assignee: | Ryosuke Niwa <rniwa> | ||||||||
Status: | RESOLVED FIXED | ||||||||||
Severity: | Normal | CC: | allan.jensen, darin, esprehn+autocc, ews-watchlist, glenn, gyuyoung.kim, koivisto, macpherson, menard, mifenton, rniwa, simon.fraser, webkit-bug-importer | ||||||||
Priority: | P2 | Keywords: | InRadar | ||||||||
Version: | WebKit Nightly Build | ||||||||||
Hardware: | Unspecified | ||||||||||
OS: | Unspecified | ||||||||||
Attachments: |
|
Created attachment 460765 [details]
WIP
This patch doesn't quite work.
Replacing
Style::PseudoClassChangeInvalidation focusStyleInvalidation(lineage, { { CSSSelector::PseudoClassFocusWithin, activeAndFocused } });
with
lineage.invalidateStyle();
makes it work.
So :focus, :focus-within, :focus-visible all depend on FrameSelection::isFocusedAndActive() via isFrameFocused in SelectorCheckerTestFunctions.h FrameSelection::isFocusedAndActive() in turn is defined in terms of two boolean states: FrameSelection::m_focused and FocusController::isActive(). FocusController calls FrameSelection::pageActivationChanged() whenever isActive state changes on the focused frame's FrameSelection. In the ideal world, we have a single place where these two boolean states are updated at once, and that's where we instantiate relevant Style::PseudoClassChangeInvalidation but that's tricky because FocusController is a per-Page concept and FrameSelection is per-Frame concept. To reconcile, I could imagine a few solutions: 1. Add a new boolean m_isPageActive to FrameSelection which gets sync'ed when FrameSelection becomes newly focused (inside FrameSelection::setFocused). We then update both m_focused & this new boolean whilst we have Style::PseudoClassChangeInvalidation. 2. In FrameSelection::focusedOrActiveStateChanged(), introduce a temporary override for FrameSelection::isFocusedAndActive(), which makes the function return the negative value while Style::PseudoClassChangeInvalidation are instantiated. 3. Simply use Element::invalidateStyle() on these elements for now. This will only occur when WKWebView becomes first responder or resigns first responder (i.e. view gets focused or unfocused in more Web / Windows terminology). Created attachment 460776 [details]
WIP2
Pull request: https://github.com/WebKit/WebKit/pull/2259 Committed 252324@main (ac8282feee7f): <https://commits.webkit.org/252324@main> Reviewed commits have been landed. Closing PR #2259 and removing active labels. |
Created attachment 460764 [details] test case Reproduction steps: 1. Open the attached document in Safari / Mini browser 2. Focus the address bar / other parts of app Expected result: There will be 100px by 100px green box Actual result: Green box remains 50px by 50px