From 4508f9e93dd42256a65718333fdf5cff80453346 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Tue, 18 Dec 2012 13:08:37 +0100 Subject: [PATCH] Change createClient signature - The new signature is: createClient(options, initCB), where - options is an optional object that defines different parameters such as display, etc. - initCB is an optional callback with the signature: function(err, display) - The initCB is going to be called with an error ONLY if the connection to the X server fails. Further errors in the server connection will be 'emitted'. - Update tests and test-runner.js accordingly. - Update README. --- README.md | 56 +++++++++++++++++++---------------- lib/x11/xcore.js | 30 ++++++++++++------- test-runner.js | 6 ++-- test/connect.js | 33 ++++++++++++++------- test/connection-utils.js | 18 ++++++----- test/core-CreateWindow.js | 11 ++++--- test/core-ForceScreenSaver.js | 11 ++++--- test/core-KillKlient.js | 28 +++++++++++------- test/core-properties.js | 24 ++++++++------- test/dpms.js | 26 +++++++++------- test/errors.js | 11 +++---- test/sequence-overflow.js | 14 +++++---- test/xtest.js | 26 +++++++++------- 13 files changed, 177 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 63f4956..6ceb247 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ `npm install x11` Windows users: -1) install [XMing](http://www.straightrunning.com/XmingNotes/) or [Cygwin/X](http://x.cygwin.com/) +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: @@ -14,42 +14,46 @@ Windows users: # example -Core requsests usage: +Core requests usage: var x11 = require('x11'); var Exposure = x11.eventMask.Exposure; var PointerMotion = x11.eventMask.PointerMotion; - x11.createClient(function(display) { - 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); - }); + 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); + } }); # 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) - + # Protocol documentation @@ -59,7 +63,7 @@ Core requsests usage: # 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: 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 ) - Python/twisted: https://launchpad.net/twisted-x11 diff --git a/lib/x11/xcore.js b/lib/x11/xcore.js index f0cd4fe..2bc9508 100644 --- a/lib/x11/xcore.js +++ b/lib/x11/xcore.js @@ -430,15 +430,18 @@ XClient.prototype.require = function(extName, callback) ext.requireExt(this.display, callback); } -module.exports.createClient = function(initCb, display, options) +module.exports.createClient = function(options, initCb) { - if (!options) - options = false; + if (typeof options === 'function') { + initCb = options; + options = {}; + } + if (!options) options = {}; + + var display = options.display; if (!display) - display = process.env.DISPLAY; - if (!display) - display = ':0'; + display = (process.env.DISPLAY) ? process.env.DISPLAY : ':0'; var displayMatch = display.match(/^(?:[^:]*?\/)?(.*):(\d+)(?:.(\d+))?$/); if (!displayMatch) @@ -485,18 +488,25 @@ module.exports.createClient = function(initCb, display, options) if (initCb) { client.on('connect', function(display) { + // Once connected don't call initCb on error, just emit + stream.removeListener('error', initCb); + stream.on('error', function(err) { + client.emit('error', err); + }); // opt-in BigReq if (!options.disableBigRequests) { client.require('big-requests', function(BigReq) { BigReq.Enable(function(err, maxLen) { display.max_request_length = maxLen; - initCb(display); + initCb(undefined, display); }); }); } else { - initCb(display); + initCb(undefined, display); } }); - } - return client; + + stream.on('error', initCb); + } + return client; } diff --git a/test-runner.js b/test-runner.js index 93b303e..1dea8e8 100644 --- a/test-runner.js +++ b/test-runner.js @@ -14,7 +14,8 @@ var mocha = new Mocha({ // 2 - dpms version is 1.1. // 3 - to be dpms capable. var run_dpms_test = function(cb) { - var client = x11.createClient(function(dpy) { + var client = x11.createClient(function(err, dpy) { + if (err) return cb(false); var display = dpy; var X = display.client; X.require('dpms', function(ext) { @@ -42,7 +43,8 @@ var run_dpms_test = function(cb) { }; var run_xtest_test = function(cb) { - var client = x11.createClient(function(dpy) { + var client = x11.createClient(function(err, dpy) { + if (err) return cb(false); var display = dpy; var X = display.client; X.require('dpms', function(ext) { diff --git a/test/connect.js b/test/connect.js index a154b76..0d1820e 100644 --- a/test/connect.js +++ b/test/connect.js @@ -1,16 +1,22 @@ var x11 = require('../lib/x11'); var should = require('should'); var assert = require('assert'); +var util = require('util'); describe('Client', function() { var display; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - done(); - client.removeListener('error', done); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + done(); + client.removeListener('error', done); + } else { + done(err); + } }); + client.on('error', done); }); @@ -22,13 +28,11 @@ describe('Client', function() { should.exist(display.major); done(); }); - + it('uses display variable from parameter if present ignoring anvironment $DISPLAY', function(done) { var disp = process.env.DISPLAY; process.env.DISPLAY = 'BOGUS DISPLAY'; - var client = x11.createClient(function(display) { - done(); - }, disp); + var client = x11.createClient({ display : disp }, done); client.on('error', done); process.env.DISPLAY=disp; }); @@ -36,14 +40,21 @@ describe('Client', function() { it('throws error if $DISPLAY is bogus', function(done) { try { assert.throws(function() { - var client = x11.createClient(function(display) { + var client = x11.createClient({ display : 'BOGUS DISPLAY' }, function(err, display) { done('Should not reach here'); - }, 'BOGUS DISPLAY'); + }); client.on('error', function(err) { done(); }); }, /Cannot parse display/); done(); } catch(e) { - done(); + done(); } }); + + it('returns error when connecting to non existent display', function(done) { + var client = x11.createClient({ display : ':44' }, function(err, display) { + assert(util.isError(err)); + done(); + }); + }); }); diff --git a/test/connection-utils.js b/test/connection-utils.js index 41863b5..6a25ad5 100644 --- a/test/connection-utils.js +++ b/test/connection-utils.js @@ -6,12 +6,16 @@ describe('Client', function() { var display; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - done(); - client.removeListener('error', done); - }); - client.on('error', done); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + done(); + client.removeListener('error', done); + } else { + done(err); + } + }); + client.on('error', done); }); it('should respond to ping()', function(done) { @@ -21,7 +25,7 @@ describe('Client', function() { it('should allow to enqueue requests and gracefully execute them before close()', function(done) { var count = 0; var pong = function(err) { if (err) return done(err); count++; } - display.client.ping(pong); + display.client.ping(pong); display.client.ping(pong); display.client.ping(pong); display.client.ping(pong); diff --git a/test/core-CreateWindow.js b/test/core-CreateWindow.js index 8dabaa0..2182c3c 100644 --- a/test/core-CreateWindow.js +++ b/test/core-CreateWindow.js @@ -12,10 +12,13 @@ describe('CreateWindow request', function() { var display; var X; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - X = display.client; - done(); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + } + + done(err); }); client.on('error', done); }); diff --git a/test/core-ForceScreenSaver.js b/test/core-ForceScreenSaver.js index 44c79e5..20ddfe6 100644 --- a/test/core-ForceScreenSaver.js +++ b/test/core-ForceScreenSaver.js @@ -7,10 +7,13 @@ describe('ForceScreenSaver request', function() { var display; var X; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - X = display.client; - done(); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + } + + done(err); }); client.on('error', done); }); diff --git a/test/core-KillKlient.js b/test/core-KillKlient.js index f17a62f..898cb70 100644 --- a/test/core-KillKlient.js +++ b/test/core-KillKlient.js @@ -7,13 +7,15 @@ describe('KillKlient request', function() { var display; var X; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - X = display.client; - done(); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + } + + done(err); }); client.on('error', function(err) { - console.log(err); done(err); }); }); @@ -32,12 +34,16 @@ describe('KillKlient request', function() { }); it('should terminate other client connection', function(done) { - x11.createClient(function(dpy) { - 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); + x11.createClient(function(err, dpy) { + 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); + } }); }); diff --git a/test/core-properties.js b/test/core-properties.js index 15b5cd5..5ce3a8e 100644 --- a/test/core-properties.js +++ b/test/core-properties.js @@ -13,13 +13,17 @@ describe('Window property', function() { var X; var wid; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - X = display.client; - wid = X.AllocID(); - X.CreateWindow(wid, display.screen[0].root, 0, 0, 100, 100, 0, 0, 0, 0, { eventMask: x11.eventMask.PropertyChange}); - done(); - client.removeListener('error', done); // all future errors should be attached to corresponding test 'done' + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + wid = X.AllocID(); + X.CreateWindow(wid, display.screen[0].root, 0, 0, 100, 100, 0, 0, 0, 0, { eventMask: x11.eventMask.PropertyChange}); + done(); + client.removeListener('error', done); // all future errors should be attached to corresponding test 'done' + } else { + done(err); + } }); client.on('error', done); }); @@ -38,7 +42,7 @@ describe('Window property', function() { X.GetProperty(0, wid, X.atoms.WM_NAME, X.atoms.STRING, 0, 10000000, function(err, prop) { if (err) return done(err); var propvalget = prop.data.toString(); - assert.equal(propvalset, propvalget, 'get property result different from set property value'); + assert.equal(propvalset, propvalget, 'get property result different from set property value'); done(); }); }); @@ -60,7 +64,7 @@ describe('Window property', function() { done('unexpexted event'); }); }); - + it('should not exist after DeleteProperty called', function(done) { X.on('error', done); var propvalset = "some property value"; @@ -68,7 +72,7 @@ describe('Window property', function() { X.GetProperty(0, wid, X.atoms.WM_NAME, X.atoms.STRING, 0, 10000000, function(err, prop) { if (err) return done(err); var propvalget = prop.data.toString(); - assert.equal(propvalset, propvalget, 'get property result different from set property value'); + assert.equal(propvalset, propvalget, 'get property result different from set property value'); X.DeleteProperty(wid, X.atoms.WM_NAME); X.GetProperty(0, wid, X.atoms.WM_NAME, X.atoms.STRING, 0, 10000000, function(err, prop) { assert.equal(prop.type, 0, 'non-existent property type should be 0'); diff --git a/test/dpms.js b/test/dpms.js index 46601b6..d875343 100644 --- a/test/dpms.js +++ b/test/dpms.js @@ -8,17 +8,21 @@ describe('DPMS extension', function() { var X; var dpms; before(function(done) { - var client = x11.createClient(function(dpy) { - display = dpy; - X = display.client; - X.require('dpms', function(ext) { - if (util.isError(ext)) { - done(ext); - } else { - dpms = ext; - done(); - } - }); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + X.require('dpms', function(ext) { + if (util.isError(ext)) { + done(ext); + } else { + dpms = ext; + done(); + } + }); + } else { + done(err); + } }); client.on('error', done); diff --git a/test/errors.js b/test/errors.js index 4109396..7b971a7 100644 --- a/test/errors.js +++ b/test/errors.js @@ -6,13 +6,14 @@ describe('Client', function() { var display; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - done(); - }); + var client = x11.createClient(function(err, dpy) { + console.log(err) + display = dpy; + done(err); + }); }); - it('should emit error which is instance of Error with seqence number corresponding to source request', function(done) { + it('should emit error which is instance of Error with sequence number corresponding to source request', function(done) { display.client.options.debug = true; display.client.CreateWindow(); // should emit error var seq = display.client.seq_num; diff --git a/test/sequence-overflow.js b/test/sequence-overflow.js index 20187d4..5ae50ad 100644 --- a/test/sequence-overflow.js +++ b/test/sequence-overflow.js @@ -6,10 +6,14 @@ describe('Client', function() { var display; beforeEach(function(done) { - var client = x11.createClient(function(dpy) { - display=dpy; - done(); - client.removeListener('error', done); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + done(); + client.removeListener('error', done); + } else { + done(err); + } }); client.on('error', done); }); @@ -33,7 +37,7 @@ describe('Client', function() { left--; display.client.GetAtomName(1, test); } - + left++; test(); // first call starts sequens and not a callback from GetAtomName, thus left++ }); diff --git a/test/xtest.js b/test/xtest.js index 3d018af..df6e867 100644 --- a/test/xtest.js +++ b/test/xtest.js @@ -8,17 +8,21 @@ describe('XTEST extension', function() { var X; var xtest; before(function(done) { - var client = x11.createClient(function(dpy) { - display = dpy; - X = display.client; - X.require('xtest', function(ext) { - if (util.isError(ext)) { - done(ext); - } else { - xtest = ext; - done(); - } - }); + var client = x11.createClient(function(err, dpy) { + if (!err) { + display = dpy; + X = display.client; + X.require('xtest', function(ext) { + if (util.isError(ext)) { + done(ext); + } else { + xtest = ext; + done(); + } + }); + } else { + done(err); + } }); client.on('error', done);