feat(ags osk): add cairo arc for fun
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
7775cb71b6
commit
88d0a52a4e
4 changed files with 219 additions and 95 deletions
|
@ -132,6 +132,7 @@ export default tseslint.config({
|
||||||
'no-loop-func': [
|
'no-loop-func': [
|
||||||
'error',
|
'error',
|
||||||
],
|
],
|
||||||
|
/*
|
||||||
'no-magic-numbers': [
|
'no-magic-numbers': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
|
@ -159,6 +160,7 @@ export default tseslint.config({
|
||||||
ignoreClassFieldInitialValues: true,
|
ignoreClassFieldInitialValues: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
*/
|
||||||
'no-multi-assign': [
|
'no-multi-assign': [
|
||||||
'error',
|
'error',
|
||||||
],
|
],
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
.osk {
|
.osk {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
border-radius: 10px 10px 0;
|
|
||||||
|
|
||||||
&.hidden {
|
&.hidden {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -83,6 +82,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right-side {
|
&.right-side {
|
||||||
|
border-radius: 0 10px 0 0;
|
||||||
|
|
||||||
.key .mod {
|
.key .mod {
|
||||||
&.Ctrl {
|
&.Ctrl {
|
||||||
min-width: 2.4rem;
|
min-width: 2.4rem;
|
||||||
|
@ -91,6 +92,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left-side {
|
&.left-side {
|
||||||
|
border-radius: 10px 0 0 0;
|
||||||
|
|
||||||
.key .mod {
|
.key .mod {
|
||||||
&.Alt {
|
&.Alt {
|
||||||
min-width: 3rem;
|
min-width: 3rem;
|
||||||
|
|
74
nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx
Normal file
74
nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import { Gtk } from 'astal/gtk3';
|
||||||
|
import Cairo from 'cairo';
|
||||||
|
|
||||||
|
/* Types */
|
||||||
|
interface Point {
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
}
|
||||||
|
type Bezier = [number, number, number, number];
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
css = 'background-color: black;',
|
||||||
|
allocation = { width: 0, height: 0 },
|
||||||
|
}) => (
|
||||||
|
<box>
|
||||||
|
<drawingarea
|
||||||
|
css={css}
|
||||||
|
|
||||||
|
setup={(widget) => {
|
||||||
|
widget.set_size_request(allocation.width, allocation.height);
|
||||||
|
|
||||||
|
const styleContext = widget.get_style_context();
|
||||||
|
const bgColor = styleContext.get_background_color(Gtk.StateFlags.NORMAL);
|
||||||
|
|
||||||
|
widget.connect('draw', (_, cairoContext: Cairo.Context) => {
|
||||||
|
const drawBezier = (dest: Point, curve: Bezier) => {
|
||||||
|
curve[0] *= (dest.x - cairoContext.getCurrentPoint()[0]);
|
||||||
|
curve[0] += cairoContext.getCurrentPoint()[0];
|
||||||
|
|
||||||
|
curve[1] *= (dest.y - cairoContext.getCurrentPoint()[1]);
|
||||||
|
curve[1] += cairoContext.getCurrentPoint()[1];
|
||||||
|
|
||||||
|
curve[2] *= (dest.x - cairoContext.getCurrentPoint()[0]);
|
||||||
|
curve[2] += cairoContext.getCurrentPoint()[0];
|
||||||
|
|
||||||
|
curve[3] *= (dest.y - cairoContext.getCurrentPoint()[1]);
|
||||||
|
curve[3] += cairoContext.getCurrentPoint()[1];
|
||||||
|
|
||||||
|
cairoContext.curveTo(...curve, dest.x, dest.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
// bottom left to top left
|
||||||
|
cairoContext.moveTo(0, allocation.height);
|
||||||
|
cairoContext.lineTo(0, 0);
|
||||||
|
|
||||||
|
// top left to middle left
|
||||||
|
drawBezier(
|
||||||
|
{ x: allocation.width / 3, y: allocation.height * 0.8 },
|
||||||
|
[0.76, 0, 0.24, 1],
|
||||||
|
);
|
||||||
|
|
||||||
|
// middle left to middle right
|
||||||
|
cairoContext.lineTo((allocation.width / 3) * 2, allocation.height * 0.8);
|
||||||
|
|
||||||
|
// middle right to top right
|
||||||
|
drawBezier(
|
||||||
|
{ x: allocation.width, y: 0 },
|
||||||
|
[0.76, 0, 0.24, 1],
|
||||||
|
);
|
||||||
|
|
||||||
|
// top right to bottom right
|
||||||
|
cairoContext.lineTo(allocation.width, allocation.height);
|
||||||
|
|
||||||
|
// bottom right to bottom left
|
||||||
|
cairoContext.closePath();
|
||||||
|
|
||||||
|
// Add color
|
||||||
|
cairoContext.setSourceRGBA(bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha);
|
||||||
|
cairoContext.fill();
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</box>
|
||||||
|
);
|
|
@ -1,8 +1,10 @@
|
||||||
|
import { bind, idle, Variable } from 'astal';
|
||||||
import { Astal, astalify, Gtk, type ConstructProps, Widget } from 'astal/gtk3';
|
import { Astal, astalify, Gtk, type ConstructProps, Widget } from 'astal/gtk3';
|
||||||
import { register } from 'astal/gobject';
|
import { register } from 'astal/gobject';
|
||||||
|
|
||||||
import Separator from '../misc/separator';
|
import Separator from '../misc/separator';
|
||||||
|
|
||||||
|
import Arc from './arcs';
|
||||||
import Key from './keys';
|
import Key from './keys';
|
||||||
|
|
||||||
import { defaultOskLayout, oskLayouts } from './keyboard-layouts';
|
import { defaultOskLayout, oskLayouts } from './keyboard-layouts';
|
||||||
|
@ -22,110 +24,153 @@ class ToggleButton extends astalify(Gtk.ToggleButton) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const L_KEY_PER_ROW = [8, 7, 6, 6, 6, 4]; // eslint-disable-line
|
const L_KEY_PER_ROW = [8, 7, 6, 6, 6, 4];
|
||||||
const COLOR = 'rgba(0, 0, 0, 0.3)';
|
|
||||||
const SPACING = 4;
|
const SPACING = 4;
|
||||||
|
const COLOR = 'rgba(0, 0, 0, 0.3)';
|
||||||
|
|
||||||
export default () => (
|
export default () => {
|
||||||
<box vertical>
|
const ThirdWidth = Variable(0);
|
||||||
<centerbox
|
|
||||||
css={`background: ${COLOR};`}
|
return (
|
||||||
className="osk hidden"
|
<box
|
||||||
hexpand
|
vertical
|
||||||
|
onRealize={(self) => idle(() => {
|
||||||
|
ThirdWidth.set(self.get_allocated_width() / 3);
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<box
|
<centerbox
|
||||||
className="left-side side"
|
className="osk hidden"
|
||||||
halign={Gtk.Align.START}
|
hexpand
|
||||||
vertical
|
|
||||||
>
|
|
||||||
{...keyboardJson.keys.map((row, rowIndex) => {
|
|
||||||
const keys = [] as Widget.Box[];
|
|
||||||
|
|
||||||
row.forEach((key, keyIndex) => {
|
|
||||||
if (keyIndex < L_KEY_PER_ROW[rowIndex]) {
|
|
||||||
keys.push(Key(key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<box vertical>
|
|
||||||
<box className="row">
|
|
||||||
<Separator size={SPACING} />
|
|
||||||
|
|
||||||
{...keys}
|
|
||||||
</box>
|
|
||||||
|
|
||||||
<Separator size={SPACING} vertical />
|
|
||||||
</box>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</box>
|
|
||||||
|
|
||||||
<box
|
|
||||||
halign={Gtk.Align.CENTER}
|
|
||||||
valign={Gtk.Align.END}
|
|
||||||
>
|
>
|
||||||
|
{/* LEFT */}
|
||||||
<box
|
<box
|
||||||
halign={Gtk.Align.CENTER}
|
widthRequest={bind(ThirdWidth)}
|
||||||
className="settings"
|
css={`background: ${COLOR};`}
|
||||||
|
className="left-side side"
|
||||||
|
halign={Gtk.Align.START}
|
||||||
|
vertical
|
||||||
>
|
>
|
||||||
<ToggleButton
|
{...keyboardJson.keys.map((row, rowIndex) => {
|
||||||
className="button"
|
const keys = [] as Widget.Box[];
|
||||||
cursor="pointer"
|
|
||||||
active
|
|
||||||
valign={Gtk.Align.CENTER}
|
|
||||||
|
|
||||||
onToggled={(self) => {
|
row.forEach((key, keyIndex) => {
|
||||||
self.toggleClassName(
|
if (keyIndex < L_KEY_PER_ROW[rowIndex]) {
|
||||||
'toggled',
|
keys.push(Key(key));
|
||||||
self.get_active(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (self.get_toplevel() === self) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
(self.get_toplevel() as Widget.Window | undefined)
|
return (
|
||||||
?.set_exclusivity(
|
<box vertical>
|
||||||
self.get_active() ?
|
<box className="row">
|
||||||
Astal.Exclusivity.EXCLUSIVE :
|
<Separator size={SPACING} />
|
||||||
Astal.Exclusivity.NORMAL,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Exclusive
|
|
||||||
</ToggleButton>
|
|
||||||
</box>
|
|
||||||
</box>
|
|
||||||
|
|
||||||
<box
|
{...keys}
|
||||||
className="right-side side"
|
</box>
|
||||||
halign={Gtk.Align.END}
|
|
||||||
vertical
|
|
||||||
>
|
|
||||||
{...keyboardJson.keys.map((row, rowIndex) => {
|
|
||||||
const keys = [] as Widget.Box[];
|
|
||||||
|
|
||||||
row.forEach((key, keyIndex) => {
|
<Separator size={SPACING} vertical />
|
||||||
if (keyIndex >= L_KEY_PER_ROW[rowIndex]) {
|
|
||||||
keys.push(Key(key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<box vertical>
|
|
||||||
<box
|
|
||||||
className="row"
|
|
||||||
halign={Gtk.Align.END}
|
|
||||||
>
|
|
||||||
{...keys}
|
|
||||||
</box>
|
</box>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</box>
|
||||||
|
|
||||||
<Separator size={SPACING} vertical />
|
{/* MIDDLE */}
|
||||||
</box>
|
<box
|
||||||
);
|
widthRequest={bind(ThirdWidth)}
|
||||||
})}
|
halign={Gtk.Align.CENTER}
|
||||||
</box>
|
valign={Gtk.Align.FILL}
|
||||||
</centerbox>
|
vertical
|
||||||
</box>
|
>
|
||||||
) as Widget.Box;
|
<box
|
||||||
|
valign={Gtk.Align.START}
|
||||||
|
>
|
||||||
|
{bind(ThirdWidth).as((width) => (
|
||||||
|
<Arc
|
||||||
|
allocation={{ width, height: 160 }}
|
||||||
|
css={`background: ${COLOR};`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</box>
|
||||||
|
|
||||||
|
<box
|
||||||
|
halign={Gtk.Align.FILL}
|
||||||
|
hexpand
|
||||||
|
vexpand
|
||||||
|
css={`background: ${COLOR};`}
|
||||||
|
className="settings"
|
||||||
|
>
|
||||||
|
<centerbox
|
||||||
|
halign={Gtk.Align.FILL}
|
||||||
|
hexpand
|
||||||
|
vexpand
|
||||||
|
>
|
||||||
|
<box />
|
||||||
|
|
||||||
|
<ToggleButton
|
||||||
|
className="button"
|
||||||
|
cursor="pointer"
|
||||||
|
active
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.CENTER}
|
||||||
|
|
||||||
|
onToggled={(self) => {
|
||||||
|
self.toggleClassName(
|
||||||
|
'toggled',
|
||||||
|
self.get_active(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (self.get_toplevel() === self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(self.get_toplevel() as Widget.Window | undefined)
|
||||||
|
?.set_exclusivity(
|
||||||
|
self.get_active() ?
|
||||||
|
Astal.Exclusivity.EXCLUSIVE :
|
||||||
|
Astal.Exclusivity.NORMAL,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Exclusive
|
||||||
|
</ToggleButton>
|
||||||
|
|
||||||
|
<box />
|
||||||
|
</centerbox>
|
||||||
|
</box>
|
||||||
|
</box>
|
||||||
|
|
||||||
|
{/* RIGHT */}
|
||||||
|
<box
|
||||||
|
widthRequest={bind(ThirdWidth)}
|
||||||
|
css={`background: ${COLOR};`}
|
||||||
|
className="right-side side"
|
||||||
|
halign={Gtk.Align.END}
|
||||||
|
vertical
|
||||||
|
>
|
||||||
|
{...keyboardJson.keys.map((row, rowIndex) => {
|
||||||
|
const keys = [] as Widget.Box[];
|
||||||
|
|
||||||
|
row.forEach((key, keyIndex) => {
|
||||||
|
if (keyIndex >= L_KEY_PER_ROW[rowIndex]) {
|
||||||
|
keys.push(Key(key));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<box vertical>
|
||||||
|
<box
|
||||||
|
className="row"
|
||||||
|
halign={Gtk.Align.END}
|
||||||
|
>
|
||||||
|
{...keys}
|
||||||
|
</box>
|
||||||
|
|
||||||
|
<Separator size={SPACING} vertical />
|
||||||
|
</box>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</box>
|
||||||
|
</centerbox>
|
||||||
|
</box>
|
||||||
|
) as Widget.Box;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue