feat(ags): implement tablet service to replace broken scripts
This commit is contained in:
parent
5b120c844a
commit
070f5345c8
1 changed files with 162 additions and 0 deletions
162
devices/wim/config/ags/services/tablet.js
Normal file
162
devices/wim/config/ags/services/tablet.js
Normal file
|
@ -0,0 +1,162 @@
|
|||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||
import { execAsync, subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import GUdev from 'gi://GUdev';
|
||||
|
||||
const ROTATION_MAPPING = {
|
||||
'normal': 0,
|
||||
'right-up': 3,
|
||||
'bottom-up': 2,
|
||||
'left-up': 1,
|
||||
};
|
||||
const SCREEN = 'desc:BOE 0x0964';
|
||||
|
||||
|
||||
class Tablet extends Service {
|
||||
static {
|
||||
Service.register(this, {
|
||||
'device-fetched': ['boolean'],
|
||||
'autorotate-started': ['boolean'],
|
||||
'autorotate-destroyed': ['boolean'],
|
||||
'inputs-blocked': ['boolean'],
|
||||
'inputs-unblocked': ['boolean'],
|
||||
'laptop-mode': ['boolean'],
|
||||
'tablet-mode': ['boolean'],
|
||||
'mode-toggled': ['boolean'],
|
||||
});
|
||||
}
|
||||
|
||||
tabletMode = false;
|
||||
autorotate = undefined;
|
||||
blockedInputs = undefined;
|
||||
udevClient = GUdev.Client.new(['input']);
|
||||
|
||||
get tabletMode() { return this.tabletMode; }
|
||||
get autorotate() { return this.autorotate; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.initUdevConnection();
|
||||
}
|
||||
|
||||
blockInputs() {
|
||||
if (this.blockedInputs)
|
||||
return;
|
||||
|
||||
this.blockedInputs = subprocess(['libinput', 'debug-events', '--grab',
|
||||
'--device', '/dev/input/by-path/platform-i8042-serio-0-event-kbd',
|
||||
'--device', '/dev/input/by-path/platform-i8042-serio-1-event-mouse',
|
||||
'--device', '/dev/input/by-path/platform-AMDI0010:02-event-mouse',
|
||||
'--device', '/dev/input/by-path/platform-thinkpad_acpi-event',
|
||||
'--device', '/dev/video-bus',
|
||||
'--device', '/dev/touchpad',
|
||||
],
|
||||
() => {},
|
||||
err => logError(err));
|
||||
this.emit('inputs-blocked', true);
|
||||
}
|
||||
|
||||
unblockInputs() {
|
||||
if (this.blockedInputs) {
|
||||
this.blockedInputs.force_exit();
|
||||
this.blockedInputs = undefined;
|
||||
this.emit('inputs-unblocked', true);
|
||||
}
|
||||
}
|
||||
|
||||
setTabletMode() {
|
||||
execAsync(['gsettings', 'set', 'org.gnome.desktop.a11y.applications',
|
||||
'screen-keyboard-enabled', 'true']).catch(print);
|
||||
|
||||
execAsync(['brightnessctl', '-d', 'tpacpi::kbd_backlight', 's', '0'])
|
||||
.catch(print);
|
||||
|
||||
this.startAutorotate();
|
||||
this.blockInputs();
|
||||
|
||||
this.tabletMode = true;
|
||||
this.emit('tablet-mode', true);
|
||||
this.emit('mode-toggled', true);
|
||||
}
|
||||
|
||||
setLaptopMode() {
|
||||
execAsync(['gsettings', 'set', 'org.gnome.desktop.a11y.applications',
|
||||
'screen-keyboard-enabled', 'false']).catch(print);
|
||||
|
||||
execAsync(['brightnessctl', '-d', 'tpacpi::kbd_backlight', 's', '2'])
|
||||
.catch(print);
|
||||
|
||||
this.killAutorotate();
|
||||
this.unblockInputs();
|
||||
|
||||
this.tabletMode = false;
|
||||
this.emit('laptop-mode', true);
|
||||
this.emit('mode-toggled', true);
|
||||
}
|
||||
|
||||
toggleMode() {
|
||||
if (this.tabletMode)
|
||||
this.setLaptopMode();
|
||||
else
|
||||
this.setTabletMode();
|
||||
|
||||
this.emit('mode-toggled', true);
|
||||
}
|
||||
|
||||
initUdevConnection() {
|
||||
this.getDevices();
|
||||
this.udevClient.connect('uevent', (_, action) => {
|
||||
if (action === 'add' || action === 'remove')
|
||||
this.getDevices();
|
||||
});
|
||||
}
|
||||
|
||||
getDevices() {
|
||||
this.devices = [];
|
||||
execAsync(['hyprctl', 'devices', '-j']).then(out => {
|
||||
const devices = JSON.parse(out);
|
||||
devices['touch'].forEach(dev => {
|
||||
this.devices.push(dev.name);
|
||||
});
|
||||
devices['tablets'].forEach(dev => {
|
||||
this.devices.push(dev.name);
|
||||
});
|
||||
}).catch(print);
|
||||
|
||||
this.emit('device-fetched', true);
|
||||
}
|
||||
|
||||
startAutorotate() {
|
||||
if (this.autorotate)
|
||||
return;
|
||||
|
||||
this.autorotate = subprocess(
|
||||
['monitor-sensor'],
|
||||
output => {
|
||||
if (output.includes('orientation changed')) {
|
||||
const orientation = ROTATION_MAPPING[output.split(' ').at(-1)];
|
||||
|
||||
execAsync(['hyprctl', 'keyword', 'monitor',
|
||||
`${SCREEN},transform,${orientation}`]).catch(print);
|
||||
|
||||
this.devices.forEach(dev => {
|
||||
execAsync(['hyprctl', 'keyword',
|
||||
`device:"${dev}":transform`, String(orientation)]).catch(print);
|
||||
});
|
||||
}
|
||||
},
|
||||
err => logError(err),
|
||||
);
|
||||
this.emit('autorotate-started', true);
|
||||
}
|
||||
|
||||
killAutorotate() {
|
||||
if (this.autorotate) {
|
||||
this.autorotate.force_exit();
|
||||
this.autorotate = undefined;
|
||||
this.emit('autorotate-destroyed', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tabletService = new Tablet();
|
||||
export default tabletService;
|
Loading…
Reference in a new issue