Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: tools/dom/src/KeyboardEventStream.dart

Issue 12907019: KeyboardEventStream: lock it down (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: generate the tab-free version, too Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/html/dartium/html_dartium.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of html; 5 part of html;
6 6
7 /** 7 /**
8 * Internal class that does the actual calculations to determine keyCode and 8 * Internal class that does the actual calculations to determine keyCode and
9 * charCode for keydown, keypress, and keyup events for all browsers. 9 * charCode for keydown, keypress, and keyup events for all browsers.
10 */ 10 */
11 class _KeyboardEventHandler implements EventStreamProvider<KeyEvent> { 11 class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
12 // This code inspired by Closure's KeyHandling library. 12 // This code inspired by Closure's KeyHandling library.
13 // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keyhandl er.js.source.html 13 // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keyhandl er.js.source.html
14 14
15 /** 15 /**
16 * The set of keys that have been pressed down without seeing their 16 * The set of keys that have been pressed down without seeing their
17 * corresponding keyup event. 17 * corresponding keyup event.
18 */ 18 */
19 List<KeyboardEvent> _keyDownList; 19 final List<KeyboardEvent> _keyDownList = <KeyboardEvent>[];
20
21 /** The set of functions that wish to be notified when a KeyEvent happens. */
22 List<Function> _callbacks;
23 20
24 /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */ 21 /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
25 String _type; 22 final String _type;
26 23
27 /** The element we are watching for events to happen on. */ 24 /** The element we are watching for events to happen on. */
28 EventTarget _target; 25 final EventTarget _target;
29 26
30 // The distance to shift from upper case alphabet Roman letters to lower case. 27 // The distance to shift from upper case alphabet Roman letters to lower case.
31 final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0]; 28 static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
32 29
33 /** Controller to produce KeyEvents for the stream. */ 30 /** Controller to produce KeyEvents for the stream. */
34 StreamController _controller; 31 final StreamController _controller = new StreamController.broadcast();
35 32
36 String _eventType = 'KeyEvent'; 33 static const _EVENT_TYPE = 'KeyEvent';
37 34
38 /** 35 /**
39 * An enumeration of key identifiers currently part of the W3C draft for DOM3 36 * An enumeration of key identifiers currently part of the W3C draft for DOM3
40 * and their mappings to keyCodes. 37 * and their mappings to keyCodes.
41 * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set 38 * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set
42 */ 39 */
43 static Map<String, int> _keyIdentifier = { 40 static const Map<String, int> _keyIdentifier = const {
44 'Up': KeyCode.UP, 41 'Up': KeyCode.UP,
45 'Down': KeyCode.DOWN, 42 'Down': KeyCode.DOWN,
46 'Left': KeyCode.LEFT, 43 'Left': KeyCode.LEFT,
47 'Right': KeyCode.RIGHT, 44 'Right': KeyCode.RIGHT,
48 'Enter': KeyCode.ENTER, 45 'Enter': KeyCode.ENTER,
49 'F1': KeyCode.F1, 46 'F1': KeyCode.F1,
50 'F2': KeyCode.F2, 47 'F2': KeyCode.F2,
51 'F3': KeyCode.F3, 48 'F3': KeyCode.F3,
52 'F4': KeyCode.F4, 49 'F4': KeyCode.F4,
53 'F5': KeyCode.F5, 50 'F5': KeyCode.F5,
54 'F6': KeyCode.F6, 51 'F6': KeyCode.F6,
55 'F7': KeyCode.F7, 52 'F7': KeyCode.F7,
56 'F8': KeyCode.F8, 53 'F8': KeyCode.F8,
57 'F9': KeyCode.F9, 54 'F9': KeyCode.F9,
58 'F10': KeyCode.F10, 55 'F10': KeyCode.F10,
59 'F11': KeyCode.F11, 56 'F11': KeyCode.F11,
60 'F12': KeyCode.F12, 57 'F12': KeyCode.F12,
61 'U+007F': KeyCode.DELETE, 58 'U+007F': KeyCode.DELETE,
62 'Home': KeyCode.HOME, 59 'Home': KeyCode.HOME,
63 'End': KeyCode.END, 60 'End': KeyCode.END,
64 'PageUp': KeyCode.PAGE_UP, 61 'PageUp': KeyCode.PAGE_UP,
65 'PageDown': KeyCode.PAGE_DOWN, 62 'PageDown': KeyCode.PAGE_DOWN,
66 'Insert': KeyCode.INSERT 63 'Insert': KeyCode.INSERT
67 }; 64 };
68 65
69 /**
70 * Gets the type of the event which this would listen for on the specified
71 * event target.
72 */
73 String getEventType(EventTarget target) => _eventType;
74
75 /** Return a stream for KeyEvents for the specified target. */ 66 /** Return a stream for KeyEvents for the specified target. */
76 Stream<KeyEvent> forTarget(EventTarget e, {bool useCapture: false}) { 67 Stream<KeyEvent> forTarget(EventTarget e, {bool useCapture: false}) {
77 return new _KeyboardEventHandler.initializeAllEventListeners( 68 return new _KeyboardEventHandler.initializeAllEventListeners(
78 _type, e).stream; 69 _type, e).stream;
79 } 70 }
80 71
81 /** 72 /**
82 * Accessor to the stream associated with a particular KeyboardEvent 73 * Accessor to the stream associated with a particular KeyboardEvent
83 * EventTarget. 74 * EventTarget.
84 * 75 *
85 * [forTarget] must be called to initialize this stream to listen to a 76 * [forTarget] must be called to initialize this stream to listen to a
86 * particular EventTarget. 77 * particular EventTarget.
87 */ 78 */
88 Stream<KeyEvent> get stream { 79 Stream<KeyEvent> get stream {
89 if(_target != null) { 80 if(_target != null) {
90 return _controller.stream; 81 return _controller.stream;
91 } else { 82 } else {
92 throw new StateError("Not initialized. Call forTarget to access a stream " 83 throw new StateError("Not initialized. Call forTarget to access a stream "
93 "initialized with a particular EventTarget."); 84 "initialized with a particular EventTarget.");
94 } 85 }
95 } 86 }
96 87
97 /** 88 /**
98 * General constructor, performs basic initialization for our improved 89 * General constructor, performs basic initialization for our improved
99 * KeyboardEvent controller. 90 * KeyboardEvent controller.
100 */ 91 */
101 _KeyboardEventHandler(String type) { 92 _KeyboardEventHandler(this._type) :
102 _commonInit(type); 93 _target = null, super(_EVENT_TYPE) {
103 }
104
105 void _commonInit(String type) {
106 _type = type;
107 _controller = new StreamController.broadcast();
108 _callbacks = [];
109 _target = null;
110 } 94 }
111 95
112 /** 96 /**
113 * Hook up all event listeners under the covers so we can estimate keycodes 97 * Hook up all event listeners under the covers so we can estimate keycodes
114 * and charcodes when they are not provided. 98 * and charcodes when they are not provided.
115 */ 99 */
116 _KeyboardEventHandler.initializeAllEventListeners(String type, 100 _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) :
117 EventTarget target) { 101 super(_EVENT_TYPE) {
118 _commonInit(type);
119 _target = target;
120 _keyDownList = [];
121 Element.keyDownEvent.forTarget(_target, useCapture: true).listen( 102 Element.keyDownEvent.forTarget(_target, useCapture: true).listen(
122 processKeyDown); 103 processKeyDown);
123 Element.keyPressEvent.forTarget(_target, useCapture: true).listen( 104 Element.keyPressEvent.forTarget(_target, useCapture: true).listen(
124 processKeyPress); 105 processKeyPress);
125 Element.keyUpEvent.forTarget(_target, useCapture: true).listen( 106 Element.keyUpEvent.forTarget(_target, useCapture: true).listen(
126 processKeyUp); 107 processKeyUp);
127 } 108 }
128 109
129 /** 110 /**
130 * Notify all callback listeners that a KeyEvent of the relevant type has 111 * Notify all callback listeners that a KeyEvent of the relevant type has
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 /** Handle keydown events. */ 294 /** Handle keydown events. */
314 void processKeyDown(KeyboardEvent e) { 295 void processKeyDown(KeyboardEvent e) {
315 // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window 296 // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
316 // before we've caught a key-up event. If the last-key was one of these 297 // before we've caught a key-up event. If the last-key was one of these
317 // we reset the state. 298 // we reset the state.
318 if (_keyDownList.length > 0 && 299 if (_keyDownList.length > 0 &&
319 (_keyDownList.last.keyCode == KeyCode.CTRL && !e.ctrlKey || 300 (_keyDownList.last.keyCode == KeyCode.CTRL && !e.ctrlKey ||
320 _keyDownList.last.keyCode == KeyCode.ALT && !e.altKey || 301 _keyDownList.last.keyCode == KeyCode.ALT && !e.altKey ||
321 Device.userAgent.contains('Mac') && 302 Device.userAgent.contains('Mac') &&
322 _keyDownList.last.keyCode == KeyCode.META && !e.metaKey)) { 303 _keyDownList.last.keyCode == KeyCode.META && !e.metaKey)) {
323 _keyDownList = []; 304 _keyDownList.clear();
324 } 305 }
325 306
326 var event = new KeyEvent(e); 307 var event = new KeyEvent(e);
327 event._shadowKeyCode = _normalizeKeyCodes(event); 308 event._shadowKeyCode = _normalizeKeyCodes(event);
328 // Technically a "keydown" event doesn't have a charCode. This is 309 // Technically a "keydown" event doesn't have a charCode. This is
329 // calculated nonetheless to provide us with more information in giving 310 // calculated nonetheless to provide us with more information in giving
330 // as much information as possible on keypress about keycode and also 311 // as much information as possible on keypress about keycode and also
331 // charCode. 312 // charCode.
332 event._shadowCharCode = _findCharCodeKeyDown(event); 313 event._shadowCharCode = _findCharCodeKeyDown(event);
333 if (_keyDownList.length > 0 && event.keyCode != _keyDownList.last.keyCode && 314 if (_keyDownList.length > 0 && event.keyCode != _keyDownList.last.keyCode &&
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 /** Handle keyup events. */ 354 /** Handle keyup events. */
374 void processKeyUp(KeyboardEvent event) { 355 void processKeyUp(KeyboardEvent event) {
375 var e = new KeyEvent(event); 356 var e = new KeyEvent(event);
376 KeyboardEvent toRemove = null; 357 KeyboardEvent toRemove = null;
377 for (var key in _keyDownList) { 358 for (var key in _keyDownList) {
378 if (key.keyCode == e.keyCode) { 359 if (key.keyCode == e.keyCode) {
379 toRemove = key; 360 toRemove = key;
380 } 361 }
381 } 362 }
382 if (toRemove != null) { 363 if (toRemove != null) {
383 _keyDownList = 364 _keyDownList.removeWhere((element) => element == toRemove);
384 _keyDownList.where((element) => element != toRemove).toList();
385 } else if (_keyDownList.length > 0) { 365 } else if (_keyDownList.length > 0) {
386 // This happens when we've reached some international keyboard case we 366 // This happens when we've reached some international keyboard case we
387 // haven't accounted for or we haven't correctly eliminated all browser 367 // haven't accounted for or we haven't correctly eliminated all browser
388 // inconsistencies. Filing bugs on when this is reached is welcome! 368 // inconsistencies. Filing bugs on when this is reached is welcome!
389 _keyDownList.removeLast(); 369 _keyDownList.removeLast();
390 } 370 }
391 _dispatch(e); 371 _dispatch(e);
392 } 372 }
393 } 373 }
394 374
(...skipping 20 matching lines...) Expand all
415 new _KeyboardEventHandler('keypress').forTarget(target); 395 new _KeyboardEventHandler('keypress').forTarget(target);
416 396
417 /** Named constructor to produce a stream for onKeyUp events. */ 397 /** Named constructor to produce a stream for onKeyUp events. */
418 static Stream<KeyEvent> onKeyUp(EventTarget target) => 398 static Stream<KeyEvent> onKeyUp(EventTarget target) =>
419 new _KeyboardEventHandler('keyup').forTarget(target); 399 new _KeyboardEventHandler('keyup').forTarget(target);
420 400
421 /** Named constructor to produce a stream for onKeyDown events. */ 401 /** Named constructor to produce a stream for onKeyDown events. */
422 static Stream<KeyEvent> onKeyDown(EventTarget target) => 402 static Stream<KeyEvent> onKeyDown(EventTarget target) =>
423 new _KeyboardEventHandler('keydown').forTarget(target); 403 new _KeyboardEventHandler('keydown').forTarget(target);
424 } 404 }
OLDNEW
« no previous file with comments | « sdk/lib/html/dartium/html_dartium.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698