#!/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), #| Don't turn on the screens Bool :S(:$no-screens), #| 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»."e.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 ; method Str { $.name } method find($name) { for @devices { when /^ $=(.* $name .*) «Pen»/ { return self.new: 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 , 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 { when /^\h* \d+ ':' \h* '+'? '*'? $=(\S+)/ { my $name = ~$; return $name unless $name ~~ /eDP/; } } } ################################################################################ my $did-something = False; my $external = external-connected; with $external { say-v "using display '$_'" } with Tablet.find: 'Intuos4' { say-v "Setting up \"$_\""; $did-something = True; my $screen-dir = query()[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 :Area<0 0 65024 36576>; # full 65024x40640 if defined $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 => "🠙 \xF0E2"}, # rotate 12 => {map => key('ctrl'), screen => 6, label => "⌃ \xF002"}, # magnifying glass 11 => {map => key('m'), screen => 5, label => '⌽'}, 10 => {map => key('5'), screen => 4, label => '⦜'}, # lower four 9 => {map => key('.'), screen => 3, label => '●'}, 8 => {map => key(','), screen => 2, label => '⋅'}, 3 => {map => key('insert'), screen => 1, label => '⏥'}, 2 => {map => key(:ctrl, <'>), screen => 0, label => '𝞪'}, ); update , $screen-dir; spurt "$screen-dir/buttons_luminance", ($no-screens ?? 0 !! 8); given .pad { .set: :AbsWheelDown(key('shift')) :AbsWheelUp(key('shift')); for %buttons.kv -> $button, % (:$map, :$screen, :$label) { .set: :Button($button, $map); next if $no-screens or not defined $label & $screen; my $path = "$screen-dir/button{$screen}_rawimg"; fail "!!! no such device $path" unless $path.IO.f; update , $label, '-d', $path; } } } with Tablet.find: 'H420' { say-v "Setting up \"$_\""; $did-something = True; given .stylus { .set: :Rotate :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>; if defined $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 :