From 3f4c8b57009b4f327e80b24f91105cddcc5c4838 Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Fri, 15 Jul 2011 18:42:28 +1000 Subject: [PATCH 1/2] MotionNotify unpack code --- lib/x11/xcore.js | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/x11/xcore.js b/lib/x11/xcore.js index 78b1ae4..e758c5d 100644 --- a/lib/x11/xcore.js +++ b/lib/x11/xcore.js @@ -82,6 +82,7 @@ XClient.prototype.importRequestsFromTemplates = function(target, reqs) // r is request name target[r] = (function(reqName) { var reqFunc = function req_proxy() { + client.seq_num++; // TODO: handle overflw (seq should be last 15 (?) bits of the number var args = Array.prototype.slice.call(req_proxy.arguments); // TODO: setup last argument to be reply/error callback // var callback = args.length > 0 ? null : args[args.length - 1]; @@ -127,6 +128,31 @@ XClient.prototype.AllocID = function() return (this.display.rsrc_id << this.display.rsrc_shift) + this.display.resource_base; } +XClient.prototype.unpackEvent = function(type, seq, extra, raw) +{ + var event = {}; // TODO: constructor & base functions + event.type = type; + event.seq = seq; + + if (type == 6) { // motion event + var values = raw.unpack('LLLSSSSSC'); //TODO: should be LLLLsssssSC + //event.raw = values; + // TODO: use unpackTo??? + event.time = extra; + event.root = values[0]; + event.wid = values[1]; + event.child = values[2]; + event.rootx = values[3]; + event.rooty = values[4]; + event.x = values[5]; + event.y = values[6]; + event.buttons = values[7]; + event.sameScreen = values[8]; + } + //console.log(event); + return event; +} + XClient.prototype.expectReplyHeader = function() { var client = this; @@ -147,8 +173,11 @@ XClient.prototype.expectReplyHeader = function() } else if (type > 1) { client.pack_stream.get(24, function(buf) { + var extra = res[3]; + var ev = client.unpackEvent(type, seq_num, extra, buf); + client.emit('event', ev); // TODO: dispatch, use sequence number - console.error('event!!!! ' + type); + // console.error('event!!!! ' + type); client.expectReplyHeader(); } ); return; From 3d3658d0b81642440a915e706d2c28b412c1a383 Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Mon, 18 Jul 2011 10:18:52 +1000 Subject: [PATCH 2/2] Atoms requests, handling replies (work in progress) --- lib/x11/corereqs.js | 28 +++++++++++++++++++++++--- lib/x11/xcore.js | 31 +++++++++++++++++++++-------- lib/x11/xutil.js | 10 +++++++--- test/atoms.js | 14 +++++++++++++ test/c-tests/Makefile | 3 +++ test/c-tests/simplewin | Bin 0 -> 7562 bytes test/c-tests/simplewin.c | 42 +++++++++++++++++++++++++++++++++++++++ test/c-tests/simplewin.o | Bin 0 -> 2140 bytes test/testwnd.js | 32 +++++++++++++++++++++++++++-- test/wndwrap.js | 42 +++++++++++++++++++-------------------- 10 files changed, 165 insertions(+), 37 deletions(-) create mode 100644 test/atoms.js create mode 100644 test/c-tests/Makefile create mode 100755 test/c-tests/simplewin create mode 100644 test/c-tests/simplewin.c create mode 100644 test/c-tests/simplewin.o diff --git a/lib/x11/corereqs.js b/lib/x11/corereqs.js index bcdae15..24edcfb 100644 --- a/lib/x11/corereqs.js +++ b/lib/x11/corereqs.js @@ -1,3 +1,5 @@ +var xutil = require('./xutil'); + var valueMask = { CreateWindow: { backgroundPixmap: 0x00000001, @@ -65,7 +67,7 @@ function packValueMask(reqname, values) { var valueBit = reqValueMask[v]; if (!valueBit) - throw new Error('CreateWindow: incorrect value param ' + v); + throw new Error(reqname + ': incorrect value param ' + v); masksList.push(valueBit); bitmask |= valueBit; } @@ -104,7 +106,7 @@ the way requests are described here module.exports = { CreateWindow: [ // create request packet - function OR format string - function(id, parentId, x, y, width, height, borderWidth, class, visual, values) { + function(id, parentId, x, y, width, height, borderWidth, _class, visual, values) { // TODO: ??? there is depth field in xproto, but xlib just sets it to zero var depth = 0; @@ -116,7 +118,7 @@ module.exports = { // create bitmask var bitmask = 0; // TODO: slice from function arguments? - var args = [1, depth, packetLength, id, parentId, x, y, width, height, borderWidth, class, visual]; + var args = [1, depth, packetLength, id, parentId, x, y, width, height, borderWidth, _class, visual]; // TODO: the code is a little bit mess // additional values need to be packed in the following way: @@ -178,5 +180,25 @@ module.exports = { } return [format, args]; } + ], + + // opcode 16 + InternAtom: [ + function (returnOnlyIfExist, value) + { + var padded = xutil.padded_string(value); + return ['CCSSa', [16, returnOnlyIfExist ? 1 : 0, 2+padded.length/4, value.length, value] ]; + }, + + function(stream, buf) { + console.error('Intern Atom reply !!!!'); + } + ], + + GetAtomName: [ + [ 'CxSL', [17, 2] ], + function(stream, buf) { + console.error('Intern GetAtomName reply !!!!'); + } ] } diff --git a/lib/x11/xcore.js b/lib/x11/xcore.js index e758c5d..d281e89 100644 --- a/lib/x11/xcore.js +++ b/lib/x11/xcore.js @@ -7,7 +7,7 @@ var handshake = require('./handshake'); var EventEmitter = require('events').EventEmitter; var PackStream = require('./unpackstream'); var coreRequestsTemplate = require('./corereqs'); -//var hexy = require('./hexy').hexy; +var hexy = require('./hexy').hexy; var Buffer = require('buffer').Buffer; // add 'unpack' method for buffer @@ -57,6 +57,8 @@ function XClient(stream) this.importRequestsFromTemplates(this, coreRequests); this.startHandshake(); + this.event_consumers = {}; // maps window id to eventemitter + // import available extentions // TODO: lazy import on first call? /* @@ -82,8 +84,11 @@ XClient.prototype.importRequestsFromTemplates = function(target, reqs) // r is request name target[r] = (function(reqName) { var reqFunc = function req_proxy() { - client.seq_num++; // TODO: handle overflw (seq should be last 15 (?) bits of the number + client.seq_num++; // TODO: handle overflow (seq should be last 15 (?) bits of the number + + // is it fast? var args = Array.prototype.slice.call(req_proxy.arguments); + // TODO: setup last argument to be reply/error callback // var callback = args.length > 0 ? null : args[args.length - 1]; @@ -102,6 +107,7 @@ XClient.prototype.importRequestsFromTemplates = function(target, reqs) reqPack = reqTemplate.apply(this, req_proxy.arguments); var format = reqPack[0]; var requestArguments = reqPack[1]; + console.error([format, requestArguments]); client.pack_stream.pack(format, requestArguments); client.pack_stream.flush(); } else if (templateType == 'Array'){ @@ -109,6 +115,7 @@ XClient.prototype.importRequestsFromTemplates = function(target, reqs) var requestArguments = reqTemplate[1]; for (a in args) requestArguments.push(args[a]); + console.error([format, requestArguments]); client.pack_stream.pack(format, requestArguments); client.pack_stream.flush(); } else { @@ -149,7 +156,6 @@ XClient.prototype.unpackEvent = function(type, seq, extra, raw) event.buttons = values[7]; event.sameScreen = values[8]; } - //console.log(event); return event; } @@ -176,18 +182,27 @@ XClient.prototype.expectReplyHeader = function() var extra = res[3]; var ev = client.unpackEvent(type, seq_num, extra, buf); client.emit('event', ev); - // TODO: dispatch, use sequence number - // console.error('event!!!! ' + type); + var ee = client.event_consumers[ev.wid]; + if (ee) { + ee.emit('event', ev); + } client.expectReplyHeader(); } ); return; } var opt_data = res[1]; - var length_total = res[3]; // in 4-bytes units, _including_ this header - var bodylength = (length_total-2)*4; // length of the data in bytes + var length_total = res[3]; // in 4-bytes units, _including_ this header + var bodylength = 24 + length_total*4; // 24 is rest if 32-bytes header + + console.log(res); + console.log('reply of length ' + bodylength + ' should follow'); client.pack_stream.get( bodylength, function( data ) { + + var handler = this.replyHandlers[seq_num]; + // TODO: decode and dispatch, use sequence number - console.error('reply data!!!'); + console.error('reply data!!!!!!!!!!'); + console.error(hexy(data, { prefix: 'InternAtom reply' })); // wait for new packet from server client.expectReplyHeader(); diff --git a/lib/x11/xutil.js b/lib/x11/xutil.js index b401faf..87e4599 100644 --- a/lib/x11/xutil.js +++ b/lib/x11/xutil.js @@ -7,15 +7,19 @@ function padded_length(len) return padded_length; } +// TODO: make it return buffer? +// str += is slow function padded_string(str) { - if (str.length == 0); + if (str.length == 0) return ''; - var len = padded_length(str.len); + var pad = padded_length(str.length) - str.length; var res = str; - for (var i=0; i < len; ++i) + for (var i=0; i < pad; ++i) res += String.fromCharCode(0); + + return res; } module.exports.padded_length = padded_length; diff --git a/test/atoms.js b/test/atoms.js new file mode 100644 index 0000000..fba1db7 --- /dev/null +++ b/test/atoms.js @@ -0,0 +1,14 @@ +var x11 = require('../lib/x11'); + +var xclient = x11.createClient(); + +xclient.on('connect', function(display) { + var X = this; + var hello = 'Hello, node.js'; + X.InternAtom(false, hello, function(atomId) { + console.log(atomId); + }); + X.InternAtom(true, 'test', function(atomId) { + console.log(atomId); + }); +}); diff --git a/test/c-tests/Makefile b/test/c-tests/Makefile new file mode 100644 index 0000000..9b00c85 --- /dev/null +++ b/test/c-tests/Makefile @@ -0,0 +1,3 @@ +LDFLAGS=-lX11 + +simplewin: simplewin.o diff --git a/test/c-tests/simplewin b/test/c-tests/simplewin new file mode 100755 index 0000000000000000000000000000000000000000..d310a8f62f116a68a082208602af70b615450283 GIT binary patch literal 7562 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 S-*oIkdWX?BEYw4awC7(&%})^k literal 0 HcmV?d00001 diff --git a/test/c-tests/simplewin.c b/test/c-tests/simplewin.c new file mode 100644 index 0000000..a3f3926 --- /dev/null +++ b/test/c-tests/simplewin.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +int main(void) { + Display *d; + Window w, w1; + XEvent e; + char *msg = "Hello, world!"; + int s; + + d = XOpenDisplay(NULL); + if (d == NULL) { + fprintf(stderr, "Cannot open display\n"); + exit(1); + } + + s = DefaultScreen(d); + w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, + BlackPixel(d, s), WhitePixel(d, s)); + + w1 = XCreateSimpleWindow(d, RootWindow(d, s), 50, 50, 50, 50, 1, + BlackPixel(d, s), WhitePixel(d, s)); + XSelectInput(d, w, ExposureMask | KeyPressMask); + XSelectInput(d, w1, ExposureMask); + XMapWindow(d, w); + XMapWindow(d, w1); + + while (1) { + XNextEvent(d, &e); + if (e.type == Expose) { + XFillRectangle(e.xany.display, e.xany.window, DefaultGC(d, s), 20, 20, 10, 10); + XDrawString(e.xany.display, e.xany.window, DefaultGC(d, s), 10, 50, msg, strlen(msg)); + } + if (e.type == KeyPress) + break; + } + + XCloseDisplay(d); + return 0; +} diff --git a/test/c-tests/simplewin.o b/test/c-tests/simplewin.o new file mode 100644 index 0000000000000000000000000000000000000000..41e84e68755852874aae7e85a590576a5d1c1f90 GIT binary patch literal 2140 zcmb_d&x;gC6n@>)nn@hp)r>(f;D{YD=ynpFz#s}6wp~Y-`~^8g2tue*w!wCmy_530ZV-j8~( zs$R`pJ=U1kG>w#KRG?KxR5UV6HHCe&iHbB6KU@0k#TU)%&mTZ5?v(M3Z56I7pn8Xu@uLS@7*3ldxEDDdXmH-xFw+o(Gfn3S!jo$^ z*lL@TDf{{xu;jEk8UOs_ueyeham&z>R&_mVy_Q<Id^j5};jHt%o6=PX5_>uMU|Nqq;l+{TrNh~t1QC*EsTf2snL#25;+bFZu^0u}7 zp?k^i4{iCDZ8p{jZ!G;?8oPNPb**zT-i4> zKk%c$2MyPE!k|*MKDG`{)CQ@t`hLcVtp4S0=@=~RwaAMm=?7R=|7bVR1 zDgtCak>mUZm9TwU5g_wsj-ShMH^&!q{A!LTIsR>qQ{V0OJTY{At4&?U^{I6Vuhz~U zE%l?02t&Fs4BbeOSac(5O@+dVL^F;1()ByRkXlXQiFS0t?+xJasnb*XlX$4dzTy|z znszC2sKFI<|t;J6;@-i@K*%J@um zG|*AzXe?Xm&$E6L5&P;TqB5FA#|7S#_zNTcnE#ZhqfzxSqIV=tFya!H8PV|HG2+5s SFuskRMGxrs0o=p5o#