232 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var getAuthString = Require('x11/core/auth');
 | |
| var xutil = Require('x11/core/xutil');
 | |
| 
 | |
| function readVisuals(bl, visuals, n_visuals, cb)
 | |
| {
 | |
|     if (n_visuals == 0)
 | |
|     {
 | |
|         cb();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     var visual = {};
 | |
|     bl.unpackTo( visual,
 | |
|     [
 | |
|         '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;
 | |
|          visuals[visual.vid] = visual;
 | |
|          if (Object.keys(visuals).length == n_visuals)
 | |
|              cb()
 | |
|          else
 | |
|              readVisuals(bl, visuals, n_visuals, 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 default_colormap',
 | |
|              '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',
 | |
|              'S max_installed_maps',
 | |
|              '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() {
 | |
| 
 | |
|                  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);
 | |
|                      return;
 | |
|                  } else {
 | |
|                      readScreens(bl, display, cbDisplayReady);
 | |
|                  }
 | |
|              });
 | |
|          });
 | |
|      }
 | |
| }
 | |
| 
 | |
| 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);
 | |
|              });
 | |
|          });
 | |
|          // TODO: do we need to close stream from our side?
 | |
|          // TODO: api to close source stream via attached unpackstream
 | |
|          return;
 | |
|      }
 | |
| 
 | |
|      var display = {};
 | |
|      bl.unpackTo(
 | |
|          display,
 | |
|          [
 | |
|           'x',
 | |
|           'S major',
 | |
|           'S minor',
 | |
|           'S xlen',
 | |
|           'L release',
 | |
|           'L resource_base',
 | |
|           'L resource_mask',
 | |
|           'L motion_buffer_size',
 | |
|           'S vlen',
 | |
|           'S max_request_length',
 | |
|           'C screen_num',
 | |
|           'C format_num',
 | |
|           'C image_byte_order',
 | |
|           'C bitmap_bit_order',
 | |
|           'C bitmap_scanline_unit',
 | |
|           'C bitmap_scanline_pad',
 | |
|           'C min_keycode',
 | |
|           'C max_keycode',
 | |
|           'xxxx'
 | |
|          ],
 | |
| 
 | |
|          function()
 | |
|          {
 | |
|              var pvlen = xutil.padded_length(display.vlen);
 | |
| 
 | |
|              // setup data to generate resource id
 | |
|              // TODO: cleaunup code here
 | |
|              var mask = display.resource_mask;
 | |
|              display.rsrc_shift = 0;
 | |
|              while (!( (mask >> display.rsrc_shift) & 1) )
 | |
|                  display.rsrc_shift++;
 | |
|              display.rsrc_id = 0;
 | |
| 
 | |
|              bl.get(pvlen, function(vendor)
 | |
|              {
 | |
|                  display.vendor = vendor.toString().substr(0, display.vlen); // utf8 by default?
 | |
| 
 | |
|                  display.format = {};
 | |
|                  for (var i=0; i < display.format_num; ++i)
 | |
|                  {
 | |
|                      bl.unpack('CCCxxxxx', function(fmt) {
 | |
|                          var depth = fmt[0];
 | |
|                          display.format[depth] = {};
 | |
|                          display.format[depth].bits_per_pixel = fmt[1];
 | |
|                          display.format[depth].scanline_pad = fmt[2];
 | |
|                          if (Object.keys(display.format).length == display.format_num)
 | |
|                          {
 | |
|                              delete display.format_num;
 | |
|                              display.screen = [];
 | |
|                              readScreens(bl, display, cb);
 | |
|                          }
 | |
|                      });
 | |
|                  }
 | |
|              });
 | |
|          }
 | |
|      );
 | |
| });
 | |
| 
 | |
| }
 | |
| 
 | |
| function getByteOrder() {
 | |
|     var isLittleEndian = ((new Uint32Array((new Uint8Array([1,2,3,4])).buffer))[0] === 0x04030201);
 | |
|     if (isLittleEndian) {
 | |
|         return 'l'.charCodeAt(0);
 | |
|     } else {
 | |
|         return 'B'.charCodeAt(0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| function writeClientHello(stream, displayNum, authHost, authFamily)
 | |
| {
 | |
|     getAuthString( displayNum, authHost, authFamily, function( err, cookie ) {
 | |
|         if (err) {
 | |
|             throw err;
 | |
|         }
 | |
|         var byte_order = getByteOrder();
 | |
|         var protocol_major = 11; // TODO: config? env?
 | |
|         var protocol_minor = 0;
 | |
|         stream.pack(
 | |
|             'CxSSSSxxpp',
 | |
|             [
 | |
|             byte_order,
 | |
|             protocol_major,
 | |
|             protocol_minor,
 | |
|             cookie.authName.length,
 | |
|             cookie.authData.length,
 | |
|             cookie.authName,
 | |
|             cookie.authData
 | |
|             ]
 | |
|         );
 | |
|         stream.flush();
 | |
|     });
 | |
| }
 | |
| 
 | |
| module.exports.readServerHello = readServerHello;
 | |
| module.exports.writeClientHello = writeClientHello;
 |