pointerHandler.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import * as dom from '../../../base/browser/dom.js';
  6. import * as platform from '../../../base/common/platform.js';
  7. import { EventType, Gesture } from '../../../base/browser/touch.js';
  8. import { Disposable } from '../../../base/common/lifecycle.js';
  9. import { MouseHandler, createMouseMoveEventMerger } from './mouseHandler.js';
  10. import { EditorMouseEvent, EditorPointerEventFactory } from '../editorDom.js';
  11. import { BrowserFeatures } from '../../../base/browser/canIUse.js';
  12. import { TextAreaSyntethicEvents } from './textAreaInput.js';
  13. /**
  14. * Currently only tested on iOS 13/ iPadOS.
  15. */
  16. export class PointerEventHandler extends MouseHandler {
  17. constructor(context, viewController, viewHelper) {
  18. super(context, viewController, viewHelper);
  19. this._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));
  20. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));
  21. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));
  22. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Contextmenu, (e) => this._onContextMenu(new EditorMouseEvent(e, this.viewHelper.viewDomNode), false)));
  23. this._lastPointerType = 'mouse';
  24. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'pointerdown', (e) => {
  25. const pointerType = e.pointerType;
  26. if (pointerType === 'mouse') {
  27. this._lastPointerType = 'mouse';
  28. return;
  29. }
  30. else if (pointerType === 'touch') {
  31. this._lastPointerType = 'touch';
  32. }
  33. else {
  34. this._lastPointerType = 'pen';
  35. }
  36. }));
  37. // PonterEvents
  38. const pointerEvents = new EditorPointerEventFactory(this.viewHelper.viewDomNode);
  39. this._register(pointerEvents.onPointerMoveThrottled(this.viewHelper.viewDomNode, (e) => this._onMouseMove(e), createMouseMoveEventMerger(this.mouseTargetFactory), MouseHandler.MOUSE_MOVE_MINIMUM_TIME));
  40. this._register(pointerEvents.onPointerUp(this.viewHelper.viewDomNode, (e) => this._onMouseUp(e)));
  41. this._register(pointerEvents.onPointerLeave(this.viewHelper.viewDomNode, (e) => this._onMouseLeave(e)));
  42. this._register(pointerEvents.onPointerDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));
  43. }
  44. onTap(event) {
  45. if (!event.initialTarget || !this.viewHelper.linesContentDomNode.contains(event.initialTarget)) {
  46. return;
  47. }
  48. event.preventDefault();
  49. this.viewHelper.focusTextArea();
  50. const target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);
  51. if (target.position) {
  52. // this.viewController.moveTo(target.position);
  53. this.viewController.dispatchMouse({
  54. position: target.position,
  55. mouseColumn: target.position.column,
  56. startedOnLineNumbers: false,
  57. mouseDownCount: event.tapCount,
  58. inSelectionMode: false,
  59. altKey: false,
  60. ctrlKey: false,
  61. metaKey: false,
  62. shiftKey: false,
  63. leftButton: false,
  64. middleButton: false,
  65. });
  66. }
  67. }
  68. onChange(e) {
  69. if (this._lastPointerType === 'touch') {
  70. this._context.model.deltaScrollNow(-e.translationX, -e.translationY);
  71. }
  72. }
  73. _onMouseDown(e) {
  74. if (e.browserEvent.pointerType === 'touch') {
  75. return;
  76. }
  77. super._onMouseDown(e);
  78. }
  79. }
  80. class TouchHandler extends MouseHandler {
  81. constructor(context, viewController, viewHelper) {
  82. super(context, viewController, viewHelper);
  83. this._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));
  84. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));
  85. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));
  86. this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Contextmenu, (e) => this._onContextMenu(new EditorMouseEvent(e, this.viewHelper.viewDomNode), false)));
  87. }
  88. onTap(event) {
  89. event.preventDefault();
  90. this.viewHelper.focusTextArea();
  91. const target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);
  92. if (target.position) {
  93. // Send the tap event also to the <textarea> (for input purposes)
  94. const event = document.createEvent('CustomEvent');
  95. event.initEvent(TextAreaSyntethicEvents.Tap, false, true);
  96. this.viewHelper.dispatchTextAreaEvent(event);
  97. this.viewController.moveTo(target.position);
  98. }
  99. }
  100. onChange(e) {
  101. this._context.model.deltaScrollNow(-e.translationX, -e.translationY);
  102. }
  103. }
  104. export class PointerHandler extends Disposable {
  105. constructor(context, viewController, viewHelper) {
  106. super();
  107. if ((platform.isIOS && BrowserFeatures.pointerEvents)) {
  108. this.handler = this._register(new PointerEventHandler(context, viewController, viewHelper));
  109. }
  110. else if (window.TouchEvent) {
  111. this.handler = this._register(new TouchHandler(context, viewController, viewHelper));
  112. }
  113. else {
  114. this.handler = this._register(new MouseHandler(context, viewController, viewHelper));
  115. }
  116. }
  117. getTargetAtClientPoint(clientX, clientY) {
  118. return this.handler.getTargetAtClientPoint(clientX, clientY);
  119. }
  120. }