├── .gitignore
├── .gitmodules
├── Gulpfile.js
├── LICENSE
├── Makefile
├── Vagrantfile
├── autogen
├── generate2.js
├── lib
│ ├── enums.js
│ ├── errors.js
│ ├── events.js
│ ├── misc.js
│ ├── requests.js
│ ├── statement_body.js
│ └── types.js
└── proto
│ ├── bigreq.xml
│ ├── composite.xml
│ ├── damage.xml
│ ├── dpms.xml
│ ├── dri2.xml
│ ├── ge.xml
│ ├── glx.xml
│ ├── randr.xml
│ ├── record.xml
│ ├── render.xml
│ ├── res.xml
│ ├── screensaver.xml
│ ├── shape.xml
│ ├── shm.xml
│ ├── sync.xml
│ ├── xc_misc.xml
│ ├── xevie.xml
│ ├── xf86dri.xml
│ ├── xf86vidmode.xml
│ ├── xfixes.xml
│ ├── xinerama.xml
│ ├── xinput.xml
│ ├── xkb.xml
│ ├── xprint.xml
│ ├── xproto.xml
│ ├── xselinux.xml
│ ├── xtest.xml
│ ├── xv.xml
│ └── xvmc.xml
├── basic.js
├── dist
├── Gray
├── blackboxrc
└── xserver.conf
├── docs
├── SMlib.pdf
├── X11R7.5 proto.mhtml
├── X11R7.5 proto.pdf
├── XACE-Spec.pdf
├── XI2proto.txt
├── Xserver-spec.pdf
├── Xtrans.pdf
├── XvMC_API.txt
├── bigreq.pdf
├── compositeproto.txt
├── damageproto.txt
├── fixesproto.txt
├── geproto.txt
├── libXrender.txt
├── mit-shm.pdf
├── randrproto.txt
├── record.pdf
├── recordlib.pdf
├── renderproto.txt
├── shape.pdf
├── xdmcp.pdf
├── xim.pdf
├── xsmp.pdf
├── xtest.pdf
├── xtestlib.pdf
└── xv-protocol-v2.txt
├── keymap.js
├── keymap.json
├── keymap.txt
├── lib
└── fonts.js
├── package.json
├── proxy.js
├── public
├── audio
│ └── bell.mp3
├── check.png
├── fonts
├── index.html
├── require.config.js
└── reset.css
├── readme.md
├── rgb.js
├── rgb.txt
├── src
├── common.js
├── elements.js
├── endianbuffer.js
├── event_types.js
├── fs.js
├── keymap.js
├── rgb_colors.js
├── site.js
├── stack_magick.js
├── worker_comms.js
├── worker_console.js
├── x_client.js
├── x_protocol.js
├── x_protocol_new.js
├── x_server.js
├── x_types.js
├── x_types_font.js
└── xtypebuffer.js
├── types.js
└── x_types.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .project
3 | .settings
4 | *.sublime-workspace
5 | ignored
6 | npm-debug.log
7 | public/common.js
8 | public/common.js.map
9 | public/worker_comms.js
10 | public/worker_comms.js.map
11 | public/site.js
12 | public/site.js.map
13 | tmp/
14 | .swp
15 | .vagrant/
16 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "pcf-font-to-vector"]
2 | path = fonts
3 | url = git@github.com:tnkd/pcf-font-to-vector.git
4 |
--------------------------------------------------------------------------------
/Gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var source = require('vinyl-source-stream');
3 | var watch = require('gulp-watch');
4 | var sourcemaps = require('gulp-sourcemaps');
5 | var buffer = require('vinyl-buffer');
6 | var factor = require('factor-bundle');
7 | var insert = require('gulp-insert');
8 |
9 | var browserify = require('browserify');
10 | var babelify = require('babelify');
11 |
12 | if (process.env.NODE_ENV === undefined) {
13 | process.env.NODE_ENV = 'development';
14 | }
15 |
16 | gulp.task('js', function () {
17 | var worker_stream = source('./worker_comms.js');
18 | var b = browserify({
19 | entries: ['./src/site.js', './src/worker_comms.js'],
20 | debug: true,
21 | fullpath: true,
22 | })
23 | .transform(babelify.configure({
24 | sourceMap: true,
25 | optional: [
26 | 'es7.objectRestSpread',
27 | 'es7.classProperties',
28 | 'es7.exportExtensions',
29 | 'es7.asyncFunctions',
30 | 'es7.functionBind',
31 | 'es7.comprehensions',
32 | 'runtime',
33 | 'utility.inlineEnvironmentVariables',
34 | // 'minification.deadCodeElimination',
35 | 'minification.memberExpressionLiterals',
36 | 'minification.propertyLiterals',
37 | // 'validation.undeclaredVariableCheck',
38 | 'spec.undefinedToVoid',
39 | ],
40 | experimental: true,
41 | blacklist: [
42 | 'strict', // Blacklisted to allow access to objs in stacktraces
43 | ],
44 | }))
45 | .plugin(factor, {o: [
46 | './public/site.js',
47 | worker_stream,
48 | ]});
49 |
50 | worker_stream
51 | .pipe(buffer())
52 | .pipe(sourcemaps.init({loadMaps: true}))
53 | .pipe(insert.prepend('importScripts("common.js");'))
54 | .pipe(sourcemaps.write('./'))
55 | .pipe(gulp.dest('./public/'));
56 |
57 | return b.bundle()
58 | .pipe(source('./common.js'))
59 | .pipe(buffer())
60 | .pipe(sourcemaps.init({loadMaps: true}))
61 | .pipe(sourcemaps.write('./'))
62 | .pipe(gulp.dest('./public/'));
63 | });
64 |
65 | gulp.task('watcher', function () {
66 | gulp.watch(['src/**/*.js', 'Gulpfile.js'], ['js']);
67 | });
68 |
69 | gulp.task('default', ['js']);
70 |
71 | gulp.task('watch', ['js' ,'watcher']);
72 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012, Greg Miell / Tango November Kilo Delta Limited
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | The views and conclusions contained in the software and documentation are those
25 | of the authors and should not be interpreted as representing official policies,
26 | either expressed or implied, of the FreeBSD Project.
27 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all: fonts
2 |
3 | fonts:
4 | cd fonts; mkfontdir; make
5 | find public/fonts -type l -delete
6 | cd public/fonts/; ln -s ../../fonts/out/*.woff .
7 | cd public/fonts/; ln -s ../../fonts/out/*.json .
8 | cd public/fonts/; ln -s ../../fonts/fonts.dir .
9 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure(2) do |config|
5 | # config.vm.box = "ubuntu/ubuntu-15.04-snappy-core-stable"
6 | config.vm.box = "ubuntu/trusty64"
7 |
8 | config.vm.provider "virtualbox" do |vb|
9 | vb.memory = 2048
10 | vb.cpus = 2
11 | end
12 |
13 | # Create a forwarded port mapping which allows access to a specific port
14 | # within the machine from a port on the host machine. In the example below,
15 | # accessing "localhost:8080" will access port 80 on the guest machine.
16 | config.vm.network "forwarded_port", guest: 3000, host: 3080
17 | config.vm.network :forwarded_port, guest: 22, host: 2222, id: "ssh", auto_correct: true
18 |
19 | # Share an additional folder to the guest VM. The first argument is
20 | # the path on the host to the actual folder. The second argument is
21 | # the path on the guest to mount the folder. And the optional third
22 | # argument is a set of non-required options.
23 | config.vm.synced_folder ".", "/mnt/server"
24 |
25 | config.vm.provision "shell", inline: <<-SCRIPT
26 | apt-get install -y build-essential x11-apps x11-utils blackbox blackbox-themes menu git
27 |
28 | sudo -iu vagrant /bin/bash - <<-EOF
29 | cd ~
30 |
31 | if [ ! -d ~/.nvm ]; then
32 | git clone https://github.com/creationix/nvm.git ~/.nvm
33 | cd ~/.nvm
34 | git checkout $(git describe --abbrev=0 --tags)
35 | cd ~
36 | fi
37 |
38 | if ! grep -q '. ~/.nvm/nvm.sh' .profile; then
39 | echo '. ~/.nvm/nvm.sh' >> .profile
40 | fi
41 |
42 | . ~/.nvm/nvm.sh
43 |
44 | nvm install node
45 | nvm alias default node
46 | echo "rar \\$(nvm version)"
47 |
48 | nvm ls | grep -v iojs | grep -o -P "v\\d+\\.\\d+\\.\\d+" | sort -u | grep -v "\\$(nvm version)" | while read rmver; do
49 | echo "Uninstall \\$rmver"
50 | nvm uninstall \\$rmver
51 | done
52 |
53 | EOF
54 |
55 | cp /mnt/server/dist/xserver.conf /etc/init/
56 |
57 | initctl stop xserver
58 | kill -HUP 1
59 | initctl start xserver
60 |
61 | update-menus
62 | sudo -iu vagrant /bin/bash - <<-EOF
63 | cp /mnt/server/dist/blackboxrc /home/vagrant/.blackboxrc
64 | mkdir -p /home/vagrant/.blackbox/styles
65 | cp /mnt/server/dist/Gray /home/vagrant/.blackbox/styles/
66 | EOF
67 | SCRIPT
68 |
69 | # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
70 | # such as FTP and Heroku are also available. See the documentation at
71 | # https://docs.vagrantup.com/v2/push/atlas.html for more information.
72 | # config.push.define "atlas" do |push|
73 | # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
74 | # end
75 |
76 | # Enable provisioning with a shell script. Additional provisioners such as
77 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
78 | # documentation for more information about their specific syntax and use.
79 | # config.vm.provision "shell", inline: <<-SHELL
80 | # sudo apt-get update
81 | # sudo apt-get install -y apache2
82 | # SHELL
83 | end
84 |
--------------------------------------------------------------------------------
/autogen/generate2.js:
--------------------------------------------------------------------------------
1 | #!node --harmony_destructuring
2 | "use strict";
3 |
4 | var path = require('path');
5 | var fs = require('fs');
6 | var libxml = require('libxmljs');
7 | var { b: builders } = require('ast-types');
8 | var recast = require('recast');
9 | var { Classes } = require('./lib/misc');
10 |
11 | var doc = libxml.parseXml(fs.readFileSync(path.join(__dirname, 'proto/xproto.xml'), 'ascii'));
12 |
13 | var klasses = new Classes();
14 |
15 | var klass = klasses.newClass('XTypeBuffer', 'CursorBuffer');
16 |
17 | require('./lib/types')(doc, klass, klasses);
18 | require('./lib/enums')(doc, klass, klasses);
19 | require('./lib/events')(doc, klass, klasses);
20 | require('./lib/errors')(doc, klass, klasses);
21 | require('./lib/requests')(doc, klass, klasses);
22 |
23 | fs.writeFile(path.join(__dirname, '../src/xtypebuffer.js'), klasses.toString());
24 |
--------------------------------------------------------------------------------
/autogen/lib/enums.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b } = require('ast-types');
3 | var parseBody = require('./statement_body');
4 |
5 | module.exports = function genErrors(doc, klass, klasses) {
6 | var enums = new Map();
7 |
8 | for (let _enum of doc.find('enum')) {
9 | let name = _enum.attr('name').value();
10 | let values = new Map();
11 | let bits = new Map();
12 |
13 | if (name === 'Atom') {
14 | // TODO: Bojizzle the Atom Enum
15 | console.error('TODO: Implement Atom Enum');
16 | continue;
17 | }
18 |
19 | var parent_klass = `${_enum.find('*/bit').length ? 'Bit' : 'Value'}Enum`;
20 |
21 | var enum_klass = klasses.newClass(`${name}Enum`, parent_klass);
22 | enums.set(name, b.identifier(enum_klass.name));
23 |
24 | for (let item of _enum.find('item')) {
25 | let item_name = item.attr('name').value();
26 | let child = item.get('*');
27 |
28 | if (!child) {
29 | console.error('Enum item without a child, wut?!', item_name);
30 | continue;
31 | }
32 | let item_value = parseInt(child.text());
33 |
34 | switch (child.name()) {
35 | case 'value':
36 | values.set(item_value, item_name);
37 | break;
38 | case 'bit':
39 | bits.set(item_value, item_name);
40 | break;
41 | default:
42 | throw new Error(`Unknown child type ${child.name()}`);
43 | }
44 | }
45 |
46 | if (values.size) {
47 | enum_klass.addProperty('_values', values, true);
48 | }
49 | if (parent_klass === 'BitEnum' && bits.size) {
50 | enum_klass.addProperty('_bits', bits, true);
51 | }
52 | }
53 |
54 | klass.addProperty('enums', enums, true);
55 | }
56 |
--------------------------------------------------------------------------------
/autogen/lib/errors.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b } = require('ast-types');
3 | var parseBody = require('./statement_body');
4 |
5 | module.exports = function genErrors(doc, klass) {
6 | var error_numbers = new Map();
7 |
8 | for (let error of doc.find('error')) {
9 | // TODO: Create classes & objects
10 | let name = error.attr('name').value();
11 | let number = parseInt(error.attr('number').value());
12 | error_numbers.set(number, name);
13 | let [read_stmts, write_stmts] = parseBody(error);
14 | klass.addMethod(`error_read${name}`, [], read_stmts);
15 | klass.addMethod(`error_write${name}`, [b.identifier('obj')], write_stmts);
16 | }
17 |
18 | for (let error of doc.find('errorcopy')) {
19 | // TODO: Create classes & objects
20 | let name = error.attr('name').value();
21 | let ref = error.attr('ref').value();
22 | let number = parseInt(error.attr('number').value());
23 | error_numbers.set(number, name);
24 | klass.addSymRead(`error_read${name}`, `error_read${ref}`);
25 | klass.addSymWrite(`error_write${name}`, `error_write${ref}`);
26 | }
27 |
28 | klass.addProperty('error_numbers', error_numbers, true);
29 | }
30 |
--------------------------------------------------------------------------------
/autogen/lib/events.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b } = require('ast-types');
3 | var parseBody = require('./statement_body');
4 |
5 | module.exports = function genEvents(doc, klass, klasses) {
6 | var event_numbers = new Map();
7 |
8 | for (let event of doc.find('event')) {
9 | // TODO: Create classes & objects
10 | let name = event.attr('name').value();
11 | let number = parseInt(event.attr('number').value());
12 | event_numbers.set(number, name);
13 | let [read_stmts, write_stmts] = parseBody(event, klasses);
14 | klass.addMethod(`event_read${name}`, [], read_stmts);
15 | klass.addMethod(`event_write${name}`, [b.identifier('obj')], write_stmts);
16 | }
17 |
18 | for (let event of doc.find('eventcopy')) {
19 | // TODO: Create classes & objects
20 | let name = event.attr('name').value();
21 | let ref = event.attr('ref').value();
22 | let number = parseInt(event.attr('number').value());
23 | event_numbers.set(number, name);
24 | klass.addSymRead(`event_read${name}`, `event_read${ref}`);
25 | klass.addSymWrite(`event_write${name}`, `event_write${ref}`);
26 | }
27 |
28 | klass.addProperty('event_numbers', event_numbers, true);
29 | }
30 |
--------------------------------------------------------------------------------
/autogen/lib/misc.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b, namedTypes} = require('ast-types');
3 | var recast = require('recast');
4 |
5 | function _convertValToAST(value) {
6 | if (Array.isArray(value)) {
7 | return b.arrayExpression(value.map(_convertValToAST));
8 | }
9 | if (value instanceof Map) {
10 | return b.newExpression(
11 | b.identifier('Map'),
12 | [b.arrayExpression(Array.from(value).map(
13 | (v) => b.arrayExpression(v.map(_convertValToAST))))]);
14 | }
15 | if (value instanceof Set) {
16 | return b.newExpression(
17 | b.identifier('Set'),
18 | [b.arrayExpression(Array.from(value).map(_convertValToAST))]);
19 | }
20 | if (namedTypes.Node.check(value)) {
21 | return value;
22 | }
23 | return b.literal(value);
24 | }
25 |
26 | class Classes {
27 | constructor() {
28 | this.classes = new Map();
29 | }
30 | newClass(name, extend) {
31 | var klass = new Class(name, extend);
32 | this.classes.set(name, klass);
33 | return klass;
34 | }
35 | getClass(name) {
36 | return this.classes.get(name);
37 | }
38 | program() {
39 | var classes = [
40 | b.importDeclaration(
41 | [
42 | b.importSpecifier(b.identifier('ValueEnum')),
43 | b.importSpecifier(b.identifier('BitEnum')),
44 | b.importSpecifier(b.identifier('CursorBuffer')),
45 | ],
46 | b.literal('./endianbuffer')
47 | ),
48 | ];
49 | for (let [name, klass] of this.classes) {
50 | classes.push(b.exportDeclaration(false, klass.gen()));
51 | }
52 | return b.program(classes);
53 | }
54 | recastPrint() {
55 | return recast.print(this.program(), { tabWidth: 2 });
56 | }
57 | toString() {
58 | return this.recastPrint().code;
59 | }
60 | }
61 |
62 | class Class {
63 | constructor(name, extend) {
64 | this.name = name;
65 | this.extend = extend;
66 | this.body = [];
67 | }
68 |
69 | addMethod(name, args, body) {
70 | this.body.push(b.methodDefinition(
71 | 'method',
72 | b.identifier(name),
73 | b.functionExpression(
74 | null,
75 | args,
76 | b.blockStatement(body))));
77 | }
78 |
79 | __addSymMethod(name, callname, read) {
80 | var callArguments = [];
81 | if (!read) {
82 | callArguments = [b.spreadElement(b.identifier('arguments'))];
83 | }
84 | this.addMethod(
85 | name,
86 | [],
87 | [(read ? b.returnStatement : b.expressionStatement)(b.callExpression(
88 | b.memberExpression(
89 | b.thisExpression(),
90 | b.identifier(callname)),
91 | callArguments
92 | ))]);
93 | }
94 |
95 | addSymRead(name, callname) {
96 | this.__addSymMethod(name, callname, true);
97 | }
98 |
99 | addSymWrite(name, callname) {
100 | this.__addSymMethod(name, callname, false);
101 | }
102 |
103 | addProperty(name, value, is_static) {
104 | this.body.push(b.classProperty(
105 | b.identifier(name),
106 | _convertValToAST(value),
107 | null,
108 | is_static));
109 | // Add the property here so we can reference it later
110 | // (e.g. enums from statement_body)
111 | this[name] = value;
112 | if (value instanceof Map) {
113 | let inv = this[`${name}_inv`] = new Map();
114 | for (let [k, v] of value) {
115 | inv.set(v, k);
116 | }
117 | }
118 | }
119 |
120 | gen() {
121 | var extend = null;
122 | if (this.extend) {
123 | extend = b.identifier(this.extend);
124 | }
125 | return b.classDeclaration(
126 | b.identifier(this.name),
127 | b.classBody(this.body),
128 | extend,
129 | []);
130 | }
131 | }
132 |
133 | module.exports = {
134 | Class: Class,
135 | Classes: Classes,
136 | }
137 |
--------------------------------------------------------------------------------
/autogen/lib/requests.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b } = require('ast-types');
3 | var parseBody = require('./statement_body');
4 |
5 | module.exports = function genRequests(doc, klass, klasses) {
6 | var request_opcodes = new Map();
7 | for (let request of doc.find('request')) {
8 | // TODO: Classes & objects
9 | let name = request.attr('name').value();
10 | let opcode = parseInt(request.attr('opcode').value());
11 | request_opcodes.set(opcode, name);
12 | let [read_stmts, write_stmts] = parseBody(request, klasses);
13 | klass.addMethod(`request_read${name}`, [], read_stmts);
14 | klass.addMethod(`request_write${name}`, [b.identifier('obj')], write_stmts);
15 |
16 | let reply = request.get('reply');
17 | if (reply) {
18 | // TODO: Classes & objects
19 | let [read_stmts, write_stmts] = parseBody(reply, klasses);
20 | klass.addMethod(`reply_read${name}`, [], read_stmts);
21 | klass.addMethod(`reply_write${name}`, [b.identifier('obj')], write_stmts);
22 | }
23 | }
24 |
25 | klass.addProperty('request_opcodes', request_opcodes, true);
26 | }
27 |
--------------------------------------------------------------------------------
/autogen/lib/types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var { builders :b } = require('ast-types');
3 | var parseBody = require('./statement_body');
4 |
5 | module.exports = function genTypes(doc, klass, klasses) {
6 | var types = new Map([
7 | ['BOOL', 'UInt8'],
8 | ['BYTE', 'UInt8'],
9 | ['CARD8', 'UInt8'],
10 | ['INT8', 'Int8'],
11 | ['CARD16', 'UInt16'],
12 | ['INT16', 'Int16'],
13 | ['CARD32', 'UInt32'],
14 | ['INT32', 'Int32'],
15 | ]);
16 |
17 | var xids = new Map();
18 |
19 | for (let [name, type] of types) {
20 | klass.addSymRead(`read${name}`, `read${type}`);
21 | klass.addSymWrite(`write${name}`, `write${type}`);
22 | }
23 |
24 | for (let def of doc.find('typedef')) {
25 | let newname = def.attr('newname').value();
26 | let oldname = def.attr('oldname').value();
27 | klass.addSymRead(`read${newname}`, `read${oldname}`);
28 | klass.addSymWrite(`write${newname}`, `write${oldname}`);
29 | }
30 |
31 | for (let xid of doc.find('xidtype')) {
32 | let name = xid.attr('name').value();
33 | xids.set(name, null);
34 | klass.addSymRead(`read${name}`, 'readCARD32');
35 | klass.addSymWrite(`write${name}`, 'writeCARD32');
36 | }
37 |
38 | for (let xid of doc.find('xidunion')) {
39 | let name = xid.attr('name').value();
40 | let _types = xid.find('type').map(t => t.text());
41 | xids.set(name, new Set(_types));
42 | types.set(name, 'UInt32');
43 | klass.addSymRead(`read${name}`, 'readCARD32', false);
44 | klass.addSymWrite(`write${name}`, 'writeCARD32');
45 | }
46 |
47 | klass.addProperty('xids', xids, true);
48 |
49 | for (let struct of doc.find('struct')) {
50 | let name = struct.attr('name').value();
51 | let [read_stmts, write_stmts] = parseBody(struct, klasses);
52 | klass.addMethod(`read${name}`, [], read_stmts);
53 | klass.addMethod(`write${name}`, [b.identifier('obj')], write_stmts);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/autogen/proto/bigreq.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/autogen/proto/composite.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
30 |
31 | xproto
32 | xfixes
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/autogen/proto/damage.xml:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
32 | xproto
33 | xfixes
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/autogen/proto/dpms.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/autogen/proto/dri2.xml:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
32 | xproto
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | - 1
55 | - 2
56 | - 3
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | driver_name_length
95 |
96 |
97 |
98 |
99 |
100 | driver_name_length
101 | 3
102 |
103 |
104 | 3
105 |
106 |
107 | driver_name_length
108 |
109 |
110 |
111 | device_name_length
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | count
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | count
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
--------------------------------------------------------------------------------
/autogen/proto/ge.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/autogen/proto/record.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | - 0
65 | - 1
66 | - 2
67 |
68 |
69 |
70 |
71 | - 1
72 | - 2
73 | - 3
74 |
75 |
76 |
77 |
78 |
79 |
80 | num_ranges
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | num_client_specs
108 |
109 |
110 | num_ranges
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | num_client_specs
122 |
123 |
124 | num_ranges
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | num_client_specs
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | num_intercepted_clients
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | length
164 | 4
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/autogen/proto/res.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
30 | xproto
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | num_clients
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | num_types
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/autogen/proto/screensaver.xml:
--------------------------------------------------------------------------------
1 |
28 |
32 |
33 |
34 |
35 |
36 | xproto
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | - 0
46 | - 1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/autogen/proto/shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
30 | xproto
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | rectangles_len
152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/autogen/proto/shm.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
30 | xproto
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/autogen/proto/sync.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 | xproto
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | - 0
37 | - 1
38 | - 2
39 | - 3
40 | - 4
41 | - 5
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | name_len
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | counters_len
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
140 |
141 |
142 |
143 |
144 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/autogen/proto/xc_misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ids_len
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/autogen/proto/xevie.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/autogen/proto/xf86dri.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | bus_id_len
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | client_driver_name_len
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | num_clip_rects
140 |
141 |
142 | num_back_clip_rects
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | device_private_size
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/autogen/proto/xfixes.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
30 | xproto
31 | render
32 | shape
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | - 0
77 | - 1
78 | - 2
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | - 0
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | width
133 | height
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | length
234 | 2
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 | nbytes
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 | nbytes
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 | nbytes
295 |
296 |
297 | width
298 | height
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 | nbytes
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
--------------------------------------------------------------------------------
/autogen/proto/xinerama.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
31 |
32 |
33 |
34 | xproto
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | number
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/autogen/proto/xselinux.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
27 | xproto
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | context_len
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | context_len
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | context_len
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | context_len
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | context_len
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | context_len
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | context_len
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | object_context_len
113 |
114 |
115 | data_context_len
116 |
117 |
118 |
119 |
120 |
121 |
122 | context_len
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | context_len
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | context_len
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | context_len
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | context_len
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | context_len
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | properties_len
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 | context_len
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | context_len
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 | context_len
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 | context_len
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | context_len
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 | context_len
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 | selections_len
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 | context_len
272 |
273 |
274 |
275 |
276 |
277 |
--------------------------------------------------------------------------------
/autogen/proto/xtest.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
31 |
32 |
33 | xproto
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | - 0
48 | - 1
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/autogen/proto/xvmc.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
30 | xv
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | num
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | length
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | length
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | 4
121 |
122 |
123 |
124 | length
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | num
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/dist/Gray:
--------------------------------------------------------------------------------
1 | *button.pressed.appearance: sunken solid
2 | *button.pressed.backgroundColor: darkgrey
3 | *button.appearance: parentrelative
4 | *button.foregroundColor: black
5 |
6 | *backgroundColor: rgb:dd/dd/d7
7 | *color1: rgb:dd/dd/d7
8 | *color2: rgb:ee/ee/e7
9 |
10 | *font: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
11 |
12 | *borderColor: black
13 | *borderWidth: 1
14 | *marginWidth: 2
15 |
16 | menu.title.appearance: flat solid border
17 | menu.title.backgroundColor: grey
18 | menu.title.foregroundColor: black
19 | menu.title.textColor: black
20 | menu.title.alignment: center
21 | menu.title.font: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
22 |
23 | menu.frame.appearance: raised gradient border
24 | menu.frame.textColor: black
25 | menu.frame.foregroundColor: grey40
26 | menu.frame.disabledColor: darkgrey
27 | menu.frame.alignment: left
28 |
29 | menu.active.appearance: flat solid border
30 | menu.active.backgroundColor: rgb:77/77/74
31 | menu.active.foregroundColor: white
32 | menu.active.textColor: white
33 |
34 | rootCommand: bsetroot -solid rgb:aa/aa/aa
35 |
36 | slit.appearance: raised solid
37 | slit.backgroundColor: rgb:aa/aa/aa
38 | slit.marginWidth: 3
39 |
40 | toolbar.appearance: raised gradient border
41 | toolbar.alignment: center
42 | toolbar*textColor: black
43 | toolbar.label.appearance: parentrelative
44 | toolbar.clock.appearance: parentrelative
45 | toolbar.windowLabel.appearance: parentrelative
46 |
47 | window.title.focus.appearance: raised gradient border
48 | window.title.focus.color1: rgb:66/66/63
49 | window.title.focus.color2: rgb:88/88/84
50 | window.title.unfocus.appearance: raised gradient border
51 |
52 | window.label.focus.appearance: parentrelative
53 | window.label.focus.textColor: white
54 | window.label.unfocus.appearance: parentrelative
55 | window.label.unfocus.textColor: darkgrey
56 | window.label.marginWidth: 1
57 |
58 | window.button.focus.appearance: parentrelative
59 | window.button.focus.foregroundColor: white
60 |
61 | window.button.unfocus.appearance: parentrelative
62 | window.button.unfocus.foregroundColor: darkgrey
63 |
64 | window.handle.focus.appearance: raised solid border
65 | window.handle.unfocus.appearance: raised solid border
66 |
67 | window.grip.focus.appearance: raised solid border
68 | window.grip.focus.backgroundColor: rgb:77/77/74
69 | window.grip.unfocus.appearance: raised solid border
70 |
71 | window*alignment: center
72 | window.font: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
73 | window.handleHeight: 8
74 |
--------------------------------------------------------------------------------
/dist/blackboxrc:
--------------------------------------------------------------------------------
1 | session.styleFile: /home/vagrant/.blackbox/styles/Gray
2 | session.screen0.slit.placement: CenterRight
3 | session.screen0.slit.direction: Vertical
4 | session.screen0.slit.onTop: False
5 | session.screen0.slit.autoHide: False
6 | session.screen0.toolbar.onTop: False
7 | session.screen0.toolbar.autoHide: False
8 | session.screen0.toolbar.placement: BottomCenter
9 | session.screen0.toolbar.widthPercent: 66
10 | session.screen0.enableToolbar: True
11 | session.screen0.workspaces: 4
12 | session.screen0.workspaceNames: Workspace 1,Workspace 2,Workspace 3,Workspace 4
13 | session.screen0.strftimeFormat: %I:%M %p
14 | session.windowSnapThreshold: 0
15 | session.autoRaiseDelay: 400
16 | session.placementIgnoresShaded: True
17 | session.focusLastWindow: True
18 | session.opaqueMove: True
19 | session.changeWorkspaceWithMouseWheel: True
20 | session.imageDither: OrderedDither
21 | session.windowPlacement: RowSmartPlacement
22 | session.shadeWindowWithMouseWheel: True
23 | session.opaqueResize: True
24 | session.toolbarActionsWithMouseWheel: True
25 | session.rowPlacementDirection: LeftToRight
26 | session.maximumColors: 0
27 | session.disableBindingsWithScrollLock: False
28 | session.fullMaximization: False
29 | session.colPlacementDirection: TopToBottom
30 | session.doubleClickInterval: 250
31 | session.edgeSnapThreshold: 0
32 | session.focusNewWindows: True
33 | session.focusModel: ClickToFocus
34 |
--------------------------------------------------------------------------------
/dist/xserver.conf:
--------------------------------------------------------------------------------
1 | description "Play server"
2 | start on vagrant-mounted
3 |
4 | respawn
5 | respawn limit unlimited
6 |
7 | setuid vagrant
8 |
9 | script
10 | cd /mnt/server/
11 | export HOME=/home/vagrant
12 | export NVM_DIR=/home/vagrant/.nvm
13 | /home/vagrant/.nvm/nvm-exec npm start 2>&1 > /mnt/server/tmp/server.log
14 | sleep 5
15 | end script
16 |
--------------------------------------------------------------------------------
/docs/SMlib.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/SMlib.pdf
--------------------------------------------------------------------------------
/docs/X11R7.5 proto.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/X11R7.5 proto.pdf
--------------------------------------------------------------------------------
/docs/XACE-Spec.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/XACE-Spec.pdf
--------------------------------------------------------------------------------
/docs/Xserver-spec.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/Xserver-spec.pdf
--------------------------------------------------------------------------------
/docs/Xtrans.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/Xtrans.pdf
--------------------------------------------------------------------------------
/docs/bigreq.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/bigreq.pdf
--------------------------------------------------------------------------------
/docs/damageproto.txt:
--------------------------------------------------------------------------------
1 | The DAMAGE Extension
2 | Protocol Version 1.1
3 | Document Revision 1
4 | 2007-01-08
5 |
6 | Keith Packard
7 | keithp@keithp.com
8 |
9 | Eric Anholt
10 | eric@anholt.net
11 | Open Source Technology Center
12 | Intel Corporation
13 | 1. Introduction
14 |
15 | Monitoring the regions affected by rendering has wide-spread use, from
16 | VNC-like systems scraping the screen to screen magnifying applications
17 | designed to aid users with limited visual acuity. The DAMAGE extension is
18 | designed to make such applications reasonably efficient in the face of
19 | server-client latency.
20 |
21 | 2. Acknolwedgements
22 |
23 | As usual, the author had significant input from many people, in particular:
24 |
25 | + Havoc Pennington who designed and implemented a Damage extension
26 | last year which was then lost to the mists of time.
27 |
28 | + Bill Haneman whose work on accessibility in the Gnome environment
29 | is legendary.
30 |
31 | + Jim Gettys who found a way to avoid streaming damage rectangles
32 | to the client in many cases.
33 |
34 | + Owen Taylor who suggested that streaming damage rectangles may
35 | be warranted in some cases after all.
36 |
37 | 3. Damage Model
38 |
39 | We call changes made to pixel contents of windows and pixmaps 'damage'
40 | throughout this extension. Another notion of 'damage' are drawable regions
41 | which are in need of redisplay to repair the effects of window manipulation
42 | or other data loss. This extension doesn't deal with this second notion at
43 | all; suggestions on a better term which isn't easily conflated with existing
44 | notions are eagerly solicited.
45 |
46 | Damage accumulates as drawing occurs in the drawable. Each drawing operation
47 | 'damages' one or more rectangular areas within the drawable. The rectangles
48 | are guaranteed to include the set of pixels modified by each operation, but
49 | may include significantly more than just those pixels. The desire is for
50 | the damage to strike a balance between the number of rectangles reported and
51 | the extraneous area included. A reasonable goal is for each primitive
52 | object drawn (line, string, rectangle) to be represented as a single
53 | rectangle and for the damage area of the operation to be the union of these
54 | rectangles.
55 |
56 | The DAMAGE extension allows applications to either receive the raw
57 | rectangles as a stream of events, or to have them partially processed within
58 | the X server to reduce the amount of data transmitted as well as reduce the
59 | processing latency once the repaint operation has started.
60 |
61 | Damage to a window reflects both drawing within the window itself as well as
62 | drawing within any inferior window that affects pixels seen by
63 | IncludeInferiors rendering operations. To reduce the computational
64 | complexity of this, the DAMAGE extension allows the server to monitor all
65 | rendering operations within the physical target pixel storage that fall
66 | within the bounds of the window. In a system with a single frame buffer
67 | holding all windows, this means that damage will accumulate for all
68 | rendering operations that lie within the visible part of the window.
69 |
70 | The precise reason for this architecture is to enable the Composite
71 | extension which provides multiple pixel storage areas for the screen
72 | contents.
73 |
74 | 3.1 Additions in the 1.1 version of the protocol
75 |
76 | Damage is automatically computed by the X Server for X rendering operations,
77 | but direct rendering extensions have allowed clients to perform rendering
78 | outside of the control of the X Server. The 1.1 version of the protocol
79 | added a request to allow direct rendering clients to report damage to a
80 | drawable. Some direct rendering clients, due to architectural limitations,
81 | always perform rendering to the root window, even in when it should be
82 | performed to the backing pixmap in the Composite case. To provide
83 | less-incorrect rendering in this cases, the direct rendering client should
84 | translate its damage region to screen coordinates and report the damage against
85 | the root window rather than the drawable.
86 |
87 | 4. Data types
88 |
89 | The "Damage" object holds any accumulated damage region and reflects the
90 | relationship between the drawable selected for damage notification and the
91 | drawable for which damage is tracked.
92 |
93 | 5. Errors
94 |
95 | Damage
96 | A value for a DAMAGE argument does not name a defined DAMAGE.
97 |
98 | 6. Types
99 |
100 | DAMAGE 32-bit value (top three bits guaranteed to be zero)
101 |
102 | DamageReportLevel { DamageReportRawRectangles,
103 | DamageReportDeltaRectangles,
104 | DamageReportBoundingBox,
105 | DamageReportNonEmpty }
106 |
107 | DamageReportRawRectangles
108 |
109 | Delivers DamageNotify events each time the screen
110 | is modified with rectangular bounds that circumscribe
111 | the damaged area. No attempt to compress out overlapping
112 | rectangles is made.
113 |
114 | DamageReportDeltaRectangles
115 |
116 | Delivers DamageNotify events each time damage occurs
117 | which is not included in the damage region. The
118 | reported rectangles include only the changes to that
119 | area, not the raw damage data.
120 |
121 | DamageReportBoundingBox
122 |
123 | Delivers DamageNotify events each time the bounding
124 | box enclosing the damage region increases in size.
125 | The reported rectangle encloses the entire damage region,
126 | not just the changes to that size.
127 |
128 | DamageReportNonEmpty
129 |
130 | Delivers a single DamageNotify event each time the
131 | damage rectangle changes from empty to non-empty, and
132 | also whenever the result of a DamageSubtract request
133 | results in a non-empty region.
134 |
135 | 7. Events
136 |
137 | DamageNotify
138 |
139 | level: DamageReportLevel
140 | drawable: Drawable
141 | damage: DAMAGE
142 | more: Bool
143 | timestamp: Timestamp
144 | area: Rectangle
145 | drawable-geometry: Rectangle
146 |
147 | 'more' indicates whether there are subsequent damage events
148 | being delivered immediately as part of a larger damage region
149 |
150 | 8. Extension Initialization
151 |
152 | The client must negotiate the version of the extension before executing
153 | extension requests. Otherwise, the server will return BadRequest for any
154 | operations other than QueryVersion.
155 |
156 | QueryVersion
157 |
158 | client-major-version: CARD32
159 | client-minor-version: CARD32
160 |
161 | ->
162 |
163 | major-version: CARD32
164 | minor-version: CARD32
165 |
166 | The client sends the highest supported version to the server and
167 | the server sends the highest version it supports, but no higher than
168 | the requested version. Major versions changes can introduce
169 | incompatibilities in existing functionality, minor version
170 | changes introduce only backward compatible changes. It is
171 | the clients responsibility to ensure that the server supports
172 | a version which is compatible with its expectations. Servers
173 | are encouraged to support multiple versions of the extension.
174 |
175 | 9. Enable Monitoring
176 |
177 | DamageCreate
178 |
179 | damage: DAMAGE
180 | drawable: Drawable
181 | level: DamageReportLevel
182 |
183 | Creates a damage object to monitor changes to Drawable
184 |
185 | DamageDestroy
186 | damage: DAMAGE
187 |
188 | Destroys damage.
189 |
190 | DamageSubtract
191 |
192 | damage: DAMAGE
193 | repair: Region or None
194 | parts: Region or None
195 |
196 | Synchronously modifies the regions in the following manner:
197 |
198 | If repair is None:
199 |
200 | 1) if parts is not None, parts = damage
201 | 2) damage =
202 |
203 | Otherwise:
204 |
205 | 1) tmp = damage INTERSECT repair
206 | 2) damage = damage - tmp
207 | 3) if parts is not None, parts = tmp
208 | 4) Generate DamageNotify for remaining damage areas
209 |
210 | DamageAdd
211 |
212 | drawable: Drawable
213 | region: Region
214 |
215 | Reports damage of the region within the given drawable. This may be
216 | used by direct rendering clients to report damage that the server would
217 | otherwise be unaware of. The damage region is relative to the origin
218 | of the drawable.
219 |
220 | Damage posted in this way will appear in DamageNotify events as normal,
221 | and also in server internal damage tracking (for shadow framebuffer
222 | updates, pixmap damage, and other uses).
223 |
--------------------------------------------------------------------------------
/docs/geproto.txt:
--------------------------------------------------------------------------------
1 | X Generic Event Extension
2 | Peter Hutterer
3 | peter.hutterer@who-t.net
4 |
5 |
6 | 1. Introduction
7 | 2. Extension Initialization
8 | 3. Extension Events
9 | 4. Notes
10 |
11 | _____________________________________________________________________________
12 | 1. Introduction
13 |
14 | X was designed to provide 64 event opcodes for all extensions. These events
15 | are limited to 32 bytes.
16 |
17 | The Generic Event Extension provides a template event for extensions to re-use
18 | a single event opcode. GE only provide headers and the most basic
19 | functionality, leaving the extensions to interpret the events in their
20 | specific context.
21 |
22 | GenericEvents may be longer than 32 bytes. If so, the number of 4 byte units
23 | following the initial 32 bytes must be specified in the length field of the
24 | event.
25 | _____________________________________________________________________________
26 | 2. Extension Initialization
27 |
28 | The name of this extension is "Generic Event Extension"
29 |
30 | ┌───
31 | GEQueryVersion
32 | client-major-version: CARD16
33 | client-minor-version: CARD16
34 | ▶
35 | major-version: CARD16
36 | minor-version: CARD16
37 | └───
38 |
39 | The client sends the highest supported version to the server
40 | and the server sends the highest version it supports, but no
41 | higher than the requested version. Major versions changes can
42 | introduce incompatibilities in existing functionality, minor
43 | version changes introduce only backward compatible changes.
44 | It is the clients responsibility to ensure that the server
45 | supports a version which is compatible with its expectations.
46 |
47 |
48 | As of version 1.0, no other requests are provided by this extension.
49 | _____________________________________________________________________________
50 | 3. Extension Events
51 |
52 | GE defines a single event, to be used by all extensions. The event's structure
53 | is similar to a reply.
54 |
55 | ┌───
56 | GenericEvent
57 | type: BYTE; always GenericEvent
58 | extension: CARD8; extension offset
59 | sequenceNumber: CARD16 low 16 bits of request seq. number
60 | length: CARD32 length
61 | evtype: CARD16 event type
62 | └───
63 |
64 | The field 'extension' is to be set to the major opcode of the
65 | extension. The 'evtype' field is the actual opcode of the event.
66 | The length field specifies the number of 4-byte blocks after the
67 | initial 32 bytes. If length is 0, the event is 32 bytes long.
68 | _____________________________________________________________________________
69 | 4. Notes
70 |
71 | Although the wire event is of arbitrary length, the actual size of an XEvent
72 | is restricted to sizeof(XEvent) [96 bytes, see Xlib.h]. If an extension
73 | converts a wire event to an XEvent > 96 bytes, it will overwrite the space
74 | allocated for the event. See struct _XSQEvent in Xlibint.h for details.
75 |
76 | Extensions need to malloc additional data and fill the XEvent structure with
77 | pointers to the malloc'd data. The client then needs to free the data, only
78 | the XEvent structure will be released by Xlib.
79 |
80 | The server must not send GenericEvents longer than 32 bytes until it has
81 | verified that the client is able to interpret these events. If a long event is
82 | sent to a client unable to process GenericEvents, future interpretation of
83 | replies and events by this client will fail.
84 |
--------------------------------------------------------------------------------
/docs/mit-shm.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/mit-shm.pdf
--------------------------------------------------------------------------------
/docs/record.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/record.pdf
--------------------------------------------------------------------------------
/docs/recordlib.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/recordlib.pdf
--------------------------------------------------------------------------------
/docs/shape.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/shape.pdf
--------------------------------------------------------------------------------
/docs/xdmcp.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/xdmcp.pdf
--------------------------------------------------------------------------------
/docs/xim.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/xim.pdf
--------------------------------------------------------------------------------
/docs/xsmp.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/xsmp.pdf
--------------------------------------------------------------------------------
/docs/xtest.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/xtest.pdf
--------------------------------------------------------------------------------
/docs/xtestlib.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/docs/xtestlib.pdf
--------------------------------------------------------------------------------
/keymap.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 |
3 | var lines = fs.readFileSync('keymap.txt', 'utf-8').split('\n');
4 |
5 |
6 | var keymap = [];
7 |
8 | var mods = ['shift', 'altgr', 'control', 'alt', 'shiftl', 'shiftr', 'ctrll', 'ctrlr', 'capsshift']
9 |
10 | function key_mapper (list) {
11 | return list.reduce(
12 | function (o, v) {
13 | return o | ((~mods.indexOf(v)) ? (1 << mods.indexOf(v)) : 0);
14 | }
15 | , 0
16 | )
17 | }
18 |
19 | lines.forEach(function (line) {
20 | if (/^\s+/.test(line))
21 | return;
22 | line = line.match(/^\s*((?:\s*?(?:\w+))*)\s*keycode\s+(\d+)\s+=\s+((?:(?:[\w+_\-]+)+\s*?)+)\s*$/);
23 | if (!line)
24 | return;
25 | var mods = line[1].replace(/\s+/g, ' ').split(' ')
26 | , code = line[2] * 1
27 | , maps = line[3].replace(/\s+/g, ' ').split(' ');
28 |
29 | var mapped = keymap[code] = keymap[code] || {};
30 |
31 | mapped[key_mapper(mods)] = maps[0];
32 | if (maps[1])
33 | mapped[key_mapper(mods.concat('shift'))] = maps[1];
34 | if (maps[2])
35 | mapped[key_mapper(mods.concat('altgr'))] = maps[2];
36 | if (maps[3])
37 | mapped[key_mapper(mods.concat('control'))] = maps[3];
38 |
39 | });
40 | console.log(JSON.stringify(keymap, null, 2));
41 | //console.log(keymap);
42 |
--------------------------------------------------------------------------------
/keymap.json:
--------------------------------------------------------------------------------
1 | [
2 | null,
3 | {
4 | "0": "Escape"
5 | },
6 | {
7 | "0": "one",
8 | "1": "exclam"
9 | },
10 | {
11 | "0": "two",
12 | "1": "quotedbl"
13 | },
14 | {
15 | "0": "three"
16 | },
17 | {
18 | "0": "four",
19 | "1": "dollar"
20 | },
21 | {
22 | "0": "five",
23 | "1": "percent"
24 | },
25 | {
26 | "0": "six",
27 | "1": "asciicircum"
28 | },
29 | {
30 | "0": "seven",
31 | "1": "ampersand",
32 | "2": "braceleft"
33 | },
34 | {
35 | "0": "eight",
36 | "1": "asterisk",
37 | "2": "bracketleft"
38 | },
39 | {
40 | "0": "nine",
41 | "1": "parenleft",
42 | "2": "bracketright"
43 | },
44 | {
45 | "0": "zero",
46 | "1": "parenright",
47 | "2": "braceright"
48 | },
49 | {
50 | "0": "minus",
51 | "1": "underscore",
52 | "2": "backslash"
53 | },
54 | {
55 | "0": "equal"
56 | },
57 | {
58 | "0": "Delete"
59 | },
60 | {
61 | "0": "Tab"
62 | },
63 | {
64 | "0": "+q",
65 | "1": "+Q",
66 | "2": "at"
67 | },
68 | {
69 | "0": "+w",
70 | "1": "+W"
71 | },
72 | {
73 | "0": "+e"
74 | },
75 | {
76 | "0": "+r",
77 | "1": "+R"
78 | },
79 | {
80 | "0": "+t",
81 | "1": "+T"
82 | },
83 | {
84 | "0": "+y",
85 | "1": "+Y"
86 | },
87 | {
88 | "0": "+u",
89 | "1": "+U"
90 | },
91 | {
92 | "0": "+i",
93 | "1": "+I"
94 | },
95 | {
96 | "0": "+o"
97 | },
98 | {
99 | "0": "+p"
100 | },
101 | {
102 | "0": "bracketleft"
103 | },
104 | {
105 | "0": "bracketright"
106 | },
107 | {
108 | "0": "Return"
109 | },
110 | {
111 | "0": "Control"
112 | },
113 | {
114 | "0": "+a"
115 | },
116 | {
117 | "0": "+s",
118 | "1": "+S",
119 | "2": "+ssharp"
120 | },
121 | {
122 | "0": "+d"
123 | },
124 | {
125 | "0": "+f",
126 | "1": "+F"
127 | },
128 | {
129 | "0": "+g",
130 | "1": "+G"
131 | },
132 | {
133 | "0": "+h",
134 | "1": "+H"
135 | },
136 | {
137 | "0": "+j",
138 | "1": "+J"
139 | },
140 | {
141 | "0": "+k",
142 | "1": "+K"
143 | },
144 | {
145 | "0": "+l",
146 | "1": "+L"
147 | },
148 | {
149 | "0": "semicolon"
150 | },
151 | {
152 | "0": "apostrophe"
153 | },
154 | {
155 | "0": "grave"
156 | },
157 | {
158 | "0": "Shift"
159 | },
160 | {
161 | "0": "numbersign"
162 | },
163 | {
164 | "0": "+z",
165 | "1": "+Z"
166 | },
167 | {
168 | "0": "+x",
169 | "1": "+X"
170 | },
171 | {
172 | "0": "+c",
173 | "1": "+C"
174 | },
175 | {
176 | "0": "+v",
177 | "1": "+V"
178 | },
179 | {
180 | "0": "+b",
181 | "1": "+B"
182 | },
183 | {
184 | "0": "+n"
185 | },
186 | {
187 | "0": "+m"
188 | },
189 | {
190 | "0": "comma",
191 | "1": "less"
192 | },
193 | {
194 | "0": "period",
195 | "1": "greater"
196 | },
197 | {
198 | "0": "slash",
199 | "1": "question"
200 | },
201 | {
202 | "0": "Shift"
203 | },
204 | {
205 | "0": "KP_Multiply"
206 | },
207 | {
208 | "0": "Alt"
209 | },
210 | {
211 | "0": "space"
212 | },
213 | {
214 | "0": "CtrlL_Lock"
215 | },
216 | {
217 | "0": "F1"
218 | },
219 | {
220 | "0": "F2"
221 | },
222 | {
223 | "0": "F3"
224 | },
225 | {
226 | "0": "F4"
227 | },
228 | {
229 | "0": "F5"
230 | },
231 | {
232 | "0": "F6"
233 | },
234 | {
235 | "0": "F7"
236 | },
237 | {
238 | "0": "F8"
239 | },
240 | {
241 | "0": "F9"
242 | },
243 | {
244 | "0": "F10"
245 | },
246 | {
247 | "0": "Num_Lock"
248 | },
249 | {
250 | "0": "Scroll_Lock"
251 | },
252 | {
253 | "0": "KP_7"
254 | },
255 | {
256 | "0": "KP_8"
257 | },
258 | {
259 | "0": "KP_9"
260 | },
261 | {
262 | "0": "KP_Subtract"
263 | },
264 | {
265 | "0": "KP_4"
266 | },
267 | {
268 | "0": "KP_5"
269 | },
270 | {
271 | "0": "KP_6"
272 | },
273 | {
274 | "0": "KP_Add"
275 | },
276 | {
277 | "0": "KP_1"
278 | },
279 | {
280 | "0": "KP_2"
281 | },
282 | {
283 | "0": "KP_3"
284 | },
285 | {
286 | "0": "KP_0"
287 | },
288 | {
289 | "0": "KP_Period"
290 | },
291 | {
292 | "0": "Last_Console",
293 | "1": "Last_Console",
294 | "2": "Last_Console"
295 | },
296 | null,
297 | {
298 | "0": "backslash",
299 | "1": "bar",
300 | "2": "bar"
301 | },
302 | {
303 | "0": "F11"
304 | },
305 | {
306 | "0": "F12"
307 | },
308 | null,
309 | null,
310 | null,
311 | null,
312 | null,
313 | null,
314 | null,
315 | {
316 | "0": "KP_Enter"
317 | },
318 | {
319 | "0": "Control"
320 | },
321 | {
322 | "0": "KP_Divide"
323 | },
324 | null,
325 | {
326 | "0": "AltGr"
327 | },
328 | {
329 | "0": "Break",
330 | "1": "Break",
331 | "2": "Break"
332 | },
333 | {
334 | "0": "Find"
335 | },
336 | {
337 | "0": "Up"
338 | },
339 | {
340 | "0": "Prior"
341 | },
342 | {
343 | "0": "Left"
344 | },
345 | {
346 | "0": "Right"
347 | },
348 | {
349 | "0": "Select"
350 | },
351 | {
352 | "0": "Down"
353 | },
354 | {
355 | "0": "Next"
356 | },
357 | {
358 | "0": "Insert"
359 | },
360 | {
361 | "0": "Remove"
362 | },
363 | {
364 | "0": "Macro",
365 | "1": "Macro",
366 | "2": "Macro"
367 | },
368 | {
369 | "0": "F13",
370 | "1": "F13",
371 | "2": "F13"
372 | },
373 | {
374 | "0": "F14",
375 | "1": "F14",
376 | "2": "F14"
377 | },
378 | {
379 | "0": "Help",
380 | "1": "Help",
381 | "2": "Help"
382 | },
383 | {
384 | "0": "Do",
385 | "1": "Do",
386 | "2": "Do"
387 | },
388 | {
389 | "0": "F17",
390 | "1": "F17",
391 | "2": "F17"
392 | },
393 | {
394 | "0": "KP_MinPlus",
395 | "1": "KP_MinPlus",
396 | "2": "KP_MinPlus"
397 | },
398 | {
399 | "0": "Pause"
400 | },
401 | null,
402 | {
403 | "0": "KP_Period"
404 | },
405 | null,
406 | null,
407 | null,
408 | {
409 | "0": "Alt"
410 | },
411 | {
412 | "0": "Alt"
413 | }
414 | ]
415 |
--------------------------------------------------------------------------------
/lib/fonts.js:
--------------------------------------------------------------------------------
1 | var Future = require('future')
2 | , path = require('path')
3 | , fs = require('fs');
4 |
5 | var app_dir = path.dirname(require.main.filename)
6 | , fonts_dir = path.join(app_dir, 'public', 'fonts');
7 |
8 | exports.list_fonts = function (filter) {
9 | var future = new Future;
10 | fs.readdir(fonts_dir, function (err, dir) {
11 | if (err)
12 | return future.deliver(err);
13 | if (filter)
14 | try {
15 | var re = new RegExp('^'+filter.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1").replace(/\\([*?])/g, '.$1')+'\..*$');
16 | dir = dir.filter(re.test.bind(re));
17 | } catch (e) {
18 | return future.deliver(e);
19 | }
20 | future.deliver(null, dir);
21 | });
22 | return future;
23 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xserver",
3 | "version": "0.0.1",
4 | "description": "Javascript X11 Server",
5 | "main": "proxy.js",
6 | "dependencies": {
7 | "async": "*",
8 | "express": "*",
9 | "future": "*",
10 | "ip-address": "*",
11 | "morgan": "*",
12 | "react": "*",
13 | "react-tools": "*",
14 | "requirejs": "*",
15 | "source-map-support": "^0.3.2",
16 | "supervisor": "*",
17 | "websocket": "*",
18 | "wolfy-eventemitter": "*"
19 | },
20 | "devDependencies": {
21 | "babel": "^5.8.23",
22 | "babel-runtime": "^5.8.25",
23 | "babelify": "^6.1.3",
24 | "browserify": "^11.2.0",
25 | "factor-bundle": "^2.5.0",
26 | "gulp": "^3.9.0",
27 | "gulp-insert": "^0.5.0",
28 | "gulp-rename": "^1.2.2",
29 | "gulp-sourcemaps": "^1.5.2",
30 | "gulp-util": "^3.0.6",
31 | "gulp-watch": "^4.2.4",
32 | "vinyl-buffer": "^1.0.0",
33 | "vinyl-source-stream": "^1.1.0",
34 | "vinyl-transform": "^1.0.0"
35 | },
36 | "scripts": {
37 | "test": "echo \"Error: no test specified\" && exit 1",
38 | "start": "supervisor -w proxy.js proxy",
39 | "cloc": "cloc --exclude-dir=node_modules,public/lib,fonts,public/fonts,public/xcb ."
40 | },
41 | "repository": {
42 | "type": "git",
43 | "url": "git://github.com/GothAck/javascript-x-server.git"
44 | },
45 | "keywords": [
46 | "x11"
47 | ],
48 | "author": "Greg Miell ",
49 | "license": "BSD-2-Clause",
50 | "gitHead": "b9e6f6729a00444ea0c4988bc33c51bee05f2041",
51 | "readmeFilename": "readme.md"
52 | }
53 |
--------------------------------------------------------------------------------
/proxy.js:
--------------------------------------------------------------------------------
1 | var express = require('express')
2 | , morgan = require('morgan')
3 | , http = require('http')
4 | , net = require('net')
5 | , WSS = require('websocket').server
6 | , child_process = require('child_process')
7 | , util = require('util')
8 | , EventEmitter = require('events').EventEmitter
9 | , ip = require('ip-address')
10 | , lib_fonts = require('./lib/fonts');
11 |
12 | var app = exports.app = express()
13 | // .use(morgan('combined'))
14 | .use(express.static(__dirname + '/public'));
15 |
16 | app.get('/fonts', function (req, res) {
17 | lib_fonts.list_fonts(req.query.filter)
18 | .when(function (err, fonts) {
19 | if (err)
20 | return res.send(500, err);
21 | res.send(fonts);
22 | });
23 | })
24 |
25 | var server = exports.server = http.createServer(app)
26 |
27 | if (require.main === module)
28 | server.listen(3000);
29 |
30 | var screens = [41];
31 |
32 | var wss = new WSS({
33 | httpServer: server
34 | , autoAcceptConnections: false
35 | });
36 |
37 | function X11Proxy (screen, connection, window_manager) {
38 | var self = this;
39 | this.screen = screen;
40 | this.connection = connection;
41 |
42 | this.id = ['family', 'address', 'port']
43 | .map(function (k) { return connection.socket._peername[k] })
44 | .join(':');
45 | this.client_sockets = {};
46 | this.ping = {
47 | counter: 0
48 | , interval: null
49 | , timeout: null
50 | , start: null
51 | , results: []
52 | , average: 0
53 | };
54 | this.processes = [];
55 | this.connection.on('message', this.data.bind(this));
56 | this.connection.on('close', this.close.bind(this));
57 | this.connection.sendUTF('SCR ' + this.screen);
58 | this.server_socket = net.createServer(this.newClient.bind(this)).listen(6000 + this.screen);
59 | if (window_manager)
60 | setTimeout(function () {
61 | self.spawnProcess(window_manager, []); //['-fn', 'cursor']);
62 | }, 750);
63 | }
64 | util.inherits(X11Proxy, EventEmitter);
65 | X11Proxy.prototype.newClient = function (socket) {
66 | var self = this
67 | , idBuf = new Buffer(19)
68 | , idStr;
69 | idBuf.fill(0);
70 | idBuf.writeUInt16BE(socket.remotePort, 16);
71 | if (net.isIPv4(socket.remoteAddress)) {
72 | idBuf.writeUInt8(4, 18);
73 | idBuf = socket.remoteAddress.split('.')
74 | .reduce(
75 | function (o, v, i) {
76 | o.writeUInt8(v, i);
77 | return o;
78 | }
79 | , idBuf
80 | );
81 | } else {
82 | idBuf.writeUInt8(6, 18);
83 | idBuf = (new ip.v6.Address(socket.remoteAddress)).parsedAddress
84 | .reduce(
85 | function (o, v, i) {
86 | o.writeUInt16BE(v, i * 2);
87 | return o;
88 | }
89 | , idBuf
90 | );
91 | }
92 | idStr = idBuf.toString('hex');
93 |
94 | this.client_sockets[idStr] = socket;
95 | this.connection.sendUTF('NEW ' + idStr);
96 | socket.on('close', function () {
97 | self.connection.sendUTF('END ' + idStr);
98 | delete self.client_sockets[idStr];
99 | });
100 | socket.on('data', function (data) {
101 | var buffer = new Buffer(data.length + 19);
102 | idBuf.copy(buffer, 0)
103 | data.copy(buffer, 19);
104 | self.connection.sendBytes(buffer);
105 | });
106 | }
107 | X11Proxy.prototype.data = function (message) {
108 | if (message.type === 'utf8') {
109 | var data = (message.utf8Data || '').split(' ');
110 | switch (data[0]) {
111 | case 'PONG':
112 | if (data[1] == this.ping.counter - 1) {
113 | this.ping.results.unshift(Date.now() - this.ping.start);
114 | this.ping.results.splice(10, 10);
115 | this.ping.average = this.ping.results.reduce(function (o, v) { return o + v }) / this.ping.results.length
116 | clearTimeout(this.ping.timeout);
117 | this.ping.timeout = null;
118 | } else {
119 | console.log('Out of order ping', data[1], this.ping.counter - 1);
120 | }
121 | break;
122 | }
123 | } else {
124 | var data = message.binaryData
125 | , length = data.readUInt8(0)
126 | , id = data.toString('ascii', 1, length + 1);
127 | if (this.client_sockets[id] && this.client_sockets[id].writable) {
128 | this.client_sockets[id].write(data.slice(length + 1));
129 | } else {
130 | console.error('Socket closed already', length, id);
131 | this.connection.sendUTF('END ' + id);
132 | }
133 | }
134 | }
135 | X11Proxy.prototype.close = function () {
136 | console.log('closed');
137 | clearTimeout(this.ping.timeout);
138 | clearInterval(this.ping.interval);
139 | this.processes.forEach(function (process) {
140 | process.kill();
141 | });
142 | Object.keys(this.client_sockets).forEach(function (id) {
143 | this.client_sockets[id].end();
144 | }, this);
145 | try {
146 | this.server_socket.close();
147 | } catch (e) {}
148 | screens.push(this.screen);
149 | }
150 | X11Proxy.prototype.spawnProcess = function (command, arguments) {
151 | var env = {}
152 | , prefix
153 | , child;
154 | Object.keys(process.env)
155 | .forEach(function (k) {
156 | env[k] = process.env[k];
157 | });
158 | env.DISPLAY = 'localhost:' + this.screen;
159 | this.processes.push(
160 | child = child_process.spawn(command, arguments || [], { env: env })
161 | );
162 | prefix = [this.id, child.pid, command, ': \t'].join(' ');
163 | function handleOutput (data) {
164 | console.log(prefix, data.toString().replace('\n', '\n' + prefix + ' '));
165 | }
166 | child.stdout.on('data', handleOutput);
167 | child.stderr.on('data', handleOutput);
168 | }
169 |
170 | wss.on('request', function (req) {
171 | var screen = screens.shift();
172 |
173 | if (!(req.origin && screen)) {
174 | console.log('reject');
175 | return req.reject();
176 | }
177 | console.log('New client');
178 | var proxy = new X11Proxy(screen, req.accept('x11-proxy', req.origin), 'xeyes'); //, 'blackbox' Don't load blackbox by default
179 | /*
180 | ping_interval = setInterval(function () {
181 | var counter = ping_counter ++;
182 | con.sendUTF('PING ' + counter);
183 | ping_start = Date.now();
184 | ping_timeout = setTimeout(function () {
185 | console.log('Ping timeout', counter);
186 | ping_timeout = null;
187 | }, 500);
188 | }, 5000);
189 | */
190 | });
191 |
192 |
--------------------------------------------------------------------------------
/public/audio/bell.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/public/audio/bell.mp3
--------------------------------------------------------------------------------
/public/check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GothAck/javascript-x-server/23f5118db68ec99d19189a8fc57e5d5b8e7a9ed0/public/check.png
--------------------------------------------------------------------------------
/public/fonts:
--------------------------------------------------------------------------------
1 | ../fonts/out
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | X Session
5 |
6 |
7 |
42 |
43 |
44 |
45 |
46 |
52 |
53 |
56 |
57 |
76 |
77 |
78 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/public/require.config.js:
--------------------------------------------------------------------------------
1 | requirejs.config({
2 | baseUrl: 'modules',
3 | paths: {
4 | site: '../site',
5 | lib: '../lib'
6 | },
7 | shim: {
8 | 'lib/jsbn-combined': {
9 | exports: 'BigInteger'
10 | }
11 | , 'lib/sprintf': {
12 | exports: 'sprintf'
13 | }
14 | , 'lib/ipv6': {
15 | deps: ['lib/jsbn-combined', 'lib/sprintf']
16 | , exports: 'v6'
17 | }
18 | }
19 | })
20 |
--------------------------------------------------------------------------------
/public/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html, body, div, span, applet, object, iframe,
7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8 | a, abbr, acronym, address, big, cite, code,
9 | del, dfn, em, img, ins, kbd, q, s, samp,
10 | small, strike, strong, sub, sup, tt, var,
11 | b, u, i, center,
12 | dl, dt, dd, ol, ul, li,
13 | fieldset, form, label, legend,
14 | table, caption, tbody, tfoot, thead, tr, th, td,
15 | article, aside, canvas, details, embed,
16 | figure, figcaption, footer, header, hgroup,
17 | menu, nav, output, ruby, section, summary,
18 | time, mark, audio, video {
19 | margin: 0;
20 | padding: 0;
21 | border: 0;
22 | font-size: 100%;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 | /* HTML5 display-role reset for older browsers */
27 | article, aside, details, figcaption, figure,
28 | footer, header, hgroup, menu, nav, section {
29 | display: block;
30 | }
31 | body {
32 | line-height: 1;
33 | }
34 | ol, ul {
35 | list-style: none;
36 | }
37 | blockquote, q {
38 | quotes: none;
39 | }
40 | blockquote:before, blockquote:after,
41 | q:before, q:after {
42 | content: '';
43 | content: none;
44 | }
45 | table {
46 | border-collapse: collapse;
47 | border-spacing: 0;
48 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # JavaScript X Server
2 |
3 | ## Concept
4 |
5 | ### Now
6 |
7 | This is currently very much a work in progress, with me learning about how an X11 server operates and it's underlying protocol.
8 | A subset of the protocol is now working within Chromium with output to canvas and div elements.
9 | Both xlogo and xeyes are 100% functional, with work currently being done to support xfn (with bitmap fonts)!
10 |
11 | ### Future
12 |
13 | The project may eventually have both server and client side X processing,
14 | allowing for optimisation of the X protocol and compression of Pixmaps before transferring to the client allowing
15 | for lightweight remote desktop connections in a web browser.
16 |
17 | It'd also be great to experiement with GLX and WebGL to see if there is enough crossover to allow 3d rendering via the browser!
18 |
19 | ## Loose Requirements
20 | * A basic window manager or application (we're talking blackbox wm, xlogo, xeyes, xfd, more complex apps are more likely to hit bugs / unknown features / unimplemented opcodes).
21 | * Developed on Mac, but should also work on Ilnux boxes
22 |
23 | ## Getting started
24 | 1. `git clone https://github.com/GothAck/javascript-x-server.git xserver; cd xserver`
25 | 2. `npm install`
26 | 3. Edit proxy.js:
27 |
28 | Change line:
29 |
30 | ` var proxy = new X11Proxy(screen, req.accept('x11-proxy', req.origin));`
31 |
32 | To contain the desired wm/application:
33 |
34 | ` var proxy = new X11Proxy(screen, req.accept('x11-proxy', req.origin), 'xeyes');`
35 | 4. In one terminal: `grunt; grunt watch` (you can just run `grunt`)
36 | 5. In another: `npm start`
37 | 6. Open http://localhost:3000 in a decent browser (currently only Chrome is tested working)
38 |
--------------------------------------------------------------------------------
/rgb.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 |
3 | var rgbs = fs.readFileSync('rgb.txt', 'ascii');
4 | rgbs = rgbs.split('\n').reduce(function (obj, line) {
5 | if (/^[!#]/.test(line))
6 | return obj;
7 | var vals = line.match(/^(\d+)\s+(\d+)\s+(\d+)\s+([\w\s]+)$/);
8 | if (! vals)
9 | return obj;
10 | obj[vals[4]] = ((vals[1] ^ 0) << 16) | ((vals[2] ^ 0) << 8) | (vals[3] ^ 0);
11 | return obj;
12 | }, {});
13 |
14 | fs.writeFileSync(
15 | 'public/rgb_colors.js'
16 | , '(function (module) {\n'
17 | + ' module.exports.rgb_colors = ' + JSON.stringify(rgbs, null, 2)
18 | + '})({ exports: window });'
19 | );
20 |
21 | console.log(rgbs);
22 |
--------------------------------------------------------------------------------
/src/common.js:
--------------------------------------------------------------------------------
1 | var useCaptureStackTrace = !!Error.captureStackStace;
2 |
3 | import type EndianBuffer from './endianbuffer';
4 |
5 | export class MustImplementError extends Error {
6 | constructor(cls, method) {
7 | super(`Subclasses of ${cls} must implement ${method}`);
8 | useCaptureStackTrace && Error.captureStackStace(this, MustImplementError);
9 | }
10 | }
11 |
12 | export class MaskedField extends Map {
13 | static fields: Map;
14 | static default_type: string = 'UInt32';
15 | static type_lengths: Map = new Map([
16 | ['UInt8', 1],
17 | ['UInt16', 2],
18 | ['UInt32', 4],
19 | ['Int8', 1],
20 | ['Int16', 2],
21 | ['Int32', 4],
22 | ]);
23 |
24 | constructor(vmask: Number, vdata?: EndianBuffer) {
25 | super();
26 | if (vmask === 0) {
27 | return;
28 | }
29 | var fields = this.constructor.fields;
30 | var default_type = this.constructor.default_type;
31 | var type_lengths = this.constructor.type_lengths;
32 | var i = 0;
33 | var offset = 0;
34 | for (let [k, v] of fields) {
35 | if (vmask & (2 ** i)) {
36 | let type = v || default_type;
37 | let value = vdata['readUInt32'](offset);
38 | this.set(k, value);
39 | offset += 4; // type_lengths.get(type);
40 | }
41 | i++;
42 | }
43 | }
44 |
45 | writeBuffer(buffer: EndianBuffer, offset?: number) {
46 | var fields = this.constructor.fields;
47 | var default_type = this.constructor.default_type;
48 | var type_lengths = this.constructor.type_lengths;
49 | var vmask = 0;
50 | for (let [k, v] of this.map) {
51 | let type = fields.get(k) || default_type;
52 | buffer['write' + type](v, offset);
53 | offset += type_lengths.get(type);
54 | }
55 | }
56 |
57 | toMap() {
58 | return new Map(this);
59 | }
60 |
61 | toObject() {
62 | var o = {};
63 | for (let [k, v] of this) {
64 | o[k] = v;
65 | }
66 | return o;
67 | }
68 |
69 | static fromMap(map) {
70 | var mf = new this(0);
71 | for (let [k, _] of this.fields) {
72 | if (map.has(k)) {
73 | mf.set(k, map.get(k));
74 | }
75 | }
76 | return mf;
77 | }
78 |
79 | static fromObject(o) {
80 | if (o instanceof Map) {
81 | return this.fromMap(o);
82 | }
83 | var mf = new this(0);
84 | if (o) {
85 | for (let [k, _] of this.fields) {
86 | if (o.hasOwnProperty(k)) {
87 | mf.set(k, o[k]);
88 | }
89 | }
90 | }
91 | return mf;
92 | }
93 |
94 | static getFieldNames(vmask: Number): Array {
95 | var names = [];
96 | var fields = this.fields;
97 | var i = 0;
98 | for (let [k, v] of fields) {
99 | if (vmask & Math.pow(2, i)) {
100 | names.push(k);
101 | }
102 | }
103 | return names;
104 | }
105 | }
106 |
107 | export class GCVField extends MaskedField {
108 | static fields = new Map([
109 | 'function', 'plane_mask', 'foreground' , 'background', 'line_width',
110 | 'line_style', 'cap_style', 'join_style', 'fill_style', 'fill_rule',
111 | 'tile', 'stipple', 'tile_stipple_x_origin', 'tile_stipple_y_origin', 'font',
112 | 'subwindow_mode', 'graphics_exposures', 'clip_x_origin', 'clip_y_origin',
113 | 'clip_mask', 'dash_offset', 'gc_dashes', 'arc_mode'
114 | ].map((v) => [v]));
115 | }
116 |
117 | export class WinVField extends MaskedField {
118 | static fields = new Map([
119 | ['background_pixmap', 'UInt32'],
120 | ['background_pixel', 'UInt32'],
121 | ['border_pixmap', 'UInt32'],
122 | ['border_pixel', 'UInt32'],
123 | ['bit_gravity', 'UInt8' ],
124 | ['win_gravity', 'UInt8' ],
125 | ['backing_store', 'UInt8' ],
126 | ['backing_planes', 'UInt32'],
127 | ['backing_pixel', 'UInt32'],
128 | ['override_redirect', 'UInt8' ],
129 | ['save_under', 'UInt8' ],
130 | ['event_mask', 'UInt32'],
131 | ['do_not_propagate_mask', 'UInt32'],
132 | ['colormap', 'UInt32'],
133 | ['cursor', 'UInt32'],
134 | ]);
135 | }
136 |
137 | export class WinConfigureField extends MaskedField {
138 | static fields = new Map(
139 | ['x', 'y', 'width', 'height', 'border_width', 'sibling', 'stack_mode']
140 | .map((v) => [v])
141 | );
142 | }
143 |
144 | export function* yieldAll(...generators) {
145 | for (var gen of generators) {
146 | yield* gen;
147 | }
148 | }
149 |
150 | export class ArrayMap extends Map> {
151 | set(key: K, value: Array): void {
152 | throw new Error('set is not callable on ArrayMap')
153 | }
154 |
155 | addTo(key: K, value: V): self {
156 | if (!this.has(key)) {
157 | super.set(key, []);
158 | }
159 | this.get(key).push(value);
160 | return this;
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/elements.js:
--------------------------------------------------------------------------------
1 | import * as x_types from "./x_types";
2 |
3 | var x11_dom_event_map = new Map((
4 | for (p of x_types.events.map.values())
5 | if (p.dom_event)
6 | [p.dom_event, p]));
7 |
8 | function _HTMLDivElement() {}
9 | _HTMLDivElement.prototype = HTMLDivElement.prototype;
10 |
11 | export class XDrawableElement extends _HTMLDivElement {
12 | createElement(name, props, style) {
13 | var elem = document.createElement(name);
14 | if (props) {
15 | for (let k in props) {
16 | elem[k] = props[k];
17 | }
18 | }
19 | if (style) {
20 | for (let k in style) {
21 | elem.style[k] = style[k];
22 | }
23 | }
24 | return elem;
25 | }
26 | createdCallback() {
27 | var shadow = this.createShadowRoot();
28 | this.canvas = this.createElement('canvas');
29 | shadow.appendChild(this.canvas);
30 | shadow.appendChild(
31 | document.importNode(
32 | document.getElementById('x-drawable-style').content, true));
33 | }
34 | attributeChangedCallback(name, oldVal, newVal) {
35 | switch (name) {
36 | case 'width':
37 | this.canvas.width = newVal;
38 | this.style.width = newVal + 'px';
39 | break;
40 | case 'height':
41 | this.canvas.height = newVal;
42 | this.style.height = newVal + 'px';
43 | break;
44 | }
45 | }
46 | }
47 |
48 | var mouse_buttons = [1,3,2];
49 | var events = [
50 | 'blur',
51 | 'focus',
52 | 'focusin',
53 | 'focusout',
54 | 'load',
55 | 'resize',
56 | 'scroll',
57 | 'unload',
58 | 'click',
59 | 'dblclick',
60 | 'mousedown',
61 | 'mouseup',
62 | 'mousemove',
63 | 'mouseover',
64 | 'mouseout',
65 | 'mouseenter',
66 | 'mouseleave',
67 | 'change',
68 | 'select',
69 | 'submit',
70 | 'keydown',
71 | 'keypress',
72 | 'keyup',
73 | 'error'
74 | ];
75 |
76 | export class XWindowElement extends XDrawableElement {
77 | getCustomEventData(dom_event) {
78 | var server = this.xob.owner.server;
79 | var keybutmask = (
80 | (server && server.buttons || 0) |
81 | // (
82 | // dom_event.type === 'mousedown' &&
83 | // (1 << (mouse_buttons[dom_event.button] - 1))
84 | // )
85 | 0
86 | ) << 8;
87 | if (dom_event.type === 'mousedown' || dom_event.type === 'mouseup') {
88 | keybutmask |= 0x10;
89 | keybutmask &= ~((1 << (mouse_buttons[dom_event.button] - 1)) << 8);
90 | }
91 | // keybutmask |= dom_event.shiftKey && 1;
92 | // lock? = 2
93 | // keybutmask |= dom_event.ctrlKey && 4;
94 |
95 | return {
96 | x: dom_event.offsetX
97 | , y: dom_event.offsetY
98 | , root_x: dom_event.offsetX
99 | , root_y: dom_event.offsetY
100 | , button: mouse_buttons[dom_event.button]
101 | , keycode: dom_event.keyCode
102 | , keybutmask: keybutmask
103 | };
104 | }
105 | browserEventCallback(event) {
106 | var X11Event = x_types.events.dom_event_to_x11_map.get(event.type);
107 | if (X11Event) {
108 | var src = this;
109 | var window = this.xob;
110 | if (event.type === 'mouseover') {
111 | this.classList.add('hover');
112 | }
113 | if (event.type === 'mouseout') {
114 | this.classList.remove('hover');
115 | }
116 | var x11_event = new X11Event(window, this.getCustomEventData(event))
117 | window.triggerEvent(x11_event);
118 | event.stopPropagation();
119 | }
120 | }
121 | createdCallback() {
122 | super.createdCallback();
123 | if (!this.void_events) {
124 | for (let event of events) {
125 | this.addEventListener(event, (e) => this.browserEventCallback(e));
126 | }
127 | this.addEventListener('SendMask', (e) => {
128 | var xob = this.xob;
129 | var event_mask = e.detail.event_mask;
130 | var x_event = e.detail.event;
131 | if ((xob.event_mask && event_mask) || ! event_mask) {
132 | x_event.event_window = xob;
133 | xob.onEvent('SendEvent', x_event);
134 | e.stopPropagation();
135 | }
136 | });
137 | }
138 | this.style.display = 'none';
139 | this.addEventListener('contextmenu', (e) => {
140 | e.stopPropagation();
141 | e.preventDefault();
142 | });
143 | var shadow = this.createShadowRoot();
144 | var relative = this.createElement('div', {className: 'relative'})
145 | this.container = this.createElement('div', {className: 'container'});
146 |
147 | shadow.appendChild(
148 | document.importNode(
149 | document.getElementById('x-window-style').content, true));
150 |
151 | shadow.appendChild(this.container);
152 | this.container.appendChild(relative);
153 | relative.appendChild(this.createElement('shadow'));
154 | relative.appendChild(this.createElement('content'));
155 | }
156 | attributeChangedCallback(name, oldVal, newVal) {
157 | super.attributeChangedCallback(name, oldVal, newVal);
158 | switch (name) {
159 | case 'width':
160 | this.container.style.width = newVal + 'px';
161 | break;
162 | case 'height':
163 | this.container.style.height = newVal + 'px';
164 | break;
165 | case 'mapped':
166 | if (newVal) {
167 | this.style.display = 'block';
168 | } else {
169 | this.style.display = 'none';
170 | }
171 | }
172 | }
173 | collidesWith(...elems) {
174 | var res = [];
175 | for (let elem of elems) {
176 | if (elem.tagName !== this.tagName) {
177 | throw new Error('x-window.collidesWith must take another x-window elem');
178 | }
179 | var t_br = this.getBoundingClientRect();
180 | var e_br = elem.getBoundingClientRect();
181 | if (
182 | (t_br.left > e_br.right || e_br.left > t_br.right) ||
183 | (t_br.top < e_br.bottom || e_br.top < t_br.bottom)
184 | ) {
185 | continue;
186 | }
187 | res.push(elem);
188 | }
189 | if (res.length) {
190 | return res;
191 | }
192 | return false;
193 | }
194 | *genPreviousSiblings() {
195 | var elem = this
196 | while (elem = elem.previousSibling) {
197 | yield elem;
198 | }
199 | }
200 | *genNextSiblings() {
201 | var elem = this
202 | while (elem = elem.nextSibling) {
203 | yield elem;
204 | }
205 | }
206 | *genSiblings() {
207 | yield* this.genNextSiblings();
208 | yield* this.genPreviousSiblings();
209 | }
210 | hasPrevSibling(...siblings) {
211 | for (let elem of this.genPreviousSiblings()) {
212 | if (siblings.includes(elem)) {
213 | return true;
214 | }
215 | }
216 | return false;
217 | }
218 | hasNextSibling(...siblings) {
219 | for (let elem of this.genNextSiblings()) {
220 | if (siblings.includes(elem)) {
221 | return true;
222 | }
223 | }
224 | return false;
225 | }
226 | prependChild(elem) {
227 | if (this.childNodes.length) {
228 | this.insertBefore(elem, this.childNodes[0]);
229 | } else {
230 | this.appendChild(elem);
231 | }
232 | }
233 | insertAfter(elem, after) {
234 | if (after.nextSibling) {
235 | this.insertBefore(elem, after.nextSibling);
236 | } else {
237 | this.appendChild(elem);
238 | }
239 | }
240 | }
241 |
242 | export class XScreenElement extends XWindowElement {
243 | createdCallback() {
244 | this.void_events = true;
245 | super.createdCallback();
246 | this.addEventListener('mousedown', (e) => {
247 | this.xob.owner.buttons |= 1 << (mouse_buttons[e.button] - 1);
248 | }, true);
249 | this.addEventListener('mouseup', (e) => {
250 | this.xob.owner.buttons &= ~ (1 << (mouse_buttons[e.button] - 1));
251 | }, true);
252 | this.addEventListener('mousemove', (e) => {
253 | this.xob.owner.mouseX = e.offsetX;
254 | this.xob.owner.mouseY = e.offsetY;
255 | }, true);
256 | for (let [name, XEvent] of x_types.events.x11_events_map) {
257 | if (XEvent.grab) {
258 | this.addEventListener(
259 | name,
260 | (event) => this.xob.owner.screenEvent(event, true),
261 | true);
262 | // this.addEventListener(
263 | // name,
264 | // (event) => this.xob.owner.screenEvent(event));
265 | }
266 | }
267 | this.setAttribute('mapped', true);
268 |
269 | }
270 | }
271 |
272 | export function register() {
273 | document.registerElement(
274 | 'x-drawable', {prototype: XDrawableElement.prototype});
275 | document.registerElement(
276 | 'x-window', {prototype: XWindowElement.prototype});
277 | document.registerElement(
278 | 'x-screen', {prototype: XScreenElement.prototype});
279 | }
280 |
--------------------------------------------------------------------------------
/src/endianbuffer.js:
--------------------------------------------------------------------------------
1 | export default class EndianBuffer {
2 | constructor(buf) {
3 | this.endian = false;
4 | if (typeof buf === 'number') {
5 | this.buffer = new ArrayBuffer(buf);
6 | } else if (buf instanceof ArrayBuffer) {
7 | this.buffer = buf;
8 | } else if (buf instanceof EndianBuffer) {
9 | this.buffer = new ArrayBuffer(buf.length);
10 | buf.copy(this);
11 | } else if (typeof buf === 'string') {
12 | this.buffer = new ArrayBuffer(buf.length / 2);
13 | }
14 | this.dataview = new DataView(this.buffer, 0);
15 | if (typeof buf === 'string')
16 | for (var i = 0; i < buf.length; i += 2)
17 | this.writeUInt8(parseInt(buf.slice(i, i + 2), 16), i / 2);
18 | }
19 |
20 | get length() {
21 | return this.buffer.byteLength;
22 | }
23 |
24 | copy(buffer, t_start, s_start, s_end) {
25 | t_start = t_start || 0;
26 | s_start = s_start || 0;
27 | s_end = s_end || Math.min(this.length, buffer.length);
28 | var length = s_end - s_start
29 | , src_arr = new Uint8Array(this.buffer, s_start, length)
30 | , dst_arr = new Uint8Array(buffer.buffer, t_start, length)
31 | dst_arr.set(src_arr);
32 | return length;
33 | }
34 |
35 | slice(start, end) {
36 | start = start || 0;
37 | end = end || this.length;
38 | var newb = new (this.constructor)(this.buffer.slice(start, end));
39 | newb.endian = this.endian;
40 | return newb;
41 | }
42 |
43 | toString(type, from, to) {
44 | switch (type) {
45 | case 'ascii':
46 | if ((!from) || (!to) || (to - from > 2000))
47 | console.log('break');
48 | var arr = new Uint8Array(this.buffer.slice(from, to))
49 | , str = '';
50 | for (var i = 0; i < arr.length; i++)
51 | str += String.fromCharCode(arr[i]);
52 | return str;
53 | case '2charb':
54 | if (((to - from) ^ 2) !== 0)
55 | throw new Error('String length should be multiple of two!');
56 | var arr = new Uint8Array(this.buffer.slice(from, to))
57 | , str = '';
58 | for (var i = 0; i < arr.length; i += 2)
59 | str += String.fromCharCode( (arr[i * 2] << 8) + arr[(i * 2) + 1] );
60 | return str;
61 | case 'hex':
62 | var arr = new Uint8Array(this.buffer.slice(from, to))
63 | , str = '';
64 | for (var i = 0; i < arr.length; i++)
65 | str += (arr[i] < 16 ? '0' : '') + arr[i].toString(16);
66 | return str;
67 | default:
68 | return null;
69 | }
70 | }
71 |
72 | write(string, offset, length, encoding) {
73 | offset = offset || 0;
74 | if (length === null)
75 | length = Infinity;
76 | length = Math.min(string.length, (this.buffer.byteLength - offset), length);
77 | encoding = encoding || 'ascii';
78 | if (encoding !== 'ascii')
79 | throw new Error('Only ascii implemented');
80 | var arr = new Uint8Array(this.buffer, offset, length);
81 | for (var i = 0; i < length; i ++)
82 | arr[i] = string.charCodeAt(i);
83 | return length;
84 | }
85 |
86 | fill(value, start, end) {
87 | value = value || 0;
88 | start = start || 0;
89 | end = end || 0;
90 | var arr = new Uint8Array(this.buffer, start, end - start);
91 | for (var i = 0; i < arr.length; i++)
92 | arr[i] = value;
93 | }
94 |
95 | static ensure(obj_arr) {
96 | var Constructor = this;
97 | if (Array.isArray(obj_arr)) {
98 | obj_arr.forEach(function (v, i, a) {
99 | if (v instanceof ArrayBuffer)
100 | a[i] = new Constructor(v);
101 | });
102 | } else {
103 | var a = obj_arr;
104 | Object.keys(obj_arr).forEach(function (i) {
105 | var v = obj_arr[i];
106 | if (v instanceof ArrayBuffer)
107 | a[i] = new Constructor(v);
108 | });
109 | }
110 | }
111 | }
112 |
113 | ;(function (EndianBuffer) {
114 | var keys = ['Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Float32', 'Float64'];
115 | keys.forEach(function (key) {
116 | EndianBuffer.prototype['read' + key.replace('int', 'Int')] = function (offset) {
117 | return this.dataview['get' + key](offset, this.endian)
118 | }
119 | EndianBuffer.prototype['write' + key.replace('int', 'Int')] = function (value, offset) {
120 | return this.dataview['set' + key](offset, value, this.endian)
121 | }
122 | });
123 | })(EndianBuffer);
124 |
125 |
126 | export class CursorBuffer extends EndianBuffer {
127 | static lengths = new Map([
128 | ['Int8', 1], ['Uint8', 1],
129 | ['Int16', 2], ['Uint16', 2],
130 | ['Int32', 4], ['Uint32', 4],
131 | ['Float32', 4], ['Float64', 8],
132 | ]);
133 |
134 | constructor(buf) {
135 | super(buf);
136 | this.cursor = 0;
137 | }
138 |
139 | moveCursor(by) {
140 | this.cursor += by;
141 | }
142 | }
143 |
144 | ;(function (CursorBuffer) {
145 | var keys = ['Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Float32', 'Float64'];
146 | CursorBuffer.lengths.forEach(function (key_length, key) {
147 | CursorBuffer.prototype['read' + key.replace('int', 'Int')] = function (offset) {
148 | var val = this.dataview['get' + key](this.cursor, this.endian);
149 | this.moveCursor(key_length);
150 | return val;
151 | }
152 | CursorBuffer.prototype['write' + key.replace('int', 'Int')] = function (value, offset) {
153 | this.dataview['set' + key](this.cursor, value, this.endian);
154 | this.moveCursor(key_length);
155 | }
156 | });
157 | })(CursorBuffer);
158 |
159 | class Enum extends Set {
160 | static _values: Map = new Map();
161 | _decoded: boolean = false;
162 |
163 | constructor(values?: ?Iterable