misc/bin/tablet_setup

204 lines
4.8 KiB
Raku
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env raku
#| Sets up buttons etc on drawing tablets
unit sub MAIN(
#| Don't run the commands, just print them (implies -v)
Bool :n(:$dry-run),
#| Print each command before running it
Bool :v(:$verbose) is copy,
#| Print the output of queries too (implies -v)
Bool :V(:$very-verbose),
);
$verbose ||= $dry-run || $very-verbose;
sub say-prefix(:$prefix = '### ', |c) {
say $prefix, |c
}
sub say-vv(:$prefix = '### ', |c) {
say-prefix :$prefix, |c if $very-verbose
}
sub say-v(:$prefix = '### ', |c) {
say-prefix :$prefix, |c if $verbose
}
sub quote(Str() $_) {
when '' { '""' }
when /\s/ { qq|"$_"| }
default { $_ }
}
sub say-cmd(*@cmd, Bool() :$query!) {
my $prefix = $dry-run && !$query ?? "# " !! "> ";
say-v :$prefix, @cmd».&quote.join(' ');
}
sub query(*@cmd) {
say-cmd @cmd, :query;
my @out = run(|@cmd, :out :!in).out.lines(:close);
say-vv :prefix('< '), $_ for @out;
@out
}
sub update(*@cmd) {
say-cmd @cmd, :!query;
unless $dry-run { run(|@cmd, :!out :!in :err) }
Nil
}
class Subdev { ... }
class Tablet {
has Str $.name;
my @devices = lazy query <xsetwacom --list devices>;
method Str { $.name }
method find($name) {
for @devices {
when /^ $<name>=(.* $name .*) «Pen»/ {
return self.new: name => $<name>.trim;
}
}
fail "!!! Tablet '$name' not found";
}
method subdev($type, $name) { Subdev.new: tablet => self, :$type, :$name; }
method pad() { self.subdev: 'Pad', 'pad' }
method stylus() { self.subdev: 'Pen', 'stylus' }
method eraser() { self.subdev: 'Pen', 'eraser' }
method cursor() { self.subdev: 'Pen', 'cursor' }
}
class Subdev {
has Tablet $.tablet; has Str $.type; has Str $.name;
method Str { "$.tablet $.type $.name" }
method set(*%params-args) {
for %params-args.kv -> $param, $args {
update <xsetwacom --set>, self, $param, |$args;
}
}
}
sub key($k, *%mods where *.values.all) {
my @mods = %mods.keys.map: {
when /:i alt [_ | \-]? gr/ { 'ISO_Level3_Shift' }
default { $_ }
};
"key " ~ reduce { "+$^b $^a -$^b" }, $k, |@mods
}
sub external-connected {
for query <xrandr --listmonitors> {
when /^\h* \d+ ':' \h* '+'? '*'? $<name>=(\S+)/ {
my $name = ~$<name>;
return $name unless $name ~~ /eDP/;
}
}
}
################################################################################
my $did-something = False;
my $external = external-connected;
with $external { say-prefix "using display '$_'" }
with Tablet.find: 'Intuos4' {
say-v "Setting up \"$_\"";
$did-something = True;
my $screen-dir = query(<find /sys/devices -name wacom_led>)[0];
with $screen-dir {
say-v "wacom_led directory: {quote($screen-dir)}";
} else {
fail "!!! wacom_led directory not found";
}
for .stylus, .eraser, .cursor {
.set: :Rotate<half> :Area<0 0 65024 36576>; # full 65024x40640
with $external -> $ { .set: :MapToOutput($external); }
}
for .stylus, .eraser {
.set: :Button(3, key(:ctrl, 'z'));
}
my %buttons = (
# assuming left handed
# circle
1 => {map => key('tab')},
# upper four, top to bottom
13 => {map => key('shift'), screen => 7, label => 'Sh/Rotate'},
12 => {map => key('ctrl'), screen => 6, label => 'Ctrl/Zoom'},
11 => {map => key('m'), screen => 5, label => 'Mirror'},
10 => {map => key('5'), screen => 4, label => 'Rotate 0°'},
# lower four
9 => {map => key('.'), screen => 3, label => 'Brush +'},
8 => {map => key(','), screen => 2, label => 'Brush '},
3 => {map => key('insert'), screen => 1, label => 'Layer +'},
2 => {map => key('XF86AudioPlay'), screen => 0, label => 'Pause'},
);
update <sudo i4oled-chgrp>, $screen-dir;
spurt "$screen-dir/buttons_luminance", 15;
given .pad {
.set: :AbsWheelDown(key('shift')) :AbsWheelUp(key('shift'));
for %buttons.kv -> $button, % (:$map, :$screen, :$label) {
.set: :Button($button, $map);
next without $label & $screen;
my $path = "$screen-dir/button{$screen}_rawimg";
fail "!!! no such device $path" unless $path.IO.f;
update <i4oled -l -t>, $label, '-d', $path;
}
}
}
with Tablet.find: 'H420' {
say-v "Setting up \"$_\"";
$did-something = True;
given .stylus {
.set: :Rotate<half> :Area<0 0 8320 4680> # full: 8340x4680
:PressureCurve<0 50 50 100> :Button(3, key(:ctrl, 'z'));
# FIXME do this properly
.set: :MapToOutput<960x540+480+270>;
with $external -> $ { .set: :MapToOutput($external); }
}
my %buttons = (
# top to bottom assuming left handed
3 => key(:ctrl, 'z'),
2 => key(:ctrl:shift, 'z'),
1 => key('tab'),
);
for %buttons.kv -> $b, $map {
.pad.set: :Button($b, $map);
}
}
say "Didn't find any tablets" unless $did-something;
# vim: set ft=raku :