nixos-configs/modules/ags/config/widgets/on-screen-keyboard/gesture.ts

224 lines
6.5 KiB
TypeScript
Raw Normal View History

import { execAsync, idle } from 'astal';
2024-11-25 21:17:36 -05:00
import { Astal, Gtk } from 'astal/gtk3';
2024-11-25 12:09:03 -05:00
import Tablet from '../../services/tablet';
2024-11-25 12:09:03 -05:00
import { hyprMessage } from '../../lib';
import OskWindow from './osk-window';
import { Keys } from './keys';
2024-11-25 12:09:03 -05:00
const KEY_N = 249;
const KEYCODES = Array.from(Array(KEY_N).keys()).map((keycode) => `${keycode}:0`);
2024-11-25 12:09:03 -05:00
2024-11-25 21:17:36 -05:00
const ANIM_DURATION = 700;
2024-11-25 12:09:03 -05:00
2024-11-25 21:17:36 -05:00
const releaseAllKeys = () => {
2024-11-25 12:09:03 -05:00
execAsync([
'ydotool', 'key',
...KEYCODES,
2024-11-25 12:09:03 -05:00
]).catch(print);
};
export default (window: OskWindow) => {
const tablet = Tablet.get_default();
2024-11-25 12:09:03 -05:00
let signals = [] as number[];
2024-11-25 21:17:36 -05:00
let calculatedHeight = 0;
2024-11-25 12:09:03 -05:00
2024-11-25 21:17:36 -05:00
idle(() => {
calculatedHeight = window.get_allocated_height();
tablet.oskState = false;
setTimeout(() => {
window.get_grandchildren()[0].toggleClassName('hidden', false);
window.set_exclusivity(Astal.Exclusivity.EXCLUSIVE);
}, ANIM_DURATION * 3);
});
2024-11-25 21:17:36 -05:00
const gesture = Gtk.GestureDrag.new(window);
window.hook(tablet, 'notify::osk-state', () => {
if (tablet.oskState) {
2024-11-25 12:09:03 -05:00
window.setSlideDown();
window.get_child().css = `
2024-11-25 21:17:36 -05:00
transition: margin-bottom ${ANIM_DURATION}ms cubic-bezier(0.36, 0, 0.66, -0.56);
2024-11-25 12:09:03 -05:00
margin-bottom: 0px;
`;
}
else {
releaseAllKeys();
2024-11-25 12:09:03 -05:00
window.setSlideUp();
window.get_child().css = `
2024-11-25 21:17:36 -05:00
transition: margin-bottom ${ANIM_DURATION}ms cubic-bezier(0.36, 0, 0.66, -0.56);
margin-bottom: -${calculatedHeight}px;
2024-11-25 12:09:03 -05:00
`;
}
});
2024-11-25 12:09:03 -05:00
window.killGestureSigs = () => {
signals.forEach((id) => {
gesture.disconnect(id);
});
signals = [];
window.startY = null;
};
window.setSlideUp = () => {
window.killGestureSigs();
// Begin drag
signals.push(
gesture.connect('drag-begin', () => {
hyprMessage('j/cursorpos').then((out) => {
window.startY = JSON.parse(out).y;
});
}),
);
// Update drag
signals.push(
gesture.connect('drag-update', () => {
hyprMessage('j/cursorpos').then((out) => {
if (!window.startY) {
return;
}
const currentY = JSON.parse(out).y;
const offset = window.startY - currentY;
if (offset < 0) {
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
2024-11-25 21:17:36 -05:00
margin-bottom: -${calculatedHeight}px;
2024-11-25 12:09:03 -05:00
`;
return;
}
2024-11-25 21:17:36 -05:00
if (offset > calculatedHeight) {
window.get_child().css = `
margin-bottom: 0px;
`;
}
else {
window.get_child().css = `
2024-11-25 21:17:36 -05:00
margin-bottom: ${offset - calculatedHeight}px;
`;
}
2024-11-25 12:09:03 -05:00
});
}),
);
// End drag
signals.push(
gesture.connect('drag-end', () => {
hyprMessage('j/cursorpos').then((out) => {
if (!window.startY) {
return;
}
const currentY = JSON.parse(out).y;
const offset = window.startY - currentY;
2024-11-25 21:17:36 -05:00
if (offset > calculatedHeight) {
2024-11-25 12:09:03 -05:00
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
margin-bottom: 0px;
`;
tablet.oskState = true;
2024-11-25 12:09:03 -05:00
}
else {
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
2024-11-25 21:17:36 -05:00
margin-bottom: -${calculatedHeight}px;
2024-11-25 12:09:03 -05:00
`;
}
window.startY = null;
2024-11-25 12:09:03 -05:00
});
}),
);
};
window.setSlideDown = () => {
window.killGestureSigs();
// Begin drag
signals.push(
gesture.connect('drag-begin', () => {
hyprMessage('j/cursorpos').then((out) => {
const hasActiveKey = Keys.get().map((v) => v.get()).includes(true);
if (!hasActiveKey) {
window.startY = JSON.parse(out).y;
}
2024-11-25 12:09:03 -05:00
});
}),
);
// Update drag
signals.push(
gesture.connect('drag-update', () => {
hyprMessage('j/cursorpos').then((out) => {
if (!window.startY) {
return;
}
const currentY = JSON.parse(out).y;
const offset = window.startY - currentY;
if (offset > 0) {
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
margin-bottom: 0px;
`;
return;
}
window.get_child().css = `
margin-bottom: ${offset}px;
`;
});
}),
);
// End drag
signals.push(
gesture.connect('drag-end', () => {
hyprMessage('j/cursorpos').then((out) => {
if (!window.startY) {
return;
}
const currentY = JSON.parse(out).y;
const offset = window.startY - currentY;
2024-11-25 21:17:36 -05:00
if (offset < -(calculatedHeight * 2 / 3)) {
2024-11-25 12:09:03 -05:00
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
2024-11-25 21:17:36 -05:00
margin-bottom: -${calculatedHeight}px;
2024-11-25 12:09:03 -05:00
`;
tablet.oskState = false;
2024-11-25 12:09:03 -05:00
}
else {
window.get_child().css = `
transition: margin-bottom 0.5s ease-in-out;
margin-bottom: 0px;
`;
}
window.startY = null;
2024-11-25 12:09:03 -05:00
});
}),
);
};
return window;
};