Skip to content

Commit

Permalink
fix(input): Fix touch/mouse input detection
Browse files Browse the repository at this point in the history
update media feature detection for mouse and touch detection

Ref #3854
  • Loading branch information
netil committed Oct 11, 2024
1 parent 23b41bf commit 2f7fa95
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/module/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,9 @@ function isTabVisible(): boolean {
*/
function convertInputType(mouse: boolean, touch: boolean): "mouse" | "touch" | null {
const {DocumentTouch, matchMedia, navigator} = window;

// https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer#coarse
const hasPointerCoarse = matchMedia?.("(pointer:coarse)").matches;
let hasTouch = false;

if (touch) {
Expand All @@ -873,7 +876,7 @@ function convertInputType(mouse: boolean, touch: boolean): "mouse" | "touch" | n
hasTouch = true;
} else {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#avoiding_user_agent_detection
if (matchMedia?.("(pointer:coarse)").matches) {
if (hasPointerCoarse) {
hasTouch = true;
} else {
// Only as a last resort, fall back to user agent sniffing
Expand All @@ -885,11 +888,9 @@ function convertInputType(mouse: boolean, touch: boolean): "mouse" | "touch" | n
}
}

// Check if agent has mouse using any-hover, touch devices (e.g iPad) with external mouse will return true as long as mouse is connected
// https://css-tricks.com/interaction-media-features-and-their-potential-for-incorrect-assumptions/#aa-testing-the-capabilities-of-all-inputs
// Demo: https://patrickhlauke.github.io/touch/pointer-hover-any-pointer-any-hover/
const hasMouse = mouse &&
(matchMedia?.("any-hover:hover").matches || matchMedia?.("any-pointer:fine").matches);
// For non-touch device, media feature condition is: '(pointer:coarse) = false' and '(pointer:fine) = true'
// https://github.com/naver/billboard.js/issues/3854#issuecomment-2404183158
const hasMouse = mouse && !hasPointerCoarse && matchMedia?.("(pointer:fine)").matches;

// fallback to 'mouse' if no input type is detected.
return (hasMouse && "mouse") || (hasTouch && "touch") || "mouse";
Expand Down

0 comments on commit 2f7fa95

Please sign in to comment.