diff --git a/Cargo.lock b/Cargo.lock index 543350b2..6d37ccb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,6 +1996,7 @@ version = "1.2.1" dependencies = [ "serde", "serde_derive", + "toml", "zvariant", ] diff --git a/Makefile b/Makefile index 57dbfede..7bd5e503 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ install: $(INSTALL_PROGRAM) "./target/release/$(BIN_ROG)" "$(DESTDIR)$(bindir)/$(BIN_ROG)" $(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).desktop" "$(DESTDIR)$(datarootdir)/applications/$(BIN_ROG).desktop" $(INSTALL_DATA) "./rog-control-center/data/$(BIN_ROG).png" "$(DESTDIR)$(datarootdir)/icons/hicolor/512x512/apps/$(BIN_ROG).png" + cd rog-aura/data/layouts && find . -type f -name "*.toml" -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/rog-gui/layouts/{}" \; $(INSTALL_PROGRAM) "./target/release/$(BIN_C)" "$(DESTDIR)$(bindir)/$(BIN_C)" $(INSTALL_PROGRAM) "./target/release/$(BIN_D)" "$(DESTDIR)$(bindir)/$(BIN_D)" @@ -68,8 +69,6 @@ install: $(INSTALL_DATA) "./data/icons/scalable/gpu-vfio.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg" $(INSTALL_DATA) "./data/icons/scalable/notification-reboot.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg" - $(INSTALL_DATA) "./data/_asusctl" "$(DESTDIR)$(zshcpl)/_asusctl" - $(INSTALL_DATA) "./data/completions/asusctl.fish" "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" cd rog-anime/data && find "./anime" -type f -exec install -Dm 755 "{}" "$(DESTDIR)$(datarootdir)/asusd/{}" \; uninstall: @@ -94,9 +93,8 @@ uninstall: rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-nvidia.svg" rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/gpu-vfio.svg" rm -r "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/status/notification-reboot.svg" - rm -f "$(DESTDIR)$(zshcpl)/_asusctl" - rm -f "$(DESTDIR)$(datarootdir)/fish/vendor_completions.d/asusctl.fish" rm -rf "$(DESTDIR)$(datarootdir)/asusd" + rm -rf "$(DESTDIR)$(datarootdir)/rog-gui" update: cargo update diff --git a/README.md b/README.md index af7d2122..71167400 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ Now includes a GUI, `rog-control-center`. ## Kernel support -**The minimum supported kernel version is 5.15** - -Fan curve control on laptops with this feature require [this patch](https://lkml.org/lkml/2021/10/23/250) which has been merged for 5.17 upstream. +**The minimum supported kernel version is 5.17** ## Goals @@ -44,6 +42,16 @@ then it may work without tweaks. Technically all other functions except the LED and AniMe parts should work regardless of your latop make. Eventually this project will probably suffer another rename once it becomes generic enough to do so. +### Unsupported (e.g, TUF laptops) + +- `sudo systemctl mask asusd && sudo systemctl stop asusd` +- `copy asusd-alt.service to /etc/systemd/system/` +- `sudo systemctl enable asusd-alt` +- `sudo systemctl start asusd-alt` +- `asusctl -s` + +`asusd-alt.service` is in the `data` dir of this repo. + ## Implemented - [X] System daemon diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 4d391fb1..efb313e3 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -10,6 +10,7 @@ use anime_cli::{AnimeActions, AnimeCommand}; use profiles_cli::{FanCurveCommand, ProfileCommand}; use rog_anime::usb::get_anime_type; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2}; + use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev}; use rog_aura::{self, AuraEffect}; use rog_dbus::RogDbusClientBlocking; diff --git a/data/_asusctl b/data/_asusctl deleted file mode 100644 index 3fc70122..00000000 --- a/data/_asusctl +++ /dev/null @@ -1,50 +0,0 @@ -function _asusctl() { - local line - - _arguments -C \ - {-h,--help}'[print help message]' \ - {-v,--version}'[print version number]' \ - {-k,--kbd-bright}':[Set keyboard brightness (off, low, med, high)]' \ - {-p,--pwr-profile}':[Set power profile (silent, normal, boost)]' \ - {-c,--chg-limit}':[Set charging limit (20-100)]' \ - ': :((led-mode\:"Set the keyboard lighting from built-in modes" profile\:"Create and configure profiles" graphics\:"Set the graphics mode"))' \ - '*::arg:->args' - case $line[1] in - led-mode) - _arguments ': :((static\:"set a single static colour" - breathe\:"pulse between one or two colours" - strobe\:"strobe through all colours" - rainbow\:"rainbow cycling in one of four directions" - star\:"rain pattern mimicking raindrops" - rain\:"rain pattern of three preset colours" - highlight\:"pressed keys are highlighted to fade" - laser\:"pressed keys generate horizontal laser" - ripple\:"pressed keys ripple outwards like a splash" - pulse\:"set a rapid pulse" - comet\:"set a vertical line zooming from left" - flash\:"set a wide vertical line zooming from left" - multi-static\:"4-zone multi-colour"))' \ - {-h,--help}'[print help message]' \ - '-c:[set the RGB value e.g, ff00ff]' \ - '-s:[set the speed (low, med, high)]' - ;; - profile) - _arguments {-h,--help}'[print help message]' \ - {-c,--create}"[create the profile if it doesn't exist]" \ - {-t,--turbo}':[enable or disable cpu turbo]' \ - {-m,--min-percentage}':[set min cpu scaling (intel)]' \ - {-M,--max-percentage}':[set max cpu scaling (intel)]' \ - {-p,--preset}':[]' \ - {-C,--curve}':[set fan curve]' - - ;; - graphics) - _arguments {-h,--help}'[print help message]' \ - {-m,--mode}':[Set graphics mode (nvidia, hybrid, compute, integrated)]' \ - {-g,--get}'[Get the current mode]' \ - {-p,--pow}'[Get the current power status]' \ - {-f,--force}'[Do not ask for confirmation]' - ;; - esac -} -compdef _asusctl asusctl diff --git a/data/completions/asusctl.fish b/data/completions/asusctl.fish deleted file mode 100644 index 4b2dac03..00000000 --- a/data/completions/asusctl.fish +++ /dev/null @@ -1,77 +0,0 @@ -# Author: AlenPaulVarghese - -set -l progname asusctl - -set -l noopt "not __fish_contains_opt -s -s h -s v -s s -s k -s f -s c help version show-supported kbd-bright fan-mode chg-limit; and not __fish_seen_subcommand_from led-mode profile graphics;" - - -set -l gmod_options '__fish_contains_opt -s m mode;' -set -l fan_options '__fish_contains_opt -s f fan-mode;' -set -l led_options '__fish_seen_subcommand_from led-mode;' -set -l profile_options '__fish_seen_subcommand_from profile;' -set -l keyboard_options '__fish_contains_opt -s k kbd-bright;' -set -l graphics_options '__fish_seen_subcommand_from graphics;' - -set -l fan_modes 'silent normal boost' -set -l brightness_modes 'off low med high' -set -l led_modes 'static breathe strobe rainbow comet' -set -l graphics_modes 'nvidia hybird compute integrated' - - -complete -c $progname -e -complete -c $progname -f - -# asusctl completion -complete -c $progname -s h -f -l help -n "$noopt" -d "print help message" -complete -c $progname -s v -f -l version -n "$noopt" -d "show program version number" -complete -c $progname -s s -f -l show-supported -n "$noopt" -d "show supported functions of this laptop" -complete -c $progname -s k -f -l kbd-bright -n "$noopt" -d "set led brightness" -complete -c $progname -s f -f -l fan-mode -n "$noopt" -d "set fan mode independent of profile" -complete -c $progname -s c -f -l chg-limit -n "$noopt" -d "set charge limit <20-100>" -complete -c $progname -f -a "led-mode" -n "$noopt" -d "Set the keyboard lighting from built-in modes" -complete -c $progname -f -a "profile" -n "$noopt" -d "Create and configure profiles" -complete -c $progname -f -a "graphics" -n "$noopt" -d "Set the graphics mode" - -# brightness completion -complete -c $progname -n "$keyboard_options" -d "available brightness modes" -a "$brightness_modes" - -# fan completion -complete -c $progname -n "$fan_options" -d "available fan modes" -a $fan_modes - -# graphics completion -set -l gopt 'not __fish_contains_opt -s h -s g -s m -s p help mode get pow;' - -complete -c $progname -n "$graphics_options and $gopt" -a "-h" -d "print help message" -complete -c $progname -n "$graphics_options and $gopt" -a "-g" -d "Get the current mode" - -complete -c $progname -s h -f -l help -n "$graphics_options and $gopt" -d "print help message" -complete -c $progname -s m -f -l mode -n "$graphics_options and $gopt" -d "Set graphics mode: " -complete -c $progname -s g -f -l get -n "$graphics_options and $gopt" -d "Get the current mode" -complete -c $progname -s p -f -l pow -n "$graphics_options and $gopt" -d "Get the current power status" - -complete -c $progname -n "$graphics_options and $gmod_options" -d "available graphics modes" -a "$graphics_modes" - -# led-mode completion -complete -c $progname -n "$led_options" -a "-h" -d "print help message" -complete -c $progname -n "$led_options" -a "-n" -d "switch to next aura mode" - -complete -c $progname -s h -f -l help -n "$led_options" -d "print help message" -complete -c $progname -s n -f -l next-mode -n "$led_options" -d "switch to nex aura mode" -complete -c $progname -s p -f -l prev-mode -n "$led_options" -d "switch to previous aura mode" -complete -c $progname -n "$led_options" -d "available led modes" -a "$led_modes" - -# profile completion -set -l popt 'not __fish_contains_opt -s h -s n -s c -s t -s m -s M -s f help next create turbo min-percentage max-percentage fan-preset;' - -complete -c $progname -n "$profile_options and $popt" -a "-h" -d "print help message" -complete -c $progname -n "$profile_options and $popt" -a "-n" -d "toggle to next profile in list" - -complete -c $progname -s h -f -l help -n "$profile_options and $popt" -d "print help message" -complete -c $progname -s n -f -l next -n "$profile_options and $popt" -d "toggle to next profile in list" -complete -c $progname -s c -f -l create -n "$profile_options and $popt" -d "create the profile if it doesn't exist" -complete -c $progname -s t -f -l turbo -n "$profile_options and $popt" -d "enable or disable cpu turbo" -complete -c $progname -s m -f -l min-percentage -n "$profile_options and $popt" -d "set min cpu scaling (intel)" -complete -c $progname -s M -f -l max-percentage -n "$profile_options and $popt" -d "set max cpu scaling (intel)" -complete -c $progname -s f -f -l fan-preset -n "$profile_options and $popt" -d "" -complete -c $progname -n "$profile_option and __fish_contains_opt fan-preset" -d "available fan modes" -a $fan_modes - diff --git a/rog-aura/Cargo.toml b/rog-aura/Cargo.toml index 43b32d33..57b43e5e 100644 --- a/rog-aura/Cargo.toml +++ b/rog-aura/Cargo.toml @@ -13,11 +13,11 @@ edition = "2018" exclude = ["data"] [features] -default = ["dbus"] +default = ["dbus", "toml"] dbus = ["zvariant"] [dependencies] serde = "^1.0" serde_derive = "^1.0" - -zvariant = { version = "^3.0", optional = true } +toml = { version = "^0.5", optional = true } +zvariant = { version = "^3.0", optional = true } \ No newline at end of file diff --git a/rog-aura/data/layouts/g513_US.toml b/rog-aura/data/layouts/g513_US.toml new file mode 100644 index 00000000..351e0338 --- /dev/null +++ b/rog-aura/data/layouts/g513_US.toml @@ -0,0 +1,153 @@ +matches = [ + 'G513', +] + +locale = "US" + +[[rows]] +row = [ + 'NormalSpacer', + 'FuncSpacer', + 'VolDown', + 'VolUp', + 'MicMute', + 'Fan', + 'Rog', +] + +[[rows]] +row = [ + 'Esc', + 'FuncSpacer', + 'F1', + 'F2', + 'F3', + 'F4', + 'FuncSpacer', + 'F5', + 'F6', + 'F7', + 'F8', + 'FuncSpacer', + 'F9', + 'F10', + 'F11', + 'F12', + 'RowEndSpacer', + 'Del', +] + +[[rows]] +row = [ + 'Tilde', + 'N1', + 'N2', + 'N3', + 'N4', + 'N5', + 'N6', + 'N7', + 'N8', + 'N9', + 'N0', + 'Hyphen', + 'Equals', + 'BkSpc', + 'RowEndSpacer', + 'Home', +] + +[[rows]] +row = [ + 'Tab', + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + 'LBracket', + 'RBracket', + 'BackSlash', + 'RowEndSpacer', + 'PgUp', +] + +[[rows]] +row = [ + 'Caps', + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + 'SemiColon', + 'Quote', + 'Return', + 'RowEndSpacer', + 'PgDn', +] + +[[rows]] +row = [ + 'LShift', + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M', + 'Comma', + 'Period', + 'FwdSlash', + 'Rshift', + 'RowEndSpacer', + 'End', +] + +[[rows]] +row = [ + 'LCtrl', + 'LFn', + 'Meta', + 'LAlt', + 'Space', + 'RAlt', + 'PrtSc', + 'RCtrl', + 'ArrowSpacer', + 'Up', + 'ArrowSpacer', + 'RowEndSpacer', + 'RFn', +] + +[[rows]] +row = [ + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'Left', + 'Down', + 'Right', + 'ArrowSpacer', +] diff --git a/rog-aura/data/layouts/g533_US.toml b/rog-aura/data/layouts/g533_US.toml new file mode 100644 index 00000000..507eb7db --- /dev/null +++ b/rog-aura/data/layouts/g533_US.toml @@ -0,0 +1,137 @@ +matches = [ + 'G533', + 'GU502', +] + +locale = "US" + +[[rows]] +row = [ + 'NormalSpacer', + 'FuncSpacer', + 'VolDown', + 'VolUp', + 'MicMute', + 'Fan', + 'Rog', +] + +[[rows]] +row = [ + 'Esc', + 'FuncSpacer', + 'F1', + 'F2', + 'F3', + 'F4', + 'FuncSpacer', + 'F5', + 'F6', + 'F7', + 'F8', + 'FuncSpacer', + 'F9', + 'F10', + 'F11', + 'F12', + 'Del', +] + +[[rows]] +row = [ + 'Tilde', + 'N1', + 'N2', + 'N3', + 'N4', + 'N5', + 'N6', + 'N7', + 'N8', + 'N9', + 'N0', + 'Hyphen', + 'Equals', + 'BkSpc3_1', + 'BkSpc3_2', + 'BkSpc3_3', + 'Home', +] + +[[rows]] +row = [ + 'Tab', + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + 'LBracket', + 'RBracket', + 'BackSlash', + 'PgUp', +] + +[[rows]] +row = [ + 'Caps', + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + 'SemiColon', + 'Quote', + 'Return3_1', + 'Return3_2', + 'Return3_3', + 'PgDn', +] + +[[rows]] +row = [ + 'LShift', + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M', + 'Comma', + 'Period', + 'FwdSlash', + 'Caps', + 'Up', + 'End', +] + +[[rows]] +row = [ + 'LCtrl', + 'LFn', + 'Meta', + 'LAlt', + 'Space5_1', + 'Space5_2', + 'Space5_3', + 'Space5_4', + 'Space5_5', + 'RAlt', + 'PrtSc', + 'RCtrl', + 'ArrowSpacer', + 'Left', + 'Down', + 'Right', +] + diff --git a/rog-aura/data/layouts/ga401_US.toml b/rog-aura/data/layouts/ga401_US.toml new file mode 100644 index 00000000..74bd3897 --- /dev/null +++ b/rog-aura/data/layouts/ga401_US.toml @@ -0,0 +1,146 @@ +matches = [ + 'GA401', + 'GA402', + 'GU603', + 'GV301', + 'GA502', + 'GA503', +] + +locale = "US" + +[[rows]] +row = [ + 'NormalSpacer', + 'FuncSpacer', + 'VolDown', + 'VolUp', + 'MicMute', + 'Rog', +] + +[[rows]] +row = [ + 'Esc', + 'FuncSpacer', + 'F1', + 'F2', + 'F3', + 'F4', + 'FuncSpacer', + 'F5', + 'F6', + 'F7', + 'F8', + 'FuncSpacer', + 'F9', + 'F10', + 'F11', + 'F12', +] + +[[rows]] +row = [ + 'Tilde', + 'N1', + 'N2', + 'N3', + 'N4', + 'N5', + 'N6', + 'N7', + 'N8', + 'N9', + 'N0', + 'Hyphen', + 'Equals', + 'BkSpc', +] + +[[rows]] +row = [ + 'Tab', + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + 'LBracket', + 'RBracket', + 'BackSlash', +] + +[[rows]] +row = [ + 'Caps', + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + 'SemiColon', + 'Quote', + 'Return', +] + +[[rows]] +row = [ + 'LShift', + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M', + 'Comma', + 'Period', + 'FwdSlash', + 'Rshift', +] + +[[rows]] +row = [ + 'LCtrl', + 'LFn', + 'Meta', + 'LAlt', + 'Space', + 'RAlt', + 'PrtSc', + 'RCtrl', + 'ArrowSpacer', + 'Up', + 'ArrowSpacer', +] + +[[rows]] +row = [ + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'Left', + 'Down', + 'Right', + 'ArrowSpacer', +] + diff --git a/rog-aura/data/layouts/gx502_US.toml b/rog-aura/data/layouts/gx502_US.toml new file mode 100644 index 00000000..26dad3ea --- /dev/null +++ b/rog-aura/data/layouts/gx502_US.toml @@ -0,0 +1,164 @@ +matches = [ + 'GX502', + 'GU502', +] + +locale = "US" + +[[rows]] +row = [ + 'NormalSpacer', + 'FuncSpacer', + 'VolDown', + 'VolUp', + 'MicMute', + 'Rog', +] + +[[rows]] +row = [ + 'Esc', + 'FuncSpacer', + 'F1', + 'F2', + 'F3', + 'F4', + 'FuncSpacer', + 'F5', + 'F6', + 'F7', + 'F8', + 'FuncSpacer', + 'F9', + 'F10', + 'F11', + 'F12', + 'RowEndSpacer', + 'Del', +] + +[[rows]] +row = [ + 'Tilde', + 'N1', + 'N2', + 'N3', + 'N4', + 'N5', + 'N6', + 'N7', + 'N8', + 'N9', + 'N0', + 'Hyphen', + 'Equals', + 'BkSpc3_1', + 'BkSpc3_2', + 'BkSpc3_3', + 'RowEndSpacer', + 'Home', +] + +[[rows]] +row = [ + 'Tab', + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + 'LBracket', + 'RBracket', + 'BackSlash', + 'RowEndSpacer', + 'PgUp', +] + +[[rows]] +row = [ + 'Caps', + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + 'SemiColon', + 'Quote', + 'Return3_1', + 'Return3_2', + 'Return3_3', + 'RowEndSpacer', + 'PgDn', +] + +[[rows]] +row = [ + 'LShift', + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M', + 'Comma', + 'Period', + 'FwdSlash', + 'Rshift3_1', + 'Rshift3_2', + 'Rshift3_3', + 'RowEndSpacer', + 'End', +] + +[[rows]] +row = [ + 'LCtrl', + 'LFn', + 'Meta', + 'LAlt', + 'Space5_1', + 'Space5_2', + 'Space5_3', + 'Space5_4', + 'Space5_5', + 'RAlt', + 'PrtSc', + 'RCtrl', + 'ArrowSpacer', + 'Up', + 'ArrowSpacer', + 'RowEndSpacer', + 'RFn', +] + +[[rows]] +row = [ + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'ArrowSpacer', + 'Left', + 'Down', + 'Right', + 'ArrowSpacer', +] + diff --git a/rog-aura/src/error.rs b/rog-aura/src/error.rs index 7cb9f6a4..b1961474 100644 --- a/rog-aura/src/error.rs +++ b/rog-aura/src/error.rs @@ -7,7 +7,8 @@ pub enum Error { ParseSpeed, ParseDirection, ParseBrightness, - ParseAnime, + Io(std::io::Error), + Toml(toml::de::Error), } impl fmt::Display for Error { @@ -18,9 +19,22 @@ impl fmt::Display for Error { Error::ParseSpeed => write!(f, "Could not parse speed"), Error::ParseDirection => write!(f, "Could not parse direction"), Error::ParseBrightness => write!(f, "Could not parse brightness"), - Error::ParseAnime => write!(f, "Could not parse anime"), + Error::Io(io) => write!(f, "IO Error: {io}"), + Error::Toml(e) => write!(f, "TOML Parse Error: {e}"), } } } impl error::Error for Error {} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Self::Io(e) + } +} + +impl From for Error { + fn from(e: toml::de::Error) -> Self { + Self::Toml(e) + } +} diff --git a/rog-aura/src/keys.rs b/rog-aura/src/keys.rs new file mode 100644 index 00000000..63c240a6 --- /dev/null +++ b/rog-aura/src/keys.rs @@ -0,0 +1,286 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)] +pub enum Key { + VolUp, + VolDown, + MicMute, + Rog, + Fan, + Esc, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + Del, + Tilde, + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + N0, + Hyphen, + Equals, + BkSpc, + BkSpc3_1, + BkSpc3_2, + BkSpc3_3, + Home, + Tab, + Q, + W, + E, + R, + T, + Y, + U, + I, + O, + P, + LBracket, + RBracket, + BackSlash, + PgUp, + Caps, + A, + S, + D, + F, + G, + H, + J, + K, + L, + SemiColon, + Quote, + Return, + Return3_1, + Return3_2, + Return3_3, + PgDn, + LShift, + LShift3_1, + LShift3_2, + LShift3_3, + Z, + X, + C, + V, + B, + N, + M, + Comma, + Period, + FwdSlash, + Rshift, + Rshift3_1, + Rshift3_2, + Rshift3_3, + End, + LCtrl, + LFn, + Meta, + LAlt, + Space, + Space5_1, + Space5_2, + Space5_3, + Space5_4, + Space5_5, + RAlt, + PrtSc, + RCtrl, + Up, + Down, + Left, + Right, + RFn, + NormalBlank, + /// To be ignored by per-key effects + NormalSpacer, + FuncBlank, + /// To be ignored by per-key effects + FuncSpacer, + ArrowBlank, + /// To be ignored by per-key effects + ArrowSpacer, + /// A gap between regular rows and the rightside buttons + RowEndSpacer, +} + +/// Types of shapes of LED on keyboards. The shape is used for visual representations +/// +/// A post fix of Spacer *must be ignored by per-key effects +#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)] +pub enum KeyShape { + Tilde, + #[default] + Normal, + NormalBlank, + NormalSpacer, + Func, + FuncBlank, + FuncSpacer, + Space, + Space5, + LShift, + /// Used in a group of 3 (LED's) + LShift3, + RShift, + /// Used in a group of 3 (LED's) + RShift3, + Return, + Return3, + Tab, + Caps, + Backspace, + /// Used in a group of 3 (LED's) + Backspace3, + Arrow, + ArrowBlank, + ArrowSpacer, + RowEndSpacer, +} + +impl KeyShape { + pub const fn ux(&self) -> f32 { + match self { + Self::Tilde => 0.8, + Self::Normal => 1.0, + Self::NormalBlank => 1.0, + Self::NormalSpacer => 1.0, + Self::Func => 1.0, + Self::FuncBlank => 1.0, + Self::FuncSpacer => 0.6, + Self::Space => 5.0, + Self::Space5 => 1.0, + Self::LShift => 2.1, + Self::LShift3 => 0.67, + Self::RShift => 2.7, + Self::RShift3 => 0.9, + Self::Return => 2.2, + Self::Return3 => 0.7333, + Self::Tab => 1.4, + Self::Caps => 1.6, + Self::Backspace => 2.0, + Self::Backspace3 => 0.666, + Self::Arrow => 0.93, + Self::ArrowBlank => 0.93, + Self::ArrowSpacer => 0.93, + Self::RowEndSpacer => 0.1, + } + } + pub const fn uy(&self) -> f32 { + match self { + Self::Func => 0.8, + Self::FuncBlank => 0.8, + Self::FuncSpacer => 0.8, + Self::Arrow => 0.6, + Self::ArrowBlank => 0.6, + Self::ArrowSpacer => 0.6, + _ => 1.0, + } + } + + /// A blank is used to space keys out in GUI's and can be used or ignored + /// depednign on the per-key effect + pub const fn is_blank(&self) -> bool { + match self { + Self::NormalBlank | Self::FuncBlank | Self::ArrowBlank => true, + _ => false, + } + } + + /// A spacer is used to space keys out in GUI's, but ignored in per-key effects + pub const fn is_spacer(&self) -> bool { + match self { + Self::FuncSpacer | Self::NormalSpacer | Self::ArrowSpacer => true, + _ => false, + } + } + + /// All keys with a postfix of some number + pub const fn is_group(&self) -> bool { + match self { + Self::LShift3 | Self::RShift3 => true, + Self::Return3 | Self::Space5 | Self::Backspace3 => true, + _ => false, + } + } +} + +impl From for KeyShape { + fn from(k: Key) -> Self { + match k { + Key::VolUp + | Key::VolDown + | Key::MicMute + | Key::Rog + | Key::Fan + | Key::Esc + | Key::F1 + | Key::F2 + | Key::F3 + | Key::F4 + | Key::F5 + | Key::F6 + | Key::F7 + | Key::F8 + | Key::F9 + | Key::F10 + | Key::F11 + | Key::F12 + | Key::Del => KeyShape::Func, + Key::Tilde => KeyShape::Tilde, + + Key::BkSpc => KeyShape::Backspace, + Key::BkSpc3_1 | Key::BkSpc3_2 | Key::BkSpc3_3 => KeyShape::Backspace3, + Key::Tab | Key::BackSlash => KeyShape::Tab, + Key::Caps => KeyShape::Caps, + + Key::Return => KeyShape::Return, + Key::Return3_1 | Key::Return3_2 | Key::Return3_3 => KeyShape::Return3, + Key::LShift => KeyShape::LShift, + + Key::Rshift => KeyShape::RShift, + Key::Rshift3_1 | Key::Rshift3_2 | Key::Rshift3_3 => KeyShape::RShift3, + + Key::Space => KeyShape::Space, + Key::Space5_1 | Key::Space5_2 | Key::Space5_3 | Key::Space5_4 | Key::Space5_5 => { + KeyShape::Space5 + } + Key::Up | Key::Down | Key::Left | Key::Right => KeyShape::Arrow, + Key::NormalBlank => KeyShape::NormalBlank, + Key::NormalSpacer => KeyShape::NormalSpacer, + + Key::FuncBlank => KeyShape::FuncBlank, + Key::FuncSpacer => KeyShape::FuncSpacer, + + Key::ArrowBlank => KeyShape::ArrowBlank, + Key::ArrowSpacer => KeyShape::ArrowSpacer, + + Key::RowEndSpacer => KeyShape::RowEndSpacer, + + _ => KeyShape::Normal, + } + } +} + +impl From<&Key> for KeyShape { + fn from(k: &Key) -> Self { + (*k).into() + } +} diff --git a/rog-aura/src/layouts/g513.rs b/rog-aura/src/layouts/g513.rs new file mode 100644 index 00000000..8873b5d7 --- /dev/null +++ b/rog-aura/src/layouts/g513.rs @@ -0,0 +1,146 @@ +use super::{KeyLayout, KeyRow}; +use crate::keys::Key; + +impl KeyLayout { + /// Similar to GX502, but not per-key enabled + pub fn g513_layout() -> Self { + Self { + matches: vec!["G513".into()], + locale: "US".to_string(), + rows: vec![ + KeyRow::new(vec![ + Key::NormalSpacer, + Key::FuncSpacer, + Key::VolDown, + Key::VolUp, + Key::MicMute, + Key::Fan, + Key::Rog, + ]), + KeyRow::new(vec![ + Key::Esc, + Key::FuncSpacer, + Key::F1, + Key::F2, + Key::F3, + Key::F4, + Key::FuncSpacer, // not sure which key to put here + Key::F5, + Key::F6, + Key::F7, + Key::F8, + Key::FuncSpacer, + Key::F9, + Key::F10, + Key::F11, + Key::F12, + Key::RowEndSpacer, + Key::Del, + ]), + KeyRow::new(vec![ + Key::Tilde, + Key::N1, + Key::N2, + Key::N3, + Key::N4, + Key::N5, + Key::N6, + Key::N7, + Key::N8, + Key::N9, + Key::N0, + Key::Hyphen, + Key::Equals, + Key::BkSpc, + Key::RowEndSpacer, + Key::Home, + ]), + KeyRow::new(vec![ + Key::Tab, + Key::Q, + Key::W, + Key::E, + Key::R, + Key::T, + Key::Y, + Key::U, + Key::I, + Key::O, + Key::P, + Key::LBracket, + Key::RBracket, + Key::BackSlash, + Key::RowEndSpacer, + Key::PgUp, + ]), + KeyRow::new(vec![ + Key::Caps, + Key::A, + Key::S, + Key::D, + Key::F, + Key::G, + Key::H, + Key::J, + Key::K, + Key::L, + Key::SemiColon, + Key::Quote, + Key::Return, + Key::RowEndSpacer, + Key::PgDn, + ]), + KeyRow::new(vec![ + Key::LShift, + Key::Z, + Key::X, + Key::C, + Key::V, + Key::B, + Key::N, + Key::M, + Key::Comma, + Key::Period, + Key::FwdSlash, + Key::Rshift, + Key::RowEndSpacer, + Key::End, + ]), + KeyRow::new(vec![ + Key::LCtrl, + Key::LFn, + Key::Meta, + Key::LAlt, + Key::Space, + Key::RAlt, + Key::PrtSc, + Key::RCtrl, + Key::ArrowSpacer, + Key::Up, + Key::ArrowSpacer, + Key::RowEndSpacer, + Key::RFn, + ]), + KeyRow::new(vec![ + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::Left, + Key::Down, + Key::Right, + Key::ArrowSpacer, + ]), + ], + } + } +} diff --git a/rog-aura/src/layouts/ga401.rs b/rog-aura/src/layouts/ga401.rs new file mode 100644 index 00000000..ae905318 --- /dev/null +++ b/rog-aura/src/layouts/ga401.rs @@ -0,0 +1,132 @@ +use super::{KeyLayout, KeyRow}; +use crate::keys::Key; + +impl KeyLayout { + pub fn ga401_layout() -> Self { + Self { + matches: vec!["GA401".into(), "GA402".into()], + locale: "US".to_string(), + rows: vec![ + KeyRow::new(vec![ + Key::NormalSpacer, + Key::FuncSpacer, + Key::VolDown, + Key::VolUp, + Key::MicMute, + Key::Rog, + ]), + KeyRow::new(vec![ + Key::Esc, + Key::FuncSpacer, + Key::F1, + Key::F2, + Key::F3, + Key::F4, + Key::FuncSpacer, // not sure which key to put here + Key::F5, + Key::F6, + Key::F7, + Key::F8, + Key::FuncSpacer, + Key::F9, + Key::F10, + Key::F11, + Key::F12, + ]), + KeyRow::new(vec![ + Key::Tilde, + Key::N1, + Key::N2, + Key::N3, + Key::N4, + Key::N5, + Key::N6, + Key::N7, + Key::N8, + Key::N9, + Key::N0, + Key::Hyphen, + Key::Equals, + Key::BkSpc, + ]), + KeyRow::new(vec![ + Key::Tab, + Key::Q, + Key::W, + Key::E, + Key::R, + Key::T, + Key::Y, + Key::U, + Key::I, + Key::O, + Key::P, + Key::LBracket, + Key::RBracket, + Key::BackSlash, + ]), + KeyRow::new(vec![ + Key::Caps, + Key::A, + Key::S, + Key::D, + Key::F, + Key::G, + Key::H, + Key::J, + Key::K, + Key::L, + Key::SemiColon, + Key::Quote, + Key::Return, + ]), + KeyRow::new(vec![ + Key::LShift, + Key::Z, + Key::X, + Key::C, + Key::V, + Key::B, + Key::N, + Key::M, + Key::Comma, + Key::Period, + Key::FwdSlash, + Key::Rshift, + ]), + KeyRow::new(vec![ + Key::LCtrl, + Key::LFn, + Key::Meta, + Key::LAlt, + Key::Space, + Key::RAlt, + Key::PrtSc, + Key::RCtrl, + Key::ArrowSpacer, + Key::Up, + Key::ArrowSpacer, + ]), + KeyRow::new(vec![ + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::Left, + Key::Down, + Key::Right, + Key::ArrowSpacer, + ]), + ], + } + } +} diff --git a/rog-aura/src/layouts/gx502.rs b/rog-aura/src/layouts/gx502.rs new file mode 100644 index 00000000..9b45e51e --- /dev/null +++ b/rog-aura/src/layouts/gx502.rs @@ -0,0 +1,154 @@ +use super::{KeyLayout, KeyRow}; +use crate::keys::Key; + +impl KeyLayout { + pub fn gx502_layout() -> Self { + Self { + matches: vec!["GX502".into(), "GU502".into()], + locale: "US".to_string(), + rows: vec![ + KeyRow::new(vec![ + Key::NormalSpacer, + Key::FuncSpacer, + Key::VolDown, + Key::VolUp, + Key::MicMute, + Key::Rog, + ]), + KeyRow::new(vec![ + Key::Esc, + Key::FuncSpacer, + Key::F1, + Key::F2, + Key::F3, + Key::F4, + Key::FuncSpacer, // not sure which key to put here + Key::F5, + Key::F6, + Key::F7, + Key::F8, + Key::FuncSpacer, + Key::F9, + Key::F10, + Key::F11, + Key::F12, + Key::RowEndSpacer, + Key::Del, + ]), + KeyRow::new(vec![ + Key::Tilde, + Key::N1, + Key::N2, + Key::N3, + Key::N4, + Key::N5, + Key::N6, + Key::N7, + Key::N8, + Key::N9, + Key::N0, + Key::Hyphen, + Key::Equals, + Key::BkSpc3_1, + Key::BkSpc3_2, + Key::BkSpc3_3, + Key::RowEndSpacer, + Key::Home, + ]), + KeyRow::new(vec![ + Key::Tab, + Key::Q, + Key::W, + Key::E, + Key::R, + Key::T, + Key::Y, + Key::U, + Key::I, + Key::O, + Key::P, + Key::LBracket, + Key::RBracket, + Key::BackSlash, + Key::RowEndSpacer, + Key::PgUp, + ]), + KeyRow::new(vec![ + Key::Caps, + Key::A, + Key::S, + Key::D, + Key::F, + Key::G, + Key::H, + Key::J, + Key::K, + Key::L, + Key::SemiColon, + Key::Quote, + Key::Return3_1, + Key::Return3_2, + Key::Return3_3, + Key::RowEndSpacer, + Key::PgDn, + ]), + KeyRow::new(vec![ + Key::LShift, + Key::Z, + Key::X, + Key::C, + Key::V, + Key::B, + Key::N, + Key::M, + Key::Comma, + Key::Period, + Key::FwdSlash, + Key::Rshift3_1, + Key::Rshift3_2, + Key::Rshift3_3, + Key::RowEndSpacer, + Key::End, + ]), + KeyRow::new(vec![ + Key::LCtrl, + Key::LFn, + Key::Meta, + Key::LAlt, + Key::Space5_1, + Key::Space5_2, + Key::Space5_3, + Key::Space5_4, + Key::Space5_5, + Key::RAlt, + Key::PrtSc, + Key::RCtrl, + Key::ArrowSpacer, + Key::Up, + Key::ArrowSpacer, + Key::RowEndSpacer, + Key::RFn, + ]), + KeyRow::new(vec![ + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::ArrowSpacer, + Key::Left, + Key::Down, + Key::Right, + Key::ArrowSpacer, + ]), + ], + } + } +} diff --git a/rog-aura/src/layouts/mod.rs b/rog-aura/src/layouts/mod.rs new file mode 100644 index 00000000..2af7432e --- /dev/null +++ b/rog-aura/src/layouts/mod.rs @@ -0,0 +1,64 @@ +/// Hardcoded layout. Was used to generate a toml default +pub mod g513; +/// Hardcoded layout. Was used to generate a toml default +pub mod ga401; +/// Hardcoded layout. Was used to generate a toml default +pub mod gx502; + +use crate::{error::Error, keys::Key}; +use serde::{Deserialize, Serialize}; +use std::{fs::OpenOptions, io::Read, path::Path, slice::Iter}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct KeyLayout { + /// A series of board names that this layout can be used for. The board names + /// stored with the layout can be globbed, e.g, GA401 will match all of the + /// GA401I and GA401Q range variants. + /// + /// `/sys/class/dmi/id/board_name` + matches: Vec, + locale: String, + rows: Vec, +} + +impl KeyLayout { + pub fn from_file(path: &Path) -> Result { + let mut file = OpenOptions::new().read(true).open(path)?; + let mut buf = String::new(); + let read_len = file.read_to_string(&mut buf)?; + if read_len == 0 { + return Err(Error::Io(std::io::ErrorKind::InvalidData.into())); + } else { + return Ok(toml::from_str::(&buf)?); + } + } + + pub fn matches(&self, board_name: &str) -> bool { + let board = board_name.to_ascii_uppercase(); + for tmp in self.matches.iter() { + if board.contains(tmp.as_str()) { + return true; + } + } + false + } + + pub fn rows(&self) -> Iter { + self.rows.iter() + } +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct KeyRow { + row: Vec, +} + +impl KeyRow { + pub fn new(row: Vec) -> Self { + Self { row } + } + + pub fn row(&self) -> Iter { + self.row.iter() + } +} diff --git a/rog-aura/src/lib.rs b/rog-aura/src/lib.rs index 63a40c01..edcffd34 100644 --- a/rog-aura/src/lib.rs +++ b/rog-aura/src/lib.rs @@ -8,13 +8,12 @@ pub use builtin_modes::*; mod per_key_rgb; pub use per_key_rgb::*; - +pub mod error; +pub mod keys; +pub mod layouts; pub mod usb; -pub mod error; - pub const LED_MSG_LEN: usize = 17; - pub static VERSION: &str = env!("CARGO_PKG_VERSION"); pub const RED: Colour = Colour(0xff, 0x00, 0x00); diff --git a/rog-aura/src/per_key_rgb.rs b/rog-aura/src/per_key_rgb.rs index 4f8f19b1..d70d6609 100644 --- a/rog-aura/src/per_key_rgb.rs +++ b/rog-aura/src/per_key_rgb.rs @@ -1,3 +1,5 @@ +use crate::keys::Key; + /// A `KeyColourArray` contains all data to change the full set of keyboard /// key colours individually. /// @@ -45,16 +47,16 @@ impl KeyColourArray { #[inline] pub fn set(&mut self, key: Key, r: u8, g: u8, b: u8) { - if let Some((rr, gg, bb)) = self.key(key) { - *rr = r; - *gg = g; - *bb = b; + if let Some(c) = self.rgb(key) { + c[0] = r; + c[1] = g; + c[2] = b; } } /// Indexes in to `KeyColourArray` at the correct row and column /// to set a series of three bytes to the chosen R,G,B values - pub fn key(&mut self, key: Key) -> Option<(&mut u8, &mut u8, &mut u8)> { + pub fn rgb(&mut self, key: Key) -> Option<&mut [u8]> { // Tuples are indexes in to array let (row, col) = match key { Key::VolDown => (0, 15), @@ -91,9 +93,9 @@ impl KeyColourArray { Key::N0 => (3, 21), Key::Hyphen => (3, 24), Key::Equals => (3, 27), - Key::BkSpc1 => (3, 30), - Key::BkSpc2 => (3, 33), - Key::BkSpc3 => (3, 36), + Key::BkSpc3_1 => (3, 30), + Key::BkSpc3_2 => (3, 33), + Key::BkSpc3_3 => (3, 36), Key::Home => (3, 39), Key::Tab => (3, 54), // @@ -125,11 +127,16 @@ impl KeyColourArray { Key::SemiColon => (5, 51), Key::Quote => (5, 54), // - Key::Ret1 => (6, 12), - Key::Ret2 => (6, 15), - Key::Ret3 => (6, 18), + Key::Return => (6, 9), + Key::Return3_1 => (6, 12), + Key::Return3_2 => (6, 15), + Key::Return3_3 => (6, 18), Key::PgDn => (6, 21), Key::LShift => (6, 36), + // TODO: Find correct locations + Key::LShift3_1 => (6, 36), + Key::LShift3_2 => (6, 36), + Key::LShift3_3 => (6, 36), Key::Z => (6, 42), Key::X => (6, 45), Key::C => (6, 48), @@ -141,19 +148,21 @@ impl KeyColourArray { Key::Comma => (7, 15), Key::Period => (7, 18), Key::FwdSlash => (7, 21), - Key::Rshift1 => (7, 27), - Key::Rshift2 => (7, 30), - Key::Rshift3 => (7, 33), + Key::Rshift => (7, 24), + Key::Rshift3_1 => (7, 27), + Key::Rshift3_2 => (7, 30), + Key::Rshift3_3 => (7, 33), Key::End => (7, 36), Key::LCtrl => (7, 51), Key::LFn => (7, 54), // Key::Meta => (8, 9), Key::LAlt => (8, 12), - Key::Space1 => (8, 15), - Key::Space2 => (8, 18), - Key::Space3 => (8, 21), - Key::Space4 => (8, 24), + Key::Space5_1 => (8, 15), + Key::Space5_2 => (8, 18), + Key::Space5_3 => (8, 21), + Key::Space5_4 => (8, 24), + Key::Space5_5 => (8, 27), Key::RAlt => (8, 30), Key::PrtSc => (8, 33), Key::RCtrl => (8, 36), @@ -164,16 +173,17 @@ impl KeyColourArray { // Key::Down => (10, 9), Key::Right => (10, 12), - Key::None => return None, + Key::NormalBlank + | Key::FuncBlank + | Key::NormalSpacer + | Key::FuncSpacer + | Key::ArrowBlank + | Key::ArrowSpacer + | Key::RowEndSpacer => return None, + Key::Fan | Key::Space | Key::BkSpc => return None, }; - // LOLOLOLOLOLOLOL! Look it's safe okay - unsafe { - Some(( - &mut *(&mut self.0[row][col] as *mut u8), - &mut *(&mut self.0[row][col + 1] as *mut u8), - &mut *(&mut self.0[row][col + 2] as *mut u8), - )) - } + + Some(&mut self.0[row][col..2]) } #[inline] @@ -182,108 +192,6 @@ impl KeyColourArray { } } -#[derive(Debug, PartialEq, Copy, Clone)] -pub enum Key { - VolUp, - VolDown, - MicMute, - Rog, - Esc, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - Del, - Tilde, - N1, - N2, - N3, - N4, - N5, - N6, - N7, - N8, - N9, - N0, - Hyphen, - Equals, - BkSpc1, - BkSpc2, - BkSpc3, - Home, - Tab, - Q, - W, - E, - R, - T, - Y, - U, - I, - O, - P, - LBracket, - RBracket, - BackSlash, - PgUp, - Caps, - A, - S, - D, - F, - G, - H, - J, - K, - L, - SemiColon, - Quote, - Ret1, - Ret2, - Ret3, - PgDn, - LShift, - Z, - X, - C, - V, - B, - N, - M, - Comma, - Period, - FwdSlash, - Rshift1, - Rshift2, - Rshift3, - End, - LCtrl, - LFn, - Meta, - LAlt, - Space1, - Space2, - Space3, - Space4, - RAlt, - PrtSc, - RCtrl, - Up, - Down, - Left, - Right, - RFn, - None, -} - pub trait KeyLayout { fn get_rows(&self) -> &Vec<[Key; 17]>; } @@ -301,37 +209,37 @@ impl Default for GX502Layout { fn default() -> Self { GX502Layout(vec![ [ - Key::None, - Key::None, + Key::NormalSpacer, + Key::FuncSpacer, Key::VolDown, Key::VolUp, Key::MicMute, Key::Rog, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, ], [ Key::Esc, - Key::None, + Key::NormalBlank, Key::F1, Key::F2, Key::F3, Key::F4, - Key::None, // not sure which key to put here + Key::NormalBlank, // not sure which key to put here Key::F5, Key::F6, Key::F7, Key::F8, - Key::F9, + Key::NormalBlank, Key::F9, Key::F10, Key::F11, @@ -352,9 +260,9 @@ impl Default for GX502Layout { Key::N0, Key::Hyphen, Key::Equals, - Key::BkSpc1, - Key::BkSpc2, - Key::BkSpc3, + Key::BkSpc3_1, + Key::BkSpc3_2, + Key::BkSpc3_3, Key::Home, ], [ @@ -390,9 +298,9 @@ impl Default for GX502Layout { Key::SemiColon, Key::Quote, Key::Quote, - Key::Ret1, - Key::Ret2, - Key::Ret3, + Key::Return3_1, + Key::Return3_2, + Key::Return3_3, Key::PgDn, ], [ @@ -409,9 +317,9 @@ impl Default for GX502Layout { Key::Period, Key::FwdSlash, Key::FwdSlash, - Key::Rshift1, - Key::Rshift2, - Key::Rshift3, + Key::Rshift3_1, + Key::Rshift3_2, + Key::Rshift3_3, Key::End, ], [ @@ -419,11 +327,11 @@ impl Default for GX502Layout { Key::LFn, Key::Meta, Key::LAlt, - Key::Space1, - Key::Space2, - Key::Space3, - Key::Space4, - Key::Space4, + Key::Space5_1, + Key::Space5_2, + Key::Space5_3, + Key::Space5_4, + Key::Space5_5, Key::RAlt, Key::PrtSc, Key::RCtrl, @@ -434,23 +342,23 @@ impl Default for GX502Layout { Key::RFn, ], [ - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, - Key::None, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, + Key::NormalBlank, Key::Left, Key::Down, Key::Right, - Key::None, + Key::NormalBlank, ], ]) } diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index a8765c5f..a75a4e06 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -1,10 +1,13 @@ +use rog_aura::layouts::KeyLayout; use rog_control_center::{ config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists, page_states::PageDataStates, RogApp, RogDbusClientBlocking, SHOW_GUI, }; use std::{ + fs::{self, OpenOptions}, io::Read, + path::PathBuf, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -13,6 +16,9 @@ use std::{ time::Duration, }; +const DATA_DIR: &str = "/usr/share/rog-gui/"; +const BOARD_NAME: &str = "/sys/class/dmi/id/board_name"; + fn main() -> Result<(), Box> { // Startup let mut config = Config::load()?; @@ -23,6 +29,31 @@ fn main() -> Result<(), Box> { config.save()?; } + // Find and load a matching layout for laptop + let mut file = OpenOptions::new() + .read(true) + .open(PathBuf::from(BOARD_NAME)) + .map_err(|e| { + println!("{BOARD_NAME}, {e}"); + e + })?; + let mut board_name = String::new(); + file.read_to_string(&mut board_name)?; + + let mut layout = KeyLayout::ga401_layout(); // default + let mut path = PathBuf::from(DATA_DIR); + path.push("layouts"); + for path in fs::read_dir(path).map_err(|e| { + println!("{DATA_DIR}, {e}"); + e + })? { + let tmp = KeyLayout::from_file(&path?.path()).unwrap(); + if tmp.matches(board_name.as_str()) { + layout = tmp; + break; + } + } + // Cheap method to alert to notifications rather than spinning a thread for each // This is quite different when done in a retained mode app let charge_notified = Arc::new(AtomicBool::new(false)); @@ -37,6 +68,7 @@ fn main() -> Result<(), Box> { let (dbus, _) = RogDbusClientBlocking::new()?; let supported = dbus.proxies().supported().supported_functions().unwrap(); PageDataStates::new( + layout, notifs_enabled.clone(), charge_notified.clone(), bios_notified.clone(), diff --git a/rog-control-center/src/page_states.rs b/rog-control-center/src/page_states.rs index 6690b3fd..7836585b 100644 --- a/rog-control-center/src/page_states.rs +++ b/rog-control-center/src/page_states.rs @@ -7,7 +7,7 @@ use std::{ }; use egui::Vec2; -use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum}; +use rog_aura::{layouts::KeyLayout, usb::AuraPowerDev, AuraEffect, AuraModeNum}; use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile}; use rog_supported::SupportedFunctions; @@ -226,6 +226,7 @@ impl AnimeState { #[derive(Debug)] pub struct PageDataStates { + pub keyboard_layout: KeyLayout, pub notifs_enabled: Arc, pub was_notified: Arc, /// Because much of the app state here is the same as `RogBiosSupportedFunctions` @@ -241,6 +242,7 @@ pub struct PageDataStates { impl PageDataStates { pub fn new( + keyboard_layout: KeyLayout, notifs_enabled: Arc, charge_notified: Arc, bios_notified: Arc, @@ -252,6 +254,7 @@ impl PageDataStates { dbus: &RogDbusClientBlocking, ) -> Result { Ok(Self { + keyboard_layout, notifs_enabled, was_notified: charge_notified, charge_limit: dbus.proxies().charge().limit()?, @@ -308,6 +311,7 @@ impl PageDataStates { impl Default for PageDataStates { fn default() -> Self { Self { + keyboard_layout: KeyLayout::ga401_layout(), notifs_enabled: Default::default(), was_notified: Default::default(), bios: BiosState { diff --git a/rog-control-center/src/pages/aura_page.rs b/rog-control-center/src/pages/aura_page.rs index 3aebce84..61b6016c 100644 --- a/rog-control-center/src/pages/aura_page.rs +++ b/rog-control-center/src/pages/aura_page.rs @@ -1,3 +1,6 @@ +use egui::{Color32, Vec2}; +use rog_aura::keys::KeyShape; + use crate::{widgets::aura_modes_group, RogApp}; impl<'a> RogApp<'a> { @@ -9,8 +12,85 @@ impl<'a> RogApp<'a> { .. } = self; + let c = states + .aura + .modes + .get(&states.aura.current_mode) + .unwrap() + .colour1; + let colour = Color32::from_rgb(c.0, c.1, c.2); + // TODO: animation of colour changes/periods/blending egui::CentralPanel::default().show(ctx, |ui| { aura_modes_group(supported, states, dbus, ui); + + ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0); + for row in states.keyboard_layout.rows() { + ui.horizontal(|ui| { + for key in row.row() { + // your boat + let shape = KeyShape::from(key); + + if shape.is_blank() || shape.is_spacer() { + blank(ui, shape); + } else if shape.is_group() { + let label = format!("{key:?}"); + key_group(ui, colour, shape.ux(), shape.uy()).on_hover_text(label); + } else { + let label = format!("{key:?}"); + key_shape(ui, colour, shape).on_hover_text(label); + } + } + }); + } }); } } + +fn key_shape(ui: &mut egui::Ui, colour: Color32, shape: KeyShape) -> egui::Response { + let desired_size = + ui.spacing().interact_size.y * egui::vec2(2.0 * shape.ux(), 2.0 * shape.uy()); + let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); + rect = rect.shrink(3.0); + if response.clicked() { + response.mark_changed(); + } + response.widget_info(|| { + egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "") + }); + + if ui.is_rect_visible(rect) { + let visuals = ui.style().interact_selectable(&response, true); + let rect = rect.expand(visuals.expansion); + ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke); + } + + response +} + +fn key_group(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Response { + let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy); + let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); + rect = rect.shrink2(Vec2::new(3.0, 3.0)); + if response.clicked() { + response.mark_changed(); + } + response.widget_info(|| { + egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "") + }); + + if ui.is_rect_visible(rect) { + let visuals = ui.style().interact_selectable(&response, true); + let rect = rect.expand(visuals.expansion); + let mut stroke = visuals.fg_stroke; + stroke.color = visuals.bg_fill; + ui.painter().rect(rect, 0.1, colour, stroke); + } + + response +} + +fn blank(ui: &mut egui::Ui, shape: KeyShape) { + let desired_size = + ui.spacing().interact_size.y * egui::vec2(2.0 * shape.ux(), 2.0 * shape.uy()); + ui.allocate_exact_size(desired_size, egui::Sense::click()); +}