UNPKG

@teaui/core

Version:

A high-level terminal UI library for Node

193 lines 6.97 kB
"use strict"; /** * gpmclient.js - support the gpm mouse protocol * Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License). * https://github.com/chjj/blessed */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GpmClient = GpmClient; const node_net_1 = __importDefault(require("node:net")); const node_fs_1 = __importDefault(require("node:fs")); const node_events_1 = require("node:events"); var GPM_USE_MAGIC = false; var GPM_MOVE = 1, GPM_DRAG = 2, GPM_DOWN = 4, GPM_UP = 8; var GPM_DOUBLE = 32, GPM_MFLAG = 128; var GPM_REQ_NOPASTE = 3, GPM_HARD = 256; var GPM_MAGIC = 0x47706d4c; var GPM_SOCKET = '/dev/gpmctl'; // typedef struct Gpm_Connect { // unsigned short eventMask, defaultMask; // unsigned short minMod, maxMod; // int pid; // int vc; // } Gpm_Connect; function send_config(socket, Gpm_Connect, callback) { var buffer; if (GPM_USE_MAGIC) { buffer = new Buffer(20); buffer.writeUInt32LE(GPM_MAGIC, 0); buffer.writeUInt16LE(Gpm_Connect.eventMask, 4); buffer.writeUInt16LE(Gpm_Connect.defaultMask, 6); buffer.writeUInt16LE(Gpm_Connect.minMod, 8); buffer.writeUInt16LE(Gpm_Connect.maxMod, 10); buffer.writeInt16LE(process.pid, 12); buffer.writeInt16LE(Gpm_Connect.vc, 16); } else { buffer = new Buffer(16); buffer.writeUInt16LE(Gpm_Connect.eventMask, 0); buffer.writeUInt16LE(Gpm_Connect.defaultMask, 2); buffer.writeUInt16LE(Gpm_Connect.minMod, 4); buffer.writeUInt16LE(Gpm_Connect.maxMod, 6); buffer.writeInt16LE(Gpm_Connect.pid, 8); buffer.writeInt16LE(Gpm_Connect.vc, 12); } socket.write(buffer, function () { if (callback) callback(); }); } // typedef struct Gpm_Event { // unsigned char buttons, modifiers; // try to be a multiple of 4 // unsigned short vc; // short dx, dy, x, y; // displacement x,y for this event, and absolute x,y // enum Gpm_Etype type; // // clicks e.g. double click are determined by time-based processing // int clicks; // enum Gpm_Margin margin; // // wdx/y: displacement of wheels in this event. Absolute values are not // // required, because wheel movement is typically used for scrolling // // or selecting fields, not for cursor positioning. The application // // can determine when the end of file or form is reached, and not // // go any further. // // A single mouse will use wdy, "vertical scroll" wheel. // short wdx, wdy; // } Gpm_Event; function parseEvent(raw) { var evnt = {}; evnt.buttons = raw[0]; evnt.modifiers = raw[1]; evnt.vc = raw.readUInt16LE(2); evnt.dx = raw.readInt16LE(4); evnt.dy = raw.readInt16LE(6); evnt.x = raw.readInt16LE(8); evnt.y = raw.readInt16LE(10); evnt.type = raw.readInt16LE(12); evnt.clicks = raw.readInt32LE(16); evnt.margin = raw.readInt32LE(20); evnt.wdx = raw.readInt16LE(24); evnt.wdy = raw.readInt16LE(26); return evnt; } function GpmClient(options) { if (!(this instanceof GpmClient)) { return new GpmClient(options); } node_events_1.EventEmitter.call(this); var pid = process.pid; // check tty for /dev/tty[n] var path; try { path = node_fs_1.default.readlinkSync('/proc/' + pid + '/fd/0'); } catch (e) { } var tty = /tty[0-9]+$/.exec(path); if (tty === null) { // TODO: should also check for /dev/input/.. } var vc; if (tty) { tty = tty[0]; vc = +/[0-9]+$/.exec(tty)[0]; } var self = this; if (tty) { node_fs_1.default.stat(GPM_SOCKET, function (err, stat) { if (err || !stat.isSocket()) { return; } var conf = { eventMask: 0xffff, defaultMask: GPM_MOVE | GPM_HARD, minMod: 0, maxMod: 0xffff, pid: pid, vc: vc, }; var gpm = node_net_1.default.createConnection(GPM_SOCKET); this.gpm = gpm; gpm.on('connect', function () { send_config(gpm, conf, function () { conf.pid = 0; conf.vc = GPM_REQ_NOPASTE; //send_config(gpm, conf); }); }); gpm.on('data', function (packet) { var evnt = parseEvent(packet); switch (evnt.type & 15) { case GPM_MOVE: if (evnt.dx || evnt.dy) { self.emit('move', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); } if (evnt.wdx || evnt.wdy) { self.emit('mousewheel', evnt.buttons, evnt.modifiers, evnt.x, evnt.y, evnt.wdx, evnt.wdy); } break; case GPM_DRAG: if (evnt.dx || evnt.dy) { self.emit('drag', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); } if (evnt.wdx || evnt.wdy) { self.emit('mousewheel', evnt.buttons, evnt.modifiers, evnt.x, evnt.y, evnt.wdx, evnt.wdy); } break; case GPM_DOWN: self.emit('btndown', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); if (evnt.type & GPM_DOUBLE) { self.emit('dblclick', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); } break; case GPM_UP: self.emit('btnup', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); if (!(evnt.type & GPM_MFLAG)) { self.emit('click', evnt.buttons, evnt.modifiers, evnt.x, evnt.y); } break; } }); gpm.on('error', function () { self.stop(); }); }); } } GpmClient.prototype.__proto__ = node_events_1.EventEmitter.prototype; GpmClient.prototype.stop = function () { if (this.gpm) { this.gpm.end(); } delete this.gpm; }; GpmClient.prototype.ButtonName = function (btn) { if (btn & 4) return 'left'; if (btn & 2) return 'middle'; if (btn & 1) return 'right'; return ''; }; GpmClient.prototype.hasShiftKey = function (mod) { return mod & 1 ? true : false; }; GpmClient.prototype.hasCtrlKey = function (mod) { return mod & 4 ? true : false; }; GpmClient.prototype.hasMetaKey = function (mod) { return mod & 8 ? true : false; }; //# sourceMappingURL=gpmclient.js.map