OLD | NEW |
---|---|
(Empty) | |
1 <!-- | |
2 // Copyright 2015 The Chromium Authors. All rights reserved. | |
3 // Use of this source code is governed by a BSD-style license that can be | |
4 // found in the LICENSE file. | |
5 --> | |
6 <import src="/sky/framework/sky-element.sky" /> | |
7 <import src="/sky/framework/sky-scrollable.sky" /> | |
8 <sky-element> | |
9 <template> | |
10 <style> | |
11 #control { | |
12 height: -webkit-fill-available; | |
13 background-color: black; | |
14 color: rgb(255, 191, 0); | |
15 font-family: 'Courier', 'monospace'; | |
16 } | |
17 span { | |
18 white-space: nowrap; | |
19 } | |
20 </style> | |
21 <sky-scrollable id="control" contenteditable /> | |
22 </template> | |
23 <script> | |
24 import 'dart:async'; | |
25 import 'dart:core'; | |
26 import 'dart:sky'; | |
27 import 'package:examples/echo_terminal/terminal_client.mojom.dart' as terminal; | |
28 import '/sky/framework/embedder.dart'; | |
29 import 'terminal_display.dart'; | |
30 import 'terminal_file_impl.dart'; | |
31 | |
32 // Implements the <terminal> element, which implements a "terminal display". Has | |
33 // an |url| attribute, whose value should be a Mojo app that provides the | |
34 // |terminal.TerminalClient| service. | |
35 @Tagname('terminal') | |
36 class TerminalDisplayImpl extends SkyElement implements TerminalDisplay { | |
37 Element _control; | |
38 | |
39 // Queue of unconsumed input (keystrokes), with the head at index 0. | |
40 // Keystrokes end up here if there's no reader (i.e., |getChar()|) pending, | |
41 // i.e., if |_readerQueue| is empty. Invariant: At most one of |_inputQueue| | |
42 // and |_readerQueue| may be nonempty at any given time. | |
43 List<int> _inputQueue; | |
44 | |
45 // Queue of things waiting for input, with the head at index 0. If a keystroke | |
46 // is received and this is nonempty, the head is given that keystroke (and | |
47 // dequeued). | |
48 List<Completer<int>> _readerQueue; | |
49 | |
50 TerminalDisplayImpl() | |
51 : _inputQueue = new List<int>(), | |
52 _readerQueue = new List<Completer<int>>() { | |
53 } | |
54 | |
55 void shadowRootReady() { | |
56 _control = shadowRoot.getElementById('control'); | |
57 _control.addEventListener('keypress', _handleKeyPress); | |
58 | |
59 // Initialize with the first line. | |
60 _newLine(); | |
61 | |
62 _connect(getAttribute('url')); | |
63 } | |
64 | |
65 void _handleKeyPress(KeyboardEvent event) { | |
66 // TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on. | |
67 | |
68 if (_readerQueue.isEmpty) { | |
69 _inputQueue.add(event.charCode); | |
70 } else { | |
71 _readerQueue.removeAt(0).complete(event.charCode); | |
72 } | |
Elliot Glaysher
2015/03/11 20:55:43
I look...forward...to seeing how well this perform
viettrungluu
2015/03/11 21:25:18
I think it already performs better than a connecti
Elliot Glaysher
2015/03/11 21:29:05
This is not actually reassuring.
| |
73 | |
74 event.preventDefault(); | |
75 } | |
76 | |
77 void _newLine() { | |
78 _control.appendChild(document.createElement('span')); | |
79 } | |
80 | |
81 // TODO(vtl): Should we always auto-connect? Should there be facilities for | |
82 // programmatically connecting? (What if the |url| attribute isn't set?) | |
83 void _connect(String url) { | |
84 var terminalClient = new terminal.TerminalClientProxy.unbound(); | |
85 embedder.connectToService(url, terminalClient); | |
86 terminalClient.ptr.connectToTerminal(new TerminalFileImpl(this).stub); | |
87 terminalClient.close(); | |
88 } | |
89 | |
90 // |TerminalDisplay| implementation: | |
91 | |
92 @override | |
93 void putChar(int byte) { | |
94 if (byte == 10 || byte == 13) { | |
95 _newLine(); | |
96 } | |
97 _control.lastChild.textContent += new String.fromCharCode(byte); | |
Elliot Glaysher
2015/03/11 20:55:43
Doesn't this mean that there's now a newline chara
viettrungluu
2015/03/11 21:25:18
Oops, I meant to put a return above. Fixed.
| |
98 } | |
99 | |
100 @override | |
101 Future<int> getChar() async { | |
102 if (_inputQueue.isNotEmpty) { | |
103 return new Future.value(_inputQueue.removeAt(0)); | |
104 } | |
105 | |
106 var completer = new Completer<int>(); | |
107 _readerQueue.add(completer); | |
108 return completer.future; | |
109 } | |
110 } | |
111 | |
112 _init(script) => register(script, TerminalDisplayImpl); | |
113 </script> | |
114 </sky-element> | |
OLD | NEW |