feat(ags osk): add spam typing on long press
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
f445db75c1
commit
d85b0847dd
6 changed files with 92 additions and 108 deletions
|
@ -32,8 +32,7 @@
|
|||
border-radius: 0.7rem;
|
||||
min-height: 3rem;
|
||||
|
||||
transition: background-color 0.2s ease-in-out,
|
||||
border-color 0.2s ease-in-out;
|
||||
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
|
||||
|
||||
&.normal,
|
||||
&.Super {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { execAsync } from 'astal';
|
||||
import { execAsync, idle } from 'astal';
|
||||
import { Gtk } from 'astal/gtk3';
|
||||
|
||||
import Tablet from '../../services/tablet';
|
||||
import { hyprMessage } from '../../lib';
|
||||
|
||||
import OskWindow from './osk-window';
|
||||
|
@ -19,14 +20,18 @@ const releaseAllKeys = () => {
|
|||
};
|
||||
|
||||
export default (window: OskWindow) => {
|
||||
const gesture = Gtk.GestureDrag.new(window);
|
||||
|
||||
window.get_child().css = `margin-bottom: -${HIDDEN_MARGIN}px;`;
|
||||
const tablet = Tablet.get_default();
|
||||
|
||||
let signals = [] as number[];
|
||||
|
||||
window.setVisible = (state: boolean) => {
|
||||
if (state) {
|
||||
const gesture = Gtk.GestureDrag.new(window);
|
||||
|
||||
window.get_child().css = `
|
||||
margin-bottom: -${HIDDEN_MARGIN}px;
|
||||
`;
|
||||
|
||||
window.hook(tablet, 'notify::osk-state', () => {
|
||||
if (tablet.oskState) {
|
||||
window.setSlideDown();
|
||||
|
||||
window.get_child().css = `
|
||||
|
@ -36,6 +41,7 @@ export default (window: OskWindow) => {
|
|||
}
|
||||
else {
|
||||
releaseAllKeys();
|
||||
|
||||
window.setSlideUp();
|
||||
|
||||
window.get_child().css = `
|
||||
|
@ -43,7 +49,11 @@ export default (window: OskWindow) => {
|
|||
margin-bottom: -${HIDDEN_MARGIN}px;
|
||||
`;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
idle(() => {
|
||||
tablet.oskState = false;
|
||||
});
|
||||
|
||||
window.killGestureSigs = () => {
|
||||
signals.forEach((id) => {
|
||||
|
@ -115,7 +125,7 @@ export default (window: OskWindow) => {
|
|||
transition: margin-bottom 0.5s ease-in-out;
|
||||
margin-bottom: 0px;
|
||||
`;
|
||||
window.setVisible(true);
|
||||
tablet.oskState = true;
|
||||
}
|
||||
else {
|
||||
window.get_child().css = `
|
||||
|
@ -184,7 +194,7 @@ export default (window: OskWindow) => {
|
|||
margin-bottom: -${HIDDEN_MARGIN}px;
|
||||
`;
|
||||
|
||||
window.setVisible(false);
|
||||
tablet.oskState = false;
|
||||
}
|
||||
else {
|
||||
window.get_child().css = `
|
||||
|
|
|
@ -115,8 +115,8 @@ export default () => (
|
|||
return (
|
||||
<box vertical>
|
||||
<box
|
||||
halign={Gtk.Align.END}
|
||||
className="row"
|
||||
halign={Gtk.Align.END}
|
||||
>
|
||||
{...keys}
|
||||
</box>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { execAsync, Variable } from 'astal';
|
||||
import { Gdk, Gtk, Widget } from 'astal/gtk3';
|
||||
import { bind, execAsync, interval, Variable } from 'astal';
|
||||
import { Gtk, Widget } from 'astal/gtk3';
|
||||
|
||||
import Brightness from '../../services/brightness';
|
||||
|
||||
import Separator from '../misc/separator';
|
||||
|
||||
/* Types */
|
||||
import AstalIO from 'gi://AstalIO';
|
||||
|
||||
interface Key {
|
||||
keytype: string
|
||||
label: string
|
||||
|
@ -16,7 +18,6 @@ interface Key {
|
|||
}
|
||||
|
||||
|
||||
const display = Gdk.Display.get_default();
|
||||
const brightness = Brightness.get_default();
|
||||
|
||||
const SPACING = 4;
|
||||
|
@ -24,10 +25,6 @@ const LSHIFT_CODE = 42;
|
|||
const LALT_CODE = 56;
|
||||
const LCTRL_CODE = 29;
|
||||
|
||||
// Keep track of when a non modifier key
|
||||
// is clicked to release all modifiers
|
||||
const NormalClick = Variable(false);
|
||||
|
||||
// Keep track of modifier statuses
|
||||
const Super = Variable(false);
|
||||
const LAlt = Variable(false);
|
||||
|
@ -97,42 +94,14 @@ const ModKey = (key: Key) => {
|
|||
const button = (
|
||||
<eventbox
|
||||
className="key"
|
||||
cursor="pointer"
|
||||
|
||||
onButtonReleaseEvent={() => {
|
||||
console.log('mod toggled');
|
||||
|
||||
onButtonPressEvent={() => {
|
||||
execAsync(`ydotool key ${key.keycode}:${Mod.get() ? 0 : 1}`);
|
||||
|
||||
label.toggleClassName('active', !Mod.get());
|
||||
Mod.set(!Mod.get());
|
||||
}}
|
||||
|
||||
setup={(self) => {
|
||||
self.hook(NormalClick, () => {
|
||||
Mod.set(false);
|
||||
|
||||
label.toggleClassName('active', false);
|
||||
execAsync(`ydotool key ${key.keycode}:0`);
|
||||
});
|
||||
|
||||
// OnHover
|
||||
self.connect('enter-notify-event', () => {
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(
|
||||
display,
|
||||
'pointer',
|
||||
));
|
||||
self.toggleClassName('hover', true);
|
||||
});
|
||||
|
||||
// OnHoverLost
|
||||
self.connect('leave-notify-event', () => {
|
||||
self.window.set_cursor(null);
|
||||
self.toggleClassName('hover', false);
|
||||
});
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</eventbox>
|
||||
|
@ -147,65 +116,58 @@ const ModKey = (key: Key) => {
|
|||
};
|
||||
|
||||
const RegularKey = (key: Key) => {
|
||||
const IsActive = Variable(false);
|
||||
const IsLongPressing = Variable(false);
|
||||
|
||||
const widget = (
|
||||
<eventbox
|
||||
className="key"
|
||||
cursor="pointer"
|
||||
|
||||
onButtonReleaseEvent={() => {
|
||||
IsLongPressing.set(false);
|
||||
IsActive.set(false);
|
||||
}}
|
||||
>
|
||||
<label
|
||||
className={`normal ${key.label}`}
|
||||
className={bind(IsActive).as((v) => [
|
||||
'normal',
|
||||
key.label,
|
||||
(v ? 'active' : ''),
|
||||
].join(' '))}
|
||||
|
||||
label={key.label}
|
||||
|
||||
setup={(self) => {
|
||||
self
|
||||
.hook(Shift, () => {
|
||||
if (!key.labelShift) {
|
||||
return;
|
||||
if (key.labelShift) {
|
||||
self.label = Shift.get() ?
|
||||
key.labelShift :
|
||||
key.label;
|
||||
}
|
||||
|
||||
self.label = Shift.get() ? key.labelShift : key.label;
|
||||
})
|
||||
.hook(Caps, () => {
|
||||
if (key.label === 'Caps') {
|
||||
self.toggleClassName('active', Caps.get());
|
||||
IsActive.set(Caps.get());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key.labelShift) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.label.match(/[A-Za-z]/)) {
|
||||
if (key.labelShift && key.label.match(/[A-Za-z]/)) {
|
||||
self.label = Caps.get() ?
|
||||
key.labelShift :
|
||||
key.label;
|
||||
}
|
||||
})
|
||||
.hook(AltGr, () => {
|
||||
if (!key.labelAltGr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.labelAltGr) {
|
||||
self.toggleClassName('altgr', AltGr.get());
|
||||
self.label = AltGr.get() ? key.labelAltGr : key.label;
|
||||
});
|
||||
|
||||
// OnHover
|
||||
self.connect('enter-notify-event', () => {
|
||||
if (!display) {
|
||||
return;
|
||||
self.label = AltGr.get() ?
|
||||
key.labelAltGr :
|
||||
key.label;
|
||||
}
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(
|
||||
display,
|
||||
'pointer',
|
||||
));
|
||||
self.toggleClassName('hover', true);
|
||||
});
|
||||
|
||||
// OnHoverLost
|
||||
self.connect('leave-notify-event', () => {
|
||||
self.window.set_cursor(null);
|
||||
self.toggleClassName('hover', false);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
@ -216,8 +178,7 @@ const RegularKey = (key: Key) => {
|
|||
|
||||
gesture.delay_factor = 1.0;
|
||||
|
||||
// OnPrimaryClickRelease
|
||||
widget.hook(gesture, 'cancelled', () => {
|
||||
const onClick = (callback: () => void) => {
|
||||
const pointer = gesture.get_point(null);
|
||||
const x = pointer[1];
|
||||
const y = pointer[2];
|
||||
|
@ -226,11 +187,41 @@ const RegularKey = (key: Key) => {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log('key clicked');
|
||||
callback();
|
||||
};
|
||||
|
||||
widget.hook(gesture, 'begin', () => {
|
||||
IsActive.set(true);
|
||||
});
|
||||
|
||||
widget.hook(gesture, 'cancelled', () => {
|
||||
onClick(() => {
|
||||
execAsync(`ydotool key ${key.keycode}:1`);
|
||||
execAsync(`ydotool key ${key.keycode}:0`);
|
||||
NormalClick.set(true);
|
||||
|
||||
IsActive.set(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Long Press
|
||||
widget.hook(gesture, 'pressed', () => {
|
||||
onClick(() => {
|
||||
IsLongPressing.set(true);
|
||||
});
|
||||
});
|
||||
|
||||
let spamClick: AstalIO.Time | undefined;
|
||||
|
||||
IsLongPressing.subscribe((v) => {
|
||||
if (v) {
|
||||
spamClick = interval(100, () => {
|
||||
execAsync(`ydotool key ${key.keycode}:1`);
|
||||
execAsync(`ydotool key ${key.keycode}:0`);
|
||||
});
|
||||
}
|
||||
else {
|
||||
spamClick?.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import { execAsync, idle } from 'astal';
|
||||
import { execAsync } from 'astal';
|
||||
import { Astal } from 'astal/gtk3';
|
||||
|
||||
import Tablet from '../../services/tablet';
|
||||
|
||||
import OskWindow from './osk-window';
|
||||
import Gesture from './gesture';
|
||||
import Keyboard from './keyboard';
|
||||
|
||||
|
||||
export default () => {
|
||||
// Start ydotool daemon
|
||||
execAsync('ydotoold').catch(print);
|
||||
|
||||
const tablet = Tablet.get_default();
|
||||
|
||||
const window = (
|
||||
return Gesture((
|
||||
<OskWindow
|
||||
name="osk"
|
||||
namespace="noanim-osk"
|
||||
|
@ -29,15 +24,5 @@ export default () => {
|
|||
>
|
||||
<Keyboard />
|
||||
</OskWindow>
|
||||
) as OskWindow;
|
||||
|
||||
window.hook(tablet, 'notify::osk-state', (self, state) => {
|
||||
self.setVisible(state);
|
||||
});
|
||||
|
||||
idle(() => {
|
||||
window.setVisible(false);
|
||||
});
|
||||
|
||||
return Gesture(window);
|
||||
) as OskWindow);
|
||||
};
|
||||
|
|
|
@ -6,7 +6,6 @@ import { register } from 'astal/gobject';
|
|||
export default class OskWindow extends Widget.Window {
|
||||
public startY: number | null = null;
|
||||
|
||||
declare public setVisible: (state: boolean) => void;
|
||||
declare public killGestureSigs: () => void;
|
||||
declare public setSlideUp: () => void;
|
||||
declare public setSlideDown: () => void;
|
||||
|
|
Loading…
Reference in a new issue