Compare commits

..

No commits in common. "master" and "1.0.2" have entirely different histories.

62 changed files with 1919 additions and 5481 deletions

4
.gitignore vendored
View file

@ -1,4 +0,0 @@
*.log
yarn.lock
package-lock.json
node_modules

View file

@ -1,16 +1,7 @@
before_script:
- "export XAUTHORITY=/tmp/.Xauthority-Xvfb"
- "xauth add :99 . $(mcookie)"
- "xauth add 127.0.0.2:99 . $(mcookie)"
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -nolisten $NOLISTEN -auth $XAUTHORITY"
- "sleep 1"
env:
- NOLISTEN=tcp DISPLAY=:99.0
# - NOLISTEN=unix DISPLAY=:99.0
# - NOLISTEN=unix DISPLAY=127.0.0.2:99.0
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
language: node_js
node_js:
- '12'
- '14'
- 0.10

View file

@ -1,2 +0,0 @@
1.0.3 - 19/02/2015
- cleanup debug logs #83

169
README.md
View file

@ -1,119 +1,92 @@
# node-x11
# About
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/sidorares/node-x11?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
X11 protocol client for node.js
X11 protocol client for Node.js: implements the core X11 protocol, as well as Xrender, Damage, Composite, Big-Requests, Dpms, Screensaver, XFixes, Shape, XTest, XC-Misc, GLX, and Apple-WM extensions.
Implements core X11 protocol, as well as Xrender, Damage, Composite, Big-Requests, Dpms, Screensaver, XFixes, Shape, XTest, XC-Misc, GLX and Apple-WM extensions.
# install
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sidorares/node-x11?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://secure.travis-ci.org/sidorares/node-x11.png)](http://travis-ci.org/sidorares/node-x11)
## Install
npm install x11
`npm install x11`
Windows users:
1) install [XMing](http://www.straightrunning.com/XmingNotes/) or [Cygwin/X](http://x.cygwin.com/)
2) get node-x11 copy (using [git](http://code.google.com/p/msysgit/downloads/list?can=3) or from [Github](https://github.com/sidorares/node-x11/archives/master ))
1. install [XMing](http://www.straightrunning.com/XmingNotes/) or [Cygwin/X](http://x.cygwin.com/)
2. get node-x11 copy (using [git](http://code.google.com/p/msysgit/downloads/list?can=3) or from [Github](https://github.com/sidorares/node-x11/archives/master))
#CI build status:
## Example
[![Build Status](https://secure.travis-ci.org/sidorares/node-x11.png)](http://travis-ci.org/sidorares/node-x11)
# example
Core requests usage:
```js
var x11 = require('x11');
var x11 = require('x11');
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
x11.createClient(function(err, display) {
if (!err) {
var X = display.client;
var root = display.screen[0].root;
var wid = X.AllocID();
X.CreateWindow(
wid,
root, // new window id, parent
0,
0,
500,
500, // x, y, w, h
0,
0,
0,
0, // border, depth, class, visual
{ eventMask: Exposure | PointerMotion } // other parameters
);
X.MapWindow(wid);
var gc = X.AllocID();
X.CreateGC(gc, wid);
var white = display.screen[0].white_pixel;
var black = display.screen[0].black_pixel;
cidBlack = X.AllocID();
cidWhite = X.AllocID();
X.CreateGC(cidBlack, wid, { foreground: black, background: white });
X.CreateGC(cidWhite, wid, { foreground: white, background: black });
X.on('event', function(ev) {
if (ev.type == 12) {
X.PolyFillRectangle(wid, cidWhite, [0, 0, 500, 500]);
X.PolyText8(wid, cidBlack, 50, 50, ['Hello, Node.JS!']);
}
x11.createClient(function(err, display) {
if (!err) {
var X = display.client;
var root = display.screen[0].root;
var wid = X.AllocID();
X.CreateWindow(
wid, root, // new window id, parent
0, 0, 100, 100, // x, y, w, h
0, 0, 0, 0, // border, depth, class, visual
{ eventMask: Exposure|PointerMotion } // other parameters
);
X.MapWindow(wid);
var gc = X.AllocID();
X.CreateGC(gc, wid);
X.on('event', function(ev) {
if (ev.type == 12)
{
X.PolyText8(wid, gc, 50, 50, ['Hello, Node.JS!']);
}
});
X.on('error', function(e) {
console.log(e);
});
} else {
console.log(err);
}
});
X.on('error', function(e) {
console.log(e);
});
} else {
console.log(err);
}
});
```
## Screenshots
# Screenshots
![tetris game](https://lh6.googleusercontent.com/-RCRY9A7WwnA/Tlww0FHP7NI/AAAAAAAAAwo/nxfSxsw6xow/s400/tetris.png)
![XRENDER gradients](https://lh4.googleusercontent.com/-VS0BMYYmq6M/Tlww0Y1ij0I/AAAAAAAAAws/pVWsPZ63Yeo/s400/render-gradients.png)
![OpenGL glxgears](http://img-fotki.yandex.ru/get/4123/37511094.30/0_81712_6c2ebb11_L)
![OpenGL teapot](http://img-fotki.yandex.ru/get/4132/37511094.30/0_81713_82a5ac48_L)
![tetris game](https://lh6.googleusercontent.com/-RCRY9A7WwnA/Tlww0FHP7NI/AAAAAAAAAwo/nxfSxsw6xow/s400/tetris.png)
![XRENDER gradients](https://lh4.googleusercontent.com/-VS0BMYYmq6M/Tlww0Y1ij0I/AAAAAAAAAws/pVWsPZ63Yeo/s400/render-gradients.png)
![OpenGL glxgears](http://img-fotki.yandex.ru/get/4123/37511094.30/0_81712_6c2ebb11_L)
![OpenGL teapot](http://img-fotki.yandex.ru/get/4132/37511094.30/0_81713_82a5ac48_L)
## In use
# In use
- [ntk](https://github.com/sidorares/ntk) - higher level toolkit on top of X11
- [node-remote](https://github.com/AndrewSwerlick/node-remote) - metia center controller
- [tiles](https://github.com/dominictarr/tiles) - tiling window manager
- [vnc](https://github.com/sidorares/node-vnc) - vnc client.
- [node-ewmh](https://github.com/santigimeno/node-ewmh) - set of EWMH helpers.
- [OdieWM](https://github.com/bu/OdieWM) - window manager
- [Dbusmenu](https://github.com/sidorares/node-dbusmenu) - unity global menu client.
- [ntk](https://github.com/sidorares/ntk) - higher level toolkit on top of X11
- [node-remote](https://github.com/AndrewSwerlick/node-remote) - media center controller
- [tiles](https://github.com/dominictarr/tiles) - tiling window manager
- [vnc](https://github.com/sidorares/node-vnc) - vnc client.
- [node-ewmh](https://github.com/santigimeno/node-ewmh) - set of EWMH helpers.
- [OdieWM](https://github.com/bu/OdieWM) - window manager
- [Dbusmenu](https://github.com/sidorares/node-dbusmenu) - unity global menu client.
- [AirWM](https://github.com/AirWM/AirWM) - tiling window manager
- [npdf](https://github.com/sidorares/npdf) - pdf viewer
- [tinywm](https://github.com/Airblader/node-tinywm) The famous [TinyWM](https://github.com/mackstann/tinywm) written in node.js
- [basedwm](https://github.com/anko/basedwm) Infinite-desktop panning X window manager in LiveScript
# Protocol documentation
## X11 resources/documentation:
- http://www.x.org/releases/X11R7.6/doc/
- http://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.pdf
- C Xlib to X11 request mapping table http://tronche.com/gui/x/xlib/appendix/a.html
- [Xplain](https://github.com/magcius/xplain) - A series of articles to help explain the X Window System http://magcius.github.io/xplain/article/
- [Official X11 docs](http://www.x.org/releases/X11R7.6/doc/)
- [protocol specification](http://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.pdf)
- C Xlib to X11 request mapping table http://tronche.com/gui/x/xlib/appendix/a.html
- [How to write composite manager](http://www.talisman.org/~erlkonig/misc/x11-composite-tutorial/)
- [Extended Window Manager Hints specification](http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html)
# Other implementations
## Other implementations
- C: XLib - http://www.sbin.org/doc/Xlib/ http://www.tronche.com/gui/x/xlib/ http://www.x.org/docs/X11/xlib.pdf
- C: XCB - http://xcb.freedesktop.org/
- Python: http://sourceforge.net/projects/python-xlib/ ( github fork: https://github.com/Ademan/python-xlib-branch pypi: http://pypi.python.org/pypi/Python%20Xlib )
- https://github.com/alexer/python-xlib-render
- Python/twisted: https://launchpad.net/twisted-x11
- Perl: http://search.cpan.org/~smccam/X11-Protocol-0.56/Protocol.pm
- Go: https://github.com/BurntSushi/xgb
- Java: https://github.com/xderoche/J11
- Ruby: https://github.com/dj2/x-ruby-bindings
- Clojure: https://github.com/noodlewiz/xcljb
- Guile: https://github.com/mwitmer/guile-xcb
- C: XLib - http://www.sbin.org/doc/Xlib/ http://www.tronche.com/gui/x/xlib/ http://www.x.org/docs/X11/xlib.pdf
- C: XCB - http://xcb.freedesktop.org/
- Python: http://sourceforge.net/projects/python-xlib/ ( github fork: https://github.com/Ademan/python-xlib-branch pypi: http://pypi.python.org/pypi/Python%20Xlib )
- https://github.com/alexer/python-xlib-render
- Python/twisted: https://launchpad.net/twisted-x11
- Perl: http://search.cpan.org/~smccam/X11-Protocol-0.56/Protocol.pm
- Go: https://github.com/BurntSushi/xgb
- Java: https://github.com/xderoche/J11
- Ruby: https://github.com/dj2/x-ruby-bindings
- Clojure: https://github.com/noodlewiz/xcljb
- Guile: https://github.com/mwitmer/guile-xcb
- Emacs lisp: https://github.com/ch11ng/xelb ( autogenerated from XCB XML )
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/sidorares/node-x11/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
## Server side (protocol + functionality) implementations for js + DOM
would be really great to make completely web based playground page, connecting node-x11 api to DOM based implementation
- https://github.com/GothAck/javascript-x-server
- https://github.com/ttaubert/x-server-js

View file

@ -252,7 +252,7 @@ function genReq(req, last)
if (req.body.length == 0)
{
result.push(' function() {');
result.push(' return Buffer.from([' + req.opcode + ', 0, 1, 0]);');
result.push(' return new Buffer([' + req.opcode + ', 0, 1, 0]);');
} else {
result.push(' function (args) {');
result.push(' var extraLength = 0;');
@ -287,10 +287,10 @@ function genReq(req, last)
var reqLen4 = ((reqLen + 3) >> 2);
if (extraLength)
result.push(' var data = Buffer.alloc(' + reqLen + ' + extraLength);');
result.push(' var data = new Buffer(' + reqLen + ' + extraLength);');
else {
result.pop();
result.push(' var data = Buffer.alloc(' + reqLen + ');');
result.push(' var data = new Buffer(' + reqLen + ');');
}
result.push(' data[0] = ' + req.opcode + ';');
if (req.body.length != 0) {

View file

@ -12,7 +12,7 @@ var ButtonRelease = x11.eventMask.ButtonRelease;
// image and coords file from http://www.patrick-wied.at/projects/heatmap-keyboard/
// TODO: add simple tool to use&tag coords in own keyboard photo
// jpeg decoder is slightly modified version of https://github.com/notmasteryet/jpgjs
var kbdImg = require('./node-jpg').readJpeg(__dirname+'/keyboard.jpg');
var kbdImg = require('./node-jpg').readJpeg('./keyboard.jpg');
var keycoords = require('./coordinates');
// from https://github.com/substack/node-keysym

View file

@ -571,7 +571,7 @@ module.exports.readJpeg = function(path)
var imageData = {};
imageData.width = j.width;
imageData.height = j.height;
imageData.data = Buffer.from(j.width*j.height*4);
imageData.data = new Buffer(j.width*j.height*4);
j.copyToImageData(imageData);
return imageData;
}

View file

@ -1,69 +0,0 @@
var x11 = require('..');
// The list provided by GetKeyboardMapping has sublists where each position
// represents the result for some key composition.
keyComposition = [
'Key',
'shift + Key',
'modeSwitch + Key',
'modeSwitch + shift + Key',
'altGr + Key',
'altGr + shift + Key'
]
x11.createClient(function(err, display){
if (err) throw err
var min = display.min_keycode, // TODO: explain min_keycode
max = display.max_keycode, // TODO: explain max_keycode
chr2Data = [], // allow us to find a char by the charcode
key2Data = []; // associate chars to a keycode
// The keySyms is a hash of mnemonic char names, associated to an integer
// charcode and its description.
for (codeName in x11.keySyms) {
keyData = x11.keySyms[codeName];
chr2Data[keyData.code] = { codeName: codeName, description: keyData.description };
}
var X = display.client,
wid = X.AllocID(), // Get a free integer id to a new window.
root = display.screen[0].root, // The mother window. Like your window manager.
evKeyPress = x11.eventMask.KeyPress, // Allow to filter for KeyPress events.
white = display.screen[0].white_pixel; // Will paint the window.
// Get the local key mapping to build key2Data.
X.GetKeyboardMapping(min, max-min, function(err, list) {
for (var i=0; i < list.length; ++i) {
var name = key2Data[i+min] = [];
var sublist = list[i];
for (var j=0; j < sublist.length; ++j)
name.push(chr2Data[sublist[j]]);
}
});
// Launch a window to listen by key events:
X.CreateWindow(wid, root, 0, 0, 100, 100, 0, 0, 0, 0, { backgroundPixel: white, eventMask: evKeyPress });
X.MapWindow(wid);
X.on('event', function(ev) {
if (ev.type == 2) { // filter by KeyPress. Useful if you have a more open eventMask.
var key = key2Data[ev.keycode]; // key is a list of chars related to the pressed key.
if (key) {
console.log('\n>> key pressed:', ev.keycode);
for (var i=0; i<key.length; i++) // Describe each related char
if (key[i])
console.log(
key[i].codeName, '\t', (
key[i].description ? key[i].description : 'no description'
), (
keyComposition[i] ? '\t' + keyComposition[i] : ''
)
);
}
else
console.log('>> keyCode '+ ev.keycode +' was not recognized.');
}
});
});

View file

@ -874,7 +874,7 @@ module.exports.readPng = function(path)
var imageData = {};
imageData.width = j.width;
imageData.height = j.height;
imageData.data = Buffer.alloc(j.width*j.height*4);
imageData.data = new Buffer(j.width*j.height*4);
j.render(imageData);
return imageData;
}

View file

@ -1,344 +0,0 @@
/*
* Simple png decoder
* https://github.com/b37t1td/png-decoder
*/
var CRCTable = new Int32Array([
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
]);
var crc32 = function(buf) {
var crc = -1;
for (var i = 0; i < buf.length; i++) {
crc = CRCTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
}
return crc ^ -1;
};
/*
* BE byteArray implementation
* by Svetlana Linuxenko <linuxenko@yahoo.com>
*/
/* eslint no-undef: 0 */
var byteArray = Uint8Array;
var cmp = function(a, b) {
if (!b) b = a; a = this;
return a.filter(function(c,i) { return c === b[i]; }).length === a.length;
};
var toInt = function(a) {
if (!a) a = this.slice(this.off, 4);
return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
//return a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);
};
var toBytes = function(int) {
return new byteArray([
(int >> 24) & 0xff,
(int >> 16) & 0xff,
(int >> 8) & 0xff,
int & 0xff
]);
};
var nextInt = function() {
return this.toInt(this.slice(this.off, (this.off += 4)));
};
var nextIntBytes = function() {
return this.nextBytes(4);
};
var nextBytes = function(size) {
return this.slice(this.off, (this.off += size));
};
var nextByte = function() {
return this.nextBytes(1)[0];
};
var insertInt = function(int) {
this.insertBytes(this.toBytes(int));
};
var insertBytes = function(bytes, length) {
length = length || 4;
this.set(bytes, this.off, length);
this.off += length;
};
var insertByte = function(byte) {
this.set([byte], this.off, (this.off += 1));
};
byteArray.prototype.cmp = cmp;
byteArray.prototype.toInt = toInt;
byteArray.prototype.nextInt = nextInt;
byteArray.prototype.nextIntBytes = nextIntBytes;
byteArray.prototype.toBytes = toBytes;
byteArray.prototype.insertInt = insertInt;
byteArray.prototype.insertBytes = insertBytes;
byteArray.prototype.nextBytes = nextBytes;
byteArray.prototype.nextByte = nextByte;
byteArray.prototype.insertByte = insertByte;
Object.defineProperty(byteArray.prototype , 'off', {
enumerable: false,
configurable: false,
writable: true,
value : 0
});
var SIGNATURE = new byteArray([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
var IHDR = new byteArray([0x49, 0x48, 0x44, 0x52]);
var IDAT = new byteArray([0x49, 0x44, 0x41, 0x54]);
var IEND = new byteArray([0x49, 0x45, 0x4e, 0x44]);
/*
* Decoder
*/
var zlib = require('zlib');
var inflateFunction = function(data) {
return zlib.inflateSync(Buffer.from(data));
};
var Decoder = function() { };
Decoder.prototype.parse = function(data) {
if (!(data instanceof byteArray)) {
data = new byteArray(data);
}
if (!SIGNATURE.cmp(data.nextBytes(SIGNATURE.length))) {
throw new Error('Not png');
}
while (data.off < data.length) {
var len = data.nextInt();
var hdr = data.nextBytes(len + 4);
if (crc32(hdr) !== data.nextInt()) {
throw new Error('Crc error');
}
if (IHDR.cmp(hdr)) {
this._IHDR = this._chunkIHDR(hdr.slice(4, len + 4));
if (this._IHDR.palette !== 8) {
throw new Error('Depth error');
}
if (this._IHDR.compression !== 0) {
throw new Error('Compression error');
}
if (this._IHDR.filter !== 0) {
throw new Error('Filter error');
}
if (this._IHDR.interlace !== 0) {
throw new Error('Interlace error');
}
switch (this._IHDR.colorType){
case 0: this.bpp = 1; break;
case 2: this.bpp = 3; break;
case 3: this.bpp = 1; break;
case 4: this.bpp = 2; break;
case 6: this.bpp = 4; break;
default: throw new Error('ColorType error');
}
this.chunks = [];
}
if (IDAT.cmp(hdr)) {
if (!this._IHDR) {
throw new Error('IHDR error');
}
this._chunkIDAT(hdr.slice(4, len + 4));
}
if (IEND.cmp(hdr)) {
return this._chunkIEND();
}
}
throw new Error('Data error');
};
Decoder.prototype._chunkIEND = function() {
var tmp = [];
for (var i = 0; i < this.chunks.length; i++) {
for (var j = 0; j < this.chunks[i].length; j++) {
tmp.push(this.chunks[i][j]);
}
}
return this.filter(inflateFunction(tmp));
};
Decoder.prototype._chunkIDAT = function(chunk) {
this.chunks.push(chunk);
};
Decoder.prototype._chunkIHDR = function(chunk) {
return {
width : chunk.nextInt(),
height : chunk.nextInt(),
palette : chunk.nextByte(),
colorType : chunk.nextByte(),
compression : chunk.nextByte(),
filter : chunk.nextByte(),
interlace : chunk.nextByte()
};
};
Decoder.prototype.filter = function(data) {
var bpp = this.bpp;
var width = this._IHDR.width, height = this._IHDR.height;
var pixels = new byteArray((width * height) * bpp);
var filter, line, left, leftup, up, pixel;
var lineWidth = width * bpp, byte, off;
for (var y = 0; y < height; y++) {
filter = data.nextByte();
line = data.nextBytes(lineWidth);
for (var x = 0; x < lineWidth; x++) {
if (filter !== 0) {
off = (y * lineWidth) + x;
}
byte = line.nextByte();
switch(filter) {
case 0: //None
pixel = byte;
break;
case 1: // Sub Raw(x) + Raw(x - bpp)
if (x < bpp) {
pixel = byte;
break;
}
pixel = pixels[off - bpp] + byte & 0xff;
break;
case 2: // Up(x) = Raw(x) + Prior(x)
if (y === 0) {
pixel = byte;
break;
}
pixel = pixels[off - lineWidth] + byte & 0xff;
break;
case 3: // Average(x) = Raw(x) + floor((Raw(x-bpp)+Prior(x))/2)
if (y === 0) {
if (x < bpp) {
pixel = byte;
} else {
pixel = (byte + (pixels[off - bpp] >> 1)) & 0xff;
}
break;
}
if (x < bpp) {
pixel = (byte + (pixels[off - lineWidth] >> 1)) & 0xff;
break;
}
pixel = (byte + (pixels[off - bpp] + pixels[off - lineWidth] >> 1)) & 0xff;
break;
case 4: // Paeth
if (y === 0) {
if (x < bpp) {
pixel = byte;
} else {
pixel = (byte + (pixels[off - bpp])) & 0xff;
}
break;
}
if (x < bpp) {
pixel = (byte + (pixels[off - lineWidth])) & 0xff;
break;
}
up = pixels[off - lineWidth];
left = pixels[off - bpp];
leftup = pixels[(off - lineWidth) - bpp];
var p = left + up - leftup,
pleft = Math.abs(p - left),
pup = Math.abs(p - up),
pleftup = Math.abs(p - leftup);
if (pleft <= pup && pleft <= pleftup){
pixel = byte + left & 0xff;
break;
} else if (pup <= pleftup) {
pixel = byte + up & 0xff;
break;
}
pixel = byte + leftup & 0xff;
break;
default:
throw new Error('Filter error: ' + filter);
}
pixels.insertByte(pixel);
}
}
return pixels;
};
module.exports = Decoder;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -1,80 +0,0 @@
//var logo = require('./node-png').readPng('./node-logo.png');
var fs = require('fs');
var Decoder = require('./png-decoder');
var decoder = new Decoder();
var logo = {
data : Buffer.from(decoder.parse(fs.readFileSync('./screen.png'))),
width : decoder._IHDR.width,
height : decoder._IHDR.height
};
var x11 = require('../../lib');
var Exposure = x11.eventMask.Exposure;
x11.createClient(function(err, display)
{
var X = display.client;
X.require('render', function(err, Render) {
var root = display.screen[0].root;
main(root, X, Render, display);
});
});
function main(root, X, Render, display) {
var win, picWin, pic, gc;
win = X.AllocID();
X.CreateWindow(
win, root,
0, 0, logo.width, logo.height,
0, 0, 0, 0,
{ eventMask: Exposure }
);
X.MapWindow(win);
gc = X.AllocID();
X.CreateGC(gc, win);
var logoPixmap = X.AllocID();
X.CreatePixmap(logoPixmap, win, 24, logo.width, logo.height);
var rscreen = display.screen[0];
var screen =
rscreen.depths[rscreen.root_depth][
Object.keys(rscreen.depths[rscreen.root_depth])[0]];
var rmask = parseInt(screen.red_mask, 10);
var gmask = parseInt(screen.green_mask, 10);
var bmask = parseInt(screen.blue_mask, 10);
for (var y = 0; y < logo.height; y++) {
for (var x = 0; x < logo.width; x++) {
var pixel = Buffer.from([
logo.data[(x + logo.width * y) * 4],
logo.data[(x + logo.width * y) * 4 + 1],
logo.data[(x + logo.width * y) * 4 + 2], 0]).readInt32LE();
logo.data[(x + logo.width * y) * 4 ] = (pixel & rmask) >> 16;
logo.data[(x + logo.width * y) * 4 + 1] = (pixel & gmask) >> 8;
logo.data[(x + logo.width * y) * 4 + 2] = (pixel & bmask) >> 0;
logo.data[(x + logo.width * y) * 4 + 3] = 0x00;
}
}
X.PutImage(2, logoPixmap, gc, logo.width, logo.height, 0, 0, 0, 24, logo.data);
var logoPicture = X.AllocID();
Render.CreatePicture(logoPicture, logoPixmap, Render.rgb24);
var winPicture = X.AllocID();
Render.CreatePicture(winPicture, win, Render.rgb24);
X.on('event', function(ev) {
if (ev.name == 'Expose') {
Render.Composite(3, logoPicture, 0, winPicture, 0, 0, 0, 0, 0, 0, logo.width, logo.height);
}
});
}

28
examples/screenshot.js Normal file → Executable file
View file

@ -8,16 +8,16 @@ x11.createClient(function(err, display) {
var id = wid ? wid : root;
var gc = X.AllocID();
X.CreateGC(gc, id);
X.CreateGC(gc, id);
var width = 0;
var hwight = 0;
X.GetGeometry(id, function(err, clientGeom) {
X.GetGeometry(id, function(clientGeom) {
width = clientGeom.width;
height = clientGeom.height;
var dispwin = X.AllocID();
X.CreateWindow(dispwin, root, 0, 0, width, height, 0, 0, 0, 0, { eventMask: x11.eventMask.Exposure });
X.CreateWindow(dispwin, root, 0, 0, width, height, 1, 1, 0, { eventMask: x11.eventMask.Exposure });
X.MapWindow(dispwin);
//X.CopyArea(idScreenshot, dispwin, gc, 0, 0, 0, 0, width, height);
@ -25,21 +25,21 @@ x11.createClient(function(err, display) {
//var idScreenshot = X.AllocID();
//X.CreatePixmap(idScreenshot, root, 24, clientGeom.width, clientGeom.height);
// ask recursively each window to copy itself to pixmap
function drawWithKids(list, cb)
{
if (list.length == 0)
return cb();
return cb();
var p = list.pop();
var win = p.win;
if (win == dispwin)
return drawWithKids(list, cb);
X.GetWindowAttributes(win, function(err, res) {
X.GetWindowAttributes(win, function(res) {
if (res[8] == 0)
return drawWithKids(list, cb);
X.GetGeometry(win, function(err, geom) {
// (srcDrawable, dstDrawable, gc, srcX, srcY, dstX, dstY, width, height)
return drawWithKids(list, cb);
X.GetGeometry(win, function(geom) {
// (srcDrawable, dstDrawable, gc, srcX, srcY, dstX, dstY, width, height)
if (win != root)
X.CopyArea(win, dispwin, gc, 0, 0, p.x + geom.xPos, p.y + geom.yPos, geom.width, geom.height);
//X.CopyArea(win, idScreenshot, gc, 0, 0, p.x + geom.xPos, p.y + geom.yPos, geom.width, geom.height);
@ -63,19 +63,15 @@ x11.createClient(function(err, display) {
// console.log(data);
//});
console.log('DONE! ready');
X.terminate();
X.terminate();
//var dispwin = X.AllocID();
//X.CreateWindow(dispwin, root, 0, 0, width, height, 1, 1, 0, { eventMask: x11.eventMask.Exposure });
//X.MapWindow(dispwin);
//X.CopyArea(idScreenshot, dispwin, gc, 0, 0, 0, 0, width, height);
});
*/
X.GetImage(2, id, 0, 0, width, height, 0xffffffff, function(err, image) {
if (err) {
console.log(err);
process.exit(1);
}
X.GetImage(2, root, 0, 0, width, height, 0xffffffff, function(image) {
console.log(image);
// format, drawable, gc, width, height, dstX, dstY, leftPad, depth, data
X.PutImage(2, dispwin, gc, width, height, 0, 0, 0, 24, image.data);

View file

@ -1,36 +0,0 @@
/*
* GCFunction usage example
*/
var x11 = require('../../lib');
x11.createClient(function(err, display) {
var X = display.client;
var root = display.screen[0].root;
var white = display.screen[0].white_pixel;
var black = display.screen[0].black_pixel;
var wid = X.AllocID();
X.CreateWindow(wid, root, 0, 0, 400, 300, 0, 0, 0, 0, {
backgroundPixel: black,
eventMask: x11.eventMask.ButtonPress|x11.eventMask.Exposure });
var gc = X.AllocID();
X.CreateGC(gc, wid, {foreground : white, 'function' : x11.gcFunction.GXinvert});
X.MapWindow(wid);
X.on('event', function(ev) {
if (ev.type === 12) {
X.PolyFillRectangle(wid, gc, [0, 0, 400, 300]);
}
if (ev.type === 4) {
var x = ev.x;
var y = ev.y;
X.PolyFillRectangle(wid, gc, [x - 25, y - 25, 50, 50]);
}
});
});

View file

@ -7,7 +7,7 @@ var xclient = x11.createClient(function(err, display) {
display.client.require('render', function(err, Render) {
var wid = X.AllocID();
var white = display.screen[0].white_pixel;
var black = display.screen[0].black_pixel;
varblack = display.screen[0].black_pixel;
X.CreateWindow(wid, root, 10, 10, 400, 300, 0, 0, 0, 0, { backgroundPixel: white, eventMask: PointerMotion });
X.MapWindow(wid);

View file

@ -26,7 +26,7 @@ function padWidth(buf, width) {
return buf;
else {
var stride = (width+3)&~3;
var res = Buffer.alloc(height*stride);
var res = new Buffer(height*stride);
res.fill(0);
for (var y=0; y < height; ++y) {
// memcpy(tmpbitmap+y*stride, bitmap->buffer+y*ginfo.width, ginfo.width);
@ -42,7 +42,7 @@ var xclient = x11.createClient({ debug: true }, function(err, display) {
display.client.require('render', function(err, Render) {
var wid = X.AllocID();
var white = display.screen[0].white_pixel;
var black = display.screen[0].black_pixel;
varblack = display.screen[0].black_pixel;
X.CreateWindow(wid, root, 10, 10, 400, 300, 0, 0, 0, 0, { backgroundPixel: white, eventMask: Exposure|PointerMotion });
X.MapWindow(wid);
@ -88,7 +88,7 @@ var xclient = x11.createClient({ debug: true }, function(err, display) {
var glyphFromCode = [];
glyphs.forEach(function(g) {
if (!g.image || (g.image.length == 0)) {
g.image = Buffer.alloc(64);
g.image = new Buffer(64);
g.image.fill(0);
g.width = 8;
g.height = 8;

View file

@ -1,51 +0,0 @@
// the code is taken from https://github.com/mattlockyer/iat455/blob/6493c882f1956703133c1bffa1d7ee9a83741cbe/assignment1/assignment/effects/blur-effect-dyn.js
// (c) Matt Lockyer, https://github.com/mattlockyer
function hypotenuse(x1, y1, x2, y2) {
var xSquare = Math.pow(x1 - x2, 2);
var ySquare = Math.pow(y1 - y2, 2);
return Math.sqrt(xSquare + ySquare);
}
/*
* Generates a kernel used for the gaussian blur effect.
*
* @param dimension is an odd integer
* @param sigma is the standard deviation used for our gaussian function.
*
* @returns an array with dimension^2 number of numbers, all less than or equal
* to 1. Represents our gaussian blur kernel.
*/
function generateGaussianKernel(dimension, sigma) {
if (!(dimension % 2) || Math.floor(dimension) !== dimension || dimension<3) {
throw new Error(
'The dimension must be an odd integer greater than or equal to 3'
);
}
var kernel = [];
var twoSigmaSquare = 2 * sigma * sigma;
var centre = (dimension - 1) / 2;
for (var i = 0; i < dimension; i++) {
for (var j = 0; j < dimension; j++) {
var distance = hypotenuse(i, j, centre, centre);
// The following is an algorithm that came from the gaussian blur
// wikipedia page [1].
//
// http://en.wikipedia.org/w/index.php?title=Gaussian_blur&oldid=608793634#Mechanics
var gaussian = (1 / Math.sqrt(
Math.PI * twoSigmaSquare
)) * Math.exp((-1) * (Math.pow(distance, 2) / twoSigmaSquare));
kernel.push(gaussian);
}
}
// Returns the unit vector of the kernel array.
var sum = kernel.reduce(function (c, p) { return c + p; });
return kernel.map(function (e) { return e / sum; });
}
module.exports = generateGaussianKernel;

View file

@ -6,7 +6,7 @@ var Pixmap = require('./pixmap').Pixmap;
var Buffer = require('buffer').Buffer;
require('../../lib/unpackbuffer').addUnpack(Buffer);
var reversed = Buffer.alloc(256);
var reversed = new Buffer(256);
for (var i=0; i < 256; ++i)
{
var res = 0;
@ -42,4 +42,4 @@ module.exports.decodeBuffer = function(buffer)
data[i] = 255 - reversed[data[i]];
return new Pixmap(header.bpp, header.width, header.height, data);
}
}

View file

@ -1,15 +0,0 @@
var x11 = require('../../lib');
var Window = require('./wndwrap');
x11.createClient(function(err, display) {
var X = display.client;
var w = new Window(X, 0, 0, 700, 500);
w.map();
w.on('expose', function() {
var gc = X.AllocID();
X.CreateGC(gc, w.id, { foreground: w.black, background: w.white });
X.PolyFillRectangle(w.id, gc, [50, 50, 600, 400]);
X.ClearArea(w.id, 0, 0, 300, 300, 0);
});
});

View file

@ -5,7 +5,7 @@ var keysym = require('keysym');
var ks = x11.keySyms;
var ks2Name = {};
for (var key in ks)
ks2Name[ ks[key].code ] = key;
ks2Name[ ks[key] ] = key;
var kk2Name = {};
x11.createClient(function(err, display) {

View file

@ -8,7 +8,7 @@ var xclient = x11.createClient();
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
var bitmap = Buffer.alloc(128*128/8); // 16384 bits, 2048 bytes bitmap
var bitmap = new Buffer(128*128/8); // 16384 bits, 2048 bytes bitmap
for (var i=0; i < bitmap.length; ++i)
{
bitmap[i] = i % 256;

View file

@ -4,7 +4,7 @@ var x11 = require('../../lib');
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
var bitmap = Buffer.alloc(128*128*4); // 16384 bits, 2048 bytes bitmap
var bitmap = new Buffer(128*128*4); // 16384 bits, 2048 bytes bitmap
for (var i=0; i < bitmap.length; ++i)
{
var byteNum = i%4;

View file

@ -1,11 +1,11 @@
var x11 = require('../../lib');
var xclient = x11.createClient({debug: true});
var xclient = x11.createClient();
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
var pts = [];
xclient.on('connect', function(display) {
xclient.on('connect', function(err, display) {
var X = this;
var root = display.screen[0].root;
var white = display.screen[0].white_pixel;
@ -13,16 +13,18 @@ xclient.on('connect', function(display) {
function createWindow()
{
var wid = X.AllocID();
// id, parentId, x, y, width, height, borderWidth, depth, _class, visual, values
X.CreateWindow(
wid, root,
10, 10, 400, 300,
0, 0, 0, 0, {
backgroundPixel: white, eventMask: Exposure|PointerMotion
});
X.MapWindow(wid);
return wid;
var wid = X.AllocID();
X.CreateWindow(
wid, root,
10, 10, 400, 300,
1, 1, 0,
{
backgroundPixel: white, eventMask: Exposure|PointerMotion
}
);
X.MapWindow(wid);
return wid;
}
var wid = createWindow();
@ -57,7 +59,7 @@ xclient.on('connect', function(display) {
}
});
//X.on('error', function(e) {
// console.log(e);
//});
X.on('error', function(e) {
console.log(e);
});
});

View file

@ -1,22 +0,0 @@
var x11 = require('../../lib');
var Expose = 12;
x11.createClient(function(err, display) {
var X = display.client;
var root = display.screen[0].root;
X.require('shape', function(err, Shape) {
var win = X.AllocID();
X.CreateWindow(win, root, 0, 0, 200, 200);
X.ChangeWindowAttributes(win, { backgroundPixel: display.screen[0].black_pixel });
X.MapWindow(win);
Shape.Rectangles(Shape.Op.Set, Shape.Kind.Bounding, win, 0, 0, [
[40, 40, 40, 40], [120, 40, 40, 40],
[0, 120, 20, 20], [180, 120, 20, 20],
[20, 140, 30, 20], [150, 140, 30, 20],
[50, 160, 100, 20]
]);
});
X.on('error', function(err) { console.log(err); });
});

View file

@ -6,22 +6,17 @@ x11.createClient(function(err, display) {
X.require('shape', function(err, Shape) {
var win = X.AllocID();
X.CreateWindow(win, root, 0, 0, 200, 200);
X.ChangeWindowAttributes(win, { backgroundPixel: display.screen[0].white_pixel });
X.MapWindow(win);
X.ClearArea(win, 0, 0, 200, 200, false);
Shape.SelectInput(win, true);
var gc = X.AllocID();
X.CreateGC(gc, win);
//X.MapWindow(win);
Shape.SelectInput(win, 1);
Shape.InputSelected(win, function(err, isSelected) {
console.log("IsSelected: " + isSelected);
});
var bitmap = X.AllocID();
X.CreatePixmap(bitmap, win, 1, 200, 200);
var gc = X.AllocID();
X.CreateGC(gc, bitmap, { foreground: 1 });
// X.PolyText8(bitmap, gc, 0, 0, ['Hello, Node.JS!', ' Hello, world!']);
X.PolyFillArc(bitmap, gc, [0, 0, 200, 200, 0, 360 * 64]);
Shape.Mask(Shape.Op.Set, Shape.Kind.Bounding, win, 0, 0, bitmap);
//var pid = X.AllocID();
//X.CreatePixmap(pid, win, 2, 200, 200);
//X.PolyText8(pid, gc, 0, 0, ['Hello, Node.JS!', ' Hello, world!']);
//Shape.Mask(Shape.Op.Set, Shape.Kind.Input, win, 0, 0, pid);
X.on('event', function(ev) {
console.log(ev);

View file

@ -1,125 +0,0 @@
var _ = require('underscore');
var x11 = require('../../lib');
var Exposure = x11.eventMask.Exposure;
var PointerMotion = x11.eventMask.PointerMotion;
var ButtonPress = x11.eventMask.ButtonPress;
var draw;
var useConvo3 = true;
x11.createClient({ debug: true}, function(err, display) {
var X = display.client;
var root = display.screen[0].root;
var wid = X.AllocID();
X.CreateWindow(
wid, root,
0, 0, 800, 600,
0, 0, 0, 0,
{
eventMask: Exposure|PointerMotion|ButtonPress
}
);
X.MapWindow(wid);
X.require('render', function(err, Render) {
Render.QueryFilters(console.log);
var pixMask = X.AllocID();
X.CreatePixmap(pixMask, wid, 8, 600, 600);
var pictTraps = X.AllocID();
Render.CreatePicture(pictTraps, pixMask, Render.a8);
var pictWin = X.AllocID();
Render.CreatePicture(pictWin, wid, Render.rgb24);
var pictSolid = X.AllocID();
r = 0.2; g = 0.2; b = 0.2; a = 1;
Render.CreateSolidFill(pictSolid, r, g, b, a);
var pixBuff = X.AllocID();
X.CreatePixmap(pixBuff, wid, 24, 600, 600);
var pictBuff = X.AllocID();
Render.CreatePicture(pictBuff, pixBuff, Render.rgb24);
var convo5 = [ 5, 5, 0.0030, 0.0133, 0.0219, 0.0133, 0.0030,
0.0133, 0.0596, 0.0983, 0.0596, 0.0133,
0.0219, 0.0983, 0.1621, 0.0983, 0.0219,
0.0133, 0.0596, 0.0983, 0.0596, 0.0133,
0.0030, 0.0133, 0.0219, 0.0133, 0.0030];
var convo3 = [3, 3, 0.01, 0.08, 0.01, 0.08, 0.64, 0.08, 0.01, 0.08, 0.01];
var convo5 = [21, 21].concat(require('./blur-convolution')(21, 11));
//Render.SetPictureFilter(pictBuff, 'convolution', convo3);
//Render.SetPictureFilter(pictTraps, 'convolution', convo3);
//Render.SetPictureFilter(pictBuff, 'bilinear', []);
Render.SetPictureFilter(pictBuff, 'best', []);
draw1 = function(x, y) {
console.log('draw 1', x, y);
var r = 3 + 2*Math.floor(x / 100);
var convo = [r, r].concat(require('./blur-convolution')(r, r));
Render.SetPictureFilter(pictBuff, 'convolution', convo);
var a = (x-400)/500;
var m = [
Math.cos(a), Math.sin(a), 0,
-Math.sin(a), Math.cos(a), 0,
0, 0, 1
];
// Render.SetPictureTransform(pictTraps, m)
var r, g, b;
// fill window
r = 1; g = 1; b = 1; a = 0.5;
Render.FillRectangles(1, pictBuff, [r, g, b, a], [0, 0, 1000, 1000])
// fill traps
r = 0; g = 0; b = 0; a = 0;
Render.FillRectangles(1, pictTraps, [r, g, b, a], [0, 0, 1000, 1000])
Render.AddTraps(pictTraps, 0, 0, [
x, 200, y,
//150, 200, 50,
5, 250, 300,
110, 200, 310,
50, 150, 500
]);
// (op, src, mask, dst, srcX, srcY, maskX, maskY, dstX, dstY, width, height)
//Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictWin, 0, 0, 0, 0, 0, 0, 800, 600);
//Render.PictOp.Over
Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictBuff, 0, 0, 0, 0, 0, 0, 800, 600);
Render.Composite(Render.PictOp.Over, pictBuff, 0, pictWin, 0, 0, 0, 0, 0, 0, 800, 600);
};
draw = function(x, y) {
var f = _.debounce(function() {
draw1(x, y);
}, 100);
f();
};
});
}).on('error', function(err) {
console.log(err);
}).on('event', function(ev) {
//console.log(ev);
if (ev.name == 'MotionNotify') {
draw(ev.x, ev.y);
} else if (ev.name == 'ButtonPress') {
useConvo3 = !useConvo3;
draw(ev.x, ev.y);
//console.log(ev);
}
});

View file

@ -25,7 +25,7 @@ var Buffer = require('buffer').Buffer;
var startpos = [4, 15];
var cupsize = [10, 20];
var cup = Buffer.alloc(cupsize[0]*cupsize[1]);
var cup = new Buffer(cupsize[0]*cupsize[1]);
var moveInterval;
function clearCup()
@ -250,7 +250,7 @@ x11.createClient(function(err, display) {
var ks = x11.keySyms;
var ks2Name = {};
for (var key in ks)
ks2Name[ ks[key].code ] = key;
ks2Name[ ks[key] ] = key;
var kk2Name = {};
var min = display.min_keycode;
var max = display.max_keycode;

View file

@ -56,8 +56,8 @@ var pc2 = [
function deskey(key, edf)
{
var i, j, l, m, n;
var pc1m = Buffer.alloc(56);
var pcr = Buffer.alloc(56);
var pc1m = new Buffer(56);
var pcr = new Buffer(56);
var kn = new Array(32);
for ( j = 0; j < 56; j++ ) {
@ -388,17 +388,17 @@ function desfunc(block, keys)
module.exports.response = function(challenge, password)
{
var key = Buffer.alloc(8);
var key = new Buffer(8);
key.fill(0);
key.write(password.substring(0,8));
var in1 = challenge.slice(0,8);
var in2 = challenge.slice(8,16);
var res1 = Buffer.alloc(8);
var res2 = Buffer.alloc(8);
var res1 = new Buffer(8);
var res2 = new Buffer(8);
deskey(key, EN0);
des(in1, res1);
des(in2, res2);
var resp = Buffer.alloc(16);
var resp = new Buffer(16);
res1.copy(resp);
res2.copy(resp, 8);
return resp;

View file

@ -7,7 +7,7 @@
// It should create a pleasant looking hex dumb by default:
//
// var hexy = require('hexy.js'),
// b = Buffer.from("\000\001\003\005\037\012\011bcdefghijklmnopqrstuvwxyz0123456789")
// b = new Buffer("\000\001\003\005\037\012\011bcdefghijklmnopqrstuvwxyz0123456789")
//
// console.log(hexy.hexy(b))
//
@ -258,4 +258,4 @@ console.log(hexy(data, format))
console.log("doen")
*/
exports.hexy = hexy
exports.hexy = hexy

View file

@ -400,7 +400,7 @@ RfbClient.prototype.readHextileTile = function(rect, cb)
});
return;
}
tile.buffer = Buffer.alloc(tilebuflen);
tile.buffer = new Buffer(tilebuflen);
function solidBackground() {
clog('solidBackground');
@ -667,8 +667,8 @@ function createConnection(params)
var wstream = fs.createWriteStream(params.rfbFileOut);
wstream.write('FBS 001.001\n');
stream.on('data', function(data) {
var sizeBuf = Buffer.alloc(4);
var timeBuf = Buffer.alloc(4);
var sizeBuf = new Buffer(4);
var timeBuf = new Buffer(4);
var size = data.length;
sizeBuf.writeInt32BE(size, 0);
wstream.write(sizeBuf);
@ -676,7 +676,7 @@ function createConnection(params)
timeBuf.writeInt32BE(+new Date() - start, 0);
wstream.write(timeBuf);
var padding = 3 - ((size - 1) & 0x03);
var pbuf = Buffer.alloc(padding);
var pbuf = new Buffer(padding);
wstream.write(pbuf);
}).on('end', function() {
wstream.end();

View file

@ -62,7 +62,7 @@ RfbServer.prototype.processSecurity = function()
break;
case rfb.security.VNC:
// generate random 16 byte challenge
serv.challenge = Buffer.alloc(16);
serv.challenge = new Buffer(16);
serv.challenge.write('1234567890abcdef');
console.log(['sending challenge', serv.challenge]);
serv.pack_stream.pack('a', [serv.challenge]).flush();

View file

@ -34,7 +34,7 @@ function ReadFixedRequest(length, callback)
this.length = length;
this.callback = callback;
//clog(length);
this.data = Buffer.alloc(length);
this.data = new Buffer(length);
this.received_bytes = 0;
}
@ -328,7 +328,7 @@ UnpackStream.prototype.pack = function(format, args)
}
}
var buf = Buffer.alloc(packetlength);
var buf = new Buffer(packetlength);
var offset = 0;
var arg = 0;
for (var i = 0; i < format.length; ++i)

View file

@ -1,75 +0,0 @@
/* XPM */
static char * node_logo_xpm[] = {
"245 66 6 1",
" c None",
". c #FFFFFF",
"+ c #8CC84B",
"@ c #8DC84C",
"# c #89C746",
"$ c #8AC748",
" .. ",
" .... ",
" ...... ",
" ....... ",
" ......... ",
" ........... ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ",
" ............ ++ ",
" .... ++++ .. ............ .... ++++++ .. . .",
" ........ ++++++++ ...... ............ ....... +++++++++ .. .",
" ............ ++++++++++++ ....................... ........... ++++++ ++++++ ...",
" ............... ++++++++++++++ ......................... .............. +++++++ ++++++ ",
" .................. ++++++++++++++++++ .......................... .................. ++++++ ++++++ ",
" ...................... ++++++++++++++++++++++ ............................ ..................... ++++++ ++++++ ",
" .......................... +++++++++++++++++++++++++ .............................. ......................... ++++++ ++++++ ",
" ............................. ++++++++++++++++++++++++++++ ................................ ............................ +++++++ ++++++ ",
" ................................ ++++++++++++++++++++++++++++++++ ................................. ................................ ++++++ ++++++ ",
" .................................... ++++++++++++++++++++++++++++++++++++ ................................... ................................... +++++ ++++++ ",
" .................................... ++++++++++++++++++++++++++++++++++++ .................................... ..................................... ++++ ++++ ",
" .................................... ++++++++++++++++++++++++++++++++++++ ..................................... ..................................... +++ +++ ",
" .................................... ++++++++++++++++++++++++++++++++++++ ..................................... ..................................... +++ + ++++++++ +++ ",
" .................................... ++++++++++++++++++++++++++++++++++++ ..................................... ..................................... +++ +++ ++++++++++++ +++ ",
" ................ ................ ++++++++++++++++++++++++++++++++++++ .................. ................. ................. ................. +++ +++ ++++++++++++++ +++ ",
" ............... ............... ++++++++++++++++++++++++++++++++++++ ................ ............... ................ ............... +++ +++ ++++ ++++ +++ ",
" ............. ............. ++++++++++++++++++++++++++++++++++++ ............... .............. .............. .............. +++ +++ +++ +++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. ++@# ............ +++ +++ +++ +++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. #@+++++ .......... +++ +++ ++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. +++++++ ........ +++ +++ +++++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. +++++++ ...... +++ +++ ++++++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. +++++++ .... +++ +++ +++++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. @++++++ ... +++ +++ +++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............ ............. $+++ +++ +++ +++ +++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............. ............. .............. +++ +++ ++++ +++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ............... .............. ............... +++ +++ ++++ ++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ................. ................ ................. +++ +++ ++++++++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ..................................... ................... +++ +++ +++++++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ..................................... .................... +++ +++ +++++++++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ ..................................... ...................... +++ +++ +++ ",
" ............ ............ ++++++++++++++++++++++++++++++++++++ .................................... ........................ +++++ +++ ++++ ",
" ........... ........... ++++++++++++++++++++++++++++++++++++ .................................... ......................... ++++++ ++++ +++++ ",
" ......... ......... ++++++++++++++++++++++++++++++++ .................................. ........................ ++++++++++++ ++++++ ",
" ........ ........ ++++++++++++++++++++++++++++ .............................. ......................... +++++++++ ++++++ ",
" ...... ...... ++++++++++++++++++++++++++ .......................... ........................ ++++++ ++++++ ",
" .... .... ++++++++++++++++++++++ ...................... ...................... ++++++ ",
" .. .. ++++++++++++++++++ .................... .................. ++++ ++++++ ",
" ++++++++++++++ ................ ............... ++++++ ++++++ ",
" ++++++++++++ ............ ........... ++++++++++++ ",
" ++++++++ ......... ........ +++++++++ ",
" ++++ ...... .... +++++ ",
" .. "};

View file

@ -1,151 +0,0 @@
/* Extracted from https://github.com/klepthys/node-xpm
* This code is available as a standalone module named xpm
/*
The MIT License (MIT)
Copyright (c) 2015 Sebastien Dumetz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var fs = require('fs');
function PixmapFromFile (path,options){
if(!options && typeof path == "object"){
this.options = path;
path = null;
}else{
this.options = options||{};
}
if(path){
return this.parse(fs.readFileSync(path, {encoding:"utf-8"}));
}
}
/**
*
* @param {[type]} data utf-8 file data
* @param {Function} callback optionnal callback.
*/
PixmapFromFile.prototype.parse = function (data) {
if(!/^\/\*\s*XPM\s*\*\/$/m.test(data)){
throw new Error("Not an XPM file");
}
var size = this.getSize(data);
var content = this.getArray(data,size);
var colors = this.mapColors(data,size);
size.data = this.toBuffer(colors,content,size);
return size;
};
PixmapFromFile.prototype.getSize = function(data){
var match = /{\n?"([0-9\s]*)\s?"/.exec(data);
if(!match){
throw new Error("can't parse size infos");
}
var values = match[1].split(" ").map(function(i){return parseInt(i)});
return {width:values[0],height:values[1],count:values[2],length:values[3]}
}
PixmapFromFile.prototype.getArray = function(data,size){
//var reg = new RegExp('"((?!(?:[0-9]+\\s?){4}).{'+size.length+'}(?!\\sc\\s).*)"',"g"); //Works also but much less simple
var reg = new RegExp('"(.{'+size.width*size.length+'})"',"g");
var res;
var rows = [];
while((res = reg.exec(data)) !== null){
rows.push(res[1]);
}
if(rows.length != size.height){
throw new Error("found : "+rows.length+" rows. Should have found :"+size.height+" rows.");
}
return rows;
}
// return RGBA color
PixmapFromFile.prototype.mapColors = function(content,size){
var reg = new RegExp('"(.' + ((size.length > 1)? "{"+(size.length)+"}" : "") + ")\\s+c\\s+#?(None|[0-9a-fA-F]{6})\"","gm");
var res;
var colors = {};
while((res = reg.exec(content)) !== null){
if(res[2] === "None"){
colors[res[1]] = "00000000"
}else{
colors[res[1]] = res[2]+"FF";//RGBA
}
}
if(Object.keys(colors).length != size.count){
throw new Error("found : "+Object.keys(colors).length+" colors. Should have found :"+size.count+" colors.");
}
return colors;
}
PixmapFromFile.prototype.toBuffer = function (colors,content,size) {
var buf = Buffer.alloc(size.width*size.height*4);
var offset = 0, byte,color;
var copy;
if( !this.options.format || this.options.format.toUpperCase() === "BGRA"){
copy = this.copyBGRABuffer;
}else if(this.options.format && this.options.format.toUpperCase() === "RGBA"){
copy = this.copyRGBABuffer;
}else{
throw new Error("invalid format option : ",this.options.format," valid values are BGRA (default) or RGBA")
}
content.forEach(function(row){
//console.log("parsing : ",row)
while(row && row.length >0){
var code = row.slice(0,size.length);
row = row.slice(size.length);
if(!colors[code]){
throw new Error("unknown color : ",code);
}
offset = copy(buf,offset,colors[code]);;
}
});
return buf;
};
/**
* Takes an array of rows. Each char/sequence represents a colored pixel
* @param {[type]} content [description]
* @return {Buffer} A 1d array of pixels in RGBA
*/
PixmapFromFile.prototype.copyBGRABuffer = function(buf, offset, color){
[4,2,0,6].forEach(function(i){
buf.writeUInt8(parseInt(color[i]+color[i+1],16),offset);
offset ++;
});
return offset;
}
PixmapFromFile.prototype.copyRGBABuffer = function(buf, offset, color){
buf.writeUInt32BE(parseInt(color,16),offset);
return offset+4;
}
PixmapFromFile.prototype.open = function(path,callback){
var self = this;
fs.readFile(path, {encoding:"utf-8"}, function(err,data){
if(err){
return callback(err);
}else{
callback(null,self.parse(data));
}
});
}
module.exports = PixmapFromFile;

View file

@ -1,53 +0,0 @@
#!/usr/bin/env node
var x11 = require('../../lib');
var PixmapFromFile = require('./node-xpm.js');
var Exposure = x11.eventMask.Exposure;
x11.createClient(function(err, display)
{
var X = display.client;
X.require('render', function(err, Render) {
var root = display.screen[0].root;
var pixmap = new PixmapFromFile();
pixmap.open("node-logo.xpm",function(err,logo){
if(err){
console.log(new Error().stack);
return console.error("pixmap open Error : ",err);
}
main(root, X, Render,logo);
});
});
});
function main(root, X, Render, logo) {
var win, picWin, pic, gc;
win = X.AllocID();
X.CreateWindow(
win, root,
0, 0, logo.width, logo.height,
0, 0, 0, 0,
{ eventMask: Exposure }
);
X.MapWindow(win);
gc = X.AllocID();
X.CreateGC(gc, win);
var logoPixmap = X.AllocID();
X.CreatePixmap(logoPixmap, win, 24, logo.width, logo.height);
// TODO: add proper png pixel conversion here
X.PutImage(2, logoPixmap, gc, logo.width, logo.height, 0, 0, 0, 24, logo.data);
var logoPicture = X.AllocID();
Render.CreatePicture(logoPicture, logoPixmap, Render.rgb24);
var winPicture = X.AllocID();
Render.CreatePicture(winPicture, win, Render.rgb24);
X.on('event', function(ev) {
if (ev.name == 'Expose')
Render.Composite(3, logoPicture, 0, winPicture, 0, 0, 0, 0, 0, 0, logo.width, logo.height);
});
}

View file

@ -1,110 +1,91 @@
// TODO: differentiate between auth types (i.e., MIT-MAGIC-COOKIE-1 and XDM-AUTHORIZATION-1)
// and choose the best based on the algorithm in libXau's XauGetBestAuthByAddr
// TODO: http://en.wikipedia.org/wiki/X_Window_authorization
var fs = require('fs');
var Buffer = require('buffer').Buffer;
// add 'unpack' method for buffer
require('./unpackbuffer').addUnpack(Buffer);
var typeToName = {
256: 'Local',
65535: 'Wild',
254: 'Netname',
253: 'Krb5Principal',
252: 'LocalHost',
0: 'Internet',
1: 'DECnet',
2: 'Chaos',
5: 'ServerInterpreted',
6: 'Internet6'
};
function parseXauth( buf )
{
var offset = 0;
var auth = [];
var cookieProperties = ['address', 'display', 'authName', 'authData'];
function handleCookieProperty(property) {
var length = buf.unpack('n', offset)[0];
offset += 2;
cookie[property] = buf.unpackString(length, offset);
offset += length;
}
while (offset < buf.length)
{
var cookie = {};
cookie.type = buf.readUInt16BE(offset);
var cookie = {};
var typeToName = {
256: 'Local',
65535: 'Wild',
254: 'Netname',
253: 'Krb5Principal',
252: 'LocalHost',
0: 'Internet',
1: 'DECnet',
2: 'Chaos',
5: 'ServerInterpreted',
6: 'InternetV6'
};
cookie.type = buf.unpack('n')[0];
if (!typeToName[cookie.type]) {
console.warn('Unknown address type');
}
offset += 2;
cookieProperties.forEach(function(property) {
var length = buf.unpack('n', offset)[0];
offset += 2;
if (cookie.type === 0 && property == 'address') { // Internet
// 4 bytes of ip addess, convert to w.x.y.z string
cookie.address = [ buf[offset], buf[offset+1], buf[offset+2], buf[offset+3]]
.map(function(octet) { return octet.toString(10) }).join('.');
} else {
cookie[property] = buf.unpackString(length, offset);
}
offset += length;
});
//JSHint becomes angry when handleCookieProperty is declared inside loop
cookieProperties.forEach(handleCookieProperty);
auth.push(cookie);
}
return auth;
}
var homedir = require('os').homedir;
var path = require('path');
function readXauthority(cb) {
var filename = process.env.XAUTHORITY || path.join(homedir(), '.Xauthority');
fs.readFile(filename, function(err, data) {
if (!err)
return cb(null, data);
if(err.code == 'ENOENT') {
// Xming/windows uses %HOME%/Xauthority ( .Xauthority with no dot ) - try with this name
filename = process.env.XAUTHORITY || path.join(homedir(), 'Xauthority');
fs.readFile(filename, function (err, data) {
if (err.code == 'ENOENT') {
cb(null, null);
} else {
cb(err);
}
});
} else {
cb(err);
}
});
}
module.exports = function( display, host, socketFamily, cb )
module.exports = function( display, host, cb )
{
var family;
if (socketFamily === 'IPv4') {
family = 0; // Internet
} else if (socketFamily === 'IPv6') {
family = 6; // Internet6
} else {
family = 256; // Local
}
readXauthority(function(err, data) {
if(err) return cb(err);
if (!data) {
return cb(null, {
authName: '',
authData: ''
});
}
var auth = parseXauth(data);
for (var cookieNum in auth)
var XAuthorityFile = process.env.XAUTHORITY;
if (!XAuthorityFile)
{
var cookie = auth[cookieNum];
if ((typeToName[cookie.family] === 'Wild' || (cookie.type === family && cookie.address === host)) &&
(cookie.display.length === 0 || cookie.display === display))
return cb( null, cookie );
if ( process.platform.match(/win/) ) {
// http://www.straightrunning.com/XmingNotes/trouble.php
//
// The Xming magic cookie program, xauth (user-based), uses an
// Xauthority file (not the traditional .Xauthority file) in
// the %HOME% directory. To use xauth from Command Processor
// e.g. on Windows machine 192.168.0.2 with user colin...
XAuthorityFile = process.env.USERPROFILE + '\\Xauthority';
} else {
XAuthorityFile = process.env.HOME + '/.Xauthority';
}
}
// If no cookie is found, proceed without authentication
cb(null, {
authName: '',
authData: ''
});
});
fs.readFile(XAuthorityFile, function (err, data) {
if (err)
{
if (err.code == 'ENOENT')
{
cb('','');
return;
}
throw err;
}
var auth = parseXauth(data);
for (var cookieNum in auth)
{
var cookie = auth[cookieNum];
if (cookie.display == display && cookie.address == host)
{
cb( cookie.authName, cookie.authData );
return;
}
}
// throw 'No auth cookie matching display=' + display + ' and host=' + host;
cb( '', '' );
});
};

View file

@ -213,30 +213,26 @@ function packValueMask(reqname, values)
if (!reqValueMask)
throw new Error(reqname + ': no value mask description');
for (var value in values)
for (var v in values)
{
var v = reqValueMask[value];
if (v) {
var valueBit = v.mask;
if (!valueBit)
throw new Error(reqname + ': incorrect value param ' + value);
masksList.push(valueBit);
bitmask |= valueBit;
}
var valueBit = reqValueMask[v].mask;
if (!valueBit)
throw new Error(reqname + ': incorrect value param ' + v);
masksList.push(valueBit);
bitmask |= valueBit;
}
/* numeric sort */
masksList.sort(function(a, b) {
return a - b;
return a - b;
});
var args = [];
for (var i=0,length=masksList.length;i<length;i++)
for (m in masksList)
{
var value = masksList[i];
var valueName = reqValueMaskName[value];
format += reqValueMask[valueName].format
args.push( values[valueName] );
var valueName = reqValueMaskName[masksList[m]];
format += reqValueMask[valueName].format
args.push( values[valueName] );
}
return [format, bitmask, args]
}
@ -400,11 +396,6 @@ var templates = {
}
],
LowerWindow: [
function(win) {
return module.exports.ConfigureWindow[0](win, { stackMode : 1 });
}
],
QueryTree: [
['CxSL', [15, 2]],
@ -465,7 +456,7 @@ var templates = {
function(mode, wid, name, type, units, data)
{
var padded4 = (data.length + 3) >> 2;
var pad = Buffer.alloc( (padded4<<2) - data.length);
var pad = new Buffer( (padded4<<2) - data.length);
var format = 'CCSLLLCxxxLaa';
var requestLength = 6 + padded4;
var dataLenInFormatUnits = data.length / (units >> 3);
@ -614,12 +605,6 @@ var templates = {
return [ 'CCSLSxx', [ 34, key, 3, wid, modifiers ] ];
}
],
AllowEvents: [
function(mode, ts) {
return [ 'CCSL', [ 35, mode, 2, ts ] ];
}
],
GrabServer: [
[ 'CxS', [36, 1]]
@ -727,6 +712,12 @@ var templates = {
}
],
FreePixmap: [
function(pixmap) {
return [ 'CxSL', [ 54, 2, pixmap ] ];
}
],
FreePixmap: [
function (pixmap) {
return [ 'CxSL', [54, 2, pixmap] ];
@ -766,19 +757,17 @@ var templates = {
var vals = packValueMask('CreateGC', values);
var packetLength = 3 + (values ? vals[2].length : 0);
var args = [56, packetLength, cid];
format += vals[0]
args.push(vals[1]); // values bitmask
args = args.concat(vals[2])
args.push(vals[0]); // values bitmask
var valArr = vals[1];
for (var v in valArr)
{
format += 'L'; // TODO: we know format string length in advance and += inefficient for string
args.push(valArr[v]);
}
return [format, args];
}
],
ClearArea: [
function(wid, x, y, width, height, exposures) {
return [ 'CCSLssSS', [61, exposures, 4, wid, x, y, width, height] ];
}
],
//
CopyArea: [
function(srcDrawable, dstDrawable, gc, srcX, srcY, dstX, dstY, width, height) {
@ -851,7 +840,7 @@ var templates = {
var padded = xutil.padded_length(data.length);
var reqLen = 6 + padded/4; // (length + 3) >> 2 ???
var padLength = padded - data.length;
var pad = Buffer.alloc(padLength); // TODO: new pack format 'X' - skip amount of bytes supplied in numerical argument
var pad = new Buffer(padLength); // TODO: new pack format 'X' - skip amount of bytes supplied in numerical argument
// TODO: move code to calculate reqLength and use BigReq if needed outside of corereq.js
// NOTE: big req is used here (first 'L' in format, 0 and +1 in params), won't work if not enabled
@ -1020,12 +1009,6 @@ var templates = {
return [ 'CxSssCCxx', [107, 3, timeout, interval, preferBlanking, allowExposures]];
}
],
Bell: [
function(percent) {
return ["CxCs",[108,1]];
}
],
ForceScreenSaver: [
function(activate) {

View file

@ -258,7 +258,7 @@ exports.requireExt = function(display, callback)
ext.BindTexImage = function(ctx, drawable, buffer, attribs) {
if (!attribs)
attribs = [];
var data = Buffer.alloc(12 + attribs.length*4);
var data = new Buffer(12 + attribs.length*4);
data.writeUInt32LE(drawable, 0);
data.writeUInt32LE(buffer, 4);
data.writeUInt32LE(attribs.length, 8);
@ -268,7 +268,7 @@ exports.requireExt = function(display, callback)
}
ext.ReleaseTexImage = function(ctx, drawable, buffer) {
var data = Buffer.alloc(8);
var data = new Buffer(8);
data.writeUint32LE(drawable, 0);
data.writeUint32LE(buffer, 4);
ext.VendorPrivate(ctx, 1331, data);
@ -287,7 +287,7 @@ exports.requireExt = function(display, callback)
X.pack_stream.pack('CCSLSSL', [ext.majorOpcode, 2, length, ctx, requestNum, requestTotal, data.length]);
X.pack_stream.write_queue.push(data);
var pad = Buffer.alloc(padLength);
var pad = new Buffer(padLength);
pad.fill(0);
X.pack_stream.write_queue.push(pad);
X.pack_stream.flush();

View file

@ -16,7 +16,7 @@ module.exports = function(GLX, ctx) {
throw Error('Buffer too big. Make sure you are using RenderLarge for large commands');
currentLength += len;
var res = Buffer.alloc(len);
var res = Buffer(len);
res.writeUInt16LE(len, 0);
res.writeUInt16LE(opcode, 2);
return res;
@ -266,7 +266,7 @@ module.exports = function(GLX, ctx) {
typeSize[constants.BYTE] = 1;
typeSize[constants.UNSIGNED_BYTE] = 1;
var res = Buffer.alloc(60 + data.length*typeSize[type]);
var res = new Buffer(60 + data.length*typeSize[type]);
res.writeUInt32LE(res.length, 0);
res.writeUInt32LE(110, 4);

View file

@ -204,43 +204,7 @@ exports.requireExt = function(display, callback)
X.pack_stream.flush();
},
ext.GetOutputInfo = function(output, ts, cb)
{
X.seq_num ++;
X.pack_stream.pack('CCSLL', [ext.majorOpcode, 9, 3, output, ts ]);
X.replies[X.seq_num] = [
function(buf, opt) {
var i;
var pos = 0;
var res = buf.unpack('LLLLCCSSSSS');
var info = {
timestamp : res[0],
crtc : res[1],
mm_width : res[2],
mm_height : res[3],
connection : res[4],
subpixelOrder : res[5],
preferredModes: res[8]
};
pos += 28;
var format = Array(res[6] + 1).join('L');
info.crtcs = buf.unpack(format, pos);
pos += res[6] << 2;
format = Array(res[7] + 1).join('L');
info.modes = buf.unpack(format, pos);
pos += res[7] << 2;
format = Array(res[9] + 1).join('L');
info.clones = buf.unpack(format, pos);
pos += res[9] << 2;
info.name = buf.slice(pos, pos + res_modes[10]).toString('binary');
return info;
},
cb
];
X.pack_stream.flush();
},
ext.GetCrtcInfo = function(crtc, configTs, cb) {
X.seq_num ++;
X.pack_stream.pack('CCSLL', [ext.majorOpcode, 20, 3, crtc, configTs ]);

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,7 @@ exports.requireExt = function(display, callback)
ext.Kind = {
Bounding: 0,
Clip: 1,
Clip: 1,
Input: 2
};
@ -31,19 +31,12 @@ exports.requireExt = function(display, callback)
Intersect: 2,
Subtract: 3,
Invert: 4
};
ext.Ordering = {
Unsorted: 0,
YSorted: 1,
YXSorted: 2,
YXBanded: 3
};
}
ext.QueryVersion = function(cb)
{
X.seq_num++;
// captureStack();
captureStack();
X.pack_stream.pack('CCSLL', [ext.majorOpcode, 0, 1]);
X.replies[X.seq_num] = [
function(buf, opt) {
@ -55,36 +48,18 @@ exports.requireExt = function(display, callback)
X.pack_stream.flush();
}
// Accepts rectangles as [[x, y, width, height]]
ext.Rectangles = function( op, kind, window, x, y, rectangles, ordering /* = Ordering.Unsorted */ )
{
if (ordering === undefined)
ordering = ext.Ordering.Unsorted;
var length = 4 + rectangles.length * 2;
X.seq_num++;
// captureStack();
X.pack_stream.pack('CCSCCCxLss', [ext.majorOpcode, 1, length, op, kind, ordering, window, x, y]);
for (var i = 0; i < rectangles.length; ++i) {
var r = rectangles[i];
X.pack_stream.pack('ssSS', r);
}
X.pack_stream.flush();
}
ext.Mask = function( op, kind, window, x, y, bitmap )
{
X.seq_num++;
// captureStack();
X.pack_stream.pack('CCSCCxxLssL', [ext.majorOpcode, 2, 5, op, kind, window, x, y, bitmap]);
captureStack();
X.pack_stream.pack('CCSCCxxLssL', [ext.majorOpcode, 2, 5, op, kind, x, y, bitmap]);
X.pack_stream.flush();
}
ext.SelectInput = function( window, enable )
{
X.seq_num++;
// captureStack();
captureStack();
X.pack_stream.pack('CCSLCxxx', [ext.majorOpcode, 6, 3, window, enable ]);
X.pack_stream.flush();
}
@ -92,7 +67,7 @@ exports.requireExt = function(display, callback)
ext.InputSelected = function( window, cb )
{
X.seq_num++;
// captureStack();
captureStack();
X.pack_stream.pack('CCSL', [ext.majorOpcode, 7, 2, window ]);
X.replies[X.seq_num] = [
function(buf, opt) {
@ -112,31 +87,5 @@ exports.requireExt = function(display, callback)
callback(null, ext);
});
*/
ext.events = {
ShapeNotify: 0
}
X.eventParsers[ext.firstEvent + ext.events.ShapeNotify] = function(type, seq, extra, code, raw)
{
var event = {};
event.type = type;
event.kind = code;
event.seq = seq;
event.window = extra;
var values = raw.unpack('ssSSLC');
event.x = values[0];
event.y = values[1];
event.width = values[2];
event.height = values[3];
event.time = values[4];
event.shaped = values[5];
event.name = 'ShapeNotify';
return event;
};
});
}

View file

@ -1,22 +0,0 @@
/*
* GCFunction named shortcuts
*/
module.exports = {
GXclear : 0x0,
GXand : 0x1,
GXandReverse : 0x2,
GXcopy : 0x3,
GXandInverted : 0x4,
GXnoop : 0x5,
GXxor : 0x6,
GXor : 0x7,
GXnor : 0x8,
GXequiv : 0x9,
GXinvert : 0xa,
GXorReverse : 0xb,
GXcopyInverted : 0xc,
GXorInverted : 0xd,
GXnand : 0xe,
GXset : 0xf
};

View file

@ -12,15 +12,15 @@ function readVisuals(bl, visuals, n_visuals, cb)
var visual = {};
bl.unpackTo( visual,
[
'L vid',
'C class',
'C bits_per_rgb',
'L vid',
'C class',
'C bits_per_rgb',
'S map_ent',
'L red_mask',
'L green_mask',
'L blue_mask',
'xxxx'
],
],
function() {
var vid = visual.vid;
// delete visual.vid;
@ -28,65 +28,57 @@ function readVisuals(bl, visuals, n_visuals, cb)
if (Object.keys(visuals).length == n_visuals)
cb()
else
readVisuals(bl, visuals, n_visuals, cb);
readVisuals(bl, visuals, n_visuals, cb);
});
}
function readDepths(bl, display, depths, n_depths, cb)
{
if (n_depths == 0)
{
cb();
return;
}
bl.unpack( 'CxSxxxx', function(res) {
var dep = res[0];
var n_visuals = res[1];
var visuals = {};
readVisuals(bl, visuals, n_visuals, function()
{
depths[dep] = visuals;
if (Object.keys(depths).length == n_depths)
cb();
else
readDepths(bl, display, depths, n_depths, cb);
});
});
}
function readScreens(bl, display, cbDisplayReady)
{
var numParsedDepths = 0;
var readDepths = function(bl, display, depths, n_depths, cb)
{
if (n_depths == 0)
{
cb();
return;
}
bl.unpack( 'CxSxxxx', function(res) {
var dep = res[0];
var n_visuals = res[1];
var visuals = {};
readVisuals(bl, visuals, n_visuals, function()
{
if (dep in depths) {
for (var visual in visuals) {
depths[dep][visual] = visuals[visual];
}
} else {
depths[dep] = visuals;
}
numParsedDepths++;
if (numParsedDepths == n_depths)
cb();
else
readDepths(bl, display, depths, n_depths, cb);
});
});
}
// for (i=0; i < display.screen_num; ++i)
{
var scr = {};
bl.unpackTo( scr,
[
'L root',
'L root',
'L default_colormap',
'L white_pixel',
'L white_pixel',
'L black_pixel',
'L input_masks',
'S pixel_width',
'S pixel_height',
'S mm_width',
'S mm_height',
'S min_installed_maps',
'L input_masks',
'S pixel_width',
'S pixel_height',
'S mm_width',
'S mm_height',
'S min_installed_maps',
'S max_installed_maps',
'L root_visual',
'L root_visual',
'C root_depth',
'C backing_stores',
'C root_depth',
'C num_depths'
],
],
function () {
var depths = {};
readDepths(bl, display, depths, scr.num_depths, function() {
@ -94,17 +86,17 @@ function readScreens(bl, display, cbDisplayReady)
scr.depths = depths;
delete scr.num_depths;
display.screen.push(scr);
if (display.screen.length == display.screen_num)
{
delete display.screen_num;
cbDisplayReady(null, display);
cbDisplayReady(display);
return;
} else {
readScreens(bl, display, cbDisplayReady);
}
});
});
});
}
}
@ -112,18 +104,13 @@ function readServerHello(bl, cb)
{
bl.unpack('C', function(res) {
if (res[0] == 0)
{
// conection time error
// unpack error
bl.unpack('Cxxxxxx', function (rlen) {
bl.get(rlen[0], function (reason) {
var err = new Error;
err.message = 'X server connection failed: ' + reason.toString();
cb(err);
});
});
// unpack error (? TODO)
var err = new Error;
cb(err); // TODO: detect that this is error on xcore side
// TODO: do we need to close stream from our side?
// TODO: api to close source stream via attached unpackstream
return;
@ -137,10 +124,10 @@ bl.unpack('C', function(res) {
'S major',
'S minor',
'S xlen',
'L release',
'L resource_base',
'L resource_mask',
'L motion_buffer_size',
'L release',
'L resource_base',
'L resource_mask',
'L motion_buffer_size',
'S vlen',
'S max_request_length',
'C screen_num',
@ -152,8 +139,8 @@ bl.unpack('C', function(res) {
'C min_keycode',
'C max_keycode',
'xxxx'
],
],
function()
{
var pvlen = xutil.padded_length(display.vlen);
@ -161,12 +148,12 @@ bl.unpack('C', function(res) {
// setup data to generate resource id
// TODO: cleaunup code here
var mask = display.resource_mask;
display.rsrc_shift = 0;
display.rsrc_shift = 0;
while (!( (mask >> display.rsrc_shift) & 1) )
display.rsrc_shift++;
display.rsrc_id = 0;
bl.get(pvlen, function(vendor)
bl.get(pvlen, function(vendor)
{
display.vendor = vendor.toString().substr(0, display.vlen); // utf8 by default?
@ -185,7 +172,7 @@ bl.unpack('C', function(res) {
readScreens(bl, display, cb);
}
});
}
}
});
}
);
@ -202,28 +189,25 @@ function getByteOrder() {
}
}
function writeClientHello(stream, displayNum, authHost, authFamily)
function writeClientHello(stream, displayNum, authHost)
{
getAuthString( displayNum, authHost, authFamily, function( err, cookie ) {
if (err) {
throw err;
}
getAuthString( displayNum, authHost, function( authType, authData ) {
var byte_order = getByteOrder();
var protocol_major = 11; // TODO: config? env?
var protocol_minor = 0;
stream.pack(
'CxSSSSxxpp',
[
'CxSSSSxxpp',
[
byte_order,
protocol_major,
protocol_minor,
cookie.authName.length,
cookie.authData.length,
cookie.authName,
cookie.authData
authType.length,
authData.length,
authType,
authData
]
);
stream.flush();
stream.flush();
});
}

View file

@ -7,7 +7,7 @@
// It should create a pleasant looking hex dumb by default:
//
// var hexy = require('hexy.js'),
// b = Buffer.alloc("\000\001\003\005\037\012\011bcdefghijklmnopqrstuvwxyz0123456789")
// b = new Buffer("\000\001\003\005\037\012\011bcdefghijklmnopqrstuvwxyz0123456789")
//
// console.log(hexy.hexy(b))
//
@ -258,4 +258,4 @@ console.log(hexy(data, format))
console.log("doen")
*/
exports.hexy = hexy
exports.hexy = hexy

View file

@ -1,20 +1,13 @@
var core = require('./xcore');
var em = require('./eventmask').eventMask;
var keysyms = require('./keysyms');
var server = require('./xserver');
module.exports.createClient = core.createClient;
module.exports.createServer = server.createServer;
module.exports.eventMask = em;
module.exports.keySyms = keysyms;
Object.defineProperty(module.exports, 'keySyms', {
enumerable: true,
get: function() { return require('./keysyms'); }
});
Object.defineProperty(module.exports, 'gcFunction', {
enumerable: true,
get: function() { return require('./gcfunction'); }
});
//TODO:
// keepe everything in namespace for consistensy (eventMask, keySyms, class, destination ...

File diff suppressed because it is too large Load diff

View file

@ -1,35 +0,0 @@
#!/bin/bash -e
keysymdef_url=http://cgit.freedesktop.org/xorg/proto/xproto/plain/keysymdef.h
keysymdef=$(mktemp)
wget $keysymdef_url -O $keysymdef
(
echo "
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\\
This file is automatically translated from X.Org's xproto/keysymdef.h
Please, do not update this file with your hands, run $(basename "$0").
\\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
module.exports = {
"
sed -r '
s/#ifdef\s+/\/\/ Group /
s/#endif.*//
s/#define\s+([^ ]+)(\s+)([^ ]+)\s*\/\*\s*([^\*]+[^ ])\s*\*\// \1:\2{ code: \3, description: "\4" },/
s/(\b)U\+([0-9A-F]+)(\b)/\1(\\u\2)\3/i
s/#define\s+([^ ]+)(\s+)([^ ]+)/ \1:\2{ code: \3, description: null },/
#s/#define\s+([^ ]+)(\s+[^ ]+)/ \1:\2,/
' $keysymdef
echo -n '
NoSymbol: 0
};'
) > "$(dirname "$0")/keysyms.js"
rm $keysymdef

View file

@ -23,7 +23,7 @@ function ReadFixedRequest(length, callback)
{
this.length = length;
this.callback = callback;
this.data = Buffer.alloc(length);
this.data = new Buffer(length);
this.received_bytes = 0;
}
@ -201,7 +201,7 @@ UnpackStream.prototype.pstr = function(str)
var len = xutil.padded_length(str.length);
if (len == 0)
return; // nothing to write
var buf = Buffer.alloc(len);
var buf = new Buffer(len);
buf.write(str, 'binary');
this.write_queue.push(buf);
}
@ -231,7 +231,7 @@ UnpackStream.prototype.pack = function(format, args)
}
}
var buf = Buffer.alloc(packetlength);
var buf = new Buffer(packetlength);
var offset = 0;
var arg = 0;
for (var i = 0; i < format.length; ++i)
@ -269,14 +269,12 @@ UnpackStream.prototype.pack = function(format, args)
buf[offset++] = (n >> 16) & 0xff;
buf[offset++] = (n >> 24) & 0xff;
break;
case 'a': // string, buffer, or array
case 'a': // string or buffer
var str = args[arg++];
if (Buffer.isBuffer(str))
{
str.copy(buf, offset);
offset += str.length;
} else if(Array.isArray(str)) {
for(var item of str) buf[offset++] = item;
} else {
// TODO: buffer.write could be faster
for (var c = 0; c < str.length; ++c)

View file

@ -6,6 +6,7 @@ var handshake = require('./handshake');
var EventEmitter = require('events').EventEmitter;
var PackStream = require('./unpackstream');
var coreRequestsTemplate = require('./corereqs');
var hexy = require('./hexy').hexy;
var Buffer = require('buffer').Buffer;
@ -19,28 +20,10 @@ var coreRequests = require('./corereqs');
var stdatoms = require('./stdatoms');
var em = require('./eventmask').eventMask;
function stash ()
{
require('./ext/apple-wm');
require('./ext/big-requests');
require('./ext/composite');
require('./ext/damage');
require('./ext/dpms');
require('./ext/fixes');
require('./ext/glxconstants');
require('./ext/glx');
require('./ext/glxrender');
require('./ext/randr');
require('./ext/render');
require('./ext/screen-saver');
require('./ext/shape');
require('./ext/xc-misc');
require('./ext/xtest');
}
function XClient(displayNum, screenNum, options)
function XClient(stream, displayNum, screenNum, options)
{
EventEmitter.call(this);
this.stream = stream;
this.options = options ? options : {};
// TODO: this is probably not used
@ -49,20 +32,7 @@ function XClient(displayNum, screenNum, options)
this.displayNum = displayNum;
this.screenNum = screenNum;
}
util.inherits(XClient, EventEmitter);
XClient.prototype.init = function(stream)
{
this.stream = stream;
this.authHost = stream.remoteAddress;
// Node v0.10.x does not have stream.remoteFamily, so dig in to find it
this.authFamily = stream._getpeername ? stream._getpeername().family : stream.remoteFamily;
if (!this.authHost || this.authHost === '127.0.0.1' || this.authHost === '::1') {
this.authHost = os.hostname();
this.authFamily = null;
}
this.authHost = os.hostname();
var pack_stream = new PackStream();
@ -132,14 +102,13 @@ XClient.prototype.init = function(stream)
this.event_consumers = {}; // maps window id to eventemitter TODO: bad name
this.eventParsers = {};
this.errorParsers = {};
this._extensions = {};
this.importRequestsFromTemplates(this, coreRequests);
this.startHandshake();
this._closing = false;
this._unusedIds = [];
}
util.inherits(XClient, EventEmitter);
// TODO: close() = set 'closing' flag, watch it in replies and writeQueue, terminate if empty
XClient.prototype.terminate = function()
@ -267,17 +236,12 @@ XClient.prototype.importRequestsFromTemplates = function(target, reqs)
XClient.prototype.AllocID = function()
{
if (this._unusedIds.length > 0) {
return this._unusedIds.pop();
}
// TODO: handle overflow (XCMiscGetXIDRange from XC_MISC ext)
this.display.rsrc_id++;
return (this.display.rsrc_id << this.display.rsrc_shift) + this.display.resource_base;
};
// TODO: handle overflow (XCMiscGetXIDRange from XC_MISC ext)
// TODO: unused id buffer
this.display.rsrc_id++;
return (this.display.rsrc_id << this.display.rsrc_shift) + this.display.resource_base;
}
XClient.prototype.ReleaseID = function(id) {
this._unusedIds.push(id);
};
// TODO: move core events unpackers to corereqs.js
XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
@ -311,8 +275,8 @@ XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
event.y = values[6];
event.buttons = values[7];
event.sameScreen = values[8];
} else if (type == 7 || type == 8) { //EnterNotify || LeaveNotify
event.name = type === 7 ? 'EnterNotify' : 'LeaveNotify';
} else if (type == 7) { //EnterNotify
event.name = 'EnterNotify'
var values = raw.unpack('LLLssssSC');
event.root = values[0]
event.wid = values[1]
@ -322,14 +286,7 @@ XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
event.x = values[5];
event.y = values[6];
event.values = values
} else if (type == 9) { // FocusIn
event.name = "FocusIn";
event.mode = raw.unpack('C')[0];
event.wid = extra;
} else if (type == 10) { // FocusOut
event.name = "FocusOut";
event.mode = raw.unpack('C')[0];
event.wid = extra;
} else if (type == 12) { // Expose
var values = raw.unpack('SSSSS');
event.name = 'Expose'
@ -340,36 +297,36 @@ XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
event.height = values[3];
event.count = values[4]; // TODO: ???
} else if (type == 16) { // CreateNotify
var values = raw.unpack('LssSSSc');
var values = raw.unpack('LLssSSSc');
event.name = 'CreateNotify'
event.parent = extra;
event.wid = values[0];
event.x = values[1];
event.y = values[2];
event.width = values[3];
event.height = values[4];
event.borderWidth = values[5];
event.overrideRedirect = values[6] ? true : false;
event.parent = values[0];
event.wid = values[1];
event.x = values[2];
event.y = values[3];
event.width = values[4];
event.height = values[5];
event.borderWidth = values[6];
event.overrideRedirect = values[7] ? true : false;
// x, y, width, height, border
} else if (type == 17) { // destroy notify
var values = raw.unpack('L');
var values = raw.unpack('LL');
event.name = 'DestroyNotify'
event.event = extra;
event.wid = values[0];
} else if (type == 18) { // UnmapNotify
var values = raw.unpack('LC');
var values = raw.unpack('LLC');
event.name = 'UnmapNotify'
event.event = extra;
event.wid = values[0];
event.fromConfigure = values[1] ? true : false;
} else if (type == 19) { // MapNotify
var values = raw.unpack('LC');
var values = raw.unpack('LLC');
event.name = 'MapNotify'
event.event = extra;
event.wid = values[0];
event.overrideRedirect = values[1] ? true : false;
} else if (type == 20) {
var values = raw.unpack('L');
var values = raw.unpack('LL');
event.name = 'MapRequest'
event.parent = extra;
event.wid = values[0];
@ -443,7 +400,7 @@ XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
event.name = 'ClientMessage';
event.format = code;
event.wid = extra;
event.message_type = raw.unpack('L')[0];
event.type = raw.readUInt32LE(0);
var format = (code === 32) ? 'LLLLL' : (code === 16) ? 'SSSSSSSSSS' : 'CCCCCCCCCCCCCCCCCCCC';
event.data = raw.unpack(format, 4);
} else if (type == 34) {
@ -451,6 +408,9 @@ XClient.prototype.unpackEvent = function(type, seq, extra, code, raw, headerBuf)
event.request = headerBuf[4];
event.firstKeyCode = headerBuf[5];
event.count = headerBuf[6];
// TODO cleanup
console.log(values);
console.log(raw);
}
return event;
}
@ -515,7 +475,7 @@ XClient.prototype.expectReplyHeader = function()
// raw event 32-bytes packet (primarily for use in SendEvent);
// TODO: Event::pack based on event parameters, inverse to unpackEvent
ev.rawData = Buffer.alloc(32);
ev.rawData = new Buffer(32);
headerBuf.copy(ev.rawData);
buf.copy(ev.rawData, 8);
@ -560,16 +520,15 @@ XClient.prototype.expectReplyHeader = function()
);
}
XClient.prototype.startHandshake = function() {
XClient.prototype.startHandshake = function()
{
var client = this;
handshake.writeClientHello(this.pack_stream, this.displayNum, this.authHost, this.authFamily);
handshake.readServerHello(this.pack_stream, function(err, display)
handshake.writeClientHello(this.pack_stream, this.displayNum, this.authHost);
handshake.readServerHello(this.pack_stream, function(display)
{
if (err) {
client.emit('error', err);
return;
}
// TODO: readServerHello can set error state in display
// emit error in that case
client.expectReplyHeader();
client.display = display;
display.client = client;
@ -579,24 +538,9 @@ XClient.prototype.startHandshake = function() {
XClient.prototype.require = function(extName, callback)
{
var self = this;
var ext = this._extensions[extName];
if (ext) {
return process.nextTick(function() {
callback(null, ext);
});
}
ext = require('./ext/' + extName);
ext.requireExt(this.display, function(err, _ext) {
if (err) {
return callback(err);
}
self._extensions[extName] = _ext;
callback(null, _ext);
});
};
var ext = require('./ext/' + extName);
ext.requireExt(this.display, callback);
}
module.exports.createClient = function(options, initCb)
{
@ -616,6 +560,8 @@ module.exports.createClient = function(options, initCb)
throw new Error("Cannot parse display");
var host = displayMatch[1];
if (!host)
host = '127.0.0.1';
var displayNum = displayMatch[2];
if (!displayNum)
@ -626,8 +572,6 @@ module.exports.createClient = function(options, initCb)
// open stream
var stream;
var connected = false;
var cbCalled = false;
var socketPath;
// try local socket on non-windows platforms
@ -640,38 +584,22 @@ module.exports.createClient = function(options, initCb)
{
socketPath = display;
}
} else if(!host)
} else if(host == '127.0.0.1') //TODO check if it's consistent with xlib (DISPLAY=127.0.0.1:0 -> local unix socket or port 6000?)
socketPath = '/tmp/.X11-unix/X' + displayNum;
}
var client = new XClient(displayNum, screenNum, options);
var connectStream = function() {
if (socketPath) {
stream = net.createConnection(socketPath);
} else {
stream = net.createConnection(6000 + parseInt(displayNum), host);
}
stream.on('connect', function() {
connected = true;
client.init(stream);
});
stream.on('error', function(err) {
if (!connected && socketPath && err.code === 'ENOENT') {
// Retry connection with TCP on localhost
socketPath = null;
host = 'localhost';
connectStream();
} else if (initCb && !cbCalled) {
cbCalled = true;
initCb(err);
} else {
client.emit('error', err);
}
});
};
connectStream();
//socketPath = '/tmp/.X11-unix/X' + displayNum;
if(socketPath)
{
stream = net.createConnection(socketPath);
}
else
{
stream = net.createConnection(6000 + parseInt(displayNum), host);
}
var client = new XClient(stream, displayNum, screenNum, options);
if (initCb)
{
var cbCalled = false;
client.on('connect', function(display) {
// opt-in BigReq
if (!options.disableBigRequests) {
@ -689,6 +617,14 @@ module.exports.createClient = function(options, initCb)
initCb(undefined, display);
}
});
stream.on('error', function(err) {
if (cbCalled)
client.emit('error', err);
else {
cbCalled = true;
initCb(err);
}
});
}
return client;
}

View file

@ -12,7 +12,7 @@
"X"
],
"homepage": "https://github.com/sidorares/node-x11",
"version": "2.3.0",
"version": "1.0.2",
"maintainers": [
{
"name": "Andrey Sidorov",
@ -40,15 +40,14 @@
"node": "*"
},
"devDependencies": {
"async": "^3.0.1",
"mocha": "^7.1.2",
"sax": "^1.2.4",
"should": "^13.2.1",
"sinon": "^7.2.5"
"mocha": "*",
"should": "*",
"sax": "*",
"async": "*",
"sinon": "*"
},
"scripts": {
"test": "node test-runner.js",
"prepublish": "npm prune"
},
"dependencies": {}
}
}

View file

@ -1,103 +0,0 @@
var x11 = require('../lib');
var should = require('should');
var assert = require('assert');
// This test was ported from X Test Suite @ http://cgit.freedesktop.org/xorg/test/xts/
function warp_pointer(wid, x, y, cb) {
var self = this;
this.X.QueryPointer(wid, function(err, old_pointer) {
if (err) {
return cb(err);
}
self.X.WarpPointer(0,
wid,
0,
0,
0,
0,
x,
y);
self.X.QueryPointer(wid, function(err, new_pointer) {
if (err) {
return cb(err);
}
cb(undefined, {
old_x : old_pointer.childX,
old_y : old_pointer.childY,
new_x : new_pointer.childX,
new_y : new_pointer.childY
});
});
});
}
function is_pointer_frozen(cb) {
var self = this;
warp_pointer.call(this, this.wid, 0, 0, function(err) {
if (err) {
return cb(err);
}
warp_pointer.call(self, self.wid, 1, 1, function(err, data) {
if (err) {
return cb(err);
}
cb(undefined, data.old_x === data.new_x);
});
});
}
describe('AllowEvents', function() {
before(function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X = dpy.client;
self.screen = dpy.screen[0];
self.root = self.screen.root;
self.wid = self.X.AllocID();
self.X.CreateWindow(self.wid,
self.root,
0,
0,
self.screen.pixel_width,
self.screen.pixel_height);
self.X.MapWindow(self.wid);
done();
});
client.on('error', function (err) {
console.error('Error : ', err);
});
});
it('if pointer is frozen by the client calling AllowEvents with AsyncPointer should resume the processing', function(done) {
var self = this;
this.X.GrabPointer(
this.wid,
false,
x11.eventMask.PointerMotion,
0, // sync
1, // async
0, // None
0, // None
0
);
is_pointer_frozen.call(this, function(err, frozen) {
should.not.exist(err);
frozen.should.equal(true);
self.X.AllowEvents(0, 0);
is_pointer_frozen.call(self, function(err, frozen) {
should.not.exist(err);
frozen.should.equal(false);
done();
});
});
});
});

View file

@ -63,7 +63,7 @@ describe('Atoms and atom names cache', function() {
});
});
xit('should be used after the first request for non-std atom_names', function(done) {
it('should be used after the first request for non-std atom_names', function(done) {
var self = this;
var my_name;
/*
@ -94,7 +94,7 @@ describe('Atoms and atom names cache', function() {
function(err) {
should.not.exist(err);
should.exist(my_name);
self.spy.resetHistory();
self.spy.reset();
self.X.InternAtom(true, my_name, function(err, atom) {
should.not.exist(err);
my_atom.should.equal(atom);

View file

@ -1,34 +0,0 @@
var x11 = require('../lib');
var should = require('should');
describe('requiring an X11 extension on same connection', function() {
before(function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X = dpy.client;
done();
});
client.on('error', function (err) {
console.error('Error : ', err);
});
});
it('should be cached', function(done) {
var self = this;
this.X.require('xtest', function(err, randr) {
should.not.exist(err);
self.X.require('xtest', function(err, randr1) {
should.not.exist(err);
randr.should.equal(randr1);
done();
});
});
});
after(function(done) {
this.X.terminate();
this.X.on('end', done);
});
});

View file

@ -27,7 +27,7 @@ describe('ChangeProperty', function() {
var self = this;
this.X.InternAtom(false, TEST_PROPERTY, function(err, atom) {
should.not.exist(err);
var raw = Buffer.alloc(4);
var raw = new Buffer(4);
raw.writeUInt32LE(self.wid, 0);
self.X.ChangeProperty(0, self.wid, atom, self.X.atoms.WINDOW, 32, raw);
self.X.once('event', function(ev) {
@ -47,7 +47,7 @@ describe('ChangeProperty', function() {
var self = this;
this.X.InternAtom(false, TEST_PROPERTY, function(err, atom) {
should.not.exist(err);
var raw = Buffer.from(new Array(8));
var raw = new Buffer(new Array(8));
raw.writeUInt32LE(self.wid, 0);
raw.writeUInt32LE(self.wid_helper, 4);
self.X.ChangeProperty(0, self.wid, atom, self.X.atoms.ATOM, 32, raw);
@ -69,7 +69,7 @@ describe('ChangeProperty', function() {
var self = this;
this.X.InternAtom(false, TEST_PROPERTY, function(err, atom) {
should.not.exist(err);
var raw = Buffer.alloc(0);
var raw = new Buffer(0);
self.X.ChangeProperty(0, self.wid, atom, self.X.atoms.WINDOW, 32, raw);
self.X.once('event', function(ev) {
ev.type.should.equal(28);

View file

@ -1,54 +0,0 @@
var x11 = require('../lib');
var should = require('should');
describe('CreateGC', function() {
before(function(done) {
var self = this;
this.client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X = dpy.client;
self.root = dpy.screen[0].root;
self.white = dpy.screen[0].white_pixel;
self.black = dpy.screen[0].black_pixel;
self.wid = self.X.AllocID();
self.X.CreateWindow(self.wid, self.root, 0, 0, 1, 1); // 1x1 pixel window
self.X.MapWindow(self.wid);
self.X.QueryTree(self.root, function(err, list) {
should.not.exist(err);
list.children.indexOf(self.wid).should.not.equal(-1);
done();
});
});
});
it('should create a Graphic Context correctly', function() {
var self = this;
this.client.on('error', function(err) {
should.not.exist(err);
});
this.gc = this.X.AllocID();
this.X.CreateGC(this.gc,
this.wid,
{
foreground: this.black,
background: this.white,
lineStyle : 0
}
);
this.X.ChangeGC(this.gc,
{
foreground: 0xffff00,
background: 0x0000ff,
lineStyle : 2
}
);
});
after(function(done) {
this.X.DestroyWindow(this.wid);
this.X.on('end', done);
this.X.terminate();
});
});

View file

@ -1,114 +0,0 @@
var x11 = require('../lib');
var UnpackStream = require('../lib/unpackstream.js');
var should = require('should');
//Used Atoms
var ATOM = {};
describe('ClientMessage', function() {
before(function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X = dpy.client;
self.wid = self.X.AllocID();
self.X.CreateWindow(self.wid, dpy.screen[0].root, 0, 0, 1, 1); // 1x1 pixel window
self.X.InternAtom(false, 'TEST_ATOM_1', function(err, atom) {
should.not.exist(err);
ATOM['TEST_ATOM_1'] = atom;
done();
});
});
client.on('error', done);
});
it('should receive client message with format=8', function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X.once('event', function(ev) {
ev.name.should.equal('ClientMessage');
ev.wid.should.equal(self.wid);
ev.message_type.should.equal(ATOM.TEST_ATOM_1);
ev.data.should.be.an.Array();
ev.data.length.should.equal(20);
done();
});
var X = dpy.client;
var eventData = Buffer.alloc(32);
eventData.writeInt8(33, 0); //Event Type 33 = ClientMessage
eventData.writeInt8(8, 1); //Format
eventData.writeInt32LE(self.wid, 4); //Window ID
eventData.writeInt32LE(ATOM.TEST_ATOM_1, 8); //Message Type
X.SendEvent(self.wid, false, 0, eventData);
});
client.on('error', done);
});
it('should receive client message with format=16', function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X.once('event', function(ev) {
ev.name.should.equal('ClientMessage');
ev.wid.should.equal(self.wid);
ev.message_type.should.equal(ATOM.TEST_ATOM_1);
ev.data.should.be.an.Array();
ev.data.length.should.equal(10);
done();
});
var X = dpy.client;
var eventData = Buffer.alloc(32);
eventData.writeInt8(33, 0); //Event Type 33 = ClientMessage
eventData.writeInt8(16, 1); //Format
eventData.writeInt32LE(self.wid, 4); //Window ID
eventData.writeInt32LE(ATOM.TEST_ATOM_1, 8); //Message Type
X.SendEvent(self.wid, false, 0, eventData);
});
client.on('error', done);
});
it('should receive client message with format=32', function(done) {
var self = this;
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
self.X.once('event', function(ev) {
ev.name.should.equal('ClientMessage');
ev.wid.should.equal(self.wid);
ev.message_type.should.equal(ATOM.TEST_ATOM_1);
ev.data.should.be.an.Array();
ev.data.length.should.equal(5);
done();
});
var X = dpy.client;
var eventData = Buffer.alloc(32);
eventData.writeInt8(33, 0); //Event Type 33 = ClientMessage
eventData.writeInt8(32, 1); //Format
eventData.writeInt32LE(self.wid, 4); //Window ID
eventData.writeInt32LE(ATOM.TEST_ATOM_1, 8); //Message Type
X.SendEvent(self.wid, false, 0, eventData);
});
client.on('error', done);
});
after(function(done) {
this.X.DestroyWindow(this.wid);
this.X.on('end', done);
this.X.terminate();
});
});

View file

@ -72,29 +72,7 @@ describe('ConfigureWindow', function() {
this.X.RaiseWindow(this.wid);
});
it('should LowerWindow correctly', function(done) {
var self = this;
this.X.once('event', function(ev) {
ev.type.should.equal(22); /* ConfigureNotify */
ev.aboveSibling.should.equal(0); /* 0 -> no window below this */
done();
});
this.X.LowerWindow(this.wid);
});
it('should ignore invalid mask values', function(done) {
this.X.once('event', function(ev) {
ev.x.should.equal(0);
done();
});
this.X.ConfigureWindow(this.wid, { foo : 3, x : 0 }, function(err) {
console.log(err);
});
});
after(function(done) {
this.X.removeAllListeners('event');
this.X.DestroyWindow(this.wid);
this.X.DestroyWindow(this.wid_helper);
this.X.on('end', done);

View file

@ -57,47 +57,4 @@ describe('CreateWindow request', function() {
done();
});
});
it('should emit CreateNotify event when', function(done) {
var wid = X.AllocID();
var root = display.screen[0].root;
X.ChangeWindowAttributes(root, { eventMask: x11.eventMask.SubstructureNotify });
X.on('event', function(ev) {
switch (ev.name) {
case 'CreateNotify':
ev.parent.should.equal(root);
ev.wid.should.equal(wid);
ev.x.should.equal(0);
ev.y.should.equal(0);
ev.width.should.equal(1);
ev.height.should.equal(1);
ev.borderWidth.should.equal(0);
ev.overrideRedirect.should.equal(false);
break;
case 'MapNotify':
ev.event.should.equal(root);
ev.wid.should.equal(wid);
ev.overrideRedirect.should.equal(false);
X.UnmapWindow(wid);
break;
case 'UnmapNotify':
ev.event.should.equal(root);
ev.wid.should.equal(wid);
ev.fromConfigure.should.equal(false);
X.DestroyWindow(wid);
break;
case 'DestroyNotify':
ev.event.should.equal(root);
ev.wid.should.equal(wid);
done();
break;
}
});
X.CreateWindow(wid, root, 0, 0, 1, 1); // 1x1 pixel window
X.MapWindow(wid);
})
});

View file

@ -8,41 +8,43 @@ describe('KillKlient request', function() {
var X;
beforeEach(function(done) {
var client = x11.createClient(function(err, dpy) {
should.not.exist(err);
display = dpy;
X = display.client;
var root = display.screen[0].root;
var eventMask = x11.eventMask.SubstructureNotify;
X.ChangeWindowAttributes(root, { eventMask: eventMask });
done();
});
if (!err) {
display = dpy;
X = display.client;
}
client.on('error', done);
done(err);
});
client.on('error', function(err) {
done(err);
});
});
afterEach(function(done) {
X.on('end', done);
X.terminate();
X.on('end', done);
X = null;
display = null;
});
it('should exist as client member', function() {
it('should exist as client member', function(done) {
should.exist(X.KillKlient);
assert.equal(typeof X.KillKlient, 'function');
done();
});
it('should terminate other client connection', function(done) {
x11.createClient(function(err, dpy) {
should.not.exist(err);
var otherclient = dpy.client;
var wnd = otherclient.AllocID();
X.once('event', function(ev) {
ev.name.should.equal('CreateNotify');
ev.wid.should.equal(wnd);
X.KillKlient(wnd);
});
otherclient.CreateWindow(wnd, dpy.screen[0].root, 0, 0, 1, 1);
otherclient.on('end', done);
if (!err) {
var otherclient = dpy.client;
var wnd = otherclient.AllocID();
otherclient.CreateWindow(wnd, dpy.screen[0].root, 0, 0, 1, 1);
otherclient.on('end', done);
X.KillKlient(wnd);
} else {
done(err);
}
});
});
});

View file

@ -1,5 +1,4 @@
var x11 = require('../lib');
var async = require('async');
var should = require('should');
var assert = require('assert');
var util = require('util');
@ -13,7 +12,7 @@ describe('RANDR extension', function() {
self.screen = dpy.screen[0];
self.root = self.screen.root;
self.X.require('randr', function(err, ext) {
should.not.exist(err);
err.should.equal(null);
self.randr = ext;
/* We HAVE to QueryVersion before using it. Otherwise it does not work as expected */
self.randr.QueryVersion(1, 2, done);
@ -36,26 +35,6 @@ describe('RANDR extension', function() {
});
});
it('GetScreenResources && GetOutputInfo', function(done) {
var self = this;
this.randr.GetScreenResources(this.root, function(err, resources) {
should.not.exist(err);
should.exist(resources);
async.each(
resources.outputs,
function(output, cb) {
self.randr.GetOutputInfo(output, 0, function(err, info) {
should.not.exist(err);
should.exist(info);
cb();
});
},
done
);
});
});
after(function(done) {
this.X.terminate();
this.X.on('end', done);

View file

@ -1,16 +0,0 @@
var fs = require('fs');
var assert = require('assert');
describe('all extension modules', function() {
it('should not throw when require\'d', function(done) {
var extFolder = __dirname + '/../lib/ext';
fs.readdir(extFolder, function(err, list) {
assert.ifError(err);
list.forEach(function(name) {
var m = require(extFolder + '/' + name);
});
done();
});
});
})