From 88d0a52a4ea509523146e2453110f73f7421c024 Mon Sep 17 00:00:00 2001 From: matt1432 Date: Tue, 26 Nov 2024 19:25:02 -0500 Subject: [PATCH] feat(ags osk): add cairo arc for fun --- nixosModules/ags/config/eslint.config.ts | 2 + .../widgets/on-screen-keyboard/_index.scss | 5 +- .../widgets/on-screen-keyboard/arcs.tsx | 74 ++++++ .../widgets/on-screen-keyboard/keyboard.tsx | 233 +++++++++++------- 4 files changed, 219 insertions(+), 95 deletions(-) create mode 100644 nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx diff --git a/nixosModules/ags/config/eslint.config.ts b/nixosModules/ags/config/eslint.config.ts index 48b1f19a..c8613917 100644 --- a/nixosModules/ags/config/eslint.config.ts +++ b/nixosModules/ags/config/eslint.config.ts @@ -132,6 +132,7 @@ export default tseslint.config({ 'no-loop-func': [ 'error', ], + /* 'no-magic-numbers': [ 'error', { @@ -159,6 +160,7 @@ export default tseslint.config({ ignoreClassFieldInitialValues: true, }, ], + */ 'no-multi-assign': [ 'error', ], diff --git a/nixosModules/ags/config/widgets/on-screen-keyboard/_index.scss b/nixosModules/ags/config/widgets/on-screen-keyboard/_index.scss index 479a3948..410f746e 100644 --- a/nixosModules/ags/config/widgets/on-screen-keyboard/_index.scss +++ b/nixosModules/ags/config/widgets/on-screen-keyboard/_index.scss @@ -18,7 +18,6 @@ .osk { padding-top: 4px; - border-radius: 10px 10px 0; &.hidden { opacity: 0; @@ -83,6 +82,8 @@ } &.right-side { + border-radius: 0 10px 0 0; + .key .mod { &.Ctrl { min-width: 2.4rem; @@ -91,6 +92,8 @@ } &.left-side { + border-radius: 10px 0 0 0; + .key .mod { &.Alt { min-width: 3rem; diff --git a/nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx b/nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx new file mode 100644 index 00000000..fec1399c --- /dev/null +++ b/nixosModules/ags/config/widgets/on-screen-keyboard/arcs.tsx @@ -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 }, +}) => ( + + { + 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(); + }); + }} + /> + +); diff --git a/nixosModules/ags/config/widgets/on-screen-keyboard/keyboard.tsx b/nixosModules/ags/config/widgets/on-screen-keyboard/keyboard.tsx index 65af4021..6b946a73 100644 --- a/nixosModules/ags/config/widgets/on-screen-keyboard/keyboard.tsx +++ b/nixosModules/ags/config/widgets/on-screen-keyboard/keyboard.tsx @@ -1,8 +1,10 @@ +import { bind, idle, Variable } from 'astal'; import { Astal, astalify, Gtk, type ConstructProps, Widget } from 'astal/gtk3'; import { register } from 'astal/gobject'; import Separator from '../misc/separator'; +import Arc from './arcs'; import Key from './keys'; 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 COLOR = 'rgba(0, 0, 0, 0.3)'; +const L_KEY_PER_ROW = [8, 7, 6, 6, 6, 4]; const SPACING = 4; +const COLOR = 'rgba(0, 0, 0, 0.3)'; -export default () => ( - - { + const ThirdWidth = Variable(0); + + return ( + idle(() => { + ThirdWidth.set(self.get_allocated_width() / 3); + })} > - - {...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 ( - - - - - {...keys} - - - - - ); - })} - - - + {/* LEFT */} - { + const keys = [] as Widget.Box[]; - onToggled={(self) => { - self.toggleClassName( - 'toggled', - self.get_active(), - ); - - if (self.get_toplevel() === self) { - return; + row.forEach((key, keyIndex) => { + if (keyIndex < L_KEY_PER_ROW[rowIndex]) { + keys.push(Key(key)); } + }); - (self.get_toplevel() as Widget.Window | undefined) - ?.set_exclusivity( - self.get_active() ? - Astal.Exclusivity.EXCLUSIVE : - Astal.Exclusivity.NORMAL, - ); - }} - > - Exclusive - - - + return ( + + + - - {...keyboardJson.keys.map((row, rowIndex) => { - const keys = [] as Widget.Box[]; + {...keys} + - row.forEach((key, keyIndex) => { - if (keyIndex >= L_KEY_PER_ROW[rowIndex]) { - keys.push(Key(key)); - } - }); - - return ( - - - {...keys} + + ); + })} + - - - ); - })} - - - -) as Widget.Box; + {/* MIDDLE */} + + + {bind(ThirdWidth).as((width) => ( + + + ))} + + + + + + + { + 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 + + + + + + + + {/* RIGHT */} + + {...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 ( + + + {...keys} + + + + + ); + })} + + + + ) as Widget.Box; +};