@ross-technologies/xlib
Version:
Xlib for Node.JS.
295 lines (248 loc) • 10.5 kB
JavaScript
/* Required modules */
const assert = require("assert").ok;
const os = require("os");
const {buff2arr} = require("./utils.js");
/* Symbols */
const SYMS = {
"xdisplay": Symbol("xdisplay")
};
/* Structures */
/* Main Xlib class */
class Xlib {
constructor(xdisplay) {
assert(typeof(xdisplay) == "object","xdisplay must be an object");
assert(typeof(xdisplay.client) == "object","xdisplay.client must be an object");
assert(typeof(xdisplay.screen) == "object","xdisplay.screen must be an object");
this[SYMS["xdisplay"]] = xdisplay;
this.atoms = {
"WM_COMMAND": 34,
"WM_HINTS": 35,
"WM_CLIENT_MACHINE": 36,
"WM_ICON_NAME": 37,
"WM_ICON_SIZE": 38,
"WM_NAME": 39,
"WM_NORMAL_HINTS": 40,
"WM_SIZE_HINTS": 41,
"WM_ZOOM_HINTS": 42
};
this.flags = {
/* xPropSizeHints */
"USPosition": (1 << 0),
"USSize": (1 << 1),
"PPosition": (1 << 2),
"PSize": (1 << 3),
"PMinSize": (1 << 4),
"PMaxSize": (1 << 5),
"PResizeInc": (1 << 6),
"PAspect": (1 << 7),
"PBaseSize": (1 << 8),
"PWinGravity": (1 << 9),
/* xPropWMHints */
"InputHint": (1 << 0),
"StateHint": (1 << 1),
"IconPixmapHint": (1 << 2),
"IconWindowHint": (1 << 3),
"IconPositionHint": (1 << 4),
"IconMaskHint": (1 << 5),
"WindowGroupHint": (1 << 6)
};
}
SetClassHint(win,wmhints) {
assert(typeof(win) == "number","win must be a number");
assert(Array.isArray(wmhints),"wmhints must be an array");
this[SYMS["xdisplay"]].client.ChangeProperty(0,win,this.atoms.WM_CLASS,this[SYMS["xdisplay"]].client.atoms.STRING,8,wmhints);
}
SetCommand(win) {
assert(typeof(win) == "number","win must be a number");
this.SetTextProperty(win,this.atoms.WM_COMMAND,process.argv);
}
SetTextProperty(win,property,data) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(property) == "number","property must be a number");
assert(typeof(data) == "string" || Array.isArray(data),"data must be a string or array");
if(typeof(data) == "string") return this.SetTextProperty(win,property,[data]);
this[SYMS["xdisplay"]].client.ChangeProperty(0,win,property,this[SYMS["xdisplay"]].client.atoms.STRING,8,data);
}
SetWMClientMachine(win) {
assert(typeof(win) == "number","win must be a number");
this.SetTextProperty(win,this.atoms.WM_CLIENT_MACHINE,os.hostname());
}
SetWMHints(win,wmhints) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(wmhints) == "object","wmhints must be an object");
assert(typeof(wmhints.flags) == "number","wmhints.flags must be a number");
var prop = {
flags: 0,
input: 0,
initialState: 0,
iconPixmap: 0,
iconWindow: 0,
icon: [0,0],
iconMask: 0,
windowGroup: 0
};
prop.flags = wmhints.flags;
if(wmhints.flags & this.flags.InputHint) {
assert(typeof(wmhints.input) == "boolean","wmhints.input must be a boolean");
prop.input = (wmhints.input == true ? 1 : 0);
}
if(wmhints.flags & this.flags.StateHint) {
assert(typeof(wmhints.initial_state) == "number","wmhints.initial_state must be a number");
prop.initialState = wmhints.initial_state;
}
if(wmhints.flags & this.flags.IconPixmapHint) {
assert(typeof(wmhints.icon_pixmap) == "number","wmhints.icon_pixmap must be a number");
prop.iconPixmap = wmhints.icon_pixmap;
}
if(wmhints.flags & this.flags.IconWindowHint) {
assert(typeof(wmhints.icon_window) == "number","wmhints.icon_window must be a number");
prop.iconWindow = wmhints.icon_window;
}
if(wmhints.flags & this.flags.IconPositionHint) {
assert(typeof(wmhints.icon) == "object" && Array.isArray(wmhints.icon),"wmhints.icon must be an array");
prop.icon[0] = wmhints.icon[0];
prop.icon[1] = wmhints.icon[1];
}
if(wmhints.flags & this.flags.IconMaskHint) {
assert(typeof(wmhints.icon_mask) == "number","wmhints.icon_mask must be a number");
prop.iconMask = wmhints.icon_mask;
}
if(wmhints.flags & this.flags.WindowGroupHint) {
assert(typeof(wmhints.window_group) == "number","wmhints.window_group must be a number");
prop.windowGroup = wmhints.window_group;
}
var buff = Buffer.alloc(36);
buff.writeUInt32LE(prop.flags,0);
buff.writeUInt32LE(prop.input,4);
buff.writeUInt32LE(prop.initialState,8);
buff.writeUInt32LE(prop.iconPixmap,12);
buff.writeUInt32LE(prop.iconWindow,16);
buff.writeUInt32LE(prop.icon[0],20);
buff.writeUInt32LE(prop.icon[1],24);
buff.writeUInt32LE(prop.iconMask,28);
buff.writeUInt32LE(prop.windowGroup,32);
this[SYMS["xdisplay"]].client.ChangeProperty(0,win,this.atoms.WM_HINTS,this.atoms.WM_HINTS,32,buff);
}
SetWMIconName(win,data) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(data) == "string","data must be a string");
this.SetTextProperty(win,this.atoms.WM_ICON_NAME,data);
}
SetWMName(win,data) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(data) == "string","data must be a string");
this.SetTextProperty(win,this.atoms.WM_NAME,data);
}
SetWMNormalHints(win,hints) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(hints) == "object","hints must be an object");
assert(typeof(hints.flags) == "number","hints.flags must be a number");
this.SetWMSizeHints(win,hints,this.atoms.WM_NORMAL_HINTS);
}
SetWMProperties(win,window_name,icon_name,normal_hints,wm_hints,class_hints) {
assert(typeof(win) == "number","win must be a number");
if(window_name != null) this.SetWMName(win,window_name);
if(icon_name != null) this.SetWMIconName(win,icon_name);
this.SetCommand(win);
if(normal_hints != null) this.SetWMNormalHints(win,normal_hints);
if(wm_hints != null) this.SetWMHints(win,wm_hints);
if(class_hints != null) this.SetClassHint(win,class_hints);
}
SetWMProtocols(win,protocols) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(protocols) == "object" && Array.isArray(protocols),"protocols must be an array");
this[SYMS["xdisplay"]].client.InternAtom(false,"WM_PROTOCOLS",(err,WM_PROTOCOLS) => {
if(err) throw err;
this[SYMS["xdisplay"]].client.ChangeProperty(0,win,WM_PROTOCOLS,this[SYMS["xdisplay"]].client.atoms.ATOM,32,protocols);
});
}
SetWMSizeHints(win,hints,property) {
assert(typeof(win) == "number","win must be a number");
assert(typeof(hints) == "object","hints must be an object");
assert(typeof(hints.flags) == "number","hints.flags must be a number");
assert(typeof(property) == "number","property must be a number");
var data = {
x: 0, y: 0,
width: 0, height: 0,
minWidth: 0, minHeight: 0,
maxWidth: 0, maxHeight: 0,
widthInc: 0, heightInc: 0,
minAspectX: 0, minAspectY: 0,
maxAspectX: 0, maxAspectY: 0,
baseWidth: 0, baseHeight: 0,
winGravity: 0
};
data.flags = (hints.flags & (this.flags.USPosition | this.flags.USSize | this.flags.PPosition | this.flags.PSize |
this.flags.PMinSize | this.flags.PMaxSize | this.flags.PResizeInc | this.flags.PAspect | this.flags.PBaseSize
| this.flags.PWinGravity));
if(hints.flags & (this.flags.USPosition | this.flags.PPosition)) {
assert(typeof(hints.x) == "number","hints.x must be a number");
assert(typeof(hints.y) == "number","hints.y must be a number");
data.x = hints.x;
data.y = hints.y;
}
if(hints.flags & (this.flags.USSize | this.flags.PSize)) {
assert(typeof(hints.width) == "number","hints.width must be a number");
assert(typeof(hints.height) == "number","hints.height must be a number");
data.width = hints.width;
data.height = hints.height;
}
if(hints.flags & this.flags.PMinSize) {
assert(typeof(hints.min_width) == "number","hints.min_width must be a number");
assert(typeof(hints.min_height) == "number","hints.min_height must be a number");
data.minWidth = hints.min_width;
data.minHeight = hints.min_height;
}
if(hints.flags & this.flags.PMaxSize) {
assert(typeof(hints.max_width) == "number","hints.max_width must be a number");
assert(typeof(hints.max_height) == "number","hints.max_height must be a number");
data.maxWidth = hints.max_width;
data.maxHeight = hints.max_height;
}
if(hints.flags & this.flags.PResizeInc) {
assert(typeof(hints.width_inc) == "number","hints.width_inc must be a number");
assert(typeof(hints.height_inc) == "number","hints.height_inc must be a number");
data.widthInc = hints.width_inc;
data.heightInc = hints.height_inc;
}
if(hints.flags & this.flags.PAspect) {
assert(typeof(hints.min_aspect) == "object" && Array.isArray(hints.min_aspect),"hints.min_aspect must be an array");
assert(typeof(hints.max_aspect) == "object" && Array.isArray(hints.max_aspect),"hints.max_aspect must be an array");
data.minAspectX = hints.min_aspect[0];
data.minAspectY = hints.min_aspect[1];
data.maxAspectX = hints.max_aspect[0];
data.maxAspectY = hints.max_aspect[1];
}
if(hints.flags & this.flags.PBaseSize) {
assert(typeof(hints.base_width) == "number","hints.base_width must be a number");
assert(typeof(hints.base_height) == "number","hints.base_height must be a number");
data.baseWidth = hints.base_width;
data.baseHeight = hints.base_height;
}
if(hints.flags & this.flags.PWinGravity) {
assert(typeof(hints.win_gravity) == "number","hints.win_gravity must be a number");
data.winGravity = hints.win_gravity;
}
var buff = Buffer.alloc(72);
buff.writeUInt32LE(data.flags,0);
buff.writeUInt32LE(data.x,4);
buff.writeUInt32LE(data.y,8);
buff.writeUInt32LE(data.width,12);
buff.writeUInt32LE(data.height,16);
buff.writeUInt32LE(data.minWidth,20);
buff.writeUInt32LE(data.minHeight,24);
buff.writeUInt32LE(data.maxWidth,28);
buff.writeUInt32LE(data.maxHeight,32);
buff.writeUInt32LE(data.widthInc,36);
buff.writeUInt32LE(data.heightInc,40);
buff.writeUInt32LE(data.minAspectX,44);
buff.writeUInt32LE(data.minAspectY,48);
buff.writeUInt32LE(data.maxAspectX,52);
buff.writeUInt32LE(data.maxAspectY,56);
buff.writeUInt32LE(data.baseWidth,60);
buff.writeUInt32LE(data.baseHeight,64);
buff.writeUInt32LE(data.winGravity,68);
this[SYMS["xdisplay"]].client.ChangeProperty(0,win,property,this.atoms.WM_SIZE_HINTS,32,buff);
}
}
module.exports = Xlib;