| Index: sky/examples/terminal/terminal.sky
|
| diff --git a/sky/examples/terminal/terminal.sky b/sky/examples/terminal/terminal.sky
|
| deleted file mode 100644
|
| index 246bdfccf682fda7ea82dc69f6b9f64be64521de..0000000000000000000000000000000000000000
|
| --- a/sky/examples/terminal/terminal.sky
|
| +++ /dev/null
|
| @@ -1,218 +0,0 @@
|
| -<!--
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| --->
|
| -<import src="/sky/framework/elements/sky-element.sky" />
|
| -<sky-element>
|
| -<template>
|
| - <style>
|
| - #container {
|
| - height: -webkit-fill-available;
|
| - }
|
| - #input-box {
|
| - position: absolute;
|
| - left: 0;
|
| - top: 0;
|
| - z-index: 10;
|
| - width: 100%;
|
| - height: 100%;
|
| - opacity: 0;
|
| - }
|
| - #output-box {
|
| - position: absolute;
|
| - left: 0;
|
| - top: 0;
|
| - z-index: 0;
|
| - width: 100%;
|
| - height: 100%;
|
| - background-color: black;
|
| - color: rgb(255, 191, 0);
|
| - font-family: 'Courier', 'monospace';
|
| - font-size: small;
|
| - }
|
| - .line {
|
| - height: 1em;
|
| - white-space: nowrap;
|
| - }
|
| - </style>
|
| - <div id="container">
|
| - <div id="input-box" contenteditable />
|
| - <div id="output-box" />
|
| - </div>
|
| - </div>
|
| -</template>
|
| -<script>
|
| -import 'dart:async';
|
| -import 'dart:core';
|
| -import 'dart:sky';
|
| -import 'package:mojo/services/terminal/public/interfaces/terminal_client.mojom.dart' as terminal;
|
| -import 'package:sky/framework/embedder.dart';
|
| -import 'terminal_display.dart';
|
| -import 'terminal_file_impl.dart';
|
| -
|
| -// Implements the <terminal> element, which implements a "terminal display". Has
|
| -// an |url| attribute, whose value should be a Mojo app that provides the
|
| -// |terminal.TerminalClient| service.
|
| -@Tagname('terminal')
|
| -class TerminalDisplayImpl extends SkyElement implements TerminalDisplay {
|
| - Element _inputBox;
|
| - Element _outputBox;
|
| - int _maxLines;
|
| -
|
| - // Queue of unconsumed input (keystrokes), with the head at index 0.
|
| - // Keystrokes end up here if there's no reader (i.e., |getChar()|) pending,
|
| - // i.e., if |_readerQueue| is empty. Invariant: At most one of |_inputQueue|
|
| - // and |_readerQueue| may be nonempty at any given time.
|
| - List<int> _inputQueue;
|
| -
|
| - // Queue of things waiting for input, with the head at index 0. If a keystroke
|
| - // is received and this is nonempty, the head is given that keystroke (and
|
| - // dequeued).
|
| - List<Completer<int>> _readerQueue;
|
| -
|
| - TerminalDisplayImpl()
|
| - : _inputQueue = new List<int>(),
|
| - _readerQueue = new List<Completer<int>>() {
|
| - }
|
| -
|
| - void shadowRootReady() {
|
| - _inputBox = shadowRoot.getElementById('input-box');
|
| - _inputBox.addEventListener('keydown', _handleKeyDown);
|
| - _inputBox.addEventListener('keypress', _handleKeyPress);
|
| - _inputBox.addEventListener('wheel', _handleWheel);
|
| - _outputBox = shadowRoot.getElementById('output-box');
|
| -
|
| - // Hack to allow |_newLine()| to work.
|
| - _maxLines = 100;
|
| -
|
| - // Initialize with the first line.
|
| - _newLine();
|
| -
|
| - // Actually compute the maximum number of lines.
|
| - // TODO(vtl): Recompute on resize.
|
| - _maxLines = _outputBox.clientHeight ~/ _outputBox.firstChild.offsetHeight;
|
| -
|
| - var url = getAttribute('url');
|
| - if (url != null) {
|
| - connect(url);
|
| - }
|
| - }
|
| -
|
| - void _handleKeyDown(KeyboardEvent event) {
|
| - // TODO(vtl): In general, our key handling is a total hack (due in part to
|
| - // sky's keyboard support being incomplete) -- e.g., we shouldn't have to
|
| - // make our div contenteditable. We have to intercept backspace (^H) here,
|
| - // since we won't actually get a keypress event for it. (Possibly, we should
|
| - // only handle keydown instead of keypress, but then we'd have to handle
|
| - // shift, etc. ourselves.)
|
| - if (event.key == 8) {
|
| - _enqueueChar(8);
|
| - event.preventDefault();
|
| - }
|
| - }
|
| -
|
| - void _handleKeyPress(KeyboardEvent event) {
|
| - if (event.charCode != 0) {
|
| - _enqueueChar(event.charCode);
|
| - }
|
| - event.preventDefault();
|
| - }
|
| -
|
| - void _handleWheel(WheelEvent event) {
|
| - _outputBox.dispatchEvent(event);
|
| - }
|
| -
|
| - void _enqueueChar(int charCode) {
|
| - // TODO(vtl): Add "echo" mode; do |putChar(event.charCode);| if echo is on.
|
| -
|
| - if (_readerQueue.isEmpty) {
|
| - _inputQueue.add(charCode);
|
| - } else {
|
| - _readerQueue.removeAt(0).complete(charCode);
|
| - }
|
| - }
|
| -
|
| - void _backspace() {
|
| - var oldText = _outputBox.lastChild.textContent;
|
| - if (oldText.length > 0) {
|
| - _outputBox.lastChild.textContent = oldText.substring(0,
|
| - oldText.length - 1);
|
| - }
|
| - }
|
| -
|
| - void _newLine() {
|
| - var line = document.createElement('div');
|
| - line.setAttribute('class', 'line');
|
| - _outputBox.appendChild(line);
|
| -
|
| - // Scroll if necessary.
|
| - var children = _outputBox.getChildNodes();
|
| - if (children.length > _maxLines) {
|
| - children = new List.from(children.skip(children.length - _maxLines));
|
| - _outputBox.setChildren(children);
|
| - }
|
| - }
|
| -
|
| - void _clear() {
|
| - _outputBox.setChildren([]);
|
| - _newLine();
|
| - }
|
| -
|
| - void connect(String url) {
|
| - var terminalClient = new terminal.TerminalClientProxy.unbound();
|
| - embedder.connectToService(url, terminalClient);
|
| - terminalClient.ptr.connectToTerminal(new TerminalFileImpl(this).stub);
|
| - terminalClient.close();
|
| - }
|
| -
|
| - void putString(String s) {
|
| - for (var i = 0; i < s.length; i++) {
|
| - putChar(s.codeUnitAt(i));
|
| - }
|
| - }
|
| -
|
| - // |TerminalDisplay| implementation:
|
| -
|
| - @override
|
| - void putChar(int byte) {
|
| - // Fast-path for printable chars.
|
| - if (byte >= 32) {
|
| - _outputBox.lastChild.textContent += new String.fromCharCode(byte);
|
| - return;
|
| - }
|
| -
|
| - switch (byte) {
|
| - case 8: // BS (^H).
|
| - _backspace();
|
| - break;
|
| - case 10: // LF ('\n').
|
| - _newLine(); // TODO(vtl): LF and CR should be separated.
|
| - break;
|
| - case 12: // FF (^L).
|
| - _clear();
|
| - break;
|
| - case 13: // CR ('\r').
|
| - _newLine(); // TODO(vtl): LF and CR should be separated.
|
| - break;
|
| - default:
|
| - // Should beep or something.
|
| - break;
|
| - }
|
| - }
|
| -
|
| - @override
|
| - Future<int> getChar() async {
|
| - if (_inputQueue.isNotEmpty) {
|
| - return new Future.value(_inputQueue.removeAt(0));
|
| - }
|
| -
|
| - var completer = new Completer<int>();
|
| - _readerQueue.add(completer);
|
| - return completer.future;
|
| - }
|
| -}
|
| -
|
| -_init(script) => register(script, TerminalDisplayImpl);
|
| -</script>
|
| -</sky-element>
|
|
|