mirror of
https://github.com/danbulant/node-x11
synced 2026-05-22 22:09:14 +00:00
Merge pull request #54 from santigimeno/randr_requests
Add RANDR SetScreenConfig GetScreenInfo requests
This commit is contained in:
commit
b9b8451f9b
6 changed files with 315 additions and 89 deletions
|
|
@ -4,4 +4,4 @@ before_script:
|
|||
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
- 0.10
|
||||
|
|
|
|||
160
lib/ext/randr.js
160
lib/ext/randr.js
|
|
@ -40,6 +40,67 @@ exports.requireExt = function(display, callback)
|
|||
All: 15
|
||||
};
|
||||
|
||||
ext.Rotation = {
|
||||
Rotate_0: 1,
|
||||
Rotate_90: 2,
|
||||
Rotate_180: 4,
|
||||
Rotate_270: 8,
|
||||
Reflect_X: 16,
|
||||
Reflect_Y: 32
|
||||
};
|
||||
|
||||
ext.ConfigStatus = {
|
||||
Sucess: 0,
|
||||
InvalidConfigTime: 1,
|
||||
InvalidTime: 2,
|
||||
Failed: 3
|
||||
};
|
||||
|
||||
ext.ModeFlag = {
|
||||
HSyncPositive: 1,
|
||||
HSyncNegative: 2,
|
||||
VSyncPositive: 4,
|
||||
VSyncNegative: 8,
|
||||
Interlace: 16,
|
||||
DoubleScan: 32,
|
||||
CSync: 64,
|
||||
CSyncPositive: 128,
|
||||
CSyncNegative: 256,
|
||||
HSkewPresent: 512,
|
||||
BCast: 1024,
|
||||
PixelMultiplex: 2048,
|
||||
DoubleClock: 4096,
|
||||
ClockDivideBy2: 8192
|
||||
}
|
||||
|
||||
ext.SetScreenConfig = function(win, ts, configTs, sizeId, rotation, rate, cb) {
|
||||
X.seq_num ++;
|
||||
X.pack_stream.pack('CCSLLLSSSS', [ext.majorOpcode, 2, 6, win, ts, configTs, sizeId, rotation, rate, 0]);
|
||||
X.replies[X.seq_num] = [
|
||||
function(buf, opt) {
|
||||
var res = buf.unpack('LLLSSLL');
|
||||
return {
|
||||
status : opt,
|
||||
newTs : res [0],
|
||||
configTs : res[1],
|
||||
root : res[2],
|
||||
subpixelOrder : res[3]
|
||||
}
|
||||
},
|
||||
function(err, res) {
|
||||
var err;
|
||||
if (res.status !== 0) {
|
||||
err = new Error('SetScreenConfig error');
|
||||
err.code = res.status;
|
||||
}
|
||||
|
||||
cb(err, res);
|
||||
}
|
||||
];
|
||||
|
||||
X.pack_stream.flush();
|
||||
},
|
||||
|
||||
ext.SelectInput = function(win, mask)
|
||||
{
|
||||
X.seq_num++;
|
||||
|
|
@ -47,6 +108,105 @@ exports.requireExt = function(display, callback)
|
|||
X.pack_stream.flush();
|
||||
},
|
||||
|
||||
ext.GetScreenInfo = function(win, cb) {
|
||||
X.seq_num ++;
|
||||
X.pack_stream.pack('CCSL', [ext.majorOpcode, 5, 2, win]);
|
||||
X.replies[X.seq_num] = [
|
||||
function(buf, opt) {
|
||||
var i, j;
|
||||
var res = buf.unpack('LLLSSSSSS');
|
||||
var info = {
|
||||
rotations : opt,
|
||||
root : res [0],
|
||||
timestamp : res[1],
|
||||
config_timestamp : res[2],
|
||||
sizeID : res[4],
|
||||
rotation : res[5],
|
||||
rate : res[6]
|
||||
};
|
||||
|
||||
var nSizes = res[3];
|
||||
var nInfo = res[7];
|
||||
var screens_len = nSizes << 2;
|
||||
var format = Array(screens_len + 1).join('S');
|
||||
res = buf.unpack(format, 24);
|
||||
info.screens = [];
|
||||
for (i = 0; i < screens_len; i += 4) {
|
||||
info.screens.push({
|
||||
px_width : res[i],
|
||||
px_height : res[i + 1],
|
||||
mm_width : res[i + 2],
|
||||
mm_height : res[i + 3]
|
||||
});
|
||||
}
|
||||
|
||||
format = Array(nInfo + 1).join('S');
|
||||
res = buf.unpack(format, 24 + screens_len * 2);
|
||||
for (i = 0, j = 0; i < info.screens.length; ++i, j += res[j] + 1) {
|
||||
info.screens[i].rates = res.slice(j + 1, j + 1 + res[j]);
|
||||
}
|
||||
|
||||
return info;
|
||||
},
|
||||
cb
|
||||
];
|
||||
|
||||
X.pack_stream.flush();
|
||||
},
|
||||
|
||||
ext.GetScreenResources = function(win, cb)
|
||||
{
|
||||
X.seq_num ++;
|
||||
X.pack_stream.pack('CCSL', [ext.majorOpcode, 8, 2, win]);
|
||||
X.replies[X.seq_num] = [
|
||||
function(buf, opt) {
|
||||
var i;
|
||||
var pos = 0;
|
||||
var res = buf.unpack('LLSSSSxxxxxxxx');
|
||||
var resources = {
|
||||
timestamp : res[0],
|
||||
config_timestamp : res[1],
|
||||
modeinfos : []
|
||||
};
|
||||
|
||||
pos += 24;
|
||||
var format = Array(res[2] + 1).join('L');
|
||||
resources.crcs = buf.unpack(format, pos);
|
||||
pos += res[2] << 2;
|
||||
format = Array(res[3] + 1).join('L');
|
||||
resources.outputs = buf.unpack(format, pos);
|
||||
pos += res[3] << 2;
|
||||
format = Array(res[4] + 1).join('LSSLSSSSSSSSL');
|
||||
res_modes = buf.unpack(format, pos);
|
||||
pos += res[4] << 5;
|
||||
for (i = 0; i < res_modes[4]; i+= 13) {
|
||||
resources.modeinfos.push({
|
||||
id : res_modes[i + 0],
|
||||
width : res_modes[i + 1],
|
||||
height : res_modes[i + 2],
|
||||
dot_clock : res_modes[i + 3],
|
||||
h_sync_start : res_modes[i + 4],
|
||||
h_sync_end : res_modes[i + 5],
|
||||
h_total : res_modes[i + 6],
|
||||
h_skew : res_modes[i + 7],
|
||||
v_sync_start : res_modes[i + 8],
|
||||
v_sync_end : res_modes[i + 9],
|
||||
v_total : res_modes[i + 10],
|
||||
modeflags : res_modes[i + 12],
|
||||
name : buf.slice(pos, pos + res_modes[i + 11]).toString()
|
||||
});
|
||||
|
||||
pos += res_modes[i + 11];
|
||||
}
|
||||
|
||||
return resources;
|
||||
},
|
||||
cb
|
||||
];
|
||||
|
||||
X.pack_stream.flush();
|
||||
},
|
||||
|
||||
X.eventParsers[ext.firstEvent + ext.events.RRScreenChangeNotify] = function(type, seq, extra, code, raw)
|
||||
{
|
||||
var event = {};
|
||||
|
|
|
|||
164
test-runner.js
164
test-runner.js
|
|
@ -6,86 +6,106 @@ var util = require('util');
|
|||
var async = require('async');
|
||||
|
||||
var mocha = new Mocha({
|
||||
timeout : 80000
|
||||
timeout : 80000,
|
||||
reporter : 'spec'
|
||||
});
|
||||
|
||||
// To be able to perform the tests we need the server:
|
||||
// 1 - to support the dpms extension.
|
||||
// 2 - dpms version is 1.1.
|
||||
// 3 - to be dpms capable.
|
||||
var run_dpms_test = function(cb) {
|
||||
var client = x11.createClient(function(err, dpy) {
|
||||
if (err) return cb(false);
|
||||
var display = dpy;
|
||||
var X = display.client;
|
||||
X.require('dpms', function(ext) {
|
||||
if (!util.isError(ext)) {
|
||||
dpms = ext;
|
||||
dpms.GetVersion(undefined, undefined, function(err, version) {
|
||||
if (!err && version[0] === 1 && version[1] === 1) {
|
||||
dpms.Capable(function(err, capable) {
|
||||
if (!err && capable[0] == 1) cb(true);
|
||||
else cb(false);
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.on('error', function() {
|
||||
cb(false);
|
||||
});
|
||||
};
|
||||
|
||||
var run_xtest_test = function(cb) {
|
||||
var client = x11.createClient(function(err, dpy) {
|
||||
if (err) return cb(false);
|
||||
var display = dpy;
|
||||
var X = display.client;
|
||||
X.require('dpms', function(ext) {
|
||||
if (!util.isError(ext)) cb(true);
|
||||
else cb(false);
|
||||
});
|
||||
});
|
||||
|
||||
client.on('error', function() {
|
||||
cb(false);
|
||||
});
|
||||
};
|
||||
|
||||
// Add all files from test root directory
|
||||
async.forEach(
|
||||
fs.readdirSync('./test'),
|
||||
function(file, cb) {
|
||||
if (file === 'dpms.js') {
|
||||
run_dpms_test(function(run) {
|
||||
if (run) {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
var run_dpms_test = function(X, cb) {
|
||||
X.require('dpms', function(ext) {
|
||||
if (!util.isError(ext)) {
|
||||
dpms = ext;
|
||||
dpms.GetVersion(undefined, undefined, function(err, version) {
|
||||
if (!err && version[0] === 1 && version[1] === 1) {
|
||||
dpms.Capable(function(err, capable) {
|
||||
if (!err && capable[0] == 1) cb(true);
|
||||
else cb(false);
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
} else if (file === 'xtest.js') {
|
||||
run_xtest_test(function(run) {
|
||||
if (run) {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
} else {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
cb();
|
||||
cb(false);
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
mocha.run(function() {
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var run_xtest_test = function(X, cb) {
|
||||
X.require('xtest', function(ext) {
|
||||
if (!util.isError(ext)) cb(true);
|
||||
else cb(false);
|
||||
});
|
||||
};
|
||||
|
||||
var run_randr_test = function(X, cb) {
|
||||
X.require('randr', function(ext) {
|
||||
if (!util.isError(ext)) {
|
||||
randr = ext;
|
||||
randr.QueryVersion(1, 2, function(err, version) {
|
||||
if (err) {
|
||||
cb(false);
|
||||
} else {
|
||||
cb((version[0] === 1) && (version[1] >= 2));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
x11.createClient(function(err, display) {
|
||||
if (err) {
|
||||
console.log('Could not create X client');
|
||||
process.exit(-1);
|
||||
}
|
||||
);
|
||||
|
||||
var X = display.client;
|
||||
// Add all files from test root directory
|
||||
async.forEach(
|
||||
fs.readdirSync('./test'),
|
||||
function(file, cb) {
|
||||
if (file === 'dpms.js') {
|
||||
run_dpms_test(X, function(run) {
|
||||
if (run) {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
} else if (file === 'xtest.js') {
|
||||
run_xtest_test(X, function(run) {
|
||||
if (run) {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
} else if (file === 'randr.js') {
|
||||
run_randr_test(X, function(run) {
|
||||
if (run) {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
} else {
|
||||
mocha.addFile(path.join('./test', file));
|
||||
cb();
|
||||
}
|
||||
},
|
||||
function() {
|
||||
X.terminate();
|
||||
X.on('end', function() {
|
||||
mocha.run(function(failures) {
|
||||
process.exit(failures);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ describe('Window property', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should exist in the ListProperties result after inserted');
|
||||
it('should not exist after GetProperty with delete flag called');
|
||||
// it('should exist in the ListProperties result after inserted');
|
||||
// it('should not exist after GetProperty with delete flag called');
|
||||
//it('should not exist after GetProperty with delete flag called', function(done) {
|
||||
// done();
|
||||
//});
|
||||
|
|
|
|||
|
|
@ -5,26 +5,30 @@ var assert = require('assert');
|
|||
describe('Client', function() {
|
||||
|
||||
var display;
|
||||
beforeEach(function(done) {
|
||||
var client = x11.createClient({ debug: true }, function(err, dpy) {
|
||||
console.log(err)
|
||||
before(function(done) {
|
||||
var client = x11.createClient({ debug: false }, function(err, dpy) {
|
||||
should.not.exist(err);
|
||||
display = dpy;
|
||||
done(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit error which is instance of Error with sequence number corresponding to source request', function(done) {
|
||||
var times = 0;
|
||||
display.client.CreateWindow(); // should emit error
|
||||
var seq = display.client.seq_num;
|
||||
display.client.once('error', function(err) {
|
||||
assert.equal(err.constructor, Error);
|
||||
assert.equal(seq, err.seq);
|
||||
display.client.CreateWindow(); // should emit error
|
||||
seq = display.client.seq_num;
|
||||
display.client.once('error', function(err) {
|
||||
assert.equal(seq, err.seq);
|
||||
done();
|
||||
});
|
||||
});
|
||||
display.client.on('error', function(err) {
|
||||
switch (++ times) {
|
||||
case 11:
|
||||
display.client.removeAllListeners('error');
|
||||
done();
|
||||
break;
|
||||
default:
|
||||
assert.equal(err.constructor, Error);
|
||||
assert.equal(seq, err.seq);
|
||||
display.client.CreateWindow(); // should emit error
|
||||
seq = display.client.seq_num;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
42
test/randr.js
Normal file
42
test/randr.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
var x11 = require('../lib');
|
||||
var should = require('should');
|
||||
var assert = require('assert');
|
||||
var util = require('util');
|
||||
|
||||
describe('RANDR extension', 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.X.require('randr', function(ext) {
|
||||
util.isError(ext).should.equal(false);
|
||||
self.randr = ext;
|
||||
/* We HAVE to QueryVersion before using it. Otherwise it does not work as expected */
|
||||
self.randr.QueryVersion(1, 2, done);
|
||||
});
|
||||
});
|
||||
|
||||
client.on('error', done);
|
||||
});
|
||||
|
||||
it('GetScreenInfo should get same px and mm width and height as in display.screen[0]', function(done) {
|
||||
var self = this;
|
||||
this.randr.GetScreenInfo(this.root, function(err, info) {
|
||||
should.not.exist(err);
|
||||
var active_screen = info.screens[info.sizeID];
|
||||
active_screen.px_width.should.equal(self.screen.pixel_width);
|
||||
active_screen.px_height.should.equal(self.screen.pixel_height);
|
||||
active_screen.mm_width.should.equal(self.screen.mm_width);
|
||||
active_screen.mm_height.should.equal(self.screen.mm_height);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
this.X.terminate();
|
||||
this.X.on('end', done);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue