-
Notifications
You must be signed in to change notification settings - Fork 29.3k
Pointer Device & Touch support
- Which event to listen to
- Pointer/Mouse Event
- PointerDown/MouseDown
- Pointer/MouseMove monitor
- Differentiate Touch/Pen/Mouse
- Touch/Gesture
- Gesture Helper
- Troubleshoot: touch not working with native elements
- Base elements
- input/checkbox
- scrollable element
- list view
Choosing the right event to listen to is a hard decision to make, as there isn't a single unified browser standard to follow. If you are using basic elements from vs/base/browser
, you may want to only listen to predefined event listeners on them. However if you are building a plain new view component, here is a quick cheatsheet
- Do you customize overflow/scrolling, or double clicking?
- No
- Listen to both
scroll
for scrolling - Listen to both
click
for clicking.
- Listen to both
- Yes
- Add the element to
Gesture
- Listen to both
wheel
andGestureEvent.change
for scrolling - Listen to both
click
andGestureEvent.Tap
for clicking. (GestureEvent.tapCount == 2
for double clicking) - Listen to
GestureEvent.contextmenu
for content menu (right click)
- Add the element to
- No
For more details, please read blow:
Pointer events are DOM events fired by pointer devices, which include Mouse, Touch and Pen. Pointer events inherit from Mouse events, so we only need to adopt following generic mouse/pointer listeners without modifying out mouse handler code.
import * as dom from ‘vs/base/browser/dom’
// dom.addDisposableListener(domNode, ‘mouseDown’, () => {})
dom.addDisposableGenericMouseDownListener(domNode, () => {})
// dom.addDisposableListener(domNode, ‘mouseUp’, () => {})
dom.addDisposableGenericMouseUpListener(domNode, () => {})
import * as dom from ‘vs/base/browser/GlobalMouseMoveMonitor’
// no change at all
this._mouseMoveMonitor = this._register(new GlobalMouseMoveMonitor<IStandardMouseMoveEventData>());
this._mouseMoveMonitor.startMonitoring(
…
)
Under the hood we will do browser feature and platform detection to decide which is the right event to listen to. It’s not suggested to bind your own listeners to PointerEvent
as PointerEvent
can coexist with MosueEvent
, browser/platform detection code is still needed to avoid the mouse event handlers not being called twice.
The generic mouse/pointer event will carry device information if it’s from a pointer device, which can be accessed by reading event.pointerType
dom.addDisposableGenericMouseDownListner(domNode, (e) => {
const pointerType = <any>e.pointerType;
switch (key) {
case ‘touch’:
break;
case ‘mouse’:
break;
case ‘pen’:
break;
default:
break;
}
})
Gesture helper vs/base/browser/touch#Gesture
will translate native touch events (touchStart
, touchEnd
, touchMove
) to richer Gesture events based on how long users touch and how much users move their finger on the screen.
Please always use Gesture for consistence, unless you want to roll in your own touch implementation.
To register gesture event listener on a DOM node, register the DOM node to Gesture store first and listen to Gesture events the same as normal DOM events.
import * as dom from ‘vs/base/browser/dom’;
import { Gesture, EventType as GestureEventType } from ‘vs/base/browser/touch’;
Gesture.addTarget(domNode);
dom.addDisposableEventListner(domNode, GestureEventType.Tap, (e) => {});
Most of the time, if touch doesn’t work with native elements in your view, please check if one of your view’s ancestors is being tracked by Gesture
. Gesture
will prevent default behavior of touch events when a DOM node is being tracked by it, which means the DOM nodes’ all descendants will no longer receive any native touch events.
When above scenario happens (and you can’t change the behavior of the ancestor), do one of following
-
Gesture.ignoreTarget
to let Gesture ignore touch events happening on the element -
Gesture.addTarget
to the element if you want to customize its touch behavior
vs/base/browser/ui/inputBox
and vs/base/browser/ui/checkbox
, by default inputBox
and checkbox
add themselves to Gesture’s ignore list
Scrollable Element scrolls when wheel
/mousewheel
events are triggered, but by default it’s not tracked by Gesture
to ensure it doesn’t break the native touch experience on its inner elements.
To make scrollable element touch friendly, when using it, please make sure you listen to at least Tap
and Change
Gesture events.
Gesture.addTarget(domNode)
dom.addDisposableEventListner(domNode, GestureEventType.Tap, (e) => {}); // Click
dom.addDisposableEventListner(domNode, GestureEventType.Change, (e) => {}); // Scroll
List View internally listens to both scroll events and GestureEventType.Change
events (as it’s virtualized ;)). While using List View, you don’t need to worry about scrolling at all but the catch is native touch down won’t work on inner elements as the events are trapped by Gesture
.
Solution:
-
Gesture.ignoreTarget
to let Gesture ignore touch events happening on the element -
Gesture.addTarget
to the element if you want to customize its touch behavior
Project Management
- Roadmap
- Iteration Plans
- Development Process
- Issue Tracking
- Build Champion
- Release Process
- Running the Endgame
- Related Projects
Contributing
- How to Contribute
- Submitting Bugs and Suggestions
- Feedback Channels
- Source Code Organization
- Coding Guidelines
- Testing
- Dealing with Test Flakiness
- Contributor License Agreement
- Extension API Guidelines
- Accessibility Guidelines
Documentation