1// Copyright 2013 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5part of engine; 6 7/// Listens to HTML "click" gestures detected by the browser. 8/// 9/// This gestures is different from the click and tap gestures detected by the 10/// framework from raw pointer events. When an assistive technology is enabled 11/// the browser may not send us pointer events. In that mode we forward HTML 12/// click as [ui.SemanticsAction.tap]. 13class Tappable extends RoleManager { 14 Tappable(SemanticsObject semanticsObject) 15 : super(Role.tappable, semanticsObject); 16 17 html.EventListener _clickListener; 18 19 @override 20 void update() { 21 final html.Element element = semanticsObject.element; 22 23 semanticsObject.setAriaRole( 24 'button', semanticsObject.hasFlag(ui.SemanticsFlag.isButton)); 25 26 if (!semanticsObject.hasFlag(ui.SemanticsFlag.isEnabled) && 27 semanticsObject.hasFlag(ui.SemanticsFlag.isButton)) { 28 semanticsObject.element.setAttribute('aria-disabled', 'true'); 29 _stopListening(); 30 } else { 31 // Excluding text fields because text fields have browser-specific logic 32 // for recognizing taps and activating the keyboard. 33 if (semanticsObject.hasAction(ui.SemanticsAction.tap) && 34 !semanticsObject.hasFlag(ui.SemanticsFlag.isTextField)) { 35 if (_clickListener == null) { 36 _clickListener = (_) { 37 if (semanticsObject.owner.gestureMode != 38 GestureMode.browserGestures) { 39 return; 40 } 41 ui.window.onSemanticsAction( 42 semanticsObject.id, ui.SemanticsAction.tap, null); 43 }; 44 element.addEventListener('click', _clickListener); 45 } 46 } else { 47 _stopListening(); 48 } 49 } 50 } 51 52 void _stopListening() { 53 if (_clickListener == null) { 54 return; 55 } 56 57 semanticsObject.element.removeEventListener('click', _clickListener); 58 _clickListener = null; 59 } 60 61 @override 62 void dispose() { 63 _stopListening(); 64 semanticsObject.setAriaRole('button', false); 65 } 66} 67