Compare commits
No commits in common. "63c5d0b72f939871be08014d6a67b4f02bd7a97f" and "b0710205e6f4819d598e299e2f09f1c421d40477" have entirely different histories.
63c5d0b72f
...
b0710205e6
8 changed files with 80 additions and 101 deletions
|
@ -21,6 +21,7 @@ exec(`sassc ${scss} ${css}`);
|
||||||
Setup();
|
Setup();
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: get rid of 'properties' and 'binds' prop
|
||||||
export default {
|
export default {
|
||||||
style: css,
|
style: css,
|
||||||
notificationPopupTimeout: 5000,
|
notificationPopupTimeout: 5000,
|
||||||
|
|
|
@ -80,7 +80,6 @@ const ModKey = (key) => {
|
||||||
const button = EventBox({
|
const button = EventBox({
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
class_name: 'key',
|
class_name: 'key',
|
||||||
|
|
||||||
on_primary_click_release: (self) => {
|
on_primary_click_release: (self) => {
|
||||||
console.log('mod toggled');
|
console.log('mod toggled');
|
||||||
|
|
||||||
|
@ -90,7 +89,6 @@ const ModKey = (key) => {
|
||||||
self.child.toggleClassName('active', !Mod.value);
|
self.child.toggleClassName('active', !Mod.value);
|
||||||
Mod.value = !Mod.value;
|
Mod.value = !Mod.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
setup: (self) => {
|
setup: (self) => {
|
||||||
self.hook(NormalClick, () => {
|
self.hook(NormalClick, () => {
|
||||||
Mod.value = false;
|
Mod.value = false;
|
||||||
|
|
|
@ -7,13 +7,14 @@ import PopupWindow from './misc/popup.js';
|
||||||
import CursorBox from './misc/cursorbox.js';
|
import CursorBox from './misc/cursorbox.js';
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: eventboxes are the wrong size
|
||||||
const PowermenuWidget = () => CenterBox({
|
const PowermenuWidget = () => CenterBox({
|
||||||
class_name: 'powermenu',
|
class_name: 'powermenu',
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
vertical: false,
|
vertical: false,
|
||||||
|
|
||||||
start_widget: CursorBox({
|
start_widget: CursorBox({
|
||||||
class_name: 'shutdown button',
|
class_name: 'shutdown',
|
||||||
on_primary_click_release: () => execAsync(['systemctl', 'poweroff'])
|
on_primary_click_release: () => execAsync(['systemctl', 'poweroff'])
|
||||||
.catch(print),
|
.catch(print),
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ const PowermenuWidget = () => CenterBox({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
center_widget: CursorBox({
|
center_widget: CursorBox({
|
||||||
class_name: 'reboot button',
|
class_name: 'reboot',
|
||||||
on_primary_click_release: () => execAsync(['systemctl', 'reboot'])
|
on_primary_click_release: () => execAsync(['systemctl', 'reboot'])
|
||||||
.catch(print),
|
.catch(print),
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ const PowermenuWidget = () => CenterBox({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
end_widget: CursorBox({
|
end_widget: CursorBox({
|
||||||
class_name: 'logout button',
|
class_name: 'logout',
|
||||||
on_primary_click_release: () => Hyprland.sendMessage('dispatch exit')
|
on_primary_click_release: () => Hyprland.sendMessage('dispatch exit')
|
||||||
.catch(print),
|
.catch(print),
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default () => Box({
|
||||||
Icon({
|
Icon({
|
||||||
size: 26,
|
size: 26,
|
||||||
class_name: 'slider-label',
|
class_name: 'slider-label',
|
||||||
icon: SpeakerIcon.bind(),
|
binds: [['icon', SpeakerIcon, 'value']],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Slider({
|
Slider({
|
||||||
|
@ -62,7 +62,7 @@ export default () => Box({
|
||||||
children: [
|
children: [
|
||||||
Icon({
|
Icon({
|
||||||
class_name: 'slider-label',
|
class_name: 'slider-label',
|
||||||
icon: Brightness.bind('screenIcon'),
|
binds: [['icon', Brightness, 'screen-icon']],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Slider({
|
Slider({
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
min-height: 130px;
|
min-height: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
button {
|
||||||
margin: 5px 10px;
|
margin: 5px 10px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||||
|
|
||||||
import { subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
|
import { subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||||
|
import GUdev from 'gi://GUdev';
|
||||||
const { GUdev } = imports.gi;
|
|
||||||
|
|
||||||
const UDEV_POINTERS = [
|
const UDEV_POINTERS = [
|
||||||
'ID_INPUT_MOUSE',
|
'ID_INPUT_MOUSE',
|
||||||
|
@ -36,10 +34,8 @@ class Pointers extends Service {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type typeof imports.gi.Gio.Subprocess */
|
|
||||||
#process;
|
#process;
|
||||||
#lastLine = '';
|
#lastLine = '';
|
||||||
/** @type Array<string> */
|
|
||||||
#pointers = [];
|
#pointers = [];
|
||||||
#udevClient = GUdev.Client.new(['input']);
|
#udevClient = GUdev.Client.new(['input']);
|
||||||
|
|
||||||
|
@ -64,12 +60,7 @@ class Pointers extends Service {
|
||||||
// FIXME: logitech mouse screws everything up on disconnect
|
// FIXME: logitech mouse screws everything up on disconnect
|
||||||
#initUdevConnection() {
|
#initUdevConnection() {
|
||||||
this.#getDevices();
|
this.#getDevices();
|
||||||
this.#udevClient.connect('uevent',
|
this.#udevClient.connect('uevent', (_, action) => {
|
||||||
/**
|
|
||||||
* @param {typeof imports.gi.GUdev.Client} _
|
|
||||||
* @param {string} action
|
|
||||||
*/
|
|
||||||
(_, action) => {
|
|
||||||
if (action === 'add' || action === 'remove') {
|
if (action === 'add' || action === 'remove') {
|
||||||
this.#getDevices();
|
this.#getDevices();
|
||||||
if (this.#process) {
|
if (this.#process) {
|
||||||
|
@ -82,12 +73,8 @@ class Pointers extends Service {
|
||||||
|
|
||||||
#getDevices() {
|
#getDevices() {
|
||||||
this.#pointers = [];
|
this.#pointers = [];
|
||||||
this.#udevClient.query_by_subsystem('input').forEach(
|
this.#udevClient.query_by_subsystem('input').forEach((dev) => {
|
||||||
/** @param {typeof imports.gi.GUdev.Device} dev */
|
const isPointer = UDEV_POINTERS.some((p) => dev.has_property(p));
|
||||||
(dev) => {
|
|
||||||
const isPointer = UDEV_POINTERS.some(
|
|
||||||
(p) => dev.has_property(p),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isPointer) {
|
if (isPointer) {
|
||||||
const hasEventFile = dev.has_property('DEVNAME') &&
|
const hasEventFile = dev.has_property('DEVNAME') &&
|
||||||
|
@ -98,8 +85,7 @@ class Pointers extends Service {
|
||||||
this.#pointers.push(dev.get_property('DEVNAME'));
|
this.#pointers.push(dev.get_property('DEVNAME'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
this.emit('device-fetched', true);
|
this.emit('device-fetched', true);
|
||||||
}
|
}
|
||||||
|
@ -137,6 +123,7 @@ class Pointers extends Service {
|
||||||
this.emit('new-line', output);
|
this.emit('new-line', output);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
(err) => logError(err),
|
||||||
);
|
);
|
||||||
this.emit('proc-started', true);
|
this.emit('proc-started', true);
|
||||||
}
|
}
|
||||||
|
@ -152,11 +139,8 @@ class Pointers extends Service {
|
||||||
#initAppConnection() {
|
#initAppConnection() {
|
||||||
App.connect('window-toggled', () => {
|
App.connect('window-toggled', () => {
|
||||||
const anyVisibleAndClosable = Array.from(App.windows).some((w) => {
|
const anyVisibleAndClosable = Array.from(App.windows).some((w) => {
|
||||||
// @ts-expect-error
|
|
||||||
const closable = w[1].attribute?.close_on_unfocus &&
|
const closable = w[1].attribute?.close_on_unfocus &&
|
||||||
// @ts-expect-error
|
|
||||||
!(w[1].attribute?.close_on_unfocus === 'none' ||
|
!(w[1].attribute?.close_on_unfocus === 'none' ||
|
||||||
// @ts-expect-error
|
|
||||||
w[1].attribute?.close_on_unfocus === 'stay');
|
w[1].attribute?.close_on_unfocus === 'stay');
|
||||||
|
|
||||||
return w[1].visible && closable;
|
return w[1].visible && closable;
|
||||||
|
@ -172,12 +156,9 @@ class Pointers extends Service {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {string} clickStage */
|
|
||||||
static detectClickedOutside(clickStage) {
|
static detectClickedOutside(clickStage) {
|
||||||
const toClose = Array.from(App.windows).some((w) => {
|
const toClose = Array.from(App.windows).some((w) => {
|
||||||
// @ts-expect-error
|
|
||||||
const closable = (w[1].attribute?.close_on_unfocus &&
|
const closable = (w[1].attribute?.close_on_unfocus &&
|
||||||
// @ts-expect-error
|
|
||||||
w[1].attribute?.close_on_unfocus === clickStage);
|
w[1].attribute?.close_on_unfocus === clickStage);
|
||||||
|
|
||||||
return w[1].visible && closable;
|
return w[1].visible && closable;
|
||||||
|
@ -187,31 +168,22 @@ class Pointers extends Service {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hyprland.sendMessage('j/layers').then((response) => {
|
Hyprland.sendMessage('j/layers').then((layers) => {
|
||||||
// /** @type import('types/service/hyprland').Layer */
|
layers = JSON.parse(layers);
|
||||||
const layers = JSON.parse(response);
|
|
||||||
|
|
||||||
Hyprland.sendMessage('j/cursorpos').then((res) => {
|
Hyprland.sendMessage('j/cursorpos').then((pos) => {
|
||||||
const pos = JSON.parse(res);
|
pos = JSON.parse(pos);
|
||||||
|
|
||||||
Object.values(layers).forEach((key) => {
|
Object.values(layers).forEach((key) => {
|
||||||
const bar = key.levels['3'].find(
|
const bar = key.levels['3']
|
||||||
/** @param {{ namespace: string }} n */
|
.find((n) => n.namespace === 'bar');
|
||||||
(n) => n.namespace === 'bar',
|
|
||||||
);
|
|
||||||
|
|
||||||
const widgets = key.levels['3'].filter(
|
const widgets = key.levels['3'].filter((n) => {
|
||||||
/** @param {{ namespace: string }} n */
|
|
||||||
(n) => {
|
|
||||||
const window = App.getWindow(n.namespace);
|
const window = App.getWindow(n.namespace);
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
return window?.attribute?.close_on_unfocus &&
|
return window?.attribute?.close_on_unfocus &&
|
||||||
// @ts-expect-error
|
window?.attribute?.close_on_unfocus === clickStage;
|
||||||
window?.attribute
|
});
|
||||||
?.close_on_unfocus === clickStage;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pos.x > bar?.x && pos.x < bar?.x + bar?.w &&
|
if (pos.x > bar?.x && pos.x < bar?.x + bar?.w &&
|
||||||
pos.y > bar?.y && pos.y < bar?.y + bar?.h) {
|
pos.y > bar?.y && pos.y < bar?.y + bar?.h) {
|
||||||
|
@ -220,22 +192,12 @@ class Pointers extends Service {
|
||||||
// TODO: make this configurable
|
// TODO: make this configurable
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
widgets.forEach(
|
widgets.forEach((w) => {
|
||||||
/** @param {{
|
|
||||||
* namespace: string
|
|
||||||
* x: number
|
|
||||||
* y: number
|
|
||||||
* h: number
|
|
||||||
* w: number
|
|
||||||
* }} w
|
|
||||||
*/
|
|
||||||
(w) => {
|
|
||||||
if (!(pos.x > w.x && pos.x < w.x + w.w &&
|
if (!(pos.x > w.x && pos.x < w.x + w.w &&
|
||||||
pos.y > w.y && pos.y < w.y + w.h)) {
|
pos.y > w.y && pos.y < w.y + w.h)) {
|
||||||
App.closeWindow(w.namespace);
|
App.closeWindow(w.namespace);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch(print);
|
}).catch(print);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||||
import TouchGestures from './touch-gestures.js';
|
import TouchGestures from './touch-gestures.js';
|
||||||
import { execAsync, subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
|
import { execAsync, subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||||
|
import GUdev from 'gi://GUdev';
|
||||||
|
|
||||||
const ROTATION_MAP = {
|
const ROTATION_MAP = {
|
||||||
'normal': 0,
|
'normal': 0,
|
||||||
|
@ -10,10 +11,6 @@ const ROTATION_MAP = {
|
||||||
'left-up': 1,
|
'left-up': 1,
|
||||||
};
|
};
|
||||||
const SCREEN = 'desc:BOE 0x0964';
|
const SCREEN = 'desc:BOE 0x0964';
|
||||||
const DEVICES = [
|
|
||||||
'wacom-hid-52eb-finger',
|
|
||||||
'wacom-hid-52eb-pen',
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
class Tablet extends Service {
|
class Tablet extends Service {
|
||||||
|
@ -33,10 +30,9 @@ class Tablet extends Service {
|
||||||
|
|
||||||
#tabletMode = false;
|
#tabletMode = false;
|
||||||
#oskState = false;
|
#oskState = false;
|
||||||
/** @type typeof imports.gi.Gio.Subprocess */
|
|
||||||
#autorotate;
|
#autorotate;
|
||||||
/** @type typeof imports.gi.Gio.Subprocess */
|
|
||||||
#blockedInputs;
|
#blockedInputs;
|
||||||
|
#udevClient = GUdev.Client.new(['input']);
|
||||||
|
|
||||||
get tabletMode() {
|
get tabletMode() {
|
||||||
return this.#tabletMode;
|
return this.#tabletMode;
|
||||||
|
@ -48,6 +44,7 @@ class Tablet extends Service {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this.#initUdevConnection();
|
||||||
this.#listenOskState();
|
this.#listenOskState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +59,8 @@ class Tablet extends Service {
|
||||||
'--device', '/dev/input/by-path/platform-AMDI0010:02-event-mouse',
|
'--device', '/dev/input/by-path/platform-AMDI0010:02-event-mouse',
|
||||||
'--device', '/dev/input/by-path/platform-thinkpad_acpi-event',
|
'--device', '/dev/input/by-path/platform-thinkpad_acpi-event',
|
||||||
'--device', '/dev/video-bus'],
|
'--device', '/dev/video-bus'],
|
||||||
() => { /**/ });
|
() => { /**/ },
|
||||||
|
(err) => logError(err));
|
||||||
this.emit('inputs-blocked', true);
|
this.emit('inputs-blocked', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +113,31 @@ class Tablet extends Service {
|
||||||
this.emit('mode-toggled', true);
|
this.emit('mode-toggled', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#initUdevConnection() {
|
||||||
|
this.#getDevices();
|
||||||
|
this.#udevClient.connect('uevent', (_, action) => {
|
||||||
|
if (action === 'add' || action === 'remove') {
|
||||||
|
this.#getDevices();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#getDevices() {
|
||||||
|
this.devices = [];
|
||||||
|
Hyprland.sendMessage('j/devices').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() {
|
startAutorotate() {
|
||||||
if (this.#autorotate) {
|
if (this.#autorotate) {
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +153,7 @@ class Tablet extends Service {
|
||||||
`keyword monitor ${SCREEN},transform,${orientation}`,
|
`keyword monitor ${SCREEN},transform,${orientation}`,
|
||||||
).catch(print);
|
).catch(print);
|
||||||
|
|
||||||
const batchRotate = DEVICES.map((dev) =>
|
const batchRotate = this.devices.map((dev) =>
|
||||||
`keyword device:${dev}:transform ${orientation}; `);
|
`keyword device:${dev}:transform ${orientation}; `);
|
||||||
|
|
||||||
Hyprland.sendMessage(`[[BATCH]] ${batchRotate.flat()}`);
|
Hyprland.sendMessage(`[[BATCH]] ${batchRotate.flat()}`);
|
||||||
|
@ -141,6 +164,7 @@ class Tablet extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
(err) => logError(err),
|
||||||
);
|
);
|
||||||
this.emit('autorotate-started', true);
|
this.emit('autorotate-started', true);
|
||||||
}
|
}
|
||||||
|
@ -158,14 +182,11 @@ class Tablet extends Service {
|
||||||
['bash', '-c', 'busctl monitor --user sm.puri.OSK0'],
|
['bash', '-c', 'busctl monitor --user sm.puri.OSK0'],
|
||||||
(output) => {
|
(output) => {
|
||||||
if (output.includes('BOOLEAN')) {
|
if (output.includes('BOOLEAN')) {
|
||||||
const match = output.match('true|false');
|
this.#oskState = output.match('true|false')[0] === 'true';
|
||||||
|
|
||||||
if (match) {
|
|
||||||
this.#oskState = match[0] === 'true';
|
|
||||||
this.emit('osk-toggled', this.#oskState);
|
this.emit('osk-toggled', this.#oskState);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
(err) => logError(err),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,17 +44,12 @@ class TouchGestures extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
#gestures = new Map();
|
#gestures = new Map();
|
||||||
/** @type typeof imports.gi.Gio.Subprocess */
|
|
||||||
#gestureDaemon;
|
#gestureDaemon;
|
||||||
|
|
||||||
get gestures() {
|
get gestures() {
|
||||||
return this.#gestures;
|
return this.#gestures;
|
||||||
}
|
}
|
||||||
|
|
||||||
get gestureDaemon() {
|
|
||||||
return this.#gestureDaemon;
|
|
||||||
}
|
|
||||||
|
|
||||||
addGesture({
|
addGesture({
|
||||||
name,
|
name,
|
||||||
nFingers = '1',
|
nFingers = '1',
|
||||||
|
@ -62,7 +57,7 @@ class TouchGestures extends Service {
|
||||||
edge = '*',
|
edge = '*',
|
||||||
distance = '*',
|
distance = '*',
|
||||||
command,
|
command,
|
||||||
}) {
|
} = {}) {
|
||||||
gesture = String(gesture).toUpperCase();
|
gesture = String(gesture).toUpperCase();
|
||||||
if (!GESTURE_VERIF.includes(gesture)) {
|
if (!GESTURE_VERIF.includes(gesture)) {
|
||||||
logError('Wrong gesture id');
|
logError('Wrong gesture id');
|
||||||
|
@ -124,6 +119,7 @@ class TouchGestures extends Service {
|
||||||
this.#gestureDaemon = subprocess(
|
this.#gestureDaemon = subprocess(
|
||||||
command,
|
command,
|
||||||
() => { /**/ },
|
() => { /**/ },
|
||||||
|
(err) => logError(err),
|
||||||
);
|
);
|
||||||
this.emit('daemon-started', true);
|
this.emit('daemon-started', true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue