1085 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1085 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // full list of event/error/request codes for all extensions:
 | |
| // http://www.opensource.apple.com/source/X11server/X11server-106.7/kdrive/xorg-server-1.6.5-apple3/dix/protocol.txt
 | |
| 
 | |
| var xutil = Require('x11/core/xutil');
 | |
| var hexy = Require('x11/core/hexy').hexy;
 | |
| 
 | |
| var valueMask = {
 | |
|     CreateWindow: {
 | |
|         backgroundPixmap      : {
 | |
|           mask: 0x00000001,
 | |
|           format: 'L'
 | |
|         },
 | |
|         backgroundPixel       : {
 | |
|           mask: 0x00000002,
 | |
|           format: 'L'
 | |
|         },
 | |
|         borderPixmap          : {
 | |
|           mask: 0x00000004,
 | |
|           format: 'L'
 | |
|         },
 | |
|         borderPixel           : {
 | |
|           mask: 0x00000008,
 | |
|           format: 'L'
 | |
|         },
 | |
|         bitGravity            : {
 | |
|           mask: 0x00000010,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|         winGravity            : {
 | |
|           mask: 0x00000020,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|         backingStore          : {
 | |
|           mask: 0x00000040,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|         backingPlanes         : {
 | |
|           mask: 0x00000080,
 | |
|           format: 'L'
 | |
|         },
 | |
|         backingPixel          : {
 | |
|           mask: 0x00000100,
 | |
|           format: 'L'
 | |
|         },
 | |
|         overrideRedirect      : {
 | |
|           mask: 0x00000200,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|         saveUnder             : {
 | |
|           mask: 0x00000400,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|         eventMask             : {
 | |
|           mask: 0x00000800,
 | |
|           format: 'L'
 | |
|         },
 | |
|         doNotPropagateMask    : {
 | |
|           mask: 0x00001000,
 | |
|           format: 'L'
 | |
|         },
 | |
|         colormap              : {
 | |
|           mask: 0x00002000,
 | |
|           format: 'L'
 | |
|         },
 | |
|         cursor                : {
 | |
|           mask: 0x00004000,
 | |
|           format: 'L'
 | |
|         }
 | |
|     },
 | |
|     CreateGC: {
 | |
|        'function'             : { // TODO: alias? _function?
 | |
|           mask: 0x00000001,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        planeMask              : {
 | |
|           mask: 0x00000002,
 | |
|           format: 'L'
 | |
|         },
 | |
|        foreground             : {
 | |
|           mask: 0x00000004,
 | |
|           format: 'L'
 | |
|         },
 | |
|        background             : {
 | |
|           mask: 0x00000008,
 | |
|           format: 'L'
 | |
|         },
 | |
|        lineWidth              : {
 | |
|           mask: 0x00000010,
 | |
|           format: 'Sxx'
 | |
|         },
 | |
|        lineStyle              : {
 | |
|           mask: 0x00000020,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        capStyle               : {
 | |
|           mask: 0x00000040,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        joinStyle              : {
 | |
|           mask: 0x00000080,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        fillStyle              : {
 | |
|           mask: 0x00000100,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        fillRule               : {
 | |
|           mask: 0x00000200,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        tile                   : {
 | |
|           mask: 0x00000400,
 | |
|           format: 'L'
 | |
|         },
 | |
|        stipple                : {
 | |
|           mask: 0x00000800,
 | |
|           format: 'L'
 | |
|         },
 | |
|        tileStippleXOrigin     : {
 | |
|           mask: 0x00001000,
 | |
|           format: 'sxx'
 | |
|         },
 | |
|        tileStippleYOrigin     : {
 | |
|           mask: 0x00002000,
 | |
|           format: 'sxx'
 | |
|         },
 | |
|        font                   : {
 | |
|           mask: 0x00004000,
 | |
|           format: 'L'
 | |
|         },
 | |
|        subwindowMode          : {
 | |
|           mask: 0x00008000,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        graphicsExposures      : {
 | |
|           mask: 0x00010000,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        clipXOrigin            : {
 | |
|           mask: 0x00020000,
 | |
|           format: 'Sxx'
 | |
|         },
 | |
|        clipYOrigin            : {
 | |
|           mask: 0x00040000,
 | |
|           format: 'Sxx'
 | |
|         },
 | |
|        clipMask               : {
 | |
|           mask: 0x00080000,
 | |
|           format: 'L'
 | |
|         },
 | |
|        dashOffset             : {
 | |
|           mask: 0x00100000,
 | |
|           format: 'Sxx'
 | |
|         },
 | |
|        dashes                 : {
 | |
|           mask: 0x00200000,
 | |
|           format: 'Cxxx'
 | |
|         },
 | |
|        arcMode                : {
 | |
|           mask: 0x00400000,
 | |
|           format: 'Cxxx'
 | |
|         }
 | |
|     },
 | |
|     ConfigureWindow: {
 | |
|       x                       : {
 | |
|         mask: 0x000001,
 | |
|         format: 'sxx'
 | |
|       },
 | |
|     	y                       : {
 | |
|         mask: 0x000002,
 | |
|         format: 'sxx'
 | |
|       },
 | |
|     	width                   : {
 | |
|         mask: 0x000004,
 | |
|         format: 'Sxx'
 | |
|       },
 | |
|     	height                  : {
 | |
|         mask: 0x000008,
 | |
|         format: 'Sxx'
 | |
|       },
 | |
|     	borderWidth             : {
 | |
|         mask: 0x000010,
 | |
|         format: 'Sxx'
 | |
|       },
 | |
|     	sibling                 : {
 | |
|         mask: 0x000020,
 | |
|         format: 'L'
 | |
|       },
 | |
|     	stackMode               : {
 | |
|         mask: 0x000040,
 | |
|         format: 'Cxxx'
 | |
|       }
 | |
|     }
 | |
| };
 | |
| 
 | |
| 
 | |
| var valueMaskName = {};
 | |
| for (var req in valueMask) {
 | |
|     var masks = valueMask[req];
 | |
|     var names = valueMaskName[req] = {};
 | |
|     for (var m in masks)
 | |
|         names[masks[m].mask] = m;
 | |
| }
 | |
| 
 | |
| function packValueMask(reqname, values)
 | |
| {
 | |
|     var bitmask = 0;
 | |
|     var masksList = [];
 | |
|     var format = '';
 | |
|     var reqValueMask = valueMask[reqname];
 | |
|     var reqValueMaskName = valueMaskName[reqname];
 | |
| 
 | |
|     if (!reqValueMask)
 | |
|         throw new Error(reqname + ': no value mask description');
 | |
| 
 | |
|     for (var value 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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* numeric sort */
 | |
|     masksList.sort(function(a, b) {
 | |
|       return a - b;
 | |
|     });
 | |
| 
 | |
|     var args = [];
 | |
|     for (m in masksList)
 | |
|     {
 | |
|        var valueName = reqValueMaskName[masksList[m]];
 | |
|        format += reqValueMask[valueName].format
 | |
|        args.push( values[valueName] );
 | |
|     }
 | |
|     return [format, bitmask, args]
 | |
| }
 | |
| 
 | |
| /*
 | |
| 
 | |
| the way requests are described here
 | |
| 
 | |
| - outgoing request
 | |
| 
 | |
|    1) as function
 | |
|    client.CreateWindow( params, params ) ->
 | |
|        req = reqs.CreateWindow[0]( param, param );
 | |
|        pack_stream.pack(req[0], req[1]);
 | |
| 
 | |
|    2) as array: [format, [opcode, request_length, additional known params]]
 | |
| 
 | |
|    client.MapWindow[0](id) ->
 | |
|        req = reqs.MwpWindow;
 | |
|        req[1].push(id);
 | |
|        pack_stream.pack( req[0], req[1] );
 | |
| 
 | |
| - reply
 | |
| 
 | |
| */
 | |
| 
 | |
| var templates = {
 | |
|    CreateWindow: [
 | |
|        // create request packet - function OR format string
 | |
|        function(id, parentId, x, y, width, height, borderWidth, depth, _class, visual, values) {
 | |
| 
 | |
|            if (borderWidth === undefined)
 | |
|                borderWidth = 0;
 | |
|            if (depth === undefined)
 | |
|                depth = 0;
 | |
|            if (_class === undefined)
 | |
|                _class = 0;
 | |
|            if (visual === undefined)
 | |
|                visual = 0;
 | |
|            if (values === undefined)
 | |
|                values = {}
 | |
| 
 | |
|            var format = 'CCSLLssSSSSLL';
 | |
| 
 | |
|            // TODO: slice from function arguments?
 | |
| 
 | |
|            // TODO: the code is a little bit mess
 | |
|            // additional values need to be packed in the following way:
 | |
|            // bitmask (bytes #24 to #31 in the packet) - 32 bit indicating what adittional arguments we supply
 | |
|            // values list (bytes #32 .. #32+4*num_values) in order of corresponding bits TODO: it's actually not 4*num. Some values are 4b ytes, some - 1 byte
 | |
| 
 | |
|            var vals = packValueMask('CreateWindow', values);
 | |
|            var packetLength = 8 + (values ? vals[2].length : 0);
 | |
|            var args = [1, depth, packetLength, id, parentId, x, y, width, height, borderWidth, _class, visual];
 | |
|            format += vals[0];
 | |
|            args.push(vals[1]);
 | |
|            args = args.concat(vals[2]);
 | |
|            return [format, args];
 | |
|        }
 | |
| 
 | |
|    ],
 | |
| 
 | |
|    ChangeWindowAttributes:[
 | |
|        function(wid, values) {
 | |
|            var format = 'CxSLSxx';
 | |
|            var vals = packValueMask('CreateWindow', values);
 | |
|            var packetLength = 3 + (values ? vals[2].length : 0);
 | |
|            var args = [2, packetLength, wid, vals[1]];
 | |
|            var valArr = vals[2];
 | |
|            format += vals[0];
 | |
|            args = args.concat(valArr);
 | |
|            return [format, args];
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    GetWindowAttributes: [
 | |
|        ['CxSL', [3, 2]],
 | |
|        function(buf, backingStore)
 | |
|        {
 | |
|            // TODO: change from array to named object fields
 | |
|            var res = buf.unpack('LSCCLLCCCCLLLS');
 | |
|            var ret = {
 | |
|                backingStore: backingStore
 | |
|            };
 | |
|            ( "visual klass bitGravity winGravity backingPlanes backingPixel" +
 | |
|              " saveUnder mapIsInstalled mapState overrideRedirect colormap" +
 | |
|              " allEventMasks myEventMasks doNotPropogateMask" )
 | |
|            .split(' ').forEach(function(field, index) {
 | |
|                ret[field] = res[index];
 | |
|            });
 | |
|            return ret;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    DestroyWindow: [
 | |
|        [ 'CxSL', [4, 2] ]
 | |
|    ],
 | |
| 
 | |
|    ChangeSaveSet: [
 | |
|       function(isInsert, wid)
 | |
|       {
 | |
|           return [ 'CCSL', [6, (isInsert ? 0 : 1), 2, wid]]
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    // wid, newParentId, x, y
 | |
|    ReparentWindow: [
 | |
|        [ 'CxSLLss', [7, 4]]
 | |
|    ],
 | |
| 
 | |
|    MapWindow: [
 | |
|        // 8 - opcode, 2 - length, wid added as parameter
 | |
|        [ 'CxSL', [8, 2] ]
 | |
|    ],
 | |
| 
 | |
|    UnmapWindow: [
 | |
|        [ 'CxSL', [10, 2] ]
 | |
|    ],
 | |
| 
 | |
|    ConfigureWindow: [
 | |
|         /*
 | |
|          * options : {
 | |
|          *     x : x_value,
 | |
|          *     y : y_value,
 | |
|          *     width : width_value,
 | |
|          *     height : height_value,
 | |
|          *     borderWidth : borderWidth_value,
 | |
|          *     sibling : sibling_value
 | |
|          * }
 | |
|          */
 | |
|         function(win, options) {
 | |
|             var vals = packValueMask('ConfigureWindow', options);
 | |
|             var format = 'CxSLSxx' + vals[0];
 | |
|             var args = [12, vals[2].length + 3, win, vals[1]];
 | |
|             args = args.concat(vals[2]);
 | |
|             return [format, args];
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    ResizeWindow: [
 | |
|         function(win, width, height) {
 | |
|             return module.exports.ConfigureWindow[0](win, { width : width, height: height });
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    MoveWindow: [
 | |
|         function(win, x, y) {
 | |
|             return module.exports.ConfigureWindow[0](win, { x : x, y: y });
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    MoveResizeWindow: [
 | |
|         function(win, x, y, width, height) {
 | |
|             return module.exports.ConfigureWindow[0](win, { x : x, y: y, width : width, height: height });
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    RaiseWindow: [
 | |
|         function(win) {
 | |
|             return module.exports.ConfigureWindow[0](win, { stackMode : 0 });
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    LowerWindow: [
 | |
|         function(win) {
 | |
|             return module.exports.ConfigureWindow[0](win, { stackMode : 1 });
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    QueryTree: [
 | |
|         ['CxSL', [15, 2]],
 | |
| 
 | |
|         function(buf) {
 | |
|             var tree = {};
 | |
|             var res = buf.unpack('LLS');
 | |
|             tree.root = res[0];
 | |
|             tree.parent = res[1];
 | |
|             tree.children = [];
 | |
|             for (var i=0; i < res[2]; ++i)
 | |
|                 tree.children.push(buf.unpack('L', 24 + i*4)[0]);
 | |
|             return tree;
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    // opcode 16
 | |
|    InternAtom: [
 | |
|        function (returnOnlyIfExist, value)
 | |
|        {
 | |
|            var padded = xutil.padded_string(value);
 | |
|            return ['CCSSxxa', [16, returnOnlyIfExist ? 1 : 0, 2+padded.length/4, value.length, padded] ];
 | |
|        },
 | |
| 
 | |
|        function(buf, seq_num) {
 | |
|            var res = buf.unpack('L')[0];
 | |
|            var pending_atom = this.pending_atoms[seq_num];
 | |
|            if (!this.atoms[pending_atom]) {
 | |
|                this.atoms[pending_atom] = res;
 | |
|                this.atom_names[res] = pending_atom;
 | |
|            }
 | |
| 
 | |
|            delete this.pending_atoms[seq_num];
 | |
|            return res;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GetAtomName: [
 | |
|        [ 'CxSL', [17, 2] ],
 | |
|        function(buf, seq_num) {
 | |
|           var nameLen = buf.unpack('S')[0];
 | |
|           // Atom value starting from 24th byte in the buffer
 | |
|           var name = buf.unpackString(nameLen, 24);
 | |
|           var pending_atom = this.pending_atoms[seq_num];
 | |
|           if (!this.atoms[pending_atom]) {
 | |
|               this.atom_names[pending_atom] = name;
 | |
|               this.atoms[name] = pending_atom;
 | |
|           }
 | |
| 
 | |
|           delete this.pending_atoms[seq_num];
 | |
|           return name;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    ChangeProperty: [
 | |
|        // mode: 0 replace, 1 prepend, 2 append
 | |
|        // format: 8/16/32
 | |
|        function(mode, wid, name, type, units, data)
 | |
|        {
 | |
|           var padded4 = (data.length + 3) >> 2;
 | |
|           var pad = new Buffer( (padded4<<2) - data.length);
 | |
|           var format = 'CCSLLLCxxxLaa';
 | |
|           var requestLength = 6 + padded4;
 | |
|           var dataLenInFormatUnits = data.length / (units >> 3);
 | |
|           return [format, [18, mode, requestLength, wid, name, type, units, dataLenInFormatUnits, data, pad] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    // TODO: test
 | |
|    DeleteProperty: [
 | |
|        function(wid, prop) {
 | |
|            return [ 'CxSLL', [19, 3, wid, prop] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GetProperty: [
 | |
| 
 | |
|        function(del, wid, name, type, longOffset, longLength) //  - offest and maxLength in 4-byte units
 | |
|        {
 | |
|            return [ 'CCSLLLLL', [20, del, 6, wid, name, type, longOffset, longLength ] ];
 | |
|        },
 | |
| 
 | |
|        function(buf, format) {
 | |
|      var res = buf.unpack('LLL');
 | |
|            var prop = {};
 | |
|            prop.type = res[0];
 | |
|            prop.bytesAfter = res[1];
 | |
|            var len = res[2]*(format >> 3)
 | |
|            prop.data = buf.slice(24, 24+len);
 | |
|            return prop;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    ListProperties: [
 | |
| 
 | |
|        function(wid)
 | |
|        {
 | |
|           return ['CxSL', [21, 2, wid]];
 | |
|        },
 | |
| 
 | |
|        function(buf) {
 | |
|           var n = buf.unpack('S')[0];
 | |
|           var i;
 | |
|           var atoms = [];
 | |
|           for(i=0; i < n; ++i) {
 | |
|              atoms.push(buf.unpack('L', 24+4*i)[0]);
 | |
|              //console.log([n, i, atoms]);
 | |
|           }
 | |
|           return atoms;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    SetSelectionOwner: [
 | |
|       function(owner, selection, time)
 | |
|       {
 | |
|           if (!time)
 | |
|               time = 0; // current time
 | |
|           return ['CxSLLL', [22, 4, owner, selection, time]];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    GetSelectionOwner: [
 | |
|       function(selection)
 | |
|       {
 | |
|           return ['CxSL', [23, 2, selection]];
 | |
|       },
 | |
| 
 | |
|       function(buf) {
 | |
|           return buf.unpack('L')[0];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    ConvertSelection: [
 | |
|       function(requestor, selection, target, property, time) {
 | |
|           if (!time)
 | |
|               time = 0;
 | |
|           return ['CxSLLLLL', [24, 6, requestor, selection, target, property, time]];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    SendEvent: [
 | |
| 
 | |
|        function(destination, propagate, eventMask, eventRawData)
 | |
|        {
 | |
|            return [ 'CCSLLa', [25, propagate, 11, destination, eventMask, eventRawData] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GrabPointer: [
 | |
|        function(wid, ownerEvents, mask, pointerMode, keybMode, confineTo, cursor, time) {
 | |
|            return [ 'CCSLSCCLLL', [ 26, ownerEvents, 6, wid, mask, pointerMode, keybMode,
 | |
|                                     confineTo, cursor, time] ];
 | |
|        },
 | |
|        function(buf, status) {
 | |
|            return status;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    UngrabPointer: [
 | |
|        function(time) {
 | |
|            return [ 'CxSL', [ 27, 2, time] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GrabButton: [
 | |
|        function(wid, ownerEvents, mask, pointerMode, keybMode, confineTo, cursor, button, modifiers) {
 | |
|            return [ 'CCSLSCCLLCxS', [ 28, ownerEvents, 6, wid, mask, pointerMode, keybMode, confineTo,
 | |
|                                       cursor, button, modifiers ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    UngrabButton: [
 | |
|        function(wid, button, modifiers) {
 | |
|            return [ 'CCSLSxx', [ 29, button, 3, wid, modifiers ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    ChangeActivePointerGrab: [
 | |
|        function(cursor, time, mask) {
 | |
|            return [ 'CxSLLSxx', [ 30, 4, cursor, time, mask ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GrabKeyboard: [
 | |
|        function(wid, ownerEvents, time, pointerMode, keybMode) {
 | |
|            return [ 'CCSLLCCxx', [ 31, ownerEvents, 4, wid, time, pointerMode, keybMode ] ];
 | |
|        },
 | |
|        function(buf, status) {
 | |
|            return status;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    UngrabKeyboard: [
 | |
|        function(time) {
 | |
|            return [ 'CxSL', [ 32, 2, time ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GrabKey: [
 | |
|        function(wid, ownerEvents, modifiers, key, pointerMode, keybMode) {
 | |
|            return [ 'CCSLSCCCxxx', [ 33, ownerEvents, 4, wid, modifiers, key, pointerMode, keybMode ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    UngrabKey: [
 | |
|        function(wid, key, modifiers) {
 | |
|            return [ 'CCSLSxx', [ 34, key, 3, wid, modifiers ] ];
 | |
|        }
 | |
|    ],
 | |
|    
 | |
|    AllowEvents: [
 | |
|        function(mode, ts) {
 | |
|            return [ 'CCSL', [ 35, mode, 2, ts ] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GrabServer: [
 | |
|        [ 'CxS', [36, 1]]
 | |
|    ],
 | |
| 
 | |
|    UngrabServer: [
 | |
|        [ 'CxS', [37, 1]]
 | |
|    ],
 | |
| 
 | |
|    QueryPointer: [
 | |
|        [ 'CxSL', [38, 2] ],
 | |
|        function(buf, sameScreen) {
 | |
|            var res = buf.unpack('LLssssS');
 | |
|            return {
 | |
|                root: res[0],
 | |
|                child: res[1],
 | |
|                rootX: res[2],
 | |
|                rootY: res[3],
 | |
|                childX: res[4],
 | |
|                childY: res[5],
 | |
|                keyMask: res[6],
 | |
|                sameScreen : sameScreen
 | |
|            };
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    TranslateCoordinates: [
 | |
|        function(srcWid, dstWid, srcX, srcY) {
 | |
|            return [ 'CxSLLSS', [ 40, 4, srcWid, dstWid, srcX, srcY ] ];
 | |
|        },
 | |
|        function(buf, sameScreen)
 | |
|        {
 | |
|            var res = buf.unpack('Lss');
 | |
|            var ext = {};
 | |
|            ext.child = res[0];
 | |
|            ext.destX = res[1];
 | |
|            ext.destY = res[2];
 | |
|            ext.sameScreen = sameScreen;
 | |
|            return ext;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    WarpPointer: [
 | |
| 
 | |
|       function (srcWin, dstWin, srcX, srcY, srcWidth, srcHeight, dstX, dstY)
 | |
|       {
 | |
|           return [ 'CxSLLssSSss', [41, 6, srcWin, dstWin, srcX, srcY, srcWidth, srcHeight, dstX, dstY] ];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    SetInputFocus: [
 | |
| 
 | |
|       function (wid, revertTo) // revertTo: 0 - None, 1 - PointerRoot, 2 - Parent
 | |
|       {
 | |
|           return [ 'CCSLL', [42, revertTo, 3, wid, 0] ];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    GetInputFocus: [
 | |
|        function() {
 | |
|            return [ 'CxS', [ 43, 1 ] ];
 | |
|        },
 | |
|        function(buf, revertTo)
 | |
|        {
 | |
|            return {
 | |
|                focus : buf.unpack('L')[0],
 | |
|                revertTo : revertTo
 | |
|            };
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    OpenFont: [
 | |
|        function(name,fid) {
 | |
|            var padded = xutil.padded_string(name);
 | |
|            return ['CxSLSxxa', [45, 3+padded.length/4, fid, name.length, padded] ];
 | |
|        }    
 | |
|    ],
 | |
| 
 | |
|    ListFonts: [
 | |
|       function(pattern, max)
 | |
|       {
 | |
|           var req_len = 2+xutil.padded_length(pattern.length)/4;
 | |
|           return [ 'CxSSSp', [49, req_len, max, pattern.length, pattern] ];
 | |
|       },
 | |
| 
 | |
|       function(buf) {
 | |
|           console.log(buf);
 | |
|           // TODO: move to buffer.unpackStringList
 | |
|           var res = [];
 | |
|           var off = 24;
 | |
|           while (off < buf.length)
 | |
|           {
 | |
|               var len = buf[off++];
 | |
|               if (len == 0)
 | |
|                   break;
 | |
|               if (off + len > buf.length)
 | |
|               {
 | |
|                   len = buf.length - off;
 | |
|                   if (len <= 0)
 | |
|                      break;
 | |
|               }
 | |
|               res.push(buf.unpackString(len, off));
 | |
|               off += len;
 | |
|           }
 | |
|           return res;
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    CreatePixmap: [
 | |
|        function(pid, drawable, depth, width, height) {
 | |
|           return [ 'CCSLLSS', [53, depth, 4, pid, drawable, width, height] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    FreePixmap: [
 | |
|       function (pixmap) {
 | |
|           return [ 'CxSL', [54, 2, pixmap] ];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    CreateCursor: [
 | |
|        function(cid, source, mask, foreRGB, backRGB, x, y) {
 | |
|           foreR = foreRGB.R
 | |
|           foreG = foreRGB.G
 | |
|           foreB = foreRGB.B
 | |
| 
 | |
|           backR = backRGB.R
 | |
|           backG = backRGB.G
 | |
|           backB = backRGB.B
 | |
|           return [ 'CxSLLLSSSSSSSS', [93, 8, cid, source, mask, foreR, foreG, foreB, backR, backG, backB, x, y] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    // opcode 55
 | |
|    CreateGC: [
 | |
|        function(cid, drawable, values) {
 | |
|            var format = 'CxSLLL';
 | |
|            var vals = packValueMask('CreateGC', values);
 | |
|            var packetLength = 4 + (values ? vals[2].length : 0);
 | |
|            var args = [55, packetLength, cid, drawable];
 | |
|            format += vals[0]
 | |
|            args.push(vals[1]);     // values bitmask
 | |
|            args = args.concat(vals[2])
 | |
|            return [format, args];
 | |
|         }
 | |
|    ],
 | |
| 
 | |
|    ChangeGC: [
 | |
|        function(cid, values) {
 | |
|            var format = 'CxSLL';
 | |
|            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])
 | |
|            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) {
 | |
|           return [ 'CxSLLLssssSS', [62, 7, srcDrawable, dstDrawable, gc, srcX, srcY, dstX, dstY, width, height] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
| 
 | |
|    PolyPoint: [
 | |
|        function(coordMode, drawable, gc, points)
 | |
|        {
 | |
|           var format = 'CCSLL';
 | |
|           var args = [64, coordMode, 3+points.length/2, drawable, gc];
 | |
|           for (var i=0; i < points.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(points[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    PolyLine: [
 | |
|        // TODO: remove copy-paste - exectly same as PolyPoint, only differ with opcode
 | |
|        function(coordMode, drawable, gc, points)
 | |
|        {
 | |
|           var format = 'CCSLL';
 | |
|           var args = [65, coordMode, 3+points.length/2, drawable, gc];
 | |
|           for (var i=0; i < points.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(points[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|        }
 | |
| 
 | |
|    ],
 | |
| 
 | |
|    PolyRectangle: [
 | |
|       function(drawable, gc, coords) { // x1, y1, w1, h1, x2, y2, w2, h2...
 | |
|           var format = 'CxSLL';
 | |
|           var numrects4bytes = coords.length/2;
 | |
|           var args = [67, 3+numrects4bytes, drawable, gc];
 | |
|           for (var i=0; i < coords.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(coords[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    PolyArc: [
 | |
|       function(drawable, gc, coords) { // x1, y1, w1, h1, a11, a12, ...
 | |
|           var format = 'CxSLL';
 | |
|           var numrects4bytes = coords.length/2;
 | |
|           var args = [68, 3+numrects4bytes, drawable, gc];
 | |
|           for (var i=0; i < coords.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(coords[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    FillPoly: [
 | |
|        // TODO: remove copy-paste - exectly same as PolyPoint, only differ with opcode
 | |
|        function(drawable, gc, shape, coordMode, points)
 | |
|        {
 | |
|           var format = 'CxSLLCCxx';
 | |
|           var args = [69, 4+points.length/2, drawable, gc, shape, coordMode];
 | |
|           for (var i=0; i < points.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(points[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|        }
 | |
| 
 | |
|    ],
 | |
| 
 | |
|    PolyFillRectangle: [
 | |
|       function(drawable, gc, coords) { // x1, y1, w1, h1, x2, y2, w2, h2...
 | |
|           var format = 'CxSLL';
 | |
|           var numrects4bytes = coords.length/2;
 | |
|           var args = [70, 3+numrects4bytes, drawable, gc];
 | |
|           for (var i=0; i < coords.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(coords[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    PolyFillArc: [
 | |
|       function(drawable, gc, coords) { // x1, y1, w1, h1, a11, a12, ...
 | |
|           var format = 'CxSLL';
 | |
|           var numrects4bytes = coords.length/2;
 | |
|           var args = [71, 3+numrects4bytes, drawable, gc];
 | |
|           for (var i=0; i < coords.length; ++i)
 | |
|           {
 | |
|               format += 'S';
 | |
|               args.push(coords[i]);
 | |
|           }
 | |
|           return [format, args];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
| 
 | |
|    PutImage: [
 | |
|       // format:  0 - Bitmap, 1 - XYPixmap, 2 - ZPixmap
 | |
|       function(format, drawable, gc, width, height, dstX, dstY, leftPad, depth, data) {
 | |
|           var padded = xutil.padded_length(data.length);
 | |
|           var reqLen = 6 + padded/4; // (length + 3) >> 2 ???
 | |
|           var padLength = padded - data.length;
 | |
|           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
 | |
|           return [ 'CCSLLLSSssCCxxaa', [72, format, 0, 1+reqLen, drawable, gc, width, height, dstX, dstY, leftPad, depth, data, pad]];
 | |
|       }
 | |
|    ],
 | |
| 
 | |
|    GetImage: [
 | |
|        function(format, drawable, x, y, width, height, planeMask)
 | |
|        {
 | |
|            return [ 'CCSLssSSL', [73, format, 5, drawable, x, y, width, height, planeMask]];
 | |
|        },
 | |
|        function(buf, depth)
 | |
|        {
 | |
|            var visualId = buf.unpack('L')[0];
 | |
|            return {
 | |
|                depth: depth,
 | |
|                visualId: visualId,
 | |
|                data: buf.slice(24)
 | |
|            };
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    PolyText8: [
 | |
|        function(drawable, gc, x, y, items) {
 | |
|           var format = 'CxSLLss';
 | |
|           var numItems = items.length;
 | |
|           var reqLen = 16;
 | |
|           var args = [74, 0, drawable, gc, x, y];
 | |
|           for (var i=0; i < numItems; ++i)
 | |
|           {
 | |
|               var it = items[i];
 | |
|               if (typeof it == 'string')
 | |
|               {
 | |
|                   if (it.length > 254) // TODO: split string in set of items
 | |
|                       throw 'not supported yet';
 | |
|                   format += 'CCa';
 | |
|                   args.push(it.length);
 | |
|                   args.push(0); // delta???
 | |
|                   args.push(it);
 | |
|                   reqLen += 2 + it.length;
 | |
|               } else {
 | |
|                   throw 'not supported yet';
 | |
|               }
 | |
|           }
 | |
|           var len4 = xutil.padded_length(reqLen)/4;
 | |
|           var padLen = len4*4 - reqLen;
 | |
|           args[1] = len4; // set request length to calculated value
 | |
|           var pad = '';
 | |
|           for (var i=0; i < padLen; ++i)
 | |
|              pad += String.fromCharCode(0);
 | |
|           format += 'a';
 | |
|           args.push(pad);
 | |
|           return [format, args];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    CreateColormap:
 | |
|    [
 | |
|        function(cmid, wid, vid, alloc)
 | |
|        {
 | |
|            return ['CCSLLL', [78, alloc, 4, cmid, wid, vid]];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    AllocColor: [
 | |
|        [ 'CxSLSSSxx', [84, 4] ], // params: colormap, red, green, blue
 | |
| 
 | |
|        function(buf) {
 | |
| 	   var res = buf.unpack('SSSxL');
 | |
|            var color = {};
 | |
|            color.red   = res[0];
 | |
|            color.blue  = res[1];
 | |
|            color.green = res[2];
 | |
|            color.pixel = res[3]>>8; // it looks like 3 first bytes contain RGB value in response
 | |
|            return color;
 | |
|        }
 | |
|    ],
 | |
|    
 | |
|    QueryExtension: [
 | |
|        function(name) {
 | |
|            var padded = xutil.padded_string(name);
 | |
|            return ['CxSSxxa', [98, 2+padded.length/4, name.length, padded] ];
 | |
|        },
 | |
| 
 | |
|        function(buf) {
 | |
| 	   var res = buf.unpack('CCCC');
 | |
|            var ext = {};
 | |
|            ext.present = res[0];
 | |
|            ext.majorOpcode = res[1];
 | |
|            ext.firstEvent = res[2];
 | |
|            ext.firstError = res[3];
 | |
|            return ext;
 | |
|        }
 | |
| 
 | |
|    ],
 | |
| 
 | |
|    ListExtensions: [
 | |
|        [ 'CxS', [99, 1] ],
 | |
| 
 | |
|        function(buf) {
 | |
|           // TODO: move to buffer.unpackStringList
 | |
|           var res = [];
 | |
|           var off = 24;
 | |
|           while (off < buf.length)
 | |
|           {
 | |
|               var len = buf[off++];
 | |
|               if (len == 0)
 | |
|                   break;
 | |
|               if (off + len > buf.length)
 | |
|               {
 | |
|                   len = buf.length - off;
 | |
|                   if (len <= 0)
 | |
|                      break;
 | |
|               }
 | |
|               res.push(buf.unpackString(len, off));
 | |
|               off += len;
 | |
|           }
 | |
|           return res;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    GetKeyboardMapping: [
 | |
|        function(startCode, num) {
 | |
|            return [ 'CxSCCxx', [101, 2, startCode, num] ]
 | |
|        },
 | |
|        function(buff, listLength) {
 | |
|            var res = [];
 | |
|            var format = '';
 | |
|            for (var i=0; i < listLength; ++i)
 | |
|                format += 'L';
 | |
|            for (var offset=24; offset < buff.length - 4*listLength; offset += 4*listLength)
 | |
|                 res.push(buff.unpack(format, offset));
 | |
|            return res;
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|         // todo: move up to keep reque
 | |
| 	GetGeometry: [
 | |
| 		function(drawable){
 | |
| 			return ['CxSL', [14, 2, drawable]]
 | |
| 		},
 | |
| 		function(buff, depth)
 | |
| 		{
 | |
| 			var res = buff.unpack('LssSSSx');
 | |
| 			var ext = {};
 | |
| 			ext.windowid = res[0]
 | |
| 			ext.xPos = res[1];
 | |
| 			ext.yPos = res[2];
 | |
| 			ext.width = res[3];
 | |
| 			ext.height = res[4];
 | |
| 			ext.borderWidth = res[5];
 | |
| 			ext.depth = depth;
 | |
| 			return ext;
 | |
| 		}
 | |
|    ],
 | |
| 
 | |
|    KillClient: [
 | |
|        function(resource) {
 | |
|            return [ 'CxSL', [113, 2, resource] ];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    SetScreenSaver: [
 | |
|        function(timeout, interval, preferBlanking, allowExposures) {
 | |
|            return [ 'CxSssCCxx', [107, 3, timeout, interval, preferBlanking, allowExposures]];
 | |
|        }
 | |
|    ],
 | |
| 
 | |
|    ForceScreenSaver: [
 | |
|        function(activate) {
 | |
|            return [ 'CCS', [115, activate?1:0, 1] ];
 | |
|        }
 | |
|    ]
 | |
| };
 | |
| 
 | |
| templates.KillKlient = templates.KillClient;
 | |
| 
 | |
| module.exports = templates;
 |