On a touch screen, long-press (~1s) a button and lift the finger. The
:active pseudo-class styles are retained after
pointerup / touchend instead of being released.
Another tap or a mouse move is needed to clear them. With a mouse the state
is correctly cleared on mouseup. Firefox clears the state on
release for touch as well.
Root cause: a long-press ends with a GestureLongTap (not a
GestureTap), and Blink treated its hit test as read-only, so the
active state set by GestureShowPress was never released. On
platforms that show the context menu on release (Windows), the context-menu
hit test additionally re-applied the active state.
1. Long-press (~1 second) button 1 below, then lift your finger.
2. Watch the button: the red :active styling must disappear
when the finger lifts.
3. Repeat with button 2 (the reporter's virtual-keyboard scenario).
Both buttons call preventDefault() on
contextmenu so the native menu does not cover the page. The
check below samples button.matches(':active') shortly after
the touch ends.
waiting for input...
:active is released when the finger lifts
(pointerup/touchend), regardless of how long the
press was -- matching mouse behavior and Firefox.
:active stays applied after the long-press release; only a
further tap or mouse move clears it.
Blink: treat GestureLongTap as a release in
GestureManager::GetHitTypeForGestureType(), and make the
context-menu hit tests read-only so the deferred
show-menu-on-mouse-up path does not re-apply the state
(third_party/blink/renderer/core/input/gesture_manager.cc,
event_handler.cc).