feat(ags): make a service to monitor clicks instead of closer window
This commit is contained in:
parent
9b7fd772f0
commit
0733e83964
3 changed files with 138 additions and 113 deletions
|
@ -1,5 +1,7 @@
|
||||||
import { App, Widget } from '../../imports.js';
|
import { App, Utils, Widget } from '../../imports.js';
|
||||||
const { Window, EventBox } = Widget;
|
const { Window, Revealer } = Widget;
|
||||||
|
|
||||||
|
import Pointers from '../../services/pointers.js';
|
||||||
|
|
||||||
const ALWAYS_OPEN = [
|
const ALWAYS_OPEN = [
|
||||||
'closer',
|
'closer',
|
||||||
|
@ -12,7 +14,6 @@ const ALWAYS_OPEN = [
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// TODO: close on scroll event too?
|
|
||||||
export const closeAll = () => {
|
export const closeAll = () => {
|
||||||
App.windows.forEach(w => {
|
App.windows.forEach(w => {
|
||||||
if (!ALWAYS_OPEN.some(window => window === w.name))
|
if (!ALWAYS_OPEN.some(window => window === w.name))
|
||||||
|
@ -21,19 +22,61 @@ export const closeAll = () => {
|
||||||
App.closeWindow('closer');
|
App.closeWindow('closer');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Pointers.connect('new-line', (_, out) => {
|
||||||
|
if (out) {
|
||||||
|
Utils.execAsync('hyprctl layers -j').then(layers => {
|
||||||
|
layers = JSON.parse(layers);
|
||||||
|
|
||||||
|
Utils.execAsync('hyprctl cursorpos -j').then(pos => {
|
||||||
|
pos = JSON.parse(pos);
|
||||||
|
|
||||||
|
Object.values(layers).forEach(key => {
|
||||||
|
let bar = key['levels']['3']
|
||||||
|
.find(n => n.namespace === "bar");
|
||||||
|
|
||||||
|
let widgets = key['levels']['3']
|
||||||
|
.filter(n => !ALWAYS_OPEN.includes(n.namespace));
|
||||||
|
|
||||||
|
if (pos.x > bar.x && pos.x < bar.x + bar.w &&
|
||||||
|
pos.y > bar.y && pos.y < bar.y + bar.h) {
|
||||||
|
|
||||||
|
// don't handle clicks when on bar
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
widgets.forEach(l => {
|
||||||
|
if (!(pos.x > l.x && pos.x < l.x + l.w &&
|
||||||
|
pos.y > l.y && pos.y < l.y + l.h)) {
|
||||||
|
closeAll();
|
||||||
|
return
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}).catch(print);
|
||||||
|
}).catch(print);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export const Closer = Window({
|
export const Closer = Window({
|
||||||
name: 'closer',
|
name: 'closer',
|
||||||
popup: true,
|
popup: true,
|
||||||
layer: 'top',
|
layer: 'top',
|
||||||
anchor: [ 'top', 'bottom', 'left', 'right' ],
|
|
||||||
|
|
||||||
child: EventBox({
|
child: Revealer({
|
||||||
onPrimaryClickRelease: () => closeAll(),
|
connections: [[App, (_, windowName, visible) => {
|
||||||
connections: [[App, (_b, _w, _v) => {
|
|
||||||
if (!Array.from(App.windows).some(w => w[1].visible &&
|
if (!Array.from(App.windows).some(w => w[1].visible &&
|
||||||
!ALWAYS_OPEN.some(window => window === w[0]))) {
|
!ALWAYS_OPEN.some(window => window === w[0]))) {
|
||||||
App.closeWindow('closer');
|
App.closeWindow('closer');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (windowName === 'closer') {
|
||||||
|
if (visible)
|
||||||
|
Pointers.startProc();
|
||||||
|
else
|
||||||
|
Pointers.killProc();
|
||||||
|
}
|
||||||
}]],
|
}]],
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
88
hosts/wim/config/ags/services/pointers.js
Normal file
88
hosts/wim/config/ags/services/pointers.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// TODO: read /dev to recalculate devices and remake subprocess
|
||||||
|
|
||||||
|
import { Service, Utils } from '../imports.js';
|
||||||
|
|
||||||
|
|
||||||
|
class Pointers extends Service {
|
||||||
|
static {
|
||||||
|
Service.register(this, {
|
||||||
|
'proc-started': ['boolean'],
|
||||||
|
'proc-destroyed': ['boolean'],
|
||||||
|
'device-fetched': ['boolean'],
|
||||||
|
'new-line': ['string'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
proc;
|
||||||
|
output = "";
|
||||||
|
devices = new Map();
|
||||||
|
|
||||||
|
get proc() { return this.proc; }
|
||||||
|
get output() { return this.output; }
|
||||||
|
get devices() { return this.devices; }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.parseDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
parseDevices() {
|
||||||
|
Utils.execAsync(['libinput', 'list-devices']).then(out => {
|
||||||
|
let lines = out.split('\n');
|
||||||
|
let device = null;
|
||||||
|
let devices = new Map();
|
||||||
|
|
||||||
|
lines.forEach(line => {
|
||||||
|
let parts = line.split(':');
|
||||||
|
|
||||||
|
if (parts[0] === 'Device') {
|
||||||
|
device = {};
|
||||||
|
devices.set(parts[1].trim(), device);
|
||||||
|
}
|
||||||
|
else if (device && parts[1]) {
|
||||||
|
let key = parts[0].trim();
|
||||||
|
let value = parts[1].trim();
|
||||||
|
device[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.devices = Array.from(devices).filter(dev => dev.Capabilities &&
|
||||||
|
dev.Capabilities.includes('pointer'));
|
||||||
|
this.emit('device-fetched', true);
|
||||||
|
}).catch(print);
|
||||||
|
}
|
||||||
|
|
||||||
|
startProc() {
|
||||||
|
let args = [];
|
||||||
|
this.devices.forEach(dev => {
|
||||||
|
if (dev.Kernel) {
|
||||||
|
args.push('--device');
|
||||||
|
args.push(dev.Kernel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.proc = Utils.subprocess(
|
||||||
|
['libinput', 'debug-events', ...args],
|
||||||
|
(output) => {
|
||||||
|
if (output.includes('BTN') && output.includes('released') ||
|
||||||
|
output.includes('TOUCH_UP') ||
|
||||||
|
output.includes('HOLD_END') && !output.includes('cancelled')) {
|
||||||
|
|
||||||
|
this.output = output;
|
||||||
|
this.emit('new-line', output);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => logError(err)
|
||||||
|
);
|
||||||
|
this.emit('proc-started', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
killProc() {
|
||||||
|
if (this.proc) {
|
||||||
|
this.proc.force_exit();
|
||||||
|
this.emit('proc-destroyed', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointersService = new Pointers();
|
||||||
|
export default pointersService;
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
import Libinput from './libinput.js';
|
|
||||||
Libinput.instance.connect('device-init', () => {
|
|
||||||
let pointers = [];
|
|
||||||
Libinput.devices.forEach(dev => {
|
|
||||||
if (dev.Capabilities.includes('pointer')) {
|
|
||||||
pointers.push(dev);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
Libinput.addDebugInstance('pointers', pointers)
|
|
||||||
.connect('new-line', e => print(e.lastLine))
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
// WIP
|
|
||||||
Utils.execAsync('hyprctl layers -j').then(layers => {
|
|
||||||
layers = JSON.parse(layers);
|
|
||||||
Utils.execAsync('hyprctl cursorpos -j').then(pos => {
|
|
||||||
pos = JSON.parse(pos);
|
|
||||||
|
|
||||||
Object.values(layers).forEach(key => {
|
|
||||||
key['levels']['3'].forEach(l => {
|
|
||||||
print(l.namespace);
|
|
||||||
if (pos.x > l.x && pos.x < l.x + l.w &&
|
|
||||||
pos.y > l.y && pos.y < l.y + l.h)
|
|
||||||
{
|
|
||||||
print('inside window');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print('outside window');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).catch(print);
|
|
||||||
}).catch(print);
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: use hyprctl layers to determine if clicks were on a widget
|
|
||||||
// read /dev to recalculate devices and remake subprocess
|
|
||||||
|
|
||||||
const { Service, Utils } = '../imports.js';
|
|
||||||
|
|
||||||
|
|
||||||
class PointersService extends Service {
|
|
||||||
static {
|
|
||||||
Service.register(this, {
|
|
||||||
'log-started': ['boolean'],
|
|
||||||
'device-fetched': ['boolean'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
log;
|
|
||||||
output = "";
|
|
||||||
devices = new Map();
|
|
||||||
|
|
||||||
get log() {return this.log;}
|
|
||||||
get output() {return this.output;}
|
|
||||||
get devices() {return this.devices;}
|
|
||||||
|
|
||||||
parseDevices() {
|
|
||||||
Utils.execAsync(['libinput', 'list-devices']).then(out => {
|
|
||||||
let lines = out.split('\n');
|
|
||||||
let device = null;
|
|
||||||
let devices = new Map();
|
|
||||||
|
|
||||||
lines.forEach(line => {
|
|
||||||
let parts = line.split(':');
|
|
||||||
|
|
||||||
if (parts[0] === 'Device') {
|
|
||||||
device = {};
|
|
||||||
devices.set(parts[1].trim(), device);
|
|
||||||
}
|
|
||||||
else if (device && parts[1]) {
|
|
||||||
let key = parts[0].trim();
|
|
||||||
let value = parts[1].trim();
|
|
||||||
device[key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.devices = devices.filter(dev => dev.Capabilities && dev.Capabilities.includes('pointer'));
|
|
||||||
this.emit('device-fetched', true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
startLog() {
|
|
||||||
let args = [];
|
|
||||||
this.devices.forEach(dev => {
|
|
||||||
if (dev.Kernel) {
|
|
||||||
args.push('--device');
|
|
||||||
args.push(dev.Kernel);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.log = Utils.subprocess(
|
|
||||||
['libinput', 'debug-events', ...args],
|
|
||||||
(output) => {
|
|
||||||
this.output = output;
|
|
||||||
},
|
|
||||||
(err) => logError(err)
|
|
||||||
);
|
|
||||||
this.emit('log-started', true);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue