Keybow : Virtual Desktop Controller
The Pimoroni Keybow Kit is a DIY mini mechanical keyboard powered by a Raspberry Pi Zero WH with twelve illuminated RGB keys. The behaviour of the keys is setup in a Lua script. It come with severals examples, but you are free to experiment and setup something that match your needs.
The first application I had in mind was to use this beautiful keyboard to control my Virtual Desktops on macOS (Mission Control), and on my other Un*x system : GNUX Linux and OpenBSD (I use ratpoison window manager).
The main idea was to use :
- 8 keys (the 2 first line in green) for direct access to my 8 Virtual Desktops.
- The bottom left key (blue) for Dashboard access on macOS, and WTF on GNU Linux distributions / OpenBSD.
- The bottom right key (violet) for ScreenLock
- The 2 bottom middle keys (yellow) to switch between previous / next Virtual Desktop.
I wanted to keep a visual information of which Desktop is active : so the active Desktop and Dashboard key stay in red when active. While Previous / Next Desktop keys and ScreenLock key are red only when pressed.
The Lua script take place on your microSD card on folder 'layouts' where you can find other examples of keyboard layouts Lua script.
Here is my first (and ugly) Lua script :
require "keybow"
function setup() -- Set custom lights up
keybow.auto_lights(false)
keybow.clear_lights()
keybow.set_pixel(11, 0, 255, 0) -- Green
keybow.set_pixel(08, 0, 255, 0) -- Green
keybow.set_pixel(05, 0, 255, 0) -- Green
keybow.set_pixel(02, 0, 255, 0) -- Green
keybow.set_pixel(10, 0, 255, 0) -- Green
keybow.set_pixel(07, 0, 255, 0) -- Green
keybow.set_pixel(04, 0, 255, 0) -- Green
keybow.set_pixel(01, 0, 255, 0) -- Green
keybow.set_pixel(09, 0, 0, 255) -- Blue
keybow.set_pixel(06, 255, 255, 0) -- Yellow
keybow.set_pixel(03, 255, 255, 0) -- Yellow
keybow.set_pixel(00, 255, 0, 255) -- Purple
end
if desktop_number == nil then
desktop_number = 1
end
-- Standard number pad mapping --
-- Physical Horizontal :
-- USB
-- ||
-- [11][08][05][02]
-- [10][07][04][01]
-- [09][06][03][00]
--
-- Key mappings --
function desktop_light( number )
prev_desktop_number = desktop_number
desktop_number = number
if desktop_number == 1 then
keybow.set_pixel(11, 255, 0, 0)
else
keybow.set_pixel(11, 0, 255, 0)
end
if desktop_number == 2 then
keybow.set_pixel(08, 255, 0, 0)
else
keybow.set_pixel(08, 0, 255, 0)
end
if desktop_number == 3 then
keybow.set_pixel(05, 255, 0, 0)
else
keybow.set_pixel(05, 0, 255, 0)
end
if desktop_number == 4 then
keybow.set_pixel(02, 255, 0, 0)
else
keybow.set_pixel(02, 0, 255, 0)
end
if desktop_number == 5 then
keybow.set_pixel(10, 255, 0, 0)
else
keybow.set_pixel(10, 0, 255, 0)
end
if desktop_number == 6 then
keybow.set_pixel(07, 255, 0, 0)
else
keybow.set_pixel(07, 0, 255, 0)
end
if desktop_number == 7 then
keybow.set_pixel(04, 255, 0, 0)
else
keybow.set_pixel(04, 0, 255, 0)
end
if desktop_number == 8 then
keybow.set_pixel(01, 255, 0, 0)
else
keybow.set_pixel(01, 0, 255, 0)
end
if desktop_number == 0 then
keybow.set_pixel(09, 255, 0, 0)
else
keybow.set_pixel(09, 0, 0, 255)
end
end
-- First Line :
function handle_key_11(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F1, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 1
end
desktop_light(desktop_number)
end
function handle_key_08(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F2, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 2
end
desktop_light(desktop_number)
end
function handle_key_05(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F3, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 3
end
desktop_light(desktop_number)
end
function handle_key_02(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F4, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 4
end
desktop_light(desktop_number)
end
-- Second Line :
function handle_key_10(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F5, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 5
end
desktop_light(desktop_number)
end
function handle_key_07(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F6, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 6
end
desktop_light(desktop_number)
end
function handle_key_04(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F7, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 7
end
desktop_light(desktop_number)
end
function handle_key_01(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F8, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 8
end
desktop_light(desktop_number)
end
-- Third Line :
function handle_key_09(pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.set_key(keybow.F10, pressed)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
if pressed then
desktop_number = 0
end
desktop_light(desktop_number)
end
function handle_key_06(pressed)
if pressed then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key(keybow.LEFT_ARROW)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
keybow.set_pixel(06, 255, 0, 0)
desktop_number = desktop_number - 1
if desktop_number < 0 then
desktop_number = 0
end
desktop_light(desktop_number)
else
keybow.set_pixel(06, 255, 255, 0)
end
end
function handle_key_03(pressed)
if pressed then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key(keybow.RIGHT_ARROW)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
keybow.set_pixel(03, 255, 0, 0)
desktop_number = desktop_number + 1
if desktop_number > 8 then
desktop_number = 8
end
desktop_light(desktop_number)
else
keybow.set_pixel(03, 255, 255, 0)
end
end
function handle_key_00(pressed)
-- lock screen
if pressed then
keybow.set_modifier(keybow.LEFT_META, keybow.KEY_DOWN)
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_DOWN)
keybow.tap_key("q")
keybow.set_modifier(keybow.LEFT_META, keybow.KEY_UP)
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_UP)
keybow.set_pixel(00, 255, 0, 0)
else
keybow.set_pixel(00, 255, 0, 255)
end
end
For information, my Shortcuts settings in macOS :
It do the job, but have some limitations : They Keybow keyboard send information to your computer, but receive any. So if you change Virtual Desktop from another way (main keyboard or gesture for example), it will not have knowledge of the changes, so can't change the color for active desktop key.
I hope this example will give you some ideas about how to use this nice little keyboard kit :)