Repository: pop-os/keyboard-configurator Branch: master Commit: 676cdc6bba54 Files: 316 Total size: 1.2 MB Directory structure: gitextract_79fuba_k/ ├── .cargo/ │ └── config ├── .github/ │ └── workflows/ │ ├── ci.yml │ └── version.py ├── .gitignore ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── RELEASING.md ├── backend/ │ ├── Cargo.toml │ ├── build.rs │ ├── examples/ │ │ ├── benchmark.rs │ │ └── daemon.rs │ ├── i18n.toml │ └── src/ │ ├── backend.rs │ ├── benchmark/ │ │ ├── block_dev.rs │ │ ├── mod.rs │ │ ├── usb_dev.rs │ │ └── usb_hub.rs │ ├── board.rs │ ├── color.rs │ ├── daemon/ │ │ ├── client.rs │ │ ├── daemon_thread.rs │ │ ├── dummy.rs │ │ ├── mod.rs │ │ ├── s76power.rs │ │ └── server.rs │ ├── deref_cell.rs │ ├── key.rs │ ├── keymap.rs │ ├── layer.rs │ ├── layout/ │ │ ├── meta.rs │ │ ├── mod.rs │ │ └── physical_layout.rs │ ├── lib.rs │ ├── localize.rs │ ├── matrix.rs │ ├── mode.rs │ ├── nelson.rs │ └── rect.rs ├── build.rs ├── data/ │ ├── com.system76.keyboardconfigurator.gresource.xml │ ├── system76_launch_1_default.hex │ ├── system76_launch_2_default.hex │ ├── system76_launch_heavy_1_default.hex │ └── system76_launch_lite_1_default.hex ├── debian/ │ ├── changelog │ ├── com.system76.pkexec.keyboardconfigurator.policy │ ├── compat │ ├── control │ ├── copyright │ ├── libsystem76-keyboard-configurator-dev.install │ ├── libsystem76-keyboard-configurator.install │ ├── libsystem76-keyboard-configurator.trigger │ ├── rules │ ├── source/ │ │ ├── format │ │ └── options │ ├── system76-keyboard-configurator.install │ └── test-launch-system76-keyboard-configurator.install ├── ffi/ │ ├── Cargo.toml │ ├── build.rs │ ├── src/ │ │ └── lib.rs │ ├── system76_keyboard_configurator.h │ └── system76_keyboard_configurator.pc.in ├── flake.nix ├── i18n/ │ ├── cs/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── da/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── de/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── en/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── es/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── fi/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── fr/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── hu/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── it/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── ko/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── nl/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── pl/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── pt-BR/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── ru/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ ├── sl/ │ │ ├── system76_keyboard_configurator.ftl │ │ ├── system76_keyboard_configurator_backend.ftl │ │ └── system76_keyboard_configurator_widgets.ftl │ └── tr/ │ ├── system76_keyboard_configurator.ftl │ ├── system76_keyboard_configurator_backend.ftl │ └── system76_keyboard_configurator_widgets.ftl ├── i18n.toml ├── layouts/ │ ├── README.md │ ├── keyboards/ │ │ └── system76/ │ │ ├── 14in_81/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 14in_83/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 14in_86/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 15in_102/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 15in_102_nkey/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 18H9LHA04/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── 18H9LHA05/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_1/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_2/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_3/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_alpha_1/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_alpha_2/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_heavy_1/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ ├── launch_heavy_3/ │ │ │ ├── layout.json │ │ │ ├── leds.json │ │ │ └── physical.json │ │ └── launch_lite_1/ │ │ ├── layout.json │ │ ├── leds.json │ │ └── physical.json │ ├── keymap/ │ │ ├── ec.json │ │ ├── qmk.json │ │ └── qmk_legacy.json │ ├── picker.json │ └── system76/ │ ├── addw1/ │ │ ├── default.json │ │ └── meta.json │ ├── addw2/ │ │ ├── default.json │ │ └── meta.json │ ├── addw3/ │ │ ├── default.json │ │ └── meta.json │ ├── addw4/ │ │ ├── default.json │ │ └── meta.json │ ├── bonw14/ │ │ ├── default.json │ │ └── meta.json │ ├── bonw15/ │ │ ├── default.json │ │ └── meta.json │ ├── darp10/ │ │ ├── default.json │ │ └── meta.json │ ├── darp10-b/ │ │ ├── default.json │ │ └── meta.json │ ├── darp11/ │ │ ├── default.json │ │ └── meta.json │ ├── darp11-b/ │ │ ├── default.json │ │ └── meta.json │ ├── darp5/ │ │ ├── default.json │ │ └── meta.json │ ├── darp6/ │ │ ├── default.json │ │ └── meta.json │ ├── darp7/ │ │ ├── default.json │ │ └── meta.json │ ├── darp8/ │ │ ├── default.json │ │ └── meta.json │ ├── darp9/ │ │ ├── default.json │ │ └── meta.json │ ├── galp3-c/ │ │ ├── default.json │ │ └── meta.json │ ├── galp4/ │ │ ├── default.json │ │ └── meta.json │ ├── galp5/ │ │ ├── default.json │ │ └── meta.json │ ├── galp6/ │ │ ├── default.json │ │ └── meta.json │ ├── galp7/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze15/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze16-3050/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze16-3060/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze16-3060-b/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze17-3050/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze17-3060-b/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze18/ │ │ ├── default.json │ │ └── meta.json │ ├── gaze20/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_1/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_2/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_3/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_alpha_1/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_alpha_2/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_heavy_1/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_heavy_3/ │ │ ├── default.json │ │ └── meta.json │ ├── launch_lite_1/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp10/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp11/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp12/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp13/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp13-b/ │ │ ├── default.json │ │ └── meta.json │ ├── lemp9/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp10/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp11/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp12/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp5/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp6/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp7/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp8/ │ │ ├── default.json │ │ └── meta.json │ ├── oryp9/ │ │ ├── default.json │ │ └── meta.json │ └── serw13/ │ ├── default.json │ └── meta.json ├── layouts.py ├── linux/ │ ├── build.py │ ├── com.system76.keyboardconfigurator.appdata.xml │ ├── com.system76.keyboardconfigurator.desktop │ ├── com.system76.keyboardconfiguratorlaunchtest.desktop │ └── linuxdeploy-plugin-gtk.sh ├── macos/ │ ├── Info.plist.in │ ├── README.md │ ├── appdmg.json │ ├── build.py │ ├── deploy.py │ ├── launcher.sh │ └── signing.sh ├── rust-toolchain.toml ├── src/ │ ├── about_dialog.rs │ ├── backlight.rs │ ├── configurator_app.rs │ ├── error_dialog.rs │ ├── keyboard.rs │ ├── keyboard_layer.rs │ ├── localize.rs │ ├── main.rs │ ├── main_window.rs │ ├── page.rs │ ├── picker/ │ │ ├── mod.rs │ │ ├── picker_group.rs │ │ ├── picker_group_box.rs │ │ ├── picker_json.rs │ │ └── picker_key.rs │ ├── shortcuts_window.rs │ ├── shortcuts_window.ui │ └── testing.rs ├── tools/ │ ├── Cargo.toml │ └── src/ │ └── pkgconfig.rs ├── widgets/ │ ├── Cargo.toml │ ├── examples/ │ │ └── keyboard_color.rs │ ├── i18n.toml │ └── src/ │ ├── choose_color.rs │ ├── color_circle.rs │ ├── color_wheel.rs │ ├── keyboard_backlight_widget.rs │ ├── keyboard_color.rs │ ├── lib.rs │ ├── localize.rs │ └── selected_keys.rs └── windows/ ├── README.md ├── build.bat ├── build.py ├── gpl.rtf └── keyboard-configurator.wxs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cargo/config ================================================ [target.'cfg(target_os = "macos")'] rustflags = ["-C", "link-args=-headerpad_max_install_names"] ================================================ FILE: .github/workflows/ci.yml ================================================ on: push: branches: '**' tags-ignore: '**' pull_request: release: types: [published] name: ci env: RELEASE: ${{ github.event_name == 'release' && '--release' || '' }} jobs: run-tests: runs-on: ubuntu-latest steps: - run: sudo apt-get update && sudo apt-get install libgtk-3-dev libhidapi-dev libudev-dev - uses: actions/checkout@v4 - run: rustup component add rustfmt - run: cargo test --all - run: cargo fmt -- --check linux-x86_64: runs-on: ubuntu-22.04 steps: - run: sudo apt-get update && sudo apt-get install cargo libgtk-3-dev libhidapi-dev libudev-dev patchelf - uses: actions/checkout@v4 - run: cd linux && ./build.py $RELEASE - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: keyboard-configurator-linux-x86_64-${{ github.sha }} path: linux/keyboard-configurator-x86_64.AppImage linux-x86_64-test: runs-on: ubuntu-latest needs: linux-x86_64 steps: - run: sudo apt-get install xvfb libfuse2 - uses: actions/download-artifact@v4 with: name: keyboard-configurator-linux-x86_64-${{ github.sha }} - run: chmod +x keyboard-configurator-x86_64.AppImage - run: xvfb-run ./keyboard-configurator-x86_64.AppImage --help-gtk linux-arm64: runs-on: ubuntu-22.04-arm steps: - uses: actions/checkout@v4 - run: sudo apt-get update && sudo apt-get install cargo libgtk-3-dev libhidapi-dev libudev-dev patchelf libfuse2 - run: cd linux && ./build.py --arm64 $RELEASE - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: keyboard-configurator-linux-aarch64-${{ github.sha }} path: linux/keyboard-configurator-aarch64.AppImage linux-arm64-test: runs-on: ubuntu-22.04-arm needs: linux-arm64 steps: - run: sudo apt-get install xvfb libfuse2 - uses: actions/download-artifact@v4 with: name: keyboard-configurator-linux-aarch64-${{ github.sha }} - run: chmod +x keyboard-configurator-aarch64.AppImage - run: xvfb-run ./keyboard-configurator-aarch64.AppImage --help-gtk windows-mingw32: runs-on: windows-latest steps: - uses: msys2/setup-msys2@v2 with: msystem: MINGW32 install: mingw-w64-i686-gtk3 mingw-w64-i686-rust mingw-w64-i686-toolchain mingw-w64-i686-ntldd mingw-w64-x86_64-imagemagick - uses: actions/checkout@v4 - name: Build and package shell: msys2 {0} env: SSL_COM_USERNAME: ${{ github.event_name == 'release' && secrets.SSL_COM_USERNAME || '' }} SSL_COM_PASSWORD: ${{ github.event_name == 'release' && secrets.SSL_COM_PASSWORD || '' }} SSL_COM_CREDENTIAL_ID: ${{ github.event_name == 'release' && secrets.SSL_COM_CREDENTIAL_ID || '' }} SSL_COM_TOTP_SECRET: ${{ github.event_name == 'release' && secrets.SSL_COM_TOTP_SECRET || '' }} MSYS2_ENV_CONV_EXCL: SSL_COM_TOTP_SECRET SIGN: ${{ github.event_name == 'release' && '--sign' || '' }} run: cd windows && python build.py $RELEASE $SIGN - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: keyboard-configurator-mingw32-${{ github.sha }} path: windows/keyboard-configurator.msi windows-mingw32-test: runs-on: windows-latest needs: windows-mingw32 steps: - uses: actions/download-artifact@v4 with: name: keyboard-configurator-mingw32-${{ github.sha }} - run: msiexec /i keyboard-configurator.msi /qb - run: Start-Sleep 10 - run: '& "C:\Program Files (x86)\System76\Keyboard Configurator\system76-keyboard-configurator.exe" --help-gtk' macos: runs-on: macos-14-large # Intel steps: - run: brew install gtk+3 imagemagick librsvg adwaita-icon-theme - run: npm install -g appdmg - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - uses: actions/checkout@v4 - env: AC_PASSWORD: ${{ github.event_name == 'release' && secrets.AC_PASSWORD || '' }} AC_USERNAME: ${{ github.event_name == 'release' && secrets.AC_USERNAME || '' }} MACOS_CERTIFICATE: ${{ github.event_name == 'release' && secrets.MACOS_CERTIFICATE || '' }} MACOS_SCRIPT: ${{ github.event_name == 'release' && 'bash ./signing.sh' || 'python3 ./build.py' }} run: cd macos && $MACOS_SCRIPT $RELEASE - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: keyboard-configurator-macos-${{ github.sha }} path: macos/keyboard-configurator.dmg macos-test: runs-on: macos-14-large # Intel needs: macos steps: - uses: actions/download-artifact@v4 with: name: keyboard-configurator-macos-${{ github.sha }} - run: mkdir mnt && hdiutil attach keyboard-configurator.dmg -mountpoint $PWD/mnt - run: '"./mnt/System76 Keyboard Configurator.app/Contents/MacOS/keyboard-configurator" --help-gtk' - run: 'open "mnt/System76 Keyboard Configurator.app" --args --help-gtk' macos-arm64: runs-on: macos-14 # arm64 steps: - run: brew install gtk+3 imagemagick librsvg adwaita-icon-theme - run: npm install -g appdmg - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - uses: actions/checkout@v4 - env: AC_PASSWORD: ${{ github.event_name == 'release' && secrets.AC_PASSWORD || '' }} AC_USERNAME: ${{ github.event_name == 'release' && secrets.AC_USERNAME || '' }} MACOS_CERTIFICATE: ${{ github.event_name == 'release' && secrets.MACOS_CERTIFICATE || '' }} MACOS_SCRIPT: ${{ github.event_name == 'release' && 'bash ./signing.sh' || 'python3 ./build.py' }} run: cd macos && $MACOS_SCRIPT $RELEASE - run: mv macos/keyboard-configurator.dmg macos/keyboard-configurator-arm64.dmg - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: keyboard-configurator-macos-arm64-${{ github.sha }} path: macos/keyboard-configurator-arm64.dmg macos-arm64-test: runs-on: macos-14 # arm64 needs: macos-arm64 steps: - uses: actions/download-artifact@v4 with: name: keyboard-configurator-macos-arm64-${{ github.sha }} - run: mkdir mnt && hdiutil attach keyboard-configurator-arm64.dmg -mountpoint $PWD/mnt - run: '"./mnt/System76 Keyboard Configurator.app/Contents/MacOS/keyboard-configurator" --help-gtk' - run: 'open "mnt/System76 Keyboard Configurator.app" --args --help-gtk' upload-to-release: if: github.event_name == 'release' runs-on: ubuntu-latest needs: [linux-x86_64, linux-arm64, windows-mingw32, macos, macos-arm64] steps: - uses: actions/checkout@v4 - run: echo VERSION=$(./.github/workflows/version.py) > $GITHUB_ENV - uses: actions/download-artifact@v4 - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: keyboard-configurator-linux-x86_64-${{ github.sha }}/keyboard-configurator-x86_64.AppImage asset_name: keyboard-configurator-${{ env.VERSION }}-x86_64.AppImage asset_content_type: application/vnd.appimage - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: keyboard-configurator-linux-aarch64-${{ github.sha }}/keyboard-configurator-aarch64.AppImage asset_name: keyboard-configurator-${{ env.VERSION }}-aarch64.AppImage asset_content_type: application/vnd.appimage - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: keyboard-configurator-mingw32-${{ github.sha }}/keyboard-configurator.msi asset_name: keyboard-configurator-${{ env.VERSION }}.msi asset_content_type: application/x-msi - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: keyboard-configurator-macos-${{ github.sha }}/keyboard-configurator.dmg asset_name: keyboard-configurator-${{ env.VERSION }}.dmg asset_content_type: application/x-apple-diskimage - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: keyboard-configurator-macos-arm64-${{ github.sha }}/keyboard-configurator-arm64.dmg asset_name: keyboard-configurator-arm64-${{ env.VERSION }}.dmg asset_content_type: application/x-apple-diskimage ================================================ FILE: .github/workflows/version.py ================================================ #!/usr/bin/env python3 import json import subprocess meta_str = subprocess.check_output(["cargo", "metadata", "--format-version", "1", "--no-deps"]) meta = json.loads(meta_str) package = next(i for i in meta['packages'] if i['name'] == 'system76-keyboard-configurator') print(package['version']) ================================================ FILE: .gitignore ================================================ /result /target /linux/system76-keyboard-configurator /windows/out /windows/sign /windows/libraries.wxi /windows/*.png /windows/*.bmp /macos/Info.plist /macos/background.png /macos/keyboard-configurator *.AppDir *.AppImage *.msi *.wixobj *.wixpdb *.dmg *.icns *.app .DS_Store __pycache__ vendor vendor.tar gschemas.compiled debian/.debhelper/ debian/debhelper-build-stamp debian/files debian/libsystem76-keyboard-configurator-dev.debhelper.log debian/libsystem76-keyboard-configurator-dev.substvars debian/libsystem76-keyboard-configurator-dev/ debian/libsystem76-keyboard-configurator.debhelper.log debian/libsystem76-keyboard-configurator.substvars debian/libsystem76-keyboard-configurator/ debian/system76-keyboard-configurator.debhelper.log debian/system76-keyboard-configurator.substvars debian/system76-keyboard-configurator/ debian/tmp/ ================================================ FILE: Cargo.toml ================================================ [package] name = "system76-keyboard-configurator" version = "1.3.13" authors = ["Ian Douglas Scott ", "Jeremy Soller "] license = "GPL-3.0-or-later" edition = "2021" rust-version = "1.64" [workspace] members = [ "tools", "ffi", "backend", "widgets" ] [dependencies] cascade = "1" futures = "0.3.13" gtk = { version = "0.18.0" } libc = "0.2" once_cell = "1.4" pangocairo = "0.18.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = "0.4.0" env_logger = "0.10" backend = { package = "system76-keyboard-configurator-backend", path = "backend" } widgets = { package = "system76-keyboard-configurator-widgets", path = "widgets" } # Translation support i18n-embed = { version = "0.13.0", features = ["fluent-system", "desktop-requester"] } i18n-embed-fl = "0.6.0" rust-embed = { version = "6.2.0", features = ["debug-embed"] } [build-dependencies] glib-build-tools = "0.18.0" [target.'cfg(target_os = "windows")'.dependencies] winreg = "0.8" [features] appimage = ["backend/appimage"] ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: Makefile ================================================ prefix ?= /usr/local bindir = $(prefix)/bin libdir = $(prefix)/lib includedir = $(prefix)/include datarootdir = $(prefix)/share datadir = $(datarootdir) TARGET = debug DEBUG ?= 0 ifeq ($(DEBUG),0) TARGET = release ARGS += --release endif VENDOR ?= 0 ifneq ($(VENDOR),0) ARGS += --frozen endif PACKAGE = system76_keyboard_configurator APPID = "com.system76.keyboardconfigurator" PKGCONFIG = $(PACKAGE).pc BIN = system76-keyboard-configurator FFI = lib$(PACKAGE).so APPDATA = $(APPID).appdata.xml DESKTOP = $(APPID).desktop ICON = data/icons/scalable/apps/$(APPID).svg all: $(BIN) $(PKGCONFIG) clean: rm -rf target distclean: clean rm -rf .cargo vendor vendor.tar $(BIN): Cargo.toml Cargo.lock src/main.rs vendor-check cargo build $(ARGS) $(FFI): Cargo.toml Cargo.lock ffi/src/lib.rs vendor-check cargo build $(ARGS) --manifest-path ffi/Cargo.toml install: install -Dm0755 target/$(TARGET)/$(BIN) $(DESTDIR)$(bindir)/$(BIN) install -Dm0644 target/$(TARGET)/$(FFI) "$(DESTDIR)$(libdir)/$(FFI)" install -Dm0644 target/$(PKGCONFIG) "$(DESTDIR)$(libdir)/pkgconfig/$(PKGCONFIG)" install -Dm0644 ffi/$(PACKAGE).h "$(DESTDIR)$(includedir)/$(PACKAGE).h" install -Dm0644 "linux/$(DESKTOP)" "$(DESTDIR)$(datadir)/applications/$(DESKTOP)" install -Dm0644 "linux/$(APPDATA)" "$(DESTDIR)$(datadir)/metainfo/$(APPDATA)" install -Dm0644 $(ICON) "$(DESTDIR)$(datadir)/icons/hicolor/scalable/apps/$(APPID).svg" $(PKGCONFIG): $(FFI) tools/src/pkgconfig.rs cargo run -p tools --bin pkgconfig $(DESKTOP_ARGS) -- \ $(PACKAGE) $(libdir) $(includedir) ## Cargo Vendoring vendor: rm .cargo -rf mkdir -p .cargo cargo vendor | head -n -1 > .cargo/config echo 'directory = "vendor"' >> .cargo/config tar cf vendor.tar vendor rm -rf vendor vendor-check: ifeq ($(VENDOR),1) rm vendor -rf && tar xf vendor.tar endif ================================================ FILE: README.md ================================================ # System76 Keyboard Configurator Tool for configuring System76 keyboards, internal and external, with support for changing the keymap and LED settings. This requires a System76 laptop with recent open EC firmware, or a Launch keyboard. Note that LED settings are not currently persisted on internal keyboards. ## Releases See [releases](https://github.com/pop-os/keyboard-configurator/releases) page for pre-built binaries of the latest tagged release. ## Building ``` # Install dependencies if necessary sudo apt-get install cargo libgtk-3-dev libhidapi-dev libudev-dev # Clone keyboard-configurator if necessary git clone https://github.com/pop-os/keyboard-configurator # Make sure it is up to date cd keyboard-configurator git pull # Build and run the configurator cargo run --release ``` ## Translators Translators are welcome to submit translations directly as a pull request to this project. It is generally expected that your pull requests will contain a single commit for each language that was added or improved, using a syntax like so: ``` i18n(eo): Add Esperanto language support ``` ``` i18n(pl): Improvements to Polish language support ``` Translation files can be found [here](./i18n/). We are using [Project Fluent](https://projectfluent.org) for our translations, which should be easier than working with gettext. ================================================ FILE: RELEASING.md ================================================ # Releasing * Make sure all builds and tests are passing on CI. * Update version in `Cargo.toml`. * Add new release to `debian/changelog`. * No change is needed in `windows/keyboard-configurator.wxs` or `macos/Info.plist` - `windows/build.py` and `macos/build.py` populate the version from `Cargo.toml` - `UpgradeCode` should **not** be changed between releases. * Create a release on Github - Github Actions will automatically build artifacts in release mode, and attach them to the release. * Deploy release to Pop!\_OS repos. ================================================ FILE: backend/Cargo.toml ================================================ [package] name = "system76-keyboard-configurator-backend" version = "0.1.0" authors = ["Ian Douglas Scott ", "Jeremy Soller "] license = "GPL-3.0-or-later" edition = "2021" [dependencies] async-process = "1.7.0" cascade = "1" futures = { version = "0.3.13", features = ["thread-pool"] } futures-timer = "3.0.2" glib = { version = "0.18.0", optional = true } hidapi = { version = "1.2", default-features = false, features = ["linux-shared-hidraw"] } libc = "0.2" once_cell = "1.4" ordered-float = { version = "3.0", features = ["serde"] } palette = "0.5" regex = "1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = "0.4.0" uuid = { version = "1", features = ["v4"] } i18n-embed = { version = "0.13.0", features = ["fluent-system", "desktop-requester"] } i18n-embed-fl = "0.6.0" rust-embed = { version = "6.2.0", features = ["debug-embed"] } [dependencies.system76_ectool] version = "0.3.8" features = ["hidapi", "std"] [target.'cfg(target_os = "linux")'.dependencies] zbus = "3" [build-dependencies] serde_json = "1.0" [dev-dependencies] libc = "0.2" [features] appimage = [] ================================================ FILE: backend/build.rs ================================================ use std::{ env, fs::{self, File}, io::Write, path::Path, }; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let mut outfile = File::create(Path::new(&out_dir).join("keyboards.rs")).unwrap(); writeln!(outfile, "keyboards![").unwrap(); println!("cargo:rerun-if-changed=../layouts/system76"); for i in fs::read_dir("../layouts/system76").unwrap() { let i = i.unwrap(); let path = i.path().join("meta.json"); let meta = serde_json::from_reader::<_, serde_json::Map<_, _>>(File::open(&path).unwrap()) .unwrap(); let file_name = i.file_name().into_string().unwrap(); let keyboard = meta .get("keyboard") .and_then(|x| x.as_str()) .unwrap_or_else(|| { panic!("'keyboard:' not found in {}", path.display()); }); let is_qmk = meta .get("is_qmk") .and_then(|v| v.as_bool()) .unwrap_or(false); writeln!( outfile, " (\"system76/{}\", \"{}\", {}),", file_name, keyboard, is_qmk ) .unwrap(); println!("cargo:rerun-if-changed=../layouts/system76/{}", file_name); println!("cargo:rerun-if-changed=../layouts/keyboards/{}", keyboard); } writeln!(outfile, "];").unwrap(); } ================================================ FILE: backend/examples/benchmark.rs ================================================ use std::io; use system76_keyboard_configurator_backend::Benchmark; fn benchmark() -> io::Result<()> { let benchmark = Benchmark::new()?; for (port_desc, port_result) in benchmark.port_results.iter() { eprintln!("{}: {:.2?}", port_desc, port_result); } Ok(()) } fn main() { benchmark().unwrap(); } ================================================ FILE: backend/examples/daemon.rs ================================================ use std::env; use system76_keyboard_configurator_backend::{run_daemon, Backend, Events}; #[cfg(target_os = "linux")] fn with_daemon(f: F) { let (backend, events) = if unsafe { libc::geteuid() == 0 } { eprintln!("Already running as root"); Backend::new().expect("Failed to create server") } else { Backend::new_pkexec().unwrap() }; f(backend, events); } #[cfg(not(target_os = "linux"))] fn with_daemon(f: F) { let (backend, events) = Backend::new().expect("Failed to create server"); f(backend, events); } fn main() { for arg in env::args().skip(1) { if arg.as_str() == "--daemon" { run_daemon() } } with_daemon(|_backend, _events| { // println!("boards: {:?}", daemon.boards()); }); } ================================================ FILE: backend/i18n.toml ================================================ fallback_language = "en" [fluent] assets_dir = "../i18n" ================================================ FILE: backend/src/backend.rs ================================================ use futures::{ channel::mpsc as async_mpsc, stream::{FusedStream, Stream}, }; use std::{ pin::Pin, process, sync::Arc, task::{Context, Poll}, time::Duration, }; use crate::daemon::*; use crate::{Board, BoardEvent, Bootloaded}; #[derive(Clone, Debug)] pub enum Event { BoardLoading, BoardLoadingDone, BoardNotUpdated, Board(BoardId, BoardEvent), BoardAdded(Board), BoardRemoved(BoardId), BootloadedAdded(Bootloaded), BootloadedRemoved, } #[derive(Debug)] pub struct Events(async_mpsc::UnboundedReceiver); impl Stream for Events { type Item = Event; fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let receiver = &mut self.get_mut().0; futures::pin_mut!(receiver); receiver.poll_next(cx) } } impl FusedStream for Events { fn is_terminated(&self) -> bool { self.0.is_terminated() } } impl Unpin for Events {} #[derive(Debug)] struct BackendInner { thread_client: Arc, executor: futures::executor::ThreadPool, } #[derive(Clone, Debug)] pub struct Backend(Arc); unsafe impl Send for Backend {} impl Backend { fn new_internal(daemon: T) -> Result<(Self, Events), String> { let (sender, receiver) = async_mpsc::unbounded(); let executor = futures::executor::ThreadPool::builder() .pool_size(1) .create() .unwrap(); let thread_client = ThreadClient::new(Box::new(daemon), sender); Ok(( Self(Arc::new(BackendInner { thread_client, executor, })), Events(receiver), )) } pub fn new_dummy(board_names: Vec) -> Result<(Self, Events), String> { let dummy_daemon = DaemonDummy::new(board_names)?; Self::new_internal(dummy_daemon) } #[cfg(target_os = "linux")] pub fn new_s76power() -> Result<(Self, Events), String> { Self::new_internal(DaemonS76Power::new()?) } pub fn new_pkexec() -> Result<(Self, Events), String> { Self::new_internal(DaemonClient::new_pkexec()) } pub fn new() -> Result<(Self, Events), String> { Self::new_internal(DaemonServer::new_stdio()?) } /// Test for added/removed boards, emitting `board-added`/`board-removed` signals /// /// This function does not block, and loads new boards in the background. pub fn refresh(&self) { let self_ = self.clone(); self.0.executor.spawn_ok(async move { if let Err(err) = self_.0.thread_client.refresh().await { error!("Failed to refresh boards: {}", err); } }); } pub fn check_for_bootloader(&self) { let self_ = self.clone(); self.0.executor.spawn_ok(async move { if let Err(err) = self_.0.thread_client.check_for_bootloader().await { error!("Failed to check for board in bootloader mode: {}", err); } }); } pub fn set_matrix_get_rate(&self, rate: Option) { let self_ = self.clone(); self.0.executor.spawn_ok(async move { let _ = self_.0.thread_client.set_matrix_get_rate(rate).await; }); } } impl Drop for BackendInner { fn drop(&mut self) { self.thread_client.close(); } } pub fn run_daemon() -> ! { let server = DaemonServer::new_stdio().expect("Failed to create server"); server.run().expect("Failed to run server"); process::exit(0) } ================================================ FILE: backend/src/benchmark/block_dev.rs ================================================ #[cfg(target_os = "linux")] use std::os::unix::fs::OpenOptionsExt; use std::{ alloc::{alloc, dealloc, handle_alloc_error, Layout}, fs, io::{self, Read}, path::{Path, PathBuf}, slice, time, }; const ALIGN: usize = 4096; const SIZE: usize = ALIGN * 1024; #[derive(Eq, Ord, PartialEq, PartialOrd)] pub struct BlockDev(PathBuf); impl BlockDev { pub fn new(path: PathBuf) -> Self { Self(path) } pub fn path(&self) -> &Path { &self.0 } pub fn benchmark(&self) -> io::Result { let mut open_options = fs::OpenOptions::new(); open_options.read(true); #[cfg(target_os = "linux")] open_options.custom_flags(libc::O_DIRECT); let mut file = open_options.open(self.path())?; // Buffer needs to be aligned for direct reads let layout = Layout::from_size_align(SIZE, ALIGN).unwrap(); let ptr = unsafe { alloc(layout) }; if ptr.is_null() { handle_alloc_error(layout); } let (res, elapsed) = { let data = unsafe { slice::from_raw_parts_mut(ptr as *mut u8, SIZE) }; let start = time::Instant::now(); (file.read(data), start.elapsed()) }; unsafe { dealloc(ptr, layout); } // Do this after free to ensure no memory leaks res?; Ok(4.0 / elapsed.as_secs_f64()) } } ================================================ FILE: backend/src/benchmark/mod.rs ================================================ use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, io}; use self::usb_hub::UsbHub; mod block_dev; mod usb_dev; mod usb_hub; #[derive(Debug, Deserialize, Serialize)] pub struct Benchmark { pub port_results: BTreeMap>, } impl Benchmark { pub fn new() -> io::Result { let hubs = UsbHub::probe()?; let mut port_descs = BTreeMap::new(); port_descs.insert("1", "USB-C Right"); port_descs.insert("2", "USB-A Right"); port_descs.insert("3", "USB-A Left"); port_descs.insert("4", "USB-C Left"); let mut usb_2_hubs = 0; let mut usb_3_hubs = 0; for hub in hubs.iter() { match hub { UsbHub::Usb2(_) => usb_2_hubs += 1, UsbHub::Usb3(_) => usb_3_hubs += 1, } } if usb_2_hubs != 1 { return Err(io::Error::new( io::ErrorKind::Other, format!("Found {} USB 2 hubs instead of 1", usb_2_hubs), )); } if usb_3_hubs != 1 { return Err(io::Error::new( io::ErrorKind::Other, format!("Found {} USB 3 hubs instead of 1", usb_3_hubs), )); } let mut port_results = BTreeMap::new(); for hub in hubs.iter() { let (required_speed, speed_name) = match hub { UsbHub::Usb2(_) => ( 1.5, // USB 1.1 max speed is 12 Mbps or 1.5 MBps "USB 2.0", ), UsbHub::Usb3(_) => ( 60.0, // USB 2.0 max speed is 480 Mbps or 60 MBps "USB 3.2 Gen 2", ), }; for (port_name, dev) in hub.ports()?.iter() { let port_desc = match port_descs.get(port_name.as_str()) { Some(some) => some, // Ports 5 and 6 connect to the Launch microcontroller (port 5) // and an integrated hub device (port 6) None => continue, }; let port_result = if dev.path().is_dir() { let mut best_speed = -1.0; for block_dev in dev.block_devs()? { match block_dev.benchmark() { Ok(benchmark) => { if benchmark > best_speed { best_speed = benchmark; } } Err(_err) => { //TODO: do something with error } } } if best_speed < 0.0 { Err("no accessible disks".to_string()) } else if best_speed > required_speed { Ok(best_speed) } else { Err(format!("benchmarked speed of {:.2} MB/s was less than required speed of {:.2} MB/s", best_speed, required_speed)) } } else { Err("no devices".to_string()) }; port_results.insert(format!("{}: {}", speed_name, port_desc), port_result); } } Ok(Self { port_results }) } } ================================================ FILE: backend/src/benchmark/usb_dev.rs ================================================ use std::{ fs, io, path::{Path, PathBuf}, }; use super::block_dev::BlockDev; pub struct UsbDev(PathBuf); impl UsbDev { pub fn new(path: PathBuf) -> Self { Self(path) } pub fn path(&self) -> &Path { &self.0 } pub fn vendor_id(&self) -> io::Result { let vid_path = self.path().join("idVendor"); let vid_str = fs::read_to_string(vid_path)?; u16::from_str_radix(vid_str.trim(), 16) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) } pub fn product_id(&self) -> io::Result { let pid_path = self.path().join("idProduct"); let pid_str = fs::read_to_string(pid_path)?; u16::from_str_radix(pid_str.trim(), 16) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) } pub fn block_devs(&self) -> io::Result> { let mut ifaces = Vec::new(); //TODO: support multiple ifaces let iface_suffix = ":1.0"; for entry_res in fs::read_dir(self.path())? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { if entry_name.ends_with(&iface_suffix) { ifaces.push((entry_name, entry.path())); } } } let mut hosts = Vec::new(); for (_iface_name, iface_path) in ifaces.iter() { let host_prefix = "host"; for entry_res in fs::read_dir(iface_path)? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { if entry_name.starts_with(host_prefix) { hosts.push((entry_name, entry.path())); } } } } let mut targets = Vec::new(); for (host_name, host_path) in hosts.iter() { let host_id = host_name.trim_start_matches("host"); let target_prefix = format!("target{}:", host_id); for entry_res in fs::read_dir(host_path)? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { if entry_name.starts_with(&target_prefix) { targets.push((entry_name, entry.path())); } } } } let mut disks = Vec::new(); for (target_name, target_path) in targets.iter() { let target_id = target_name.trim_start_matches("target"); let disk_prefix = format!("{}:", target_id); for entry_res in fs::read_dir(target_path)? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { if entry_name.starts_with(&disk_prefix) { disks.push((entry_name, entry.path())); } } } } let mut blocks = Vec::new(); for (_disk_name, disk_path) in disks.iter() { let disk_block_path = disk_path.join("block"); for entry_res in fs::read_dir(&disk_block_path)? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { blocks.push((entry_name, entry.path())); } } } let mut block_devs = Vec::new(); for (block_name, _block_path) in blocks.iter() { block_devs.push(BlockDev::new(Path::new("/dev").join(block_name))); } block_devs.sort(); Ok(block_devs) } } ================================================ FILE: backend/src/benchmark/usb_hub.rs ================================================ use std::{collections::BTreeMap, fs, io, path::Path}; use super::usb_dev::UsbDev; const SYSTEM76_VID: u16 = 0x3384; const USB_2_HUB_PID: u16 = 0x0003; const USB_3_HUB_PID: u16 = 0x0004; //TODO: Determine why USB7216 doesn't respect PID updates const USB_2_HUB_PID_ALT: u16 = 0x4216; const USB_3_HUB_PID_ALT: u16 = 0x7216; pub enum UsbHub { Usb2(UsbDev), Usb3(UsbDev), } impl UsbHub { pub fn probe() -> io::Result> { let mut hubs = Vec::new(); for entry_res in fs::read_dir("/sys/bus/usb/devices")? { let entry = entry_res?; let entry_path = entry.path(); let vid_path = entry_path.join("idVendor"); let pid_path = entry_path.join("idProduct"); if vid_path.is_file() && pid_path.is_file() { let usb = UsbDev::new(entry_path); match (usb.vendor_id()?, usb.product_id()?) { (SYSTEM76_VID, USB_2_HUB_PID_ALT) | (SYSTEM76_VID, USB_2_HUB_PID) => { hubs.push(UsbHub::Usb2(usb)) } (SYSTEM76_VID, USB_3_HUB_PID_ALT) | (SYSTEM76_VID, USB_3_HUB_PID) => { hubs.push(UsbHub::Usb3(usb)) } _ => (), } } } Ok(hubs) } pub fn usb_dev(&self) -> &UsbDev { match self { UsbHub::Usb2(usb) => usb, UsbHub::Usb3(usb) => usb, } } pub fn path(&self) -> &Path { self.usb_dev().path() } pub fn ports(&self) -> io::Result> { let mut hub_ports = BTreeMap::new(); let hub_path = self.path(); let hub_name = hub_path .file_name() .and_then(|x| x.to_str()) .ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidData, "hub_ports file_name not found or not UTF-8", ) })?; let if_path = hub_path.join(format!("{}:1.0", hub_name)); let port_prefix = format!("{}-port", hub_name); for entry_res in fs::read_dir(&if_path)? { let entry = entry_res?; if let Ok(entry_name) = entry.file_name().into_string() { if entry_name.starts_with(&port_prefix) { let port_name = entry_name.trim_start_matches(&port_prefix); let dev_path = entry.path().join("device"); hub_ports.insert(port_name.to_owned(), UsbDev::new(dev_path)); } } } Ok(hub_ports) } } ================================================ FILE: backend/src/board.rs ================================================ use futures::channel::mpsc as async_mpsc; use once_cell::sync::{Lazy, OnceCell}; use regex::Regex; use serde::{Deserialize, Serialize}; use std::{ collections::BTreeMap, process::Command, sync::{ atomic::{AtomicBool, Ordering}, Arc, Mutex, MutexGuard, Weak, }, }; use crate::daemon::ThreadClient; use crate::{ Benchmark, BoardId, Daemon, Event, Key, KeyMap, KeyMapLayer, Layer, Layout, Matrix, Nelson, NelsonKind, }; #[derive(Clone, Debug)] pub enum BoardEvent { KeymapChanged, LedsChanged, MatrixChanged, } #[derive(Debug)] struct BoardInner { thread_client: Arc, board: BoardId, model: String, version: String, layout: Layout, keys: OnceCell>, layers: OnceCell>, max_brightness: i32, leds_changed: AtomicBool, has_led_save: bool, led_save_blocked: AtomicBool, has_matrix: bool, is_fake: bool, has_keymap: bool, matrix: Arc>, updated: bool, event_sender: async_mpsc::UnboundedSender, } #[derive(Clone, Debug)] pub struct Board(Arc); impl PartialEq for Board { fn eq(&self, other: &Self) -> bool { Arc::ptr_eq(&self.0, &other.0) } } impl Eq for Board {} #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Hash, Eq)] pub enum Bootloaded { // Launch 2, Launch Heavy 1, At90usb646, // Launch Lite 1 At90usb646Lite, // Launch 1 AtMega32u4, } #[derive(Debug)] pub(crate) struct WeakBoard(Weak); impl Board { pub fn new( daemon: &dyn Daemon, thread_client: Arc, board: BoardId, matrix: Arc>, event_sender: async_mpsc::UnboundedSender, ) -> Result { let model = match daemon.model(board) { Ok(model) => model, Err(err) => { return Err(format!("Failed to get board model: {}", err)); } }; let version = daemon.version(board).unwrap_or_else(|err| { error!("Error getting firmware version: {}", err); String::new() }); let layout = Layout::from_board(&model, &version) .ok_or_else(|| format!("Failed to locate layout for '{}'", model))?; let max_brightness = daemon.max_brightness(board).unwrap_or_else(|err| { error!("Error getting max brightness: {}", err); 100 }); let num_layers = if layout.meta.has_per_layer { layout.meta.num_layers } else { 1 }; let has_led_save = daemon.led_save(board).is_ok(); let has_matrix = daemon.matrix_get(board).is_ok(); let logical = layout.layout.values().next().unwrap(); let has_keymap = daemon.keymap_get(board, 0, logical.0, logical.1).is_ok(); let self_ = Board(Arc::new(BoardInner { thread_client, board, model, version, layout, max_brightness, has_led_save, has_matrix, is_fake: daemon.is_fake(), has_keymap, keys: OnceCell::new(), layers: OnceCell::new(), leds_changed: AtomicBool::new(false), led_save_blocked: AtomicBool::new(false), matrix, event_sender, updated: is_launch_updated().unwrap_or(false), })); let keys = self_ .layout() .physical .keys .iter() .map(|i| Key::new(daemon, &self_, i)) .collect(); self_.0.keys.set(keys).unwrap(); let layers = (0..num_layers) .map(|layer| Layer::new(daemon, &self_, layer)) .collect(); self_.0.layers.set(layers).unwrap(); Ok(self_) } pub(crate) fn send_event(&self, event: BoardEvent) { let _ = self .0 .event_sender .unbounded_send(Event::Board(self.0.board, event)); } pub(crate) fn set_leds_changed(&self) { self.0.leds_changed.store(true, Ordering::SeqCst); self.send_event(BoardEvent::LedsChanged); } pub fn board(&self) -> BoardId { self.0.board } pub(crate) fn thread_client(&self) -> &ThreadClient { &self.0.thread_client } pub fn model(&self) -> &str { &self.0.model } pub fn version(&self) -> &str { &self.0.version } pub fn has_matrix(&self) -> bool { self.0.has_matrix } pub fn max_brightness(&self) -> i32 { self.0.max_brightness } pub async fn benchmark(&self) -> Result { self.thread_client().benchmark(self.board()).await } pub async fn nelson(&self, kind: NelsonKind) -> Result { self.thread_client().nelson(self.board(), kind).await } pub async fn led_save(&self) -> Result<(), String> { if self.0.led_save_blocked.load(Ordering::SeqCst) { return Ok(()); } if self.has_led_save() && self.0.leds_changed.load(Ordering::SeqCst) { self.thread_client().led_save(self.board()).await?; self.0.leds_changed.store(false, Ordering::SeqCst); debug!("led_save"); } Ok(()) } pub fn block_led_save(&self) { self.0.led_save_blocked.store(true, Ordering::SeqCst); } pub fn unblock_led_save(&self) { self.0.led_save_blocked.store(false, Ordering::SeqCst); } pub fn is_fake(&self) -> bool { self.0.is_fake } pub fn is_lite(&self) -> bool { static RE: Lazy = Lazy::new(|| Regex::new("system76/launch_lite_.*").unwrap()); RE.is_match(self.model()) } pub fn is_updated(&self) -> bool { self.0.updated } pub fn has_led_save(&self) -> bool { self.0.has_led_save } pub fn has_keymap(&self) -> bool { self.0.has_keymap } pub fn layout(&self) -> &Layout { &self.0.layout } pub fn layers(&self) -> &[Layer] { self.0.layers.get().unwrap() } pub fn keys(&self) -> &[Key] { self.0.keys.get().unwrap() } pub(crate) fn matrix(&self) -> MutexGuard { self.0.matrix.lock().unwrap() } pub fn export_keymap(&self) -> KeyMap { let mut map = BTreeMap::new(); let mut key_leds = BTreeMap::new(); for key in self.keys().iter() { let scancodes = (0..self.layout().meta.num_layers as usize) .map(|layer| key.get_scancode(layer).unwrap().1) .collect(); map.insert(key.logical_name.clone(), scancodes); if !key.leds.is_empty() { key_leds.insert(key.logical_name.clone(), key.color()); } } let layers = self .layers() .iter() .map(|layer| KeyMapLayer { mode: *layer.mode.lock().unwrap(), brightness: layer.brightness(), color: layer.color(), }) .collect(); KeyMap { model: self.model().to_string(), version: 1, map, key_leds, layers, } } pub async fn set_no_input(&self, no_input: bool) -> Result<(), String> { self.thread_client() .set_no_input(self.board(), no_input) .await } pub(crate) fn downgrade(&self) -> WeakBoard { WeakBoard(Arc::downgrade(&self.0)) } } impl WeakBoard { pub fn upgrade(&self) -> Option { Some(Board(self.0.upgrade()?)) } } pub fn is_launch_updated() -> Result { use regex::bytes::Regex; let stdout = Command::new("fwupdmgr") .args(["get-updates", "--json"]) .output() .map_err(|e| format!("Failed to use fwupdmgr: {}", e))? .stdout; static RE: Lazy = Lazy::new(|| Regex::new("Launch.* Configurable Keyboard").unwrap()); Ok(!RE.is_match(&stdout)) } ================================================ FILE: backend/src/color.rs ================================================ use ordered_float::NotNan; use palette::{Component, IntoColor, RgbHue}; use serde::{de, Deserialize, Serialize}; use std::{f64::consts::PI, fmt}; type PaletteHsv = palette::Hsv; type PaletteLinSrgb = palette::LinSrgb; /// Floating point hue/saturation color #[cfg_attr(feature = "glib", derive(glib::Boxed))] #[derive( Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq, Hash, Eq, Ord, PartialOrd, )] #[cfg_attr(feature = "glib", boxed_type(name = "S76Hs"))] pub struct Hs { /// Hue, in radians pub h: NotNan, /// Saturation, from 0.0 to 1.0 pub s: NotNan, } impl Hs { pub fn new(h: f64, s: f64) -> Self { Self { h: NotNan::new(h).unwrap(), s: NotNan::new(s).unwrap(), } } pub fn from_ints(h: u8, s: u8) -> Self { Self::new(h.convert::() * (2. * PI), s.convert()) } pub fn to_ints(self) -> (u8, u8) { let h = (self.h / (2. * PI)).rem_euclid(1.); (h.convert(), self.s.convert()) } pub fn to_rgb(self) -> Rgb { let hue = RgbHue::from_radians(*self.h); let hsv = PaletteHsv::new(hue, *self.s, 1.); let rgb: PaletteLinSrgb = hsv.into_rgb(); let (r, g, b) = rgb.into_components(); Rgb::from_floats(r, g, b) } } /// Integer RGB color #[cfg_attr(feature = "glib", derive(glib::Boxed))] #[derive(Clone, Copy, Debug, Default)] #[cfg_attr(feature = "glib", boxed_type(name = "S76Rgb"))] pub struct Rgb { /// Red pub r: u8, /// Green pub g: u8, /// Blue pub b: u8, } impl Rgb { pub fn new(r: u8, g: u8, b: u8) -> Self { Self { r, g, b } } pub fn from_floats(r: f64, g: f64, b: f64) -> Self { Self { r: r.convert(), g: g.convert(), b: b.convert(), } } pub fn to_floats(self) -> (f64, f64, f64) { (self.r.convert(), self.g.convert(), self.b.convert()) } /// Parse from hexadecimal string pub fn parse(s: &str) -> Option { if s.len() == 7 && s.starts_with('#') { let r = u8::from_str_radix(&s[1..3], 16).ok()?; let g = u8::from_str_radix(&s[3..5], 16).ok()?; let b = u8::from_str_radix(&s[5..7], 16).ok()?; Some(Self::new(r, g, b)) } else { None } } #[allow(clippy::many_single_char_names)] pub fn to_hs_lossy(self) -> Hs { let (r, g, b) = self.to_floats(); let rgb = PaletteLinSrgb::new(r, g, b); let hsv: PaletteHsv = rgb.into_hsv(); let (h, s, _) = hsv.into_components(); Hs::new(h.to_radians(), s) } } /// Convert to hexadecimal string impl fmt::Display for Rgb { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b) } } impl Serialize for Rgb { fn serialize(&self, serializer: S) -> Result { serializer.serialize_str(&self.to_string()) } } struct RgbVisitor; impl<'de> de::Visitor<'de> for RgbVisitor { type Value = Rgb; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "a hexadecimal rgb code prefixed with #") } fn visit_str(self, v: &str) -> Result { Rgb::parse(v).ok_or_else(|| E::invalid_value(de::Unexpected::Str(v), &self)) } } impl<'de> Deserialize<'de> for Rgb { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_str(RgbVisitor) } } #[cfg(test)] mod test { use crate::*; #[test] fn test_hs_rgb_hs() { let hs1 = Hs::new(0.3, 0.4); let hs2 = hs1.to_rgb().to_hs_lossy(); let hs3 = hs2.to_rgb().to_hs_lossy(); assert!((hs1.h - hs2.h).abs() < 0.01); assert!((hs1.s - hs2.s).abs() < 0.01); assert!((hs2.h - hs3.h).abs() < 0.0001); assert!((hs2.s - hs3.s).abs() < 0.0001); } } ================================================ FILE: backend/src/daemon/client.rs ================================================ use std::{ cell::RefCell, env, io::{BufRead, BufReader, Write}, path::PathBuf, process::{Child, ChildStdin, ChildStdout, Command, Stdio}, }; use super::{err_str, Daemon, DaemonClientTrait, DaemonCommand, DaemonResponse}; pub struct DaemonClient { child: Child, read: RefCell>, write: RefCell, } impl DaemonClient { pub fn new_pkexec() -> Self { // Use canonicalized command name let command_path = if cfg!(feature = "appimage") { PathBuf::from(env::var("APPIMAGE").expect("Failed to get executable path")) } else { env::current_exe().expect("Failed to get executable path") }; let mut child = Command::new("pkexec") .arg(command_path) .arg("--daemon") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .expect("Failed to spawn daemon"); let stdin = child.stdin.take().unwrap(); let mut stdout = BufReader::new(child.stdout.take().unwrap()); // Check if daemon has started let mut line = String::new(); if let Ok(count) = stdout.read_line(&mut line) { // pkexec terminated returning EOF if count == 0 { panic!("Failed to start daemon with pkexec"); } } Self { child, read: RefCell::new(stdout), write: RefCell::new(stdin), } } } impl DaemonClientTrait for DaemonClient { fn send_command(&self, command: DaemonCommand) -> Result { let mut command_json = serde_json::to_string(&command).map_err(err_str)?; command_json.push('\n'); self.write .borrow_mut() .write_all(command_json.as_bytes()) .map_err(err_str)?; let mut response_json = String::new(); self.read .borrow_mut() .read_line(&mut response_json) .map_err(err_str)?; serde_json::from_str(&response_json).map_err(err_str)? } } impl Drop for DaemonClient { fn drop(&mut self) { let _ = self.exit(); let status = self.child.wait().expect("Failed to wait for daemon"); if !status.success() { panic!("Failed to run daemon with exit status {:?}", status); } } } ================================================ FILE: backend/src/daemon/daemon_thread.rs ================================================ use futures::{ channel::{mpsc as async_mpsc, oneshot}, executor::LocalPool, future::{abortable, AbortHandle}, prelude::*, task::LocalSpawnExt, }; use futures_timer::Delay; use once_cell::sync::Lazy; use std::{ cell::{Cell, RefCell}, cmp::PartialEq, collections::HashMap, hash::{Hash, Hasher}, rc::Rc, sync::{Arc, Mutex, Weak}, thread::{self, JoinHandle}, time::Duration, }; use super::{Benchmark, BoardId, Daemon, Matrix, Nelson, NelsonKind}; use crate::{Board, BoardEvent, Bootloaded, Event}; #[derive(Clone, Debug)] struct Item { key: K, value: V, } impl Item { fn new(key: K, value: V) -> Self { Self { key, value } } } impl Hash for Item { fn hash(&self, state: &mut H) { self.key.hash(state); } } impl PartialEq for Item { fn eq(&self, other: &Self) -> bool { self.key == other.key } } impl Eq for Item {} #[derive(Clone, Hash, Eq, PartialEq, Debug)] enum SetEnum { KeyMap(Item<(BoardId, u8, u8, u8), u16>), Color(Item<(BoardId, u8), (u8, u8, u8)>), Brightness(Item<(BoardId, u8), i32>), Mode(Item<(BoardId, u8), (u8, u8)>), Benchmark(BoardId), Nelson(BoardId, NelsonKind), LedSave(BoardId), MatrixGetRate(Item<(), Option>), Refresh, BootLoaderUpdate(Option), NoInput(BoardId, bool), Exit, } impl SetEnum { fn is_cancelable(&self) -> bool { !matches!(self, Self::Nelson(_, _) | Self::Benchmark(_)) } } #[derive(Debug)] struct Set { inner: SetEnum, oneshot: oneshot::Sender>, } #[derive(Debug)] enum Response { Benchmark(Benchmark), Canceled, Empty, Nelson(Box), } impl From for Response { fn from(benchmark: Benchmark) -> Self { Response::Benchmark(benchmark) } } impl From<()> for Response { fn from(_unit: ()) -> Self { Response::Empty } } impl From for Response { fn from(nelson: Nelson) -> Self { Response::Nelson(Box::new(nelson)) } } impl Set { fn reply>(self, resp: Result) { let _ = self.oneshot.send(resp.map(|x| x.into())); } } #[derive(Debug)] pub struct ThreadClient { cancels: Mutex>, channel: async_mpsc::UnboundedSender, join_handle: Mutex>>, } impl ThreadClient { pub fn new( daemon: Box, event_sender: async_mpsc::UnboundedSender, ) -> Arc { let (sender, reciever) = async_mpsc::unbounded(); let client = Arc::new(Self { cancels: Mutex::new(HashMap::new()), channel: sender, join_handle: Mutex::new(None), }); let join_handle = Thread::new(daemon, client.clone(), event_sender).spawn(reciever); *client.join_handle.lock().unwrap() = Some(join_handle); client } #[allow(clippy::await_holding_lock)] async fn send(&self, set_enum: SetEnum) -> Result { let (sender, receiver) = oneshot::channel(); let (receiver, cancel) = abortable(receiver); { let mut cancels = self.cancels.lock().unwrap(); if set_enum.is_cancelable() { if let Some(cancel) = cancels.remove(&set_enum) { cancel.abort(); } } cancels.insert(set_enum.clone(), cancel); } let _ = self.channel.unbounded_send(Set { inner: set_enum, oneshot: sender, }); match receiver.await { Ok(Ok(res)) => res, _ => Ok(Response::Canceled), } } async fn send_noresp(&self, set_enum: SetEnum) -> Result<(), String> { self.send(set_enum).await.and(Ok(())) } pub async fn refresh(&self) -> Result<(), String> { self.send_noresp(SetEnum::Refresh).await } pub async fn check_for_bootloader(&self) -> Result<(), String> { use regex::bytes::Regex; static HAS_USB_HUB: Lazy = Lazy::new(|| Regex::new("3384:000.*System76 USB").unwrap()); static ATMEGA32U4: Lazy = Lazy::new(|| Regex::new("03eb:2ff4.*atmega32u4.*bootloader").unwrap()); static AT90USB646: Lazy = Lazy::new(|| Regex::new("03eb:2ff9.*at90usb646.*bootloader").unwrap()); let lsusb = async_process::Command::new("lsusb") .arg("--verbose") .output() .await .map_err(|_| "Failed to run lsusb".to_string())? .stdout; let update = if AT90USB646.is_match(&lsusb) { if HAS_USB_HUB.is_match(&lsusb) { Some(Bootloaded::At90usb646) } else { Some(Bootloaded::At90usb646Lite) } } else if ATMEGA32U4.is_match(&lsusb) { Some(Bootloaded::AtMega32u4) } else { None }; self.send_noresp(SetEnum::BootLoaderUpdate(update)).await } pub async fn keymap_set( &self, board: BoardId, layer: u8, output: u8, input: u8, value: u16, ) -> Result<(), String> { self.send_noresp(SetEnum::KeyMap(Item::new( (board, layer, output, input), value, ))) .await } pub async fn set_color( &self, board: BoardId, index: u8, color: (u8, u8, u8), ) -> Result<(), String> { self.send_noresp(SetEnum::Color(Item::new((board, index), color))) .await } pub async fn set_brightness( &self, board: BoardId, index: u8, brightness: i32, ) -> Result<(), String> { self.send_noresp(SetEnum::Brightness(Item::new((board, index), brightness))) .await } pub async fn set_mode( &self, board: BoardId, layer: u8, mode: u8, speed: u8, ) -> Result<(), String> { self.send_noresp(SetEnum::Mode(Item::new((board, layer), (mode, speed)))) .await } pub async fn set_matrix_get_rate(&self, rate: Option) -> Result<(), String> { self.send_noresp(SetEnum::MatrixGetRate(Item::new((), rate))) .await } pub async fn benchmark(&self, board: BoardId) -> Result { let resp = self.send(SetEnum::Benchmark(board)).await?; if let Response::Benchmark(benchmark) = resp { Ok(benchmark) } else { panic!("{}", format!("'{:?}' unexpected", resp)); } } pub async fn nelson(&self, board: BoardId, kind: NelsonKind) -> Result { let resp = self.send(SetEnum::Nelson(board, kind)).await?; if let Response::Nelson(nelson) = resp { Ok(*nelson) } else { panic!("{}", format!("'{:?}' unexpected", resp)); } } pub async fn led_save(&self, board: BoardId) -> Result<(), String> { self.send_noresp(SetEnum::LedSave(board)).await } pub async fn set_no_input(&self, board: BoardId, no_input: bool) -> Result<(), String> { self.send_noresp(SetEnum::NoInput(board, no_input)).await } pub fn close(&self) { let join_handle = match self.join_handle.lock().unwrap().take() { Some(join_handle) => join_handle, None => { return; } }; // Send exit command to thread let (sender, _receiver) = oneshot::channel(); let _ = self.channel.unbounded_send(Set { inner: SetEnum::Exit, oneshot: sender, }); // Wait for thread to terminate join_handle.join().unwrap(); } } /* TODO BootloadedAdded(Bootloaded), BootloadedRemoved */ struct ThreadBoard { matrix: Arc>, board: BoardId, event_sender: async_mpsc::UnboundedSender, has_matrix: bool, } impl ThreadBoard { fn new( board: BoardId, event_sender: async_mpsc::UnboundedSender, has_matrix: bool, matrix: Arc>, ) -> Self { Self { matrix, board, event_sender, has_matrix, } } } struct Thread { daemon: Box, boards: RefCell>, client: Weak, event_sender: async_mpsc::UnboundedSender, matrix_get_rate: Cell>, previous_bootloaded: RefCell>, current_bootloaded: RefCell>, } impl Thread { fn new( daemon: Box, client: Arc, event_sender: async_mpsc::UnboundedSender, ) -> Self { Self { daemon, client: Arc::downgrade(&client), event_sender, boards: RefCell::new(HashMap::new()), matrix_get_rate: Cell::new(None), previous_bootloaded: RefCell::new(None), current_bootloaded: RefCell::new(None), } } fn spawn(self, mut channel: async_mpsc::UnboundedReceiver) -> JoinHandle<()> { thread::spawn(move || { let mut pool = LocalPool::new(); let spawner = pool.spawner(); let self_ = Rc::new(self); let self_clone = self_.clone(); spawner .spawn_local(async move { loop { if let Some(rate) = self_clone.matrix_get_rate.get() { Delay::new(rate).await; self_clone.matrix_refresh_all(); } else { Delay::new(Duration::from_millis(100)).await; } } }) .unwrap(); pool.run_until(async move { while let Some(set) = channel.next().await { if !self_.handle_set(set) { break; } } }); }) } fn handle_set(&self, set: Set) -> bool { if set.oneshot.is_canceled() && set.inner != SetEnum::Exit { return true; } match set.inner { SetEnum::KeyMap(Item { key, value }) => { set.reply(self.daemon.keymap_set(key.0, key.1, key.2, key.3, value)) } SetEnum::Color(Item { key, value }) => { set.reply(self.daemon.set_color(key.0, key.1, value)) } SetEnum::Brightness(Item { key, value }) => { set.reply(self.daemon.set_brightness(key.0, key.1, value)) } SetEnum::Mode(Item { key, value }) => { set.reply(self.daemon.set_mode(key.0, key.1, value.0, value.1)) } SetEnum::Benchmark(board) => set.reply(self.daemon.benchmark(board)), SetEnum::Nelson(board, kind) => set.reply(self.daemon.nelson(board, kind)), SetEnum::LedSave(board) => set.reply(self.daemon.led_save(board)), SetEnum::MatrixGetRate(Item { value, .. }) => { self.matrix_get_rate.set(value); set.reply(Ok(())) } SetEnum::Refresh => set.reply(self.refresh()), SetEnum::BootLoaderUpdate(update) => set.reply(self.bootloader_update(update)), SetEnum::NoInput(board, no_input) => { set.reply(self.daemon.set_no_input(board, no_input)) } SetEnum::Exit => return false, } true } fn matrix_refresh_all(&self) { for (k, v) in self.boards.borrow_mut().iter_mut() { if !v.has_matrix { continue; } let matrix = match self.daemon.matrix_get(*k) { Ok(ok) => ok, Err(err) => { error!("failed to get matrix: {}", err); continue; } }; let mut matrix_lock = v.matrix.lock().unwrap(); if *matrix_lock != matrix { *matrix_lock = matrix; let _ = v .event_sender .unbounded_send(Event::Board(v.board, BoardEvent::MatrixChanged)); } } } fn bootloader_update(&self, update: Option) -> Result<(), String> { *self.previous_bootloaded.borrow_mut() = *self.current_bootloaded.borrow(); *self.current_bootloaded.borrow_mut() = update; // If a new board is plugged in and is in bootloader mode, update the gui // only check if we are in launch test mode for production. match ( *self.previous_bootloaded.borrow(), *self.current_bootloaded.borrow(), ) { (None, Some(board)) => { let _ = self .event_sender .unbounded_send(Event::BootloadedAdded(board)); } (Some(_), None) => { let _ = self.event_sender.unbounded_send(Event::BootloadedRemoved); } _ => {} } Ok(()) } fn refresh(&self) -> Result<(), String> { self.daemon.refresh()?; let mut boards = self.boards.borrow_mut(); let new_ids = self.daemon.boards()?; // Removed boards let event_sender = &self.event_sender; boards.retain(|id, _| { if !new_ids.iter().any(|i| i == id) { let _ = event_sender.unbounded_send(Event::BoardRemoved(*id)); return false; } true }); // Added boards let mut have_new_board = false; for i in &new_ids { if boards.contains_key(i) { continue; } if !have_new_board { let _ = self.event_sender.unbounded_send(Event::BoardLoading); have_new_board = true; } let matrix = Arc::new(Mutex::new(Matrix::default())); match Board::new( self.daemon.as_ref(), self.client.upgrade().unwrap(), *i, matrix.clone(), self.event_sender.clone(), ) { Ok(board) => { boards.insert( *i, ThreadBoard::new(*i, event_sender.clone(), board.has_matrix(), matrix), ); let _ = self.event_sender.unbounded_send(Event::BoardAdded(board)); } Err(err) => error!("Failed to add board: {}", err), } } if have_new_board { let _ = self.event_sender.unbounded_send(Event::BoardLoadingDone); } Ok(()) } } ================================================ FILE: backend/src/daemon/dummy.rs ================================================ use std::{cell::RefCell, collections::HashMap}; use super::{BoardId, Daemon}; use crate::{fl, Benchmark, Layout, Matrix, Nelson, NelsonKind}; struct BoardDummy { name: String, layout: Layout, keymap: RefCell>, colors: RefCell>, brightnesses: RefCell>, modes: RefCell>, } impl BoardDummy { fn valid_index(&self, index: u8, allow_key: bool) -> bool { if !self.layout.meta.has_per_layer { index == 0xff } else if index >= 0xf0 { index < 0xf0 + self.layout.meta.num_layers } else { allow_key && self.layout.leds.values().flatten().any(|i| *i == index) } } } pub struct DaemonDummy { boards: Vec, } impl DaemonDummy { pub fn new(board_names: Vec) -> Result { let mut boards = Vec::with_capacity(board_names.len()); for name in board_names { if let Some(layout) = Layout::from_board(&name, "dummy") { boards.push(BoardDummy { layout, name, keymap: Default::default(), colors: Default::default(), brightnesses: Default::default(), modes: Default::default(), }) } else { return Err(format!( "'{name}' is an invalid board name. Might need a prefix, 'system76/{name}'?" )); } } Ok(Self { boards }) } fn board(&self, board: BoardId) -> Result<&BoardDummy, String> { self.boards .get(board.0 as usize) .ok_or_else(|| fl!("no-board")) } } impl Daemon for DaemonDummy { fn boards(&self) -> Result, String> { Ok((0..self.boards.len() as u128).map(BoardId).collect()) } fn model(&self, board: BoardId) -> Result { Ok(self.board(board)?.name.clone()) } fn version(&self, _board: BoardId) -> Result { Ok("1970-01-01-deadbee".to_string()) } fn is_fake(&self) -> bool { true } fn keymap_get(&self, board: BoardId, layer: u8, output: u8, input: u8) -> Result { let keymap = self.board(board)?.keymap.borrow(); Ok(keymap.get(&(layer, output, input)).copied().unwrap_or(0)) } fn keymap_set( &self, board: BoardId, layer: u8, output: u8, input: u8, value: u16, ) -> Result<(), String> { let mut keymap = self.board(board)?.keymap.borrow_mut(); keymap.insert((layer, output, input), value); Ok(()) } fn matrix_get(&self, _board: BoardId) -> Result { Ok(Matrix::new(0, 0, Vec::new().into_boxed_slice())) } fn benchmark(&self, _board: BoardId) -> Result { Err("Unimplemented".to_string()) } fn nelson(&self, _board: BoardId, _kind: NelsonKind) -> Result { Err("Unimplemented".to_string()) } fn color(&self, board: BoardId, index: u8) -> Result<(u8, u8, u8), String> { let board = self.board(board)?; if !board.valid_index(index, true) { return Err(format!("Can't get color index {} {}", index, board.name)); } Ok(*board.colors.borrow_mut().entry(index).or_default()) } fn set_color(&self, board: BoardId, index: u8, color: (u8, u8, u8)) -> Result<(), String> { let board = self.board(board)?; if !board.valid_index(index, true) { return Err(format!("Can't set color index {}", index)); } board.colors.borrow_mut().insert(index, color); Ok(()) } fn max_brightness(&self, _board: BoardId) -> Result { Ok(100) } fn brightness(&self, board: BoardId, index: u8) -> Result { let board = self.board(board)?; if !board.valid_index(index, false) { return Err(format!("Can't get brightness index {}", index)); } Ok(*board.brightnesses.borrow_mut().entry(index).or_default()) } fn set_brightness(&self, board: BoardId, index: u8, brightness: i32) -> Result<(), String> { let board = self.board(board)?; if !board.valid_index(index, false) { return Err(format!("Can't set brightness index {}", index)); } board.brightnesses.borrow_mut().insert(index, brightness); Ok(()) } fn mode(&self, board: BoardId, layer: u8) -> Result<(u8, u8), String> { let index = layer + 0xf0; let board = self.board(board)?; if !board.valid_index(index, false) { return Err(format!("Can't get mode index {}", index)); } Ok(*board.modes.borrow_mut().entry(index).or_default()) } fn set_mode(&self, board: BoardId, layer: u8, mode: u8, speed: u8) -> Result<(), String> { let index = layer + 0xf0; let board = self.board(board)?; if !board.valid_index(index, false) { return Err(format!("Can't get mode index {}", index)); } board.modes.borrow_mut().insert(index, (mode, speed)); Ok(()) } fn led_save(&self, board: BoardId) -> Result<(), String> { self.board(board)?; Ok(()) } fn refresh(&self) -> Result<(), String> { Ok(()) } fn set_no_input(&self, _board: BoardId, _no_input: bool) -> Result<(), String> { Ok(()) } fn exit(&self) -> Result<(), String> { Ok(()) } } ================================================ FILE: backend/src/daemon/mod.rs ================================================ use serde::{Deserialize, Serialize}; use crate::{Benchmark, Matrix, Nelson, NelsonKind}; mod client; mod daemon_thread; mod dummy; mod server; #[cfg(target_os = "linux")] mod s76power; #[cfg(target_os = "linux")] pub use self::s76power::*; pub use self::{client::*, daemon_thread::*, dummy::*, server::*}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] pub struct BoardId(u128); pub trait DaemonClientTrait: Send + 'static { fn send_command(&self, command: DaemonCommand) -> Result; } // Define Daemon trait, DaemonCommand enum, and DaemonResponse enum macro_rules! commands { ( $( fn $func:ident(&self $(,)? $( $arg:ident: $type:ty ),*) -> Result<$ret:ty, String>; )* ) => { pub trait Daemon: Send + 'static { $( fn $func(&self, $( $arg: $type ),*) -> Result<$ret, String>; )* fn is_fake(&self) -> bool { false } fn dispatch_command_to_method(&self, command: DaemonCommand) -> Result { match command { $( DaemonCommand::$func{$( $arg ),*} => { self.$func($( $arg ),*).map(DaemonResponse::$func) } )* } } } #[allow(non_camel_case_types)] #[derive(Deserialize, Serialize)] #[serde(tag = "t", content = "c")] pub enum DaemonCommand { $( $func{$( $arg: $type ),*} ),* } #[allow(non_camel_case_types)] #[derive(Deserialize, Serialize)] #[serde(tag = "t", content = "c")] pub enum DaemonResponse { $( $func($ret) ),* } impl Daemon for T { $( fn $func(&self, $( $arg: $type ),*) -> Result<$ret, String> { let res = self.send_command(DaemonCommand::$func{$( $arg ),*}); match res { Ok(DaemonResponse::$func(ret)) => Ok(ret), Ok(_) => unreachable!(), Err(err) => Err(err), } } )* } }; } commands! { fn boards(&self) -> Result, String>; fn model(&self, board: BoardId) -> Result; fn version(&self, board: BoardId) -> Result; fn refresh(&self) -> Result<(), String>; fn keymap_get(&self, board: BoardId, layer: u8, output: u8, input: u8) -> Result; fn keymap_set(&self, board: BoardId, layer: u8, output: u8, input: u8, value: u16) -> Result<(), String>; fn matrix_get(&self, board: BoardId) -> Result; fn benchmark(&self, board: BoardId) -> Result; fn nelson(&self, board: BoardId, kind: NelsonKind) -> Result; fn color(&self, board: BoardId, index: u8) -> Result<(u8, u8, u8), String>; fn set_color(&self, board: BoardId, index: u8, color: (u8, u8, u8)) -> Result<(), String>; fn max_brightness(&self, board: BoardId) -> Result; fn brightness(&self, board: BoardId, index: u8) -> Result; fn set_brightness(&self, board: BoardId, index: u8, brightness: i32) -> Result<(), String>; fn mode(&self, board: BoardId, layer: u8) -> Result<(u8, u8), String>; fn set_mode(&self, board: BoardId, layer: u8, mode: u8, speed: u8) -> Result<(), String>; fn led_save(&self, board: BoardId) -> Result<(), String>; fn set_no_input(&self, board: BoardId, no_input: bool) -> Result<(), String>; fn exit(&self) -> Result<(), String>; } fn err_str(err: E) -> String { format!("{:?}", err) } ================================================ FILE: backend/src/daemon/s76power.rs ================================================ // Note: Linux only // Need to watch properties of each object? // TODO: Hotplug detection support use std::iter::Iterator; use zbus::{blocking::fdo::ObjectManagerProxy, blocking::Connection, dbus_proxy}; use super::{err_str, BoardId, Daemon, Matrix}; use crate::{fl, Benchmark, Nelson, NelsonKind, Rgb}; const DBUS_NAME: &str = "com.system76.PowerDaemon"; #[dbus_proxy( interface = "com.system76.PowerDaemon.Keyboard", assume_defaults = true )] trait Keyboard { #[dbus_proxy(property, name = "brightness")] fn brightness(&self) -> zbus::Result; #[dbus_proxy(property, name = "brightness")] fn set_brightness(&self, value: i32) -> zbus::Result<()>; #[dbus_proxy(property, name = "color")] fn color(&self) -> zbus::Result; #[dbus_proxy(property, name = "color")] fn set_color(&self, value: &str) -> zbus::Result<()>; #[dbus_proxy(property, name = "max_brightness")] fn max_brightness(&self) -> zbus::Result; #[dbus_proxy(property, name = "name")] fn name(&self) -> zbus::Result; } struct Keyboard { proxy: KeyboardProxyBlocking<'static>, } impl Keyboard { fn new(path: &str) -> Result { let connection = Connection::system().map_err(err_str)?; let proxy = KeyboardProxyBlocking::builder(&connection) .destination(DBUS_NAME.to_owned()) .map_err(err_str)? .path(path.to_owned()) .map_err(err_str)? .build() .map_err(err_str)?; Ok(Self { proxy }) } } pub struct DaemonS76Power { boards: Vec, } impl DaemonS76Power { fn board(&self, board: BoardId) -> Result<&Keyboard, String> { self.boards .get(board.0 as usize) .ok_or_else(|| fl!("no-board")) } } impl DaemonS76Power { pub fn new() -> Result { let mut boards = Vec::new(); let connection = Connection::system().map_err(err_str)?; let proxy = ObjectManagerProxy::builder(&connection) .destination(DBUS_NAME) .map_err(err_str)? .path("/com/system76/PowerDaemon") .map_err(err_str)? .build() .map_err(err_str)?; let objects = proxy.get_managed_objects().map_err(err_str)?; for path in objects.keys() { if path.starts_with("/com/system76/PowerDaemon/keyboard") { boards.push(Keyboard::new(path)?); } } Ok(Self { boards }) } } impl Daemon for DaemonS76Power { fn boards(&self) -> Result, String> { Ok((0..self.boards.len() as u128).map(BoardId).collect()) } fn model(&self, _board: BoardId) -> Result { // XXX Ok("system76/darp6".to_string()) } fn version(&self, _board: BoardId) -> Result { Err("Unimplemented".to_string()) } fn keymap_get( &self, _board: BoardId, _layer: u8, _output: u8, _input: u8, ) -> Result { Err("Unimplemented".to_string()) } fn keymap_set( &self, _board: BoardId, _layer: u8, _output: u8, _input: u8, _value: u16, ) -> Result<(), String> { Err("Unimplemented".to_string()) } fn matrix_get(&self, _board: BoardId) -> Result { Err("Unimplemented".to_string()) } fn benchmark(&self, _board: BoardId) -> Result { Err("Unimplemented".to_string()) } fn nelson(&self, _board: BoardId, _kind: NelsonKind) -> Result { Err("Unimplemented".to_string()) } fn color(&self, board: BoardId, index: u8) -> Result<(u8, u8, u8), String> { if index != 0xFF { return Err(format!("Can't set color index {}", index)); } let color = self.board(board)?.proxy.color().map_err(err_str)?; Ok(Rgb::parse(&color).map_or((0, 0, 0), |rgb| (rgb.r, rgb.g, rgb.b))) } fn set_color(&self, board: BoardId, index: u8, color: (u8, u8, u8)) -> Result<(), String> { if index != 0xFF { return Err(format!("Can't set color index {}", index)); } self.board(board)? .proxy .set_color(&Rgb::new(color.0, color.1, color.2).to_string()) .map_err(err_str) } fn max_brightness(&self, board: BoardId) -> Result { self.board(board)?.proxy.max_brightness().map_err(err_str) } fn brightness(&self, board: BoardId, index: u8) -> Result { if index != 0xFF { return Err(format!("Can't set brightness index {}", index)); } self.board(board)?.proxy.brightness().map_err(err_str) } fn set_brightness(&self, board: BoardId, index: u8, brightness: i32) -> Result<(), String> { if index != 0xFF { return Err(format!("Can't set brightness index {}", index)); } self.board(board)? .proxy .set_brightness(brightness) .map_err(err_str) } fn mode(&self, _board: BoardId, _layer: u8) -> Result<(u8, u8), String> { Err("Unimplemented".to_string()) } fn set_mode(&self, _board: BoardId, _layer: u8, _mode: u8, _speed: u8) -> Result<(), String> { Err("Unimplemented".to_string()) } fn led_save(&self, _board: BoardId) -> Result<(), String> { Err("Unimplemented".to_string()) } fn refresh(&self) -> Result<(), String> { Ok(()) } fn set_no_input(&self, _board: BoardId, _no_input: bool) -> Result<(), String> { Err("Unimplemented".to_string()) } fn exit(&self) -> Result<(), String> { Ok(()) } } ================================================ FILE: backend/src/daemon/server.rs ================================================ #[cfg(target_os = "linux")] use ectool::AccessLpcLinux; use ectool::{Access, AccessHid, Ec}; use hidapi::{DeviceInfo, HidApi}; use std::{ cell::{Cell, RefCell, RefMut}, collections::HashMap, io::{self, BufRead, BufReader, Read, Write}, str, thread::sleep, time::Duration, }; use uuid::Uuid; use super::{err_str, BoardId, Daemon, DaemonCommand}; use crate::{Benchmark, Matrix, Nelson, NelsonKind}; const QMK_RAW_USAGE_PAGE: u16 = 0xFF60; const QMK_RAW_USAGE_ID: u16 = 0x61; #[allow(clippy::type_complexity)] pub struct DaemonServer { hidapi: RefCell>, running: Cell, read: BufReader, write: W, boards: RefCell>, Option)>>, board_ids: RefCell>, nelson: RefCell>>, } impl DaemonServer { pub fn new_stdio() -> Result { Self::new(io::stdin(), io::stdout()) } } impl DaemonServer { pub fn new(read: R, write: W) -> Result { #[cfg_attr(not(target_os = "linux"), allow(unused_mut))] let mut boards = HashMap::new(); #[cfg_attr(not(target_os = "linux"), allow(unused_mut))] let mut board_ids = Vec::new(); #[cfg(target_os = "linux")] match unsafe { AccessLpcLinux::new(Duration::new(1, 0)) } { Ok(access) => match unsafe { Ec::new(access) } { Ok(ec) => { info!("Adding LPC EC"); let id = BoardId(Uuid::new_v4().as_u128()); boards.insert(id, (ec.into_dyn(), None)); board_ids.push(id); } Err(err) => { error!("Failed to probe LPC EC: {:?}", err); } }, Err(err) => { error!("Failed to access LPC EC: {:?}", err); } } //TODO: should we continue through HID errors? let hidapi = match HidApi::new() { Ok(api) => Some(api), Err(err) => { error!("Failed to list USB HID ECs: {:?}", err); None } }; Ok(Self { hidapi: RefCell::new(hidapi), running: Cell::new(true), read: BufReader::new(read), write, boards: RefCell::new(boards), board_ids: RefCell::new(board_ids), nelson: RefCell::new(None), }) } fn have_device(&self, info: &DeviceInfo) -> bool { for (_, i) in self.boards.borrow().values() { if let Some(i) = i { if (i.vendor_id(), i.product_id(), i.path()) == (info.vendor_id(), info.product_id(), info.path()) { return true; } } } false } pub fn run(mut self) -> io::Result<()> { println!("Daemon started"); while self.running.get() { let mut command_json = String::new(); self.read.read_line(&mut command_json)?; let command = serde_json::from_str::(&command_json) .expect("failed to deserialize command"); let response = self.dispatch_command_to_method(command); //TODO: what to do if we fail to serialize result? let mut result_json = serde_json::to_string(&response).expect("failed to serialize result"); result_json.push('\n'); self.write.write_all(result_json.as_bytes())?; } Ok(()) } fn board(&self, board: BoardId) -> Result>>, String> { let mut boards = self.boards.borrow_mut(); if boards.get_mut(&board).is_some() { Ok(RefMut::map(boards, |x| &mut x.get_mut(&board).unwrap().0)) } else { Err("failed to find board".to_string()) } } } impl Daemon for DaemonServer { fn boards(&self) -> Result, String> { Ok(self.board_ids.borrow().clone()) } fn model(&self, board: BoardId) -> Result { let mut ec = self.board(board)?; let data_size = unsafe { ec.access().data_size() }; let mut data = vec![0; data_size]; let len = unsafe { ec.board(&mut data).map_err(err_str)? }; let board = str::from_utf8(&data[..len]).map_err(err_str)?; Ok(board.to_string()) } fn version(&self, board: BoardId) -> Result { let mut ec = self.board(board)?; let data_size = unsafe { ec.access().data_size() }; let mut data = vec![0; data_size]; let len = unsafe { ec.version(&mut data).map_err(err_str)? }; let version = str::from_utf8(&data[..len]).map_err(err_str)?; Ok(version.to_string()) } fn keymap_get(&self, board: BoardId, layer: u8, output: u8, input: u8) -> Result { let mut ec = self.board(board)?; unsafe { ec.keymap_get(layer, output, input).map_err(err_str) } } fn keymap_set( &self, board: BoardId, layer: u8, output: u8, input: u8, value: u16, ) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.keymap_set(layer, output, input, value).map_err(err_str) } } fn matrix_get(&self, board: BoardId) -> Result { let mut ec = self.board(board)?; let data_size = unsafe { ec.access().data_size() }; let mut data = vec![0; data_size]; unsafe { ec.matrix_get(&mut data).map_err(err_str)? }; let rows = data.remove(0) as usize; let cols = data.remove(0) as usize; Ok(Matrix::new(rows, cols, data.into_boxed_slice())) } fn benchmark(&self, _board: BoardId) -> Result { Benchmark::new().map_err(err_str) } fn nelson(&self, board: BoardId, kind: NelsonKind) -> Result { if let Some(nelson) = &mut *self.nelson.borrow_mut() { const DELAY_MS: u64 = 200; info!("Nelson delay is {} ms", DELAY_MS); let delay = Duration::from_millis(DELAY_MS); // Check if Nelson is already closed if unsafe { nelson.led_get_value(0).map_err(err_str)?.0 > 0 } { info!("Open Nelson"); unsafe { nelson.led_set_value(0, 0).map_err(err_str)? }; info!("Sleep"); sleep(delay); } info!("Close Nelson"); unsafe { nelson.led_set_value(0, 1).map_err(err_str)? }; info!("Sleep"); sleep(delay); // Get pressed keys while nelson is closed let matrix = self.matrix_get(board)?; // Either missing or bouncing is set depending on test let (mut missing, bouncing) = match kind { NelsonKind::Normal => (matrix, Matrix::default()), NelsonKind::Bouncing => (Matrix::default(), matrix), }; // Missing must be inverted, since missing keys are not pressed for row in 0..missing.rows() { for col in 0..missing.cols() { let value = missing.get(row, col).unwrap_or(false); missing.set(row, col, !value); } } info!("Open Nelson"); unsafe { nelson.led_set_value(0, 0).map_err(err_str)? }; info!("Sleep"); sleep(delay); // Anything still pressed after nelson is opened is sticking let sticking = self.matrix_get(board)?; Ok(Nelson { missing, bouncing, sticking, }) } else { Err("failed to find Nelson".to_string()) } } fn color(&self, board: BoardId, index: u8) -> Result<(u8, u8, u8), String> { let mut ec = self.board(board)?; unsafe { ec.led_get_color(index) }.map_err(err_str) } fn set_color(&self, board: BoardId, index: u8, color: (u8, u8, u8)) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.led_set_color(index, color.0, color.1, color.2) .map_err(err_str) } } fn max_brightness(&self, board: BoardId) -> Result { let mut ec = self.board(board)?; let index = if unsafe { ec.access().is::() } { 0xf0 } else { 0xff }; unsafe { ec.led_get_value(index) } .map(|x| i32::from(x.1)) .map_err(err_str) } fn brightness(&self, board: BoardId, index: u8) -> Result { let mut ec = self.board(board)?; unsafe { ec.led_get_value(index) .map(|x| i32::from(x.0)) .map_err(err_str) } } fn set_brightness(&self, board: BoardId, index: u8, brightness: i32) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.led_set_value(index, brightness as u8).map_err(err_str) } } fn mode(&self, board: BoardId, layer: u8) -> Result<(u8, u8), String> { let mut ec = self.board(board)?; unsafe { ec.led_get_mode(layer).map_err(err_str) } } fn set_mode(&self, board: BoardId, layer: u8, mode: u8, speed: u8) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.led_set_mode(layer, mode, speed).map_err(err_str) } } fn led_save(&self, board: BoardId) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.led_save().map_err(err_str) } } fn refresh(&self) -> Result<(), String> { if let Some(api) = &mut *self.hidapi.borrow_mut() { // Remove USB boards that are no longer attached { let mut boards = self.boards.borrow_mut(); let mut board_ids = self.board_ids.borrow_mut(); boards.retain(|_, (ec, _)| unsafe { !(ec.access().is::() && ec.probe().is_err()) }); board_ids.retain(|i| boards.contains_key(i)); } if let Err(err) = api.refresh_devices() { error!("Failed to refresh hidapi devices: {}", err); } for info in api.device_list() { match ( info.vendor_id(), info.product_id(), info.interface_number(), info.usage_page(), info.usage(), ) { // System76 (0x3384, // launch_1 0x0001 | // launch_lite_1 0x0005 | // launch_2 0x0006 | // launch_heavy_1 0x0007 | // launch_3 0x0009 | // launch_heavy_3 0x000A, interface, usage_page, usage) if is_qmk_raw_interface(interface, usage_page, usage) => { // Skip if device already open if self.have_device(info) { continue; } match info.open_device(api) { Ok(device) => match AccessHid::new(device, 10, 1000) { Ok(access) => match unsafe { Ec::new(access) } { Ok(ec) => { info!("Adding USB HID EC at {:?}", info.path()); let id = BoardId(Uuid::new_v4().as_u128()); self.boards .borrow_mut() .insert(id, (ec.into_dyn(), Some(info.clone()))); self.board_ids.borrow_mut().push(id); } Err(err) => error!( "Failed to probe USB HID EC at {:?}: {:?}", info.path(), err ), }, Err(err) => error!( "Failed to access USB HID EC at {:?}: {:?}", info.path(), err ), }, Err(err) => { error!("Failed to open USB HID EC at {:?}: {:?}", info.path(), err) } } } // System76 launch-nelson (0x3384, 0x0002, 0, _, _) => { if self.nelson.borrow().is_some() { continue; } match info.open_device(api) { Ok(device) => match AccessHid::new(device, 10, 1000) { Ok(access) => match unsafe { Ec::new(access) } { Ok(ec) => { info!("Adding Nelson at {:?}", info.path()); *self.nelson.borrow_mut() = Some(ec); } Err(err) => error!( "Failed to probe Nelson at {:?}: {:?}", info.path(), err ), }, Err(err) => error!( "Failed to access Nelson at {:?}: {:?}", info.path(), err ), }, Err(err) => { error!("Failed to open Nelson at {:?}: {:?}", info.path(), err) } } } _ => (), } } } Ok(()) } fn set_no_input(&self, board: BoardId, no_input: bool) -> Result<(), String> { let mut ec = self.board(board)?; unsafe { ec.set_no_input(no_input) }.map_err(err_str) } fn exit(&self) -> Result<(), String> { self.running.set(false); Ok(()) } } // Getting the interface number isn't working on macOS 13.3 // (https://github.com/libusb/hidapi/pull/530) // And `usage_page` and `usage` seem to have issues on Linux with older versions of `hidapi`. fn is_qmk_raw_interface(interface: i32, usage_page: u16, usage: u16) -> bool { if cfg!(target_os = "macos") { (usage_page, usage) == (QMK_RAW_USAGE_PAGE, QMK_RAW_USAGE_ID) } else { interface == 1 } } ================================================ FILE: backend/src/deref_cell.rs ================================================ use once_cell::unsync::OnceCell; /// Wrapper around `OnceCell` implementing `Deref`, and thus also panicking /// when not set (or set twice). /// /// To be used in place of `gtk::TemplateChild`, but without xml. pub struct DerefCell(OnceCell); impl DerefCell { pub fn is_some(&self) -> bool { self.0.get().is_some() } #[track_caller] pub fn set(&self, value: T) { if self.0.set(value).is_err() { panic!("Initialized twice"); } } } impl Default for DerefCell { fn default() -> Self { Self(OnceCell::default()) } } impl std::ops::Deref for DerefCell { type Target = T; #[track_caller] fn deref(&self) -> &T { self.0.get().unwrap() } } ================================================ FILE: backend/src/key.rs ================================================ use std::sync::{ atomic::{AtomicU16, Ordering}, Mutex, }; use crate::{Board, BoardEvent, Daemon, Hs, PhysicalLayoutKey, Rect, Rgb, WeakBoard}; #[derive(Debug)] pub struct Key { pub(crate) board: WeakBoard, /// Logical position (row, column) pub logical: (u8, u8), /// Logical name (something like K01, where 0 is the row and 1 is the column) pub logical_name: String, /// Physical position and size pub physical: Rect, /// Physical key name (what is printed on the keycap) pub physical_name: String, /// Electrical mapping (output, input) pub electrical: (u8, u8), /// Electrical name (output, input) pub electrical_name: String, /// LED indexes pub leds: Vec, /// LED name pub led_name: String, led_color: Mutex>, /// Currently loaded scancodes and their names scancodes: Vec, /// Background color pub background_color: Rgb, } impl Key { pub(crate) fn new( daemon: &dyn Daemon, board: &Board, physical_key: &PhysicalLayoutKey, ) -> Self { let logical = physical_key.logical; let logical_name = physical_key.logical_name(); let physical = physical_key.physical; let physical_name = physical_key.physical_name.clone(); let background_color = physical_key.background_color; debug!("Key {}, {} = {:?}", physical.x, physical.y, physical_name); debug!(" Logical: {:?}", logical); debug!(" Logical Name: {}", logical_name); let electrical = *board .layout() .layout .get(logical_name.as_str()) //.expect("Failed to find electrical mapping"); .unwrap_or(&(0, 0)); debug!(" Electrical: {:?}", electrical); let leds = board .layout() .leds .get(logical_name.as_str()) .map_or(Vec::new(), |x| x.clone()); debug!(" LEDs: {:?}", leds); let mut led_name = String::new(); for led in leds.iter() { if !led_name.is_empty() { led_name.push_str(", "); } led_name.push_str(&led.to_string()); } let mut scancodes = Vec::new(); for layer in 0..board.layout().meta.num_layers { debug!(" Layer {}", layer); let scancode = match daemon.keymap_get(board.board(), layer, electrical.0, electrical.1) { Ok(value) => value, Err(err) => { error!("Failed to read scancode: {:?}", err); 0 } }; debug!(" Scancode: {:04X}", scancode); debug!( " Scancode Name: {:?}", board.layout().scancode_to_name(scancode) ); scancodes.push(AtomicU16::new(scancode)); } let mut led_color = None; if board.layout().meta.has_mode && !leds.is_empty() { match daemon.color(board.board(), leds[0]) { Ok((0, 0, 0)) => {} Ok((r, g, b)) => led_color = Some(Rgb::new(r, g, b).to_hs_lossy()), Err(err) => error!("error getting key color: {}", err), } } Self { board: board.downgrade(), logical, logical_name, physical, physical_name, electrical, electrical_name: format!("{}, {}", electrical.0, electrical.1), leds, led_name, led_color: Mutex::new(led_color), scancodes, background_color, } } fn board(&self) -> Board { self.board.upgrade().unwrap() } pub fn pressed(&self) -> bool { self.board() .matrix() .get(self.electrical.0 as usize, self.electrical.1 as usize) .unwrap_or(false) } pub fn color(&self) -> Option { *self.led_color.lock().unwrap() } pub async fn set_color(&self, color: Option) -> Result<(), String> { let board = self.board(); let Rgb { r, g, b } = color.map_or(Rgb::new(0, 0, 0), Hs::to_rgb); for index in &self.leds { board .thread_client() .set_color(board.board(), *index, (r, g, b)) .await?; } *self.led_color.lock().unwrap() = color; board.set_leds_changed(); Ok(()) } pub fn get_scancode(&self, layer: usize) -> Option<(u16, String)> { let board = self.board(); let scancode = self.scancodes.get(layer)?.load(Ordering::SeqCst); let scancode_name = match board.layout().scancode_to_name(scancode) { Some(some) => some, None => String::new(), }; Some((scancode, scancode_name)) } pub async fn set_scancode(&self, layer: usize, scancode_name: &str) -> Result<(), String> { let board = self.board(); let scancode = board .layout() .scancode_from_name(scancode_name) .ok_or_else(|| format!("Unable to find scancode '{}'", scancode_name))?; board .thread_client() .keymap_set( board.board(), layer as u8, self.electrical.0, self.electrical.1, scancode, ) .await?; self.scancodes[layer].store(scancode, Ordering::SeqCst); board.send_event(BoardEvent::KeymapChanged); Ok(()) } } ================================================ FILE: backend/src/keymap.rs ================================================ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{ collections::BTreeMap, convert::TryFrom, io::{Read, Write}, }; use crate::Hs; mod hs_serde { use super::*; pub fn serialize(color: &Hs, serializer: S) -> Result { color.to_ints().serialize(serializer) } pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { let (h, s) = <(u8, u8)>::deserialize(deserializer)?; Ok(Hs::from_ints(h, s)) } } mod hs_map_serde { use super::*; pub fn serialize( map: &BTreeMap>, serializer: S, ) -> Result { let map = map .iter() .map(|(k, hs)| (k, hs.map(|hs| hs.to_ints()))) .collect::>(); map.serialize(serializer) } pub fn deserialize<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result>, D::Error> { let map = >>::deserialize(deserializer)?; Ok(map .into_iter() .map(|(k, v)| (k, v.map(|(h, s)| Hs::from_ints(h, s)))) .collect()) } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyMapLayer { pub mode: Option<(u8, u8)>, pub brightness: i32, #[serde(with = "hs_serde")] pub color: Hs, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyMap { pub model: String, pub version: u8, pub map: BTreeMap>, #[serde(with = "hs_map_serde")] pub key_leds: BTreeMap>, pub layers: Vec, } impl KeyMap { /// Parse layout from json file pub fn from_reader(rdr: R) -> serde_json::Result { serde_json::from_reader(rdr) } /// Write layout to json file, pretty printed pub fn to_writer_pretty(&self, wtr: W) -> serde_json::Result<()> { serde_json::to_writer_pretty(wtr, self) } /// Write layout to json string, pretty printed pub fn to_string_pretty(&self) -> String { serde_json::to_string_pretty(self).unwrap() } } impl TryFrom<&str> for KeyMap { type Error = serde_json::Error; fn try_from(s: &str) -> Result { serde_json::from_str(s) } } ================================================ FILE: backend/src/layer.rs ================================================ use std::sync::{ atomic::{AtomicI32, Ordering}, Mutex, }; use crate::{Board, Daemon, Hs, Mode, Rgb, WeakBoard}; #[derive(Debug)] pub struct Layer { layer: u8, index: u8, board: WeakBoard, pub(crate) mode: Mutex>, brightness: AtomicI32, color: Mutex, } impl Layer { pub(crate) fn new(daemon: &dyn Daemon, board: &Board, layer: u8) -> Self { let index = if board.layout().meta.has_per_layer { 0xf0 + layer } else { 0xff }; let mode = if board.layout().meta.has_mode { daemon .mode(board.board(), layer) .map(Some) .unwrap_or_else(|err| { error!("Error getting layer mode: {}", err); None }) } else { None }; let brightness = daemon .brightness(board.board(), index) .unwrap_or_else(|err| { error!("error getting layer brightness: {}", err); 0 }); let color = daemon .color(board.board(), index) .map(|color| { if index == 0xff { Rgb::new(color.0, color.1, color.2).to_hs_lossy() } else { Hs::from_ints(color.0, color.1) } }) .unwrap_or_else(|err| { error!("error getting layer color: {}", err); Hs::new(0., 0.) }); Self { layer, index, board: board.downgrade(), mode: Mutex::new(mode), brightness: AtomicI32::new(brightness), color: Mutex::new(color), } } fn board(&self) -> Board { self.board.upgrade().unwrap() } /// Get the current mode and speed. `None` if not supported by board. pub fn mode(&self) -> Option<(&'static Mode, u8)> { let (index, speed) = (*self.mode.lock().unwrap())?; Some((Mode::from_index(index)?, speed)) } pub async fn set_mode(&self, mode: &Mode, speed: u8) -> Result<(), String> { let board = self.board(); board .thread_client() .set_mode(board.board(), self.layer, mode.index, speed) .await?; *self.mode.lock().unwrap() = Some((mode.index, speed)); board.set_leds_changed(); Ok(()) } /// Get the current brightness pub fn brightness(&self) -> i32 { self.brightness.load(Ordering::SeqCst) } pub async fn set_brightness(&self, brightness: i32) -> Result<(), String> { let board = self.board(); board .thread_client() .set_brightness(board.board(), self.index, brightness) .await?; self.brightness.store(brightness, Ordering::SeqCst); board.set_leds_changed(); Ok(()) } /// Get the current color pub fn color(&self) -> Hs { *self.color.lock().unwrap() } pub async fn set_color(&self, hs: Hs) -> Result<(), String> { let board = self.board(); let color = if self.index == 0xff { let Rgb { r, g, b } = hs.to_rgb(); (r, g, b) } else { let (h, s) = hs.to_ints(); (h, s, 0) }; board .thread_client() .set_color(board.board(), self.index, color) .await?; *self.color.lock().unwrap() = hs; board.set_leds_changed(); Ok(()) } } ================================================ FILE: backend/src/layout/meta.rs ================================================ use crate::Rgb; use serde::Deserialize; fn num_layers_default() -> u8 { 2 } /// Metadata for keyboard #[derive(Debug, Deserialize)] pub struct Meta { /// Display name for keyboard pub display_name: String, /// Keyboard has per-key controllable LEDs supporting various modes #[serde(default)] pub has_mode: bool, /// LED settings are per-layer, not for the whole keyboard #[serde(default)] pub has_per_layer: bool, /// Has LED with brightness pub has_brightness: bool, /// Has LED with color (i.e. not monochrome) pub has_color: bool, /// Supports mod-tap bindings (assumes QMK mod-tap encoding) #[serde(default)] pub has_mod_tap: bool, #[serde(default)] /// Disable "Invert F Keys" option pub no_fn_f: bool, /// Number or layers; e.g. 2 where layer 2 is used when `Fn` is held #[serde(default = "num_layers_default")] pub num_layers: u8, pub pressed_color: Rgb, #[serde(default)] pub is_qmk: bool, } ================================================ FILE: backend/src/layout/mod.rs ================================================ use cascade::cascade; use regex::Regex; use std::{collections::HashMap, convert::TryFrom, fs, path::Path, str::FromStr}; mod meta; use once_cell::sync::Lazy; mod physical_layout; pub use self::meta::Meta; pub(crate) use physical_layout::{PhysicalLayout, PhysicalLayoutKey}; use crate::KeyMap; // Merge date of https://github.com/system76/ec/pull/229 // Before this, `PAUSE` will not work. const EC_PAUSE_DATE: (u16, u16, u16) = (2022, 5, 23); // https://github.com/system76/ec/pull/263 const EC_FNLOCK_DATE: (u16, u16, u16) = (2023, 8, 1); const QK_MOD_TAP_LEGACY: u16 = 0x6000; const QK_MOD_TAP_MAX_LEGACY: u16 = 0x7FFF; const QK_MOD_TAP: u16 = 0x2000; const QK_MOD_TAP_MAX: u16 = 0x3FFF; pub static MOD_TAP_MODS: Lazy> = Lazy::new(|| { cascade! { HashMap::new(); ..insert("LEFT_CTRL", 0x01); ..insert("LEFT_SHIFT", 0x02); ..insert("LEFT_ALT", 0x04); ..insert("LEFT_SUPER", 0x08); ..insert("RIGHT_CTRL", 0x11); ..insert("RIGHT_SHIFT", 0x12); ..insert("RIGHT_ALT", 0x14); ..insert("RIGHT_SUPER", 0x18); } }); #[derive(Debug)] pub struct Layout { /// Metadata for keyboard pub meta: Meta, /// Default keymap for this keyboard pub default: KeyMap, keymap: HashMap, scancode_names: HashMap, pub(crate) physical: PhysicalLayout, pub(crate) layout: HashMap, pub(crate) leds: HashMap>, use_legacy_scancodes: bool, } macro_rules! keyboards { ($( ($board:expr, $keyboard:expr, $is_qmk:expr) ),* $(,)?) => { fn layout_data(board: &str, use_legacy_scancodes: bool) -> Option<(&'static str, &'static str, &'static str, &'static str, &'static str, &'static str)> { match board { $( $board => { let meta_json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/", $board, "/meta.json")); let default_json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/", $board, "/default.json")); let keymap_json = if use_legacy_scancodes && $is_qmk { include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keymap/qmk_legacy.json")) } else if $is_qmk { include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keymap/qmk.json")) } else { include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keymap/ec.json")) }; let layout_json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keyboards/", $keyboard, "/layout.json")); let leds_json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keyboards/", $keyboard, "/leds.json")); let physical_json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../layouts/keyboards/", $keyboard, "/physical.json")); Some((meta_json, default_json, keymap_json, layout_json, leds_json, physical_json)) } )* _ => None } } /// Names of board layouts that can be opened with `Layout::from_board` pub fn layouts() -> &'static [&'static str] { &[$( $board ),*] } }; } // Calls the `keyboards!` macro include!(concat!(env!("OUT_DIR"), "/keyboards.rs")); impl Layout { #[allow(clippy::too_many_arguments)] pub fn from_data( board: &str, meta_json: &str, default_json: &str, keymap_json: &str, layout_json: &str, leds_json: &str, physical_json: &str, version: &str, use_legacy_scancodes: bool, ) -> Self { let meta: Meta = serde_json::from_str(meta_json).unwrap(); let mut default = KeyMap::try_from(default_json).unwrap(); let has_pause_scancode = if meta.is_qmk { true } else { parse_ec_date(version).map_or(true, |date| date >= EC_PAUSE_DATE) }; if !has_pause_scancode { keymap_remove_pause(&mut default); } let has_fnlock_scancode = if meta.is_qmk { false } else { parse_ec_date(version).map_or(true, |date| date >= EC_FNLOCK_DATE) }; if !has_fnlock_scancode { keymap_remove_fnlock(&mut default); } let (keymap, scancode_names) = parse_keymap_json( keymap_json, board, &meta, has_pause_scancode, has_fnlock_scancode, ); let layout = serde_json::from_str(layout_json).unwrap(); let leds = serde_json::from_str(leds_json).unwrap(); let physical = PhysicalLayout::from_str(physical_json); Self { meta, default, keymap, scancode_names, physical, layout, leds, use_legacy_scancodes, } } #[allow(dead_code)] pub fn from_dir>(board: &str, dir: P) -> Self { let dir = dir.as_ref(); let meta_json = fs::read_to_string(dir.join("meta.json")).expect("Failed to load meta.json"); let default_json = fs::read_to_string(dir.join("default.json")).expect("Failed to load default.json"); let keymap_json = fs::read_to_string(dir.join("keymap.json")).expect("Failed to load keymap.json"); let layout_json = fs::read_to_string(dir.join("layout.json")).expect("Failed to load layout.json"); let leds_json = fs::read_to_string(dir.join("leds.json")).expect("Failed to load leds.json"); let physical_json = fs::read_to_string(dir.join("physical.json")).expect("Failed to load physical.json"); Self::from_data( board, &meta_json, &default_json, &keymap_json, &layout_json, &leds_json, &physical_json, "dummy", false, ) } pub fn from_board(board: &str, version: &str) -> Option { let use_legacy_scancodes = version.contains("0.7.103") || version.contains("0.7.104") || version.contains("0.12.20"); layout_data(board, use_legacy_scancodes).map( |(meta_json, default_json, keymap_json, layout_json, leds_json, physical_json)| { Self::from_data( board, meta_json, default_json, keymap_json, layout_json, leds_json, physical_json, version, use_legacy_scancodes, ) }, ) } /// Get the scancode number corresponding to a name pub fn scancode_to_name(&self, scancode: u16) -> Option { if self.meta.is_qmk { let (qk_mod_tap, qk_mod_tap_max) = if self.use_legacy_scancodes { (QK_MOD_TAP_LEGACY, QK_MOD_TAP_MAX_LEGACY) } else { (QK_MOD_TAP, QK_MOD_TAP_MAX) }; if scancode >= qk_mod_tap && scancode < qk_mod_tap_max { let mod_ = (scancode >> 8) & 0x1f; let kc = scancode & 0xff; let mod_name = MOD_TAP_MODS.iter().find(|(_, v)| **v == mod_)?.0; let kc_name = self.scancode_names.get(&kc)?; return Some(format!("MT({}, {})", mod_name, kc_name)); } } self.scancode_names.get(&scancode).cloned() } /// Get the name corresponding to a scancode number pub fn scancode_from_name(&self, name: &str) -> Option { if self.meta.is_qmk { // Check if mod-tap let mt_re = Regex::new("MT\\(([^()]+), ([^()]+)\\)").unwrap(); if let Some(captures) = mt_re.captures(name) { let qk_mod_tap = if self.use_legacy_scancodes { QK_MOD_TAP_LEGACY } else { QK_MOD_TAP }; let mod_ = *MOD_TAP_MODS.get(&captures.get(1).unwrap().as_str())?; let kc = *self.keymap.get(captures.get(2).unwrap().as_str())?; return Some(qk_mod_tap | ((mod_ & 0x1f) << 8) | (kc & 0xff)); } } self.keymap.get(name).copied() } pub fn f_keys(&self) -> impl Iterator { self.default.map.iter().filter_map(|(k, v)| { if let Some(num) = v[0].strip_prefix('F') { if num.parse::().is_ok() { return Some(k.as_str()); } } None }) } pub fn layout(&self) -> &HashMap { &self.layout } } fn parse_keymap_json( keymap_json: &str, board: &str, meta: &Meta, has_pause_scancode: bool, has_fnlock_scancode: bool, ) -> (HashMap, HashMap) { let mut keymap: HashMap = serde_json::from_str(keymap_json).unwrap(); // Filter out keycodes that aren't relevant to this particular model // TODO: Support bonw backlight over USB? if meta.has_color || board == "system76/bonw14" || board == "system76/bonw15" { keymap.remove("KBD_BKL"); } else if meta.has_brightness { keymap.remove("KBD_COLOR"); } else { for i in ["KBD_COLOR", "KBD_DOWN", "KBD_UP", "KBD_BKL", "KBD_TOGGLE"] { keymap.remove(i); } } if !has_pause_scancode { keymap.remove("PAUSE"); } if !has_fnlock_scancode { keymap.remove("FNLOCK"); } // Generate reverse mapping, from scancode to names let mut scancode_names = HashMap::new(); for (scancode_name, scancode) in &keymap { scancode_names.insert(*scancode, scancode_name.clone()); } (keymap, scancode_names) } fn parse_ec_date(version: &str) -> Option<(u16, u16, u16)> { let groups = Regex::new(r"^(\d+)-(\d+)-(\d+)_") .unwrap() .captures(version)?; let mut groups = groups .iter() .skip(1) .map(|g| u16::from_str(g.unwrap().as_str()).unwrap()); Some(( groups.next().unwrap(), groups.next().unwrap(), groups.next().unwrap(), )) } fn keymap_remove_pause(keymap: &mut KeyMap) { for values in keymap.map.values_mut() { if values.get(1).map(String::as_str) == Some("PAUSE") { // Change `PAUSE` on layer 1 to match layer 0 values[1] = values[0].clone(); } } } fn keymap_remove_fnlock(keymap: &mut KeyMap) { for values in keymap.map.values_mut() { if values.get(1).map(String::as_str) == Some("FNLOCK") { // Change `FNLOCK` on layer 1 to match layer 0 values[1] = values[0].clone(); } } } #[cfg(test)] mod tests { use super::*; use std::{collections::HashSet, fs, io}; const VERSIONS: [&str; 3] = ["0.7.103", "0.7.104", "0.19.12"]; #[test] fn layout_from_board() { for i in layouts() { for version in VERSIONS { Layout::from_board(i, version).unwrap(); } } } #[test] fn default_keys_exist() { for i in layouts() { for version in VERSIONS { let mut missing = HashSet::new(); let layout = Layout::from_board(i, version).unwrap(); for j in layout.default.map.values().flatten() { if !layout.keymap.keys().any(|x| x == j) { missing.insert(j.to_owned()); } } assert_eq!(missing, HashSet::new(), "Mssing in keymap for {}", i); } } } #[test] fn qmk_has_ec_keycodes() { for version in VERSIONS { let layout_ec = Layout::from_board("system76/darp6", version).unwrap(); let layout_qmk = Layout::from_board("system76/launch_1", version).unwrap(); for k in layout_ec.keymap.keys() { if k == "KBD_COLOR" || k == "KBD_BKL" || k == "TOUCHPAD" || k == "DISPLAY_TOGGLE" || k == "DISPLAY_MODE" || k == "FAN_TOGGLE" || k == "CAMERA_TOGGLE" || k == "AIRPLANE_MODE" || k == "MIC_MUTE" || k == "FNLOCK" { continue; } assert_eq!(layout_qmk.keymap.keys().find(|x| x == &k), Some(k)); } } } #[test] fn color_brightness_keycodes() { const VERSION: &str = "0.19.12"; let layout_no_color = Layout::from_board("system76/lemp10", VERSION).unwrap(); assert!( layout_no_color.keymap.contains_key("KBD_BKL") && !layout_no_color.keymap.contains_key("KBD_COLOR") ); let layout_color = Layout::from_board("system76/gaze15", VERSION).unwrap(); assert!( layout_color.keymap.contains_key("KBD_COLOR") && !layout_color.keymap.contains_key("KBD_BKL") ); let layout_bonw = Layout::from_board("system76/bonw14", VERSION).unwrap(); assert!( layout_bonw.keymap.contains_key("KBD_COLOR") && !layout_bonw.keymap.contains_key("KBD_BKL") ); } #[test] fn has_all_layouts_in_dir() -> io::Result<()> { let layouts = layouts(); for i in fs::read_dir("../layouts/system76")? { let i = i?; if i.file_type()?.is_dir() { let name = format!("system76/{}", i.file_name().into_string().unwrap()); assert!( layouts.contains(&name.as_str()), "{} not listed in {}", name, file!() ); } } Ok(()) } #[test] fn physical_layout_leds_logical() { for i in layouts() { for version in VERSIONS { let layout = Layout::from_board(i, version).unwrap(); let logical_in_physical = layout .physical .keys .iter() .map(|i| i.logical_name()) .collect::>(); let logical_in_layout = layout.layout.keys().cloned().collect::>(); let logical_in_leds = layout.layout.keys().cloned().collect::>(); assert_eq!( &logical_in_physical - &logical_in_layout, HashSet::new(), "{}", i ); assert_eq!( &logical_in_layout - &logical_in_physical, HashSet::new(), "{}", i ); assert_eq!( &logical_in_physical - &logical_in_leds, HashSet::new(), "{}", i ); assert_eq!( &logical_in_leds - &logical_in_physical, HashSet::new(), "{}", i ); } } } #[test] fn layout_has_f_keys() { for i in layouts() { if *i == "system76/launch_lite_1" { continue; } for version in VERSIONS { let layout = Layout::from_board(i, version).unwrap(); assert_eq!(layout.f_keys().count(), 12); } } } } ================================================ FILE: backend/src/layout/physical_layout.rs ================================================ //! Serde based deserialization for physical.json //! From use serde::Deserialize; use std::char; use crate::{Rect, Rgb}; #[allow(dead_code)] #[derive(Debug)] pub(crate) struct PhysicalLayout { pub meta: PhysicalLayoutMeta, pub keys: Vec, } impl PhysicalLayout { pub fn from_str(physical_json: &str) -> Self { let json = serde_json::from_str::(physical_json).unwrap(); let mut keys = Vec::new(); let mut row_i = 0; let mut col_i = 0; let mut physical = Rect::new(0.0, 0.0, 1.0, 1.0); let mut background_color = Rgb::new(0xcc, 0xcc, 0xcc); let mut meta = None; for entry in json.0 { match entry { PhysicalLayoutEntry::Meta(data) => { meta = Some(data); } PhysicalLayoutEntry::Row(row) => { for i in &row.0 { match i { PhysicalKeyEnum::Meta(meta) => { debug!("Key metadata {:?}", meta); physical.x += meta.x; physical.y -= meta.y; physical.w = meta.w.unwrap_or(physical.w); physical.h = meta.h.unwrap_or(physical.h); background_color = meta.c.unwrap_or(background_color); } PhysicalKeyEnum::Name(name) => { keys.push(PhysicalLayoutKey { logical: (row_i as u8, col_i as u8), physical, physical_name: name.clone(), background_color, }); physical.x += physical.w; physical.w = 1.0; physical.h = 1.0; col_i += 1; } } } physical.x = 0.0; physical.y -= 1.0; col_i = 0; row_i += 1; } } } let meta = meta.expect("No layout meta"); Self { keys, meta } } } #[derive(Debug)] pub(crate) struct PhysicalLayoutKey { pub logical: (u8, u8), pub physical: Rect, pub physical_name: String, pub background_color: Rgb, } impl PhysicalLayoutKey { pub fn logical_name(&self) -> String { let row_char = char::from_digit(u32::from(self.logical.0), 36).expect("Failed to convert row to char"); let col_char = char::from_digit(u32::from(self.logical.1), 36).expect("Failed to convert col to char"); format!("K{}{}", row_char, col_char).to_uppercase() } } #[derive(Debug, Deserialize)] struct PhysicalLayoutJson(Vec); #[derive(Debug, Deserialize)] #[serde(untagged)] enum PhysicalLayoutEntry { Meta(PhysicalLayoutMeta), Row(PhysicalRow), } #[derive(Debug, Deserialize)] #[allow(dead_code)] pub(crate) struct PhysicalLayoutMeta { pub name: String, pub author: String, } #[derive(Debug, Deserialize)] struct PhysicalRow(Vec); #[derive(Debug, Deserialize)] #[serde(untagged)] enum PhysicalKeyEnum { Name(String), Meta(PhysicalKeyMeta), } #[derive(Debug, Deserialize)] struct PhysicalKeyMeta { #[serde(default)] x: f64, #[serde(default)] y: f64, w: Option, h: Option, c: Option, } ================================================ FILE: backend/src/lib.rs ================================================ //#![warn(missing_docs)] //! ```no_run //! # use futures::{executor::ThreadPool, stream::StreamExt}; //! use system76_keyboard_configurator_backend::{Backend, Event}; //! //! # let executor = ThreadPool::new().unwrap(); //! //! let (backend, mut events) = Backend::new()?; //! executor.spawn_ok(async move { //! while let Some(event) = events.next().await { //! if let Event::BoardAdded(board) = event { //! println!("{}", board.model()); //! } //! } //! }); //! backend.refresh(); //! # Ok::<(), String>(()) //! ``` #[macro_use] extern crate log; mod backend; mod benchmark; mod board; mod color; mod daemon; mod deref_cell; mod key; mod keymap; mod layer; mod layout; mod localize; mod matrix; mod mode; mod nelson; mod rect; pub use crate::daemon::BoardId; use crate::daemon::*; pub use crate::{ backend::*, benchmark::*, board::*, color::*, deref_cell::*, key::*, keymap::*, layer::*, layout::*, localize::*, matrix::*, mode::*, nelson::*, rect::*, }; ================================================ FILE: backend/src/localize.rs ================================================ use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DefaultLocalizer, LanguageLoader, Localizer, }; use once_cell::sync::Lazy; use rust_embed::RustEmbed; #[derive(RustEmbed)] #[folder = "../i18n/"] struct Localizations; pub static LANGUAGE_LOADER: Lazy = Lazy::new(|| { let loader: FluentLanguageLoader = fluent_language_loader!(); loader .load_fallback_language(&Localizations) .expect("Error while loading fallback language"); loader }); #[macro_export] macro_rules! fl { ($message_id:literal) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id) }}; ($message_id:literal, $($args:expr),*) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *) }}; } // Get the `Localizer` to be used for localizing this library. pub fn localizer() -> Box { Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) } ================================================ FILE: backend/src/matrix.rs ================================================ use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, Debug, Default, PartialEq, Clone)] pub struct Matrix { rows: usize, cols: usize, data: Box<[u8]>, } impl Matrix { pub fn new(rows: usize, cols: usize, data: Box<[u8]>) -> Self { Self { rows, cols, data } } pub fn rows(&self) -> usize { self.rows } pub fn cols(&self) -> usize { self.cols } pub fn get(&self, row: usize, col: usize) -> Option { if row < self.rows && col < self.cols { let i = row * self.cols + col; let byte = i / 8; let bit = i % 8; Some((self.data[byte] & (1 << bit)) != 0) } else { None } } pub fn set(&mut self, row: usize, col: usize, value: bool) { if row < self.rows && col < self.cols { let i = row * self.cols + col; let byte = i / 8; let bit = i % 8; if value { self.data[byte] |= 1 << bit; } else { self.data[byte] &= !(1 << bit); } } } } ================================================ FILE: backend/src/mode.rs ================================================ use crate::fl; use once_cell::sync::Lazy; use std::collections::HashMap; /// A mode/pattern for the keyboard's LEDs to display #[non_exhaustive] pub struct Mode { /// Index (as used in firmware) pub index: u8, /// Textual ID of mode, for `ListBox` or debugging pub id: &'static str, /// Display name of mode pub name: String, /// Hue setting has effect in this mode pub has_hue: bool, /// Speed setting has effect in this mode pub has_speed: bool, } impl Mode { const fn new( index: u8, id: &'static str, name: String, has_hue: bool, has_speed: bool, ) -> Self { Self { index, id, name, has_hue, has_speed, } } /// Return slice of all `Mode`s, ordered as they should be displayed pub fn all() -> &'static [Mode] { &MODES } /// Get `Mode` corresponding to index (as used in firmware) pub fn from_index(index: u8) -> Option<&'static Self> { static MODE_BY_INDEX: Lazy> = Lazy::new(|| MODES.iter().map(|i| (i.index, i)).collect()); MODE_BY_INDEX.get(&index).cloned() } /// Get `Mode` corresponding to textual ID pub fn from_id(id: &str) -> Option<&'static Self> { static MODE_BY_ID: Lazy> = Lazy::new(|| MODES.iter().map(|i| (i.id, i)).collect()); MODE_BY_ID.get(&id).cloned() } /// `true` for Per Key mode, otherwise `false` pub fn is_per_key(&self) -> bool { self.index == 1 } pub fn is_disabled(&self) -> bool { self.index == 14 } } static MODES: Lazy> = Lazy::new(|| { vec![ Mode::new(14, "DISABLED", fl!("mode-disabled"), false, false), Mode::new(0, "SOLID_COLOR", fl!("mode-solid-color"), true, false), Mode::new(1, "PER_KEY", fl!("mode-per-key"), true, false), Mode::new(13, "ACTIVE_KEYS", fl!("mode-active-keys"), true, false), Mode::new(2, "CYCLE_ALL", fl!("mode-cycle-all"), false, true), Mode::new( 3, "CYCLE_LEFT_RIGHT", fl!("mode-cycle-left-right"), false, true, ), Mode::new(4, "CYCLE_UP_DOWN", fl!("mode-cycle-up-down"), false, true), Mode::new(5, "CYCLE_OUT_IN", fl!("mode-cycle-out-in"), false, true), Mode::new( 6, "CYCLE_OUT_IN_DUAL", fl!("mode-cycle-out-in-dual"), false, true, ), Mode::new( 7, "RAINBOW_MOVING_CHEVRON", fl!("mode-rainbow-moving-chevron"), false, true, ), Mode::new(8, "CYCLE_PINWHEEL", fl!("mode-cycle-pinwheel"), false, true), Mode::new(9, "CYCLE_SPIRAL", fl!("mode-cycle-spiral"), false, true), Mode::new(10, "RAINDROPS", fl!("mode-raindrops"), false, false), Mode::new(11, "SPLASH", fl!("mode-splash"), false, true), Mode::new(12, "MULTISPLASH", fl!("mode-multisplash"), false, true), ] }); ================================================ FILE: backend/src/nelson.rs ================================================ use serde::{Deserialize, Serialize}; use std::cmp; use std::collections::HashMap; use crate::Matrix; #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum NelsonKind { Normal, Bouncing, } #[derive(Debug, Deserialize, Serialize)] pub struct Nelson { pub missing: Matrix, pub bouncing: Matrix, pub sticking: Matrix, } impl Nelson { pub fn max_rows(&self) -> usize { cmp::max( self.missing.rows(), cmp::max(self.bouncing.rows(), self.sticking.rows()), ) } pub fn max_cols(&self) -> usize { cmp::max( self.missing.cols(), cmp::max(self.bouncing.cols(), self.sticking.cols()), ) } pub fn success(&self, layout: &HashMap) -> bool { let values: Vec<&(u8, u8)> = layout.values().collect(); for matrix in &[&self.missing, &self.bouncing, &self.sticking] { for (row, col) in values.iter() { if matrix.get(*row as usize, *col as usize).unwrap_or(false) { return false; } } } true } } ================================================ FILE: backend/src/rect.rs ================================================ #[derive(Copy, Clone, Debug)] pub struct Rect { pub x: f64, pub y: f64, pub w: f64, pub h: f64, } impl Rect { pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self { Self { x, y, w, h } } /// Test if `(x, y)` is a point in the rectangle pub fn contains(&self, x: f64, y: f64) -> bool { (self.x..=self.x + self.w).contains(&x) && (self.y..=self.y + self.h).contains(&y) } } ================================================ FILE: build.rs ================================================ fn main() { glib_build_tools::compile_resources( &["data"], "data/com.system76.keyboardconfigurator.gresource.xml", "compiled.gresource", ); } ================================================ FILE: data/com.system76.keyboardconfigurator.gresource.xml ================================================ icons/scalable/apps/com.system76.keyboardconfigurator.svg icons/scalable/status/launch-keyboard-not-found.svg ================================================ FILE: data/system76_launch_1_default.hex ================================================ :100000000C9458030C949F030C949F030C949F032F :100010000C949F030C949F030C949F030C949F03D8 :100020000C949F030C949F030C94912C0C94462BDE :100030000C94E11A0C949F030C949F030C949F035F :100040000C949F030C949F030C949F030C949F03A8 :100050000C949F030C94AF1A0C949F030C949F0371 :100060000C949F030C949F030C949F030C949F0388 :100070000C949F030C949F030C949F030C949F0378 :100080000C949F030C949F030C949F030C949F0368 :100090000C949F030C949F030C949F030C949F0358 :1000A0000C949F030C949F030C949F0395079E0749 :1000B000D10715085B08A508F108F408F908FC0841 :1000C0000109040909090C090F0912091509180980 :1000D0001B091E092109240927092C096809A409FB :1000E000A709AC09B709BA09C509C809D309D609CE :1000F000E109E409EF09F5096D0ABA0AB80BBE0B6C :10010000C30B5E0D5E0DCC0B5E0D5E0DD60BE70BCB :100110000D0C2C0C4D0C7F0CAE0CD60C090D010DEA :10012000540D98179817D217D2172518C819C8193F :10013000C81941181F19301930199B1C9B1CAE1C83 :10014000AE1CA41CAE1CAE1CAE1C9B1C9B1CA91C94 :10015000AE1CAE1CA91C33245A2401265A240126A5 :10016000A624C9240126BE25CE2529003A003B003D :100170003C003D003E003F00400041004200430083 :10018000440045004C0035001E001F0020002100E7 :100190002200230024002500260027002D002E0029 :1001A0002A002B0014001A000800150017001C007C :1001B00018000C00120013002F003000310039002D :1001C00004001600070009000A000B000D000E00D5 :1001D0000F003300340028004A00E1001D001B001E :1001E0000600190005001100100036003700380025 :1001F000E50052004B00E000E2000151E3002C005A :100200004D002C00E400E6000151500051004F0069 :100210004E00005C0100010001000100010001002E :1002200001000100010001000100010001000100C6 :1002300001000100010001000100010001000100B6 :100240000100C35CCB5CCA5C0100460001000100F8 :100250000100010001004A004E004B004D0001006A :100260000100010001000100010001000100010086 :1002700001005000510052004F0001000100010038 :10028000AE000100010001000100010001000100B9 :10029000010001000100010001004B00A900010064 :1002A0000100010001000100A8000100010001009F :1002B00001004A004E004D00AA00010001000100AB :1002C0000100010001000100010001000100010026 :1002D0000100010001000100010001000100010016 :1002E0000100010001000100010001000100010006 :1002F00001000100010001000100010001000100F6 :1003000001000100010001000100010001000100E5 :1003100001000100010001000100010001000100D5 :1003200001000100010001000100010001000100C5 :1003300001000100010001000100010001000100B5 :1003400001000100010001000100010001000100A5 :100350000100010001000100010001000100010095 :100360000100010001000100010001000100010085 :100370000100010001000100010001000100010075 :100380000100010001000100010001000100010065 :100390000100010001000100010001000100010055 :1003A0000100010001000100010001000100010045 :1003B0000100010001000100010001000100010035 :1003C0000100010001000100010001000100010025 :1003D0000100010001000100010001000100010015 :1003E0000100010001000100010001000100010005 :1003F00001000100010001000100010001000100F5 :1004000001000100010001000100000101010101E2 :1004100001010101020202020202020202030303BD :10042000030303030304040404040404050505058D :10043000050606060606070707070708080808094D :100440000909090A0A0A0B0B0B0C0C0C0D0D0D0EF9 :100450000E0E0F0F0F10101111111212131314148E :10046000151516161717181819191A1A1B1B1C1D03 :100470001D1E1E1F2020212222232424252626275C :100480002829292A2B2C2D2D2E2F3031323233348E :1004900035363738393A3B3C3D3E3F404142434494 :1004A00045464748494A4C4D4E4F50515354555676 :1004B00058595A5B5D5E5F616264656668696B6C22 :1004C0006D6F7072737577787A7B7D7E808283859D :1004D00087888A8C8E8F91939596989A9C9EA0A2DD :1004E000A3A5A7A9ABADAFB1B3B5B7BABCBEC0C2E7 :1004F000C4C6C9CBCDCFD1D4D6D8DBDDDFE2E4E7AB :10050000E9EBEEF0F3F5F8FAFDFF05010980A10132 :10051000850319012AB700150126B700950175104A :100520008100C0050C0901A101850419012AA0025E :10053000150126A002950175108100C0050109066C :10054000A1018505050719E029E715002501950892 :10055000750181020507190029EF1500250195F0A5 :10056000750181020508190129059505750191029A :10057000950175039101C00660FF0961A10109623F :10058000150026FF009520750881020963150026D5 :10059000FF00952075089102C005010906A101051B :1005A0000719E029E71500250195087501810295D5 :1005B00001750881010507190029FF150026FF00B4 :1005C000950675088100050819012905950575012D :1005D0009102950175039101C009025B00030100BE :1005E000A0FA090400000103010100092111010022 :1005F000012240000705810308000A0904010002E6 :1006000003000000092111010001222200070582D8 :100610000320000107050303200001090402000173 :1006200003000000092111010001226D000705846B :100630000320000A120110010000000884330100A9 :1006400001000102000150034C00610075006E00C2 :1006500063006800200043006F006E0066006900C0 :10066000670075007200610062006C006500200088 :100670004B006500790062006F0061007200640049 :10068000200028006C00610075006E0063006800A7 :100690005F0031002900000012035300790073004D :1006A000740065006D003700360000000403090483 :1006B00011241FBECFEFDAE0DEBFCDBF04B603FECC :1006C00027C08091080790910907A0910A07B0916F :1006D0000B078730904BA740B04BD1F4109208071E :1006E0001092090710920A0710920B0714BE84B7E4 :1006F000877F84BF0FB6F894A895809160008861C9 :1007000080936000109260000FBEE0E0F8E309956E :1007100013E0A0E0B1E0E2E9F0E602C005900D923E :10072000AA34B107D9F727E0AAE4B3E001C01D92CB :10073000A830B207E1F70E94A1030C9447300C9453 :100740000000CF93DF93CDB7DEB7AD970FB6F89427 :10075000DEBF0FBECDBF84B7877F84BF0FB6F894CE :10076000A89580916000886180936000109260007D :100770000FBE91E080E80FB6F894809361009093EB :1007800061000FBE85B7806885BF85B7806885BF6B :100790008EE09AE190934B0380934A030E948A2B48 :1007A0000E94302C8091E20084608093E200789473 :1007B0008091CB068823A1F01091E9001F709091E1 :1007C000EC00892F817090FD80E8182B1092E900D1 :1007D0008091E80083FD0E944D231F701093E90073 :1007E00082E084BD93E095BD9DE797BD80936E0048 :1007F00009E711E07FE7E72E71E0F72ED8018D9130 :100800008D010E946226E016F106C1F70FE711E0A4 :100810006DE8E62E61E0F62EF80181918F010E94CD :100820006226E016F106C1F7ECE4F3E088E593E018 :10083000A7EFB3E0119211921D921D928E179F07A0 :10084000C9F780E090E00E94642F8B3E9E4F11F02C :100850000E94781B1092D506EEEEF6E08EEF96E041 :100860002FEF3FEF219331938E179F07D9F7109207 :100870005D03E6E7F3E08FEF9FEF8193919323E031 :10088000E638F207D1F780E090E00E94642F8B3EBB :100890009E4F21F00E94781B0E94471245E050E0D5 :1008A0006CE170E082E097E00E944C2F809102079B :1008B0008C7F11F40E9447121092BA0080E280935C :1008C000B8001092BC008CE08CA701E010E09E0103 :1008D000245D3F4F4AEF50E360E87FEB8AE391E00D :1008E0000E94872997FD4CC01BA69E01255D3F4FA6 :1008F00042E154E362ED7FEB8AE391E00E948729B5 :1009000097FD3EC019821A821B821C829E012F5FB6 :100910003F4F48E054E362ED7FEB8AE391E00E94B1 :10092000EE1F97FD2DC009811A812B813C8101604A :1009300009831A832B833C8348E054E362ED7FEB09 :100940008AE391E00E94DF2997FD1AC004E813E3CF :1009500023E030E040E050E360E87FEB8AE391E0A1 :100960000E94DF2997FD0CC004E813E324E030E087 :1009700048E455EE62ED7FEB8AE391E00E94DF29C7 :100980001FEF1093460180914701909148010E940A :10099000932A0E9476201093150180911601909160 :1009A00017010E94932A10931101809112019091D6 :1009B00013010E94932A8091490190914A01A091CC :1009C0004B0189839A83AB8343E050E0BE016F5FA4 :1009D0007F4F80913A010E94502904E610E00E9466 :1009E00076208FE19EE40197F1F700C000000150EE :1009F0001109A9F70E94DA13AFE0B7E21197F1F7F6 :100A000000C00000EFE0F7E23197F1F700C000000E :100A10000E94DA138091F70380FF13C06FEF7FEF1E :100A200080E490E00E94982F6FEF82E490E00E94B3 :100A30007A2F6FEF7FEF80E090E00E94982F0E9466 :100A40008B1A80E490E00E94642F8C3E964739F424 :100A500082E490E00E945C2F91E0823009F090E007 :100A600090FD39C000E010E0780158EAE50EF11C75 :100A700058012CE1A20EB11CF801E659FE4FC590B9 :100A8000D4906D2DC8018D5B9F4F0E947A2F6C2DE5 :100A9000C8018C5B9F4F0E947A2F0E5F1F4FA016DC :100AA000B10651F78501EA14FB0411F7870130EA1A :100AB000E31632E0F306C1F681E00E94282B6CEECB :100AC00076E780E490E00E94982F62E082E490E074 :100AD0000E947A2F03C080E00E94282B60910005BD :100AE0007091010580910205909103050E94FC2AF6 :100AF00080E090E00E94642F8B3E9E4F11F00E9498 :100B0000781B82E090E00E945C2F8093EA030E94B1 :100B1000671B909359038093580383E090E00E94F1 :100B20005C2F682F70E080E090E00E947E1D609155 :100B300000057091010580910205909103050E94C6 :100B4000FC2A609158036068609358031091590320 :100B500084E090E00E947A2F612F81E290E00E9471 :100B60007A2F8FE291E090935B0380935A032224C3 :100B70002394312C8091CB06853009F053C040E49A :100B8000F42EEE24E39400E112E18091CB0685304F :100B900009F042C08091CB06843051F140E060E022 :100BA00080E00E944312E092E80310925C0388E127 :100BB00090E00FB6F894A895809360000FBEF09275 :100BC000600083B7817F846083BF83B7816083BF08 :100BD0007894889583B78E7F83BF0FB6F894A895D5 :100BE00080916000886180936000109260000FBE69 :100BF0008091CA06882309F4C8CF0E94DA13E7EF70 :100C0000F3E081919191892B09F090C7A3E0B4E0C2 :100C1000AE17BF07B1F7B9CF0E94AD1F0E946D118B :100C20001092E8030E94DA13882359F08FB7F894E2 :100C30004091E4035091E5036091E6037091E7036E :100C40008FBFABEEB3E0E7EFF3E0E12CF12C4E2DDC :100C5000A190B1908D919D918A259B25009709F4D3 :100C6000AEC010E0CC24C394D12C9C012C213D219A :100C7000232B09F49EC019A34AA3AC20BD2081E018 :100C8000A114B10409F480E08BA30E94D51A8160FD :100C9000782F9DA38CA349A15AA16BA18DA10E947D :100CA000A310F701EE0FFF1FE551FC4F80819181EA :100CB000C826D926D182C082AB2889F08EE08E9DCD :100CC000F0018F9DF00D1124E753FE4FE10FF11D50 :100CD00080818F3F21F08DA7DD24D39401C0D12CDA :100CE000C0905D03ED2CF12CC7018C0D911D09976F :100CF0009CF108E010E00E191F09B7016F5F7F4FEC :100D0000635A7C4FA8018EE593E00E942F30B70113 :100D1000675F7F4F635A7C4FA80186E693E00E948D :100D20002F30A801440F551FB701660F771F675E6C :100D30007F4F635A7C4F86E793E00E942F30B701C4 :100D40006F5E7F4F635A7C4FA8018EE693E00E944E :100D50002F30CA94C0925D0380915D0390E0EDA5B1 :100D6000AE2FB0E09D01220F331F235E3D4FAA0F2F :100D7000BB1FBD01625E7D4F41E0480F9D15B0F481 :100D800090E0FC01E35AFC4FD9015C915183DB01F7 :100D90005C915187BDA5B18B880F991FFC01E35A67 :100DA000FC4F128E118E91E0842FE6CF80935D036D :100DB0001EC01F5FCC0CDD1C1E3009F056CF2FEF7C :100DC000E21AF20A36E0E316F10409F040CF8FEFA1 :100DD0008EA38FA318A60E94D51A8160782F9AA798 :100DE00089A74EA15FA168A58AA50E94A310409182 :100DF00086035091870360918803709189032FB710 :100E0000F8948091E4039091E503A091E603B091FA :100E1000E7032FBF841B950BA60BB70B2FB7F894D6 :100E2000C090E403D090E503E090E603F090E70380 :100E30002FBFC0928603D0928703E0928803F0927E :100E4000890360915D03EDE5F3E0462F50E0442413 :100E50004A94542C612C712C481A590A6A0A7B0A4C :100E6000651799F0218D328D4901A12CB12C4814C0 :100E700059046A047B0410F4415004C0280F391F40 :100E8000328F218F5F5F3296EBCF40935D0380916D :100E9000E803811108C010910207812F837019F0B7 :100EA0001695169501C010E080911A018130E9F085 :100EB00038F0823009F4DFC3833009F4E9C305C494 :100EC00010924201C092FE06D092FF06E092000707 :100ED000F092010789E2EDE5F3E0A5EDB6E00190BF :100EE0000D928A95E1F781E0D0C380911901181322 :100EF0000DC020910207237030E04091180150E0AE :100F000081E02417350719F480E001C081E0817089 :100F100080934401412F50E04832510508F099C3B5 :100F2000FA01EA5AFF4F0C942930882309F491C33F :100F300040E060E080E00E9443128BC300914201D8 :100F400081E1089F002D112421E1F22EF00E54E5DD :100F50005F1510F494E5F92E609103077091040772 :100F6000809105070E94E212E62ED72EC82E0F159B :100F700090F4E02FF0E0DF01AB53BD4F8C919091E6 :100F80004301982331F02C2D4E2D6D2DCF010E9461 :100F900045120F5FECCF81E063E56F1508F05AC38F :100FA00058C30091420181E1089F002D112481E185 :100FB000F82EF00E74E57F1510F4B4E5FB2ED090FA :100FC0000407E0900507C0900307B6018E2D0E942C :100FD000E212B62EA72E782E609106076C0D7D2D9D :100FE0008E2D0E94E212E62ED72EC82E0F15B8F4D1 :100FF000802F90E0FC01EB53FD4F308120914301A5 :10100000232359F030FF04C02C2D4E2D6D2D03C02D :10101000272D4B2D6A2D0E9445120F5FE7CF81E0EF :1010200093E59F1508F016C314C30091420181E1B6 :10103000089F002D1124A1E1DA2ED00EA4E5AD15F4 :1010400010F4F4E5DF2EB0900407A090050720917E :101050000607E0E4CE2E3C2D329F312D1124C32E05 :101060000D1518F5E02EF12CF701EB53FD4F908193 :10107000809143018923B9F0F701EE0FFF1FE25E73 :10108000FD4F808182958F70609103078C9D600D6C :1010900011247B2D8A2D0E94E212462F282F672FC4 :1010A000C7010E9445120F5FDBCF81E053E55D155C :1010B00008F0D0C2CEC20091420181E1089F002D0C :1010C000112461E1D62ED00E64E56D1510F454E5BF :1010D000D52EB0900407A09005072091060740E4A4 :1010E000C42E7C2D729F712D1124C72E0D1538F53D :1010F000E02EF12CF701EB53FD4F908180914301DD :101100008923D9F0F701EE0FFF1FE35EFD4F6081E9 :10111000C69EB001112435E0759567953A95E1F7C3 :1011200080910307680F7B2D8A2D0E94E212462FC3 :10113000282F672FC7010E9445120F5FD7CF81E08C :1011400093E59D1508F086C284C20091420181E1B9 :10115000089F002D112491E1F92EF00EA4E5AF15A2 :1011600010F484E5F82ED0900307E0900407C090B7 :101170000507609106076695669566958091FE065F :101180009091FF060E94D8120E945D12805887FD40 :101190008195880F282F3C2D239F212D1124822FEC :1011A0006D2D7E2D0E94E212E62ED72EC82E0F1531 :1011B00090F4E02FF0E0DF01AB53BD4F8C919091A4 :1011C0004301982331F02C2D4E2D6D2DCF010E941F :1011D00045120F5FECCF81E053E55F1508F03AC28E :1011E00038C28BE89FE002C08FE59FE00E94732128 :1011F00031C284E690E102C085E490E10E941721AB :1012000029C28AE290E102C08EE090E10E949B2018 :1012100021C28DE59FE0EACF84E59FE0E7CF8BE434 :101220009FE0E4CF80E39FE0E1CF81E29FE0EECF5B :101230008FEA92E1E3CF8DEF9FE0E0CF89EE9FE070 :10124000E5CF83EF9EE005C081EC9EE002C083E81D :101250009EE00E94BD21FEC181111EC06091060763 :1012600020E1620F08F46FEF8091FE069091FF0677 :101270000E94D8126AE070E00E940130892B09F0C8 :10128000E8C10E943C2F64E570E00E941530609137 :1012900043010E947213DDC18091420191E1899F57 :1012A000802D112401E1080F053508F004E5E82E32 :1012B000F12CC02ED12CEC14FD040CF0C7C16091B0 :1012C0004301C7010E9472136FEFE61AF60AF3CFCB :1012D00081111EC06091060720E1620F08F46FEFD4 :1012E0008091FE069091FF060E94D81265E070E0A2 :1012F0000E940130892B09F0ACC10E943C2F64E5AB :1013000070E00E941530609143010E94B813A1C1A2 :101310008091420191E1899F802D112401E1080F04 :10132000053508F004E5E82EF12CC02ED12CEC1484 :10133000FD040CF08BC160914301C7010E94B813FA :101340007FEFE71AF70AF3CF8CE79EE002C086E74B :101350009EE00E941E227EC18091D50621E0382F9A :10136000321B08F430E0832F6DE57EE03BC06DE575 :101370007EE037C08091D50621E0582F521B08F43B :1013800050E0852F65E27EE02DC065E27EE029C059 :101390008091D50621E0682F621B08F460E0862F5B :1013A00063EF7DE01FC063EF7DE01BC08091D50639 :1013B00021E0782F721B08F470E0872F6BED7DE041 :1013C00011C06BED7DE00DC08091D50621E0382F76 :1013D000321B08F430E0832F65EC7DE003C065EC40 :1013E0007DE080E00E948A2235C18091DE03811178 :1013F00025C069EC71E040E050E0942F9295907F19 :1014000020E030E0FB01E20FF31F8081843538F4E7 :10141000E82FF0E0E657FC4F892F822B80832F5F67 :101420003F4F2E30310571F74F5F5F4F625F7F4F47 :101430004630510511F781E08093DE0300914201AF :1014400081E1089F002D1124B1E1DB2ED00E54E57F :101450005D1510F4A4E5DA2E609100057091010588 :1014600080910205909103050E94F527C82E609196 :10147000030770910407809105070E94E212B62EBF :10148000A72E782E0D1518F5E02EF12CF701EB5351 :10149000FD4F9081809143018923B9F0F701E65710 :1014A000FC4F6081462F4F7062956F708C2D0E94AB :1014B0000F12029720F420E040E060E003C0272DE7 :1014C0004B2D6A2DC7010E9445120F5FDBCF81E0D3 :1014D00063E56D1508F0BEC0BCC00091420181E11A :1014E000089F002D1124F1E17F2E700E74E5771511 :1014F00010F4E4E57E2EEE24EA94F12C0715A0F515 :10150000E02FF0E0DF01AB53BD4F9C918091430190 :10151000892341F1DF01AA0FBB1FAE0FBF1FAC5FD4 :10152000BB4FAC901196CC90119712968C919091E4 :101530000507A99E50011124C99E60011124899FAD :10154000C0011124B7010E940130262FC501B70147 :101550000E940130462FC601B7010E940130CF0121 :101560000E9445120F5FCACF81E093E5971508F0FE :1015700071C06FC0D090420191E1D99ED02C11244E :1015800001E10D0D053508F004E5811106C08091DB :10159000E3038F5F8093E30304C01092E303109290 :1015A000E2038091E303811147C08091E203883018 :1015B00029F41092E1031092E2033EC0A82FB0E09C :1015C000AA0FBB1FA357BE4FEC9111969C91AEE0A2 :1015D000EA9FF0011124E753FE4FE90FF11D9081BE :1015E0009F3F21F09093DF0391E001C090E0909342 :1015F000E1038F5F8093E2031FC0ED2CF12CF70114 :10160000EB53FD4F9081809143018923A1F06091BC :10161000E3036D0D2091E103EFEDF3E080E77FEF51 :1016200090E092130CC00E94E212462F282F672FE1 :10163000C7010E944512D394D016F8F207C0319129 :10164000D31202C08FEF70E09F5FEBCF81E00435D3 :1016500008F080E0909142019F5F909342018111D8 :1016600034C082E080931A018091440181112DC021 :10167000112351F02AC01093190180910207837041 :10168000809318010E94821083E080931A011DC08C :101690004091FE065091FF0660910007709101078E :1016A0002FB7F8948091E4039091E503A091E603AD :1016B000B091E7032FBF841B950BA60BB70B409788 :1016C000A105B10510F010921A010E946D119091C0 :1016D000E903891721F00E946D118093E90380913D :1016E000CB06843009F046CA83E08093E9008091FC :1016F000E80082FF3FCA8091E80085FF21C00E9478 :10170000A92B81111BC000E210E0FE0131967F0180 :1017100008C08091F100D7018D937D01015011091E :1017200069F08091E80085FDF4CF8091E8008B7727 :101730008093E8000E94A92B882399F391E001C0CF :1017400090E08091E8008B778093E800992309F47A :1017500011CA81E08A83E9818E2F90E0FC013197E4 :10176000E331F10508F0AAC1E258FF4F0C9429308B :1017700086E78B838CEE8C8381E012C14EE150E0D2 :1017800062E571E004C04EE150E064E671E0CE0134 :1017900003960E94383091C180910505882309F491 :1017A0008DC11A8281E08093040588C18B818430C9 :1017B00008F084C16C81663008F080C14D814E30E4 :1017C00008F07CC10E940F128E839F8376C19B819B :1017D000943008F073C10C81063008F06FC18D8120 :1017E0008E3008F06BC1FE806F81BCE10B9F8001E1 :1017F0001124E8EA9E9F000D111D1124080F111DF0 :10180000080F111D0D5B1F4FC8010E947A2F6F2D0D :10181000C80101960E947A2F50C18091050581115F :101820004DC18B81803F49F0813F49F0823F49F0B3 :10183000833F09F043C1E3E005C0E0E003C0E1E01D :1018400001C0E2E025E0E29FF0011124E55EFE4FD9 :1018500083818C8380EBA4C08091050581112EC10A :101860008B819C81903B08F090EB803F49F0813F59 :1018700049F0823F49F0833F09F020C1E3E005C011 :10188000E0E003C0E1E001C0E2E035E0E39FF00109 :101890001124E55EFE4F9383A8C080910505811158 :1018A0000DC1EB81E43558F0E03FC1F0E13FC1F0FC :1018B000E23FC1F0E33F09F001C1E3E014C0F0E012 :1018C000CF01880F991FE80FF91FEC5FFB4F818153 :1018D0008C8380818D8382818E83EFC0E0E003C0A2 :1018E000E1E001C0E2E055E0E59FF0011124E55E92 :1018F000FE4F81818C8382818D831E82DEC0809128 :1019000005058111DBC0EB818D819C81E43558F0A8 :10191000E03FB1F0E13FB1F0E23FB1F0E33F09F069 :10192000CDC0E3E012C02E81F0E0AF01440F551F9F :10193000E40FF51FEC5FFB4F808391832283BDC0D2 :10194000E0E003C0E1E001C0E2E065E0E69FF00115 :101950001124E55EFE4F9183828347C08091050587 :101960008111ACC0EB81E43008F0A8C02E2F30E02C :1019700075E0E79FF0011124E55EFE4F908196959A :101980009695EDE9F1E0419194130CC08C8385E0CC :10199000829FF001839FF00D1124E55EFE4F84814C :1019A0008D838BC08F5F8F3071F788C08091050564 :1019B000811184C0EB81E43008F080C0AC81AF308D :1019C00008F07CC02D8185E0E89FF0011124E55EE0 :1019D000FE4FB0E0A356BE4F8C91982F990F990FF0 :1019E00080818370892B808324831A826091000513 :1019F0007091010580910205909103050E94FC2AD7 :101A00005DC080910505811159C081E00E94282B9D :101A100054C086E08B838EE08C8387EFE82E83E0D2 :101A2000F82E16E0A0E0B4E040E050E0B03258F507 :101A3000F70160817181C101042E02C0880F991FD6 :101A40000A94E2F7682379238B2F90E091010A2E04 :101A500001C0220F0A94EAF7672B51F061E070E0B1 :101A60006C0F7D1F860F971FFC013081232B0AC04E :101A700061E070E06C0F7D1F860F971F2095FC01C1 :101A8000308123232083AF5FA83010F0BF5FA0E038 :101A90004F5F5F4F4E30510549F61150F2E0EF0EA7 :101AA000F11C1111C1CF09C00E94AD1F81E09B81C3 :101AB000911101C080E0809303041A828091CB06CB :101AC000843009F51091E9001F709091EC00892F86 :101AD000817090FD80E8182B82E08093E90080916E :101AE000E80080FF0DC040E050E060E270E0CE0111 :101AF00001960E94C21F8091E8008E778093E800D3 :101B00001F701093E90080910405882311F40C9450 :101B1000BA052FEF30E752E0215030405040E1F756 :101B200000C000000E948B1A0C94BA0509BD19BDB3 :101B300009B400FEFDCF8091D8008F7D8093D8003E :101B40008091E00082608093E0008091E00081FD60 :101B5000FCCF0E94AD1F0C94C505EBE0F5E096E0CC :101B6000E730F90729F08183608342833396F7CF0A :101B70000895FC01EE0FFF1F8E0F9F1FFC01E55F14 :101B8000FA4F6183408322830895EF92FF920F936F :101B90009701201B31092F3F310519F010F02FEF6D :101BA00030E02095382F320F08F43FEF832F0F914C :101BB000FF90EF900895EF92FF920F939701201BF3 :101BC00031092F3F310519F010F02FEF30E0322F9F :101BD0003095482F430F08F44FEF842F620F0F9179 :101BE000FF90EF900895EF92FF920F93972F093493 :101BF00038F4B701601B71096F3F710519F010F0DF :101C00006FEF70E0485F5F4F4131510540F0A9012F :101C1000485F5F4F4131510510F06FEF70E0609504 :101C2000482F460F08F44FEF842F37FF02C02D5F77 :101C30003F4F359527953595279560910307620F9E :101C4000792F0F91FF90EF900895EF92FF920F93ED :101C5000E00EF11CF90137FF03C0F195E195F109A0 :101C600024E0EE0FFF1F2A95E1F7EF3FF10519F091 :101C700014F0EFEFF0E09A0157FF03C03195219582 :101C8000310994E0220F331F9A95E1F72E173F0791 :101C90000CF4F901EE0DFF1DEF3FF10519F010F006 :101CA000EFEFF0E02E2F2095382F320F08F43FEFA2 :101CB000832F0F91FF90EF900895EF92FF920F9373 :101CC000970195E0099F200D311D11242F3F31050B :101CD00019F010F02FEF30E02095382F320F08F474 :101CE0003FEF832F0F91FF90EF90089522E8241B80 :101CF00008F420E0620F08954095282F429F412D5F :101D00001124842F08950F931F9310E0F801EE0F14 :101D1000FF1FE35EFD4F9081905797FD9195000F57 :101D2000111FF801E25EFD4FE081F0E0B097DF01A6 :101D3000AA0FBB1F8D010E0F1F1F2003D001219F73 :101D4000B00D1124E8E3F0E0E91BF10997FDF395EC :101D50009F01220F331F89010E0F1F1F40039001A7 :101D6000419F300D11242A0F3B1F37FF02C021581D :101D70003F4F220F232F221F330B620F1F910F9112 :101D800008950F931F93522F10E0F801EE0FFF1FDD :101D9000E25EFD4FE081F0E0B097EE0FFF1F9F0184 :101DA0005203D001539FB00D1124000F111FF801F1 :101DB000E35EFD4F008110E000571109000F111F75 :101DC00040039001419F300D11242A0F3B1F37FF24 :101DD00002C021583F4F220F232F221F330B620FC7 :101DE0001F910F9108950F931F93522F10E0F80148 :101DF000EE0FFF1FE25EFD4FE081F0E0B0979F0124 :101E00005203D001539FB00D1124000F111FF80190 :101E1000E35EFD4F008110E000571109400390017F :101E2000419F300D11242A0F3B1F37FF02C021585C :101E30003F4F220F232F221F330B620F1F910F9151 :101E40000895EF920F931F9393E0099F800111244F :101E5000159507956E2D600F1F910F91EF900895C6 :101E6000A22F50E0FA01EE0FFF1FE25EFD4F9081BE :101E7000905297FD9195440F551FFA01E35EFD4F77 :101E80003081232F30E02A1B3109290F311D97FDA6 :101E90003A95620F0895E42FF0E0EE0FFF1FE25E27 :101EA000FD4F6081621B0895E42FF0E0EE0FFF1FED :101EB000E35EFD4F6081621B0895622F0895E42F59 :101EC000F0E0EE0FFF1FE35EFD4F408134EE439FD5 :101ED000412D1124E82FF0E050E0445E5F4FDA011D :101EE000A21BB1099D01B7FF03C0319521953109AE :101EF00093E0220F331F9A95E1F7AF01421B530B7A :101F00009A0157FF02C020E030E0582F259F212D75 :101F10001124822F0895E42FF0E0EE0FFF1FE35EFF :101F2000FD4F408134EE439F412D1124E72FF0E017 :101F300050E0445E5F4FDA01A21BB1099D01B7FF7B :101F400003C031952195310993E0220F331F9A95F3 :101F5000E1F7AF01421B530B9A0157FF02C020E08B :101F600030E0279F212D1124722F0895FC019B0141 :101F7000009721F477FF2BC080E80895AC0197FF0C :101F800004C044275527481B590BB901640F751F1E :101F900037FD0CC0241B350BC901A5E0880F991F24 :101FA000AA95E1F70E94153080E20CC0CB0165E0F4 :101FB000880F991F6A95E1F7BA01621B730B0E94A3 :101FC000153080E6861BF7FF03C08195089580E0F9 :101FD0000895EF920F93CF93DF93D72FC82FC901A6 :101FE0000E19BA010E94B60F602F681B7D2F8C2F2F :101FF000DF91CF910F91EF9008950F93CF93DF93DF :10200000D72FC82FC901BA010E94B60F682F600FE1 :102010007D2F8C2FDF91CF910F910895EF920F9329 :102020001F93CF93DF93D62FC72F182FC9010E19F7 :10203000010FBA010E94B60F081B202F219F212DEE :102040001124822F6D2F7C2FDF91CF911F910F9143 :10205000EF900895EF920F931F93CF93DF93D62FB6 :10206000172FC82FC9010E19070FBA010E94B60F0A :10207000702F781B719F712D11246D2F8C2FDF9184 :10208000CF911F910F91EF900895FF920F931F939F :10209000CF93DF93F62ED72F182FC901C12FC01B66 :1020A000BA010E94B60F982F990F890FC81B2C2FC9 :1020B000219F212D1124822F6F2D7D2FDF91CF9114 :1020C0001F910F91FF900895FF920F931F93CF934D :1020D000DF93F62E172FD82FC901C72FC01BBA01C7 :1020E0000E94B60F982F990F890F7C2F781B719F34 :1020F000712D11246F2D8D2FDF91CF911F910F9195 :10210000FF9008956A9A8EB18B7F9EB194602FB72D :10211000F894EBE0F5E036E0E730F30761F0319159 :1021200048E09EB937FF8EB9330F000000C08EB96A :102130004A95B9F7F0CF2FBF8FE292E00197F1F700 :1021400000C0000008951F93CF93DF93CDB7DEB793 :1021500067970FB6F894DEBF0FBECDBF342F4B8B01 :10216000252F5C8B6D8B7E8B8F8B4E895F896111E8 :102170001092A00686E0FE013D96DF01982F1D9289 :102180009A95E9F73D872E876F87598B488BDE013B :10219000179601900D928A95E1F7CE0107960E945D :1021A000FE1D81113EC086E0FE013796DE011196CC :1021B00001900D928A95E1F7FF81E8856A857B851C :1021C0006115710531F0EF3F31F481E0FF3F19F403 :1021D00003C081E001C080E080FD23C0209135066E :1021E00030E0C9010196877099274091660650E05A :1021F0008417950779F1F983EA837D836C8396E0F0 :10220000929FD001939FB00D1124AA5CB94FFE019B :10221000319601900D929A95E1F7809335060E94D0 :10222000881D16E080916606909135068917F9F0B1 :10223000189FC00111248A5C994F0E94FE1D8823BB :10224000B1F08091660690E001968770992780939F :102250006606E8CF0E94AD1F109235061092660602 :10226000EFE2F6E086E0DF011D928A95E9F76796D6 :102270000FB6F894DEBF0FBECDBFDF91CF911F9197 :10228000089520910B0630910C062817390771F03C :1022900090930C0680930B06E0915A03F0915B0338 :1022A000309721F00084F185E02D09940895209164 :1022B000090630910A062817390771F090930A062B :1022C00080930906E0915A03F0915B03309721F067 :1022D0000680F781E02D09940895E0915A03F0916A :1022E0005B03309721F00190F081E02D099480E0AC :1022F0000895EF92FF920F93CF93DF93C42FD22FC5 :10230000FC0182818823D1F040930D060E94D51AEA :10231000909308068093070680E28C0F883008F0BF :1023200078C0C77081E001C0880FCA95EAF7DF91D5 :10233000CF910F91FF90EF900C94CF2D80910D06CF :10234000481356C020910706309108064FB7F894FD :102350008091E4039091E503A091E603B091E70337 :102360004FBF821B930B883C910508F041C0CD17ED :10237000C9F080E28C0F883040F4C77081E001C062 :10238000880FCA95EAF70E94C42D80E28D0F88302D :1023900048F481E09D2F977001C0880F9A95EAF765 :1023A0000E94CF2D093319F0E12CF12C03C080E5F8 :1023B000E82EF12C802F0E94352EE114F10451F00B :1023C0008FEC97E00197F1F700C0000091E0E91A67 :1023D000F108F3CF802F0E94D92D80E28D0F883035 :1023E000C0F4D77081E001C0880FDA95EAF70AC01F :1023F00080E28C0F883068F4C77081E001C0880FDC :10240000CA95EAF7DF91CF910F91FF90EF900C946E :10241000C42DDF91CF910F91FF90EF9008950F930E :102420001F93CF93DF93C42FD0E0CC0FDD1F2CE19F :10243000629FC00DD11D112438EA839FC00DD11DAC :102440001124CD5BDF4FCE010E945C2F082F10E0DE :10245000102F0027CE0101960E945C2F9801282B97 :10246000C901DF91CF911F910F910895462F8430BC :1024700038F4763028F46E3018F4672F0C940F126D :1024800080E090E008950C94AD0D0C94B90DE2E05D :10249000F7E08DE3808380914C0190914D01A091F4 :1024A0004E0181839283A3838FE7848345E050E0CC :1024B0006CE170E0CF010C946A2F482F982F46FDF5 :1024C0009095E92FEF739F7046FD9F5FE295EF7047 :1024D000EE0FF0E0E455FE4F2181299F802D212D44 :1024E000112482958F702295207F822B3081982F26 :1024F000930F892F47FD819580580895BC01823044 :10250000910508F40895613E8EE1780748F49B0137 :1025100095E0369527959A95E1F748E0420F01C07E :102520004FEF91E0242F30E0290F311D359527958D :10253000229FF001239FF00DF00D11246E177F07ED :1025400018F44FEF420F04C02F3F39F091E0920F83 :10255000491740F78FEF890F08958FEF08950F9374 :10256000CF93DF93D72FC82F47FD4195E8E3F0E0E5 :10257000CF01841B910947FD9395889FB001899FE6 :10258000700D700D1124229FC001239F900D900D9E :102590001124860F971F0E947E12682F660F860FE8 :1025A000682F600F7D2F8C2FDF91CF910F910895B1 :1025B00020E030E0869F212D969F200D311D1124B3 :1025C000C9010895CF92DF92EF92FF920F931F936C :1025D000CF93DF93F62E472FE82FF0E0711106C05E :1025E000E65FFB4F8491782F682F73C0272F30E070 :1025F000E65FFB4FE491FE2F0E2F10E056E0659F43 :10260000C0011124CFEFD0E0BE010E9401305BEA8F :102610005603C001579F900D11248F0D911D8F0DF2 :10262000911D982F990F980F7E01E21AF30AE09EF0 :10263000D001E19EB00DF09EB00D11248B2F499F6B :10264000A0011124452F55277E01E41AF50AE09ECA :10265000A001E19E500DF09E500D11246E01C91A8B :10266000D108C29E7001C39EF00CD29EF00C1124C2 :102670002F2D3327C21BD30BC09F9001C19F300D5C :10268000D09F300D1124932F6230710591F048F4E2 :1026900061157105E1F061307105B9F49E2FE52FE8 :1026A00016C06430710569F040F06630710579F04C :1026B0000CC09E2FEB2F832F0AC0EB2F8F2F952F4F :1026C00006C09B2F8E2FE32F02C09B2F852F7E2FBE :1026D000692FDF91CF911F910F91FF90EF90DF90C5 :1026E000CF900895DF92EF92FF920F931F93CF93B5 :1026F000DF93EC01FC01EB53FD4F9081692381F1E5 :10270000D09004070091050710910307E12EF12CEA :102710000E943C2F282FC7018C549F4F68E671E020 :102720000E9415308E199F0997FD03969595879500 :10273000959587952370612F289F600D11247D2D1D :10274000802F0E94E212462F282F672FCE01DF91A3 :10275000CF911F910F91FF90EF90DF900C94451255 :10276000DF91CF911F910F91FF90EF90DF9008952F :102770001F93CF93DF93FC01EB53FD4F2081622326 :10278000A9F0EC010E943C2F182F0E943C2F612FD2 :10279000782F809105070E94E212462F282F672F7D :1027A000CE01DF91CF911F910C944512DF91CF9113 :1027B0001F9108959F92AF92BF92CF92DF92EF92B6 :1027C000FF920F931F93CF93DF930CE413E089E7FD :1027D000E82E81E0F82EC0E0D0E0912CCC24C39408 :1027E000D12CB701D7018C91F894E82FE295EF70C6 :1027F000F0E021A18F70A60102C0440F551F8A95F9 :10280000E2F7CA01922F982B91A392A18095892378 :1028100082A3789400C0EFE7F1E020E030E0A12C43 :10282000B12C4191842F82958F7090E0DC019096BD :102830008C9190E04F7002C0959587954A95E2F78C :1028400080FD08C0C601022E02C0880F991F0A949D :10285000E2F702C080E090E0A82AB92A2F5F3F4F3C :102860002E303105F1F6BFEFEB1AFB0AFB01808138 :102870000E946226C530D10519F0F0E5FA95F1F70E :10288000D8018D919C911197A816B90621F0AD92AF :10289000BC9281E001C080E0982A21960E5F1F4F14 :1028A000C630D10509F09DCF992049F081E0809391 :1028B00008050E94D51A909307058093060580911C :1028C0000805882309F445C02091060530910705C5 :1028D0004FB7F8948091E4039091E503A091E6034B :1028E000B091E7034FBF821B930B069790F1809145 :1028F0004C0390914D039093F8038093F7038091DC :102900004E0390914F039093FA038093F9038091C3 :102910005003909151039093FC038093FB038091AB :102920005203909153039093FE038093FD03809193 :10293000540390915503909300048093FF0380917A :1029400056039091570390930204809301041092D0 :1029500008058091090590910A05883EB3E09B0720 :102960006CF010920A051092090584E191E00E9432 :102970005A2A80E191E00E945A2A05C0019690935C :102980000A0580930905892DDF91CF911F910F9141 :10299000FF90EF90DF90CF90BF90AF909F90089501 :1029A0008F929F92AF92BF92CF92DF92EF92FF925F :1029B0000F931F93CF93DF9300D000D01F92CDB71A :1029C000DEB7FC018081918123813481232B31F09A :1029D0009F3F31F491E08F3F19F403C091E001C0B3 :1029E00090E090FD05C57F0185E0DE011196019024 :1029F0000D928A95E1F7F701228189819A8122233C :102A000049F00E943C1C182F682F89819A810E94EE :102A1000DE1C03C00E94B21C182F69817A81812FAD :102A20000E9436128C018091030481111EC2033C66 :102A3000FCE51F0709F446C028F401153CE513071F :102A400051F052C00A3C8CE5180749F10B3C9CE55B :102A5000190799F049C0F7018281882309F405C25A :102A600080910207837029F08C698093020710928D :102A70001A0181E080930505F8C1F701828188235E :102A800009F4F3C180910507EAEBF1E024EB31E0B2 :102A900092919817A8F02E173F07D1F722C0F7019F :102AA0008281882309F4E1C180910507E4EBF1E01C :102AB0002AEB31E02E173F07A1F091918917D0F74B :102AC000892F0FC0F7018281882309F4CEC180913C :102AD0000507811103C08091390103C0809339013A :102AE00080E00E94112BC1C1043FFCE51F0799F44F :102AF00006E221EE40EE64EF7CE509C0083D9CE56E :102B0000190711F506E221EE41EE68ED7CE5C701FB :102B10000E947911AAC1053F2CE5120708F042C1B5 :102B2000093D3CE5130731F407E225EE45EE69ED7A :102B30007CE5EDCF0A3D8CE5180701F708E221E0BE :102B400045EE6AED7CE5E3CFF7018281882309F445 :102B50005EC110920D060230FCE51F0708F441C16A :102B600006312CE5120738F098012B5F3C452930DF :102B7000310508F036C10E94671B9093590380937A :102B8000580300313CE5130709F4C3C008F041C005 :102B900008309CE5190709F49AC0F0F40430FCE50C :102BA0001F0709F487C068F402303CE5130709F4F5 :102BB00077C003301C4509F0E5C08091580382605E :102BC00076C006309CE5190709F46EC008F07BC09A :102BD0008091580388606BC00C30FCE51F0709F436 :102BE00085C068F40A303CE5130709F474C008F0A6 :102BF00079C00E94AD1F80915803806858C00E3084 :102C00009CE5190709F476C008F07FC0809158034D :102C10008BC00C3FFCE51F0709F44FC018F50331CA :102C20003CE5130709F47DC078F401319CE51907F0 :102C300009F473C002311C4509F0A4C00E94AD1F05 :102C4000809158038F7733C00531FCE51F0709F4E5 :102C500072C008F486C00B3F1C4509F093C08091F8 :102C600059033EC001158DE5180709F45FC058F4FB :102C70000E3FECE51E0709F444C008F43FC0809104 :102C8000590382602DC002302DE5120709F475C08A :102C900008F45DC003301D4509F074C060E06EC0EB :102CA00080915803816003C08091580380618093B4 :102CB000580368C08091580311C080915903826005 :102CC000809359035FC0809158038062F0CF809158 :102CD00058038064ECCF8091580388608460E7CF0C :102CE0008160EECF809158038E7FE1CF80915803B1 :102CF0008D7FDDCF80915803877FD9CF8091590395 :102D000018C0809159038D7FDBCF809158038F7E4F :102D1000CECF809158038F7DCACF809158038F7B8F :102D2000C6CF80915803877F8B7FC1CF8091590395 :102D30008D7F8E7FC5CF8091580382FB222720F99B :102D400091E0922790FB82F990FB83F9B0CF8091BC :102D50005903982F909591708E7F892B90FB81F964 :102D6000AFCF0E94AD1F8091580387FB222720F927 :102D700091E0922790FB87F99ACF61E08EE090E096 :102D80000E947A2F609158031091590384E090E0DB :102D90000E947A2F612F81E290E00E947A2F0E9498 :102DA000AD1F63C0063FECE51E0731F406E221EEDD :102DB00042EE66EF7CE5ABCE063FFCE51F0730F444 :102DC00007E225EE44EE65EF7CE5A1CE073F2CE55A :102DD000120709F0B9CE07E225EE46EE67EF7CE573 :102DE00096CE06313CE5130719F58091A1068A7A43 :102DF00091E009F490E090930E06882311F065E3CA :102E000001C069E28FE096E00E94321B0EC00631DD :102E10001C4509F048C080910E06882309F4E6C2DB :102E200065E38FE096E00E940A1B0E94E81B1DC02C :102E30009801235C3C4524313105B8F001159CE52F :102E4000190731F00F3D1C4571F50E94781B0DC02C :102E50000E94AD1FFFE70AE116E0F150004010406C :102E6000E1F700C000000E948B1A80919E068770D7 :102E700009F4BEC2F7018281882309F4B9C282E055 :102E80000F900F900F900F900F90DF91CF911F91A7 :102E90000F91FF90EF90DF90CF90BF90AF909F90F9 :102EA0008F900C94441DF70100811181882349F013 :102EB000C8010E943C1CD82E682FC8010E94DE1C4D :102EC00004C0C8010E94B21CD82EB8018D2D0E94EA :102ED00079268C01982EF701B280A580A2949FE0FC :102EE000A92280919E06877099F0BB2089F0812FDE :102EF000807F803421F080E2800F883048F082E0CB :102F00000E94441D80919E068770DD24D394811118 :102F1000D12CC12EC2948FE0C8228C2D90E08C3031 :102F2000910508F035C2FC01EF56FF4F0C94293093 :102F3000812F807F1F70882311F01295107FBB2096 :102F4000B9F0112309F40FC280E2800F883010F02D :102F5000911006C08091A106182B1093A10605C000 :102F60008091A006182B1093A0060E94E81BFBC1BD :102F7000802F0E94D92D112309F40AC2005E1095FA :102F8000083010F0911006C08091A106182310930C :102F9000A10605C08091A00618231093A0060E94E8 :102FA000E81BF6C1812F807F1F70803211F01295CF :102FB000107F992021F0F1E09F16E1F02AC0BB209C :102FC00081F08091A206AA2051F001E0A01207C072 :102FD000182B181709F4DCC11093A206D9C1812B54 :102FE00010C0AA2021F021E0A21609F4D1C10E944C :102FF000E21B27C0BB2041F035E03A1508F4C8C1F8 :10300000812F0E94CF2DC4C184E08A1508F4C0C16D :1030100018C0BB2049F0AA2099F3F701858180FFF1 :10302000A2C18F708583ECCFAA2059F0093309F033 :10303000ACC1FFEF13EF21E0F15010402040E1F769 :10304000A2C1812F0E94C42DA3C1812F8695869590 :10305000837019F0813059F09BC1BB2019F0C80171 :10306000937002C080E090E00E94571197C1BB208E :1030700019F0C801937002C080E090E00E944111F5 :103080008DC1812F837009F069C0B11085C1902F67 :10309000929596959770990F990F802F8F70882E23 :1030A000912CA12CB12C092E04C0880C991CAA1CAF :1030B000BB1C0A94D2F704FF12C04FE050E060E05E :1030C00070E004C0440F551F661F771F9A95D2F712 :1030D000DB01CA0180959095A095B09503C080E072 :1030E00090E0DC0116951695412F4370423019F19E :1030F000C8F40091A3061091A4062091A506309172 :10310000A606413059F088299929AA29BB29BC0172 :10311000CD0160237123822393230AC0802A912A40 :10312000A22AB32ABC01CD01682979298A299B29C1 :103130000E947E1D31C188299929AA29BB290091A5 :10314000A3061091A4062091A5063091A606BC0105 :10315000CD016027712782279327EACFBB2019F082 :10316000812F817001C08695882309F415C1902FA5 :10317000929596959770990F990F802F8F70882E42 :10318000912CA12CB12C092E04C0880C991CAA1CCE :10319000BB1C0A94D2F704FF12C04FE050E060E07D :1031A00070E004C0440F551F661F771F9A95D2F731 :1031B000DB01CA0180959095A095B09503C080E091 :1031C00090E0DC0116951695412F43704230D9F0FE :1031D00068F50091000510910105209102053091DC :1031E0000305413059F088299929AA29BB29BC0136 :1031F000CD0160237123822393231EC0802A912A4C :10320000A22AB32A13C088299929AA29BB29009187 :103210000005109101052091020530910305BC01C4 :10322000CD01602771278227932706C0BC01CD01FD :10323000682979298A299B290E94091DADC01F7020 :10324000BB2039F0812F0E945D1D802F0E94CF2D61 :10325000A3C0802F0E94C42D812F0E941F1D9CC0DF :10326000802F32EF931609F440C0391538F090EFF3 :10327000991661F0E1EF9E1699F170C0F3EF9F1679 :10328000D9F124EF921609F44EC068C0BB2019F1A1 :1032900034E03A1508F47CC01F7181E090E0A0E0B2 :1032A000B0E0AC01BD0104C0440F551F661F771F7D :1032B0001A95D2F78091000590910105A091020521 :1032C000B09103058A019B01082719272A273B276C :1032D000C901B80125C025E02A1508F459C0DCCF82 :1032E000BB2029F0812F8F712CC0BB20D9F3812FF7 :1032F0008F710E941F1D4CC0BB2079F01F7181E0AF :1033000090E0A0E0B0E0BC01CD0104C0660F771FE3 :10331000881F991F1A95D2F703C060E070E0CB01B7 :103320000E94091D35C0BB2079F01F71812F0E94BA :103330005D1D38E0139FC0011124836080939E06B9 :10334000812F0E945D1D24C081E00E94441D81E008 :103350008A15F0F482E00E94441D1AC0BB2039F0A7 :10336000AA2009F4BFCF802F0E94352E11C0AA20B9 :1033700009F4BDCF893349F49FEFE3EFF1E09150B9 :10338000E040F040E1F700C00000802F0E94D92DFE :1033900088EF8C0D843010F40E946D11DD2041F116 :1033A00080919E0680FD24C0F70112828595859547 :1033B00085950E945D1DC7010E94D01480919E06D4 :1033C0008595859585950F900F900F900F900F9094 :1033D000DF91CF911F910F91FF90EF90DF90CF90F1 :1033E000BF90AF909F908F900C941F1D69E219CDF4 :1033F0000F900F900F900F900F90DF91CF911F9132 :103400000F91FF90EF90DF90CF90BF90AF909F9083 :103410008F90089508958091A806089580E00895FA :10342000CF93DF9300D01F92CDB7DEB79091CB063C :10343000943011F589837B836A839093E9008FEF41 :103440009091E800815095FD06C09AE69A95F1F7B3 :1034500000C08111F5CF8091E80085FF0DC040E0EC :1034600050E063E070E0CE0101960E94C21F80919F :10347000E8008E778093E8000F900F900F90DF9117 :10348000CF910895BC0184E00C94101ABC0183E034 :103490000C94101ACF93DF9320914101222339F02D :1034A0002091580327FF03C060E224E002C068E0D7 :1034B00021E02093E9002FEF3091E800215035FD05 :1034C00006C03AE63A95F1F700C02111F5CF2091F8 :1034D000E80025FF1DC0EC0180914101811105C06C :1034E00040E050E068E070E003C070E040E050E091 :1034F000CE010E94C21F8091E8008E778093E80081 :1035000080E2FE01A9EAB6E001900D928A95E1F70A :10351000DF91CF91089581E08093E00080E2809375 :10352000D8001092C9008FE097E20197F1F700C030 :10353000000087E090EBDC01809308079093090777 :10354000A0930A07B0930B079CE088E10FB6F894AC :10355000A895809360000FBE90936000FFCF789491 :103560001F920F920FB60F9211248F939F93AF93D8 :10357000BF938091E4039091E503A091E603B0919D :10358000E7030196A11DB11D8093E4039093E50329 :10359000A093E603B093E703BF91AF919F918F9102 :1035A0000F900FBE0F901F9018952FB7F894809131 :1035B000E4039091E503A091E603B091E7032FBFE8 :1035C00008951F920F920FB60F9211248F939F931D :1035D000AF93BF9380915C03811113C08091E4038A :1035E0009091E503A091E603B091E7034196A11DF8 :1035F000B11D8093E4039093E503A093E603B09399 :10360000E703BF91AF919F918F910F900FBE0F90E5 :103610001F901895209141012223C9F02091580351 :1036200027FF15C0262F2695269526952E31C8F4FE :10363000FC01E20FF11D677081E090E001C0880F8E :103640006A95EAF780959281892382830895FC0127 :1036500006962281621301C012823196E817F9079B :10366000C1F70895209141012223C1F02091580310 :1036700027FF14C0262F2695269526952E3130F546 :10368000FC01E20FF11D677081E090E001C0880F3E :103690006A95EAF79281892B82830895FC0132961C :1036A0002FEF30E04191641789F02F3F19F4411159 :1036B00001C0232F3F5F3630A9F72F3F39F0FC01BF :1036C000E20FF11D27FDFA95628308950895CF93C7 :1036D00084E090E00E945C2FC82F81E290E00E947D :1036E0005C2F2C2F30E0A901582BCA01CF910895EF :1036F0006BEE7EEF80E090E00E94982F60E082E029 :1037000090E00E947A2F60E083E090E00E947A2FA0 :103710001092A3061092A4061092A5061092A60677 :1037200060E084E090E00E947A2F60E081E290E027 :103730000E947A2F60E085E090E00E947A2F60E09E :1037400086E090E00E947A2F6FEF87E090E00E9481 :103750007A2F40E050E0BA0188E090E00E948C2F80 :1037600060E08DE090E00E947A2F40E050E0BA01E6 :1037700088E190E00E948C2F60E087E190E00E9459 :103780007A2F40E050E0BA018CE190E00E948C2F4B :1037900060E080E290E00E947A2F40E050E0BA01C1 :1037A00088E190E00E948C2F40E050E0BA018FE069 :1037B00090E00E948C2F40E050E0BA0183E190E05D :1037C0000C948C2F8091A20681111092A20608956C :1037D0009091A1068091A006892B20919F06982F99 :1037E000922B90930F068091A2068823D9F0892B03 :1037F00080930F0680914101882331F08091580316 :1038000087FF02C08EE101C086E0E1E1F6E090E0D2 :10381000815028F021912223D9F39F5FF9CF911194 :103820000E94E21BE0915A03F0915B033097A9F0EC :1038300080914101882359F08091580387FF07C088 :1038400080910F068093100685E080930F0602801A :10385000F381E02D8FE096E00994089580E090E0F8 :103860000E94571180E090E00E9441111092A00642 :1038700010929F060C94E81BBF92CF92DF92EF92BA :10388000FF920F931F93CF93DF938C01C09000059D :10389000D0900105E0900205F09003058091A30609 :1038A0009091A406A091A506B091A606C82AD92A8F :1038B000EA2AFB2ACFE1D0E0D701C6010C2E04C0D2 :1038C000B695A795979587950A94D2F780FD04C081 :1038D000219790F7B12C07C0BC2EB8018C2F0E9405 :1038E00079260197A9F38B2DDF91CF911F910F912D :1038F000FF90EF90DF90CF90BF900895CF93DF932C :10390000EC010E943C1CBE010E947926DF91CF9100 :1039100008950E947E1C292F2F70E92FE295EF70E9 :103920004E2F50E0FA013297EE30F105B8F4E3562D :10393000FF4F0C942930803F99F018F4883E70F4C2 :103940000FC0843F59F40CC0883E50F0813F31F4E1 :1039500007C0822F869586958695089580E0089504 :1039600081E008952EE0929F800D1124682F6695C6 :1039700066956695982F977085E0689FB001112431 :1039800040E050E080E0FB01E40FF51FE959F94FFA :10399000208130E0092E02C0369527950A94E2F77F :1039A00021703327042E01C0220F0A94EAF7822BDC :1039B0004F5F5F4F4530510531F708952EE0929FDC :1039C000800D1124E82FE695E695E695877051E085 :1039D00001C0550F8A95EAF785E0E89FF0011124B0 :1039E000E959F94F20E030E070E04081CB01022E30 :1039F00002C0969587950A94E2F781708195842795 :103A00008523842781932F5F3F4F2530310569F748 :103A10000895CF92DF92EF92FF926B017C010E949A :103A2000FC2AC0920005D0920105E0920205F092B6 :103A30000305FF90EF90DF90CF900C942E1C0F9316 :103A40001F9341E050E060E070E004C0440F551F58 :103A5000661F771F8A95D2F74095509560957095AF :103A60008091000590910105A0910205B091030598 :103A70008A019B01082319232A233B23C901B8018A :103A80001F910F910C94091D20919E068095822311 :103A900080939E06982F977079F430E0482F082E77 :103AA000000C550B2417350739F0859585958595BC :103AB0000E941F1D10929E0608950F931F9341E0D0 :103AC00050E060E070E004C0440F551F661F771F90 :103AD0008A95D2F78091000590910105A091020589 :103AE000B09103058A019B01082B192B2A2B3B2B34 :103AF000C901B8011F910F910C94091D6093A30691 :103B00007093A4068093A5069093A6060C942E1C91 :103B10008091660690913506891719F08F5F87703E :103B2000FBCF08950F931F93CF93DF9380913406BB :103B300082958F7009F05DC080913106882309F469 :103B400058C0809166061091350660912F067091DD :103B50003006C0913206D091330691E06F3F09F0F4 :103B600090E0292F06E0811709F443C0209721F047 :103B70007F3F21F030E003C031E001C0322F90E000 :103B800030FD34C0089FF001099FF00D1124DF01C2 :103B9000AA5CB94F11963C911197371327C03C91FD :103BA000361324C012963C91129731111FC0139600 :103BB0004D915C9114974C1B5D0B483C5105B0F442 :103BC000809134068F70806180933406E55CF94FF4 :103BD00080818F70806180838FE296E00E94D01494 :103BE000DF91CF911F910F910C94881D01968770E2 :103BF000BACFDF91CF911F910F9108959F92AF920D :103C0000BF92CF92DF92EF92FF920F931F93CF93C9 :103C1000DF93CDB7DEB761970FB6F894DEBF0FBE66 :103C2000CDBF8C0185E0F801DE011D9601900D925B :103C30008A95E1F7F80190818181E28030912F0629 :103C4000609130064091320650913306411551057E :103C500031F06F3F31F421E03F3F19F403C021E020 :103C600001C020E0F22FF1709F2E20FD23C1F8014A :103C7000C380D4802FE2A22E26E0B22EF09031062F :103C8000F601E41BF50BFF2009F4CEC020913406A9 :103C9000E83CF10508F099C0422F407F09F051C07F :103CA000681311C039130FC0FE2CE1100CC02F7027 :103CB000206120933406C5010E94D01480913406FF :103CC000F801858337C1CD2831F08F3F31F421E0F1 :103CD0009F3F19F403C021E001C020E020FD03C094 :103CE00021E02E2502C020E030E0F22FF170FF2EFF :103CF00020FF1DC0209166064091350656E024172E :103D000009F4F6C030E0529FF001539FF00D1124EA :103D1000EA5CF94F6181861306C06081961303C087 :103D20006281E61204C02F5F3F4F2770E8CFFE2C60 :103D3000EE2009F4FFC08091340681608093340640 :103D400050C0681307C0391305C0E11003C0F80163 :103D500025838DC09D878E878D859E850E94891CB9 :103D6000882369F1EE2059F120913406822F829543 :103D70008F7090E0029774F080912F06909130063A :103D800098878F831986DB86CA862C87CE01079693 :103D90000E94D01486E0F801AFE2B6E001900D92E7 :103DA0008A95E1F70E94921D0DC06817E1F09D878A :103DB0008E878D859E850E94891C81111EC0C80139 :103DC0000E94D014FF24F394B5C0422F407F69F7BE :103DD0008FE296E00E94D01486E0F50111928A9558 :103DE000E9F7F12CA7C03913E2CFE110E0CFF801D9 :103DF0002583C8010E94D01457C0EE2001F3209102 :103E00003406822F82958F7090E002971CF2809189 :103E10002F06909130069A8389831B82DD82CC82A3 :103E20002E83CE010196B4CFE83CF105E8F5FE2CD7 :103E3000EE2029F2681327C0391325C020913406DB :103E400020FD18C0822F82958F70482F50E04115B9 :103E5000510581F0F80125834F30510541F08F5F06 :103E6000982F9295907F822F8F70892B8583C80120 :103E70000E94D01486E0F801AFE2B6E001900D9206 :103E80008A95E1F757C09D878E878D859E850E9414 :103E9000891C81117FCF8091340681608093340624 :103EA000C8010E94D01446C086E0F50111928A959F :103EB000E9F740C0EE2009F482CF9D878E878D857B :103EC0009E850E94891CF82E882309F478CF86E00D :103ED000F801AFE2B6E001900D928A95E1F780918A :103EE0002F06909130060E947E1C0E94921D22C0D7 :103EF0009D878E878D859E850E947E1C292F229509 :103F00002F70223028F49F7039F0811105C00BC04A :103F1000243028F49F7049F4805E883020F0C80176 :103F20000E94D0149F2CF92C05C0F8019581907F38 :103F300099F7F9CF8F2D61960FB6F894DEBF0FBEBB :103F4000CDBFDF91CF911F910F91FF90EF90DF9048 :103F5000CF90BF90AF909F9008951092A10680914E :103F60004101882331F08091580387FF02C08EE120 :103F700001C086E0E1E1F6E0DF011D928A95E9F7F4 :103F80000C942E1CEF92FF920F931F93CF93DF930D :103F90007C018B010E94A92B811119C0E701011539 :103FA0001105A1F08091E80085FD0AC08091E8002C :103FB0008E778093E8000E94A92B882381F307C0A5 :103FC00089918093F10001501109E9CF80E0DF91E0 :103FD000CF911F910F91FF90EF900895CF92DF92B4 :103FE000EF92FF920F931F93CF93DF93CDB7DEB77E :103FF0002F970FB6F894DEBF0FBECDBF7C018901AD :104000001A861B861C861D8619821A8286E0D82E87 :10401000DB8281E08C8384E08D837E836F8358878D :10402000498749E050E0BE016F5F7F4FF701808113 :104030000E94502997FD40C0C7010E94692997FD41 :104040003BC060E0F70180810E949F2897FD34C04B :104050001E86DF8662E070E0CE010E960E94672821 :1040600097FD2AC061E0F70180810E949F2897FD9B :1040700023C081E00E94452897FD1EC06E01FAE032 :10408000CF0ED11CE12CF12C8FEFE81AF80A81E059 :1040900094E0E916F1040CF080E00E94452897FDB9 :1040A0000BC0F60181936F01F4E0EF16F10461F7A4 :1040B0000E94972884E090E097FD09C04A855B85BF :1040C0006C857D85F80140835183628373832F96CD :1040D0000FB6F894DEBF0FBECDBFDF91CF911F9119 :1040E0000F91FF90EF90DF90CF900895CF93DF93E3 :1040F0001F92CDB7DEB7BE016F5F7F4F85E491E0C1 :104100000E941A2997FD13C09981292F237080914D :10411000470190914801211102C060E001C061E0B7 :104120000E94FB291816190614F480E090E00F9005 :10413000DF91CF9108956F927F928F929F92AF926D :10414000BF92CF92DF92EF920F931F93CF93DF93A3 :104150003C01C091420181E1C89FC02D1124D1E1F1 :10416000DC0FD53508F0D4E560910607669580919F :10417000FE069091FF060E94D812182FCD1708F066 :1041800044C08C2E912CF401EB53FD4F9081809113 :1041900043018923C1F1F401EE0FFF1FE35EFD4FE0 :1041A000C080D12C80E7C81AD108F401EE0FFF1FA0 :1041B000E25EFD4FA080B12CE0E2AE1AB108CC9CCB :1041C0009001CD9C300D300D1124AA9CC001AB9CF8 :1041D000900D900D1124820F931F0E947E12082FC4 :1041E000609103077091040780910507E12E950106 :1041F000A601F30109950E94E212462F282F672F8E :10420000C4010E944512CF5FB9CF81E0D43508F0D8 :1042100080E0DF91CF911F910F91EF90DF90CF90D1 :10422000BF90AF909F908F907F906F900895CF92A6 :10423000DF92EF92FF920F931F93CF93DF936C0166 :10424000C091420181E1C89FC02D1124D1E1DC0F52 :10425000D53508F0D4E56091060766958091FE0695 :104260009091FF060E94D812182FCD1778F5EC2EEA :10427000F12CF701EB53FD4F90818091430189238D :1042800019F1F701EE0FFF1FE25EFD4F208130E0D4 :1042900020523109F701EE0FFF1FE35EFD4F408111 :1042A00050E04057510960910307709104078091D5 :1042B0000507012FF60109950E94E212462F282FCB :1042C000672FC7010E944512CF5FCFCF81E0D43561 :1042D00008F080E0DF91CF911F910F91FF90EF9058 :1042E000DF90CF900895DF92EF92FF920F931F938C :1042F000CF93DF937C01C091420181E1C89FC02D23 :104300001124D1E1DC0FD53508F0D4E56091060722 :10431000669566958091FE069091FF060E94D812E0 :10432000D82ECD17F0F40C2F10E0F801EB53FD4F11 :10433000908180914301892391F0609103077091EE :104340000407809105072D2D4C2FF70109950E9438 :10435000E212462F282F672FC8010E944512CF5F17 :10436000E0CF81E0D43508F080E0DF91CF911F915C :104370000F91FF90EF90DF9008959F92AF92BF92C0 :10438000CF92DF92EF92FF920F931F93CF93DF9321 :104390006C01C091420181E1C89FC02D1124D1E17F :1043A000DC0FD53508F0D4E5609106076695669573 :1043B0008091FE069091FF060E94D812182F80E48B :1043C000810F0E945D1290E8F92EF80E812F0E9455 :1043D0005D1220E8922E980ECD1700F5AC2EB12C70 :1043E000F501EB53FD4F9081809143018923A1F0AA :1043F000609103077091040780910507E12E0C2F4F :10440000292D4F2DF60109950E94E212462F282FE3 :10441000672FC5010E944512CF5FDECF81E0D43502 :1044200008F080E0DF91CF911F910F91FF90EF9006 :10443000DF90CF90BF90AF909F900895CF92DF9282 :10444000EF92FF920F931F93CF93DF936C01C09174 :10445000420181E1C89FC02D1124D1E1DC0FD53587 :1044600008F0D4E52091060730E040E050E06FEF1F :104470007FEF80E090E00E949E2F8901CD17E8F544 :10448000EC2EF12CF701EB53FD4F9081809143010D :10449000892389F19091D506915097FD15C0492F38 :1044A000092E000C550BFA01EB52F94F8189C81304 :1044B000F3CF440F551FFA01EB52F94F218D328D86 :1044C0002017310748F701C0980160910607C9011C :1044D0000E94D812AC01609103077091040780918B :1044E0000507F60109950E94E212462F282F672F33 :1044F000C7010E944512CF5FC1CF81E0D43508F0DB :1045000080E0DF91CF911F910F91FF90EF90DF90AE :10451000CF9008952F923F924F925F926F927F9229 :104520008F929F92AF92BF92CF92DF92EF92FF92C3 :104530000F931F93CF93DF93CDB7DEB727970FB6B7 :10454000F894DEBF0FBECDBF282E4B012091420153 :1045500081E1289F802D11248E83182F1F5E153531 :1045600008F014E53091D50639839E81911708F043 :1045700077C08E81682E712CF301EB53FD4F908133 :1045800080914301892309F467C03090030740906C :104590000407522C1F82C301880F991FDC01A35E00 :1045A000BD4FBB83AA83C301880F991FFC01E25E44 :1045B000FD4FFD83EC83F9815F16E0F5E52CF12CCE :1045C000AA81BB81CC90D12CF701EB52F94F8181AC :1045D000C81AD108AC81BD81AC90B12C8185A81AD4 :1045E000B108CC9C9001CD9C300D300D1124AA9CBB :1045F000C001AB9C900D900D1124820F931F0E945F :104600007E12082FF701EE0FFF1FEB52F94F60915A :104610000607818D928D0E94D8127C019501A6011A :10462000632D742D8F81F4010995362E472E8F83CB :104630005394C1CF209105078F81382F329F312DA0 :104640001124832F632D742D0E94E212462F282FF0 :10465000672FC3010E9445128E818F5F8E8385CFA5 :1046600081E0143508F080E027960FB6F894DEBF9D :104670000FBECDBFDF91CF911F910F91FF90EF90B3 :10468000DF90CF90BF90AF909F908F907F906F9072 :104690005F904F903F902F9008951F93CF93DF939B :1046A000CDB7DEB7AA970FB6F894DEBF0FBECDBF69 :1046B000EDECF6E08091F100819346E0E53DF407F2 :1046C000C9F78091CE06833009F462C030F481309E :1046D00071F0823009F49CC0B3C08A3009F488C0FC :1046E0008B3009F46DC0893009F0AAC020C08091D8 :1046F000CD06813A09F0A4C08091E800877F8093BD :10470000E8008091D1069091D206892B21F460E2D5 :1047100089EA96E003C060E080E090E070E00E94EB :10472000662D8091E8008B778093E80089C08091A6 :10473000CD06813209F084C08091D1069091D206D5 :10474000009719F0029709F07BC08091E800877FFD :104750008093E8008091E80082FD05C08091CB063F :104760008111F8CF6DC02091F3008091F20090E0AC :10477000922B029729F48091F1008B7F813021F4F4 :104780008091F1008093A8068091E8008B7754C057 :104790008091CD06813A09F053C08091D106909165 :1047A000D206892B09F04CC08091E800877F809366 :1047B000E8008091E80080FFFCCF8091410137C084 :1047C0008091CD068132E1F58091D1069091D2069B :1047D000892BB1F58091E800877F8093E8000E94E3 :1047E000DC2B8091CF06809341010E94AD1F28C031 :1047F0008091CD06813221F58091E800877F8093FA :10480000E8000E94DC2B8091D0068093A70618C098 :104810008091CD06813AA1F48091E800877F809352 :10482000E8008091E80080FFFCCF8091A70680938C :10483000F1008091E8008E778093E8000E94DC2BE5 :104840008091E80083FFDDC18091CD069091CE0676 :10485000492F50E04A30510508F0D3C1FA01E5551F :10486000FF4F0C942930803821F0823809F0C9C1FB :1048700008C08091C9069091CA06992389F0826088 :104880000FC08091D1068F70873008F0BAC1809335 :10489000E9008091EB0085FB882780F91092E90000 :1048A0009091E800977F9093E8008093F100109238 :1048B000F10070C1282F2D7F09F0A3C1882319F0C2 :1048C000823061F09EC18091CF06813009F099C19C :1048D000933009F080E08093CA062EC08091CF0605 :1048E00081112AC08091D1068F702FEF280F2630BA :1048F00008F087C18093E9002091EB0020FF1CC0E5 :10490000933021F48091EB00806214C09091EB0011 :1049100090619093EB0021E030E0A90102C0440FC8 :10492000551F8A95E2F74093EA001092EA008091C1 :10493000EB0088608093EB001092E9008091E80022 :10494000877F8093E8000E94DC2B5BC1811159C1F5 :104950001091CF061F778091E3008078812B8093A0 :10496000E3008091E800877F8093E8000E94DC2BC1 :104970008091E80080FFFCCF8091E3008068809305 :10498000E300111102C082E001C083E08093CB06F6 :1049900038C18058823008F034C12091CF06309160 :1049A000D0062C3D53E0350779F583E08A838AE20F :1049B00089834FB7F894DE01139620E03EE051E280 :1049C000E32FF0E050935700E49120FF03C0E295FD :1049D000EF703F5FEF708E2F90E0EA3010F0C796D7 :1049E00001C0C0968D939D932F5F243149F74FBF2F :1049F0008091E800877F8093E8006AE270E0CE0152 :104A000001960E94662DB4C08091D1069091D20685 :104A1000432F552743305105A9F068F44130510523 :104A200009F4FEC04230510509F0EBC08BE590E07F :104A3000E9EDF5E04BC04132510529F14232510513 :104A400089F1DFC0C901992781309105A1F058F0A3 :104A5000029709F0D6C0E6E4F6E0E4918E2F90E0EC :104A6000E6E4F6E030C0ECEAF6E0E4918E2F90E068 :104A7000ECEAF6E028C0E8E9F6E0E4918E2F90E059 :104A8000E8E9F6E020C08330910508F0BAC0880F4D :104A9000991FFC01ED53FE4F0190F081E02D89E05C :104AA00090E014C08330910508F0ABC0FC01EE0F1C :104AB000FF1FE354FE4F0190F081E02DDC01A6546E :104AC000BE4F8C9190E0009709F49BC02091E800C4 :104AD000277F2093E8002091D3063091D406281731 :104AE000390708F4C90140E0009789F12091CB060D :104AF000222309F43DC02530D9F12091E80023FD9F :104B000037C02091E80022FD2FC02091E80020FF4F :104B1000EBCF4091F3002091F20030E0342B00976E :104B200059F02830310540F444914093F10031961A :104B300001972F5F3F4FF3CF41E02830310509F057 :104B400040E02091E8002E772093E800CDCF41117E :104B5000CDCF0AC08091CB06882351F0853041F03B :104B60008091E80083FD04C08091E80082FFF2CFCD :104B70008091E8008B778093E80043C0803809F08B :104B800040C08091E800877F8093E8008091CC0648 :104B90008093F1008091E8008E77D3CE811131C0EF :104BA0008091CF069091D0069927029754F5809175 :104BB000E800877F8093E8001091CF061093CC0621 :104BC0000E94DC2B111106C08091E30087FD02C01A :104BD00081E001C084E08093CB0642E061EC81E09B :104BE0000E94FB2B42E261EC84E00E94FB2B42E23C :104BF00061EC82E00E94FB2B42E260EC83E00E94C9 :104C0000FB2B8091E80083FF10C08091E800877F34 :104C10008093E8008091EB0080628093EB0005C0F8 :104C200082E190E0E4E3F6E051CFAA960FB6F89463 :104C3000DEBF0FBECDBFDF91CF911F910895909140 :104C4000580392FF0DC0282F2871283019F4877F50 :104C5000846006C0282F2471243011F48B7F886073 :104C600093FF0DC0282F2871283119F4877E8461A5 :104C700006C0282F2471243111F48B7E8861209185 :104C8000590320FF0DC0382F3871383019F4877F51 :104C9000816006C0382F3171313011F48E7F886009 :104CA00021FF0DC0282F2871283119F4877E8161DA :104CB00006C0282F2171213111F48E7E886194FD68 :104CC000877E0895F894E82FE295EF70F0E031A127 :104CD000282F2F7081E090E001C0880F2A95EAF715 :104CE000982F9095932391A392A1892B82A37894D6 :104CF0000895CF93DF930E943612EC01823891051C :104D000059F1A0F48133910509F473C040F489325C :104D1000910509F467C08A9709F472C084C085338D :104D2000910509F458C0C997B9F07DC0833E91053B :104D300071F138F4803E9105B1F0823E910511F198 :104D400072C0863E9105B9F1873E9105C9F1843E56 :104D5000910509F068C024C08091580380FD5DC0B2 :104D600081FD5BC060C08091580380FD50C0809180 :104D7000590380FF36C18091580384FD30C1C3EED2 :104D8000D0E02FC18091580382FF2BC1F4CF8091D6 :104D9000580382FD3FC08091590380FD3EC0EBCF98 :104DA0008091590381FF1DC18091580384FD17C173 :104DB000C7EED0E016C18091580383FF12C1F4CF33 :104DC0008091580383FD2CC08091590381FFECCF63 :104DD000C4EED0E006C18091580385FF02C1C9E24C :104DE000D0E0FFC08091580385FFFBC0C5E3D0E051 :104DF000F8C08091580386FFF4C0CAE2D0E0F1C049 :104E00008091580386FFEDC0C1E3D0E0EAC0C9E35A :104E1000D0E0E7C0C2EED0E0E4C0C0EED0E0E1C038 :104E2000C6EED0E0DEC0C11582E5D80708F066C046 :104E3000C11591E5D90728F0DC2FCC27C16FD06AC6 :104E4000D0C0C83ED10560F5C03ED10508F0C9C04C :104E5000C83AD105B0F4C53AD10540F0C55AD0E002 :104E6000C75EDC4FC881D0E0D064BBC0C130D10583 :104E700009F4B7C008F4B3C0C430D10508F4AFC01A :104E8000B0C0CF3BD10508F0AAC0C85AD0E0CC0FC3 :104E9000DD1FC45EDC4F0990D881C02DD464A1C051 :104EA000C11520E5D207E0F0CE0174E09695879514 :104EB0007A95E1F783709C2F937021E030E002C077 :104EC000220F331F9A95E2F73C68382BCF70C695B6 :104ED000C69580E2C89FE0011124C22BD32B81C06C :104EE000C11580E4D80718F0DF70D06A7AC0CE010F :104EF0009A9581159F4108F474C071C0C11586E56B :104F0000D807F0F5C11595E5D90750F08C2F0E9410 :104F10001F268F71C82FD0E0DC2FCC27D06261C054 :104F2000C11524E5D20728F0DC2FCC27C46FD06A46 :104F300058C09E01237033278C2F86958695C11506 :104F4000D34578F4C1E0D0E002C0CC0FDD1F2A9534 :104F5000E2F720E2829FC0011124C82BD92BDC6824 :104F600040C0C1E0D0E002C0CC0FDD1F2A95E2F7BF :104F700020E2829FC0011124C82BD92BDA6831C0EE :104F8000C1152AE5D207E8F4C11589E5D80780F0F4 :104F90008C2F8F700E941F2694E0D695C7959A9506 :104FA000E1F7CF70D0E0DC2FCC27D069C82B19C037 :104FB000C11598E5D90798F0DC2FCC27C06FD06ACF :104FC00010C0CE0190568115904248F48D2F8F71FC :104FD0000E941F26DD27D0628F71D82B02C0C0E04F :104FE000D0E0CE01DF91CF910895CF92DF92EF9282 :104FF000FF926C01EE24FF24C114D104E104F104FA :1050000021F0C701B60120E101C020E0C72ED82E53 :10501000E92EFF24C114D104E104F10419F0285F42 :10502000C701B6016B017C0154E0F694E794D79474 :10503000C7945A95D1F7C114D104E104F10419F0D1 :105040002C5FC701B6016B017C0142E0F694E79446 :10505000D794C7944A95D1F7C114D104E104F1045F :1050600019F02E5FC701B601DC01CB01B695A795FB :1050700097958795892B8A2B8B2B09F02F5F822F91 :10508000FF90EF90DF90CF900895882311F084EC8B :1050900001C084E88093BC0080E49FE1A0E0B0E020 :1050A0002091BC0027FD08C00097A105B10561F063 :1050B0000197A109B109F4CF892B8A2B8B2B21F001 :1050C0008091BB0090E008958FEF9FEF0895DB0182 :1050D000FC0120E030E084E82A173B071CF59191A1 :1050E0009093BB008093BC0040E45FE160E070E01F :1050F0009091BC0097FD0AC04115510561057105ED :1051000099F04150510961097109F2CF452B462BA5 :10511000472B51F09091B900987F983229F42F5F76 :105120003F4FDACFC90108958FEF9FEF089584E9CB :105130008093BC008091BC0084FDFCCF0895262F95 :1051400094EA9093BC0040E45FE160E070E09091ED :10515000BC0097FD0AC0411551056105710549F074 :105160004150510961097109F2CF452B462B472B5C :1051700019F48FEF9FEF08959091B900987F9830C0 :1051800011F09031B1F7682F660F622B6093BB006E :1051900084E88093BC0080E49FE1A0E0B0E020912F :1051A000BC0027FD08C00097A105B10511F30197C8 :1051B000A109B109F4CF892B8A2B8B2BD1F28091D5 :1051C000B900887F883111F0803499F680E090E052 :1051D00008950F931F93CF93DF9300D0CDB7DEB721 :1051E0006A83FC01808193E2998360E00E949F289A :1051F00097FD14C061E070E0CE0101960E9467281F :1052000097FD0CC061E070E0CE0102960E94672815 :105210008C0197FD05C00E94972802C0282F02C06C :10522000202F912F822F0F900F90DF91CF911F9100 :105230000F910895FF920F931F93CF93DF931F92C7 :10524000CDB7DEB78B01FC01F0808DE1898360E092 :105250008F2D0E949F2897FD1AC061E070E0CE015B :1052600001960E94672897FD12C061E08F2D0E9471 :105270009F2897FD0CC080E00E94452897FD07C03D :10528000F80180830E94972821E090E001C0282F38 :10529000822F0F90DF91CF911F910F91FF90089572 :1052A0000F931F93CF93DF93EB018A0160E00E947D :1052B0009F2897FD09C0B801CE010E946728EC0124 :1052C00097FF0E949728CE01DF91CF911F910F91F8 :1052D0000895CF93DF9300D01F92CDB7DEB7209112 :1052E0004F01309150014091510129833A834B8302 :1052F00043E050E0BE016F5F7F4FFC0180810E9460 :1053000050290F900F900F90DF91CF9108958F92B9 :105310009F92AF92BF92CF92DF92EF92FF920F9344 :105320001F93CF93DF93CDB7DEB729970FB6F894CD :10533000DEBF0FBECDBF7C01B42EA52E962E872ECC :10534000690160E0FC0180810E949F2897FD22C0D6 :1053500019821A8286E0800F8B831C820D838E82D5 :105360009F82A886B98669E070E0CE0101960E940E :10537000672897FD0FC0B801C6010E94672897FDF6 :1053800009C00E949728C7010E94692997FD02C0A1 :10539000912F01C0082F802F29960FB6F894DEBFF9 :1053A0000FBECDBFDF91CF911F910F91FF90EF9076 :1053B000DF90CF90BF90AF909F908F9008950F9304 :1053C0001F93CF93DF9300D000D0CDB7DEB7098312 :1053D0001A832B833C8304E010E09E012F5F3F4F34 :1053E0000E9487290F900F900F900F90DF91CF911F :1053F0001F910F910895EF92FF920F931F93CF93F8 :10540000DF9300D000D0CDB7DEB77C01162F198214 :105410001A821B821C829E012F5F3F4F48E259E097 :1054200060E87FEBFC01808191810E94EE1F97FD77 :1054300036C089819A81AB81BC8141E050E060E057 :1054400070E0F701028004C0440F551F661F771FEC :105450000A94D2F7112329F0842B952BA62BB72B76 :1054600008C0409550956095709584239523A62398 :10547000B72389839A83AB83BC8309811A812B81EB :105480003C8148E259E060E87FEBF701808191813F :105490000E94DF291816190614F480E090E00F909E :1054A0000F900F900F90DF91CF911F910F91FF9070 :1054B000EF9008950F931F93CF93DF931F92CDB773 :1054C000DEB78C01BE016F5F7F4F0E941A2997FDE6 :1054D00024C08981F80191819817E9F08183982F80 :1054E0009370923039F0869586958370823061F49E :1054F00060E001C061E0F801828193810E94FB2994 :1055000097FD0BC067E701C066E6C8010E94E92865 :105510001816190614F480E090E00F90DF91CF91F7 :105520001F910F910895EF92FF920F931F93CF93C6 :10553000DF9300D000D01F92CDB7DEB77C01FC0115 :1055400042815381648175814D5F534F6F47704431 :10555000808191811D8201E010E09E012B5F3F4F11 :105560000E94872997FD3CC060E0C7010E94FB298B :1055700019821A821B821C829E012F5F3F4F48E0D6 :1055800059E060E87FEBF701808191810E94EE1F76 :1055900097FD26C001E010E020E030E0F701028036 :1055A00004C0000F111F221F331F0A94D2F78981F4 :1055B0009A81AB81BC81082B192B2A2B3B2B0983A9 :1055C0001A832B833C8348E059E060E87FEB8081BD :1055D00091810E94DF291816190614F480E090E0EA :1055E0000F900F900F900F900F90DF91CF911F9120 :1055F0000F91FF90EF90089520910505211110C0A3 :105600000E94F527843060F495E0989FF001112402 :10561000E55EFE4FA2E0B7E001900D929A95E1F7AA :10562000089590910505911112C080931E018093F9 :1056300023018093280180932D01609100057091D2 :10564000010580910205909103050C94FC2A0895B0 :1056500044E150E063EE72E0882361F08BE191E079 :105660000E946A2F4CEF50E067EF72E084E094E014 :105670000C946A2F8BE191E00E944C2F4CEF50E08C :1056800067EF72E084E094E00C944C2F1F920F922D :105690000FB60F9211242F933F934F935F936F9305 :1056A0007F938F939F93AF93BF93CF93DF93EF93AA :1056B000FF93C091E900CF708091EC00D82FD1709A :1056C00080FDD0E81092E9008091F000877F809300 :1056D000F00078940E944D231092E9008091F00030 :1056E00088608093F000CD2BCF70C093E900FF91CC :1056F000EF91DF91CF91BF91AF919F918F917F916A :105700006F915F914F913F912F910F900FBE0F902E :105710001F901895E8EDF0E080818E7F80831092D5 :10572000E2001092DA001092E100A0EEB0E08C915D :1057300081608C9380818F77808319BCA7EDB0E066 :105740008C918E7F8C9380818F7E8083109207074F :1057500008952091E4003091E50095E64091EC0039 :10576000842F817040FF23C08091E80080FD1DC020 :105770008091CB06882399F0853099F08091EB00D9 :1057800085FD11C04091E4005091E50024173507D4 :1057900029F3915011F09A01E1CF84E0089582E05D :1057A000089583E0089581E0089580E00895409190 :1057B000E80042FFDDCF08958091CD0687FF11C03C :1057C0008091E80082FD05C08091CB068111F8CF61 :1057D00011C08091E8008B770BC08091CB068823A5 :1057E00049F08091E80080FFF8CF8091E8008E7743 :1057F0008093E8000895982F973068F59093E9001A :10580000981739F07091EC002091ED005091F00064 :1058100003C0242F762F50E021FD02C09F5FECCF04 :105820003091EB003E7F3093EB003091ED003D7FF7 :105830003093ED003091EB0031603093EB007093CA :10584000EC002093ED005093F0002091EE0027FD36 :10585000E5CF80E008958F708093E90081E008959E :10586000CF92DF92EF92FF920F931F93CF93DF932C :10587000C8EDD0E088818F7E8883E7EDF0E08081FD :105880008160808384E082BF81E080930707888104 :105890008E7F888302EE10E0F80110821092DA0009 :1058A00081EEC82ED12CF601108288818F778883F3 :1058B00088818068888388818F7D888319BC109255 :1058C000CB061092CC061092CA061092C90690EE32 :1058D000E92EF12CF70180818B7F808388818160A4 :1058E000888342E060E080E00E94FB2BF60180812B :1058F0008E7F8083F80180818160808380818860D1 :105900008083F70180818E7F808388818061888396 :10591000DF91CF911F910F91FF90EF90DF90CF908B :1059200008951F920F920FB60F9211242F933F9359 :105930004F935F936F937F938F939F93AF93BF9397 :10594000EF93FF938091E10082FF09C08091E20014 :1059500082FF05C08091E1008B7F8093E100809100 :10596000DA0080FF2AC08091D80080FF26C0809195 :10597000DA008E7F8093DA008091D90080FF18C012 :1059800080E189BD82E189BD09B400FEFDCF81E0DF :105990008093CB068091070781110FC00E948A2B4C :1059A0000E94302C8091E20084608093E20005C068 :1059B00019BC1092CB06109207078091E10080FF7E :1059C00017C08091E20080FF13C08091E2008E7FBB :1059D0008093E2008091E20080618093E2008091F8 :1059E000D80080628093D80019BC85E08093CB06F4 :1059F0008091E10084FF2EC08091E20084FF2AC0E4 :105A000080E189BD82E189BD09B400FEFDCF8091AE :105A1000D8008F7D8093D8008091E1008F7E8093A5 :105A2000E1008091E2008F7E8093E2008091E200AD :105A300081608093E2008091CC06882311F084E09D :105A400007C08091E30087FD02C081E001C083E0D0 :105A50008093CB068091E10083FF27C08091E20014 :105A600083FF23C08091E100877F8093E10082E083 :105A70008093CB061092CC068091E1008E7F8093BC :105A8000E1008091E2008E7F8093E2008091E2004D :105A900080618093E20042E060E080E00E94FB2BA6 :105AA0008091F00088608093F000FF91EF91BF91AA :105AB000AF919F918F917F916F915F914F913F91A6 :105AC0002F910F900FBE0F901F9018952091D30625 :105AD0003091D4062617370748F06115710539F45F :105AE0002091E8002E772093E80001C0B901FC0165 :105AF00020E06115710579F18091CB068823F1F1E1 :105B00008530F1F18091E80083FD3CC08091E80090 :105B100082FD2EC08091E80080FFEBCF2091F30042 :105B20008091F20090E0922B6115710551F0883060 :105B3000910538F421912093F1006150710901968B :105B4000F3CF21E0089709F020E08091E8008E77FC :105B50008093E800CECF2111CFCF0AC08091CB0631 :105B6000882361F0853061F08091E80083FD0AC0F0 :105B70008091E80082FFF2CF80E0089582E00895EE :105B800083E0089581E00895882341F08095909105 :105B9000A10689238093A1060C94E81B089588230D :105BA00039F09091A106892B8093A1060C94E81BF3 :105BB0000895882309F458C0682F823869F40E9438 :105BC0006D1181FF51C069E38FE096E00E94321BA6 :105BD0000E94E81B69E30EC0833891F40E946D11A6 :105BE00080FF42C063E58FE096E00E94321B0E9476 :105BF000E81B63E58FE096E00E940A1B0C94E81B0B :105C0000843869F40E946D1182FF2EC067E48FE032 :105C100096E00E94321B0E94E81B67E4EBCF8CEFFA :105C2000860F813A38F380E2860F883070F467700F :105C300081E090E001C0880F6A95EAF78095909125 :105C4000A10689238093A106D9CF8BE5860F8330E7 :105C500020F480E090E00C945711685A673120F4EA :105C600080E090E00C9441110895CF93882309F4CB :105C7000B5C0C82F8238B1F40E946D1181FDAEC04D :105C800069E38FE096E00E94321B0E94E81B2FEF31 :105C900080E792E0215080409040E1F700C0000092 :105CA00069E317C08338E1F40E946D1180FD96C04E :105CB00063E58FE096E00E94321B0E94E81B2FEF05 :105CC00080E792E0215080409040E1F700C0000062 :105CD00063E58FE096E00E940A1BCF910C94E81BCD :105CE0008438B1F40E946D1182FD78C067E48FE0C2 :105CF00096E00E94321B0E94E81B2FEF80E792E0A3 :105D0000215080409040E1F700C0000067E4E1CFFF :105D10008CEF8C0F813AB8F5809141018823E1F036 :105D20008091580387FF18C0EC2FE695E695E6951D :105D3000F0E0E15FF94F8281282F30E04C2F47706F :105D400081E090E002C0880F991F4A95E2F7822314 :105D50009323892B59F411C0E1E1F6E08191C81732 :105D600029F026E0E731F207C9F707C06C2F8FE072 :105D700096E00E940A1B0E94E81B6C2F8FE096E0C1 :105D80000E94321BAACF80E28C0F883068F4C77063 :105D900081E090E001C0880FCA95EAF79091A106D2 :105DA000892B8093A10699CFEBE5EC0FE33040F40B :105DB000F0E0E75EFC4F808190E0CF910C945711AA :105DC000C85AC73158F4EC2FF0E0EE0FFF1FE45E25 :105DD000FC4F80819181CF910C944111CF91089516 :105DE0008F929F92AF92BF92CF92DF92EF92FF92EB :105DF000CF93DF93EC01688179818A819B81611562 :105E000071058105910521F464E279ED8BE597E058 :105E10002DE133EF41E050E00E949E2F49015A01ED :105E20009B01AC01A7EAB1E40E94BD2F6B017C018C :105E3000ACEEB4EFA50194010E94CB2FDC01CB01A5 :105E40008C0D9D1DAE1DBF1DB7FF03C00197A1099D :105E5000B04888839983AA83BB839F77DF91CF91D2 :105E6000FF90EF90DF90CF90BF90AF909F908F907A :105E700008950E94F02E089580E091E00E94F02E97 :105E80000895A0E0B0E08093000190930101A093F9 :105E90000201B09303010895DC01CB01FC01F999E3 :105EA000FECF06C0F2BDE1BDF89A319600B40D9266 :105EB00041505040B8F70895F999FECF92BD81BD89 :105EC000F89A992780B50895A8E1B0E042E050E043 :105ED0000C944E2FDC01A40FB51F4150504048F0E8 :105EE000CB01840F951F2E910E947B2F4150504073 :105EF000D0F70895262FF999FECF92BD81BDF89A6B :105F0000019700B4021639F01FBA20BD0FB6F894FD :105F1000FA9AF99A0FBE08950396272F0E947B2FB5 :105F20000E947A2F252F0E947B2F242F0C947B2FE9 :105F30000196272F0E947B2F0C947A2F052E97FB1A :105F40001EF400940E94B52F57FD07D00E94D02F59 :105F500007FC03D04EF40C94B52F50954095309526 :105F600021953F4F4F4F5F4F0895909580957095C5 :105F700061957F4F8F4F9F4F08950E94F22FA59FED :105F8000900DB49F900DA49F800D911D1124089534 :105F9000B7FF0C94BD2F0E94BD2F821B930B089559 :105FA000A1E21A2EAA1BBB1BFD010DC0AA1FBB1F1D :105FB000EE1FFF1FA217B307E407F50720F0A21B8F :105FC000B30BE40BF50B661F771F881F991F1A94FC :105FD00069F760957095809590959B01AC01BD0126 :105FE000CF010895A29FB001B39FC001A39F700D80 :105FF000811D1124911DB29F700D811D1124911DD1 :106000000895AA1BBB1B51E107C0AA1FBB1FA617FF :10601000B70710F0A61BB70B881F991F5A95A9F751 :1060200080959095BC01CD01089597FB072E16F43D :10603000009407D077FD09D00E94013007FC05D0FD :106040003EF4909581959F4F0895709561957F4F8F :106050000895EE0FFF1F0590F491E02D0994FB01C8 :10606000DC0102C001900D9241505040D8F70895D4 :10607000FB01DC014150504048F001900D9200209E :10608000C9F701C01D9241505040E0F70895F894BF :02609000FFCF40 :10609200010000003A01190000003A010A00000064 :1060A2005000040152000A01FFFF033D8EFFB07F42 :1060B200958EFFB07F958EFFB07F958EFFB07F0BE0 :1060C2001A4A1A0A1A461A421AB02D3A011D00003B :1060D200000100FF0051003B01AA56008EFFB0995B :1060E200370073797374656D37362F6C61756E6323 :1060F200685F3100302E372E3130332D343031315C :106102002D6737303865643500F0F1F4F5F6F7970E :1061120067663635349694C69593923730020704F3 :106122000603090209040303080203030301260C00 :106132000D0E10110F1213172122250000313129E3 :106142005A1B750A2131426384B040226D9905774A :10615200050A05EB050406240645464748494A4B0D :106162004C4D4E4F50515244434241403F3E3D3CC4 :106172003B3A3938372728292A2B2C2D2E2F30311C :10618200323334262524232221201F1E1D1C1B1AD4 :10619200530C0B0A09080706050403020100360D19 :1061A2000E0F1011191213141516171835D133BE0C :1061B20033AB339C338C337D336E335F3350334197 :1061C20033313322330B3308401B402A40394050CD :1061D200406E4085409440A740C240D140E040E03C :1061E20026C526B226A32694268526762667265716 :1061F20026482639262A261B260826041A171A2676 :106202001A351A441A541A631A721A811A901A9F6A :106212001AAF1ABE1ACD1AE01AE00DC90DB60DA7B3 :106222000D980D890D790D6A0D5B0D4C0D3D0D2EEE :106232000D1E0D0F0D000D00000F001E002E003D63 :10624200004C005B006A00790089009800A700B644 :1062520000C900E000040404040404040404040467 :1062620004040404040404040404040404040404EC :1062720004040404040404040404040404040404DC :1062820004040404040404040404040404040404CC :1062920004040404040404040404040404040404BC :1062A200040404040404040404818283E200E90077 :1062B200EA00B500B600B700CD008301CC008A0128 :1062C20092019401210223022402250226022702BE :0A62D2002A02B300B4006F00700050 :00000001FF ================================================ FILE: data/system76_launch_2_default.hex ================================================ :100000000C944E030C9495030C9495030C94950357 :100010000C9495030C9495030C9495030C94950300 :100020000C9495030C9495030C94FB2C0C94AF2B1F :100030000C94421A0C9495030C9495030C9495031C :100040000C9495030C9495030C9495030C949503D0 :100050000C9495030C94101A0C9495030C9495032E :100060000C9495030C9495030C9495030C949503B0 :100070000C9495030C9495030C9495030C949503A0 :100080000C9495030C9495030C9495030C94950390 :100090000C9495030C949503F206FB062607630760 :1000A000A107E307260829082C082F08320835087D :1000B00038083B083E084108460849084C085108E2 :1000C000560859085C0861089D08D908DC08E10851 :1000D000EC08EF08FA08FD0808090B0916091909C8 :1000E00024092A099A09DF09DF0AE50AEA0A870CC6 :1000F000870CF30A870C870CFD0A0E0B350B540B8B :10010000750BA70BD60BFF0B320C2A0C7D0C1D17A1 :100110001D1757175717AA174D194D194D19C617FF :10012000A418B518B518FC1BFC1B0F1C0F1C051CD4 :100130000F1C0F1C0F1CFC1BFC1B0A1C0F1C0F1C94 :100140000A1C9923C0236425C02364250C242F2472 :1001500064252125312529003A003B003C003D0063 :100160003E003F0040004100420043004400450083 :100170004C0035001E001F0020002100220023003B :1001800024002500260027002D002E002A002B0029 :1001900014001A000800150017001C0018000C00BD :1001A000120013002F003000310039000400160047 :1001B000070009000A000B000D000E000F003300BD :1001C000340028004A00E1001D001B000600190051 :1001D000050011001000360037003800E50052001D :1001E0004B00E000E2000151E3002C004D002C0028 :1001F000E400E6000151500051004F004E00005C49 :1002000001000100010001000100010001000100E6 :1002100001000100010001000100010001000100D6 :100220000100010001000100010001000100C35CA8 :10023000CB5CCA5C01004600010001000100010026 :1002400001004A004E004B004D000100010001007A :100250000100010001000100010001000100500047 :10026000510052004F00010001000100AE000100EA :100270000100010001000100010001000100010076 :100280000100010001004B00A90001000100010074 :1002900001000100A80001000100010001004A0066 :1002A0004E004D00AA000100010001000100010004 :1002B0000100010001000100010001000100010036 :1002C0000100010001000100010001000100010026 :1002D0000100010001000100010001000100010016 :1002E0000100010001000100010001000100010006 :1002F00001000100010001000100010001000100F6 :1003000001000100010001000100010001000100E5 :1003100001000100010001000100010001000100D5 :1003200001000100010001000100010001000100C5 :1003300001000100010001000100010001000100B5 :1003400001000100010001000100010001000100A5 :100350000100010001000100010001000100010095 :100360000100010001000100010001000100010085 :100370000100010001000100010001000100010075 :100380000100010001000100010001000100010065 :100390000100010001000100010001000100010055 :1003A0000100010001000100010001000100010045 :1003B0000100010001000100010001000100010035 :1003C0000100010001000100010001000100010025 :1003D0000100010001000100010001000100010015 :1003E0000100010001000100010001000100010005 :1003F00001000100010005010980A1018503190127 :100400002AB700150126B700950175108100C005B7 :100410000C0901A101850419012AA002150126A0D9 :1004200002950175108100C005010906A10185052D :10043000050719E029E715002501950875018102D6 :100440000507190029EF1500250195F075018102B6 :100450000508190129059505750191029501750396 :100460009101C00660FF0961A1010962150026FF24 :10047000009520750881020963150026FF0095206C :1004800075089102C005010906A101050719E029B7 :10049000E715002501950875018102950175088110 :1004A000010507190029FF150026FF0095067508AC :1004B000810005081901290595057501910295012D :1004C00075039101C009025B00030100A0FA090451 :1004D0000000010301010009211101000122400077 :1004E0000705810308000A09040100020300000057 :1004F00009211101000122220007058203200001C9 :1005000007050303200001090402000103000000A5 :10051000092111010001226D000705840320000A52 :1005200012011001000000088433060001000102DE :10053000000150034C00610075006E00630068000C :10054000200043006F006E006600690067007500C0 :100550007200610062006C00650020004B006500C5 :10056000790062006F0061007200640020002800C2 :100570006C00610075006E00630068005F0032006F :100580002900000012035300790073007400650015 :100590006D0037003600000004030904000101016A :1005A0000101010101010202020202020202020330 :1005B0000303030303030304040404040404050500 :1005C00005050506060606060707070707080808C3 :1005D00008090909090A0A0A0B0B0B0C0C0C0D0D72 :1005E0000D0E0E0E0F0F0F1010111111121213130A :1005F0001414151516161717181819191A1A1B1B83 :100600001C1D1D1E1E1F20202122222324242526DE :1006100026272829292A2B2C2D2D2E2F3031323216 :10062000333435363738393A3B3C3D3E3F40414222 :10063000434445464748494A4C4D4E4F5051535408 :10064000555658595A5B5D5E5F61626465666869BC :100650006B6C6D6F7072737577787A7B7D7E80823C :10066000838587888A8C8E8F91939596989A9C9E85 :10067000A0A2A3A5A7A9ABADAFB1B3B5B7BABCBE95 :10068000C0C2C4C6C9CBCDCFD1D4D6D8DBDDDFE262 :10069000E4E7E9EBEEF0F3F5F8FAFDFF11241FBEF5 :1006A000CFEFD0E1DEBFCDBF04B603FE27C08091FF :1006B000100790911107A0911207B091130787308E :1006C000904BA740B04BD1F4109210071092110735 :1006D000109212071092130714BE84B7877F84BF4D :1006E0000FB6F894A89580916000886180936000AF :1006F000109260000FBEE0E0F8E7099513E0A0E07B :10070000B1E0E2E6F1E602C005900D92A035B10736 :10071000D9F727E0A0E5B3E001C01D92A031B207F0 :10072000E1F70E9497030C94AF300C940000CF9334 :10073000DF93CDB7DEB7AB970FB6F894DEBF0FBE31 :10074000CDBF84B7877F84BF0FB6F894A8958091FA :100750006000886180936000109260000FBE91E09D :1007600080E80FB6F89480936100909361000FBE0B :1007700085B7806885BF85B7806885BF83E999E1C3 :1007800090935103809350030E94F32B0E94992C65 :100790008091E20084608093E20078948091D1059A :1007A0008823A1F01091E9001F709091EC00892F2F :1007B000817090FD80E8182B1092E9008091E8008C :1007C00083FD0E94B5221F701093E90082E084BD72 :1007D00093E095BD9DE797BD80936E000FE711E014 :1007E00045E8C42E41E0D42ED8018D918D010E94A0 :1007F000080DC016D106C1F705E811E033E9C32E94 :1008000031E0D32EF80181918F010E94080DC016AE :10081000D106C1F7E2E5F3E08EE593E0ADEFB3E09A :10082000119211921D921D928E179F07C9F780E0B9 :1008300090E00E94CC2F8B3E9E4F11F00E94D91A5F :100840001092DB05E4EFF5E084E096E02FEF3FEF58 :10085000219331938E179F07D9F710926303ECE72A :10086000F3E08CE893E02FEF3FEF219331938E1765 :100870009F07D9F780E090E00E94CC2F8B3E9E4FDF :1008800021F00E94D91A0E941C2A45E050E06CE138 :1008900070E088E096E00E94B42F809108068C7F7B :1008A00011F40E941C2A0E9480128FE097E20197A7 :1008B000F1F700C00000AFE0B7E21197F1F700C018 :1008C00000000E9480128091FD0380FF14C06FEF32 :1008D0007FEF80E490E00E9400306FEF82E490E0D0 :1008E0000E94E22F6FEF7FEF80E090E00E940030E7 :1008F0000E94B61302C00E94C91180E490E00E94D9 :10090000CC2F8C3E964739F482E490E00E94C42FAD :1009100091E0823009F090E090FD39C000E010E0F5 :10092000680128EAC20ED11C4801ECE18E0E911C30 :10093000F801EA5AFE4FA590B4906B2DC8018D5B6B :100940009F4F0E94E22F6A2DC8018C5B9F4F0E942F :10095000E22F0E5F1F4F8016910651F78401C814D5 :10096000D90411F78601F0EACF16F2E0DF06C1F6EE :1009700081E00E9416146CEE76E780E490E00E941D :10098000003062E082E490E00E94E22F03C080E049 :100990000E94161460910605709107058091080564 :1009A000909109050E94EA1380E090E00E94CC2F0C :1009B0008B3E9E4F11F00E94D91A82E090E00E9477 :1009C000C42F8093F0030E94C81A90935F03809312 :1009D0005E0383E090E00E94C42F682F70E080E007 :1009E00090E00E94DF1C60910605709107058091E0 :1009F0000805909109050E94EA1360915E03606802 :100A000060935E0310915F0384E090E00E94E22F08 :100A1000612F81E290E00E94E22F8BE191E09093C0 :100A200061038093600322242394312C8091D105AB :100A3000853009F054C080E4E82EDD24D39498E199 :100A4000F92E1AE18091D105853009F042C08091DC :100A5000D105843051F140E060E080E00E94182A26 :100A6000D092EE031092620368E170E00FB6F89442 :100A7000A895609360000FBEE092600083B7817F0D :100A8000846083BF83B7816083BF7894889583B780 :100A90008E7F83BF0FB6F894A8958091600088611F :100AA00080936000109260000FBE8091D005882373 :100AB00009F4C8CF0E948012EDEFF3E0819191918B :100AC000892B09F04BC789E094E08E179F07B1F797 :100AD000B9CF0E940E1F0E9442291092EE030E947D :100AE0008012882359F08FB7F8944091EA0350910F :100AF000EB036091EC037091ED038FBFA1EFB3E0C6 :100B0000EDEFF3E0E12CF12C4E2DA190B1908D9101 :100B10009D918A259B25009709F4AEC010E0CC2456 :100B2000C394D12C9C012C213D21232B09F49EC080 :100B300019A34AA3AC20BD2081E0A114B10409F49B :100B400080E08BA30E94361A8160782F9DA38CA32E :100B500049A15AA16BA18DA10E947828F701EE0F3F :100B6000FF1FEF50FC4F80819181C826D926D1828A :100B7000C082AB2881F08EE08E9DF0018F9DF00D3C :100B80001124E953FE4FE10FF11D80818F3F19F0D1 :100B90008BA711E001C010E0B0906303E12EF12CAF :100BA000C7018B0D911D0997A4F188E090E06C01BD :100BB000CE18DF08B7016F5F7F4F6D597C4FA601DC :100BC00084E693E00E949730B701675F7F4F6D59CD :100BD0007C4FA6018CE693E00E949730A601440F5B :100BE000551FB701660F771F675E7F4F6D597C4FAA :100BF0008CE793E00E949730B7016F5E7F4F6D598D :100C00007C4FA60184E793E00E949730BA94B0929B :100C100063038091630390E0EBA5AE2FB0E09D01EC :100C2000220F331F255E3D4FAA0FBB1FBD01645E1F :100C30007D4F41E0480F9117B0F490E0FC01ED5971 :100C4000FC4FD9015C915183DB015C915187BBA5BD :100C5000B18B880F991FFC01ED59FC4F128E118E3C :100C600091E0842FE6CF809363031EC01F5FCC0CFE :100C7000DD1C1E3009F056CF2FEFE21AF20A36E0E3 :100C8000E316F10409F040CF8FEF8EA38FA318A6CF :100C90000E94361A8160782F9AA789A74EA15FA17A :100CA00068A58AA50E94782840918C0350918D03F5 :100CB00060918E0370918F032FB7F8948091EA03AF :100CC0009091EB03A091EC03B091ED032FBF841B37 :100CD000950BA60BB70B2FB7F894C090EA03D090F2 :100CE000EB03E090EC03F090ED032FBFC0928C0378 :100CF000D0928D03E0928E03F0928F036091630394 :100D0000E3E6F3E0462F50E088248A94982CA12C47 :100D1000B12C881A990AAA0ABB0A651799F0218D85 :100D2000328D2901612C712C84149504A604B7041A :100D300010F4415004C0280F391F328F218F5F5F9C :100D40003296EBCF409363038091EE03811108C08C :100D500010910806812F837019F01695169501C021 :100D600010E0809106018130E9F038F0823009F41A :100D7000A7C3833009F4B1C3CDC310924901C09217 :100D80000406D0920506E0920606F092070689E274 :100D9000E3E6F3E0ABEDB5E001900D928A95E1F763 :100DA00081E098C38091050118130DC020910806B9 :100DB000237030E04091040150E081E024173507B2 :100DC00019F480E001C081E0817080934B01412FD4 :100DD00050E04832510508F061C3FA01E45BFF4F6F :100DE0000C949130882309F459C340E060E080E01E :100DF0000E94182A53C3F090490181E1F89EF02C1B :100E0000112401E10F0D053508F004E56091090694 :100E100070910A0680910B060E94B72AD62EC72E23 :100E2000B82EF01608F037C3EF2DF0E0DF01AD5318 :100E3000BD4F8C9190914A01982331F02B2D4D2D6F :100E40006C2DCF010E941A2AF394EBCFF090490148 :100E500081E1F89EF02C112401E10F0D053508F019 :100E600004E5C0900A06D0900B06B09009066B2DE1 :100E70007C2D8D2D0E94B72AA62E972E882E60914C :100E80000C066B0D7C2D8D2D0E94B72AD62EC72EF9 :100E9000B82EF01608F0FFC28F2D90E0FC01ED5344 :100EA000FD4F308120914A01232359F030FF04C0C7 :100EB0002B2D4D2D6C2D03C0282D4A2D692D0E9400 :100EC0001A2AF394E6CFD090490181E1D89ED02C24 :100ED000112401E10D0D053508F004E5A0900A0686 :100EE00090900B0620910C0630E4B32E5B2D529FA0 :100EF000512D1124B52ED01608F0CDC2ED2CF12CB9 :100F0000F701ED53FD4F908180914A018923B9F09B :100F1000F701EE0FFF1FE45EFD4F808182958F7019 :100F2000609109068B9D600D11247A2D892D0E94F8 :100F3000B72A462F282F672FC7010E941A2AD39459 :100F4000DACFD090490181E1D89ED02C112401E163 :100F50000D0D053508F004E5A0900A0690900B06EB :100F600020910C0680E4B82E6B2D629F612D112418 :100F7000B62ED01608F08FC2ED2CF12CF701ED53F0 :100F8000FD4F908180914A018923D9F0F701EE0F3E :100F9000FF1FE55EFD4F6081B69EB0011124B5E0F4 :100FA00075956795BA95E1F780910906680F7A2DD6 :100FB000892D0E94B72A462F282F672FC7010E942C :100FC0001A2AD394D6CFF090490181E1F89EF02CF3 :100FD000112401E10F0D053508F004E5C090090664 :100FE000D0900A06B0900B0660910C066695669547 :100FF000669580910406909105060E94AD2A0E9494 :10100000322A805887FD8195880F782F2B2D729F6B :10101000712D1124872FB6010E94B72AD62EC72E14 :10102000B82EF01608F037C2EF2DF0E0DF01AD5317 :10103000BD4F8C9190914A01982331F02B2D4D2D6D :101040006C2DCF010E941A2AF394EBCF80E697E231 :101050001AC084E397E217C089E398E21FC08AE1CF :1010600098E21CC08FEF97E21EC083EE97E21BC090 :1010700082E397E208C089E297E205C080E297E246 :1010800002C085E097E20E94DB2009C286EF96E26B :101090000AC084E89AE202C082ED97E20E947F20B3 :1010A000FEC18EEB97E20E940320F9C188EC96E224 :1010B00005C086E996E202C088E596E20E942521F5 :1010C000EEC181111EC060910C0620E1620F08F490 :1010D0006FEF80910406909105060E94AD2A6AE0A8 :1010E00070E00E946930892B09F0D8C10E94A42FBA :1010F00064E570E00E947D3060914A010E94472BB8 :10110000CDC18091490191E1899F802D112401E198 :10111000080F053508F004E5E82EF12CC02ED12C7F :10112000EC14FD040CF0B7C160914A01C7010E94A4 :10113000472B3FEFE31AF30AF3CF81111EC06091F2 :101140000C0620E1620F08F46FEF80910406909185 :1011500005060E94AD2A65E070E00E946930892B87 :1011600009F09CC10E94A42F64E570E00E947D30CC :1011700060914A010E948D2B91C18091490191E1BA :10118000899F802D112401E1080F053508F004E541 :10119000E82EF12CC02ED12CEC14FD040CF07BC1F8 :1011A00060914A01C7010E948D2B5FEFE51AF50A95 :1011B000F3CF81E596E202C08BE496E20E9486219D :1011C0006EC18091DB0521E0682F621B08F460E0AE :1011D000862F62E376E23BC062E376E237C080911D :1011E000DB0521E0782F721B08F470E0872F6AEF8F :1011F00075E22DC06AEF75E229C08091DB0521E020 :10120000382F321B08F430E0832F68EC75E21FC0E2 :1012100068EC75E21BC08091DB0521E0582F521B62 :1012200008F450E0852F60EB75E211C060EB75E2C9 :101230000DC08091DB0521E0682F621B08F460E09F :10124000862F6AE975E203C06AE975E280E00E94D0 :10125000F22125C18091E403811125C067EC71E082 :1012600040E050E0942F9295907F20E030E0FB0129 :10127000E20FF31F8081843538F4E82FF0E0E05767 :10128000FC4F892F822B80832F5F3F4F2E303105FB :1012900071F74F5F5F4F625F7F4F4630510511F727 :1012A00081E08093E403D090490181E1D89ED02C65 :1012B000112401E10D0D053508F004E560910605E6 :1012C0007091070580910805909109050E949B0E79 :1012D000B82E6091090670910A0680910B060E9453 :1012E000B72AA62E972E882ED01608F0D4C0ED2C43 :1012F000F12CF701ED53FD4F908180914A01892334 :10130000B9F0F701E057FC4F6081462F4F706295AE :101310006F708B2D0E94E429029720F420E040E0BA :1013200060E003C0282D4A2D692DC7010E941A2AAA :10133000D394DACF9090490181E1989E902C1124AA :1013400001E1090D053508F004E5EE24EA94F12CDD :10135000901608F0A0C0E92DF0E0DF01AD53BD4FBD :101360009C9180914A01892341F1DF01AA0FBB1FA3 :10137000AE0FBF1FA65FBB4FAC901196CC901197DC :1013800012968C9190910B06A99E50011124C99E32 :1013900060011124899FC0011124B7010E946930A6 :1013A000262FC501B7010E946930462FC601B7013B :1013B0000E946930CF010E941A2A9394C9CFC0902D :1013C000490191E1C99EC02C112401E10C0D0535A4 :1013D00008F004E5811106C08091E9038F5F8093D6 :1013E000E90304C01092E9031092E8038091E90335 :1013F000811147C08091E803883029F41092E703F7 :101400001092E8033EC0A82FB0E0AA0FBB1FAD5654 :10141000BE4FEC9111969C917EE0E79FF001112464 :10142000E953FE4FE90FF11D90819F3F21F090930A :10143000E50391E001C090E09093E7038F5F809314 :10144000E8031FC0EC2CF12CF701ED53FD4F908108 :1014500080914A018923A1F06091E9036C0D2091EC :10146000E703E5EEF3E080E77FEF90E092130CC036 :101470000E94B72A462F282F672FC7010E941A2AD9 :10148000C394C016F8F207C03191C31202C08FEFA7 :1014900070E09F5FEBCF81E0043508F080E0909131 :1014A00049019F5F90934901811134C082E080938C :1014B000060180914B0181112DC0112351F02AC0EA :1014C00010930501809108068370809304010E94A7 :1014D000572883E0809306011DC040910406509177 :1014E000050660910606709107062FB7F894809163 :1014F000EA039091EB03A091EC03B091ED032FBFB1 :10150000841B950BA60BB70B4097A105B10510F0F6 :10151000109206010E9442299091EF03891721F051 :101520000E9442298093EF038091D105843009F015 :101530007DCA83E08093E9008091E80082FF76CA4B :101540008091E80085FF23C00E94122C81111DC0EC :1015500050E2E52EF12CCE0101966C0109C080917C :10156000F100D6018D936D01B1E0EB1AF10869F03D :101570008091E80085FDF3CF8091E8008B77809320 :10158000E8000E94122C882399F391E001C090E0BA :101590008091E8008B778093E800992309F446CA8C :1015A00081E08A83E9818E2F90E0FC013197E3315D :1015B000F10508F0ACC1EC58FF4F0C94913086E770 :1015C0008B838CEE8C8381E014C14EE150E065E5A5 :1015D00071E004C04EE150E067E671E0CE01039691 :1015E0000E94A03093C180910B05882309F48FC11C :1015F0001A8281E080930A058AC18B81843008F0C9 :1016000086C16C81663008F082C14D814E3008F091 :101610007EC10E94E4298E839F8378C12B81243070 :1016200008F075C18C81863008F071C19D819E30B3 :1016300008F06DC11E816F81ECE18E9F7001112455 :10164000F8EA2F9FE00CF11C1124E90EF11CE90EC1 :10165000F11C23E4E20EF11CC7010E94E22F612F6E :10166000C70101960E94E22F51C180910B058111A3 :101670004EC18B81803F49F0813F49F0823F49F064 :10168000833F09F044C1E3E005C0E0E003C0E1E0CE :1016900001C0E2E035E0E39FF0011124E95FFE4F75 :1016A00083818C8380EBA5C080910B0581112FC1B4 :1016B0008B819C81903B08F090EB803F49F0813F0B :1016C00049F0823F49F0833F09F021C1E3E005C0C2 :1016D000E0E003C0E1E001C0E2E055E0E59FF00199 :1016E0001124E95FFE4F9383A9C080910B058111FE :1016F0000EC1EB81E43558F0E03FC1F0E13FC1F0AD :10170000E23FC1F0E33F09F002C1E3E014C0F0E0C2 :10171000CF01880F991FE80FF91FE65FFB4F81810A :101720008C8380818D8382818E83F0C0E0E003C052 :10173000E1E001C0E2E065E0E69FF0011124E95F2D :10174000FE4F81818C8382818D831E82DFC08091D8 :101750000B058111DCC0EB818D819C81E43558F053 :10176000E03FB1F0E13FB1F0E23FB1F0E33F09F01B :10177000CEC0E3E012C02E81F0E0AF01440F551F50 :10178000E40FF51FE65FFB4F808391832283BEC089 :10179000E0E003C0E1E001C0E2E075E0E79FF001B6 :1017A0001124E95FFE4F9183828348C080910B052D :1017B0008111ADC0EB81E43008F0A9C02E2F30E0DC :1017C00085E0E89FF0011124E95FFE4F9081969536 :1017D0009695E3EAF1E080E0419194130CC08C838C :1017E00085E0829FF001839FF00D1124E95FFE4F99 :1017F00084818D838BC08F5F8F3071F788C080911B :101800000B05811184C0EB81E43008F080C0AC810D :10181000AF3008F07CC02D8195E0E99FF0011124E4 :10182000E95FFE4FB0E0AD55BE4F8C91982F990FF8 :10183000990F80818370892B808324831A82609121 :1018400006057091070580910805909109050E9491 :10185000EA135DC080910B05811159C081E00E949F :10186000161454C086E08B838EE08C838DEFE82EB7 :1018700083E0F82E16E0A0E0B4E040E050E0B032A3 :1018800058F5F70160817181C101042E02C0880FF3 :10189000991F0A94E2F7682379238B2F90E0910136 :1018A0000A2E01C0220F0A94EAF7672B51F061E07B :1018B00070E06C0F7D1F860F971FFC013081232B7A :1018C0000AC061E070E06C0F7D1F860F971F2095A6 :1018D000FC01308123232083AF5FA83010F0BF5F6D :1018E000A0E04F5F5F4F4E30510549F61150F2E0D6 :1018F000EF0EF11C1111C1CF09C00E940E1F81E033 :101900009B81911101C080E0809309041A8280912B :10191000D105843009F08AC81091E9001F709091B8 :10192000EC00892F817090FD80E8182B82E0809375 :10193000E9008091E80080FF0DC040E050E060E2E7 :1019400070E0CE0101960E94231F8091E8008E77FF :101950008093E8001F701093E90068C8F9BC19BDB6 :1019600009B400FEFDCF8091D8008F7D8093D80010 :101970008091E00082608093E0008091E00081FD32 :10198000FCCF0E940E1F0C94220590915E0392FFE3 :101990000DC0282F2871283019F4877F846006C075 :1019A000282F2471243011F48B7F886093FF0DC0A1 :1019B000282F2871283119F4877E846106C0282FCA :1019C0002471243111F48B7E886120915F0320FF04 :1019D0000DC0382F3871383019F4877F816006C008 :1019E000382F3171313011F48E7F886021FF0DC0A6 :1019F000282F2871283119F4877E816106C0282F8D :101A00002171213111F48E7E886194FD877E0895C5 :101A1000F894E82FE295EF70F0E031A1282F2F70B5 :101A200081E090E001C0880F2A95EAF7982F909501 :101A3000932391A392A1892B82A378940895CF93A5 :101A4000DF930E940B2AEC018238910559F1A0F432 :101A50008133910509F473C040F48932910509F48A :101A600067C08A9709F472C084C08533910509F470 :101A700058C0C997B9F07DC0833E910571F138F423 :101A8000803E9105B1F0823E910511F172C0863E13 :101A90009105B9F1873E9105C9F1843E910509F0A0 :101AA00068C024C080915E0380FD5DC081FD5BC085 :101AB00060C080915E0380FD50C080915F0380FF15 :101AC00036C180915E0384FD30C1C3EED0E02FC1EA :101AD00080915E0382FF2BC1F4CF80915E0382FD73 :101AE0003FC080915F0380FD3EC0EBCF80915F03DC :101AF00081FF1DC180915E0384FD17C1C7EED0E058 :101B000016C180915E0383FF12C1F4CF80915E0302 :101B100083FD2CC080915F0381FFECCFC4EED0E049 :101B200006C180915E0385FF02C1C9E2D0E0FFC01B :101B300080915E0385FFFBC0C5E3D0E0F8C08091D3 :101B40005E0386FFF4C0CAE2D0E0F1C080915E037C :101B500086FFEDC0C1E3D0E0EAC0C9E3D0E0E7C052 :101B6000C2EED0E0E4C0C0EED0E0E1C0C6EED0E00E :101B7000DEC0C11582E5D80708F066C0C11591E541 :101B8000D90728F0DC2FCC27C16FD06AD0C0C83E5F :101B9000D10560F5C03ED10508F0C9C0C83AD105ED :101BA000B0F4C53AD10540F0C55AD0E0C15EDC4F73 :101BB000C881D0E0D064BBC0C130D10509F4B7C042 :101BC00008F4B3C0C430D10508F4AFC0B0C0CF3BF7 :101BD000D10508F0AAC0C85AD0E0CC0FDD1FCE5DF9 :101BE000DC4F0990D881C02DD464A1C0C11520E577 :101BF000D207E0F0CE0174E0969587957A95E1F7EB :101C000083709C2F937021E030E002C0220F331FBD :101C10009A95E2F73C68382BCF70C695C69580E25E :101C2000C89FE0011124C22BD32B81C0C11580E4D1 :101C3000D80718F0DF70D06A7AC0CE019A95811566 :101C40009F4108F474C071C0C11586E5D807F0F54E :101C5000C11595E5D90750F08C2F0E94C50C8F71E6 :101C6000C82FD0E0DC2FCC27D06261C0C11524E59D :101C7000D20728F0DC2FCC27C46FD06A58C09E0151 :101C8000237033278C2F86958695C115D34578F41C :101C9000C1E0D0E002C0CC0FDD1F2A95E2F720E2C0 :101CA000829FC0011124C82BD92BDC6840C0C1E041 :101CB000D0E002C0CC0FDD1F2A95E2F720E2829F20 :101CC000C0011124C82BD92BDA6831C0C1152AE50F :101CD000D207E8F4C11589E5D80780F08C2F8F7002 :101CE0000E94C50C94E0D695C7959A95E1F7CF7000 :101CF000D0E0DC2FCC27D069C82B19C0C11598E5DE :101D0000D90798F0DC2FCC27C06FD06A10C0CE0165 :101D100090568115904248F48D2F8F710E94C50C0A :101D2000DD27D0628F71D82B02C0C0E0D0E0CE0199 :101D3000DF91CF910895CF92DF92EF92FF926C01E5 :101D4000EE24FF24C114D104E104F10421F0C70101 :101D5000B60120E101C020E0C72ED82EE92EFF24D5 :101D6000C114D104E104F10419F0285FC701B601E0 :101D70006B017C0154E0F694E794D794C7945A958C :101D8000D1F7C114D104E104F10419F02C5FC701AB :101D9000B6016B017C0142E0F694E794D794C794B6 :101DA0004A95D1F7C114D104E104F10419F02E5F72 :101DB000C701B601DC01CB01B695A795979587952C :101DC000892B8A2B8B2B09F02F5F822FFF90EF90AE :101DD000DF90CF900895882311F084EC01C084E84F :101DE0008093BC0080E49FE1A0E0B0E02091BC00C3 :101DF00027FD08C00097A105B10561F00197A10971 :101E0000B109F4CF892B8A2B8B2B21F08091BB0059 :101E100090E008958FEF9FEF0895DB01FC0120E033 :101E200030E084E82A173B071CF591919093BB00A2 :101E30008093BC0040E45FE160E070E09091BC0002 :101E400097FD0AC0411551056105710599F0415092 :101E5000510961097109F2CF452B462B472B51F0EF :101E60009091B900987F983229F42F5F3F4FDACFD5 :101E7000C90108958FEF9FEF089584E98093BC0016 :101E80008091BC0084FDFCCF0895262F94EA9093A6 :101E9000BC0040E45FE160E070E09091BC0097FD21 :101EA0000AC0411551056105710549F041505109BC :101EB00061097109F2CF452B462B472B19F48FEF9F :101EC0009FEF08959091B900987F983011F090316C :101ED000B1F7682F660F622B6093BB0084E8809394 :101EE000BC0080E49FE1A0E0B0E02091BC0027FDB1 :101EF00008C00097A105B10511F30197A109B10927 :101F0000F4CF892B8A2B8B2BD1F28091B900887F5B :101F1000883111F0803499F680E090E00895FF92C6 :101F20000F931F93CF93DF931F92CDB7DEB78B0133 :101F3000FC01F1808DE1898360E08F2D0E94450FC7 :101F400097FD1AC061E070E0CE0101960E940D0F6E :101F500097FD12C061E08F2D0E94450F97FD0CC0C8 :101F600080E00E94EB0E97FD07C0F80180830E947D :101F70003D0F21E090E001C0282F822F0F90DF91CC :101F8000CF911F910F91FF9008950F931F93CF93BF :101F9000DF93EB018A0160E00E94450F97FD09C0C5 :101FA000B801CE010E940D0FEC0197FF0E943D0F7A :101FB000CE01DF91CF911F910F910895CF93DF93C1 :101FC00000D01F92CDB7DEB720914C0130914D016A :101FD00040914E0129833A834B8343E050E0BE0198 :101FE0006F5F7F4FFC0180810E94C50F0F900F90A3 :101FF0000F90DF91CF9108958F929F92AF92BF92F1 :10200000CF92DF92EF92FF920F931F93CF93DF93C4 :10201000CDB7DEB729970FB6F894DEBF0FBECDBFA0 :102020007C01B42EA52E962E872E690160E0FC015E :1020300080810E94450F97FD22C019821A8286E096 :10204000800F8B831C820D838E829F82A886B98627 :1020500069E070E0CE0101960E940D0F97FD0FC060 :10206000B801C6010E940D0F97FD09C00E943D0FE7 :10207000C7010E94DE0F97FD02C0912F01C0082FFB :10208000802F29960FB6F894DEBF0FBECDBFDF912B :10209000CF911F910F91FF90EF90DF90CF90BF9065 :1020A000AF909F908F9008950F931F93CF93DF93DE :1020B00000D000D0CDB7DEB709831A832B833C83D1 :1020C00004E010E09E012F5F3F4F0E94FC0F0F9035 :1020D0000F900F900F90DF91CF911F910F91089566 :1020E000EF92FF920F931F93CF93DF9300D000D016 :1020F000CDB7DEB77C01162F19821A821B821C8293 :102100009E012F5F3F4F48E259E060E87FEBFC0102 :10211000808191810E947B1F97FD36C089819A81C1 :10212000AB81BC8141E050E060E070E0F7010280EB :1021300004C0440F551F661F771F0A94D2F711235E :1021400029F0842B952BA62BB72B08C040955095D2 :102150006095709584239523A623B72389839A835A :10216000AB83BC8309811A812B813C8148E259E011 :1021700060E87FEBF701808191810E94541018166E :10218000190614F480E090E00F900F900F900F90DC :10219000DF91CF911F910F91FF90EF9008950F93D2 :1021A0001F93CF93DF9300D01F92CDB7DEB78C0182 :1021B000BE016D5F7F4F0E948F0F97FD2EC08B81F8 :1021C000F8019281981739F18283982F9370923099 :1021D00039F0869586958370823081F460E001C085 :1021E00061E0F801838194810E94701097FD15C011 :1021F00087E78A83AE014E5F5F4F05C086E689831D :10220000AE014F5F5F4F63E2F80181810E944F1F73 :102210001816190614F480E090E00F900F900F90BC :10222000DF91CF911F910F9108950F931F93CF933B :10223000DF931F92CDB7DEB78C01BE016F5F7F4F7A :102240000E948F0F97FD12C09981292F2370F801EA :1022500083819481211102C060E001C061E00E948D :1022600070101816190614F480E090E00F90DF91BA :10227000CF911F910F910895CF92DF92EF92FF922D :102280000F931F93CF93DF9300D000D01F92CDB751 :10229000DEB76C018FEFF6018283E380F480F701F3 :1022A00042815381648175814D5F534F6F47704404 :1022B000808191811D8201E010E09E012B5F3F4FE4 :1022C0000E94FC0F97FD3CC060E0C7010E947010A7 :1022D00019821A821B821C829E012F5F3F4F48E0A9 :1022E00059E060E87FEBF701808191810E947B1FBC :1022F00097FD26C001E010E020E030E0F701028009 :1023000004C0000F111F221F331F0A94D2F78981C6 :102310009A81AB81BC81082B192B2A2B3B2B09837B :102320001A832B833C8348E059E060E87FEB80818F :1023300091810E9454101816190614F480E090E060 :102340000097C9F4F6012081222369F0213099F425 :1023500085E08983AE014F5F5F4F6AE1F6018181BD :102360000E944F1F03C0C6010E94151118161906BE :1023700014F480E090E00F900F900F900F900F906A :10238000DF91CF911F910F91FF90EF90DF90CF9051 :1023900008950F931F93CF93DF9300D000D000D008 :1023A000CDB7DEB70B9A13981092BA0080E28093F3 :1023B000B8001092BC008FE19EE40197F1F700C0D5 :1023C0000000139A9FEF20E782E091502040804068 :1023D000E1F700C000008CE08E8301E010E09E0178 :1023E0002A5F3F4F4AEF50E360E87FEB8CE391E0D8 :1023F0000E94FC0F97FD4CC01D829E012B5F3F4F3A :1024000042E154E362ED7FEB8CE391E00E94FC0F2C :1024100097FD3EC019821A821B821C829E012F5F8B :102420003F4F48E054E362ED7FEB8CE391E00E9484 :102430007B1F97FD2DC009811A812B813C81016092 :1024400009831A832B833C8348E054E362ED7FEBDE :102450008CE391E00E94541097FD1AC004E813E346 :1024600023E030E040E050E360E87FEB8CE391E074 :102470000E94541097FD0CC004E813E324E030E000 :1024800048E450E960E87FEB8CE391E00E9454104F :1024900087E391E00E943C1182E491E00E943C11AC :1024A0008DE391E00E943C1180914F019091500189 :1024B000A091510189839A83AB8343E050E0BE0130 :1024C0006F5F7F4F80913C010E94C50F04E610E0D2 :1024D00087E391E00E9415118FE19EE40197F1F7E7 :1024E00000C000000150110999F726960FB6F89424 :1024F000DEBF0FBECDBFDF91CF911F910F91089529 :102500009F92AF92BF92CF92DF92EF92FF920F9382 :102510001F93CF93DF9302E513E08FE7E82E81E06E :10252000F82EC0E0D0E0912CCC24C394D12CB7017C :10253000D7018C91F894E82FE295EF70F0E021A19B :102540008F70A60102C0440F551F8A95E2F7CA0199 :10255000922F982B91A392A18095892382A378949E :1025600000C0E5E8F1E020E030E0A12CB12C419181 :10257000842F82958F7090E0DC0190968C9190E092 :102580004F7002C0959587954A95E2F780FD08C087 :10259000C601022E02C0880F991F0A94E2F702C0FA :1025A00080E090E0A82AB92A2F5F3F4F2E303105F6 :1025B000F1F6BFEFEB1AFB0AFB0180810E94080DC8 :1025C000C530D10519F0F0E5FA95F1F7D8018D91F4 :1025D0009C911197A816B90621F0AD92BC9281E0AA :1025E00001C080E0982A21960E5F1F4FC630D105AA :1025F00009F09DCF992049F081E080930E050E945B :10260000361A90930D0580930C0580910E05882352 :1026100009F445C020910C0530910D054FB7F89491 :102620008091EA039091EB03A091EC03B091ED034C :102630004FBF821B930B069790F1809152039091AC :1026400053039093FE038093FD0380915403909174 :102650005503909300048093FF038091560390915B :102660005703909302048093010480915803909142 :102670005903909304048093030480915A0390912A :102680005B03909306048093050480915C03909112 :102690005D03909308048093070410920E058091C7 :1026A0000A058823E1F1BFEFE0E7F2E0B150E04036 :1026B000F040E1F700C0000081E08093E00080E29C :1026C0008093D8001092C9008FE097E20197F1F74C :1026D00000C000001DBA109268001CBC10BE1FBADA :1026E00010927A0010926E0010926F00109270009B :1026F000109271001092C9001092BC0088E081B95C :1027000014B817B81AB81DB810BA82B915B818B8E5 :102710001BB81EB811BA0E94C9110C94527880914E :102720000F0590911005883EA3E09A076CF0109277 :10273000100510920F0582E491E00E94CF108DE306 :1027400091E00E94CF1005C00196909310058093F0 :102750000F05892DDF91CF911F910F91FF90EF9081 :10276000DF90CF90BF90AF909F90089581E08093CD :10277000E00080E28093D800E9ECF0E010828FE086 :1027800097E20197F1F700C000001DBA10926800AF :102790001CBC10BE1FBA10927A0010926E001092EC :1027A0006F00109270001092710010821092BC00A5 :1027B00088E081B914B817B81AB81DB810BA82B930 :1027C00015B818B81BB81EB811BA0E94C9110C94DC :1027D000007E089520910B05211110C00E949B0ED0 :1027E000843060F495E0989FF0011124E95FFE4F7A :1027F000A8E0B6E001900D929A95E1F708959091C6 :102800000B05911112C080930A0180930F018093F0 :10281000140180931901609106057091070580915C :102820000805909109050C94EA13089544E150E0DD :1028300063EE72E0882361F087E091E00E94D22F7E :102840004CEF50E067EF72E08AE094E00C94D22FF6 :1028500087E091E00E94B42F4CEF50E067EF72E008 :102860008AE094E00C94B42F80910806837029F0DC :102870008C69809308061092060181E080930B0515 :1028800008958F929F92AF92BF92CF92DF92EF9274 :10289000FF920F931F93CF93DF9300D000D01F922E :1028A000CDB7DEB7FC018081918123813481232B58 :1028B00031F09F3F31F491E08F3F19F403C091E074 :1028C00001C090E090FD19C57F0185E0DE01119601 :1028D00001900D928A95E1F7F701228189819A8111 :1028E000222349F00E949D1B182F682F89819A810D :1028F0000E943F1C03C00E94131C182F69817A811B :10290000812F0E940B2A8C0180910904811132C20F :102910000115FCE51F0731F168F4003E110509F4CB :102920005FC0043E110509F460C00932110509F0C9 :102930008EC10EC00A3C3CE5130769F10B3C8CE5E7 :102940001807C1F0033C9CE5190709F080C136C0A7 :1029500080911205882309F44CC0809111058823C9 :1029600009F447C0F7018281882309F403C20E9459 :10297000341400C2F7018281882309F4FBC18091DD :102980000B06E8EBF1E092919817B0F001E0E23B22 :10299000F007C9F722C0F7018281882309F4EAC150 :1029A00080910B06E2EBF1E028EB31E02E173F07B8 :1029B000A1F091918917D0F7892F0FC0F70182817B :1029C000882309F4D7C180910B06811103C080913F :1029D000470103C08093470180E00E94FF13CAC1F2 :1029E000F70182818093120504C0F70182818093F0 :1029F0001105F7018281882309F48EC11092130515 :102A00000230FCE51F0708F471C106312CE51207FE :102A100038F098012B5F3C452930310508F066C13C :102A20000E94C81A90935F0380935E0300313CE5D7 :102A3000130709F4C3C008F041C008309CE519072A :102A400009F49AC0F0F40430FCE51F0709F487C0CC :102A500068F402303CE5130709F477C003301C45E5 :102A600009F0E5C080915E03826076C006309CE587 :102A7000190709F46EC008F07BC080915E0388607E :102A80006BC00C30FCE51F0709F485C068F40A3000 :102A90003CE5130709F474C008F079C00E940E1FCA :102AA00080915E03806858C00E309CE5190709F4D8 :102AB00076C008F07FC080915E038BC00C3FFCE5C0 :102AC0001F0709F44FC018F503313CE5130709F45B :102AD0007DC078F401319CE5190709F473C0023117 :102AE0001C4509F0A4C00E940E1F80915E038F77E1 :102AF00033C00531FCE51F0709F472C008F486C035 :102B00000B3F1C4509F093C080915F033EC0011547 :102B10008DE5180709F45FC058F40E3FECE51E0779 :102B200009F444C008F43FC080915F0382602DC067 :102B300002302DE5120709F475C008F45DC00330BA :102B40001D4509F074C060E06EC080915E03816035 :102B500003C080915E03806180935E0368C08091B2 :102B60005E0311C080915F03826080935F035FC04A :102B700080915E038062F0CF80915E038064ECCF31 :102B800080915E0388608460E7CF8160EECF8091A2 :102B90005E038E7FE1CF80915E038D7FDDCF8091DC :102BA0005E03877FD9CF80915F0318C080915F0358 :102BB0008D7FDBCF80915E038F7ECECF80915E03D1 :102BC0008F7DCACF80915E038F7BC6CF80915E03DD :102BD000877F8B7FC1CF80915F038D7F8E7FC5CF35 :102BE00080915E0382FB222720F991E0922790FBDF :102BF00082F990FB83F9B0CF80915F03982F909575 :102C000091708E7F892B90FB81F9AFCF0E940E1FB0 :102C100080915E0387FB222720F991E0922790FBA9 :102C200087F99ACF61E08EE090E00E94E22F6091F8 :102C30005E0310915F0384E090E00E94E22F612F19 :102C400081E290E00E94E22F0E940E1F93C0043F99 :102C5000FCE51F07A1F406E221EE40EE64EF7CE5FF :102C60000AC0083D9CE5190709F0C3CE06E221EE33 :102C700041EE68ED7CE5C7010E944E297BC0053F0F :102C80002CE51207A0F4093D3CE5130731F407E2F7 :102C900025EE45EE69ED7CE5EECF0A3D8CE51807A3 :102CA00001F708E221E045EE6AED7CE5E4CF063F5E :102CB000ECE51E0731F406E221EE42EE66EF7CE51C :102CC000DACF063FFCE51F0730F407E225EE44EEBD :102CD00065EF7CE5D0CF073F2CE5120709F089CEE0 :102CE00007E225EE46EE67EF7CE5C5CF06313CE511 :102CF000130719F58091A7058A7A91E009F490E00D :102D000090931405882311F065E301C069E285E121 :102D100095E00E94931A0EC006311C4509F048C088 :102D200080911405882309F4E6C265E385E195E006 :102D30000E946B1A0E94491B1DC09801235C3C45F0 :102D400024313105B8F001159CE5190731F00F3D2C :102D50001C4571F50E94D91A0DC00E940E1FFFE795 :102D60000AE116E0F15000401040E1F700C0000019 :102D70000E94B6138091A405877009F4BEC2F701C2 :102D80008281882309F4B9C282E00F900F900F90DE :102D90000F900F90DF91CF911F910F91FF90EF90C7 :102DA000DF90CF90BF90AF909F908F900C94A51C18 :102DB000F70100811181882349F0C8010E949D1B01 :102DC000D82E682FC8010E943F1C04C0C8010E9471 :102DD000131CD82EB8018D2D0E941F0D8C01982E2A :102DE000F701B280A580A2949FE0A9228091A4055A :102DF000877099F0BB2089F0812F807F803421F08B :102E000080E2800F883048F082E00E94A51C80910B :102E1000A4058770DD24D3948111D12CC12EC294D6 :102E20008FE0C8228C2D90E08C30910508F035C2DF :102E3000FC01E957FF4F0C949130812F807F1F7068 :102E4000882311F01295107FBB20B9F0112309F4EB :102E50000FC280E2800F883010F0911006C0809180 :102E6000A705182B1093A70505C08091A605182B60 :102E70001093A6050E94491BFBC1802F0E94412E82 :102E8000112309F40AC2005E1095083010F0911069 :102E900006C08091A70518231093A70505C080914F :102EA000A60518231093A6050E94491BF6C1812F81 :102EB000807F1F70803211F01295107F992021F0D1 :102EC000F1E09F16E1F02AC0BB2081F08091A805B7 :102ED000AA2051F001E0A01207C0182B181709F41E :102EE000DCC11093A805D9C1812B10C0AA2021F004 :102EF00021E0A21609F4D1C10E94431B27C0BB20C8 :102F000041F035E03A1508F4C8C1812F0E94372EF0 :102F1000C4C184E08A1508F4C0C118C0BB2049F0C0 :102F2000AA2099F3F701858180FFA2C18F70858364 :102F3000ECCFAA2059F0093309F0ACC1FFEF13EF31 :102F400021E0F15010402040E1F7A2C1812F0E9402 :102F50002C2EA3C1812F86958695837019F0813020 :102F600059F09BC1BB2019F0C801937002C080E0EA :102F700090E00E942C2997C1BB2019F0C8019370E2 :102F800002C080E090E00E9416298DC1812F8370DD :102F900009F069C0B11085C1902F929596959770F0 :102FA000990F990F802F8F70882E912CA12CB12C06 :102FB000092E04C0880C991CAA1CBB1C0A94D2F7C9 :102FC00004FF12C04FE050E060E070E004C0440F26 :102FD000551F661F771F9A95D2F7DB01CA018095AE :102FE0009095A095B09503C080E090E0DC01169527 :102FF0001695412F4370423019F1C8F40091A9058C :103000001091AA052091AB053091AC05413059F0E3 :1030100088299929AA29BB29BC01CD0160237123E4 :10302000822393230AC0802A912AA22AB32ABC01B0 :10303000CD01682979298A299B290E94DF1C31C189 :1030400088299929AA29BB290091A9051091AA05C7 :103050002091AB053091AC05BC01CD0160277127F3 :1030600082279327EACFBB2019F0812F817001C0FE :103070008695882309F415C1902F9295969597709F :10308000990F990F802F8F70882E912CA12CB12C25 :10309000092E04C0880C991CAA1CBB1C0A94D2F7E8 :1030A00004FF12C04FE050E060E070E004C0440F45 :1030B000551F661F771F9A95D2F7DB01CA018095CD :1030C0009095A095B09503C080E090E0DC01169546 :1030D0001695412F43704230D9F068F500910605EE :1030E000109107052091080530910905413059F0EC :1030F00088299929AA29BB29BC01CD016023712304 :10310000822393231EC0802A912AA22AB32A13C0A5 :1031100088299929AA29BB2900910605109107053C :103120002091080530910905BC01CD016027712768 :103130008227932706C0BC01CD01682979298A29F5 :103140009B290E946A1CADC01F70BB2039F0812FE3 :103150000E94BE1C802F0E94372EA3C0802F0E9489 :103160002C2E812F0E94801C9CC0802F32EF931642 :1031700009F440C0391538F090EF991661F0E1EF8D :103180009E1699F170C0F3EF9F16D9F124EF9216B5 :1031900009F44EC068C0BB2019F134E03A1508F4B8 :1031A0007CC01F7181E090E0A0E0B0E0AC01BD0107 :1031B00004C0440F551F661F771F1A95D2F78091E0 :1031C000060590910705A0910805B09109058A01AF :1031D0009B01082719272A273B27C901B80125C0C9 :1031E00025E02A1508F459C0DCCFBB2029F0812F37 :1031F0008F712CC0BB20D9F3812F8F710E94801C4E :103200004CC0BB2079F01F7181E090E0A0E0B0E0FD :10321000BC01CD0104C0660F771F881F991F1A9546 :10322000D2F703C060E070E0CB010E946A1C35C099 :10323000BB2079F01F71812F0E94BE1C38E0139FC4 :10324000C001112483608093A405812F0E94BE1CBD :1032500024C081E00E94A51C81E08A15F0F482E080 :103260000E94A51C1AC0BB2039F0AA2009F4BFCFC8 :10327000802F0E949D2E11C0AA2009F4BDCF893352 :1032800049F49FEFE3EFF1E09150E040F040E1F7C7 :1032900000C00000802F0E94412E88EF8C0D8430EA :1032A00010F40E944229DD2041F18091A40580FDA7 :1032B00024C0F70112828595859585950E94BE1CD4 :1032C000C7010E9441148091A40585958595859537 :1032D0000F900F900F900F900F90DF91CF911F9153 :1032E0000F91FF90EF90DF90CF90BF90AF909F90A5 :1032F0008F900C94801C69E219CD0F900F900F9065 :103300000F900F90DF91CF911F910F91FF90EF9051 :10331000DF90CF90BF90AF909F908F9008950895C9 :103320008091AE05089580E00895CF93DF9300D09B :103330001F92CDB7DEB79091D105943011F58983F6 :103340007B836A839093E9008FEF9091E80081502E :1033500095FD06C09AE69A95F1F700C08111F5CF68 :103360008091E80085FF0DC040E050E063E070E030 :10337000CE0101960E94231F8091E8008E778093F2 :10338000E8000F900F900F90DF91CF910895BC014E :1033900084E00C949519BC0183E00C949519CF93AB :1033A000DF9320914801222339F020915E0327FF0B :1033B00003C060E224E002C068E021E02093E9005D :1033C0002FEF3091E800215035FD06C03AE63A95DE :1033D000F1F700C02111F5CF2091E80025FF1DC0B5 :1033E000EC0180914801811105C040E050E068E0A7 :1033F00070E003C070E040E050E0CE010E94231F67 :103400008091E8008E778093E80080E2FE01AFEAC9 :10341000B5E001900D928A95E1F7DF91CF91089583 :1034200078941F920F920FB60F9211248F939F934F :10343000AF93BF938091EA039091EB03A091EC03CB :10344000B091ED030196A11DB11D8093EA03909305 :10345000EB03A093EC03B093ED03BF91AF919F9169 :103460008F910F900FBE0F901F9018952FB7F89463 :103470008091EA039091EB03A091EC03B091ED03EE :103480002FBF08951F920F920FB60F9211248F93A2 :103490009F93AF93BF9380916203811113C080917A :1034A000EA039091EB03A091EC03B091ED034196F8 :1034B000A11DB11D8093EA039093EB03A093EC034D :1034C000B093ED03BF91AF919F918F910F900FBE7D :1034D0000F901F901895209148012223C9F0209148 :1034E0005E0327FF15C0262F2695269526952E319B :1034F000C8F4FC01E20FF11D677081E090E001C0AB :10350000880F6A95EAF780959281892382830895CE :10351000FC0106962281621301C012823196E817DF :10352000F907C1F70895209148012223C1F02091A5 :103530005E0327FF14C0262F2695269526952E314B :1035400030F5FC01E20FF11D677081E090E001C0F1 :10355000880F6A95EAF79281892B82830895FC018E :1035600032962FEF30E04191641789F02F3F19F424 :10357000411101C0232F3F5F3630A9F72F3F39F0AB :10358000FC01E20FF11D27FDFA956283089508956D :10359000CF9384E090E00E94C42FC82F81E290E096 :1035A0000E94C42F2C2F30E0A901582BCA01CF91C3 :1035B00008956BEE7EEF80E090E00E94003060E0C6 :1035C00082E090E00E94E22F60E083E090E00E94C1 :1035D000E22F1092A9051092AA051092AB05109245 :1035E000AC0560E084E090E00E94E22F60E081E2C0 :1035F00090E00E94E22F60E085E090E00E94E22FE0 :1036000060E086E090E00E94E22F6FEF87E090E0BC :103610000E94E22F40E050E0BA0188E090E00E9472 :10362000F42F60E08DE090E00E94E22F40E050E057 :10363000BA0188E190E00E94F42F60E087E190E019 :103640000E94E22F40E050E0BA018CE190E00E943D :10365000F42F60E080E290E00E94E22F40E050E032 :10366000BA0188E190E00E94F42F40E050E0BA01F6 :103670008FE090E00E94F42F40E050E0BA0183E137 :1036800090E00C94F42F8091A80581111092A80568 :1036900008959091A7058091A605892B2091A505F5 :1036A000982F922B909315058091A8058823D9F027 :1036B000892B8093150580914801882331F08091F2 :1036C0005E0387FF02C08EE101C086E0E7E1F5E01E :1036D00090E0815028F021912223D9F39F5FF9CF08 :1036E00091110E94431BE0916003F09161033097B8 :1036F000A9F080914801882359F080915E0387FFEB :1037000007C0809115058093160585E08093150507 :103710000280F381E02D85E195E00994089580E031 :1037200090E00E942C2980E090E00E9416291092DF :10373000A6051092A5050C94491BBF92CF92DF926B :10374000EF92FF920F931F93CF93DF938C01C09062 :103750000605D0900705E0900805F09009058091D6 :10376000A9059091AA05A091AB05B091AC05C82A16 :10377000D92AEA2AFB2ACFE1D0E0D701C6010C2ED4 :1037800004C0B695A795979587950A94D2F780FDC2 :1037900004C0219790F7B12C07C0BC2EB8018C2F24 :1037A0000E941F0D0197A9F38B2DDF91CF911F91DF :1037B0000F91FF90EF90DF90CF90BF900895CF933F :1037C000DF93EC010E949D1BBE010E941F0DDF9143 :1037D000CF9108950E94DF1B292F2F70E92FE295CA :1037E000EF704E2F50E0FA013297EE30F105B8F449 :1037F000ED56FF4F0C949130803F99F018F4883EBD :1038000070F40FC0843F59F40CC0883E50F0813FE3 :1038100031F407C0822F869586958695089580E0BD :10382000089581E008952EE0929F800D1124682F65 :10383000669566956695982F977085E0689FB001AC :10384000112440E050E080E0FB01E40FF51FE35954 :10385000FA4F208130E0092E02C0369527950A9450 :10386000E2F721703327042E01C0220F0A94EAF7F1 :10387000822B4F5F5F4F4530510531F708952EE0A1 :10388000929F800D1124E82FE695E695E6958770C6 :1038900051E001C0550F8A95EAF785E0E89FF001F5 :1038A0001124E359FA4F20E030E070E04081CB0171 :1038B000022E02C0969587950A94E2F78170819551 :1038C00084278523842781932F5F3F4F253031053F :1038D00069F70895CF92DF92EF92FF926B017C011E :1038E0000E94EA13C0920605D0920705E0920805EF :1038F000F0920905FF90EF90DF90CF900C948F1B12 :103900000F931F9341E050E060E070E004C0440F6B :10391000551F661F771F8A95D2F740955095609581 :1039200070958091060590910705A0910805B091CA :1039300009058A019B01082319232A233B23C90176 :10394000B8011F910F910C946A1C2091A4058095D9 :1039500082238093A405982F977079F430E0482F44 :10396000082E000C550B2417350739F085958595E1 :1039700085950E94801C1092A40508950F931F93B3 :1039800041E050E060E070E004C0440F551F661F46 :10399000771F8A95D2F78091060590910705A0912F :1039A0000805B09109058A019B01082B192B2A2BC8 :1039B0003B2BC901B8011F910F910C946A1C6093B5 :1039C000A9057093AA058093AB059093AC050C9460 :1039D0008F1B80916C0590913B05891719F08F5FC3 :1039E0008770FBCF08950F931F93CF93DF93809140 :1039F0003A0582958F7009F05DC080913705882364 :103A000009F458C080916C0510913B056091350513 :103A100070913605C0913805D091390591E06F3F1E :103A200009F090E0292F06E0811709F443C02097A0 :103A300021F07F3F21F030E003C031E001C0322FA0 :103A400090E030FD34C0089FF001099FF00D112473 :103A5000DF01A45CBA4F11963C911197371327C030 :103A60003C91361324C012963C91129731111FC01D :103A700013964D915C9114974C1B5D0B483C51057E :103A8000B0F480913A058F70806180933A05EF5BC6 :103A9000FA4F80818F708061808385E395E00E947A :103AA0004114DF91CF911F910F910C94E91C019665 :103AB0008770BACFDF91CF911F910F9108959F9298 :103AC000AF92BF92CF92DF92EF92FF920F931F932C :103AD000CF93DF93CDB7DEB761970FB6F894DEBF13 :103AE0000FBECDBF8C0185E0F801DE011D9601906F :103AF0000D928A95E1F7F80190818181E280309101 :103B000035056091360540913805509139054115CC :103B1000510531F06F3F31F421E03F3F19F403C00C :103B200021E001C020E0F22FF1709F2E20FD23C183 :103B3000F801C380D48025E3A22E25E0B22EF090B8 :103B40003705F601E41BF50BFF2009F4CEC02091E8 :103B50003A05E83CF10508F099C0422F407F09F092 :103B600051C0681311C039130FC0FE2CE1100CC0F6 :103B70002F70206120933A05C5010E944114809165 :103B80003A05F801858337C1CD2831F08F3F31F4F4 :103B900021E09F3F19F403C021E001C020E020FD97 :103BA00003C021E02E2502C020E030E0F22FF170AA :103BB000FF2E20FF1DC020916C0540913B0556E073 :103BC000241709F4F6C030E0529FF001539FF00D26 :103BD0001124E45CFA4F6181861306C0608196135C :103BE00003C06281E61204C02F5F3F4F2770E8CF09 :103BF000FE2CEE2009F4FFC080913A05816080938D :103C00003A0550C0681307C0391305C0E11003C05E :103C1000F80125838DC09D878E878D859E850E94A6 :103C2000EA1B882369F1EE2059F120913A05822F91 :103C300082958F7090E0029774F080913505909195 :103C4000360598878F831986DB86CA862C87CE0136 :103C500007960E94411486E0F801A5E3B5E00190C3 :103C60000D928A95E1F70E94F31C0DC06817E1F0F0 :103C70009D878E878D859E850E94EA1B81111EC0BF :103C8000C8010E944114FF24F394B5C0422F407F25 :103C900069F785E395E00E94411486E0F5011192F1 :103CA0008A95E9F7F12CA7C03913E2CFE110E0CFF4 :103CB000F8012583C8010E94411457C0EE2001F38A :103CC00020913A05822F82958F7090E002971CF226 :103CD00080913505909136059A8389831B82DD8218 :103CE000CC822E83CE010196B4CFE83CF105E8F5F5 :103CF000FE2CEE2029F2681327C0391325C020912D :103D00003A0520FD18C0822F82958F70482F50E011 :103D10004115510581F0F80125834F30510541F0DF :103D20008F5F982F9295907F822F8F70892B85833C :103D3000C8010E94411486E0F801A5E3B5E00190B6 :103D40000D928A95E1F757C09D878E878D859E8558 :103D50000E94EA1B81117FCF80913A058160809398 :103D60003A05C8010E94411446C086E0F50111924F :103D70008A95E9F740C0EE2009F482CF9D878E87AF :103D80008D859E850E94EA1BF82E882309F478CF42 :103D900086E0F801A5E3B5E001900D928A95E1F780 :103DA00080913505909136050E94DF1B0E94F31C1F :103DB00022C09D878E878D859E850E94DF1B292FBF :103DC00022952F70223028F49F7039F0811105C0A0 :103DD0000BC0243028F49F7049F4805E883020F0B6 :103DE000C8010E9441149F2CF92C05C0F80195814F :103DF000907F99F7F9CF8F2D61960FB6F894DEBFBB :103E00000FBECDBFDF91CF911F910F91FF90EF902B :103E1000DF90CF90BF90AF909F9008951092A7052C :103E200080914801882331F080915E0387FF02C0B2 :103E30008EE101C086E0E7E1F5E0DF011D928A95A1 :103E4000E9F70C948F1BEF92FF920F931F93CF9380 :103E5000DF937C018B010E94122C811119C0E701B4 :103E600001151105A1F08091E80085FD0AC080913F :103E7000E8008E778093E8000E94122C882381F35B :103E800007C089918093F10001501109E9CF80E0CA :103E9000DF91CF911F910F91FF90EF9008950F93B5 :103EA0001F93CF93DF931F92CDB7DEB769838A014B :103EB00060E00E94450F97FD13C061E070E0CE0105 :103EC00001960E940D0F97FD0BC061E070E0C801E4 :103ED0000E940D0F8C0197FD05C00E943D0F02C08E :103EE000282F02C0202F912F822F0F90DF91CF918A :103EF0001F910F910895CF92DF92EF92FF920F934F :103F00001F93CF93DF93CDB7DEB72F970FB6F894FB :103F1000DEBF0FBECDBF7C0189011A861B861C86C1 :103F20001D8619821A8286E0D82EDB8281E08C837E :103F300084E08D837E836F835887498749E050E012 :103F4000BE016F5F7F4FF70180810E94C50F97FD13 :103F500040C0C7010E94DE0F97FD3BC060E0F70143 :103F600080810E94450F97FD34C01E86DF8662E087 :103F700070E0CE010E960E940D0F97FD2AC061E001 :103F8000F70180810E94450F97FD23C081E00E94C8 :103F9000EB0E97FD1EC06E01FAE0CF0ED11CE12C96 :103FA000F12C8FEFE81AF80A81E094E0E916F104A9 :103FB0000CF080E00E94EB0E97FD0BC0F6018193A0 :103FC0006F01F4E0EF16F10461F70E943D0F84E009 :103FD00090E097FD09C04A855B856C857D85F80179 :103FE00040835183628373832F960FB6F894DEBFAC :103FF0000FBECDBFDF91CF911F910F91FF90EF903A :10400000DF90CF9008956F927F928F929F92AF92A0 :10401000BF92CF92DF92EF920F931F93CF93DF93D4 :104020003C01C091490181E1C89FC02D1124D1E11B :10403000DC0FD53508F0D4E560910C0666958091CB :104040000406909105060E94AD2A182FCD1708F09E :1040500044C08C2E912CF401ED53FD4F9081809142 :104060004A018923C1F1F401EE0FFF1FE55EFD4F08 :10407000C080D12C80E7C81AD108F401EE0FFF1FD1 :10408000E45EFD4FA080B12CE0E2AE1AB108CC9CFA :104090009001CD9C300D300D1124AA9CC001AB9C29 :1040A000900D900D1124820F931F0E94532A082F08 :1040B0006091090670910A0680910B06E12E950128 :1040C000A601F30109950E94B72A462F282F672FD2 :1040D000C4010E941A2ACF5FB9CF81E0D43508F01D :1040E00080E0DF91CF911F910F91EF90DF90CF9003 :1040F000BF90AF909F908F907F906F900895CF92D8 :10410000DF92EF92FF920F931F93CF93DF936C0197 :10411000C091490181E1C89FC02D1124D1E1DC0F7C :10412000D53508F0D4E560910C06669580910406BB :10413000909105060E94AD2A182FCD1778F5EC2E28 :10414000F12CF701ED53FD4F908180914A018923B5 :1041500019F1F701EE0FFF1FE45EFD4F208130E003 :1041600020523109F701EE0FFF1FE55EFD4F408140 :1041700050E0405751096091090670910A068091FC :104180000B06012FF60109950E94B72A462F282F0A :10419000672FC7010E941A2ACF5FCFCF81E0D435A5 :1041A00008F080E0DF91CF911F910F91FF90EF9089 :1041B000DF90CF900895DF92EF92FF920F931F93BD :1041C000CF93DF937C01C091490181E1C89FC02D4D :1041D0001124D1E1DC0FD53508F0D4E560910C064F :1041E0006695669580910406909105060E94AD2A19 :1041F000D82ECD17F0F40C2F10E0F801ED53FD4F41 :10420000908180914A01892391F060910906709113 :104210000A0680910B062D2D4C2FF70109950E945F :10422000B72A462F282F672FC8010E941A2ACF5F6E :10423000E0CF81E0D43508F080E0DF91CF911F918D :104240000F91FF90EF90DF9008959F92AF92BF92F1 :10425000CF92DF92EF92FF920F931F93CF93DF9352 :104260006C01C091490181E1C89FC02D1124D1E1A9 :10427000DC0FD53508F0D4E560910C06669566959F :1042800080910406909105060E94AD2A182F80E4C3 :10429000810F0E94322A90E8F92EF80E812F0E9499 :1042A000322A20E8922E980ECD1700F5AC2EB12CB4 :1042B000F501ED53FD4F908180914A018923A1F0D2 :1042C0006091090670910A0680910B06E12E0C2F71 :1042D000292D4F2DF60109950E94B72A462F282F28 :1042E000672FC5010E941A2ACF5FDECF81E0D43547 :1042F00008F080E0DF91CF911F910F91FF90EF9038 :10430000DF90CF90BF90AF909F900895CF92DF92B3 :10431000EF92FF920F931F93CF93DF936C01C091A5 :10432000490181E1C89FC02D1124D1E1DC0FD535B1 :1043300008F0D4E520910C0630E040E050E06FEF4B :104340007FEF80E090E00E9406308901CD17E8F50C :10435000EC2EF12CF701ED53FD4F908180914A0135 :10436000892389F19091DB05915097FD15C0492F64 :10437000092E000C550BFA01E552FA4F8189C8133A :10438000F3CF440F551FFA01E552FA4F218D328DBC :104390002017310748F701C0980160910C06C90148 :1043A0000E94AD2AAC016091090670910A068091C5 :1043B0000B06F60109950E94B72A462F282F672F72 :1043C000C7010E941A2ACF5FC1CF81E0D43508F01F :1043D00080E0DF91CF911F910F91FF90EF90DF90E0 :1043E000CF9008952F923F924F925F926F927F925B :1043F0008F929F92AF92BF92CF92DF92EF92FF92F5 :104400000F931F93CF93DF93CDB7DEB727970FB6E8 :10441000F894DEBF0FBECDBF282E4B01209149017D :1044200081E1289F802D11248E83182F1F5E153562 :1044300008F014E53091DB0539839E81911708F06F :1044400077C08E81682E712CF301ED53FD4F908162 :1044500080914A01892309F467C030900906409091 :104460000A06522C1F82C301880F991FDC01A55E2A :10447000BD4FBB83AA83C301880F991FFC01E45E73 :10448000FD4FFD83EC83F9815F16E0F5E52CF12CFF :10449000AA81BB81CC90D12CF701E552FA4F8181E2 :1044A000C81AD108AC81BD81AC90B12C8185A81A05 :1044B000B108CC9C9001CD9C300D300D1124AA9CEC :1044C000C001AB9C900D900D1124820F931F0E9490 :1044D000532A082FF701EE0FFF1FE552FA4F6091A4 :1044E0000C06818D928D0E94AD2A7C019501A6015A :1044F000632D742D8F81F4010995362E472E8F83FD :104500005394C1CF20910B068F81382F329F312DCC :104510001124832F632D742D0E94B72A462F282F34 :10452000672FC3010E941A2A8E818F5F8E8385CFE9 :1045300081E0143508F080E027960FB6F894DEBFCE :104540000FBECDBFDF91CF911F910F91FF90EF90E4 :10455000DF90CF90BF90AF909F908F907F906F90A3 :104560005F904F903F902F9008951F93CF93DF93CC :10457000CDB7DEB7AA970FB6F894DEBF0FBECDBF9A :10458000E3EDF5E08091F100819345E0EB3DF40728 :10459000C9F78091D405833009F460C030F48130CC :1045A00071F0823009F49AC0B1C08A3009F486C033 :1045B0008B3009F46BC0893009F0A8C020C080910D :1045C000D305813A09F0A2C08091E800877F8093EB :1045D000E8008091D7059091D805892B21F460E2FD :1045E0008FEA95E003C060E080E090E070E00E9418 :1045F000D02D8091E8008B778093E80087C0809170 :10460000D305813209F082C08091D7059091D805F9 :10461000009719F0029709F079C08091E800877F30 :104620008093E8008091E80082FD05C08091D1056B :104630008111F8CF6BC08091F2009091F300029746 :1046400029F48091F1008B7F813021F48091F10079 :104650008093AE058091E8008B7754C08091D3059C :10466000813A09F053C08091D7059091D805892BE4 :1046700009F04CC08091E800877F8093E80080912A :10468000E80080FFFCCF8091480137C08091D305BE :104690008132E1F58091D7059091D805892BB1F54C :1046A0008091E800877F8093E8000E94452C8091EC :1046B000D505809348010E940E1F28C08091D30524 :1046C000813221F58091E800877F8093E8000E9485 :1046D000452C8091D6058093AD0518C08091D305F7 :1046E000813AA1F48091E800877F8093E80080916F :1046F000E80080FFFCCF8091AD058093F1008091B0 :10470000E8008E778093E8000E94452C8091E800B5 :1047100083FFDAC18091D3059091D405492F50E0F1 :104720004A30510508F0D0C1FA01EF55FF4F0C9403 :104730009130803821F0823809F0C6C108C08091DC :10474000CF059091D005992389F082600FC08091A8 :10475000D7058F70873008F0B7C18093E90080914A :10476000EB0085FB882780F91092E9009091E80022 :10477000977F9093E8008093F1001092F1006DC153 :10478000282F2D7F09F0A0C1882319F0823061F015 :104790009BC18091D505813009F096C1933009F015 :1047A00080E08093D0052EC08091D50581112AC06C :1047B0008091D7058F702FEF280F263008F084C125 :1047C0008093E9002091EB0020FF1CC0933021F47E :1047D0008091EB00806214C09091EB009061909307 :1047E000EB0021E030E0A90102C0440F551F8A957B :1047F000E2F74093EA001092EA008091EB008860B3 :104800008093EB001092E9008091E800877F80930D :10481000E8000E94452C58C1811156C11091D50560 :104820001F778091E3008078812B8093E300809153 :10483000E800877F8093E8000E94452C8091E80083 :1048400080FFFCCF8091E30080688093E30011112A :1048500002C082E001C083E08093D10535C1805859 :10486000823008F031C12091D5053091D6052C3D1C :1048700053E0350779F583E08A838AE289834FB76D :10488000F894DE01139620E03EE051E2E32FF0E0E1 :1048900050935700E49120FF03C0E295EF703F5F13 :1048A000EF708E2F90E0EA3010F0C79601C0C096EE :1048B0008D939D932F5F243149F74FBF8091E8007E :1048C000877F8093E8006AE270E0CE0101960E9443 :1048D000D02DB1C08091D7059091D805432F552791 :1048E00043305105A9F068F44130510509F4FBC08B :1048F0004230510509F0E8C08BE590E0E5ECF4E0CA :104900004BC04132510529F14232510589F1DCC0D9 :10491000C901992781309105A1F058F0029709F05B :10492000D3C0E2E3F5E0E4918E2F90E0E2E3F5E01E :1049300030C0E8E9F5E0E4918E2F90E0E8E9F5E099 :1049400028C0E4E8F5E0E4918E2F90E0E4E8F5E09B :1049500020C08330910508F0B7C0880F991FFC0173 :10496000EF53FE4F0190F081E02D89E090E014C0FC :104970008330910508F0A8C0FC01EE0FFF1FE5543D :10498000FE4F0190F081E02DDC01A854BE4F8C91C8 :1049900090E0009709F498C02091E800277F2093C9 :1049A000E8002091D9053091DA052817390708F475 :1049B000C90140E0009771F12091D1052223D9F17E :1049C0002530C9F12091E80023FD35C02091E80091 :1049D00022FD2DC02091E80020FFECCF2091F200B5 :1049E0003091F300009759F02830310540F444919C :1049F0004093F100319601972F5F3F4FF3CF41E095 :104A00002830310509F040E02091E8002E7720930E :104A1000E800D0CF4111D0CF0AC08091D1058823C2 :104A200051F0853041F08091E80083FD04C0809111 :104A3000E80082FFF2CF8091E8008B778093E80056 :104A400043C0803809F040C08091E800877F8093A0 :104A5000E8008091D2058093F1008091E8008E7784 :104A6000D6CE811131C08091D5059091D605992778 :104A7000029754F58091E800877F8093E8001091B9 :104A8000D5051093D2050E94452C111106C08091C6 :104A9000E30087FD02C081E001C084E08093D1057E :104AA00042E061EC81E00E94642C42E261EC84E02F :104AB0000E94642C42E261EC82E00E94642C42E29B :104AC00060EC83E00E94642C8091E80083FF10C0BA :104AD0008091E800877F8093E8008091EB008062FE :104AE0008093EB0005C082E190E0E0E2F5E054CF76 :104AF000AA960FB6F894DEBF0FBECDBFDF91CF915F :104B00001F910895EDE0F6E097E0E930F90729F00C :104B10008183608342833396F7CF0895FC01EE0FC3 :104B2000FF1F8E0F9F1FFC01E35FF94F61834083DE :104B300022830895EF92FF920F939701201B310972 :104B40002F3F310519F010F02FEF30E02095382F6E :104B5000320F08F43FEF832F0F91FF90EF900895ED :104B6000EF92FF920F939701201B31092F3F3105E0 :104B700019F010F02FEF30E0322F3095482F430F0F :104B800008F44FEF842F620F0F91FF90EF9008957C :104B9000EF92FF920F93972F093438F4B701601BFF :104BA00071096F3F710519F010F06FEF70E0485F09 :104BB0005F4F4131510540F0A901485F5F4F4131DE :104BC000510510F06FEF70E06095482F460F08F424 :104BD0004FEF842F37FF02C02D5F3F4F359527954C :104BE0003595279560910906620F792F0F91FF90F7 :104BF000EF900895EF92FF920F93E00EF11CF901F0 :104C000037FF03C0F195E195F10924E0EE0FFF1F96 :104C10002A95E1F7EF3FF10519F014F0EFEFF0E01E :104C20009A0157FF03C031952195310994E0220F75 :104C3000331F9A95E1F72E173F070CF4F901EE0D9B :104C4000FF1DEF3FF10519F010F0EFEFF0E02E2F10 :104C50002095382F320F08F43FEF832F0F91FF90EC :104C6000EF900895EF92FF920F93970195E0099FBF :104C7000200D311D11242F3F310519F010F02FEFB9 :104C800030E02095382F320F08F43FEF832F0F913B :104C9000FF90EF90089522E8241B08F420E0620FB3 :104CA00008954095282F429F412D1124842F089567 :104CB0000F931F9310E0F801EE0FFF1FE55EFD4F0D :104CC0009081905797FD9195000F111FF801E45EB8 :104CD000FD4FE081F0E0B097DF01AA0FBB1F8D010F :104CE0000E0F1F1F2003D001219FB00D1124E8E3F8 :104CF000F0E0E91BF10997FDF3959F01220F331FA7 :104D000089010E0F1F1F40039001419F300D112498 :104D10002A0F3B1F37FF02C021583F4F220F232F7E :104D2000221F330B620F1F910F9108950F931F9352 :104D3000522F10E0F801EE0FFF1FE45EFD4FE081FF :104D4000F0E0B097EE0FFF1F9F015203D001539F79 :104D5000B00D1124000F111FF801E55EFD4F008119 :104D600010E000571109000F111F40039001419FEF :104D7000300D11242A0F3B1F37FF02C021583F4F2F :104D8000220F232F221F330B620F1F910F910895C3 :104D90000F931F93522F10E0F801EE0FFF1FE45EF8 :104DA000FD4FE081F0E0B0979F015203D001539F87 :104DB000B00D1124000F111FF801E55EFD4F0081B9 :104DC00010E00057110940039001419F300D11245C :104DD0002A0F3B1F37FF02C021583F4F220F232FBE :104DE000221F330B620F1F910F910895EF920F93C3 :104DF0001F9393E0099F80011124159507956E2D4F :104E0000600F1F910F91EF900895A22F50E0FA01CB :104E1000EE0FFF1FE45EFD4F9081905297FD91953C :104E2000440F551FFA01E55EFD4F3081232F30E01E :104E30002A1B3109290F311D97FD3A95620F0895FC :104E4000E42FF0E0EE0FFF1FE45EFD4F6081621B78 :104E50000895E42FF0E0EE0FFF1FE55EFD4F608147 :104E6000621B0895622F0895E42FF0E0EE0FFF1FFC :104E7000E55EFD4F408134EE439F412D1124E82F24 :104E8000F0E050E0445E5F4FDA01A21BB1099D01E2 :104E9000B7FF03C031952195310993E0220F331FED :104EA0009A95E1F7AF01421B530B9A0157FF02C0DD :104EB00020E030E0582F259F212D1124822F0895C6 :104EC000E42FF0E0EE0FFF1FE55EFD4F408134EE72 :104ED000439F412D1124E72FF0E050E0445E5F4FE7 :104EE000DA01A21BB1099D01B7FF03C031952195DD :104EF000310993E0220F331F9A95E1F7AF01421B6E :104F0000530B9A0157FF02C020E030E0279F212D6C :104F10001124722F0895FC019B01009721F477FF63 :104F20002BC080E80895AC0197FF04C044275527A3 :104F3000481B590BB901640F751F37FD0CC0241BAA :104F4000350BC901A5E0880F991FAA95E1F70E94CA :104F50007D3080E20CC0CB0165E0880F991F6A9517 :104F6000E1F7BA01621B730B0E947D3080E6861B5D :104F7000F7FF03C08195089580E00895EF920F93A5 :104F8000CF93DF93D72FC82FC9010E19BA010E9402 :104F90008B27602F681B7D2F8C2FDF91CF910F9176 :104FA000EF9008950F93CF93DF93D72FC82FC901A8 :104FB000BA010E948B27682F600F7D2F8C2FDF9105 :104FC000CF910F910895EF920F931F93CF93DF939B :104FD000D62FC72F182FC9010E19010FBA010E9431 :104FE0008B27081B202F219F212D1124822F6D2F0D :104FF0007C2FDF91CF911F910F91EF900895EF9249 :105000000F931F93CF93DF93D62F172FC82FC9016C :105010000E19070FBA010E948B27702F781B719F02 :10502000712D11246D2F8C2FDF91CF911F910F9136 :10503000EF900895FF920F931F93CF93DF93F62E77 :10504000D72F182FC901C12FC01BBA010E948B276F :10505000982F990F890FC81B2C2F219F212D1124C8 :10506000822F6F2D7D2FDF91CF911F910F91FF9098 :105070000895FF920F931F93CF93DF93F62E172F70 :10508000D82FC901C72FC01BBA010E948B27982FA8 :10509000990F890F7C2F781B719F712D11246F2D13 :1050A0008D2FDF91CF911F910F91FF900895879AD7 :1050B00081B38F7791B390682FB7F894EDE0F6E065 :1050C00037E0E930F30761F0319148E091BB37FFF9 :1050D00081BB330F000000C081BB4A95B9F7F0CF08 :1050E0002FBF8FE292E00197F1F700C00000089512 :1050F0001F93CF93DF93CDB7DEB767970FB6F894C2 :10510000DEBF0FBECDBF342F4B8B252F5C8B6D8B3D :105110007E8B8F8B4E895F8961111092A60586E088 :10512000FE013D96DF01982F1D929A95E9F73D8784 :105130002E876F87598B488BDE01179601900D9251 :105140008A95E1F7CE0107960E945F1D81113EC04E :1051500086E0FE013796DE01119601900D928A9548 :10516000E1F7FF81E8856A857B856115710531F07E :10517000EF3F31F481E0FF3F19F403C081E001C04B :1051800080E080FD23C020913B0530E0C9010196FD :105190008770992740916C0550E08417950779F145 :1051A000F983EA837D836C8396E0929FD001939F7D :1051B000B00D1124A45CBA4FFE01319601900D92FE :1051C0009A95E1F780933B050E94E91C16E08091D7 :1051D0006C0590913B058917F9F0189FC0011124C7 :1051E000845C9A4F0E945F1D8823B1F080916C050A :1051F00090E001968770992780936C05E8CF0E9414 :105200000E1F10923B0510926C05E5E3F5E086E079 :10521000DF011D928A95E9F767960FB6F894DEBF15 :105220000FBECDBFDF91CF911F91089520910D0743 :1052300030910E072817390771F090930E0780936D :105240000D07E0916003F0916103309721F0008435 :10525000F185E02D0994089520910B0730910C07FA :105260002817390771F090930C0780930B07E09192 :105270006003F0916103309721F00680F781E02D03 :1052800009940895E0916003F0916103309721F053 :105290000190F081E02D099480E00895EF92FF9253 :1052A0000F93CF93DF93C42FD22FFC0182818823E9 :1052B000D1F0409313050E94361A90930A07809309 :1052C000090780E28C0F883008F078C0C77081E051 :1052D00001C0880FCA95EAF7DF91CF910F91FF9037 :1052E000EF900C94372E80911305481356C02091EF :1052F000090730910A074FB7F8948091EA0390911B :10530000EB03A091EC03B091ED034FBF821B930B15 :10531000883C910508F041C0CD17C9F080E28C0FA0 :10532000883040F4C77081E001C0880FCA95EAF761 :105330000E942C2E80E28D0F883048F481E09D2F52 :10534000977001C0880F9A95EAF70E94372E0933AB :1053500019F0E12CF12C03C080E5E82EF12C802F10 :105360000E949D2EE114F10451F08FEC97E001971B :10537000F1F700C0000091E0E91AF108F3CF802FA7 :105380000E94412E80E28D0F8830C0F4D77081E0FA :1053900001C0880FDA95EAF70AC080E28C0F8830E6 :1053A00068F4C77081E001C0880FCA95EAF7DF9101 :1053B000CF910F91FF90EF900C942C2EDF91CF9115 :1053C0000F91FF90EF9008950F931F93CF93DF936A :1053D000C42FD0E0CC0FDD1F2CE1629FC00DD11D8A :1053E000112438EA839FC00DD11D1124CD5BDF4FFE :1053F000CE010E94C42F082F10E0102F0027CE01ED :1054000001960E94C42F9801282BC901DF91CF91EA :105410001F910F910895462F843038F4763028F488 :105420006E3018F4672F0C94E42980E090E0089522 :105430000C9482250C948E25E8E0F6E08DE38083C1 :105440008091520190915301A091540181839283E4 :10545000A3838FE7848345E050E06CE170E0CF01E7 :105460000C94D22F482F982F46FD9095E92FEF737B :105470009F7046FD9F5FE295EF70EE0FF0E0E95EF2 :10548000FC4F2181299F802D212D112482958F7021 :105490002295207F822B3081982F930F892F47FDF3 :1054A000819580580895BC018230910508F40895D3 :1054B000613E8EE1780748F49B0195E0369527958B :1054C0009A95E1F748E0420F01C04FEF91E0242F99 :1054D00030E0290F311D35952795229FF001239F3C :1054E000F00DF00D11246E177F0718F44FEF420FE7 :1054F00004C02F3F39F091E0920F491740F78FEF2A :10550000890F08958FEF08950F93CF93DF93D72FCF :10551000C82F47FD4195E8E3F0E0CF01841B9109D6 :1055200047FD9395889FB001899F700D700D1124E0 :10553000229FC001239F900D900D1124860F971F6D :105540000E94532A682F660F860F682F600F7D2FE9 :105550008C2FDF91CF910F91089520E030E0869F4E :10556000212D969F200D311D1124C9010895CF9240 :10557000DF92EF92FF920F931F93CF93DF93F62E5C :10558000472FE82FF0E0711106C0E456FA4F8491DE :10559000782F682F73C0272F30E0E456FA4FE4913C :1055A000FE2F0E2F10E056E0659FC0011124CFEFB3 :1055B000D0E0BE010E9469305BEA5603C001579FEC :1055C000900D11248F0D911D8F0D911D982F990F06 :1055D000980F7E01E21AF30AE09ED001E19EB00D21 :1055E000F09EB00D11248B2F499FA0011124452F4F :1055F00055277E01E41AF50AE09EA001E19E500DB8 :10560000F09E500D11246E01C91AD108C29E70017E :10561000C39EF00CD29EF00C11242F2D3327C21BF9 :10562000D30BC09F9001C19F300DD09F300D11242E :10563000932F6230710591F048F461157105E1F026 :1056400061307105B9F49E2FE52F16C064307105E5 :1056500069F040F06630710579F00CC09E2FEB2F99 :10566000832F0AC0EB2F8F2F952F06C09B2F8E2FD5 :10567000E32F02C09B2F852F7E2F692FDF91CF91C3 :105680001F910F91FF90EF90DF90CF900895DF92E0 :10569000EF92FF920F931F93CF93DF93EC01FC01E6 :1056A000ED53FD4F9081692381F1D0900A0600915E :1056B0000B0610910906E12EF12C0E94A42F282F31 :1056C000C7018C549F4F68E671E00E947D308E19AF :1056D0009F0997FD039695958795959587952370D6 :1056E000612F289F600D11247D2D802F0E94B72AE5 :1056F000462F282F672FCE01DF91CF911F910F9159 :10570000FF90EF90DF900C941A2ADF91CF911F91B8 :105710000F91FF90EF90DF9008951F93CF93DF9349 :10572000FC01ED53FD4F20816223A9F0EC010E94A2 :10573000A42F182F0E94A42F612F782F80910B0681 :105740000E94B72A462F282F672FCE01DF91CF91D5 :105750001F910C941A2ADF91CF911F9108951F92E7 :105760000F920FB60F9211242F933F934F935F9395 :105770006F937F938F939F93AF93BF93CF93DF9359 :10578000EF93FF93C091E900CF708091EC00D82F88 :10579000D17080FDD0E81092E9008091F000877F01 :1057A0008093F00078940E94B5221092E9008091D5 :1057B000F00088608093F000CD2BCF70C093E9009B :1057C000FF91EF91DF91CF91BF91AF919F918F9119 :1057D0007F916F915F914F913F912F910F900FBEED :1057E0000F901F901895E8EDF0E080818C7F80830A :1057F0001092E2001092DA001092E100A0EEB0E008 :105800008C9181608C9380818F77808319BCA7ED08 :10581000B0E08C918E7F8C9380818F7E80831092FC :105820000F0708952091E4003091E50095E640913E :10583000EC00842F817040FF23C08091E80080FD40 :105840001DC08091D105882399F0853099F0809111 :10585000EB0085FD11C04091E4005091E500241754 :10586000350729F3915011F09A01E1CF84E00895B2 :1058700082E0089583E0089581E0089580E008952E :105880004091E80042FFDDCF08958091D30587FF66 :1058900011C08091E80082FD05C08091D105811181 :1058A000F8CF11C08091E8008B770BC08091D105B3 :1058B000882349F08091E80080FFF8CF8091E800CC :1058C0008E778093E8000895982F973068F590932D :1058D000E900981739F07091EC002091ED0050919B :1058E000F00003C0242F762F50E021FD02C09F5FFF :1058F000ECCF3091EB003E7F3093EB003091ED0028 :105900003D7F3093ED003091EB0031603093EB0040 :105910007093EC002093ED005093F0002091EE0086 :1059200027FDE5CF80E008958F708093E90081E046 :105930000895CF92DF92EF92FF920F931F93CF9330 :10594000DF93C8EDD0E088818F7E8883E7EDF0E0BB :1059500080818160808381E080930F0788818C7FC4 :10596000888302EE10E0D8011C921092DA0081EEDA :10597000C82ED12CD6011C9288818F77888388818C :105980008068888388818F7D888380818068808318 :1059900019BC1092D1051092D2051092D005109228 :1059A000CF0590EEE92EF12CF70180818B7F80836B :1059B00088818160888342E060E080E00E94642CFE :1059C000D6018C918E7F8C93F801808181608083D9 :1059D000808188608083D7018C918E7F8C938881B1 :1059E00080618883DF91CF911F910F91FF90EF909D :1059F000DF90CF9008951F920F920FB60F9211244F :105A00002F933F934F935F936F937F938F939F93C6 :105A1000AF93BF93EF93FF938091E10082FF09C0A2 :105A20008091E20082FF05C08091E1008B7F80932E :105A3000E1008091DA0080FF2AC08091D80080FFC9 :105A400026C08091DA008E7F8093DA008091D900A1 :105A500080FF18C088E189BD8AE189BD09B400FED4 :105A6000FDCF81E08093D10580910F0781110FC098 :105A70000E94F32B0E94992C8091E2008460809315 :105A8000E20005C019BC1092D10510920F07809159 :105A9000E10080FF17C08091E20080FF13C0809179 :105AA000E2008E7F8093E2008091E200806180932B :105AB000E2008091D80080628093D80019BC85E014 :105AC0008093D1058091E10084FF2EC08091E20097 :105AD00084FF2AC088E189BD8AE189BD09B400FE3E :105AE000FDCF8091D8008F7D8093D8008091E10018 :105AF0008F7E8093E1008091E2008F7E8093E200B0 :105B00008091E20081608093E2008091D205882339 :105B100011F084E007C08091E30087FD02C081E0BE :105B200001C083E08093D1058091E10083FF27C00D :105B30008091E20083FF23C08091E100877F809302 :105B4000E10082E08093D1051092D2058091E100BE :105B50008E7F8093E1008091E2008E7F8093E2004F :105B60008091E20080618093E20042E060E080E0AA :105B70000E94642C8091F00088608093F000FF9177 :105B8000EF91BF91AF919F918F917F916F915F91B5 :105B90004F913F912F910F900FBE0F901F9018952E :105BA0002091D9053091DA052617370748F061159D :105BB000710539F42091E8002E772093E80001C0A8 :105BC000B901FC0120E06115710569F18091D105F1 :105BD0008823E1F18530E1F18091E80083FD3AC04E :105BE0008091E80082FD2CC08091E80080FFEBCF1F :105BF0008091F2009091F3006115710551F08830A9 :105C0000910538F421912093F100615071090196BA :105C1000F3CF21E0089709F020E08091E8008E772B :105C20008093E800D0CF2111D1CF0AC08091D10557 :105C3000882361F0853061F08091E80083FD0AC01F :105C40008091E80082FFF2CF80E0089582E008951D :105C500083E0089581E00895882341F08095909134 :105C6000A70589238093A7050C94491B08958823D1 :105C700039F09091A705892B8093A7050C94491BB7 :105C80000895882309F458C0682F823869F40E9467 :105C9000422981FF51C069E385E195E00E94931A92 :105CA0000E94491B69E30EC0833891F40E94422987 :105CB00080FF42C063E585E195E00E94931A0E944F :105CC000491B63E585E195E00E946B1A0C94491B22 :105CD000843869F40E94422982FF2EC067E485E17E :105CE00095E00E94931A0E94491B67E4EBCF8CEF6A :105CF000860F813A38F380E2860F883070F467703F :105D000081E090E001C0880F6A95EAF78095909154 :105D1000A70589238093A705D9CF8BE5860F83300C :105D200020F480E090E00C942C29685A673120F42C :105D300080E090E00C9416290895CF93882309F40D :105D4000B5C0C82F8238B1F40E94422981FDAEC08F :105D500069E385E195E00E94931A0E94491B2FEFA9 :105D600080E792E0215080409040E1F700C00000C1 :105D700069E317C08338E1F40E94422980FD96C090 :105D800063E585E195E00E94931A0E94491B2FEF7D :105D900080E792E0215080409040E1F700C0000091 :105DA00063E585E195E00E946B1ACF910C94491B45 :105DB0008438B1F40E94422982FD78C067E485E10D :105DC00095E00E94931A0E94491B2FEF80E792E012 :105DD000215080409040E1F700C0000067E4E1CF2F :105DE0008CEF8C0F813AB8F5809148018823E1F05F :105DF00080915E0387FF18C0EC2FE695E695E69547 :105E0000F0E0EB5EFA4F8281282F30E04C2F477094 :105E100081E090E002C0880F991F4A95E2F7822343 :105E20009323892B59F411C0E7E1F5E08191C8175C :105E300029F025E0ED31F207C9F707C06C2F85E1A5 :105E400095E00E946B1A0E94491B6C2F85E195E03A :105E50000E94931AAACF80E28C0F883068F4C77032 :105E600081E090E001C0880FCA95EAF79091A705FC :105E7000892B8093A70599CFEBE5EC0FE33040F435 :105E8000F0E0E15EFC4F808190E0CF910C942C29F2 :105E9000C85AC73158F4EC2FF0E0EE0FFF1FEE5D4B :105EA000FC4F80819181CF910C941629CF91089558 :105EB0008F929F92AF92BF92CF92DF92EF92FF921A :105EC000CF93DF93EC01688179818A819B81611591 :105ED00071058105910521F464E279ED8BE597E088 :105EE0002DE133EF41E050E00E94063049015A01B4 :105EF0009B01AC01A7EAB1E40E9425306B017C0153 :105F0000ACEEB4EFA50194010E943330DC01CB016B :105F10008C0D9D1DAE1DBF1DB7FF03C00197A109CC :105F2000B04888839983AA83BB839F77DF91CF9101 :105F3000FF90EF90DF90CF90BF90AF909F908F90A9 :105F400008950E94582F089580E091E00E94582FF4 :105F50000895A0E0B0E08093000190930101A09328 :105F60000201B09303010895DC01CB01FC01F99912 :105F7000FECF06C0F2BDE1BDF89A319600B40D9295 :105F800041505040B8F70895F999FECF92BD81BDB8 :105F9000F89A992780B50895A8E1B0E042E050E072 :105FA0000C94B62FDC01A40FB51F4150504048F0AF :105FB000CB01840F951F2E910E94E32F415050403A :105FC000D0F70895262FF999FECF92BD81BDF89A9A :105FD000019700B4021639F01FBA20BD0FB6F8942D :105FE000FA9AF99A0FBE08950396272F0E94E32F7D :105FF0000E94E22F252F0E94E32F242F0C94E32FE1 :106000000196272F0E94E32F0C94E22F052E97FB79 :106010001EF400940E941D3057FD07D00E943830B6 :1060200007FC03D04EF40C941D30509540953095EC :1060300021953F4F4F4F5F4F0895909580957095F4 :1060400061957F4F8F4F9F4F08950E945A30A59FB3 :10605000900DB49F900DA49F800D911D1124089563 :10606000B7FF0C9425300E942530821B930B0895B6 :10607000A1E21A2EAA1BBB1BFD010DC0AA1FBB1F4C :10608000EE1FFF1FA217B307E407F50720F0A21BBE :10609000B30BE40BF50B661F771F881F991F1A942B :1060A00069F760957095809590959B01AC01BD0155 :1060B000CF010895A29FB001B39FC001A39F700DAF :1060C000811D1124911DB29F700D811D1124911D00 :1060D0000895AA1BBB1B51E107C0AA1FBB1FA6172F :1060E000B70710F0A61BB70B881F991F5A95A9F781 :1060F00080959095BC01CD01089597FB072E16F46D :10610000009407D077FD09D00E94693007FC05D0C4 :106110003EF4909581959F4F0895709561957F4FBE :106120000895EE0FFF1F0590F491E02D0994FB01F7 :10613000DC0102C001900D9241505040D8F7089503 :10614000FB01DC014150504048F001900D920020CD :10615000C9F701C01D9241505040E0F70895F894EE :02616000FFCF6F :1061620001000000FFFF033D8EFFB07F958EFFB060 :106172007F958EFFB07F958EFFB07F9019CF198FDC :1061820019CB19C7193C011D0000003C0119000080 :10619200003C010A00000000510025012D015000C1 :1061A2002B010152003101B00100FF00993700AA12 :1061B20056008EFFB073797374656D37362F6C613C :1061C200756E63685F3200302E372E3130342D31D8 :1061D20038382D673761363535653533306200F032 :1061E200F1F2F3F4F566656463626167070605041C :1061F200C660C70207040603090209040303080272 :1062020003030301260C0D0E10110F121317212286 :1062120025002131426384B040226D85046304F677 :1062220003D704F004100545464748494A4B4C4DF4 :106232004E4F50515244434241403F3E3D3C3B3A17 :106242003938372728292A2B2C2D2E2F303132335B :1062520034262524232221201F1E1D1C1B1A530C09 :106262000B0A09080706050403020100360D0E0F8A :106272001011191213141516171835D133BE33AB7A :10628200339C338C337D336E335F33503341333140 :106292003322330B3308401B402A40394050406EB2 :1062A2004085409440A740C240D140E040E026C52E :1062B20026B226A3269426852676266726572648C2 :1062C2002639262A261B260826041A171A261A35C4 :1062D2001A441A541A631A721A811A901A9F1AAF20 :1062E2001ABE1ACD1AE01AE00DC90DB60DA70D9807 :1062F2000D890D790D6A0D5B0D4C0D3D0D2E0D1E98 :106302000D0F0D000D00000F001E002E003D004C71 :10631200005B006A00790089009800A700B600C9F6 :1063220000E0000404040404040404040404040457 :10633200040404040404040404040404040404041B :10634200040404040404040404040404040404040B :1063520004040404040404040404040404040404FB :1063620004040404040404040404040404040404EB :1063720004040404040404003131295A1B750A81FF :106382008283E200E900EA00B500B600B700CD0062 :106392008301CC008A01920194012102230224028A :1063A2002502260227022A02B300B4006F00700001 :10F000004BC0000074C0000072C0000070C000005F :10F010006EC000006CC000006AC0000068C0000044 :10F0200066C0000064C00000A9C5000060C0000008 :10F030005EC000005CC000005AC0000058C0000064 :10F0400056C0000054C0000052C0000050C0000074 :10F05000E5C100004CC000004AC0000048C00000EC :10F0600046C0000044C0000042C0000040C0000094 :10F070003EC000003CC000003AC0000038C00000A4 :10F0800036C0000034C0000032C0000030C00000B4 :10F090002EC000002CC0000011241FBECFEFD0E115 :10F0A000DEBFCDBF83E090E050D480FD04C084B7C4 :10F0B0008D7F84BF03C084B7877F84BFE0E0F0E02A :10F0C0008591949111E0A0E0B1E0E8EAFEEF02C082 :10F0D00005900D92A638B107D9F721E0A6E8B1E076 :10F0E00001C01D92A33AB207E1F736D1DBC688CF43 :10F0F0008823B9F02091F2003091F300232B69F4BA :10F100009091E8009B7F9093E8009091E80092FD39 :10F1100006C09EB39111F9CF04C09091F1008150C7 :10F12000E7CF0895EEE8F1E0358124819381828173 :10F130009093880180938901C901909386018093FF :10F1400087010895CF92DF92EF92FF921F93CF93A2 :10F15000DF9300D01F92CDB7DEB7909198018091D8 :10F160008E019923D1F0843049F480918F0181116F :10F1700008C0809190018F3F21F455C0853009F47B :10F18000A2C08AE08093000183E080939601809181 :10F19000EB0080628093EB00D4C0843009F443C05C :10F1A00028F4813051F08330D9F0CBC0853009F498 :10F1B0008AC0863009F4B2C0C4C010918F011230E9 :10F1C00008F0BFC0AFDF111109C0609188017091D4 :10F1D000890120918A01822F90E064D385E007C0E5 :10F1E00080918F01982F9D7F29F49CDF89E0809387 :10F1F0000001A7C0813009F0A4C0E0E0F0E08491F4 :10F200008F3F59F010928A01F0938901E0938801B1 :10F210008AE08093000185E092C03196E11520EFED :10F22000F20769F78EC080918F01833091F581E0FC :10F2300080939701E0919401F09195018091900164 :10F24000309761F0813009F07CC0909193018091FA :10F25000920190938B0180938C0173C0811111C036 :10F2600082E49CED9093A4018093A3019CE088E14B :10F270000FB6F894A895809360000FBE909360003D :10F2800060C085919491019609F05BC010920101D4 :10F2900058C0811156C0809190018F3F09F051C034 :10F2A000C12CD12C7601C701B601FCD28FEFD81A40 :10F2B000E80AF80AC11420EFD206E104F10499F734 :10F2C000109298013EC08091020190910301A0919B :10F2D000040189839A83AB838091900190918F017F :10F2E000911107C0833038F5FE01E80FF11D8181CF :10F2F00012C0913031F5813359F020F48033D9F4C4 :10F3000088E509C0803631F08136A9F482E803C06F :10F310008EE101C086E980938D0113C080918F0139 :10F32000833079F48091900181110BC0809191011B :10F3300080938A0106C08AE08093000188E0809370 :10F3400096010F900F900F90DF91CF911F91FF903A :10F35000EF90DF90CF90089584B7877F84BF0FB67A :10F36000F894A89580916000886180936000109265 :10F3700060000FBE90E080E80FB6F89480936100C3 :10F38000909361000FBEC1E0C5BF82E085BF559A72 :10F390005D9A819AD8D36E9A769A3E9A469AC0938D :10F3A0006F0083E080938100769846987894C0E05F :10F3B000D0E080910101882361F152D58FB1827034 :10F3C00090910001923009F5C93893E1D907E8F02E :10F3D000882369F38FEC97E00197F1F700C00000F4 :10F3E0005AD36E9876983E98469810926F00109275 :10F3F000810081E085BF15BE11BA10BA1BB81AB8DA :10F40000E0918B01F0918C010995882381F221967E :10F41000D0CF809197018111D0CFDCCF1F920F9276 :10F420000FB60F9211248F9380E48CB986B98F9117 :10F430000F900FBE0F901F9018955F926F927F9262 :10F440008F929F92AF92BF92CF92DF92EF92FF92F4 :10F450000F931F93CF93DF9380919B018F7781321E :10F4600009F0DEC180E48CB986B98091A101909148 :10F47000A201909395018093940180919C01833027 :10F4800009F488C158F48130D1F0823009F0C8C144 :10F490008091E800877F8093E800F0C0853009F410 :10F4A0009FC108F495C1863009F0BAC18091E80087 :10F4B000877F8093E80082E080930001A1C1809162 :10F4C000E800877F8093E80080919701882319F0F6 :10F4D00039DE1092970180919401909195010097E7 :10F4E00051F12091E80022FD04C02EB32111F9CF83 :10F4F00097C12091F10020938E010197909395017F :10F5000080939401EFE8F1E08091F2009091F30094 :10F51000892B81F08091F1008193809194019091E9 :10F5200095010197909395018093940121E0E4392E :10F53000F20751F707DE80910001853009F096C08F :10F540008091940190919501892B21F482E0809320 :10F5500000018CC08AE1CCDD009188011091890105 :10F56000802F8F71C5DDC0918601D09187012196D2 :10F57000C01BD10B80918F01811166C0D695C795B4 :10F58000680180918A01E82EF12C7D2C682E5F2C79 :10F5900010E02097C9F18091F2009091F300892B3F :10F5A000A9F021974091F1005091F100C701B601F7 :10F5B000B9D11F5F4601570182E0880E911CA11C42 :10F5C000B11C75016401103871F40FC08091E8001E :10F5D0008B7F8093E8008091E80082FDE2CF8EB3BC :10F5E0008111F9CF1DC12097A1F6602F772D862DAF :10F5F000952D78D1209769F2C501B40153D1082D1A :10F60000792C6A2C5B2CC4CF809186019091870164 :10F61000909389018093880127C08091F200909196 :10F62000F300892BA1F021976091F100809188016E :10F630009091890125D4809188019091890101964A :10F640009093890180938801209739F70DC08091AC :10F65000E8008B7F8093E8008091E80082FDE3CF93 :10F660008EB38111F9CFDCC080E142DD8091E800EA :10F670008B7F8DC08EB3882309F4D2C08091E800BF :10F6800080FFF8CF80910001893091F08A3059F4E1 :10F6900080918F01813039F49091880180918901A6 :10F6A0009093F10002C080918D018093F1006CC0B5 :10F6B0002091880130918901C0918601D091870104 :10F6C0002196C21BD30B80918F01811131C0D69539 :10F6D000C795C90120918A01A22FB0E02197F8F0C7 :10F6E0002091F2003091F3002032310559F0FC01F5 :10F6F000259134912093F1003093F1000296A11DE1 :10F70000B11DECCF2091E8002E7F2093E8002091DE :10F71000E80020FDECCF2EB32111F9CF81C08091FC :10F72000860190918701909389018093880129C077 :10F73000823039F5209729F18091F2009091F30001 :10F74000809791F0809188019091890191D3809365 :10F75000F10080918801909189010196909389012F :10F76000809388012197E6CF8091E8008E7F809377 :10F77000E8008091E80080FDE5CF8EB38111F9CFDC :10F780004FC082E0809300018091E8008E7F8093DB :10F79000E80036C08091E800877F8093E800809180 :10F7A000E80080FD04C08EB38111F9CF39C080918B :10F7B00096018093F1001092F1001092F1001092E6 :10F7C000F100809100018093F1001092F100DCCFF4 :10F7D0008091E800877F8093E8001092960110C026 :10F7E0008091E800877F8093E8008091E80080FDA9 :10F7F00004C08EB38111F9CF13C08091000155CFA1 :10F80000DF91CF911F910F91FF90EF90DF90CF90FC :10F81000BF90AF909F908F907F906F905F901EC130 :10F82000DF91CF911F910F91FF90EF90DF90CF90DC :10F83000BF90AF909F908F907F906F905F90089552 :10F84000292F30E02230310559F02330310569F09D :10F8500021303105F9F482E190E024E731E01EC067 :10F860008BE190E029E531E019C0882349F081302F :10F8700061F0823079F48AE390E025E031E00EC057 :10F8800084E090E025E531E009C082E190E021E4E8 :10F8900031E004C080E090E020E030E0FA01318304 :10F8A00020830895611520EF72078105910510F4FA :10F8B00021E0611120E020FF14C02FB7F89407B6B3 :10F8C00000FCFDCFF999FECF33E0FB0130935700E8 :10F8D000E89507B600FCFDCF91E190935700E895BD :10F8E0002FBF0895611520EF72078105910510F46F :10F8F00021E0611120E020FF14C02FB7F89407B673 :10F9000000FCFDCFF999FECF35E0FB0130935700A5 :10F91000E89507B600FCFDCF91E190935700E8957C :10F920002FBF089507B600FCFDCFF999FECF21E067 :10F93000FB010A0120935700E8951124089521E264 :10F94000FC01209357008491089529E0FC01209345 :10F95000570084910895E1E0F0E089E0809357003A :10F96000849108959FB7F89407B600FCFDCFF999EC :10F97000FECF809529E0E1E0F0E0082E20935700CB :10F98000E8959FBF08952091A1013091A20126170B :10F99000370748F06115710539F42091E8002E7F92 :10F9A0002093E80001C0B901FC0120E06115710558 :10F9B00061F18EB38823D9F18530D9F18091E800C7 :10F9C00083FD39C08091E80082FD2BC08091E80062 :10F9D00080FFECCF8091F2009091F30061157105EA :10F9E00051F08032910538F421912093F10061505B :10F9F00071090196F3CF21E0809709F020E0809112 :10FA0000E8008E7F8093E800D1CF2111D2CF09C0CA :10FA10008EB3882361F0853061F08091E80083FD2A :10FA20000AC08091E80082FFF3CF80E0089582E071 :10FA3000089583E0089581E00895EBEEF0E0808181 :10FA400081608083EDEEF0E010826093EC004083F3 :10FA50008091EE00881F8827881F089580919B0160 :10FA600087FF0FC08091E80082FD04C08EB3811132 :10FA7000F9CF10C08091E8008B7F0AC08EB3882335 :10FA800049F08091E80080FFF9CF8091E8008E7FF7 :10FA90008093E800089565D06CD0E0EEF0E08081BE :10FAA00081608083E8EDF0E080818F77808319BCEE :10FAB000A7EDB0E08C918E7F8C9380818F7E8083C8 :10FAC00010929A0108950F931F93CF93DF9349D01B :10FAD00050D0C8EDD0E088818F7788838881806896 :10FAE000888388818F7D8883E7EDF0E0808180685E :10FAF000808319BC1EBA1092990100EE10E0F80143 :10FB000080818B7F808388818160888342E260E08E :10FB100080E093DFE1EEF0E080818E7F8083E2EE93 :10FB2000F0E0808181608083808188608083F8013B :10FB300080818E7F8083888180618883DF91CF91EF :10FB40001F910F910895E8EDF0E080818F7E808312 :10FB5000E7EDF0E080818160808381E080939A010D :10FB6000B2CFE8EDF0E080818C7F80831092E200DC :10FB700008951092DA001092E10008951F920F92FA :10FB80000FB60F9211242F933F934F935F936F9370 :10FB90007F938F939F93AF93BF93EF93FF93809146 :10FBA000DA0080FF1BC08091D80080FF17C08091D1 :10FBB000DA008E7F8093DA008091D90080FF0BC03D :10FBC00088E189BD8AE189BD09B400FEFDCF81E0ED :10FBD0008EBB45D103C019BC1EBA41D18091E10052 :10FBE00080FF17C08091E20080FF13C08091E20087 :10FBF0008E7F8093E2008091E20080618093E2003A :10FC00008091D80080628093D80019BC85E08EBBBB :10FC100026D18091E10084FF2EC08091E20084FF14 :10FC20002AC088E189BD8AE189BD09B400FEFDCF03 :10FC30008091D8008F7D8093D8008091E1008F7EE5 :10FC40008093E1008091E2008F7E8093E2008091BA :10FC5000E20081608093E20080919901882311F095 :10FC600084E007C08091E30087FD02C081E001C00D :10FC700083E08EBBF4D08091E10083FF21C08091AE :10FC8000E20083FF1DC08091E100877F8093E10047 :10FC900082E08EBB109299018091E1008E7F80936B :10FCA000E1008091E2008E7F8093E2008091E2008B :10FCB00080618093E20042E260E080E0BEDECFD06F :10FCC000FF91EF91BF91AF919F918F917F916F9134 :10FCD0005F914F913F912F910F900FBE0F901F900A :10FCE00018951F93CF93DF9300D0CDB7DEB7EBE924 :10FCF000F1E08091F100819381E0E33AF807C9F7E0 :10FD00009CDB8091E80083FF96C080919B019091DD :10FD10009C019630E1F128F4992351F09530B1F02F :10FD20008AC0983009F455C0993009F464C083C082 :10FD30008D7F803809F07FC08091E800877F8093B5 :10FD4000E8001092F1001092F1004EC0811173C0D2 :10FD500010919D011F778091E3008078812B809323 :10FD6000E3008091E800877F8093E80077DE809150 :10FD7000E80080FFFCCF8091E30080688093E3007F :10FD8000111102C082E001C083E08EBB54C08058D4 :10FD9000823008F050C060919F017091A001AE01C7 :10FDA0004F5F5F4F80919D0190919E0149DDBC01A5 :10FDB000892B09F440C09091E800977F9093E80068 :10FDC00089819A81E0DD8091E8008B7F8093E80053 :10FDD00032C0803881F58091E800877F8093E80009 :10FDE000809199018093F1008091E8008E7F80934B :10FDF000E80034DE20C081111EC080919D019091E9 :10FE00009E0199270297BCF48091E800877F809338 :10FE1000E80080919D018093990120DE80919901F5 :10FE2000811106C08091E30087FD02C081E001C01E :10FE300084E08EBB14D08091E80083FF0AC08091DB :10FE4000E800877F8093E8008091EB0080628093D8 :10FE5000EB000F900F90DF91CF911F9108950895BF :10FE60008EB3882321F08091E80083FD3ACF089576 :10FE7000F999FECF92BD81BDF89A992780B5089572 :10FE8000262FF999FECF92BD81BDF89A019700B453 :10FE9000021639F01FBA20BD0FB6F894FA9AF99AF3 :08FEA0000FBE0895F894FFCF96 :10FEA800020120DCFB3A03730079007300740065DB :10FEB800006D00370036002F006C00610075006E81 :10FEC80000630068005F003200200042006F006F8E :10FED8000074006C006F006100640065007200002F :10FEE800001203530079007300740065006D003739 :10FEF80000360000000403090409021B0001010088 :10FF080080320904000000FE0102000921030000FC :10FF1800000C10011201100100000020EB03F92F62 :06FF2800000001020001CF :10FFA00081CCA0CCBFCCCBCCD0CCD5CCDBCC0895F5 :08FFB0000895089508950895D5 :10FFE000DFCFDFCFDFCFDFCFDFCFDFCFDFCFDFCFA1 :08FFF000DFCFDFCFDFCFDFCF51 :08FFF80000F0000010DFFBDC4B :040000030000F00009 :00000001FF ================================================ FILE: data/system76_launch_heavy_1_default.hex ================================================ :100000000C94AA040C94F1040C94F1040C94F104E3 :100010000C94F1040C94F1040C94F1040C94F1048C :100020000C94F1040C94F1040C943F2E0C94F32CDA :100030000C94811B0C94F1040C94F1040C94F104C5 :100040000C94F1040C94F1040C94F1040C94F1045C :100050000C94F1040C944F1B0C94F1040C94F104D7 :100060000C94F1040C94F1040C94F1040C94F1043C :100070000C94F1040C94F1040C94F1040C94F1042C :100080000C94F1040C94F1040C94F1040C94F1041C :100090000C94F1040C94F1044F0858088308C0082C :1000A000FE0840098309860989098C098F0992098C :1000B000950998099B099E09A309A609A909AE09F2 :1000C000B309B609B909BE09FA09360A390A3E0A5E :1000D000490A4C0A570A5A0A650A680A730A760AD4 :1000E000810A870AF70A3C0B3C0C420C470CE60DD0 :1000F000E60D500CE60DE60D5A0C6B0C950CB40C8D :10010000D50C070D360D5E0D910D890DDC0D5C18BB :100110005C1896189618E9188C1A8C1A8C1A0519FE :10012000E319F419F4193B1D3B1D4E1D4E1D441DD2 :100130004E1D4E1D4E1D3B1D3B1D491D4E1D4E1D92 :10014000491DD824FF24A326FF24A3264B256E2572 :10015000A3266026702629003A003B003C003D00A3 :100160003E003F0040004100420043004400450083 :100170004C0035001E001F0020002100220023003B :1001800024002500260027002D002E002A002B0029 :1001900014001A000800150017001C0018000C00BD :1001A000120013002F003000310039000400160047 :1001B000070009000A000B000D000E000F003300BD :1001C000340028004A00E1001D001B000600190051 :1001D000050011001000360037003800E50052001D :1001E0004B00E000E2000151E3002C004D002C0028 :1001F000E400E6000151500051004F004E000000A5 :1002000000000000AB00AE00AC00000000000000E9 :100210000000000000004600000000000000000098 :1002200056005500540000000000000000000000CF :1002300000005300000000000000000057006100B3 :1002400060000000000000000000000000005F00EF :10025000000000000000000000005E005D000000E3 :10026000000000000000000000005C000000000032 :100270000000000058005B005A0000000000000071 :100280000000000000005900000000000000000015 :1002900000006300000000000000000000000000FB :1002A000000062000000005C01000100010001008C :1002B0000100010001000100010001000100010036 :1002C0000100010001000100010001000100010026 :1002D000010001000100C35CCB5CCA5C0100460068 :1002E000010001000100010001004A004E004B0026 :1002F0004D000100010001000100010001000100AA :100300000100010001005000510052004F000100A7 :1003100001000100AE000100010001000100010028 :1003200001000100010001000100010001004B007B :10033000A90001000100010001000100A800010066 :100340000100010001004A004E004D00AA0000001B :10035000000000000100010001000000000000009A :10036000000000000000010000000000000000008C :10037000010001000100000000000000000000007A :10038000000001000000000000000000010001006A :10039000010000000000000000000000000001005B :1003A000000000000000000000000100010000004B :1003B000000000000000000000000100000000003C :1003C000000000000100010001000000000000002A :1003D000000000000000010000000000000000001C :1003E000000001000000000000000000000000000C :1003F00000000100000001000100010001000100F7 :1004000001000100010001000100010001000100E4 :1004100001000100010001000100010001000100D4 :1004200001000100010001000100010001000100C4 :1004300001000100010001000100010001000100B4 :1004400001000100010001000100010001000100A4 :100450000100010001000100010001000100010094 :100460000100010001000100010001000100010084 :100470000100010001000100010001000100010074 :100480000100010001000100010001000100010064 :100490000100010001000100010001000100000055 :1004A0000000000001000100010000000000000049 :1004B000000000000000010000000000000000003B :1004C0000100010001000000000000000000000029 :1004D0000000010000000000000000000100010019 :1004E000010000000000000000000000000001000A :1004F00000000000000000000000010001000000FA :1005000000000000000000000000010000000000EA :1005100000000000010001000100000000000000D8 :1005200000000000000001000000000000000000CA :1005300000000100000000000000000000000000BA :1005400000000100000001000100010001000100A5 :100550000100010001000100010001000100010093 :100560000100010001000100010001000100010083 :100570000100010001000100010001000100010073 :100580000100010001000100010001000100010063 :100590000100010001000100010001000100010053 :1005A0000100010001000100010001000100010043 :1005B0000100010001000100010001000100010033 :1005C0000100010001000100010001000100010023 :1005D0000100010001000100010001000100010013 :1005E0000100010001000100010001000100000004 :1005F00000000000010001000100000000000000F8 :1006000000000000000001000000000000000000E9 :1006100001000100010000000000000000000000D7 :1006200000000100000000000000000001000100C7 :1006300001000000000000000000000000000100B8 :1006400000000000000000000000010001000000A8 :100650000000000000000000000001000000000099 :100660000000000001000100010000000000000087 :100670000000000000000100000000000000000079 :100680000000010000000000000000000000000069 :1006900000000100000005010980A1018503190186 :1006A0002AB700150126B700950175108100C00515 :1006B0000C0901A101850419012AA002150126A037 :1006C00002950175108100C005010906A10185058B :1006D000050719E029E71500250195087501810234 :1006E0000507190029EF1500250195F07501810214 :1006F00005081901290595057501910295017503F4 :100700009101C00660FF0961A1010962150026FF81 :10071000009520750881020963150026FF009520C9 :1007200075089102C005010906A101050719E02914 :10073000E71500250195087501810295017508816D :10074000010507190029FF150026FF009506750809 :10075000810005081901290595057501910295018A :1007600075039101C009025B00030100A0FA0904AE :1007700000000103010100092111010001224000D4 :100780000705810308000A090401000203000000B4 :100790000921110100012222000705820320000126 :1007A0000705030320000109040200010300000003 :1007B000092111010001226D000705840320000AB0 :1007C000120110010000000884330700010001023B :1007D000000168034C00610075006E006300680052 :1007E0002000480065006100760079002000430089 :1007F0006F006E006600690067007500720061009E :1008000062006C00650020004B006500790062000A :100810006F00610072006400200028006C0061001D :1008200075006E00630068005F006800650061008D :10083000760079005F0031002900000012035300A8 :1008400079007300740065006D0037003600000009 :100850000403090400010101010101010101020277 :10086000020202020202020303030303030303045E :100870000404040404040505050505060606060629 :10088000070707070708080808090909090A0A0AE3 :100890000B0B0B0C0C0C0D0D0D0E0E0E0F0F0F1085 :1008A000101111111212131314141515161617170F :1008B000181819191A1A1B1B1C1D1D1E1E1F20207B :1008C000212222232424252626272829292A2B2CC5 :1008D0002D2D2E2F30313232333435363738393AE8 :1008E0003B3C3D3E3F404142434445464748494AE0 :1008F0004C4D4E4F50515354555658595A5B5D5EAE :100900005F616264656668696B6C6D6F7072737548 :1009100077787A7B7D7E8082838587888A8C8E8FAC :1009200091939596989A9C9EA0A2A3A5A7A9ABADDA :10093000AFB1B3B5B7BABCBEC0C2C4C6C9CBCDCFC8 :10094000D1D4D6D8DBDDDFE2E4E7E9EBEEF0F3F576 :10095000F8FAFDFF11241FBECFEFD0E1DEBFCDBFFF :1009600004B603FE27C08091990890919A08A0913F :100970009B08B0919C088730904BA740B04BD1F4B6 :100980001092990810929A0810929B0810929C0855 :1009900014BE84B7877F84BF0FB6F894A895809162 :1009A0006000886180936000109260000FBEE0E0FC :1009B000F8E7099513E0A0E0B1E0EAEEF3E602C043 :1009C00005900D92A03FB107D9F728E0A0EFB3E062 :1009D00001C01D92A939B207E1F70E94F3040C94FB :1009E000F3310C940000CF93DF93CDB7DEB7AB9714 :1009F0000FB6F894DEBF0FBECDBF84B7877F84BF2C :100A00000FB6F894A895809160008861809360008B :100A1000109260000FBE91E080E80FB6F8948093CA :100A20006100909361000FBE85B7806885BF85B770 :100A3000806885BF82ED9AE19093F1038093F00383 :100A40000E94372D0E94DD2D8091E200846080930A :100A5000E200789480911B078823A1F01091E900AF :100A60001F709091EC00892F817090FD80E8182B09 :100A70001092E9008091E80083FD0E94F4231F702A :100A80001093E90082E084BD93E095BD9DE797BD9A :100A900080936E0005E811E041E9C42E41E0D42EB8 :100AA000D8018D918D010E94670EC016D106C1F745 :100AB00001E911E03FE9C32E31E0D32EF801819125 :100AC0008F010E94670EC016D106C1F7E2EFF3E076 :100AD0008AE094E0AAECB4E0119211921D921D926A :100AE0008E179F07C9F780E090E00E9410318B3E7F :100AF0009E4F11F00E94181C10922507EEE3F7E0BC :100B00008EE497E02FEF3FEF219331938E179F07ED :100B1000D9F710920F04E8E2F4E088E394E02FEFB5 :100B20003FEF219331938E179F07D9F780E090E034 :100B30000E9410318B3E9E4F21F00E94181C0E9493 :100B4000602B45E050E06CE170E082E597E00E94A8 :100B5000F830809152078C7F11F40E94602B0E9424 :100B6000DE138FE097E20197F1F700C00000AFE0DD :100B7000B7E21197F1F700C000000E94DE138091E8 :100B8000CA0480FF14C06FEF7FEF80E490E00E9402 :100B900044316FEF82E490E00E9426316FEF7FEFE7 :100BA00080E090E00E9444310E94F61402C00E944E :100BB000281380E490E00E9410318C3E964739F46F :100BC00082E490E00E94083191E0823009F090E0E8 :100BD00090FD3AC000E010E0680120EBC21A2EEF51 :100BE000D20A4801ECE18E0E911CF801EA5AFE4F40 :100BF000A590B4906B2DC8018D5B9F4F0E9426314C :100C00006A2DC8018C5B9F4F0E9426310E5F1F4FDB :100C10008016910651F78401C814D90411F7860192 :100C2000F0E4CF16F5E0DF06B9F681E00E94551535 :100C30006CEE76E780E490E00E94443162E082E46A :100C400090E00E94263103C080E00E94551560911B :100C50001E0670911F0680912006909121060E9429 :100C6000291580E090E00E9410318B3E9E4F11F0DC :100C70000E94181C82E090E00E9408318093B10429 :100C80000E94071C90930B0480930A0483E090E079 :100C90000E940831682F70E080E090E00E941E1EE4 :100CA00060911E0670911F0680912006909121068A :100CB0000E94291560910A04606860930A041091EB :100CC0000B0484E090E00E942631612F81E290E0E5 :100CD0000E9426318BE191E090930D0480930C04E7 :100CE00022242394312C80911B07853009F054C0B5 :100CF00080E4E82EDD24D39498E1F92E1AE1809166 :100D00001B07853009F042C080911B07843051F1E8 :100D100040E060E080E00E945C2BD092AF04109233 :100D20000E0468E170E00FB6F894A8956093600037 :100D30000FBEE092600083B7817F846083BF83B77A :100D4000816083BF7894889583B78E7F83BF0FB609 :100D5000F894A8958091600088618093600010925B :100D600060000FBE80911A07882309F4C8CF0E9443 :100D7000DE13EAECF4E081919191892B09F04DC7E3 :100D800082EE94E08E179F07B1F7B9CF0E944D20F5 :100D90000E94812A1092AF040E94DE13882359F02A :100DA0008FB7F8944091AB045091AC046091AD04BE :100DB0007091AE048FBFA2EBB4E0EAECF4E0E12C5A :100DC000F12C4E2DA190B1908D919D918A259B255E :100DD000009709F4AEC010E0CC24C394D12C9C0140 :100DE0002C213D21232B09F49EC019A34AA3AC203A :100DF000BD2081E0A114B10409F480E08BA30E941E :100E0000751B8160782F9DA38CA349A15AA16BA16A :100E10008DA10E94B729F701EE0FFF1FEE54FB4F83 :100E200080819181C826D926D182C082AB2881F0E9 :100E30008EE08E9DF0018F9DF00D1124ED52FE4F3E :100E4000E10FF11D80818F3F19F08BA711E001C0E8 :100E500010E0B0900F04E12EF12CC7018B0D911D15 :100E60000997A4F188E090E06C01CE18DF08B70183 :100E70006F5F7F4F615F7B4FA60180E194E00E942E :100E8000DB31B701675F7F4F615F7B4FA60188E170 :100E900094E00E94DB31A601440F551FB701660F95 :100EA000771F675E7F4F615F7B4F88E294E00E940F :100EB000DB31B7016F5E7F4F615F7B4FA60180E240 :100EC00094E00E94DB31BA94B0920F0480910F0439 :100ED00090E0EBA5AE2FB0E09D01220F331F255807 :100EE0003D4FAA0FBB1FBD0164587D4F41E0480F25 :100EF0009117B0F490E0FC01E15FFB4FD9015C91E8 :100F00005183DB015C915187BBA5B18B880F991F81 :100F1000FC01E15FFB4F128E118E91E0842FE6CF32 :100F200080930F041EC01F5FCC0CDD1C1E3009F027 :100F300056CF2FEFE21AF20A3CE0E316F10409F073 :100F400040CF8FEF8EA38FA318A60E94751B8160E0 :100F5000782F9AA789A74EA15FA168A58AA50E94AC :100F6000B729409138045091390460913A04709146 :100F70003B042FB7F8948091AB049091AC04A091FE :100F8000AD04B091AE042FBF841B950BA60BB70B1D :100F90002FB7F894C090AB04D090AC04E090AD04AF :100FA000F090AE042FBFC0923804D0923904E09282 :100FB0003A04F0923B0460910F04EFE0F4E0462F16 :100FC00050E088248A94982CA12CB12C881A990A74 :100FD000AA0ABB0A651799F0218D328D2901612C6F :100FE000712C84149504A604B70410F4415004C075 :100FF000280F391F328F218F5F5F3296EBCF4093DE :101000000F048091AF04811108C010915207812F05 :10101000837019F01695169501C010E080910601B5 :101020008130E9F038F0823009F4A7C3833009F445 :10103000B1C3CDC310924901C0924E07D0924F0761 :10104000E0925007F092510789E2EFE0F4E0A5E268 :10105000B7E001900D928A95E1F781E098C3809105 :10106000050118130DC020915207237030E0409104 :10107000040150E081E02417350719F480E001C035 :1010800081E0817080934B01412F50E0483251053F :1010900008F061C3FA01E45BFF4F0C94D53188235B :1010A00009F459C340E060E080E00E945C2B53C328 :1010B000F090490185E1F89EF02C112405E10F0D17 :1010C0000A3608F009E66091530770915407809141 :1010D00055070E94FB2BD62EC72EB82EF01608F00F :1010E00037C3EF2DF0E0DF01A35BBC4F8C919091F3 :1010F0004A01982331F02B2D4D2D6C2DCF010E94EC :101100005E2BF394EBCFF090490185E1F89EF02C33 :10111000112405E10F0D0A3608F009E6C0905407C6 :10112000D0905507B09053076B2D7C2D8D2D0E94CC :10113000FB2BA62E972E882E609156076B0D7C2DCB :101140008D2D0E94FB2BD62EC72EB82EF01608F040 :10115000FFC28F2D90E0FC01E35BFC4F30812091BA :101160004A01232359F030FF04C02B2D4D2D6C2D47 :1011700003C0282D4A2D692D0E945E2BF394E6CFE3 :10118000D090490185E1D89ED02C112405E10D0DA8 :101190000A3608F009E6A090540790905507209170 :1011A000560730E4B32E5B2D529F512D1124B52EDE :1011B000D01608F0CDC2ED2CF12CF701E35BFC4F0B :1011C000908180914A018923B9F0F701EE0FFF1F4A :1011D000E458FD4F808182958F70609153078B9DFD :1011E000600D11247A2D892D0E94FB2B462F282F6C :1011F000672FC7010E945E2BD394DACFD0904901AC :1012000085E1D89ED02C112405E10D0D0A3608F099 :1012100009E6A0905407909055072091560780E466 :10122000B82E6B2D629F612D1124B62ED01608F0BA :101230008FC2ED2CF12CF701E35BFC4F9081809184 :101240004A018923D9F0F701EE0FFF1FE558FD4F42 :101250006081B69EB0011124B5E075956795BA9589 :10126000E1F780915307680F7A2D892D0E94FB2B9F :10127000462F282F672FC7010E945E2BD394D6CF0D :10128000F090490185E1F89EF02C112405E10F0D45 :101290000A3608F009E6C0905307D0905407B09082 :1012A00055076091560766956695669580914E073D :1012B00090914F070E94F12B0E94762B805887FD5A :1012C0008195880F782F2B2D729F712D1124872FD8 :1012D000B6010E94FB2BD62EC72EB82EF01608F0B2 :1012E00037C2EF2DF0E0DF01A35BBC4F8C919091F2 :1012F0004A01982331F02B2D4D2D6C2DCF010E94EA :101300005E2BF394EBCF8FE998E21AC083E798E263 :1013100017C088E799E21FC089E599E21CC08EE3F7 :1013200099E21EC082E299E21BC081E798E208C000 :1013300088E698E205C08FE598E202C084E498E26E :101340000E941A2209C285E398E20AC088EC9BE257 :1013500002C081E199E20E94BE21FEC18DEF98E2B8 :101360000E944221F9C187E098E205C085ED97E22D :1013700002C087E997E20E946422EEC181111EC07B :101380006091560720E1620F08F46FEF80914E07DD :1013900090914F070E94F12B6AE070E00E94AD31FE :1013A000892B09F0D8C10E94E83069E670E00E94FC :1013B000C13160914A010E948B2CCDC180914901BD :1013C00095E1899F802D112405E1080F0A3608F068 :1013D00009E6E82EF12CC02ED12CEC14FD040CF003 :1013E000B7C160914A01C7010E948B2C3FEFE31AFD :1013F000F30AF3CF81111EC06091560720E1620FFE :1014000008F46FEF80914E0790914F070E94F12BE7 :1014100065E070E00E94AD31892B09F09CC10E940B :10142000E83069E670E00E94C13160914A010E9493 :10143000D12C91C18091490195E1899F802D112482 :1014400005E1080F0A3608F009E6E82EF12CC02E57 :10145000D12CEC14FD040CF07BC160914A01C70152 :101460000E94D12C5FEFE51AF50AF3CF80E997E2ED :1014700002C08AE897E20E94C5226EC180912507CA :1014800021E0682F621B08F460E0862F61E777E2B5 :101490003BC061E777E237C08091250721E0782FD4 :1014A000721B08F470E0872F69E377E22DC069E3CF :1014B00077E229C08091250721E0382F321B08F4FC :1014C00030E0832F67E077E21FC067E077E21BC060 :1014D0008091250721E0582F521B08F450E0852FFA :1014E0006FEE76E211C06FEE76E20DC080912507B7 :1014F00021E0682F621B08F460E0862F69ED76E238 :1015000003C069ED76E280E00E94312325C180911D :10151000A504811125C063ED71E040E050E0942FF7 :101520009295907F20E030E0FB01E20FF31F808175 :10153000893638F4E82FF0E0E45CFB4F892F822BEA :1015400080832F5F3F4F2E30310571F74F5F5F4F24 :10155000625F7F4F4C30510511F781E08093A50405 :10156000D090490185E1D89ED02C112405E10D0DC4 :101570000A3608F009E660911E0670911F068091F8 :101580002006909121060E94FA0FB82E6091530711 :1015900070915407809155070E94FB2BA62E972E21 :1015A000882ED01608F0D4C0ED2CF12CF701E35BA7 :1015B000FC4F908180914A018923B9F0F701E45CE6 :1015C000FB4F6081462F4F7062956F708B2D0E948C :1015D000232B029720F420E040E060E003C0282D98 :1015E0004A2D692DC7010E945E2BD394DACF9090CB :1015F000490185E1989E902C112405E1090D0A36D8 :1016000008F009E6EE24EA94F12C901608F0A0C048 :10161000E92DF0E0DF01A35BBC4F9C9180914A0172 :10162000892341F1DF01AA0FBB1FAE0FBF1FAD51D0 :10163000BB4FAC901196CC90119712968C919091D3 :101640005507A99E50011124C99E60011124899F4C :10165000C0011124B7010E94AD31262FC501B70189 :101660000E94AD31462FC601B7010E94AD31CF01B6 :101670000E945E2B9394C9CFC090490195E1C99E09 :10168000C02C112405E10C0D0A3608F009E6811181 :1016900006C08091AA048F5F8093AA0404C01092B0 :1016A000AA041092A9048091AA04811147C08091D4 :1016B000A904883029F41092A8041092A9043EC00D :1016C000A82FB0E0AA0FBB1FA156BE4FEC911196F8 :1016D0009C917EE0E79FF0011124ED52FE4FE90F4F :1016E000F11D90819F3F21F09093A60491E001C0ED :1016F00090E09093A8048F5F8093A9041FC0EC2C06 :10170000F12CF701E35BFC4F908180914A01892322 :10171000A1F06091AA046C0D2091A804E6EAF4E01F :1017200080E77FEF90E092130CC00E94FB2B462FC6 :10173000282F672FC7010E945E2BC394C016F8F2B2 :1017400007C03191C31202C08FEF70E09F5FEBCFF3 :1017500081E0093608F080E0909149019F5F909305 :101760004901811134C082E08093060180914B01D0 :1017700081112DC0112351F02AC0109305018091D1 :1017800052078370809304010E94962983E080931E :1017900006011DC040914E0750914F0760915007C0 :1017A000709151072FB7F8948091AB049091AC04DD :1017B000A091AD04B091AE042FBF841B950BA60B76 :1017C000B70B4097A105B10510F0109206010E94D9 :1017D000812A9091B004891721F00E94812A809378 :1017E000B00480911B07843009F07DCA83E08093A8 :1017F000E9008091E80082FF76CA8091E80085FFC9 :1018000023C00E94562D81111DC050E2E52EF12CFF :10181000CE0101966C0109C08091F100D6018D9333 :101820006D01B1E0EB1AF10869F08091E80085FDE7 :10183000F3CF8091E8008B778093E8000E94562DCB :10184000882399F391E001C090E08091E8008B77C4 :101850008093E800992309F446CA81E08A83E981EC :101860008E2F90E0FC013197E331F10508F0AEC115 :10187000EC58FF4F0C94D53186E78B838CEE8C832C :1018800081E016C14EE150E065E571E004C04EE133 :1018900050E06DE671E0CE0103960E94E43195C1FF :1018A00080912306882309F491C11A8281E08093F4 :1018B00022068CC18B81843008F088C16C816C3029 :1018C00008F084C14D814E3008F080C10E94232B66 :1018D0008E839F837AC12B81243008F077C19C814D :1018E0009C3008F073C18D818E3008F06FC11E816D :1018F0006F8140E551E0249F7001259FF00C112479 :10190000ECE19E9FE00CF11C1124E80EF11CE80EA6 :10191000F11CF3E4EF0EF11CC7010E942631612F88 :10192000C70101960E94263150C180912306811182 :101930004DC18B81803F49F0813F49F0823F49F0A2 :10194000833F09F043C1E3E005C0E0E003C0E1E00C :1019500001C0E2E025E0E29FF0011124E95FFE4FC3 :1019600083818C8380EBA4C08091230681112EC1DA :101970008B819C81903B08F090EB803F49F0813F48 :1019800049F0823F49F0833F09F020C1E3E005C000 :10199000E0E003C0E1E001C0E2E035E0E39FF001F8 :1019A0001124E95FFE4F9383A8C080912306811123 :1019B0000DC1EB81E93658F0E03FC1F0E13FC1F0E5 :1019C000E23FC1F0E33F09F001C1E3E014C0F0E001 :1019D000CF01880F991FE80FF91FED51FB4F81814F :1019E0008C8380818D8382818E83EFC0E0E003C091 :1019F000E1E001C0E2E055E0E59FF0011124E95F7C :101A0000FE4F81818C8382818D831E82DEC0809116 :101A100023068111DBC0EB818D819C81E93658F072 :101A2000E03FB1F0E13FB1F0E23FB1F0E33F09F058 :101A3000CDC0E3E012C02E81F0E0AF01440F551F8E :101A4000E40FF51FED51FB4F808391832283BDC0CE :101A5000E0E003C0E1E001C0E2E065E0E69FF00104 :101A60001124E95FFE4F9183828347C08091230652 :101A70008111ACC0EB81E43008F0A8C02E2F30E01B :101A800075E0E79FF0011124E95FFE4F9081969584 :101A90009695EFEAF1E0419194130CC08C8385E0B8 :101AA000829FF001839FF00D1124E95FFE4F848136 :101AB0008D838BC08F5F8F3071F788C08091230634 :101AC000811184C0EB81E43008F080C0AC81AF307C :101AD00008F07CC02D8185E0E89FF0011124E95FCA :101AE000FE4FB0E0A155BE4F8C91982F990F990FE2 :101AF00080818370892B808324831A8260911E06E3 :101B000070911F0680912006909121060E94291550 :101B10005DC080912306811159C081E00E94551556 :101B200054C08CE08B838EE08C838AECE82E84E0BA :101B3000F82E1CE0A0E0B4E040E050E0B03258F5F0 :101B4000F70160817181C101042E02C0880F991FC5 :101B50000A94E2F7682379238B2F90E091010A2EF3 :101B600001C0220F0A94EAF7672B51F061E070E0A0 :101B70006C0F7D1F860F971FFC013081232B0AC03D :101B800061E070E06C0F7D1F860F971F2095FC01B0 :101B9000308123232083AF5FA83010F0BF5FA0E027 :101BA0004F5F5F4F4E30510549F61150F2E0EF0E96 :101BB000F11C1111C1CF09C00E944D2081E09B8111 :101BC000911101C080E08093E2041A8280911B078A :101BD000843009F088C81091E9001F709091EC00E2 :101BE000892F817090FD80E8182B82E08093E900B6 :101BF0008091E80080FF0DC040E050E060E270E0BE :101C0000CE0101960E9462208091E8008E77809339 :101C1000E8001F701093E90066C8F9BC19BD09B44B :101C200000FEFDCF8091D8008F7D8093D8008091F9 :101C3000E00082608093E0008091E00081FDFCCFB5 :101C40000E944D200C947F0690910A0492FF0DC0D3 :101C5000282F2871283019F4877F846006C0282F28 :101C60002471243011F48B7F886093FF0DC0282FDE :101C70002871283119F4877E846106C0282F2471C9 :101C8000243111F48B7E886120910B0420FF0DC05C :101C9000382F3871383019F4877F816006C0382FAB :101CA0003171313011F48E7F886021FF0DC0282FF3 :101CB0002871283119F4877E816106C0282F21718F :101CC000213111F48E7E886194FD877E0895F89409 :101CD000E82FE295EF70F0E031A1282F2F7081E01E :101CE00090E001C0880F2A95EAF7982F90959323EA :101CF00091A392A1892B82A378940895CF93DF9327 :101D00000E944F2BEC018238910559F1A0F48133E8 :101D1000910509F473C040F48932910509F467C054 :101D20008A9709F472C084C08533910509F458C0BC :101D3000C997B9F07DC0833E910571F138F4803EBA :101D40009105B1F0823E910511F172C0863E910578 :101D5000B9F1873E9105C9F1843E910509F068C04B :101D600024C080910A0480FD5DC081FD5BC060C01D :101D700080910A0480FD50C080910B0480FF36C121 :101D800080910A0484FD30C1C3EED0E02FC1809160 :101D90000A0482FF2BC1F4CF80910A0482FD3FC068 :101DA00080910B0480FD3EC0EBCF80910B0481FF3E :101DB0001DC180910A0484FD17C1C7EED0E016C191 :101DC00080910A0483FF12C1F4CF80910A0483FD3D :101DD0002CC080910B0481FFECCFC4EED0E006C193 :101DE00080910A0485FF02C1C9E2D0E0FFC0809162 :101DF0000A0485FFFBC0C5E3D0E0F8C080910A0467 :101E000086FFF4C0CAE2D0E0F1C080910A0486FFE8 :101E1000EDC0C1E3D0E0EAC0C9E3D0E0E7C0C2EE64 :101E2000D0E0E4C0C0EED0E0E1C0C6EED0E0DEC05D :101E3000C11582E5D80708F066C0C11591E5D9073C :101E400028F0DC2FCC27C16FD06AD0C0C83ED105A6 :101E500060F5C03ED10508F0C9C0C83AD105B0F45C :101E6000C53AD10540F0C55AD0E0C254DC4FC88114 :101E7000D0E0D064BBC0C130D10509F4B7C008F4CC :101E8000B3C0C430D10508F4AFC0B0C0CF3BD1055A :101E900008F0AAC0C85AD0E0CC0FDD1FCF53DC4FEA :101EA0000990D881C02DD464A1C0C11520E5D20706 :101EB000E0F0CE0174E0969587957A95E1F783700E :101EC0009C2F937021E030E002C0220F331F9A95BF :101ED000E2F73C68382BCF70C695C69580E2C89F64 :101EE000E0011124C22BD32B81C0C11580E4D80797 :101EF00018F0DF70D06A7AC0CE019A9581159F41A3 :101F000008F474C071C0C11586E5D807F0F5C11595 :101F100095E5D90750F08C2F0E94240E8F71C82FA1 :101F2000D0E0DC2FCC27D06261C0C11524E5D207F8 :101F300028F0DC2FCC27C46FD06A58C09E012370D4 :101F400033278C2F86958695C115D34578F4C1E04B :101F5000D0E002C0CC0FDD1F2A95E2F720E2829F7D :101F6000C0011124C82BD92BDC6840C0C1E0D0E0EF :101F700002C0CC0FDD1F2A95E2F720E2829FC0014C :101F80001124C82BD92BDA6831C0C1152AE5D20734 :101F9000E8F4C11589E5D80780F08C2F8F700E9476 :101FA000240E94E0D695C7959A95E1F7CF70D0E0CE :101FB000DC2FCC27D069C82B19C0C11598E5D907EB :101FC00098F0DC2FCC27C06FD06A10C0CE0190569D :101FD0008115904248F48D2F8F710E94240EDD27C9 :101FE000D0628F71D82B02C0C0E0D0E0CE01DF916B :101FF000CF910895CF92DF92EF92FF926C01EE2481 :10200000FF24C114D104E104F10421F0C701B60199 :1020100020E101C020E0C72ED82EE92EFF24C114F4 :10202000D104E104F10419F0285FC701B6016B0186 :102030007C0154E0F694E794D794C7945A95D1F76D :10204000C114D104E104F10419F02C5FC701B601F9 :102050006B017C0142E0F694E794D794C7944A95CB :10206000D1F7C114D104E104F10419F02E5FC701C6 :10207000B601DC01CB01B695A79597958795892B7D :102080008A2B8B2B09F02F5F822FFF90EF90DF9030 :10209000CF900895882311F084EC01C084E88093E8 :1020A000BC0080E49FE1A0E0B0E02091BC0027FDEF :1020B00008C00097A105B10561F00197A109B10918 :1020C000F4CF892B8A2B8B2B21F08091BB0090E0E1 :1020D00008958FEF9FEF0895DB01FC0120E030E0D1 :1020E00084E82A173B071CF591919093BB008093DD :1020F000BC0040E45FE160E070E09091BC0097FDBF :102100000AC0411551056105710599F04150510909 :1021100061097109F2CF452B462B472B51F0909165 :10212000B900987F983229F42F5F3F4FDACFC90169 :1021300008958FEF9FEF089584E98093BC0080910C :10214000BC0084FDFCCF0895262F94EA9093BC0038 :1021500040E45FE160E070E09091BC0097FD0AC050 :10216000411551056105710549F041505109610959 :102170007109F2CF452B462B472B19F48FEF9FEFB8 :1021800008959091B900987F983011F09031B1F78F :10219000682F660F622B6093BB0084E88093BC00BD :1021A00080E49FE1A0E0B0E02091BC0027FD08C0E2 :1021B0000097A105B10511F30197A109B109F4CF69 :1021C000892B8A2B8B2BD1F28091B900887F8831A3 :1021D00011F0803499F680E090E00895FF920F931B :1021E0001F93CF93DF931F92CDB7DEB78B01FC0116 :1021F000F1808DE1898360E08F2D0E94A41097FD0E :102200001AC061E070E0CE0101960E946C1097FD4B :1022100012C061E08F2D0E94A41097FD0CC080E0D9 :102220000E944A1097FD07C0F80180830E949C100D :1022300021E090E001C0282F822F0F90DF91CF91F5 :102240001F910F91FF9008950F931F93CF93DF93EA :10225000EB018A0160E00E94A41097FD09C0B8015B :10226000CE010E946C10EC0197FF0E949C10CE01E1 :10227000DF91CF911F910F910895CF93DF9300D0FD :102280001F92CDB7DEB720914C0130914D014091A6 :102290004E0129833A834B8343E050E0BE016F5FD8 :1022A0007F4FFC0180810E9424110F900F900F90AE :1022B000DF91CF9108958F929F92AF92BF92CF926C :1022C000DF92EF92FF920F931F93CF93DF93CDB7DF :1022D000DEB729970FB6F894DEBF0FBECDBF7C01E5 :1022E000B42EA52E962E872E690160E0FC01808118 :1022F0000E94A41097FD22C019821A8286E0800FE6 :102300008B831C820D838E829F82A886B98669E0AA :1023100070E0CE0101960E946C1097FD0FC0B801CD :10232000C6010E946C1097FD09C00E949C10C70155 :102330000E943D1197FD02C0912F01C0082F802FF0 :1023400029960FB6F894DEBF0FBECDBFDF91CF91B7 :102350001F910F91FF90EF90DF90CF90BF90AF90C3 :102360009F908F9008950F931F93CF93DF9300D08A :1023700000D0CDB7DEB709831A832B833C8304E0FA :1023800010E09E012F5F3F4F0E945B110F900F9056 :102390000F900F90DF91CF911F910F910895EF92C1 :1023A000FF920F931F93CF93DF9300D000D0CDB750 :1023B000DEB77C01162F19821A821B821C829E01B5 :1023C0002F5F3F4F48E259E060E87FEBFC018081DE :1023D00091810E94BA2097FD36C089819A81AB8194 :1023E000BC8141E050E060E070E0F701028004C091 :1023F000440F551F661F771F0A94D2F7112329F047 :10240000842B952BA62BB72B08C040955095609533 :10241000709584239523A623B72389839A83AB835E :10242000BC8309811A812B813C8148E259E060E834 :102430007FEBF701808191810E94B3111816190674 :1024400014F480E090E00F900F900F900F90DF91C8 :10245000CF911F910F91FF90EF9008950F931F93CD :10246000CF93DF9300D01F92CDB7DEB78C01BE01B2 :102470006D5F7F4F0E94EE1097FD2EC08B81F8019B :102480009281981739F18283982F9370923039F0A6 :10249000869586958370823081F460E001C061E0AA :1024A000F801838194810E94CF1197FD15C087E7C1 :1024B0008A83AE014E5F5F4F05C086E68983AE0119 :1024C0004F5F5F4F63E2F80181810E948E201816F2 :1024D000190614F480E090E00F900F900F90DF91B8 :1024E000CF911F910F9108950F931F93CF93DF9377 :1024F0001F92CDB7DEB78C01BE016F5F7F4F0E9488 :10250000EE1097FD12C09981292F2370F801838165 :102510009481211102C060E001C061E00E94CF11EE :102520001816190614F480E090E00F90DF91CF9117 :102530001F910F910895CF92DF92EF92FF920F9328 :102540001F93CF93DF9300D000D01F92CDB7DEB79B :102550006C018FEFF6018283E380F480F701428102 :102560005381648175814D5F534F6F477044808103 :1025700091811D8201E010E09E012B5F3F4F0E9480 :102580005B1197FD3CC060E0C7010E94CF1119822A :102590001A821B821C829E012F5F3F4F48E059E048 :1025A00060E87FEBF701808191810E94BA2097FD5E :1025B00026C001E010E020E030E0F701028004C016 :1025C000000F111F221F331F0A94D2F789819A81AD :1025D000AB81BC81082B192B2A2B3B2B09831A8337 :1025E0002B833C8348E059E060E87FEB8081918158 :1025F0000E94B3111816190614F480E090E00097B9 :10260000C9F4F6012081222369F0213099F485E094 :102610008983AE014F5F5F4F6AE1F60181810E94BD :102620008E2003C0C6010E9474121816190614F4F5 :1026300080E090E00F900F900F900F900F90DF913F :10264000CF911F910F91FF90EF90DF90CF90089561 :102650000F931F93CF93DF9300D000D000D0CDB75E :10266000DEB71092BA0080E28093B8001092BC00EE :102670008FE19EE40197F1F700C000000B9A139AD6 :102680009FEF20E782E0915020408040E1F700C0BA :1026900000008CE08E8301E010E09E012A5F3F4F36 :1026A0004AEF50E360E87FEB8CE391E00E945B111E :1026B00097FD4CC01D829E012B5F3F4F42E154E3CA :1026C00062ED7FEB8CE391E00E945B1197FD3EC0D1 :1026D00019821A821B821C829E012F5F3F4F48E0A5 :1026E00054E362ED7FEB8CE391E00E94BA2097FD0A :1026F0002DC009811A812B813C81016009831A83D5 :102700002B833C8348E054E362ED7FEB8CE391E064 :102710000E94B31197FD1AC004E813E323E030E0F0 :1027200040E050E360E87FEB8CE391E00E94B3115E :1027300097FD0CC004E813E324E030E048E450E9DE :1027400060E87FEB8CE391E00E94B31187E391E0B6 :102750000E949B1282E491E00E949B128DE391E023 :102760000E949B1280914F0190915001A0915101C4 :1027700089839A83AB8343E050E0BE016F5F7F4F54 :1027800080913C010E94241104E610E087E391E06F :102790000E9474128FE19EE40197F1F700C00000DF :1027A0000150110999F726960FB6F894DEBF0FBEB7 :1027B000CDBFDF91CF911F910F9108957F928F929E :1027C0009F92AF92BF92CF92DF92EF92FF920F93C0 :1027D0001F93CF93DF9382EFC82E83E0D82E95E826 :1027E000E92E91E0F92E8601C0E0D0E0712CAA24F8 :1027F000A394B12CB701D7018C91F894E82FE295FE :10280000EF70F0E021A18F70A50102C0440F551FA9 :102810008A95E2F7CA01922F982B91A392A18095F5 :10282000892382A3789400C0E1E9F1E020E030E060 :10283000812C912C4191842F82958F7090E0DC0146 :1028400090968C9190E04F7002C0959587954A952F :10285000E2F780FD08C0C501022E02C0880F991F53 :102860000A94E2F702C080E090E0882A992A2F5F5C :102870003F4F2E303105F1F6BFEFEB1AFB0AFB019B :1028800080810E94670ECB30D10519F0F0E5FA95F2 :10289000F1F7D8018D919C9111978816990621F036 :1028A0008D929C9281E001C080E0782A21960E5F93 :1028B0001F4FCC30D10509F09DCF772049F081E042 :1028C000809326060E94751B90932506809324060C :1028D00080912606882311F1209124063091250647 :1028E0004FB7F8948091AB049091AC04A091AD04E3 :1028F000B091AE044FBF821B930B069778F0EAECC1 :10290000F4E08AE094E0D6012D913D916D01219390 :1029100031938A179B07B9F71092260680912206F9 :102920008823D9F1BFEFE0E7F2E0B150E040F0409A :10293000E1F700C0000081E08093E00080E2809336 :10294000D8001092C9008FE097E20197F1F700C01C :1029500000001DBA109268001CBC10BE1FBA109275 :102960007A0010926E0010926F0010927000109218 :1029700071001092C9001092BC0011B814B817B8B9 :102980001AB81DB810BA12B815B818B81BB81EB8C6 :1029900011BA0E9428130C945278809127069091C6 :1029A0002806883EA3E09A076CF010922806109241 :1029B000270682E491E00E942E128DE391E00E94AE :1029C0002E1205C001969093280680932706872D26 :1029D000DF91CF911F910F91FF90EF90DF90CF90FB :1029E000BF90AF909F908F907F90089581E08093EB :1029F000E00080E28093D800E9ECF0E010828FE004 :102A000097E20197F1F700C000001DBA109268002C :102A10001CBC10BE1FBA10927A0010926E00109269 :102A20006F00109270001092710010821092BC0022 :102A300011B814B817B81AB81DB810BA12B815B82A :102A400018B81BB81EB811BA0E9428130C94007E47 :102A5000089520912306211110C00E94FA0F84309E :102A600060F495E0989FF0011124E95FFE4FA2E524 :102A7000B7E001900D929A95E1F7089590912306A1 :102A8000911112C080930A0180930F018093140169 :102A90008093190160911E0670911F068091200697 :102AA000909121060C942915089544E150E063E8C3 :102AB00075E0882361F087E091E00E9416314BE3D6 :102AC00051E067E975E083EE94E00C94163187E0FD :102AD00091E00E94F8304BE351E067E975E083EE46 :102AE00094E00C94F83080915207837029F08C693F :102AF000809352071092060181E080932306089587 :102B00008F929F92AF92BF92CF92DF92EF92FF92FD :102B10000F931F93CF93DF9300D000D01F92CDB7B8 :102B2000DEB7FC018081918123813481232B31F038 :102B30009F3F31F491E08F3F19F403C091E001C051 :102B400090E090FD19C57F0185E0DE0111960190AE :102B50000D928A95E1F7F701228189819A812223DA :102B600049F00E94DC1C182F682F89819A810E94ED :102B70007E1D03C00E94521D182F69817A81812F0A :102B80000E944F2B8C018091E204811132C2011509 :102B9000FCE51F0731F168F4003E110509F45FC040 :102BA000043E110509F460C00932110509F08EC117 :102BB0000EC00A3C3CE5130769F10B3C8CE5180795 :102BC000C1F0033C9CE5190709F080C136C0809133 :102BD0002A06882309F44CC080912906882309F429 :102BE00047C0F7018281882309F403C20E9473154C :102BF00000C2F7018281882309F4FBC18091550747 :102C0000E4ECF1E092919817B0F001E0EE3BF007B0 :102C1000C9F722C0F7018281882309F4EAC18091B3 :102C20005507EEEBF1E024EC31E02E173F07A1F061 :102C300091918917D0F7892F0FC0F70182818823DE :102C400009F4D7C180915507811103C080914701D4 :102C500003C08093470180E00E943E15CAC1F7017E :102C6000828180932A0604C0F7018281809329061D :102C7000F7018281882309F48EC110922B0602305D :102C8000FCE51F0708F471C106312CE5120738F086 :102C900098012B5F3C452930310508F066C10E9440 :102CA000071C90930B0480930A0400313CE5130742 :102CB00009F4C3C008F041C008309CE5190709F4C5 :102CC0009AC0F0F40430FCE51F0709F487C068F4EB :102CD00002303CE5130709F477C003301C4509F0C6 :102CE000E5C080910A04826076C006309CE5190731 :102CF00009F46EC008F07BC080910A0488606BC044 :102D00000C30FCE51F0709F485C068F40A303CE587 :102D1000130709F474C008F079C00E944D20809117 :102D20000A04806858C00E309CE5190709F476C083 :102D300008F07FC080910A048BC00C3FFCE51F07A0 :102D400009F44FC018F503313CE5130709F47DC0C1 :102D500078F401319CE5190709F473C002311C4570 :102D600009F0A4C00E944D2080910A048F7733C0DF :102D70000531FCE51F0709F472C008F486C00B3F5B :102D80001C4509F093C080910B043EC001158DE5F0 :102D9000180709F45FC058F40E3FECE51E0709F46C :102DA00044C008F43FC080910B0482602DC0023003 :102DB0002DE5120709F475C008F45DC003301D4508 :102DC00009F074C060E06EC080910A04816003C0A5 :102DD00080910A04806180930A0468C080910A048B :102DE00011C080910B04826080930B045FC08091BE :102DF0000A048062F0CF80910A048064ECCF809155 :102E00000A0488608460E7CF8160EECF80910A0475 :102E10008E7FE1CF80910A048D7FDDCF80910A04FF :102E2000877FD9CF80910B0418C080910B048D7FD0 :102E3000DBCF80910A048F7ECECF80910A048F7DF4 :102E4000CACF80910A048F7BC6CF80910A04877F06 :102E50008B7FC1CF80910B048D7F8E7FC5CF8091FA :102E60000A0482FB222720F991E0922790FB82F945 :102E700090FB83F9B0CF80910B04982F90959170BF :102E80008E7F892B90FB81F9AFCF0E944D208091DE :102E90000A0487FB222720F991E0922790FB87F90B :102EA0009ACF61E08EE090E00E94263160910A04A2 :102EB00010910B0484E090E00E942631612F81E2A2 :102EC00090E00E9426310E944D2093C0043FFCE513 :102ED0001F07A1F406E221EE40EE64EF7CE50AC094 :102EE000083D9CE5190709F0C3CE06E221EE41EE4C :102EF00068ED7CE5C7010E948D2A7BC0053F2CE56B :102F00001207A0F4093D3CE5130731F407E225EE72 :102F100045EE69ED7CE5EECF0A3D8CE5180701F73B :102F200008E221E045EE6AED7CE5E4CF063FECE502 :102F30001E0731F406E221EE42EE66EF7CE5DACFC1 :102F4000063FFCE51F0730F407E225EE44EE65EF8F :102F50007CE5D0CF073F2CE5120709F089CE07E2C8 :102F600025EE46EE67EF7CE5C5CF06313CE513075D :102F700019F58091F1068A7A91E009F490E0909336 :102F80002C06882311F065E301C069E28DE296E02A :102F90000E94D21B0EC006311C4509F048C080912A :102FA0002C06882309F4E6C265E38DE296E00E94D0 :102FB000AA1B0E94881C1DC09801235C3C4524313B :102FC0003105B8F001159CE5190731F00F3D1C459E :102FD00071F50E94181C0DC00E944D20FFE70AE108 :102FE00016E0F15000401040E1F700C000000E94E0 :102FF000F6148091EE06877009F4BEC2F701828153 :10300000882309F4B9C282E00F900F900F900F90BF :103010000F90DF91CF911F910F91FF90EF90DF9074 :10302000CF90BF90AF909F908F900C94E41DF701CC :1030300000811181882349F0C8010E94DC1CD82E30 :10304000682FC8010E947E1D04C0C8010E94521D45 :10305000D82EB8018D2D0E947E0E8C01982EF7017E :10306000B280A580A2949FE0A9228091EE0687708D :1030700099F0BB2089F0812F807F803421F080E29D :10308000800F883048F082E00E94E41D8091EE06B7 :103090008770DD24D3948111D12CC12EC2948FE08E :1030A000C8228C2D90E08C30910508F035C2FC01CF :1030B000E957FF4F0C94D531812F807F1F708823F3 :1030C00011F01295107FBB20B9F0112309F40FC243 :1030D00080E2800F883010F0911006C08091F106D8 :1030E000182B1093F10605C08091F006182B109351 :1030F000F0060E94881CFBC1802F0E94852F11239F :1031000009F40AC2005E1095083010F0911006C054 :103110008091F10618231093F10605C08091F00606 :1031200018231093F0060E94881CF6C1812F807F1F :103130001F70803211F01295107F992021F0F1E07C :103140009F16E1F02AC0BB2081F08091F206AA20F0 :1031500051F001E0A01207C0182B181709F4DCC1C8 :103160001093F206D9C1812B10C0AA2021F021E0D2 :10317000A21609F4D1C10E94821C27C0BB2041F0D5 :1031800035E03A1508F4C8C1812F0E947B2FC4C1D5 :1031900084E08A1508F4C0C118C0BB2049F0AA20F9 :1031A00099F3F701858180FFA2C18F708583ECCFF1 :1031B000AA2059F0093309F0ACC1FFEF13EF21E069 :1031C000F15010402040E1F7A2C1812F0E94702FE2 :1031D000A3C1812F86958695837019F0813059F0AF :1031E0009BC1BB2019F0C801937002C080E090E041 :1031F0000E946B2A97C1BB2019F0C801937002C0CE :1032000080E090E00E94552A8DC1812F837009F0E3 :1032100069C0B11085C1902F929596959770990FBE :10322000990F802F8F70882E912CA12CB12C092EF4 :1032300004C0880C991CAA1CBB1C0A94D2F704FF7A :1032400012C04FE050E060E070E004C0440F551F32 :10325000661F771F9A95D2F7DB01CA01809590957A :10326000A095B09503C080E090E0DC01169516951E :10327000412F4370423019F1C8F40091F3061091C8 :10328000F4062091F5063091F606413059F0882970 :103290009929AA29BB29BC01CD016023712382236E :1032A00093230AC0802A912AA22AB32ABC01CD0105 :1032B000682979298A299B290E941E1E31C18829E3 :1032C0009929AA29BB290091F3061091F4062091AF :1032D000F5063091F606BC01CD01602771278227E3 :1032E0009327EACFBB2019F0812F817001C086950A :1032F000882309F415C1902F929596959770990F90 :10330000990F802F8F70882E912CA12CB12C092E13 :1033100004C0880C991CAA1CBB1C0A94D2F704FF99 :1033200012C04FE050E060E070E004C0440F551F51 :10333000661F771F9A95D2F7DB01CA018095909599 :10334000A095B09503C080E090E0DC01169516953D :10335000412F43704230D9F068F500911E0610915C :103360001F062091200630912106413059F088290E :103370009929AA29BB29BC01CD016023712382238D :1033800093231EC0802A912AA22AB32A13C0882917 :103390009929AA29BB2900911E0610911F06209188 :1033A000200630912106BC01CD01602771278227BC :1033B000932706C0BC01CD01682979298A299B2958 :1033C0000E94A91DADC01F70BB2039F0812F0E9443 :1033D000FD1D802F0E947B2FA3C0802F0E94702F85 :1033E000812F0E94BF1D9CC0802F32EF931609F4DD :1033F00040C0391538F090EF991661F0E1EF9E1654 :1034000099F170C0F3EF9F16D9F124EF921609F4E9 :103410004EC068C0BB2019F134E03A1508F47CC0F6 :103420001F7181E090E0A0E0B0E0AC01BD0104C0FC :10343000440F551F661F771F1A95D2F780911E06FD :1034400090911F06A0912006B09121068A019B0150 :10345000082719272A273B27C901B80125C025E0DD :103460002A1508F459C0DCCFBB2029F0812F8F71B9 :103470002CC0BB20D9F3812F8F710E94BF1D4CC07F :10348000BB2079F01F7181E090E0A0E0B0E0BC01CA :10349000CD0104C0660F771F881F991F1A95D2F7B8 :1034A00003C060E070E0CB010E94A91D35C0BB20C5 :1034B00079F01F71812F0E94FD1D38E0139FC0011C :1034C000112483608093EE06812F0E94FD1D24C08D :1034D00081E00E94E41D81E08A15F0F482E00E9400 :1034E000E41D1AC0BB2039F0AA2009F4BFCF802FF9 :1034F0000E94E12F11C0AA2009F4BDCF893349F4FD :103500009FEFE3EFF1E09150E040F040E1F700C0C1 :103510000000802F0E94852F88EF8C0D843010F4DE :103520000E94812ADD2041F18091EE0680FD24C0B9 :10353000F70112828595859585950E94FD1DC7012D :103540000E9480158091EE068595859585950F9052 :103550000F900F900F900F90DF91CF911F910F91CF :10356000FF90EF90DF90CF90BF90AF909F908F90A3 :103570000C94BF1D69E219CD0F900F900F900F9022 :103580000F90DF91CF911F910F91FF90EF90DF90FF :10359000CF90BF90AF909F908F90089508958091A5 :1035A000F806089580E00895CF93DF9300D01F922E :1035B000CDB7DEB790911B07943011F589837B83DB :1035C0006A839093E9008FEF9091E800815095FD18 :1035D00006C09AE69A95F1F700C08111F5CF809167 :1035E000E80085FF0DC040E050E063E070E0CE01F0 :1035F00001960E9462208091E8008E778093E80017 :103600000F900F900F90DF91CF910895BC0184E04F :103610000C94D41ABC0183E00C94D41ACF93DF939A :1036200020914801222339F020910A0427FF03C08A :1036300060E224E002C068E021E02093E9002FEF7F :103640003091E800215035FD06C03AE63A95F1F791 :1036500000C02111F5CF2091E80025FF1DC0EC012D :1036600080914801811105C040E050E068E070E0C1 :1036700003C070E040E050E0CE010E9462208091E3 :10368000E8008E778093E80080E2FE01A9EFB6E0C3 :1036900001900D928A95E1F7DF91CF91089578948A :1036A0001F920F920FB60F9211248F939F93AF9397 :1036B000BF938091AB049091AC04A091AD04B09104 :1036C000AE040196A11DB11D8093AB049093AC0490 :1036D000A093AD04B093AE04BF91AF919F918F9131 :1036E0000F900FBE0F901F9018952FB7F8948091F0 :1036F000AB049091AC04A091AD04B091AE042FBF87 :1037000008951F920F920FB60F9211248F939F93DB :10371000AF93BF9380910E04811113C08091AB04CD :103720009091AC04A091AD04B091AE044196A11D5E :10373000B11D8093AB049093AC04A093AD04B093FF :10374000AE04BF91AF919F918F910F900FBE0F90DC :103750001F901895209148012223C9F020910A0456 :1037600027FF15C0262F2695269526952E31C8F4BD :10377000FC01E20FF11D677081E090E001C0880F4D :103780006A95EAF780959281892382830895FC01E6 :1037900006962281621301C012823196E817F9075A :1037A000C1F70895209148012223C1F020910A0415 :1037B00027FF14C0262F2695269526952E3130F505 :1037C000FC01E20FF11D677081E090E001C0880FFD :1037D0006A95EAF79281892B82830895FC013296DB :1037E0002FEF30E04191641789F02F3F19F4411118 :1037F00001C0232F3F5F3630A9F72F3F39F0FC017E :10380000E20FF11D27FDFA95628308950895CF9385 :1038100084E090E00E940831C82F81E290E00E948D :1038200008312C2F30E0A901582BCA01CF910895FF :103830006BEE7EEF80E090E00E94443160E082E039 :1038400090E00E94263160E083E090E00E94263103 :103850001092F3061092F4061092F5061092F606F6 :1038600060E084E090E00E94263160E081E290E038 :103870000E94263160E085E090E00E94263160E001 :1038800086E090E00E9426316FEF87E090E00E9492 :10389000263140E050E0BA0188E090E00E943831E3 :1038A00060E08DE090E00E94263140E050E0BA01F7 :1038B00088E190E00E94383160E087E190E00E946A :1038C000263140E050E0BA018CE190E00E943831AE :1038D00060E080E290E00E94263140E050E0BA01D2 :1038E00088E190E00E94383140E050E0BA018FE07A :1038F00090E00E94383140E050E0BA0183E190E06E :103900000C9438318091F20681111092F2060895DC :103910009091F1068091F006892B2091EF06982F67 :10392000922B90932D068091F2068823D9F0892B53 :1039300080932D0680914801882331F080910A04FC :1039400087FF02C08EE101C086E0EFE2F6E090E082 :10395000815028F021912223D9F39F5FF9CF911153 :103960000E94821CE0910C04F0910D043097A9F0A4 :1039700080914801882359F080910A0487FF07C08D :1039800080912D0680932E0685E080932D0602807F :10399000F381E02D8DE296E00994089580E090E0B7 :1039A0000E946B2A80E090E00E94552A1092F00657 :1039B0001092EF060C94881CBF92CF92DF92EF9288 :1039C000FF920F931F93CF93DF938C01C0901E063D :1039D000D0901F06E0902006F09021068091F3061B :1039E0009091F406A091F506B091F606C82AD92A5E :1039F000EA2AFB2ACFE1D0E0D701C6010C2E04C091 :103A0000B695A795979587950A94D2F780FD04C03F :103A1000219790F7B12C07C0BC2EB8018C2F0E94C3 :103A20007E0E0197A9F38B2DDF91CF911F910F91FE :103A3000FF90EF90DF90CF90BF900895CF93DF93EA :103A4000EC010E94DC1CBE010E947E0EDF91CF9132 :103A500008950E941E1D292F2F70E92FE295EF7007 :103A60004E2F50E0FA013297EE30F105B8F4ED56E2 :103A7000FF4F0C94D531803F99F018F4883E70F4D4 :103A80000FC0843F59F40CC0883E50F0813F31F4A0 :103A900007C0822F869586958695089580E00895C3 :103AA00081E008952EE0929F800D1124682F669585 :103AB00066956695982F977085E0689FB0011124F0 :103AC00040E050E080E0FB01E40FF51FEB57F94FB9 :103AD000208130E0092E02C0369527950A94E2F73E :103AE00021703327042E01C0220F0A94EAF7822B9B :103AF0004F5F5F4F4530510531F708952EE0929F9B :103B0000800D1124E82FE695E695E695877051E043 :103B100001C0550F8A95EAF785E0E89FF00111246E :103B2000EB57F94F20E030E070E04081CB01022EEE :103B300002C0969587950A94E2F781708195842753 :103B40008523842781932F5F3F4F2530310569F707 :103B50000895CF92DF92EF92FF926B017C010E9459 :103B60002915C0921E06D0921F06E0922006F09200 :103B70002106FF90EF90DF90CF900C94CE1C0F9316 :103B80001F9341E050E060E070E004C0440F551F17 :103B9000661F771F8A95D2F740955095609570956E :103BA00080911E0690911F06A0912006B0912106DB :103BB0008A019B01082319232A233B23C901B80149 :103BC0001F910F910C94A91D2091EE0680958223E0 :103BD0008093EE06982F977079F430E0482F082EE6 :103BE000000C550B2417350739F08595859585957B :103BF0000E94BF1D1092EE0608950F931F9341E09F :103C000050E060E070E004C0440F551F661F771F4E :103C10008A95D2F780911E0690911F06A0912006EA :103C2000B09121068A019B01082B192B2A2B3B2BD3 :103C3000C901B8011F910F910C94A91D6093F3065F :103C40007093F4068093F5069093F6060C94CE1CC0 :103C50008091840690915306891719F08F5F8770C1 :103C6000FBCF08950F931F93CF93DF93809152065C :103C700082958F7009F05DC080914F06882309F40A :103C800058C0809184061091530660914D06709142 :103C90004E06C0915006D091510691E06F3F09F059 :103CA00090E0292F06E0811709F443C0209721F006 :103CB0007F3F21F030E003C031E001C0322F90E0BF :103CC00030FD34C0089FF001099FF00D1124DF0181 :103CD000AC5AB94F11963C911197371327C03C91BC :103CE000361324C012963C91129731111FC01396BF :103CF0004D915C9114974C1B5D0B483C5105B0F401 :103D0000809152068F70806180935206E75AF94F76 :103D100080818F70806180838DE496E00E948015A1 :103D2000DF91CF911F910F910C94281E01968770FF :103D3000BACFDF91CF911F910F9108959F92AF92CB :103D4000BF92CF92DF92EF92FF920F931F93CF9388 :103D5000DF93CDB7DEB761970FB6F894DEBF0FBE25 :103D6000CDBF8C0185E0F801DE011D9601900D921A :103D70008A95E1F7F80190818181E28030914D06CA :103D800060914E06409150065091510641155105E3 :103D900031F06F3F31F421E03F3F19F403C021E0DF :103DA00001C020E0F22FF1709F2E20FD23C1F80109 :103DB000C380D4802DE4A22E26E0B22EF0904F06D0 :103DC000F601E41BF50BFF2009F4CEC0209152064A :103DD000E83CF10508F099C0422F407F09F051C03E :103DE000681311C039130FC0FE2CE1100CC02F70E6 :103DF000206120935206C5010E94801580915206D1 :103E0000F801858337C1CD2831F08F3F31F421E0AF :103E10009F3F19F403C021E001C020E020FD03C052 :103E200021E02E2502C020E030E0F22FF170FF2EBD :103E300020FF1DC0209184064091530656E02417B0 :103E400009F4F6C030E0529FF001539FF00D1124A9 :103E5000EC5AF94F6181861306C06081961303C046 :103E60006281E61204C02F5F3F4F2770E8CFFE2C1F :103E7000EE2009F4FFC080915206816080935206C3 :103E800050C0681307C0391305C0E11003C0F80122 :103E900025838DC09D878E878D859E850E94291DD7 :103EA000882369F1EE2059F120915206822F8295E4 :103EB0008F7090E0029774F080914D0690914E06BD :103EC00098878F831986DB86CA862C87CE01079652 :103ED0000E94801586E0F801ADE4B6E001900D92F5 :103EE0008A95E1F70E94321E0DC06817E1F09D87A8 :103EF0008E878D859E850E94291D81111EC0C80157 :103F00000E948015FF24F394B5C0422F407F69F7CB :103F10008DE496E00E94801586E0F50111928A9565 :103F2000E9F7F12CA7C03913E2CFE110E0CFF80197 :103F30002583C8010E94801557C0EE2001F320910F :103F40005206822F82958F7090E002971CF280912A :103F50004D0690914E069A8389831B82DD82CC8226 :103F60002E83CE010196B4CFE83CF105E8F5FE2C96 :103F7000EE2029F2681327C0391325C0209152067C :103F800020FD18C0822F82958F70482F50E0411578 :103F9000510581F0F80125834F30510541F08F5FC5 :103FA000982F9295907F822F8F70892B8583C801DF :103FB0000E94801586E0F801ADE4B6E001900D9214 :103FC0008A95E1F757C09D878E878D859E850E94D3 :103FD000291D81117FCF8091520681608093520606 :103FE000C8010E94801546C086E0F50111928A95AD :103FF000E9F740C0EE2009F482CF9D878E878D853A :104000009E850E94291DF82E882309F478CF86E02A :10401000F801ADE4B6E001900D928A95E1F7809148 :104020004D0690914E060E941E1D0E94321E22C017 :104030009D878E878D859E850E941E1D292F229526 :104040002F70223028F49F7039F0811105C00BC009 :10405000243028F49F7049F4805E883020F0C80135 :104060000E9480159F2CF92C05C0F8019581907F46 :1040700099F7F9CF8F2D61960FB6F894DEBF0FBE7A :10408000CDBFDF91CF911F910F91FF90EF90DF9007 :10409000CF90BF90AF909F9008951092F1068091BD :1040A0004801882331F080910A0487FF02C08EE125 :1040B00001C086E0EFE2F6E0DF011D928A95E9F7A4 :1040C0000C94CE1CEF92FF920F931F93CF93DF932C :1040D0007C018B010E94562D811119C0E701011549 :1040E0001105A1F08091E80085FD0AC08091E800EB :1040F0008E778093E8000E94562D882381F307C0B5 :1041000089918093F10001501109E9CF80E0DF919E :10411000CF911F910F91FF90EF9008950F931F93F0 :10412000CF93DF931F92CDB7DEB769838A0160E03A :104130000E94A41097FD13C061E070E0CE010196CB :104140000E946C1097FD0BC061E070E0C8010E94F6 :104150006C108C0197FD05C00E949C1002C0282F96 :1041600002C0202F912F822F0F90DF91CF911F91AE :104170000F910895CF92DF92EF92FF920F931F93CA :10418000CF93DF93CDB7DEB72F970FB6F894DEBF8E :104190000FBECDBF7C0189011A861B861C861D8639 :1041A00019821A8286E0D82EDB8281E08C8384E03B :1041B0008D837E836F835887498749E050E0BE0135 :1041C0006F5F7F4FF70180810E94241197FD40C0EF :1041D000C7010E943D1197FD3BC060E0F70180815F :1041E0000E94A41097FD34C01E86DF8662E070E056 :1041F000CE010E960E946C1097FD2AC061E0F70177 :1042000080810E94A41097FD23C081E00E944A1083 :1042100097FD1EC06E01FAE0CF0ED11CE12CF12CEF :104220008FEFE81AF80A81E094E0E916F1040CF047 :1042300080E00E944A1097FD0BC0F60181936F0148 :10424000F4E0EF16F10461F70E949C1084E090E026 :1042500097FD09C04A855B856C857D85F8014083A3 :104260005183628373832F960FB6F894DEBF0FBE1F :10427000CDBFDF91CF911F910F91FF90EF90DF9015 :10428000CF9008956F927F928F929F92AF92BF923C :10429000CF92DF92EF920F931F93CF93DF933C0166 :1042A000C091490185E1C89FC02D1124D5E1DC0FE3 :1042B000DA3608F0D9E660915607669580914E0788 :1042C00090914F070E94F12B182FCD1708F044C092 :1042D0008C2E912CF401E35BFC4F908180914A017C :1042E0008923C1F1F401EE0FFF1FE558FD4FC08097 :1042F000D12C80E7C81AD108F401EE0FFF1FE45853 :10430000FD4FA080B12CE0E2AE1AB108CC9C900128 :10431000CD9C300D300D1124AA9CC001AB9C900D9A :10432000900D1124820F931F0E94972B082F6091EC :1043300053077091540780915507E12E9501A6010E :10434000F30109950E94FB2B462F282F672FC401EC :104350000E945E2BCF5FB9CF81E0D93608F080E0B4 :10436000DF91CF911F910F91EF90DF90CF90BF9091 :10437000AF909F908F907F906F900895CF92DF9233 :10438000EF92FF920F931F93CF93DF936C01C09135 :10439000490185E1C89FC02D1124D5E1DC0FDA3633 :1043A00008F0D9E660915607669580914E07909186 :1043B0004F070E94F12B182FCD1778F5EC2EF12C1A :1043C000F701E35BFC4F908180914A01892319F149 :1043D000F701EE0FFF1FE458FD4F208130E020521F :1043E0003109F701EE0FFF1FE558FD4F408150E006 :1043F00040575109609153077091540780915507B8 :10440000012FF60109950E94FB2B462F282F672FBD :10441000C7010E945E2BCF5FCFCF81E0D93608F075 :1044200080E0DF91CF911F910F91FF90EF90DF908F :10443000CF900895DF92EF92FF920F931F93CF9347 :10444000DF937C01C091490185E1C89FC02D1124F3 :10445000D5E1DC0FDA3608F0D9E6609156076695AB :10446000669580914E0790914F070E94F12BD82EB0 :10447000CD17F0F40C2F10E0F801E35BFC4F9081B6 :1044800080914A01892391F06091530770915407FC :10449000809155072D2D4C2FF70109950E94FB2B7C :1044A000462F282F672FC8010E945E2BCF5FE0CFD9 :1044B00081E0D93608F080E0DF91CF911F910F9114 :1044C000FF90EF90DF9008959F92AF92BF92CF92AE :1044D000DF92EF92FF920F931F93CF93DF936C01C4 :1044E000C091490185E1C89FC02D1124D5E1DC0FA1 :1044F000DA3608F0D9E660915607669566958091A0 :104500004E0790914F070E94F12B182F80E4810FE6 :104510000E94762B90E8F92EF80E812F0E94762BC0 :1045200020E8922E980ECD1700F5AC2EB12CF50197 :10453000E35BFC4F908180914A018923A1F0609157 :1045400053077091540780915507E12E0C2F292DA8 :104550004F2DF60109950E94FB2B462F282F672F20 :10456000C5010E945E2BCF5FDECF81E0D93608F017 :1045700080E0DF91CF911F910F91FF90EF90DF903E :10458000CF90BF90AF909F900895CF92DF92EF921F :10459000FF920F931F93CF93DF936C01C09149015A :1045A00085E1C89FC02D1124D5E1DC0FDA3608F073 :1045B000D9E62091560730E040E050E06FEF7FEF02 :1045C00080E090E00E944A318901CD17E8F5EC2E99 :1045D000F12CF701E35BFC4F908180914A01892324 :1045E00089F190912507915097FD15C0492F092E0B :1045F000000C550BFA01EB5DF84F8189C813F3CF1E :10460000440F551FFA01EB5DF84F218D328D2017B5 :10461000310748F701C0980160915607C9010E940F :10462000F12BAC01609153077091540780915507AD :10463000F60109950E94FB2B462F282F672FC701F3 :104640000E945E2BCF5FC1CF81E0D93608F080E0B9 :10465000DF91CF911F910F91FF90EF90DF90CF905E :1046600008952F923F924F925F926F927F928F9216 :104670009F92AF92BF92CF92DF92EF92FF920F93F1 :104680001F93CF93DF93CDB7DEB727970FB6F8947C :10469000DEBF0FBECDBF282E4B012091490185E121 :1046A000289F802D11248E83182F1B5E1A3608F048 :1046B00019E63091250739839E81911708F077C05C :1046C0008E81682E712CF301E35BFC4F9081809109 :1046D0004A01892309F467C030905307409054077A :1046E000522C1F82C301880F991FDC01A558BD4FB2 :1046F000BB83AA83C301880F991FFC01E458FD4FB7 :10470000FD83EC83F9815F16E0F5E52CF12CAA819D :10471000BB81CC90D12CF701EB5DF84F8181C81A99 :10472000D108AC81BD81AC90B12C8185A81AB108AB :10473000CC9C9001CD9C300D300D1124AA9CC00161 :10474000AB9C900D900D1124820F931F0E94972B0C :10475000082FF701EE0FFF1FEB5DF84F6091560732 :10476000818D928D0E94F12B7C019501A601632D14 :10477000742D8F81F4010995362E472E8F83539423 :10478000C1CF209155078F81382F329F312D1124B1 :10479000832F632D742D0E94FB2B462F282F672F0C :1047A000C3010E945E2B8E818F5F8E8385CF81E057 :1047B000193608F080E027960FB6F894DEBF0FBEDA :1047C000CDBFDF91CF911F910F91FF90EF90DF90C0 :1047D000CF90BF90AF909F908F907F906F905F90A1 :1047E0004F903F902F9008951F93CF93DF93CDB7B5 :1047F000DEB7AA970FB6F894DEBF0FBECDBFEDE1CE :10480000F7E08091F100819347E0E532F407C9F7C2 :1048100080911E07833009F460C030F4813071F05C :10482000823009F49AC0B1C08A3009F486C08B3056 :1048300009F46BC0893009F0A8C020C080911D0721 :10484000813A09F0A2C08091E800877F8093E80058 :104850008091210790912207892B21F460E289EF52 :1048600096E003C060E080E090E070E00E94142FCA :104870008091E8008B778093E80087C080911D07C6 :10488000813209F082C08091210790912207009720 :1048900019F0029709F079C08091E800877F809332 :1048A000E8008091E80082FD05C080911B0781111E :1048B000F8CF6BC08091F2009091F300029729F439 :1048C0008091F1008B7F813021F48091F100809301 :1048D000F8068091E8008B7754C080911D07813ADB :1048E00009F053C08091210790912207892B09F08C :1048F0004CC08091E800877F8093E8008091E800B9 :1049000080FFFCCF8091480137C080911D07813224 :10491000E1F58091210790912207892BB1F58091D3 :10492000E800877F8093E8000E94892D80911F070F :10493000809348010E944D2028C080911D0781323C :1049400021F58091E800877F8093E8000E94892DFF :10495000809120078093F70618C080911D07813A47 :10496000A1F48091E800877F8093E8008091E800BF :1049700080FFFCCF8091F7068093F1008091E800E2 :104980008E778093E8000E94892D8091E80083FF54 :10499000DAC180911D0790911E07492F50E04A30DF :1049A000510508F0D0C1FA01EF55FF4F0C94D531F5 :1049B000803821F0823809F0C6C108C080911907FB :1049C00090911A07992389F082600FC08091210786 :1049D0008F70873008F0B7C18093E9008091EB00B9 :1049E00085FB882780F91092E9009091E800977F75 :1049F0009093E8008093F1001092F1006DC1282F90 :104A00002D7F09F0A0C1882319F0823061F09BC18D :104A100080911F07813009F096C1933009F080E042 :104A200080931A072EC080911F0781112AC08091A0 :104A300021078F702FEF280F263008F084C1809354 :104A4000E9002091EB0020FF1CC0933021F48091FD :104A5000EB00806214C09091EB0090619093EB00AA :104A600021E030E0A90102C0440F551F8A95E2F70A :104A70004093EA001092EA008091EB0088608093F6 :104A8000EB001092E9008091E800877F8093E800B6 :104A90000E94892D58C1811156C110911F071F779F :104AA0008091E3008078812B8093E3008091E8007F :104AB000877F8093E8000E94892D8091E80080FF25 :104AC000FCCF8091E30080688093E300111102C065 :104AD00082E001C083E080931B0735C1805882309B :104AE00008F031C120911F07309120072C3D53E081 :104AF000350779F583E08A838AE289834FB7F89492 :104B0000DE01139620E03EE051E2E32FF0E0509307 :104B10005700E49120FF03C0E295EF703F5FEF7014 :104B20008E2F90E0EA3010F0C79601C0C0968D93AA :104B30009D932F5F243149F74FBF8091E800877F15 :104B40008093E8006AE270E0CE0101960E94142F83 :104B5000B1C08091210790912207432F5527433000 :104B60005105A9F068F44130510509F4FBC0423009 :104B7000510509F0E8C08BE590E0E5E6F7E04BC0B1 :104B80004132510529F14232510589F1DCC0C90198 :104B9000992781309105A1F058F0029709F0D3C010 :104BA000E2EDF7E0E4918E2F90E0E2EDF7E030C027 :104BB000E0E5F8E0E4918E2F90E0E0E5F8E028C031 :104BC000ECE3F8E0E4918E2F90E0ECE3F8E020C015 :104BD0008330910508F0B7C0880F991FFC01E3539B :104BE000FE4F0190F081E02D89E090E014C0833009 :104BF000910508F0A8C0FC01EE0FFF1FE953FE4F1E :104C00000190F081E02DDC01AC53BE4F8C9190E01F :104C1000009709F498C02091E800277F2093E800CE :104C200020912307309124072817390708F4C90178 :104C300040E0009771F120911B072223D9F1253024 :104C4000C9F12091E80023FD35C02091E80022FD44 :104C50002DC02091E80020FFECCF2091F200309190 :104C6000F300009759F02830310540F44491409307 :104C7000F100319601972F5F3F4FF3CF41E028308D :104C8000310509F040E02091E8002E772093E800FC :104C9000D0CF4111D0CF0AC080911B07882351F09B :104CA000853041F08091E80083FD04C08091E800E8 :104CB00082FFF2CF8091E8008B778093E80043C0B9 :104CC000803809F040C08091E800877F8093E80039 :104CD00080911C078093F1008091E8008E77D6CEFA :104CE000811131C080911F07909120079927029769 :104CF00054F58091E800877F8093E80010911F07AA :104D000010931C070E94892D111106C08091E300A9 :104D100087FD02C081E001C084E080931B0742E070 :104D200061EC81E00E94A82D42E261EC84E00E94E7 :104D3000A82D42E261EC82E00E94A82D42E260ECE4 :104D400083E00E94A82D8091E80083FF10C080912D :104D5000E800877F8093E8008091EB008062809379 :104D6000EB0005C082E190E0E0ECF7E054CFAA96BA :104D70000FB6F894DEBF0FBECDBFDF91CF911F916C :104D80000895E7E5F7E098E0E239F90729F0818333 :104D9000608342833396F7CF0895FC01EE0FFF1F27 :104DA0008E0F9F1FFC01E95AF84F618340832283D5 :104DB0000895EF92FF920F939701201B31092F3F27 :104DC000310519F010F02FEF30E02095382F320F19 :104DD00008F43FEF832F0F91FF90EF900895EF922B :104DE000FF920F939701201B31092F3F310519F0D6 :104DF00010F02FEF30E0322F3095482F430F08F49A :104E00004FEF842F620F0F91FF90EF900895EF9274 :104E1000FF920F93972F093438F4B701601B710983 :104E20006F3F710519F010F06FEF70E0485F5F4F52 :104E30004131510540F0A901485F5F4F41315105B3 :104E400010F06FEF70E06095482F460F08F44FEFB9 :104E5000842F37FF02C02D5F3F4F3595279535953D :104E6000279560915307620F792F0F91FF90EF9074 :104E70000895EF92FF920F93E00EF11CF90137FFB6 :104E800003C0F195E195F10924E0EE0FFF1F2A958B :104E9000E1F7EF3FF10519F014F0EFEFF0E09A01C0 :104EA00057FF03C031952195310994E0220F331F3C :104EB0009A95E1F72E173F070CF4F901EE0DFF1D4F :104EC000EF3FF10519F010F0EFEFF0E02E2F2095F5 :104ED000382F320F08F43FEF832F0F91FF90EF90A0 :104EE0000895EF92FF920F93970195E0099F200D8F :104EF000311D11242F3F310519F010F02FEF30E054 :104F00002095382F320F08F43FEF832F0F91FF9039 :104F1000EF90089522E8241B08F420E0620F089522 :104F20004095282F429F412D1124842F08950F93DF :104F30001F9310E0F801EE0FFF1FE558FD4F908121 :104F4000905797FD9195000F111FF801E458FD4F00 :104F5000E081F0E0B097DF01AA0FBB1F8D010E0FBB :104F60001F1F2003D001219FB00D1124E8E3F0E0C2 :104F7000E91BF10997FDF3959F01220F331F89016A :104F80000E0F1F1F40039001419F300D11242A0F67 :104F90003B1F37FF02C021583F4F220F232F221FF4 :104FA000330B620F1F910F9108950F931F93522F90 :104FB00010E0F801EE0FFF1FE458FD4FE081F0E034 :104FC000B097EE0FFF1F9F015203D001539FB00D0A :104FD0001124000F111FF801E558FD4F008110E06A :104FE00000571109000F111F40039001419F300D20 :104FF00011242A0F3B1F37FF02C021583F4F220FB9 :10500000232F221F330B620F1F910F9108950F93CF :105010001F93522F10E0F801EE0FFF1FE458FD4FD1 :10502000E081F0E0B0979F015203D001539FB00D93 :105030001124000F111FF801E558FD4F008110E009 :105040000057110940039001419F300D11242A0F90 :105050003B1F37FF02C021583F4F220F232F221F33 :10506000330B620F1F910F910895EF920F931F93CF :1050700093E0099F80011124159507956E2D600F0F :105080001F910F91EF900895A22F50E0FA01EE0FBB :10509000FF1FE458FD4F9081905297FD9195440F6A :1050A000551FFA01E558FD4F3081232F30E02A1BB0 :1050B0003109290F311D97FD3A95620F0895E42FAC :1050C000F0E0EE0FFF1FE458FD4F6081621B089572 :1050D000E42FF0E0EE0FFF1FE558FD4F6081621BEB :1050E0000895622F0895E42FF0E0EE0FFF1FE558BA :1050F000FD4F408134EE439F412D1124E82FF0E015 :1051000050E0445E5F4FDA01A21BB1099D01B7FF79 :1051100003C031952195310993E0220F331F9A95F1 :10512000E1F7AF01421B530B9A0157FF02C020E089 :1051300030E0582F259F212D1124822F0895E42F30 :10514000F0E0EE0FFF1FE558FD4F408134EE439F26 :10515000412D1124E72FF0E050E0445E5F4FDA016B :10516000A21BB1099D01B7FF03C0319521953109FB :1051700093E0220F331F9A95E1F7AF01421B530BC7 :105180009A0157FF02C020E030E0279F212D112413 :10519000722F0895FC019B01009721F477FF2BC02B :1051A00080E80895AC0197FF04C044275527481BA9 :1051B000590BB901640F751F37FD0CC0241B350B4B :1051C000C901A5E0880F991FAA95E1F70E94C13196 :1051D00080E20CC0CB0165E0880F991F6A95E1F76A :1051E000BA01621B730B0E94C13180E6861BF7FF78 :1051F00003C08195089580E00895EF920F93CF93B7 :10520000DF93D72FC82FC9010E19BA010E94CA28EF :10521000602F681B7D2F8C2FDF91CF910F91EF9026 :1052200008950F93CF93DF93D72FC82FC901BA01E9 :105230000E94CA28682F600F7D2F8C2FDF91CF919D :105240000F910895EF920F931F93CF93DF93D62F73 :10525000C72F182FC9010E19010FBA010E94CA28C1 :10526000081B202F219F212D1124822F6D2F7C2F91 :10527000DF91CF911F910F91EF900895EF920F93CF :105280001F93CF93DF93D62F172FC82FC9010E1965 :10529000070FBA010E94CA28702F781B719F712DC9 :1052A00011246D2F8C2FDF91CF911F910F91EF90D3 :1052B0000895FF920F931F93CF93DF93F62ED72F6E :1052C000182FC901C12FC01BBA010E94CA28982FEC :1052D000990F890FC81B2C2F219F212D1124822F5C :1052E0006F2D7D2FDF91CF911F910F91FF9008952A :1052F000FF920F931F93CF93DF93F62E172FD82F84 :10530000C901C72FC01BBA010E94CA28982F990F44 :10531000890F7C2F781B719F712D11246F2D8D2F7C :10532000DF91CF911F910F91FF900895879A81B3DC :105330008F7791B390682FB7F894E7E5F7E038E0FE :10534000E239F30761F0319148E091BB37FF81BB4F :10535000330F000000C081BB4A95B9F7F0CF2FBFD3 :105360008FE292E00197F1F700C0000008951F93CB :10537000CF93DF93CDB7DEB767970FB6F894DEBF54 :105380000FBECDBF342F4B8B252F5C8B6D8B7E8B4F :105390008F8B4E895F8961111092F00686E0FE01C5 :1053A0003D96DF01982F1D929A95E9F73D872E874C :1053B0006F87598B488BDE01179601900D928A9565 :1053C000E1F7CE0107960E949E1E81113EC086E045 :1053D000FE013796DE01119601900D928A95E1F754 :1053E000FF81E8856A857B856115710531F0EF3FA6 :1053F00031F481E0FF3F19F403C081E001C080E097 :1054000080FD23C02091530630E0C90101968770CA :1054100099274091840650E08417950779F1F98324 :10542000EA837D836C8396E0929FD001939FB00DB9 :105430001124AC5AB94FFE01319601900D929A9504 :10544000E1F7809353060E94281E16E0809184069F :10545000909153068917F9F0189FC00111248C5AB6 :10546000994F0E949E1E8823B1F08091840690E09F :1054700001968770992780938406E8CF0E944D207B :105480001092530610928406EDE4F6E086E0DF0108 :105490001D928A95E9F767960FB6F894DEBF0FBEA6 :1054A000CDBFDF91CF911F91089520919608309143 :1054B00097082817390771F09093970880939608FA :1054C000E0910C04F0910D04309721F00084F185F7 :1054D000E02D09940895209194083091950828179B :1054E000390771F09093950880939408E0910C042B :1054F000F0910D04309721F00680F781E02D09949A :105500000895E0910C04F0910D04309721F0019082 :10551000F081E02D099480E00895EF92FF920F93BF :10552000CF93DF93C42FD22FFC0182818823D1F047 :1055300040932B060E94751B9093930880939208CA :1055400080E28C0F883008F078C0C77081E001C01D :10555000880FCA95EAF7DF91CF910F91FF90EF90F6 :105560000C947B2F80912B06481356C020919208F3 :10557000309193084FB7F8948091AB049091AC04AC :10558000A091AD04B091AE044FBF821B930B883C39 :10559000910508F041C0CD17C9F080E28C0F88302A :1055A00040F4C77081E001C0880FCA95EAF70E94F5 :1055B000702F80E28D0F883048F481E09D2F977026 :1055C00001C0880F9A95EAF70E947B2F093319F0E2 :1055D000E12CF12C03C080E5E82EF12C802F0E94F5 :1055E000E12FE114F10451F08FEC97E00197F1F70E :1055F00000C0000091E0E91AF108F3CF802F0E946B :10560000852F80E28D0F8830C0F4D77081E001C013 :10561000880FDA95EAF70AC080E28C0F883068F4C8 :10562000C77081E001C0880FCA95EAF7DF91CF917A :105630000F91FF90EF900C94702FDF91CF910F910D :10564000FF90EF9008950F931F93CF93DF9350E057 :10565000440F551F2CE1629F400D511D112420E580 :1056600031E0682F629FC001639F900D1124480FA5 :10567000591FEA01CD5BDF4FCE010E940831082F90 :1056800010E0102F0027CE0101960E9408319801EA :10569000282BC901DF91CF911F910F910895462FBB :1056A000843038F47C3028F46E3018F4672F0C9472 :1056B000232B80E090E008950C94C1260C94CD2615 :1056C000E2E5F7E08DE380838091520190915301F0 :1056D000A091540181839283A3838FE7848345E063 :1056E00050E06CE170E0CF010C941631482F982FF8 :1056F00046FD9095E92FEF739F7046FD9F5FE29501 :10570000EF70EE0FF0E0EA54FC4F2181299F802DCD :10571000212D112482958F702295207F822B30813C :10572000982F930F892F47FD819580580895BC01CC :105730008230910508F40895613E8EE1780748F4BF :105740009B0195E0369527959A95E1F748E0420F41 :1057500001C04FEF91E0242F30E0290F311D359526 :105760002795229FF001239FF00DF00D11246E1755 :105770007F0718F44FEF420F04C02F3F39F091E03C :10578000920F491740F78FEF890F08958FEF089513 :105790000F93CF93DF93D72FC82F47FD4195E8E3B1 :1057A000F0E0CF01841B910947FD9395889FB001DC :1057B000899F700D700D1124229FC001239F900DB1 :1057C000900D1124860F971F0E94972B682F660F4C :1057D000860F682F600F7D2F8C2FDF91CF910F9157 :1057E000089520E030E0869F212D969F200D311DE9 :1057F0001124C9010895CF92DF92EF92FF920F9387 :105800001F93CF93DF93F62E472FE82FF0E071110F :1058100006C0EC5AF74F8491782F682F73C0272F5A :1058200030E0EC5AF74FE491FE2F0E2F10E056E0D7 :10583000659FC0011124CFEFD0E0BE010E94AD31C1 :105840005BEA5603C001579F900D11248F0D911DE7 :105850008F0D911D982F990F980F7E01E21AF30A70 :10586000E09ED001E19EB00DF09EB00D11248B2F73 :10587000499FA0011124452F55277E01E41AF50AFE :10588000E09EA001E19E500DF09E500D11246E018E :10589000C91AD108C29E7001C39EF00CD29EF00CB2 :1058A00011242F2D3327C21BD30BC09F9001C19F02 :1058B000300DD09F300D1124932F6230710591F07F :1058C00048F461157105E1F061307105B9F49E2F5E :1058D000E52F16C06430710569F040F0663071053F :1058E00079F00CC09E2FEB2F832F0AC0EB2F8F2F48 :1058F000952F06C09B2F8E2FE32F02C09B2F852F45 :105900007E2F692FDF91CF911F910F91FF90EF9024 :10591000DF90CF900895DF92EF92FF920F931F9345 :10592000CF93DF93EC01FC01E35BFC4F9081692393 :1059300081F1D09054070091550710915307E12E43 :10594000F12C0E94E830282FC7018C549F4F68E645 :1059500071E00E94C1318E199F0997FD03969595BC :105960008795959587952370612F289F600D112449 :105970007D2D802F0E94FB2B462F282F672FCE01D5 :10598000DF91CF911F910F91FF90EF90DF900C94DA :105990005E2BDF91CF911F910F91FF90EF90DF90E1 :1059A00008951F93CF93DF93FC01E35BFC4F2081AD :1059B0006223A9F0EC010E94E830182F0E94E83021 :1059C000612F782F809155070E94FB2B462F282F9F :1059D000672FCE01DF91CF911F910C945E2BDF9149 :1059E000CF911F9108951F920F920FB60F9211241D :1059F0002F933F934F935F936F937F938F939F93D7 :105A0000AF93BF93CF93DF93EF93FF93C091E900E0 :105A1000CF708091EC00D82FD17080FDD0E810922B :105A2000E9008091F000877F8093F00078940E94D5 :105A3000F4231092E9008091F00088608093F000D8 :105A4000CD2BCF70C093E900FF91EF91DF91CF9103 :105A5000BF91AF919F918F917F916F915F914F9186 :105A60003F912F910F900FBE0F901F901895E8ED6A :105A7000F0E080818C7F80831092E2001092DA0047 :105A80001092E100A0EEB0E08C9181608C93808157 :105A90008F77808319BCA7EDB0E08C918E7F8C93BB :105AA00080818F7E80831092980808952091E40071 :105AB0003091E50095E64091EC00842F817040FF25 :105AC00023C08091E80080FD1DC080911B078823C2 :105AD00099F0853099F08091EB0085FD11C04091DF :105AE000E4005091E5002417350729F3915011F097 :105AF0009A01E1CF84E0089582E0089583E008955B :105B000081E0089580E008954091E80042FFDDCFF4 :105B1000089580911D0787FF11C08091E80082FDE4 :105B200005C080911B078111F8CF11C08091E8005A :105B30008B770BC080911B07882349F08091E80088 :105B400080FFF8CF8091E8008E778093E800089579 :105B5000982F973068F59093E900981739F0709175 :105B6000EC002091ED005091F00003C0242F762F1F :105B700050E021FD02C09F5FECCF3091EB003E7FF3 :105B80003093EB003091ED003D7F3093ED0030918C :105B9000EB0031603093EB007093EC002093ED004C :105BA0005093F0002091EE0027FDE5CF80E00895AE :105BB0008F708093E90081E00895CF92DF92EF9299 :105BC000FF920F931F93CF93DF93C8EDD0E08881AE :105BD0008F7E8883E7EDF0E080818160808381E0C3 :105BE0008093980888818C7F888302EE10E0D8012A :105BF0001C921092DA0081EEC82ED12CD6011C9294 :105C000088818F77888388818068888388818F7D69 :105C1000888380818068808319BC10921B07109252 :105C20001C0710921A071092190790EEE92EF12C1A :105C3000F70180818B7F808388818160888342E047 :105C400060E080E00E94A82DD6018C918E7F8C931D :105C5000F801808181608083808188608083D701A2 :105C60008C918E7F8C93888180618883DF91CF9126 :105C70001F910F91FF90EF90DF90CF9008951F92AA :105C80000F920FB60F9211242F933F934F935F9370 :105C90006F937F938F939F93AF93BF93EF93FF93F4 :105CA0008091E10082FF09C08091E20082FF05C07F :105CB0008091E1008B7F8093E1008091DA0080FF8A :105CC0002AC08091D80080FF26C08091DA008E7FA4 :105CD0008093DA008091D90080FF18C088E189BDE7 :105CE0008AE189BD09B400FEFDCF81E080931B07E6 :105CF0008091980881110FC00E94372D0E94DD2DE0 :105D00008091E20084608093E20005C019BC10928B :105D10001B07109298088091E10080FF17C08091C6 :105D2000E20080FF13C08091E2008E7F8093E2004A :105D30008091E20080618093E2008091D8008062CF :105D40008093D80019BC85E080931B078091E10007 :105D500084FF2EC08091E20084FF2AC088E189BDC3 :105D60008AE189BD09B400FEFDCF8091D8008F7D06 :105D70008093D8008091E1008F7E8093E100809134 :105D8000E2008F7E8093E2008091E2008160809348 :105D9000E20080911C07882311F084E007C0809105 :105DA000E30087FD02C081E001C083E080931B0710 :105DB0008091E10083FF27C08091E20083FF23C030 :105DC0008091E100877F8093E10082E080931B0750 :105DD00010921C078091E1008E7F8093E1008091FA :105DE000E2008E7F8093E2008091E20080618093E8 :105DF000E20042E060E080E00E94A82D8091F00087 :105E000088608093F000FF91EF91BF91AF919F91D7 :105E10008F917F916F915F914F913F912F910F9053 :105E20000FBE0F901F9018952091230730912407E3 :105E30002617370748F06115710539F42091E800FD :105E40002E772093E80001C0B901FC0120E0611524 :105E5000710569F180911B078823E1F18530E1F13B :105E60008091E80083FD3AC08091E80082FD2CC05B :105E70008091E80080FFEBCF8091F2009091F300D9 :105E80006115710551F08830910538F42191209306 :105E9000F100615071090196F3CF21E0089709F0F4 :105EA00020E08091E8008E778093E800D0CF211128 :105EB000D1CF0AC080911B07882361F0853061F043 :105EC0008091E80083FD0AC08091E80082FFF2CF54 :105ED00080E0089582E0089583E0089581E00895C8 :105EE000882341F080959091F10689238093F106F3 :105EF0000C94881C0895882339F09091F106892B21 :105F00008093F1060C94881C0895882309F458C0E6 :105F1000682F823869F40E94812A81FF51C069E3A9 :105F20008DE296E00E94D21B0E94881C69E30EC09D :105F3000833891F40E94812A80FF42C063E58DE29C :105F400096E00E94D21B0E94881C63E58DE296E0D9 :105F50000E94AA1B0C94881C843869F40E94812A30 :105F600082FF2EC067E48DE296E00E94D21B0E9461 :105F7000881C67E4EBCF8CEF860F813A38F380E220 :105F8000860F883070F4677081E090E001C0880F60 :105F90006A95EAF780959091F10689238093F1063E :105FA000D9CF8BE5860F833020F480E090E00C940D :105FB0006B2A685A673120F480E090E00C94552AEF :105FC0000895CF93882309F4B5C0C82F8238B1F45F :105FD0000E94812A81FDAEC069E38DE296E00E94B5 :105FE000D21B0E94881C2FEF80E792E02150804056 :105FF0009040E1F700C0000069E317C08338E1F486 :106000000E94812A80FD96C063E58DE296E00E94A1 :10601000D21B0E94881C2FEF80E792E02150804025 :106020009040E1F700C0000063E58DE296E00E9439 :10603000AA1BCF910C94881C8438B1F40E94812A49 :1060400082FD78C067E48DE296E00E94D21B0E9438 :10605000881C2FEF80E792E0215080409040E1F7CC :1060600000C0000067E4E1CF8CEF8C0F813AB8F5F7 :10607000809148018823E1F080910A0487FF18C0CD :10608000EC2FE695E695E695F0E0E35DF94F828129 :10609000282F30E04C2F477081E090E002C0880F3D :1060A000991F4A95E2F782239323892B59F411C053 :1060B000EFE2F6E08191C81729F026E0E533F20718 :1060C000C9F707C06C2F8DE296E00E94AA1B0E94C0 :1060D000881C6C2F8DE296E00E94D21BAACF80E232 :1060E0008C0F883068F4C77081E090E001C0880FA1 :1060F000CA95EAF79091F106892B8093F10699CF22 :10610000EBE5EC0FE33040F4F0E0E254FC4F80812B :1061100090E0CF910C946B2AC85AC73158F4EC2FF9 :10612000F0E0EE0FFF1FEF53FC4F80819181CF9184 :106130000C94552ACF9108958F929F92AF92BF925F :10614000CF92DF92EF92FF92CF93DF93EC016881C1 :1061500079818A819B81611571058105910521F401 :1061600064E279ED8BE597E02DE133EF41E050E01B :106170000E944A3149015A019B01AC01A7EAB1E4EE :106180000E9469316B017C01ACEEB4EFA501940172 :106190000E947731DC01CB018C0D9D1DAE1DBF1D12 :1061A000B7FF03C00197A109B04888839983AA83E8 :1061B000BB839F77DF91CF91FF90EF90DF90CF90DF :1061C000BF90AF909F908F9008950E949C3008954B :1061D00080E091E00E949C300895A0E0B0E08093C0 :1061E000000190930101A0930201B093030108956F :1061F000DC01CB01FC01F999FECF06C0F2BDE1BD87 :10620000F89A319600B40D9241505040B8F7089575 :10621000F999FECF92BD81BDF89A992780B508956E :10622000A8E1B0E042E050E00C94FA30DC01A40FA9 :10623000B51F4150504048F0CB01840F951F2E915F :106240000E94273141505040D0F70895262FF999E8 :10625000FECF92BD81BDF89A019700B4021639F0C5 :106260001FBA20BD0FB6F894FA9AF99A0FBE089596 :106270000396272F0E9427310E942631252F0E9446 :106280002731242F0C9427310196272F0E94273184 :106290000C942631052E97FB1EF400940E94613168 :1062A00057FD07D00E947C3107FC03D04EF40C94BC :1062B000613150954095309521953F4F4F4F5F4F3D :1062C000089590958095709561957F4F8F4F9F4F62 :1062D00008950E949E31A59F900DB49F900DA49F9C :1062E000800D911D11240895B7FF0C9469310E940F :1062F0006931821B930B0895A1E21A2EAA1BBB1BC6 :10630000FD010DC0AA1FBB1FEE1FFF1FA217B30781 :10631000E407F50720F0A21BB30BE40BF50B661F97 :10632000771F881F991F1A9469F76095709580955B :1063300090959B01AC01BD01CF010895A29FB001D2 :10634000B39FC001A39F700D811D1124911DB29FA9 :10635000700D811D1124911D0895AA1BBB1B51E1D5 :1063600007C0AA1FBB1FA617B70710F0A61BB70BC5 :10637000881F991F5A95A9F780959095BC01CD016A :10638000089597FB072E16F4009407D077FD09D0E7 :106390000E94AD3107FC05D03EF4909581959F4F4A :1063A0000895709561957F4F0895EE0FFF1F05903A :1063B000F491E02D0994FB01DC0102C001900D92E3 :1063C00041505040D8F70895FB01DC014150504046 :1063D00048F001900D920020C9F701C01D92415074 :0A63E0005040E0F70895F894FFCF55 :1063EA0001000000FFFF033D8EFFB07F958EFFB0D6 :1063FA007F958EFFB07F958EFFB07FCF1A0E1BCE92 :10640A001A0A1B061B3C011D0000003C0119000072 :10641A00003C010A00000000510025012D01500036 :10642A002B010152003101B00100FF00993700AA87 :10643A0056008EFFB073797374656D37362F6C61B1 :10644A00756E63685F68656176795F3100302E37F3 :10645A002E3130342D3138382D6737613635356570 :10646A003533306200F0F1F2F3F4F5929495969791 :10647A00C06665646362616707060504C660C70291 :10648A0007040603090209040303080203030301BC :10649A00260C0D0E10110F1213172122250021317F :1064AA00426384B040226D2507030796067707905A :1064BA0007B00745464748494A4B4C4D4E4F505145 :1064CA005244434241403F3E3D3C3B3A39383727EC :1064DA0028292A2B2C2D2E2F3031323334262524ED :1064EA00232221201F1E1D1C1B1A530C0B0A0908EC :1064FA000706050403020100360D0E0F10111912CA :10650A001314151617183500000068676600000096 :10651A0000000065000000006162630000000000E6 :10652A00006400000000605F5E0000000000005D83 :10653A0000000000005A5B0000000000005C000040 :10654A0000005459580000000000005700000000E5 :10655A000055000000000000005600A9289D289060 :10656A002886287D28732869285F2855284B2841C2 :10657A002837282828253232323C324632553269A9 :10658A0032783281328E329F32A932B332B31EA2AE :10659A001E951E8B1E811E781E6E1E641E5A1E506C :1065AA001E461E3C1E321E251E23142F1439144368 :1065BA00144D14571461146B1475147F14891493B1 :1065CA00149D14A714B314B30AA40A980A8E0A8451 :1065DA000A7A0A700A660A5C0A520A480A3E0A34A9 :1065EA000A2A0A200A20002A0034003E00480052E3 :1065FA00005C00660070007A0084008E009800A497 :10660A0000B300E02DD632C732C228CC28D628D60D :10661A001ECC1EC21EC214CC14D614E019E00AD62F :10662A000ACC0AC20AC200CC00D600E00004040464 :10663A000404040404040404040404040404040410 :10664A000404040404040404040404040404040400 :10665A0004040404040404040404040404040404F0 :10666A0004040404040404040404040404040404E0 :10667A0004040404040404040404040404040404D0 :10668A0004040404040404040404040404040404C0 :10669A00040404040404003131295A1B750A818256 :1066AA0083E200E900EA00B500B600B700CD008336 :1066BA0001CC008A019201940121022302240225BD :1066CA0002260227022A02B300B4006F00700000FB :10F000004BC0000074C0000072C0000070C000005F :10F010006EC000006CC000006AC0000068C0000044 :10F0200066C0000064C00000A9C5000060C0000008 :10F030005EC000005CC000005AC0000058C0000064 :10F0400056C0000054C0000052C0000050C0000074 :10F05000E5C100004CC000004AC0000048C00000EC :10F0600046C0000044C0000042C0000040C0000094 :10F070003EC000003CC000003AC0000038C00000A4 :10F0800036C0000034C0000032C0000030C00000B4 :10F090002EC000002CC0000011241FBECFEFD0E115 :10F0A000DEBFCDBF83E090E050D480FD04C084B7C4 :10F0B0008D7F84BF03C084B7877F84BFE0E0F0E02A :10F0C0008591949111E0A0E0B1E0E8EAFEEF02C082 :10F0D00005900D92A239B107D9F721E0A2E9B1E07C :10F0E00001C01D92AF3AB207E1F736D1DBC688CF37 :10F0F0008823B9F02091F2003091F300232B69F4BA :10F100009091E8009B7F9093E8009091E80092FD39 :10F1100006C09EB39111F9CF04C09091F1008150C7 :10F12000E7CF0895EAE9F1E0358124819381828176 :10F130009093940180939501C901909392018093DB :10F1400093010895CF92DF92EF92FF921F93CF9396 :10F15000DF9300D01F92CDB7DEB79091A4018091CC :10F160009A019923D1F0843049F480919B01811157 :10F1700008C080919C018F3F21F455C0853009F46F :10F18000A2C08AE08093000183E08093A201809175 :10F19000EB0080628093EB00D4C0843009F443C05C :10F1A00028F4813051F08330D9F0CBC0853009F498 :10F1B0008AC0863009F4B2C0C4C010919B011230DD :10F1C00008F0BFC0AFDF111109C0609194017091C8 :10F1D000950120919601822F90E064D385E007C0CD :10F1E00080919B01982F9D7F29F49CDF89E080937B :10F1F0000001A7C0813009F0A4C0E0E0F0E08491F4 :10F200008F3F59F010929601F0939501E09394018D :10F210008AE08093000185E092C03196E11520EFED :10F22000F20769F78EC080919B01833091F581E0F0 :10F230008093A301E091A001F091A10180919C0134 :10F24000309761F0813009F07CC090919F018091EE :10F250009E01909397018093980173C0811111C012 :10F2600082E49CED9093B0018093AF019CE088E133 :10F270000FB6F894A895809360000FBE909360003D :10F2800060C085919491019609F05BC010920101D4 :10F2900058C0811156C080919C018F3F09F051C028 :10F2A000C12CD12C7601C701B601FCD28FEFD81A40 :10F2B000E80AF80AC11420EFD206E104F10499F734 :10F2C0001092A4013EC08091020190910301A0918F :10F2D000040189839A83AB8380919C0190919B0167 :10F2E000911107C0833038F5FE01E80FF11D8181CF :10F2F00012C0913031F5813359F020F48033D9F4C4 :10F3000088E509C0803631F08136A9F482E803C06F :10F310008EE101C086E98093990113C080919B0121 :10F32000833079F480919C0181110BC080919D0103 :10F330008093960106C08AE08093000188E0809364 :10F34000A2010F900F900F90DF91CF911F91FF902E :10F35000EF90DF90CF90089584B7877F84BF0FB67A :10F36000F894A89580916000886180936000109265 :10F3700060000FBE90E080E80FB6F89480936100C3 :10F38000909361000FBEC1E0C5BF82E085BF559A72 :10F390005D9A819AD8D36E9A769A3E9A469AC0938D :10F3A0006F0083E080938100769846987894C0E05F :10F3B000D0E080910101882361F152D58FB1827034 :10F3C00090910001923009F5C93893E1D907E8F02E :10F3D000882369F38FEC97E00197F1F700C00000F4 :10F3E0005AD36E9876983E98469810926F00109275 :10F3F000810081E085BF15BE11BA10BA1BB81AB8DA :10F40000E0919701F09198010995882381F2219666 :10F41000D0CF8091A3018111D0CFDCCF1F920F926A :10F420000FB60F9211248F9380E48CB986B98F9117 :10F430000F900FBE0F901F9018955F926F927F9262 :10F440008F929F92AF92BF92CF92DF92EF92FF92F4 :10F450000F931F93CF93DF938091A7018F77813212 :10F4600009F0DEC180E48CB986B98091AD0190913C :10F47000AE019093A1018093A0018091A8018330F7 :10F4800009F488C158F48130D1F0823009F0C8C144 :10F490008091E800877F8093E800F0C0853009F410 :10F4A0009FC108F495C1863009F0BAC18091E80087 :10F4B000877F8093E80082E080930001A1C1809162 :10F4C000E800877F8093E8008091A301882319F0EA :10F4D00039DE1092A3018091A0019091A1010097C3 :10F4E00051F12091E80022FD04C02EB32111F9CF83 :10F4F00097C12091F10020939A0101979093A10167 :10F500008093A001EBE9F1E08091F2009091F3008B :10F51000892B81F08091F10081938091A0019091DD :10F52000A10101979093A1018093A00121E0E03A0D :10F53000F20751F707DE80910001853009F096C08F :10F540008091A0019091A101892B21F482E0809308 :10F5500000018CC08AE1CCDD0091940110919501ED :10F56000802F8F71C5DDC0919201D09193012196BA :10F57000C01BD10B80919B01811166C0D695C795A8 :10F58000680180919601E82EF12C7D2C682E5F2C6D :10F5900010E02097C9F18091F2009091F300892B3F :10F5A000A9F021974091F1005091F100C701B601F7 :10F5B000B9D11F5F4601570182E0880E911CA11C42 :10F5C000B11C75016401103871F40FC08091E8001E :10F5D0008B7F8093E8008091E80082FDE2CF8EB3BC :10F5E0008111F9CF1DC12097A1F6602F772D862DAF :10F5F000952D78D1209769F2C501B40153D1082D1A :10F60000792C6A2C5B2CC4CF80919201909193014C :10F61000909395018093940127C08091F20090917E :10F62000F300892BA1F021976091F1008091940162 :10F630009091950125D48091940190919501019626 :10F640009093950180939401209739F70DC0809194 :10F65000E8008B7F8093E8008091E80082FDE3CF93 :10F660008EB38111F9CFDCC080E142DD8091E800EA :10F670008B7F8DC08EB3882309F4D2C08091E800BF :10F6800080FFF8CF80910001893091F08A3059F4E1 :10F6900080919B01813039F4909194018091950182 :10F6A0009093F10002C0809199018093F1006CC0A9 :10F6B0002091940130919501C0919201D0919301D4 :10F6C0002196C21BD30B80919B01811131C0D6952D :10F6D000C795C90120919601A22FB0E02197F8F0BB :10F6E0002091F2003091F3002032310559F0FC01F5 :10F6F000259134912093F1003093F1000296A11DE1 :10F70000B11DECCF2091E8002E7F2093E8002091DE :10F71000E80020FDECCF2EB32111F9CF81C08091FC :10F72000920190919301909395018093940129C047 :10F73000823039F5209729F18091F2009091F30001 :10F74000809791F0809194019091950191D380934D :10F75000F10080919401909195010196909395010B :10F76000809394012197E6CF8091E8008E7F80936B :10F77000E8008091E80080FDE5CF8EB38111F9CFDC :10F780004FC082E0809300018091E8008E7F8093DB :10F79000E80036C08091E800877F8093E800809180 :10F7A000E80080FD04C08EB38111F9CF39C080918B :10F7B000A2018093F1001092F1001092F1001092DA :10F7C000F100809100018093F1001092F100DCCFF4 :10F7D0008091E800877F8093E8001092A20110C01A :10F7E0008091E800877F8093E8008091E80080FDA9 :10F7F00004C08EB38111F9CF13C08091000155CFA1 :10F80000DF91CF911F910F91FF90EF90DF90CF90FC :10F81000BF90AF909F908F907F906F905F901EC130 :10F82000DF91CF911F910F91FF90EF90DF90CF90DC :10F83000BF90AF909F908F907F906F905F90089552 :10F84000292F30E02230310559F02330310569F09D :10F8500021303105F9F482E190E020E831E01EC06A :10F860008BE190E025E631E019C0882349F0813032 :10F8700061F0823079F486E490E025E031E00EC05A :10F8800084E090E021E631E009C082E190E02DE4DF :10F8900031E004C080E090E020E030E0FA01318304 :10F8A00020830895611520EF72078105910510F4FA :10F8B00021E0611120E020FF14C02FB7F89407B6B3 :10F8C00000FCFDCFF999FECF33E0FB0130935700E8 :10F8D000E89507B600FCFDCF91E190935700E895BD :10F8E0002FBF0895611520EF72078105910510F46F :10F8F00021E0611120E020FF14C02FB7F89407B673 :10F9000000FCFDCFF999FECF35E0FB0130935700A5 :10F91000E89507B600FCFDCF91E190935700E8957C :10F920002FBF089507B600FCFDCFF999FECF21E067 :10F93000FB010A0120935700E8951124089521E264 :10F94000FC01209357008491089529E0FC01209345 :10F95000570084910895E1E0F0E089E0809357003A :10F96000849108959FB7F89407B600FCFDCFF999EC :10F97000FECF809529E0E1E0F0E0082E20935700CB :10F98000E8959FBF08952091AD013091AE012617F3 :10F99000370748F06115710539F42091E8002E7F92 :10F9A0002093E80001C0B901FC0120E06115710558 :10F9B00061F18EB38823D9F18530D9F18091E800C7 :10F9C00083FD39C08091E80082FD2BC08091E80062 :10F9D00080FFECCF8091F2009091F30061157105EA :10F9E00051F08032910538F421912093F10061505B :10F9F00071090196F3CF21E0809709F020E0809112 :10FA0000E8008E7F8093E800D1CF2111D2CF09C0CA :10FA10008EB3882361F0853061F08091E80083FD2A :10FA20000AC08091E80082FFF3CF80E0089582E071 :10FA3000089583E0089581E00895EBEEF0E0808181 :10FA400081608083EDEEF0E010826093EC004083F3 :10FA50008091EE00881F8827881F08958091A70154 :10FA600087FF0FC08091E80082FD04C08EB3811132 :10FA7000F9CF10C08091E8008B7F0AC08EB3882335 :10FA800049F08091E80080FFF9CF8091E8008E7FF7 :10FA90008093E800089565D06CD0E0EEF0E08081BE :10FAA00081608083E8EDF0E080818F77808319BCEE :10FAB000A7EDB0E08C918E7F8C9380818F7E8083C8 :10FAC0001092A60108950F931F93CF93DF9349D00F :10FAD00050D0C8EDD0E088818F7788838881806896 :10FAE000888388818F7D8883E7EDF0E0808180685E :10FAF000808319BC1EBA1092A50100EE10E0F80137 :10FB000080818B7F808388818160888342E260E08E :10FB100080E093DFE1EEF0E080818E7F8083E2EE93 :10FB2000F0E0808181608083808188608083F8013B :10FB300080818E7F8083888180618883DF91CF91EF :10FB40001F910F910895E8EDF0E080818F7E808312 :10FB5000E7EDF0E080818160808381E08093A60101 :10FB6000B2CFE8EDF0E080818C7F80831092E200DC :10FB700008951092DA001092E10008951F920F92FA :10FB80000FB60F9211242F933F934F935F936F9370 :10FB90007F938F939F93AF93BF93EF93FF93809146 :10FBA000DA0080FF1BC08091D80080FF17C08091D1 :10FBB000DA008E7F8093DA008091D90080FF0BC03D :10FBC00088E189BD8AE189BD09B400FEFDCF81E0ED :10FBD0008EBB45D103C019BC1EBA41D18091E10052 :10FBE00080FF17C08091E20080FF13C08091E20087 :10FBF0008E7F8093E2008091E20080618093E2003A :10FC00008091D80080628093D80019BC85E08EBBBB :10FC100026D18091E10084FF2EC08091E20084FF14 :10FC20002AC088E189BD8AE189BD09B400FEFDCF03 :10FC30008091D8008F7D8093D8008091E1008F7EE5 :10FC40008093E1008091E2008F7E8093E2008091BA :10FC5000E20081608093E2008091A501882311F089 :10FC600084E007C08091E30087FD02C081E001C00D :10FC700083E08EBBF4D08091E10083FF21C08091AE :10FC8000E20083FF1DC08091E100877F8093E10047 :10FC900082E08EBB1092A5018091E1008E7F80935F :10FCA000E1008091E2008E7F8093E2008091E2008B :10FCB00080618093E20042E260E080E0BEDECFD06F :10FCC000FF91EF91BF91AF919F918F917F916F9134 :10FCD0005F914F913F912F910F900FBE0F901F900A :10FCE00018951F93CF93DF9300D0CDB7DEB7E7EA27 :10FCF000F1E08091F100819381E0EF3AF807C9F7D4 :10FD00009CDB8091E80083FF96C08091A7019091D1 :10FD1000A8019630E1F128F4992351F09530B1F023 :10FD20008AC0983009F455C0993009F464C083C082 :10FD30008D7F803809F07FC08091E800877F8093B5 :10FD4000E8001092F1001092F1004EC0811173C0D2 :10FD50001091A9011F778091E3008078812B809317 :10FD6000E3008091E800877F8093E80077DE809150 :10FD7000E80080FFFCCF8091E30080688093E3007F :10FD8000111102C082E001C083E08EBB54C08058D4 :10FD9000823008F050C06091AB017091AC01AE01AF :10FDA0004F5F5F4F8091A9019091AA0149DDBC018D :10FDB000892B09F440C09091E800977F9093E80068 :10FDC00089819A81E0DD8091E8008B7F8093E80053 :10FDD00032C0803881F58091E800877F8093E80009 :10FDE0008091A5018093F1008091E8008E7F80933F :10FDF000E80034DE20C081111EC08091A9019091DD :10FE0000AA0199270297BCF48091E800877F80932C :10FE1000E8008091A9018093A50120DE8091A501D1 :10FE2000811106C08091E30087FD02C081E001C01E :10FE300084E08EBB14D08091E80083FF0AC08091DB :10FE4000E800877F8093E8008091EB0080628093D8 :10FE5000EB000F900F90DF91CF911F9108950895BF :10FE60008EB3882321F08091E80083FD3ACF089576 :10FE7000F999FECF92BD81BDF89A992780B5089572 :10FE8000262FF999FECF92BD81BDF89A019700B453 :10FE9000021639F01FBA20BD0FB6F894FA9AF99AF3 :08FEA0000FBE0895F894FFCF96 :10FEA800020120DCFB4603730079007300740065CF :10FEB800006D00370036002F006C00610075006E81 :10FEC80000630068005F00680065006100760079E3 :10FED800005F003100200042006F006F0074006C6A :10FEE800006F006100640065007200000012035397 :10FEF8000079007300740065006D0037003600005B :10FF0800000403090409021B0001010080320904EE :10FF1800000000FE0102000921030000000C10018E :10FF28001201100100000020EB03F92F000001026C :02FF38000001C6 :10FFA00081CCA0CCBFCCCBCCD0CCD5CCDBCC0895F5 :08FFB0000895089508950895D5 :10FFE000DFCFDFCFDFCFDFCFDFCFDFCFDFCFDFCFA1 :08FFF000DFCFDFCFDFCFDFCF51 :08FFF80000F0000010DFFBDC4B :040000030000F00009 :00000001FF ================================================ FILE: data/system76_launch_lite_1_default.hex ================================================ :100000000C941B030C9462030C9462030C94620323 :100010000C9462030C9462030C9462030C946203CC :100020000C9462030C9462030C941A280C94CE2650 :100030000C94421C0C9462030C9462030C946203B3 :100040000C9462030C9462030C9462030C9462039C :100050000C9462030C94101C0C9462030C946203C5 :100060000C9462030C9462030C9462030C9462037C :100070000C9462030C9462030C9462030C9462036C :100080000C9462030C9462030C9462030C9462035C :100090000C9462030C946203BD06C606F1062E079B :1000A0006C07AE07F107F407F707FA07FD0700082A :1000B0000308060809080C081108140817081C088A :1000C0002108240827082C086808A408A708AC08F9 :1000D000B708BA08C508C808D308D608E108E40874 :1000E000EF08F5086509AA09AA0AB00AB50A520C70 :1000F000520CBE0A520C520CC80AD90A000B1F0B34 :10010000400B720BA10BCA0BFD0BF50B480CF91839 :10011000F918331933198619291B291B291BA21910 :10012000801A911A911AFC1DFC1D0F1E0F1E051E30 :100130000F1E0F1E0F1EFC1DFC1D0A1E0F1E0F1E84 :100140000A1EE5240C25B0260C25B02658257B2553 :10015000B0266D267D2629001E001F0020002100EC :100160002200230024002500260027002D002E0059 :100170002A002B0014001A000800150017001C00AC :1001800018000C00120013002F003000310039005D :1001900004001600070009000A000B000D000E0005 :1001A0000F003300340028004A00E1001D001B004E :1001B0000600190005001100100036003700380055 :1001C000E50052004B00E000E2000151E3002C008A :1001D0004D002C00E400E6000151500051004F009A :1001E0004E0035003A003B003C003D003E003F0021 :1001F0004000410042004300440045004C004600DE :10020000010001000100010001004A004E004B0006 :100210004D000100CB5CCA5CC35C01000100010021 :100220000100010001005000510052004F00010088 :1002300001000100AE000100010001000100010009 :1002400001000100010001000100010001004B005C :10025000A90001000100010001000100A800010047 :100260000100010001004A004E004D00AA000100FB :100270000100010001000100010001000100010076 :100280000100010001000100010001000100010066 :100290000100010001000100010001000100010056 :1002A0000100010001000100010001000100010046 :1002B0000100010001000100010001000100010036 :1002C0000100010001000100010001000100010026 :1002D0000100010001000100010001000100010016 :1002E0000100010001000100010001000100010006 :1002F00001000100010001000100010001000100F6 :1003000001000100010001000100010001000100E5 :1003100001000100010001000100010001000100D5 :1003200001000100010001000100010001000100C5 :1003300001000100010001000100010001000100B5 :1003400001000100010001000100010001000100A5 :100350000100010001000100010001000100010095 :100360000100010001000100010001000100010085 :100370000100010001000100010001000100010075 :100380000100010001000001010101010101010161 :100390000202020202020202020303030303030336 :1003A0000304040404040404050505050506060603 :1003B0000606070707070708080808090909090AC0 :1003C0000A0A0B0B0B0C0C0C0D0D0D0E0E0E0F0F65 :1003D0000F101011111112121313141415151616F3 :1003E0001717181819191A1A1B1B1C1D1D1E1E1F62 :1003F0002020212222232424252626272829292AB1 :100400002B2C2D2D2E2F30313232333435363738D8 :10041000393A3B3C3D3E3F404142434445464748D4 :10042000494A4C4D4E4F50515354555658595A5BAA :100430005D5E5F616264656668696B6C6D6F70724A :10044000737577787A7B7D7E8082838587888A8CB6 :100450008E8F91939596989A9C9EA0A2A3A5A7A9EA :10046000ABADAFB1B3B5B7BABCBEC0C2C4C6C9CBE1 :10047000CDCFD1D4D6D8DBDDDFE2E4E7E9EBEEF097 :10048000F3F5F8FAFDFF05010980A10185031901C3 :100490002AB700150126B700950175108100C00527 :1004A0000C0901A101850419012AA002150126A049 :1004B00002950175108100C005010906A10185059D :1004C000050719E029E71500250195087501810246 :1004D0000507190029EF1500250195F07501810226 :1004E0000508190129059505750191029501750306 :1004F0009101C00660FF0961A1010962150026FF94 :10050000009520750881020963150026FF009520DB :1005100075089102C005010906A101050719E02926 :10052000E71500250195087501810295017508817F :10053000010507190029FF150026FF00950675081B :10054000810005081901290595057501910295019C :1005500075039101C009025B00030100A0FA0904C0 :1005600000000103010100092111010001224000E6 :100570000705810308000A090401000203000000C6 :100580000921110100012222000705820320000138 :100590000705030320000109040200010300000015 :1005A000092111010001226D000705840320000AC2 :1005B000120110010000000884330500010001024F :1005C00000015A034C00610075006E006300680072 :1005D000200043006F006E00660069006700750030 :1005E0007200610062006C00650020004B00650035 :1005F000790062006F006100720064002000280032 :100600006C00610075006E00630068005F006C00A4 :100610006900740065005F003100290000001203CA :10062000530079007300740065006D0037003600D8 :1006300000000403090411241FBECFEFD0E1DEBF88 :10064000CDBF04B603FE27C080913E0690913F06C1 :10065000A0914006B09141068730904BA740B04B27 :10066000D1F410923E0610923F061092400610926E :10067000410614BE84B7877F84BF0FB6F894A8954F :1006800080916000886180936000109260000FBECE :10069000E0E0F8E7099512E0A0E0B1E0E0EAF7E574 :1006A00002C005900D92A23FB107D9F726E0A2EF54 :1006B000B2E001C01D92AE33B207E1F70E946403BD :1006C0000C94CE2B0C940000CF93DF93CDB7DEB704 :1006D000AB970FB6F894DEBF0FBECDBF84B7877F50 :1006E00084BF0FB6F894A8958091600088618093CC :1006F0006000109260000FBE91E080E80FB6F894A1 :1007000080936100909361000FBE85B7806885BFBC :1007100085B7806885BF8FE69BE19093F302809355 :10072000F2020E9412270E94B8278091E2008460A2 :100730008093E2007894809101068823A1F01091C3 :10074000E9001F709091EC00892F817090FD80E886 :10075000182B1092E9008091E80083FD0E9401248B :100760001F701093E90082E084BD93E095BD9DE782 :1007700097BD80936E0081EF0E94101382EF0E945C :10078000101383EF0E94101384EF0E94101385EF63 :100790000E9410130EE511E03CE6C32E31E0D32E8B :1007A000D8018D918D010E941013C016D106C1F79A :1007B000E4EFF2E08EEF92E0ADE8B3E01192119237 :1007C0001D921D928E179F07C9F780E090E00E944E :1007D000EB2A8B3E9E4F11F00E94D91C10920B0603 :1007E000E4E2F6E084E396E02FEF3FEF21933193CC :1007F0008E179F07D9F710920303ECE1F3E08CE228 :1008000093E02FEF3FEF219331938E179F07D9F796 :1008100080E090E00E94EB2A8B3E9E4F21F00E94E8 :10082000D91C0E947D1145E050E06CE170E088E346 :1008300096E00E94D32A809138068C7F11F40E94A2 :100840007D110E9427138FE097E20197F1F700C016 :100850000000AFE0B7E21197F1F700C000000E947E :10086000271380918D0380FF13C06FEF7FEF80E42B :1008700090E00E941F2B6FEF82E490E00E94012B1A :100880006FEF7FEF80E090E00E941F2B0E94EC1B37 :1008900080E490E00E94EB2A8C3E964739F482E493 :1008A00090E00E94E32A91E0823009F090E090FD10 :1008B00039C000E010E058012CE8A20EB11C48013C :1008C000ECE18E0E911CF801EA5AFE4FC590D490CF :1008D0006D2DC8018D5B9F4F0E94012B6C2DC801AF :1008E0008C5B9F4F0E94012B0E5F1F4F801691065D :1008F00051F784018A149B0411F78401F0E38F16E9 :10090000F2E09F06C1F681E00E94F2156CEE76E7F8 :1009100080E490E00E941F2B62E082E490E00E945D :10092000012B03C080E00E94F21560916A0470916F :100930006B0480916C0490916D040E94C61580E058 :1009400090E00E94EB2A8B3E9E4F11F00E94D91C32 :1009500082E090E00E94E32A809382030E94C81CF8 :100960009093FF028093FE0283E090E00E94E32ACE :10097000682F70E080E090E00E94DF1E60916A04C2 :1009800070916B0480916C0490916D040E94C61567 :100990006091FE0260686093FE021091FF0284E0A5 :1009A00090E00E94012B612F81E290E00E94012BD8 :1009B0008BE191E090930103809300032224239420 :1009C000312C80910106853009F054C080E4E82E76 :1009D000DD24D39498E1F92E1AE180910106853047 :1009E00009F042C080910106843051F140E060E09E :1009F00080E00E947911D09280031092020368E196 :100A000070E00FB6F894A895609360000FBEE09276 :100A1000600083B7817F846083BF83B7816083BFB9 :100A20007894889583B78E7F83BF0FB6F894A89586 :100A300080916000886180936000109260000FBE1A :100A400080910006882309F4C8CF0E942713EDE89F :100A5000F3E081919191892B09F05BC787E993E0DD :100A60008E179F07B1F7B9CF0E940E210E94A310E5 :100A7000109280030E942713882359F08FB7F894AF :100A800040917C0350917D0360917E0370917F03C0 :100A90008FBFA3E8B3E0EDE8F3E0E12CF12C4E2D9D :100AA000A190B1908D919D918A259B25009709F485 :100AB000AEC010E0CC24C394D12C9C012C213D214C :100AC000232B09F49EC019A34AA3AC20BD2081E0CA :100AD000A114B10409F480E08BA30E94361C81604C :100AE000782F9DA38CA349A15AA16BA18DA10E942F :100AF000D90FF701EE0FFF1FED57FC4F8081918159 :100B0000C826D926D182C082AB2881F08EE08E9D86 :100B1000F0018F9DF00D1124E855FE4FE10FF11DFE :100B200080818F3F19F08BA711E001C010E0B090D9 :100B30000303E12EF12CC7018B0D911D0997A4F140 :100B400088E090E06C01CE18DF08B7016F5F7F4F3F :100B50006D5F7C4FA60184E093E00E94B62BB70145 :100B6000675F7F4F6D5F7C4FA6018CE093E00E9432 :100B7000B62BA601440F551FB701660F771F675E9E :100B80007F4F6D5F7C4F8CE193E00E94B62BB701E5 :100B90006F5E7F4F6D5F7C4FA60184E193E00E9402 :100BA000B62BBA94B09203038091030390E0EBA5B7 :100BB000AE2FB0E09D01220F331F22513E4FAA0FEE :100BC000BB1FBD0161517E4F41E0480F9117B0F44A :100BD00090E0FC01ED5FFC4FD9015C915183DB019A :100BE0005C915187BBA5B18B880F991FFC01ED5F0C :100BF000FC4F128E118E91E0842FE6CF8093030379 :100C00001EC01F5FCC0CDD1C1E3009F056CF2FEF2D :100C1000E21AF20A35E0E316F10409F040CF8FEF53 :100C20008EA38FA318A60E94361C8160782F9AA7E6 :100C300089A74EA15FA168A58AA50E94D90F4091FE :100C40002C0350912D0360912E0370912F032FB729 :100C5000F89480917C0390917D03A0917E03B091E4 :100C60007F032FBF841B950BA60BB70B2FB7F894F0 :100C7000C0907C03D0907D03E0907E03F0907F03D2 :100C80002FBFC0922C03D0922D03E0922E03F0923E :100C90002F0360910303E3E0F3E0462F50E0882444 :100CA0008A94982CA12CB12C881A990AAA0ABB0AFA :100CB000651799F0218D328D2901612C712C8414D6 :100CC0009504A604B70410F4415004C0280F391F3E :100CD000328F218F5F5F3296EBCF40930303809179 :100CE0008003811108C010913806812F837019F09C :100CF0001695169501C010E0809106018130E9F04B :100D000038F0823009F4A7C3833009F4B1C3CDC3EE :100D100010922701C0923406D0923506E092360632 :100D2000F092370689E2E3E0F3E0ABE0B6E0019051 :100D30000D928A95E1F781E098C38091050118131F :100D40000DC020913806237030E04091040150E03E :100D500081E02417350719F480E001C081E081703B :100D600080932901412F50E04832510508F061C3BA :100D7000FA01E45BFF4F0C94B02B882309F459C3AC :100D800040E060E080E00E94791153C3F0902701B9 :100D90008EE0F89EF02C11240EE00F0D073408F0C1 :100DA00006E46091390670913A0680913B060E94F4 :100DB0001812D62EC72EB82EF01608F037C3EF2D16 :100DC000F0E0DF01A658BD4F8C9190912801982347 :100DD00031F02B2D4D2D6C2DCF010E947B11F39402 :100DE000EBCFF09027018EE0F89EF02C11240EE05E :100DF0000F0D073408F006E4C0903A06D0903B0689 :100E0000B09039066B2D7C2D8D2D0E941812A62EC8 :100E1000972E882E60913C066B0D7C2D8D2D0E94A7 :100E20001812D62EC72EB82EF01608F0FFC28F2D3E :100E300090E0FC01E658FD4F3081209128012323EA :100E400059F030FF04C02B2D4D2D6C2D03C0282DE3 :100E50004A2D692D0E947B11F394E6CFD090270193 :100E60008EE0D89ED02C11240EE00D0D073408F032 :100E700006E4A0903A0690903B0620913C0630E4B0 :100E8000B32E5B2D529F512D1124B52ED01608F094 :100E9000CDC2ED2CF12CF701E658FD4F90818091E9 :100EA00028018923B9F0F701EE0FFF1FE151FE4F32 :100EB000808182958F70609139068B9D600D112421 :100EC0007A2D892D0E941812462F282F672FC701CF :100ED0000E947B11D394DACFD09027018EE0D89E68 :100EE000D02C11240EE00D0D073408F006E4A0907C :100EF0003A0690903B0620913C0680E4B82E6B2D7C :100F0000629F612D1124B62ED01608F08FC2ED2CF1 :100F1000F12CF701E658FD4F90818091280189233B :100F2000D9F0F701EE0FFF1FE251FE4F6081B69E30 :100F3000B0011124B5E075956795BA95E1F78091F8 :100F40003906680F7A2D892D0E941812462F282FF6 :100F5000672FC7010E947B11D394D6CFF090270151 :100F60008EE0F89EF02C11240EE00F0D073408F0EF :100F700006E4C0903906D0903A06B0903B066091E6 :100F80003C06669566956695809134069091350687 :100F90000E940E120E949311805887FD8195880F40 :100FA000782F2B2D729F712D1124872FB6010E944F :100FB0001812D62EC72EB82EF01608F037C2EF2D15 :100FC000F0E0DF01A658BD4F8C9190912801982345 :100FD00031F02B2D4D2D6C2DCF010E947B11F39400 :100FE000EBCF8EE79EE01AC082E59EE017C087E552 :100FF0009FE01FC088E39FE01CC08DE19FE01EC002 :1010000081E09FE01BC080E59EE008C087E49EE091 :1010100005C08EE39EE002C083E29EE00E9427228C :1010200009C284E19EE00AC085EE91E102C080EF32 :101030009EE00E94CB21FEC18CED9EE00E944F21DC :10104000F9C186EE9DE005C084EB9DE002C086E715 :101050009DE00E947122EEC181111EC060913C068C :1010600020E1620F08F46FEF80913406909135060D :101070000E940E126AE070E00E94882B892B09F012 :10108000D8C10E94C32A66E470E00E949C2B609144 :1010900028010E94A812CDC1809127019EE0899F5E :1010A000802D11240EE0080F073408F006E4E82E26 :1010B000F12CC02ED12CEC14FD040CF0B7C16091C2 :1010C0002801C7010E94A8123FEFE31AF30AF3CFE9 :1010D00081111EC060913C0620E1620F08F46FEFA1 :1010E00080913406909135060E940E1265E070E002 :1010F0000E94882B892B09F09CC10E94C32A66E4B8 :1011000070E00E949C2B609128010E94EE1291C118 :10111000809127019EE0899F802D11240EE0080F09 :10112000073408F006E4E82EF12CC02ED12CEC1484 :10113000FD040CF07BC160912801C7010E94EE12F2 :101140005FEFE51AF50AF3CF8FE69DE002C089E66E :101150009DE00E94D2226EC180910B0621E0682F93 :10116000621B08F460E0862F60E57DE03BC060E52F :101170007DE037C080910B0621E0782F721B08F4C8 :1011800070E0872F68E17DE02DC068E17DE029C037 :1011900080910B0621E0382F321B08F430E0832FBA :1011A00066EE7CE01FC066EE7CE01BC080910B0603 :1011B00021E0582F521B08F450E0852F6EEC7CE0A4 :1011C00011C06EEC7CE00DC080910B0621E0682F11 :1011D000621B08F460E0862F68EB7CE003C068EBDC :1011E0007CE080E00E943E2325C18091760381113E :1011F00025C068EA71E040E050E0942F9295907F1E :1012000020E030E0FB01E20FF31F8081863438F4E8 :10121000E82FF0E0E05DFC4F892F822B80832F5F69 :101220003F4F2E30310571F74F5F5F4F625F7F4F49 :101230004530510511F781E080937603D090270166 :101240008EE0D89ED02C11240EE00D0D073408F04E :1012500006E460916A0470916B0480916C04909133 :101260006D040E947615B82E6091390670913A0689 :1012700080913B060E941812A62E972E882ED0161B :1012800008F0D4C0ED2CF12CF701E658FD4F908109 :10129000809128018923B9F0F701E05DFC4F60815E :1012A000462F4F7062956F708B2D0E9445110297EB :1012B00020F420E040E060E003C0282D4A2D692D95 :1012C000C7010E947B11D394DACF909027018EE062 :1012D000989E902C11240EE0090D073408F006E4C6 :1012E000EE24EA94F12C901608F0A0C0E92DF0E06D :1012F000DF01A658BD4F9C9180912801892341F1BF :10130000DF01AA0FBB1FAE0FBF1FA856BC4FAC908A :101310001196CC90119712968C9190913B06A99EB4 :1013200050011124C99E60011124899FC00111241C :10133000B7010E94882B262FC501B7010E94882B78 :10134000462FC601B7010E94882BCF010E947B1156 :101350009394C9CFC09027019EE0C99EC02C112450 :101360000EE00C0D073408F006E4811106C08091F0 :101370007B038F5F80937B0304C010927B031092EA :101380007A0380917B03811147C080917A03883072 :1013900029F41092790310927A033EC0A82FB0E08E :1013A000AA0FBB1FA459BE4FEC9111969C917EE0F1 :1013B000E79FF0011124E855FE4FE90FF11D9081E0 :1013C0009F3F21F09093770391E001C090E09093CC :1013D00079038F5F80937A031FC0EC2CF12CF70107 :1013E000E658FD4F9081809128018923A1F06091FA :1013F0007B036C0D20917903E7E7F3E080E77FEF53 :1014000090E092130CC00E941812462F282F672FCD :10141000C7010E947B11C394C016F8F207C0319136 :10142000C31202C08FEF70E09F5FEBCF81E0063404 :1014300008F080E0909127019F5F90932701811130 :1014400034C082E0809306018091290181112DC072 :10145000112351F02AC01093050180913806837042 :10146000809304010E94B80F83E0809306011DC0A1 :1014700040913406509135066091360670913706DA :101480002FB7F89480917C0390917D03A0917E0307 :10149000B0917F032FBF841B950BA60BB70B409712 :1014A000A105B10510F0109206010E94A3109091C1 :1014B0008103891721F00E94A310809381038091FA :1014C0000106843009F07DCA83E08093E9008091B1 :1014D000E80082FF76CA8091E80085FF23C00E9461 :1014E000312781111DC050E2E52EF12CCE0101966D :1014F0006C0109C08091F100D6018D936D01B1E0BE :10150000EB1AF10869F08091E80085FDF3CF809136 :10151000E8008B778093E8000E943127882399F3B5 :1015200091E001C090E08091E8008B778093E80023 :10153000992309F446CA81E08A83E9818E2F90E0DD :10154000FC013197E331F10508F0ACC1EC58FF4FD5 :101550000C94B02B86E78B838CEE8C8381E014C1D6 :101560004EE150E06DE271E004C04EE150E064E411 :1015700071E0CE0103960E94BF2B93C180916F044E :10158000882309F48FC11A8281E080936E048AC196 :101590008B81843008F086C16C81653008F082C18F :1015A0004D814E3008F07EC10E9445118E839F838D :1015B00078C12B81243008F075C18C81853008F00A :1015C00071C19D819E3008F06DC11E816F81ECE17B :1015D0008E9F70011124FCE82F9FE00CF11C112458 :1015E000E90EF11CE90EF11C23E4E20EF11CC70127 :1015F0000E94012B612FC70101960E94012B51C14E :1016000080916F0481114EC18B81803F49F0813FF1 :1016100049F0823F49F0833F09F044C1E3E005C04F :10162000E0E003C0E1E001C0E2E035E0E39FF0016B :101630001124E95FFE4F83818C8380EBA5C08091EC :101640006F0481112FC18B819C81903B08F090EB3E :10165000803F49F0813F49F0823F49F0833F09F0E4 :1016600021C1E3E005C0E0E003C0E1E001C0E2E049 :1016700055E0E59FF0011124E95FFE4F9383A9C077 :1016800080916F0481110EC1EB81E63458F0E03F88 :10169000C1F0E13FC1F0E23FC1F0E33F09F002C118 :1016A000E3E014C0F0E0CF01880F991FE80FF91FA5 :1016B000E856FC4F81818C8380818D8382818E836B :1016C000F0C0E0E003C0E1E001C0E2E065E0E69FD9 :1016D000F0011124E95FFE4F81818C8382818D832B :1016E0001E82DFC080916F048111DCC0EB818D818F :1016F0009C81E63458F0E03FB1F0E13FB1F0E23FC9 :10170000B1F0E33F09F0CEC0E3E012C02E81F0E07B :10171000AF01440F551FE40FF51FE856FC4F8083BF :1017200091832283BEC0E0E003C0E1E001C0E2E0BB :1017300075E0E79FF0011124E95FFE4F91838283FA :1017400048C080916F048111ADC0EB81E43008F096 :10175000A9C02E2F30E085E0E89FF0011124E95F59 :10176000FE4F908196959695ECE7F1E080E04191EF :1017700094130CC08C8385E0829FF001839FF00D51 :101780001124E95FFE4F84818D838BC08F5F8F3082 :1017900071F788C080916F04811184C0EB81E430BF :1017A00008F080C0AC81AF3008F07CC02D8195E09E :1017B000E99FF0011124E95FFE4FB0E0A458BE4F4D :1017C0008C91982F990F990F80818370892B80833A :1017D00024831A8260916A0470916B0480916C0476 :1017E00090916D040E94C6155DC080916F048111B7 :1017F00059C081E00E94F21554C085E08B838EE0D1 :101800008C838DE8E82E83E0F82E15E0A0E0B4E0AC :1018100040E050E0B03258F5F70160817181C101BC :10182000042E02C0880F991F0A94E2F768237923D7 :101830008B2F90E091010A2E01C0220F0A94EAF743 :10184000672B51F061E070E06C0F7D1F860F971FD2 :10185000FC013081232B0AC061E070E06C0F7D1F1A :10186000860F971F2095FC01308123232083AF5FD3 :10187000A83010F0BF5FA0E04F5F5F4F4E305105C2 :1018800049F61150F2E0EF0EF11C1111C1CF09C061 :101890000E940E2181E09B81911101C080E0809324 :1018A00097031A8280910106843009F51091E900AE :1018B0001F709091EC00892F817090FD80E8182BAB :1018C00082E08093E9008091E80080FF0DC040E055 :1018D00050E060E270E0CE0101960E9423218091E9 :1018E000E8008E778093E8001F701093E9008091E4 :1018F0006E04882309F465C82FEF30E752E02150C9 :1019000030405040E1F700C000000E94EC1B0C94F6 :10191000E104F9BC19BD09B400FEFDCF8091D800E7 :101920008F7D8093D8008091E00082608093E000FA :101930008091E00081FDFCCF0E940E210C94ED040B :10194000E3E7F4E095E0E534F90729F0818360836B :1019500042833396F7CF0895FC01EE0FFF1F8E0FE1 :101960009F1FFC01ED58FB4F618340832283089544 :10197000EF92FF920F939701201B31092F3F310502 :1019800019F010F02FEF30E02095382F320F08F4C7 :101990003FEF832F0F91FF90EF900895EF92FF920A :1019A0000F939701201B31092F3F310519F010F0DB :1019B0002FEF30E0322F3095482F430F08F44FEFD0 :1019C000842F620F0F91FF90EF900895EF92FF9296 :1019D0000F93972F093438F4B701601B71096F3FDB :1019E000710519F010F06FEF70E0485F5F4F413103 :1019F000510540F0A901485F5F4F4131510510F09A :101A00006FEF70E06095482F460F08F44FEF842F7A :101A100037FF02C02D5F3F4F3595279535952795A8 :101A200060913906620F792F0F91FF90EF90089522 :101A3000EF92FF920F93E00EF11CF90137FF03C004 :101A4000F195E195F10924E0EE0FFF1F2A95E1F7EA :101A5000EF3FF10519F014F0EFEFF0E09A0157FFB6 :101A600003C031952195310994E0220F331F9A95D7 :101A7000E1F72E173F070CF4F901EE0DFF1DEF3FC4 :101A8000F10519F010F0EFEFF0E02E2F2095382F30 :101A9000320F08F43FEF832F0F91FF90EF900895DE :101AA000EF92FF920F93970195E0099F200D311D52 :101AB00011242F3F310519F010F02FEF30E0209561 :101AC000382F320F08F43FEF832F0F91FF90EF90E4 :101AD000089522E8241B08F420E0620F0895409541 :101AE000282F429F412D1124842F08950F931F9377 :101AF00010E0F801EE0FFF1FE251FE4F908190576A :101B000097FD9195000F111FF801E151FE4FE08103 :101B1000F0E0B097DF01AA0FBB1F8D010E0F1F1F52 :101B20002003D001219FB00D1124E8E3F0E0E91B70 :101B3000F10997FDF3959F01220F331F89010E0FC5 :101B40001F1F40039001419F300D11242A0F3B1F9E :101B500037FF02C021583F4F220F232F221F330B84 :101B6000620F1F910F9108950F931F93522F10E052 :101B7000F801EE0FFF1FE151FE4FE081F0E0B0975A :101B8000EE0FFF1F9F015203D001539FB00D112490 :101B9000000F111FF801E251FE4F008110E00057C5 :101BA0001109000F111F40039001419F300D1124B6 :101BB0002A0F3B1F37FF02C021583F4F220F232F10 :101BC000221F330B620F1F910F9108950F931F93E4 :101BD000522F10E0F801EE0FFF1FE151FE4FE081A0 :101BE000F0E0B0979F015203D001539FB00D112434 :101BF000000F111FF801E251FE4F008110E0005765 :101C0000110940039001419F300D11242A0F3B1F01 :101C100037FF02C021583F4F220F232F221F330BC3 :101C2000620F1F910F910895EF920F931F9393E00E :101C3000099F80011124159507956E2D600F1F9146 :101C40000F91EF900895A22F50E0FA01EE0FFF1FC1 :101C5000E151FE4F9081905297FD9195440F551F91 :101C6000FA01E251FE4F3081232F30E02A1B310967 :101C7000290F311D97FD3A95620F0895E42FF0E08A :101C8000EE0FFF1FE151FE4F6081621B0895E42FAC :101C9000F0E0EE0FFF1FE251FE4F6081621B0895DE :101CA000622F0895E42FF0E0EE0FFF1FE251FE4F88 :101CB000408134EE439F412D1124E82FF0E050E0A5 :101CC000445E5F4FDA01A21BB1099D01B7FF03C05B :101CD00031952195310993E0220F331F9A95E1F751 :101CE000AF01421B530B9A0157FF02C020E030E0C6 :101CF000582F259F212D1124822F0895E42FF0E0E5 :101D0000EE0FFF1FE251FE4F408134EE439F412D05 :101D10001124E72FF0E050E0445E5F4FDA01A21B90 :101D2000B1099D01B7FF03C031952195310993E0B9 :101D3000220F331F9A95E1F7AF01421B530B9A0113 :101D400057FF02C020E030E0279F212D1124722F81 :101D50000895FC019B01009721F477FF2BC080E8D8 :101D60000895AC0197FF04C044275527481B590B21 :101D7000B901640F751F37FD0CC0241B350BC90159 :101D8000A5E0880F991FAA95E1F70E949C2B80E29D :101D90000CC0CB0165E0880F991F6A95E1F7BA0185 :101DA000621B730B0E949C2B80E6861BF7FF03C00F :101DB0008195089580E00895EF920F93CF93DF937C :101DC000D72FC82FC9010E19BA010E94A90E602F82 :101DD000681B7D2F8C2FDF91CF910F91EF9008958D :101DE0000F93CF93DF93D72FC82FC901BA010E9459 :101DF000A90E682F600F7D2F8C2FDF91CF910F914F :101E00000895EF920F931F93CF93DF93D62FC72F91 :101E1000182FC9010E19010FBA010E94A90E081B43 :101E2000202F219F212D1124822F6D2F7C2FDF91B8 :101E3000CF911F910F91EF900895EF920F931F9301 :101E4000CF93DF93D62F172FC82FC9010E19070F75 :101E5000BA010E94A90E702F781B719F712D112459 :101E60006D2F8C2FDF91CF911F910F91EF900895DF :101E7000FF920F931F93CF93DF93F62ED72F182F38 :101E8000C901C12FC01BBA010E94A90E982F990F3A :101E9000890FC81B2C2F219F212D1124822F6F2DDC :101EA0007D2FDF91CF911F910F91FF900895FF92A9 :101EB0000F931F93CF93DF93F62E172FD82FC901BF :101EC000C72FC01BBA010E94A90E982F990F890F26 :101ED0007C2F781B719F712D11246F2D8D2FDF9119 :101EE000CF911F910F91FF9008959091FE0292FF64 :101EF0000DC0282F2871283019F4877F846006C010 :101F0000282F2471243011F48B7F886093FF0DC03B :101F1000282F2871283119F4877E846106C0282F64 :101F20002471243111F48B7E88612091FF0220FFFF :101F30000DC0382F3871383019F4877F816006C0A2 :101F4000382F3171313011F48E7F886021FF0DC040 :101F5000282F2871283119F4877E816106C0282F27 :101F60002171213111F48E7E886194FD877E089560 :101F7000879A81B38F7791B390682FB7F894E3E78E :101F8000F4E035E0E534F30761F0319148E091BBCE :101F900037FF81BB330F000000C081BB4A95B9F702 :101FA000F0CF2FBF8FE292E00197F1F700C0000061 :101FB00008951F93CF93DF93CDB7DEB767970FB622 :101FC000F894DEBF0FBECDBF342F4B8B252F5C8B1B :101FD0006D8B7E8B8F8B4E895F8961111092D60538 :101FE00086E0FE013D96DF01982F1D929A95E9F754 :101FF0003D872E876F87598B488BDE01179601909E :102000000D928A95E1F7CE0107960E945F1F81111C :102010003EC086E0FE013796DE01119601900D92DA :102020008A95E1F7FF81E8856A857B8561157105F1 :1020300031F0EF3F31F481E0FF3F19F403C081E05C :1020400001C080E080FD23C02091750530E0C9010A :102050000196877099274091A60550E0841795074F :1020600079F1F983EA837D836C8396E0929FD001B6 :10207000939FB00D1124AA58BA4FFE0131960190DA :102080000D929A95E1F7809375050E94E91E16E07E :102090008091A605909175058917F9F0189FC001E8 :1020A00011248A589A4F0E945F1F8823B1F08091B3 :1020B000A60590E00196877099278093A605E8CF42 :1020C0000E940E21109275051092A605EFE6F5E02C :1020D00086E0DF011D928A95E9F767960FB6F894BE :1020E000DEBF0FBECDBFDF91CF911F91089520912C :1020F000490530914A052817390771F090934A0530 :1021000080934905E0910003F0910103309721F09D :102110000084F185E02D09940895209147053091C0 :1021200048052817390771F09093480580934705B3 :10213000E0910003F0910103309721F00680F781D0 :10214000E02D09940895E0910003F0910103309788 :1021500021F00190F081E02D099480E00895EF9244 :10216000FF920F93CF93DF93C42FD22FFC01828174 :102170008823D1F040934D050E94361C909346056C :102180008093450580E28C0F883008F078C0C770D6 :1021900081E001C0880FCA95EAF7DF91CF910F91D6 :1021A000FF90EF900C94562980914D05481356C02E :1021B00020914505309146054FB7F89480917C03F6 :1021C00090917D03A0917E03B0917F034FBF821B4E :1021D000930B883C910508F041C0CD17C9F080E20F :1021E0008C0F883040F4C77081E001C0880FCA9519 :1021F000EAF70E944B2980E28D0F883048F481E095 :102200009D2F977001C0880F9A95EAF70E94562972 :10221000093319F0E12CF12C03C080E5E82EF12CF4 :10222000802F0E94BC29E114F10451F08FEC97E05B :102230000197F1F700C0000091E0E91AF108F3CF2F :10224000802F0E94602980E28D0F8830C0F4D77003 :1022500081E001C0880FDA95EAF70AC080E28C0FAE :10226000883068F4C77081E001C0880FCA95EAF72A :10227000DF91CF910F91FF90EF900C944B29DF915C :10228000CF910F91FF90EF9008950F931F93CF93ED :10229000DF93C42FD0E0CC0FDD1F2CE1629FC00D77 :1022A000D11D11243CE8839FC00DD11D1124CD5BAD :1022B000DF4FCE010E94E32A082F10E0102F0027E5 :1022C000CE0101960E94E32A9801282BC901DF91D3 :1022D000CF911F910F910895462F843038F47530B7 :1022E00028F46E3018F4672F0C94451180E090E0CC :1022F00008950C94A00C0C94AC0CE8E3F6E08DE38C :10230000808380912A0190912B01A0912C018183DF :102310009283A3838FE7848345E050E06CE170E013 :10232000CF010C94F12A482F982F46FD9095E92F64 :10233000EF739F7046FD9F5FE295EF70EE0FF0E048 :10234000E557FE4F2181299F802D212D1124829553 :102350008F702295207F822B3081982F930F892FA9 :1023600047FD819580580895BC018230910508F49D :102370000895613E8EE1780748F49B0195E036951B :1023800027959A95E1F748E0420F01C04FEF91E0A1 :10239000242F30E0290F311D35952795229FF0011C :1023A000239FF00DF00D11246E177F0718F44FEFE7 :1023B000420F04C02F3F39F091E0920F491740F7C8 :1023C0008FEF890F08958FEF08950F93CF93DF93C9 :1023D000D72FC82F47FD4195E8E3F0E0CF01841BDC :1023E000910947FD9395889FB001899F700D700DED :1023F0001124229FC001239F900D900D1124860F60 :10240000971F0E94B411682F660F860F682F600F08 :102410007D2F8C2FDF91CF910F91089520E030E038 :10242000869F212D969F200D311D1124C9010895ED :10243000CF92DF92EF92FF920F931F93CF93DF9390 :10244000F62E472FE82FF0E0711106C0EA57FC4F37 :102450008491782F682F73C0272F30E0EA57FC4F04 :10246000E491FE2F0E2F10E056E0659FC00111246D :10247000CFEFD0E0BE010E94882B5BEA5603C0017B :10248000579F900D11248F0D911D8F0D911D982F29 :10249000990F980F7E01E21AF30AE09ED001E19EA7 :1024A000B00DF09EB00D11248B2F499FA001112477 :1024B000452F55277E01E41AF50AE09EA001E19E12 :1024C000500DF09E500D11246E01C91AD108C29E04 :1024D0007001C39EF00CD29EF00C11242F2D3327D7 :1024E000C21BD30BC09F9001C19F300DD09F300DF8 :1024F0001124932F6230710591F048F46115710534 :10250000E1F061307105B9F49E2FE52F16C06430FB :10251000710569F040F06630710579F00CC09E2FAE :10252000EB2F832F0AC0EB2F8F2F952F06C09B2FE9 :102530008E2FE32F02C09B2F852F7E2F692FDF91D7 :10254000CF911F910F91FF90EF90DF90CF90089562 :10255000DF92EF92FF920F931F93CF93DF93EC01E3 :10256000FC01E658FD4F9081692381F1D0903A0635 :1025700000913B0610913906E12EF12C0E94C32AEE :10258000282FC7018C549F4F68E671E00E949C2B56 :102590008E199F0997FD0396959587959595879533 :1025A0002370612F289F600D11247D2D802F0E94A4 :1025B0001812462F282F672FCE01DF91CF911F9140 :1025C0000F91FF90EF90DF900C947B11DF91CF91F2 :1025D0001F910F91FF90EF90DF9008951F93CF937D :1025E000DF93FC01E658FD4F20816223A9F0EC0146 :1025F0000E94C32A182F0E94C32A612F782F80912E :102600003B060E941812462F282F672FCE01DF911C :10261000CF911F910C947B11DF91CF911F91089561 :10262000F894E82FE295EF70F0E031A1282F2F7099 :1026300081E090E001C0880F2A95EAF7982F9095E5 :10264000932391A392A1892B82A3789408959F92BA :10265000AF92BF92CF92DF92EF92FF920F931F93B0 :10266000CF93DF9304EF12E089E5E82E81E0F82EA6 :10267000C0E0D0E0912CCC24C394D12CB701D70179 :102680008C91F894E82FE295EF70F0E021A18F7023 :10269000A60102C0440F551F8A95E2F7CA01922F86 :1026A000982B91A392A18095892382A3789400C04E :1026B000EEE5F1E020E030E0A12CB12C4191842F37 :1026C00082958F7090E0DC0190968C9190E04F7035 :1026D00002C0959587954A95E2F780FD08C0C6012E :1026E000022E02C0880F991F0A94E2F702C080E010 :1026F00090E0A82AB92A2F5F3F4F2E303105F1F61E :10270000BFEFEB1AFB0AFB0180810E941013C4305B :10271000D10519F0F0E5FA95F1F7D8018D919C916A :102720001197A816B90621F0AD92BC9281E001C0C4 :1027300080E0982A21960E5F1F4FC530D10509F021 :102740009DCF992049F081E0809372040E94361C4D :102750009093710480937004809172048823E9F14E :1027600020917004309171044FB7F89480917C03EC :1027700090917D03A0917E03B0917F034FBF821B98 :10278000930B069750F18091F4029091F50290938B :102790008E0380938D038091F6029091F7029093BF :1027A000900380938F038091F8029091F9029093A7 :1027B0009203809391038091FA029091FB0290938F :1027C0009403809393038091FC029091FD02909377 :1027D00096038093950310927204892DDF91CF9117 :1027E0001F910F91FF90EF90DF90CF90BF90AF902F :1027F0009F900895CF93DF930E946C11EC01823873 :10280000910559F1A0F48133910509F473C040F4A6 :102810008932910509F467C08A9709F472C084C0AF :102820008533910509F458C0C997B9F07DC0833E3E :10283000910571F138F4803E9105B1F0823E910529 :1028400011F172C0863E9105B9F1873E9105C9F13B :10285000843E910509F068C024C08091FE0280FD8D :102860005DC081FD5BC060C08091FE0280FD50C0F4 :102870008091FF0280FF36C18091FE0284FD30C14D :10288000C3EED0E02FC18091FE0282FF2BC1F4CFB6 :102890008091FE0282FD3FC08091FF0280FD3EC01C :1028A000EBCF8091FF0281FF1DC18091FE0284FD6C :1028B00017C1C7EED0E016C18091FE0283FF12C19E :1028C000F4CF8091FE0283FD2CC08091FF0281FF36 :1028D000ECCFC4EED0E006C18091FE0285FF02C1BC :1028E000C9E2D0E0FFC08091FE0285FFFBC0C5E3D6 :1028F000D0E0F8C08091FE0286FFF4C0CAE2D0E0CA :10290000F1C08091FE0286FFEDC0C1E3D0E0EAC0D5 :10291000C9E3D0E0E7C0C2EED0E0E4C0C0EED0E052 :10292000E1C0C6EED0E0DEC0C11582E5D80708F0F0 :1029300066C0C11591E5D90728F0DC2FCC27C16FFF :10294000D06AD0C0C83ED10560F5C03ED10508F0C0 :10295000C9C0C83AD105B0F4C53AD10540F0C55A4E :10296000D0E0C054DD4FC881D0E0D064BBC0C130DE :10297000D10509F4B7C008F4B3C0C430D10508F4D8 :10298000AFC0B0C0CF3BD10508F0AAC0C85AD0E054 :10299000CC0FDD1FCD53DD4F0990D881C02DD464FD :1029A000A1C0C11520E5D207E0F0CE0174E09695F4 :1029B00087957A95E1F783709C2F937021E030E042 :1029C00002C0220F331F9A95E2F73C68382BCF7074 :1029D000C695C69580E2C89FE0011124C22BD32B77 :1029E00081C0C11580E4D80718F0DF70D06A7AC0C2 :1029F000CE019A9581159F4108F474C071C0C1152C :102A000086E5D807F0F5C11595E5D90750F08C2F6C :102A10000E94750F8F71C82FD0E0DC2FCC27D062B9 :102A200061C0C11524E5D20728F0DC2FCC27C46F84 :102A3000D06A58C09E01237033278C2F86958695C7 :102A4000C115D34578F4C1E0D0E002C0CC0FDD1F42 :102A50002A95E2F720E2829FC0011124C82BD92BCE :102A6000DC6840C0C1E0D0E002C0CC0FDD1F2A9579 :102A7000E2F720E2829FC0011124C82BD92BDA682B :102A800031C0C1152AE5D207E8F4C11589E5D80798 :102A900080F08C2F8F700E94750F94E0D695C795AB :102AA0009A95E1F7CF70D0E0DC2FCC27D069C82B06 :102AB00019C0C11598E5D90798F0DC2FCC27C06F55 :102AC000D06A10C0CE0190568115904248F48D2FE7 :102AD0008F710E94750FDD27D0628F71D82B02C0D5 :102AE000C0E0D0E0CE01DF91CF910895CF92DF9288 :102AF000EF92FF926C01EE24FF24C114D104E10493 :102B0000F10421F0C701B60120E101C020E0C72E89 :102B1000D82EE92EFF24C114D104E104F10419F0E8 :102B2000285FC701B6016B017C0154E0F694E7947D :102B3000D794C7945A95D1F7C114D104E104F10494 :102B400019F02C5FC701B6016B017C0142E0F694DD :102B5000E794D794C7944A95D1F7C114D104E104FE :102B6000F10419F02E5FC701B601DC01CB01B69567 :102B7000A79597958795892B8A2B8B2B09F02F5F2B :102B8000822FFF90EF90DF90CF90089520916F04F7 :102B9000211110C00E947615843060F495E0989F52 :102BA000F0011124E95FFE4FA8E3B6E001900D9219 :102BB0009A95E1F7089590916F04911112C0809356 :102BC0000A0180930F018093140180931901609191 :102BD0006A0470916B0480916C0490916D040C9464 :102BE000C615089544E150E063E772E0882361F080 :102BF00087E091E00E94F12A42ED50E067E872E040 :102C000088E993E00C94F12A87E091E00E94D32AAE :102C100042ED50E067E872E088E993E00C94D32A33 :102C200080913806837029F08C6980933806109261 :102C3000060181E080936F0408958F929F92AF9276 :102C4000BF92CF92DF92EF92FF920F931F93CF9399 :102C5000DF9300D000D01F92CDB7DEB7FC0180819A :102C6000918123813481232B31F09F3F31F491E016 :102C70008F3F19F403C091E001C090E090FD19C5A9 :102C80007F0185E0DE01119601900D928A95E1F7B2 :102C9000F701228189819A81222349F00E949D1D9A :102CA000182F682F89819A810E943F1E03C00E94BD :102CB000131E182F69817A81812F0E946C118C015B :102CC00080919703811132C20115FCE51F0731F194 :102CD00068F4003E110509F45FC0043E110509F4D3 :102CE00060C00932110509F08EC10EC00A3C3CE5F6 :102CF000130769F10B3C8CE51807C1F0033C9CE518 :102D0000190709F080C136C080914C05882309F469 :102D10004CC080914B05882309F447C0F70182819C :102D2000882309F403C20E94101600C2F7018281B1 :102D3000882309F4FBC180913B06E9E9F1E0929117 :102D40009817B0F001E0E339F007C9F722C0F701A6 :102D50008281882309F4EAC180913B06E3E9F1E02E :102D600029E931E02E173F07A1F091918917D0F79B :102D7000892F0FC0F7018281882309F4D7C1809180 :102D80003B06811103C08091250103C0809325017A :102D900080E00E94DB15CAC1F701828180934C0557 :102DA00004C0F701828180934B05F701828188235B :102DB00009F48EC110924D050230FCE51F0708F49E :102DC00071C106312CE5120738F098012B5F3C45A4 :102DD0002930310508F066C10E94C81C9093FF029B :102DE0008093FE0200313CE5130709F4C3C008F0EC :102DF00041C008309CE5190709F49AC0F0F404308A :102E0000FCE51F0709F487C068F402303CE51307AE :102E100009F477C003301C4509F0E5C08091FE023B :102E2000826076C006309CE5190709F46EC008F090 :102E30007BC08091FE0288606BC00C30FCE51F07F0 :102E400009F485C068F40A303CE5130709F474C03E :102E500008F079C00E940E218091FE02806858C05F :102E60000E309CE5190709F476C008F07FC0809108 :102E7000FE028BC00C3FFCE51F0709F44FC018F59C :102E800003313CE5130709F47DC078F401319CE57A :102E9000190709F473C002311C4509F0A4C00E944F :102EA0000E218091FE028F7733C00531FCE51F07AC :102EB00009F472C008F486C00B3F1C4509F093C0AA :102EC0008091FF023EC001158DE5180709F45FC02F :102ED00058F40E3FECE51E0709F444C008F43FC067 :102EE0008091FF0282602DC002302DE5120709F4A7 :102EF00075C008F45DC003301D4509F074C060E082 :102F00006EC08091FE02816003C08091FE028061EC :102F10008093FE0268C08091FE0211C08091FF0282 :102F200082608093FF025FC08091FE028062F0CFDA :102F30008091FE028064ECCF8091FE028860846004 :102F4000E7CF8160EECF8091FE028E7FE1CF80914E :102F5000FE028D7FDDCF8091FE02877FD9CF8091E9 :102F6000FF0218C08091FF028D7FDBCF8091FE02AF :102F70008F7ECECF8091FE028F7DCACF8091FE02E0 :102F80008F7BC6CF8091FE02877F8B7FC1CF8091E0 :102F9000FF028D7F8E7FC5CF8091FE0282FB2227AC :102FA00020F991E0922790FB82F990FB83F9B0CF52 :102FB0008091FF02982F909591708E7F892B90FBC6 :102FC00081F9AFCF0E940E218091FE0287FB22275C :102FD00020F991E0922790FB87F99ACF61E08EE08B :102FE00090E00E94012B6091FE021091FF0284E0AC :102FF00090E00E94012B612F81E290E00E94012B62 :103000000E940E2193C0043FFCE51F07A1F406E2D5 :1030100021EE40EE64EF7CE50AC0083D9CE519070F :1030200009F0C3CE06E221EE41EE68ED7CE5C70172 :103030000E94AF107BC0053F2CE51207A0F4093DAC :103040003CE5130731F407E225EE45EE69ED7CE53A :10305000EECF0A3D8CE5180701F708E221E045EEC6 :103060006AED7CE5E4CF063FECE51E0731F406E2AD :1030700021EE42EE66EF7CE5DACF063FFCE51F0766 :1030800030F407E225EE44EE65EF7CE5D0CF073F54 :103090002CE5120709F089CE07E225EE46EE67EF30 :1030A0007CE5C5CF06313CE5130719F58091D705BE :1030B0008A7A91E009F490E090934E05882311F00C :1030C00065E301C069E28FE495E00E94931C0EC0A5 :1030D00006311C4509F048C080914E05882309F44B :1030E000E6C265E38FE495E00E946B1C0E94491DD7 :1030F0001DC09801235C3C4524313105B8F0011511 :103100009CE5190731F00F3D1C4571F50E94D91C53 :103110000DC00E940E21FFE70AE116E0F1500040C9 :103120001040E1F700C000000E94EC1B8091D40524 :10313000877009F4BEC2F7018281882309F4B9C2FD :1031400082E00F900F900F900F900F90DF91CF9132 :103150001F910F91FF90EF90DF90CF90BF90AF90B5 :103160009F908F900C94A51EF701008111818823F8 :1031700049F0C8010E949D1DD82E682FC8010E94E9 :103180003F1E04C0C8010E94131ED82EB8018D2D09 :103190000E94FA138C01982EF701B280A580A294A8 :1031A0009FE0A9228091D405877099F0BB2089F017 :1031B000812F807F803421F080E2800F883048F0BA :1031C00082E00E94A51E8091D4058770DD24D394EF :1031D0008111D12CC12EC2948FE0C8228C2D90E099 :1031E0008C30910508F035C2FC01E957FF4F0C9473 :1031F000B02B812F807F1F70882311F01295107FD4 :10320000BB20B9F0112309F40FC280E2800F88308F :1032100010F0911006C08091D705182B1093D70598 :1032200005C08091D605182B1093D6050E94491D24 :10323000FBC1802F0E946029112309F40AC2005E9D :103240001095083010F0911006C08091D705182312 :103250001093D70505C08091D60518231093D60585 :103260000E94491DF6C1812F807F1F70803211F0AE :103270001295107F992021F0F1E09F16E1F02AC00D :10328000BB2081F08091D805AA2051F001E0A01266 :1032900007C0182B181709F4DCC11093D805D9C141 :1032A000812B10C0AA2021F021E0A21609F4D1C17F :1032B0000E94431D27C0BB2041F035E03A1508F4B9 :1032C000C8C1812F0E945629C4C184E08A1508F420 :1032D000C0C118C0BB2049F0AA2099F3F70185812D :1032E00080FFA2C18F708583ECCFAA2059F00933EB :1032F00009F0ACC1FFEF13EF21E0F1501040204086 :10330000E1F7A2C1812F0E944B29A3C1812F86958D :103310008695837019F0813059F09BC1BB2019F05C :10332000C801937002C080E090E00E948D1097C1A8 :10333000BB2019F0C801937002C080E090E00E94A9 :1033400077108DC1812F837009F069C0B11085C1DC :10335000902F929596959770990F990F802F8F7057 :10336000882E912CA12CB12C092E04C0880C991CFC :10337000AA1CBB1C0A94D2F704FF12C04FE050E015 :1033800060E070E004C0440F551F661F771F9A95D8 :10339000D2F7DB01CA0180959095A095B09503C046 :1033A00080E090E0DC0116951695412F4370423085 :1033B00019F1C8F40091D9051091DA052091DB05C7 :1033C0003091DC05413059F088299929AA29BB2977 :1033D000BC01CD0160237123822393230AC0802A7C :1033E000912AA22AB32ABC01CD01682979298A2908 :1033F0009B290E94DF1E31C188299929AA29BB294E :103400000091D9051091DA052091DB053091DC059A :10341000BC01CD016027712782279327EACFBB200B :1034200019F0812F817001C08695882309F415C198 :10343000902F929596959770990F990F802F8F7076 :10344000882E912CA12CB12C092E04C0880C991C1B :10345000AA1CBB1C0A94D2F704FF12C04FE050E034 :1034600060E070E004C0440F551F661F771F9A95F7 :10347000D2F7DB01CA0180959095A095B09503C065 :1034800080E090E0DC0116951695412F43704230A4 :10349000D9F068F500916A0410916B0420916C04D6 :1034A00030916D04413059F088299929AA29BB2906 :1034B000BC01CD0160237123822393231EC0802A87 :1034C000912AA22AB32A13C088299929AA29BB299B :1034D00000916A0410916B0420916C0430916D048A :1034E000BC01CD01602771278227932706C0BC014C :1034F000CD01682979298A299B290E946A1EADC0BD :103500001F70BB2039F0812F0E94BE1E802F0E94A9 :103510005629A3C0802F0E944B29812F0E94801E14 :103520009CC0802F32EF931609F440C0391538F053 :1035300090EF991661F0E1EF9E1699F170C0F3EFEC :103540009F16D9F124EF921609F44EC068C0BB2033 :1035500019F134E03A1508F47CC01F7181E090E065 :10356000A0E0B0E0AC01BD0104C0440F551F661FD0 :10357000771F1A95D2F780916A0490916B04A091FD :103580006C04B0916D048A019B01082719272A2732 :103590003B27C901B80125C025E02A1508F459C008 :1035A000DCCFBB2029F0812F8F712CC0BB20D9F339 :1035B000812F8F710E94801E4CC0BB2079F01F713B :1035C00081E090E0A0E0B0E0BC01CD0104C0660F56 :1035D000771F881F991F1A95D2F703C060E070E02B :1035E000CB010E946A1E35C0BB2079F01F71812F6C :1035F0000E94BE1E38E0139FC00111248360809397 :10360000D405812F0E94BE1E24C081E00E94A51E09 :1036100081E08A15F0F482E00E94A51E1AC0BB204A :1036200039F0AA2009F4BFCF802F0E94BC2911C015 :10363000AA2009F4BDCF893349F49FEFE3EFF1E00D :103640009150E040F040E1F700C00000802F0E9460 :10365000602988EF8C0D843010F40E94A310DD20C7 :1036600041F18091D40580FD24C0F7011282859537 :10367000859585950E94BE1EC7010E941D168091EA :10368000D4058595859585950F900F900F900F9097 :103690000F90DF91CF911F910F91FF90EF90DF90EE :1036A000CF90BF90AF909F908F900C94801E69E256 :1036B00019CD0F900F900F900F900F90DF91CF9139 :1036C0001F910F91FF90EF90DF90CF90BF90AF9040 :1036D0009F908F90089508958091DE05089580E071 :1036E0000895CF93DF9300D01F92CDB7DEB79091AE :1036F0000106943011F589837B836A839093E900F6 :103700008FEF9091E800815095FD06C09AE69A955A :10371000F1F700C08111F5CF8091E80085FF0DC061 :1037200040E050E063E070E0CE0101960E9423216A :103730008091E8008E778093E8000F900F900F90B3 :10374000DF91CF910895BC0184E00C94711BBC0102 :1037500083E00C94711BCF93DF93209126012223E9 :1037600039F02091FE0227FF03C060E224E002C08E :1037700068E021E02093E9002FEF3091E80021502C :1037800035FD06C03AE63A95F1F700C02111F5CFB4 :103790002091E80025FF1DC0EC01809126018111D8 :1037A00005C040E050E068E070E003C070E040E039 :1037B00050E0CE010E9423218091E8008E77809313 :1037C000E80080E2FE01AFEDB5E001900D928A9530 :1037D000E1F7DF91CF91089581E08093E00080E2EE :1037E0008093D8001092C9008FE097E20197F1F71B :1037F00000C0000087E090EBDC0180933E069093D0 :103800003F06A0934006B09341069CE088E10FB6C6 :10381000F894A895809360000FBE90936000FFCF4E :1038200078941F920F920FB60F9211248F939F934B :10383000AF93BF9380917C0390917D03A0917E0311 :10384000B0917F030196A11DB11D80937C039093DD :103850007D03A0937E03B0937F03BF91AF919F91AF :103860008F910F900FBE0F901F9018952FB7F8945F :1038700080917C0390917D03A0917E03B0917F03A2 :103880002FBF08951F920F920FB60F9211248F939E :103890009F93AF93BF9380910203811113C08091D6 :1038A0007C0390917D03A0917E03B0917F034196AC :1038B000A11DB11D80937C0390937D03A0937E0393 :1038C000B0937F03BF91AF919F918F910F900FBEE7 :1038D0000F901F901895209126012223C9F0209166 :1038E000FE0227FF15C0262F2695269526952E31F8 :1038F000C8F4FC01E20FF11D677081E090E001C0A7 :10390000880F6A95EAF780959281892382830895CA :10391000FC0106962281621301C012823196E817DB :10392000F907C1F70895209126012223C1F02091C3 :10393000FE0227FF14C0262F2695269526952E31A8 :1039400030F5FC01E20FF11D677081E090E001C0ED :10395000880F6A95EAF79281892B82830895FC018A :1039600032962FEF30E04191641789F02F3F19F420 :10397000411101C0232F3F5F3630A9F72F3F39F0A7 :10398000FC01E20FF11D27FDFA9562830895089569 :10399000CF9384E090E00E94E32AC82F81E290E078 :1039A0000E94E32A2C2F30E0A901582BCA01CF91A5 :1039B00008956BEE7EEF80E090E00E941F2B60E0A8 :1039C00082E090E00E94012B60E083E090E00E94A2 :1039D000012B1092D9051092DA051092DB05109296 :1039E000DC0560E084E090E00E94012B60E081E271 :1039F00090E00E94012B60E085E090E00E94012BA6 :103A000060E086E090E00E94012B6FEF87E090E09D :103A10000E94012B40E050E0BA0188E090E00E9453 :103A2000132B60E08DE090E00E94012B40E050E01D :103A3000BA0188E190E00E94132B60E087E190E0FA :103A40000E94012B40E050E0BA018CE190E00E941E :103A5000132B60E080E290E00E94012B40E050E0F8 :103A6000BA0188E190E00E94132B40E050E0BA01D7 :103A70008FE090E00E94132B40E050E0BA0183E118 :103A800090E00C94132B8091D80581111092D805E9 :103A900008959091D7058091D605892B2091D50561 :103AA000982F922B90934F058091D8058823D9F0B9 :103AB000892B80934F0580912601882331F08091D6 :103AC000FE0287FF02C08EE101C086E0E1E5F5E07D :103AD00090E0815028F021912223D9F39F5FF9CF04 :103AE00091110E94431DE0910003F0910103309772 :103AF000A9F080912601882359F08091FE0287FF6A :103B000007C080914F058093500585E080934F0555 :103B10000280F381E02D8FE495E00994089580E020 :103B200090E00E948D1080E090E00E94771010924B :103B3000D6051092D5050C94491DBF92CF92DF9205 :103B4000EF92FF920F931F93CF93DF938C01C0905E :103B50006A04D0906B04E0906C04F0906D04809146 :103B6000D9059091DA05A091DB05B091DC05C82A52 :103B7000D92AEA2AFB2ACFE1D0E0D701C6010C2ED0 :103B800004C0B695A795979587950A94D2F780FDBE :103B900004C0219790F7B12C07C0BC2EB8018C2F20 :103BA0000E94FA130197A9F38B2DDF91CF911F91FA :103BB0000F91FF90EF90DF90CF90BF900895CF933B :103BC000DF93EC010E949D1DBE010E94FA13DF915C :103BD000CF9108950E94DF1D292F2F70E92FE295C4 :103BE000EF704E2F50E0FA013297EE30F105B8F445 :103BF000ED56FF4F0C94B02B803F99F018F4883E9F :103C000070F40FC0843F59F40CC0883E50F0813FDF :103C100031F407C0822F869586958695089580E0B9 :103C2000089581E008952EE0929F800D1124682F61 :103C3000669566956695982F977085E0689FB001A8 :103C4000112440E050E080E0FB01E40FF51FE9554E :103C5000FA4F208130E0092E02C0369527950A944C :103C6000E2F721703327042E01C0220F0A94EAF7ED :103C7000822B4F5F5F4F4530510531F708952EE09D :103C8000929F800D1124E82FE695E695E6958770C2 :103C900051E001C0550F8A95EAF785E0E89FF001F1 :103CA0001124E955FA4F20E030E070E04081CB016B :103CB000022E02C0969587950A94E2F7817081954D :103CC00084278523842781932F5F3F4F253031053B :103CD00069F70895CF92DF92EF92FF926B017C011A :103CE0000E94C615C0926A04D0926B04E0926C04E4 :103CF000F0926D04FF90EF90DF90CF900C948F1DA9 :103D00000F931F9341E050E060E070E004C0440F67 :103D1000551F661F771F8A95D2F74095509560957D :103D2000709580916A0490916B04A0916C04B0919D :103D30006D048A019B01082319232A233B23C9010F :103D4000B8011F910F910C946A1E2091D4058095A3 :103D500082238093D405982F977079F430E0482F10 :103D6000082E000C550B2417350739F085958595DD :103D700085950E94801E1092D40508950F931F937D :103D800041E050E060E070E004C0440F551F661F42 :103D9000771F8A95D2F780916A0490916B04A09165 :103DA0006C04B0916D048A019B01082B192B2A2BFE :103DB0003B2BC901B8011F910F910C946A1E6093AF :103DC000D9057093DA058093DB059093DC050C949C :103DD0008F1D8091A60590917505891719F08F5F49 :103DE0008770FBCF08950F931F93CF93DF9380913C :103DF000740582958F7009F05DC0809171058823EC :103E000009F458C08091A6051091750560916F0561 :103E100070917005C0917205D091730591E06F3F6C :103E200009F090E0292F06E0811709F443C020979C :103E300021F07F3F21F030E003C031E001C0322F9C :103E400090E030FD34C0089FF001099FF00D11246F :103E5000DF01AA58BA4F11963C911197371327C02A :103E60003C91361324C012963C91129731111FC019 :103E700013964D915C9114974C1B5D0B483C51057A :103E8000B0F4809174058F70806180937405E5585B :103E9000FA4F80818F70806180838FE695E00E9469 :103EA0001D16DF91CF911F910F910C94E91E019681 :103EB0008770BACFDF91CF911F910F9108959F9294 :103EC000AF92BF92CF92DF92EF92FF920F931F9328 :103ED000CF93DF93CDB7DEB761970FB6F894DEBF0F :103EE0000FBECDBF8C0185E0F801DE011D9601906B :103EF0000D928A95E1F7F80190818181E2803091FD :103F00006F056091700540917205509173054115E0 :103F1000510531F06F3F31F421E03F3F19F403C008 :103F200021E001C020E0F22FF1709F2E20FD23C17F :103F3000F801C380D4802FE6A22E25E0B22EF090A7 :103F40007105F601E41BF50BFF2009F4CEC02091AA :103F50007405E83CF10508F099C0422F407F09F054 :103F600051C0681311C039130FC0FE2CE1100CC0F2 :103F70002F70206120937405C5010E941D16809149 :103F80007405F801858337C1CD2831F08F3F31F4B6 :103F900021E09F3F19F403C021E001C020E020FD93 :103FA00003C021E02E2502C020E030E0F22FF170A6 :103FB000FF2E20FF1DC02091A6054091750556E0FB :103FC000241709F4F6C030E0529FF001539FF00D22 :103FD0001124EA58FA4F6181861306C06081961356 :103FE00003C06281E61204C02F5F3F4F2770E8CF05 :103FF000FE2CEE2009F4FFC080917405816080934F :10400000740550C0681307C0391305C0E11003C020 :10401000F80125838DC09D878E878D859E850E94A2 :10402000EA1D882369F1EE2059F120917405822F51 :1040300082958F7090E0029774F080916F05909157 :10404000700598878F831986DB86CA862C87CE01F8 :1040500007960E941D1686E0F801AFE6B5E00190D4 :104060000D928A95E1F70E94F31E0DC06817E1F0EA :104070009D878E878D859E850E94EA1D81111EC0B9 :10408000C8010E941D16FF24F394B5C0422F407F43 :1040900069F78FE695E00E941D1686E0F501119202 :1040A0008A95E9F7F12CA7C03913E2CFE110E0CFF0 :1040B000F8012583C8010E941D1657C0EE2001F3A8 :1040C00020917405822F82958F7090E002971CF2E8 :1040D00080916F05909170059A8389831B82DD82A0 :1040E000CC822E83CE010196B4CFE83CF105E8F5F1 :1040F000FE2CEE2029F2681327C0391325C0209129 :10410000740520FD18C0822F82958F70482F50E0D3 :104110004115510581F0F80125834F30510541F0DB :104120008F5F982F9295907F822F8F70892B858338 :10413000C8010E941D1686E0F801AFE6B5E00190C7 :104140000D928A95E1F757C09D878E878D859E8554 :104150000E94EA1D81117FCF809174058160809358 :104160007405C8010E941D1646C086E0F501119233 :104170008A95E9F740C0EE2009F482CF9D878E87AB :104180008D859E850E94EA1DF82E882309F478CF3C :1041900086E0F801AFE6B5E001900D928A95E1F76F :1041A00080916F05909170050E94DF1D0E94F31EA3 :1041B00022C09D878E878D859E850E94DF1D292FB9 :1041C00022952F70223028F49F7039F0811105C09C :1041D0000BC0243028F49F7049F4805E883020F0B2 :1041E000C8010E941D169F2CF92C05C0F80195816D :1041F000907F99F7F9CF8F2D61960FB6F894DEBFB7 :104200000FBECDBFDF91CF911F910F91FF90EF9027 :10421000DF90CF90BF90AF909F9008951092D705F8 :1042200080912601882331F08091FE0287FF02C031 :104230008EE101C086E0E1E5F5E0DF011D928A959F :10424000E9F70C948F1DEF92FF920F931F93CF937A :10425000DF937C018B010E943127811119C0E70196 :1042600001151105A1F08091E80085FD0AC080913B :10427000E8008E778093E8000E943127882381F33D :1042800007C089918093F10001501109E9CF80E0C6 :10429000DF91CF911F910F91FF90EF9008956F9252 :1042A0007F928F929F92AF92BF92CF92DF92EF92C6 :1042B0000F931F93CF93DF933C01C09127018EE0B2 :1042C000C89FC02D1124DEE0DC0FD73408F0D6E4FF :1042D00060913C06669580913406909135060E9467 :1042E0000E12182FCD1708F044C08C2E912CF4011B :1042F000E658FD4F9081809128018923C1F1F40196 :10430000EE0FFF1FE251FE4FC080D12C80E7C81A8C :10431000D108F401EE0FFF1FE151FE4FA080B12C38 :10432000E0E2AE1AB108CC9C9001CD9C300D300D6E :104330001124AA9CC001AB9C900D900D1124820FFA :10434000931F0E94B411082F6091390670913A06AC :1043500080913B06E12E9501A601F30109950E948B :104360001812462F282F672FC4010E947B11CF5FA0 :10437000B9CF81E0D63408F080E0DF91CF911F9172 :104380000F91EF90DF90CF90BF90AF909F908F9064 :104390007F906F900895CF92DF92EF92FF920F93EC :1043A0001F93CF93DF936C01C09127018EE0C89FCC :1043B000C02D1124DEE0DC0FD73408F0D6E4609184 :1043C0003C06669580913406909135060E940E1247 :1043D000182FCD1778F5EC2EF12CF701E658FD4F8C :1043E000908180912801892319F1F701EE0FFF1FB9 :1043F000E151FE4F208130E020523109F701EE0FEC :10440000FF1FE251FE4F408150E04057510960913B :10441000390670913A0680913B06012FF601099505 :104420000E941812462F282F672FC7010E947B1168 :10443000CF5FCFCF81E0D63408F080E0DF91CF911D :104440001F910F91FF90EF90DF90CF900895DF9232 :10445000EF92FF920F931F93CF93DF937C01C09154 :1044600027018EE0C89FC02D1124DEE0DC0FD73479 :1044700008F0D6E460913C06669566958091340616 :10448000909135060E940E12D82ECD17F0F40C2F05 :1044900010E0F801E658FD4F9081809128018923B2 :1044A00091F06091390670913A0680913B062D2D6E :1044B0004C2FF70109950E941812462F282F672FBD :1044C000C8010E947B11CF5FE0CF81E0D63408F0B5 :1044D00080E0DF91CF911F910F91FF90EF90DF90DF :1044E00008959F92AF92BF92CF92DF92EF92FF9288 :1044F0000F931F93CF93DF936C01C09127018EE040 :10450000C89FC02D1124DEE0DC0FD73408F0D6E4BC :1045100060913C06669566958091340690913506CB :104520000E940E12182F80E4810F0E94931190E8D0 :10453000F92EF80E812F0E94931120E8922E980EEA :10454000CD1700F5AC2EB12CF501E658FD4F90814A :10455000809128018923A1F06091390670913A0673 :1045600080913B06E12E0C2F292D4F2DF601099548 :104570000E941812462F282F672FC5010E947B1119 :10458000CF5FDECF81E0D63408F080E0DF91CF91BD :104590001F910F91FF90EF90DF90CF90BF90AF9061 :1045A0009F900895CF92DF92EF92FF920F931F9307 :1045B000CF93DF936C01C09127018EE0C89FC02D7F :1045C0001124DEE0DC0FD73408F0D6E420913C065D :1045D00030E040E050E06FEF7FEF80E090E00E943D :1045E000252B8901CD17E8F5EC2EF12CF701E658C3 :1045F000FD4F908180912801892389F190910B06CC :10460000915097FD15C0492F092E000C550BFA014A :10461000E55FF94F8189C813F3CF440F551FFA01A5 :10462000E55FF94F218D328D2017310748F701C022 :10463000980160913C06C9010E940E12AC01609184 :10464000390670913A0680913B06F60109950E9461 :104650001812462F282F672FC7010E947B11CF5FAA :10466000C1CF81E0D63408F080E0DF91CF911F9177 :104670000F91FF90EF90DF90CF9008952F923F928F :104680004F925F926F927F928F929F92AF92BF9262 :10469000CF92DF92EF92FF920F931F93CF93DF930E :1046A000CDB7DEB727970FB6F894DEBF0FBECDBFEC :1046B000282E4B01209127018EE0289F802D112468 :1046C0008E83182F125F173408F016E430910B0612 :1046D00039839E81911708F077C08E81682E712CE6 :1046E000F301E658FD4F908180912801892309F458 :1046F00067C03090390640903A06522C1F82C301A1 :10470000880F991FDC01A251BE4FBB83AA83C3014E :10471000880F991FFC01E151FE4FFD83EC83F98165 :104720005F16E0F5E52CF12CAA81BB81CC90D12C51 :10473000F701E55FF94F8181C81AD108AC81BD81CD :10474000AC90B12C8185A81AB108CC9C9001CD9C6D :10475000300D300D1124AA9CC001AB9C900D900D22 :104760001124820F931F0E94B411082FF701EE0F3E :10477000FF1FE55FF94F60913C06818D928D0E948D :104780000E127C019501A601632D742D8F81F40119 :104790000995362E472E8F835394C1CF20913B0627 :1047A0008F81382F329F312D1124832F632D742D4B :1047B0000E941812462F282F672FC3010E947B11D9 :1047C0008E818F5F8E8385CF81E0163408F080E084 :1047D00027960FB6F894DEBF0FBECDBFDF91CF9105 :1047E0001F910F91FF90EF90DF90CF90BF90AF900F :1047F0009F908F907F906F905F904F903F902F9001 :1048000008951F93CF93DF93CDB7DEB7AA970FB666 :10481000F894DEBF0FBECDBFE3E0F6E08091F1007B :10482000819346E0EB30F407C9F7809104068330AA :1048300009F460C030F4813071F0823009F49AC01C :10484000B1C08A3009F486C08B3009F46BC089305E :1048500009F0A8C020C080910306813A09F0A2C0E7 :104860008091E800877F8093E8008091070690910F :104870000806892B21F460E28FED95E003C060E02B :1048800080E090E070E00E94EF288091E8008B7754 :104890008093E80087C080910306813209F082C0CE :1048A0008091070690910806009719F0029709F089 :1048B00079C08091E800877F8093E8008091E800CC :1048C00082FD05C0809101068111F8CF6BC08091F7 :1048D000F2009091F300029729F48091F1008B7F10 :1048E000813021F48091F1008093DE058091E80011 :1048F0008B7754C080910306813A09F053C08091B0 :10490000070690910806892B09F04CC08091E800B9 :10491000877F8093E8008091E80080FFFCCF809142 :10492000260137C0809103068132E1F580910706A8 :1049300090910806892BB1F58091E800877F8093DC :10494000E8000E94642780910506809326010E945A :104950000E2128C080910306813221F58091E80064 :10496000877F8093E8000E946427809106068093E9 :10497000DD0518C080910306813AA1F48091E8001A :10498000877F8093E8008091E80080FFFCCF8091D2 :10499000DD058093F1008091E8008E778093E80038 :1049A0000E9464278091E80083FFDAC180910306AA :1049B00090910406492F50E04A30510508F0D0C1CB :1049C000FA01EF55FF4F0C94B02B803821F082385C :1049D00009F0C6C108C08091FF0590910006992397 :1049E00089F082600FC0809107068F70873008F0D1 :1049F000B7C18093E9008091EB0085FB882780F99F :104A00001092E9009091E800977F9093E8008093DE :104A1000F1001092F1006DC1282F2D7F09F0A0C187 :104A2000882319F0823061F09BC1809105068130A6 :104A300009F096C1933009F080E0809300062EC003 :104A40008091050681112AC0809107068F702FEF93 :104A5000280F263008F084C18093E9002091EB00F4 :104A600020FF1CC0933021F48091EB00806214C0C1 :104A70009091EB0090619093EB0021E030E0A90170 :104A800002C0440F551F8A95E2F74093EA00109246 :104A9000EA008091EB0088608093EB001092E900BF :104AA0008091E800877F8093E8000E94642758C1C6 :104AB000811156C1109105061F778091E30080781F :104AC000812B8093E3008091E800877F8093E8004A :104AD0000E9464278091E80080FFFCCF8091E30072 :104AE00080688093E300111102C082E001C083E07E :104AF0008093010635C18058823008F031C1209181 :104B00000506309106062C3D53E0350779F583E024 :104B10008A838AE289834FB7F894DE01139620E0F6 :104B20003EE051E2E32FF0E050935700E49120FF84 :104B300003C0E295EF703F5FEF708E2F90E0EA3098 :104B400010F0C79601C0C0968D939D932F5F2431BE :104B500049F74FBF8091E800877F8093E8006AE2C1 :104B600070E0CE0101960E94EF28B1C08091070647 :104B700090910806432F552743305105A9F068F45A :104B80004130510509F4FBC04230510509F0E8C03D :104B90008BE590E0E5E5F5E04BC04132510529F1A8 :104BA0004232510589F1DCC0C90199278130910554 :104BB000A1F058F0029709F0D3C0E2ECF5E0E491DF :104BC0008E2F90E0E2ECF5E030C0E2E3F6E0E49115 :104BD0008E2F90E0E2E3F6E028C0EEE1F6E0E4910B :104BE0008E2F90E0EEE1F6E020C08330910508F0D2 :104BF000B7C0880F991FFC01EE55FE4F0190F08160 :104C0000E02D89E090E014C08330910508F0A8C041 :104C1000FC01EE0FFF1FE456FE4F0190F081E02DE6 :104C2000DC01A756BE4F8C9190E0009709F498C024 :104C30002091E800277F2093E80020910906309119 :104C40000A062817390708F4C90140E0009771F1F6 :104C5000209101062223D9F12530C9F12091E800E5 :104C600023FD35C02091E80022FD2DC02091E800F1 :104C700020FFECCF2091F2003091F300009759F023 :104C80002830310540F444914093F100319601976A :104C90002F5F3F4FF3CF41E02830310509F040E06E :104CA0002091E8002E772093E800D0CF4111D0CF9B :104CB0000AC080910106882351F0853041F080912F :104CC000E80083FD04C08091E80082FFF2CF80916C :104CD000E8008B778093E80043C0803809F040C03B :104CE0008091E800877F8093E8008091020680939E :104CF000F1008091E8008E77D6CE811131C080918D :104D00000506909106069927029754F58091E800D0 :104D1000877F8093E80010910506109302060E9499 :104D20006427111106C08091E30087FD02C081E075 :104D300001C084E08093010642E061EC81E00E94C2 :104D4000832742E261EC84E00E94832742E261EC27 :104D500082E00E94832742E260EC83E00E94832786 :104D60008091E80083FF10C08091E800877F8093E6 :104D7000E8008091EB0080628093EB0005C082E147 :104D800090E0E0EBF5E054CFAA960FB6F894DEBFC2 :104D90000FBECDBFDF91CF911F9108951F920F924B :104DA0000FB60F9211242F933F934F935F936F93FE :104DB0007F938F939F93AF93BF93CF93DF93EF93A3 :104DC000FF93C091E900CF708091EC00D82FD17093 :104DD00080FDD0E81092E9008091F000877F8093F9 :104DE000F00078940E9401241092E9008091F00074 :104DF00088608093F000CD2BCF70C093E900FF91C5 :104E0000EF91DF91CF91BF91AF919F918F917F9162 :104E10006F915F914F913F912F910F900FBE0F9027 :104E20001F901895E8EDF0E080818C7F80831092D0 :104E3000E2001092DA001092E100A0EEB0E08C9156 :104E400081608C9380818F77808319BCA7EDB0E05F :104E50008C918E7F8C9380818F7E808310923D0613 :104E600008952091E4003091E50095E64091EC0032 :104E7000842F817040FF23C08091E80080FD1DC019 :104E800080910106882399F0853099F08091EB009C :104E900085FD11C04091E4005091E50024173507CD :104EA00029F3915011F09A01E1CF84E0089582E056 :104EB000089583E0089581E0089580E00895409189 :104EC000E80042FFDDCF08958091030687FF11C0FF :104ED0008091E80082FD05C0809101068111F8CF24 :104EE00011C08091E8008B770BC080910106882368 :104EF00049F08091E80080FFF8CF8091E8008E773C :104F00008093E8000895982F973068F59093E90012 :104F1000981739F07091EC002091ED005091F0005D :104F200003C0242F762F50E021FD02C09F5FECCFFD :104F30003091EB003E7F3093EB003091ED003D7FF0 :104F40003093ED003091EB0031603093EB007093C3 :104F5000EC002093ED005093F0002091EE0027FD2F :104F6000E5CF80E008958F708093E90081E0089597 :104F7000CF92DF92EF92FF920F931F93CF93DF9325 :104F8000C8EDD0E088818F7E8883E7EDF0E08081F6 :104F90008160808381E080933D0688818C7F888357 :104FA00002EE10E0D8011C921092DA0081EEC82EB9 :104FB000D12CD6011C9288818F7788838881806864 :104FC000888388818F7D888380818068808319BCF5 :104FD0001092010610920206109200061092FF0530 :104FE00090EEE92EF12CF70180818B7F8083888100 :104FF0008160888342E060E080E00E948327D601E0 :105000008C918E7F8C93F801808181608083808178 :1050100088608083D7018C918E7F8C93888180619A :105020008883DF91CF911F910F91FF90EF90DF90D8 :10503000CF9008951F920F920FB60F9211242F93C5 :105040003F934F935F936F937F938F939F93AF9310 :10505000BF93EF93FF938091E10082FF09C080919D :10506000E20082FF05C08091E1008B7F8093E10028 :105070008091DA0080FF2AC08091D80080FF26C08E :105080008091DA008E7F8093DA008091D90080FFD2 :1050900018C088E189BD8AE189BD09B400FEFDCF51 :1050A00081E08093010680913D0681110FC00E942E :1050B00012270E94B8278091E20084608093E2006A :1050C00005C019BC1092010610923D068091E100C6 :1050D00080FF17C08091E20080FF13C08091E20042 :1050E0008E7F8093E2008091E20080618093E200F5 :1050F0008091D80080628093D80019BC85E08093AD :1051000001068091E10084FF2EC08091E20084FFBF :105110002AC088E189BD8AE189BD09B400FEFDCFBE :105120008091D8008F7D8093D8008091E1008F7EA0 :105130008093E1008091E2008F7E8093E200809175 :10514000E20081608093E20080910206882311F0E2 :1051500084E007C08091E30087FD02C081E001C0C8 :1051600083E0809301068091E10083FF27C0809156 :10517000E20083FF23C08091E100877F8093E100FC :1051800082E080930106109202068091E1008E7FFA :105190008093E1008091E2008E7F8093E200809115 :1051A000E20080618093E20042E060E080E00E94E3 :1051B00083278091F00088608093F000FF91EF9149 :1051C000BF91AF919F918F917F916F915F914F911F :1051D0003F912F910F900FBE0F901F901895209127 :1051E000090630910A062617370748F06115710540 :1051F00039F42091E8002E772093E80001C0B9012E :10520000FC0120E06115710569F180910106882398 :10521000E1F18530E1F18091E80083FD3AC08091B1 :10522000E80082FD2CC08091E80080FFEBCF8091E8 :10523000F2009091F3006115710551F088309105ED :1052400038F421912093F100615071090196F3CF58 :1052500021E0089709F020E08091E8008E778093A4 :10526000E800D0CF2111D1CF0AC080910106882358 :1052700061F0853061F08091E80083FD0AC0809183 :10528000E80082FFF2CF80E0089582E0089583E095 :10529000089581E00895882341F080959091D70585 :1052A00089238093D7050C94491D0895882339F0EC :1052B0009091D705892B8093D7050C94491D0895AB :1052C000882309F458C0682F823869F40E94A3101B :1052D00081FF51C069E38FE495E00E94931C0E9416 :1052E000491D69E30EC0833891F40E94A31080FF2A :1052F00042C063E58FE495E00E94931C0E94491D23 :1053000063E58FE495E00E946B1C0C94491D843882 :1053100069F40E94A31082FF2EC067E48FE495E039 :105320000E94931C0E94491D67E4EBCF8CEF860F0F :10533000813A38F380E2860F883070F4677081E03C :1053400090E001C0880F6A95EAF780959091D705A3 :1053500089238093D705D9CF8BE5860F833020F43E :1053600080E090E00C948D10685A673120F480E062 :1053700090E00C9477100895CF93882309F4B5C07A :10538000C82F8238B1F40E94A31081FDAEC069E33A :105390008FE495E00E94931C0E94491D2FEF80E747 :1053A00092E0215080409040E1F700C0000069E3A6 :1053B00017C08338E1F40E94A31080FD96C063E516 :1053C0008FE495E00E94931C0E94491D2FEF80E717 :1053D00092E0215080409040E1F700C0000063E57A :1053E0008FE495E00E946B1CCF910C94491D84388A :1053F000B1F40E94A31082FD78C067E48FE495E0C9 :105400000E94931C0E94491D2FEF80E792E02150DB :1054100080409040E1F700C0000067E4E1CF8CEFEE :105420008C0F813AB8F5809126018823E1F08091B4 :10543000FE0287FF18C0EC2FE695E695E695F0E0B2 :10544000E15BFA4F8281282F30E04C2F477081E0DA :1054500090E002C0880F991F4A95E2F782239323B8 :10546000892B59F411C0E1E5F5E08191C81729F0C5 :1054700025E0E735F207C9F707C06C2F8FE495E008 :105480000E946B1C0E94491D6C2F8FE495E00E94C6 :10549000931CAACF80E28C0F883068F4C77081E03B :1054A00090E001C0880FCA95EAF79091D705892B43 :1054B0008093D70599CFEBE5EC0FE33040F4F0E0B3 :1054C000E054FD4F808190E0CF910C948D10C85A2C :1054D000C73158F4EC2FF0E0EE0FFF1FED53FD4FF6 :1054E00080819181CF910C947710CF9108958F9204 :1054F0009F92AF92BF92CF92DF92EF92FF92CF93A3 :10550000DF93EC01688179818A819B816115710546 :105510008105910521F464E279ED8BE597E02DE1B9 :1055200033EF41E050E00E94252B49015A019B01D5 :10553000AC01A7EAB1E40E94442B6B017C01ACEE04 :10554000B4EFA50194010E94522BDC01CB018C0D1C :105550009D1DAE1DBF1DB7FF03C00197A109B04837 :1055600088839983AA83BB839F77DF91CF91FF9034 :10557000EF90DF90CF90BF90AF909F908F90089565 :105580000E94772A089580E091E00E94772A08958A :10559000A0E0B0E08093000190930101A09302018C :1055A000B09303010895DC01CB01FC01F999FECF12 :1055B00006C0F2BDE1BDF89A319600B40D9241509B :1055C0005040B8F70895F999FECF92BD81BDF89A81 :1055D000992780B50895A8E1B0E042E050E00C942E :1055E000D52ADC01A40FB51F4150504048F0CB0133 :1055F000840F951F2E910E94022B41505040D0F7EE :105600000895262FF999FECF92BD81BDF89A019792 :1056100000B4021639F01FBA20BD0FB6F894FA9AFA :10562000F99A0FBE08950396272F0E94022B0E941D :10563000012B252F0E94022B242F0C94022B019664 :10564000272F0E94022B0C94012B052E97FB1EF492 :1056500000940E943C2B57FD07D00E94572B07FC5B :1056600003D04EF40C943C2B5095409530952195E9 :105670003F4F4F4F5F4F089590958095709561957E :105680007F4F8F4F9F4F08950E94792BA59F900DBC :10569000B49F900DA49F800D911D11240895B7FF14 :1056A0000C94442B0E94442B821B930B0895A1E27F :1056B0001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F8C :1056C000FF1FA217B307E407F50720F0A21BB30BD7 :1056D000E40BF50B661F771F881F991F1A9469F753 :1056E00060957095809590959B01AC01BD01CF01AF :1056F0000895A29FB001B39FC001A39F700D811DAB :105700001124911DB29F700D811D1124911D0895CA :10571000AA1BBB1B51E107C0AA1FBB1FA617B707D7 :1057200010F0A61BB70B881F991F5A95A9F78095F3 :105730009095BC01CD01089597FB072E16F40094B7 :1057400007D077FD09D00E94882B07FC05D03EF4D6 :10575000909581959F4F0895709561957F4F08951D :10576000EE0FFF1F0590F491E02D0994FB01DC0181 :1057700002C001900D9241505040D8F70895FB01AE :10578000DC014150504048F001900D920020C9F7D3 :1057900001C01D9241505040E0F70895F894FFCFAA :1057A00001000000FFFF033D8EFFB07F958EFFB02C :1057B0007F958EFFB07F958EFFB07F6C1BAB1B6B10 :1057C0001BA71BA31BB00100FF008EFFB0737973F2 :1057D00074656D37362F6C61756E63685F6C6974C4 :1057E000655F3100302E372E3130332D3430323674 :1057F0002D6737666432663500F1F2F3F4F56665BD :10580000646362616707060504C660C70107030693 :1058100002090109030302080103020301260C0D1A :105820000E10110F12131721222500003131295AB1 :105830001B750A2131426384B040226D1505F304C3 :10584000860467058005A00544434241403F3E3D34 :105850003C3B3A3938372728292A2B2C2D2E2F303C :1058600031323334262524232221201F1E1D1C1BE8 :105870001A450C0B0A090807060504030201003645 :105880000D0E0F1011191213141516171835D130EB :10589000BE30AB309C308C307D306E305F3050305D :1058A0004130313022300B3008401B402A40394013 :1058B00050406E4085409440A740C240D140E040F7 :1058C000E030C520B220A3209420852076206720D8 :1058D0005720482039202A201B20082004101710A8 :1058E000261035104410541063107210811090105F :1058F0009F10AF10BE10CD10E020E010C900B60020 :10590000A7009800890079006A005B004C003D0008 :105910002E001E000F000000E00004040404040434 :105920000404040404040404040404040404040437 :105930000404040404040404040404040404040427 :105940000404040404040404040404040404040417 :105950000404040404040404040404040404040407 :10596000818283E200E900EA00B500B600B700CD0D :10597000008301CC008A01920194012102230224B8 :10598000022502260227022A02B300B4006F00702B :02599000000015 :00000001FF ================================================ FILE: debian/changelog ================================================ system76-keyboard-configurator (1.3.13) jammy; urgency=medium * 1.3.13 release. -- Ian Douglas Scott Tue, 17 Feb 2026 19:58:49 -0800 system76-keyboard-configurator (1.3.12) jammy; urgency=medium * 1.3.12 release. -- Ian Douglas Scott Wed, 07 Aug 2024 10:24:27 -0700 system76-keyboard-configurator (1.3.11) jammy; urgency=medium * 1.3.11 release. -- Jeremy Soller Tue, 25 Jun 2024 09:22:20 -0600 system76-keyboard-configurator (1.3.10) jammy; urgency=medium * 1.3.10 release. -- Levi Portenier Tue, 10 Oct 2023 10:13:04 -0600 system76-keyboard-configurator (1.3.7) jammy; urgency=medium * 1.3.7 release. -- Levi Portenier Tue, 27 Jun 2023 09:58:45 -0600 system76-keyboard-configurator (1.3.6) jammy; urgency=medium * 1.3.6 release. -- Levi Portenier Wed, 07 Jun 2023 13:14:33 -0600 system76-keyboard-configurator (1.3.5) jammy; urgency=medium * 1.3.5 release -- Levi Portenier Tue, 06 Jun 2023 09:48:32 -0600 system76-keyboard-configurator (1.3.2) focal; urgency=medium * 1.3.2 release. -- Ian Douglas Scott Tue, 02 May 2023 14:42:50 -0700 system76-keyboard-configurator (1.3.1) focal; urgency=medium * 1.3.1 release. -- Jeremy Soller Mon, 27 Mar 2023 18:40:57 -0600 system76-keyboard-configurator (1.3.0) focal; urgency=medium * 1.3.0 release. -- Ian Scott Wed, 16 Nov 2022 08:23:08 -0800 system76-keyboard-configurator (1.2.0) focal; urgency=medium * 1.2.0 release. -- Ian Douglas Scott Mon, 27 Jun 2022 11:57:12 -0700 system76-keyboard-configurator (1.1.0) focal; urgency=medium * 1.1.0 release. -- Ian Douglas Scott Thu, 18 Nov 2021 08:07:12 -0800 system76-keyboard-configurator (1.0.0) focal; urgency=medium * First stable release. -- Ian Douglas Scott Thu, 27 May 2021 15:53:28 -0700 system76-keyboard-configurator (0.2.11) focal; urgency=medium * 0.2.11 release. -- Ian Douglas Scott Thu, 27 May 2021 07:21:32 -0700 system76-keyboard-configurator (0.2.10) focal; urgency=medium * 0.2.10 beta release. -- Ian Douglas Scott Mon, 24 May 2021 10:20:43 -0700 system76-keyboard-configurator (0.1.0) focal; urgency=medium * Initial release. -- Ian Douglas Scott Tue, 18 Aug 2020 09:54:33 -0700 ================================================ FILE: debian/com.system76.pkexec.keyboardconfigurator.policy ================================================ Authentication required to run System76 Keyboard Configurator com.system76.keyboardconfigurator auth_admin auth_admin auth_admin /usr/bin/system76-keyboard-configurator true ================================================ FILE: debian/compat ================================================ 11 ================================================ FILE: debian/control ================================================ Source: system76-keyboard-configurator Section: admin Priority: optional Maintainer: System76 Build-Depends: debhelper (>= 11), cargo, rustc (>=1.36.0), libgtk-3-dev, libhidapi-dev, libudev-dev, pkg-config, Standards-Version: 4.3.0 Homepage: https://github.com/pop-os/keyboard-configurator Package: system76-keyboard-configurator Architecture: amd64 arm64 Depends: ${misc:Depends}, ${shlibs:Depends} Description: System76 Keyboard Configurator Application for configuration of System76 keyboard firmware. Package: test-launch-system76-keyboard-configurator Architecture: amd64 arm64 Depends: system76-keyboard-configurator, avrdude, dfu-programmer, Description: Internal testing version of the System76 keyboard configurator. Package: libsystem76-keyboard-configurator Architecture: amd64 arm64 Depends: ${misc:Depends}, ${shlibs:Depends} Description: Pop keyboard backlight library Shared library for C which provides the Pop!_OS keyboard backlight as a GTK widget. Package: libsystem76-keyboard-configurator-dev Architecture: all Depends: libsystem76-keyboard-configurator (= ${binary:Version}), ${misc:Depends} Description: Pop keyboard backlight library header The C header required to link to the Pop!_OS keyboard backlight widget library. ================================================ FILE: debian/copyright ================================================ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: system76-keyboard-configurator Source: https://github.com/pop-os/keyboard-configurator Files: * Copyright: Copyright 2020 System76 License: GPL-3 ================================================ FILE: debian/libsystem76-keyboard-configurator-dev.install ================================================ usr/include ================================================ FILE: debian/libsystem76-keyboard-configurator.install ================================================ usr/lib/libsystem76_keyboard_configurator.so usr/lib/pkgconfig/system76_keyboard_configurator.pc ================================================ FILE: debian/libsystem76-keyboard-configurator.trigger ================================================ ldconfig ================================================ FILE: debian/rules ================================================ #!/usr/bin/make -f CLEAN ?= 1 VENDOR ?= 1 %: dh $@ override_dh_auto_clean: ifeq ($(CLEAN),1) make clean endif ifeq ($(VENDOR),1) if ! ischroot; then \ make vendor; \ fi endif override_dh_auto_build: env CARGO_HOME="$$(pwd)/target/cargo" \ make all VENDOR=$(VENDOR) prefix=/usr override_dh_auto_install: dh_auto_install -- prefix=/usr ================================================ FILE: debian/source/format ================================================ 3.0 (native) ================================================ FILE: debian/source/options ================================================ tar-ignore = ".git" tar-ignore = "target" tar-ignore = "vendor" ================================================ FILE: debian/system76-keyboard-configurator.install ================================================ usr/bin/system76-keyboard-configurator usr/share/applications/com.system76.keyboardconfigurator.desktop usr/share/metainfo/com.system76.keyboardconfigurator.appdata.xml usr/share/icons debian/com.system76.pkexec.keyboardconfigurator.policy usr/share/polkit-1/actions data/system76_launch_1_default.hex /var/lib/system76-keyboard-configurator/ data/system76_launch_2_default.hex /var/lib/system76-keyboard-configurator/ data/system76_launch_lite_1_default.hex /var/lib/system76-keyboard-configurator/ data/system76_launch_heavy_1_default.hex /var/lib/system76-keyboard-configurator/ ================================================ FILE: debian/test-launch-system76-keyboard-configurator.install ================================================ linux/com.system76.keyboardconfiguratorlaunchtest.desktop usr/share/applications/ ================================================ FILE: ffi/Cargo.toml ================================================ [package] name = "ffi" version = "0.1.0" authors = ["Ian Douglas Scott "] edition = "2021" [lib] name = "system76_keyboard_configurator" crate-type = [ "cdylib" ] [dependencies] gtk = "0.18.0" system76-keyboard-configurator-widgets = { path = "../widgets" } ================================================ FILE: ffi/build.rs ================================================ use std::{env, fs::File, io::Write, path::PathBuf}; fn main() { let target_dir = PathBuf::from("../target"); let pkg_config = format!( include_str!("system76_keyboard_configurator.pc.in"), name = "system76_keyboard_configurator", description = env::var("CARGO_PKG_DESCRIPTION").unwrap(), version = env::var("CARGO_PKG_VERSION").unwrap() ); File::create(target_dir.join("system76_keyboard_configurator.pc.stub")) .expect("failed to create pc.stub") .write_all(pkg_config.as_bytes()) .expect("failed to write pc.stub"); } ================================================ FILE: ffi/src/lib.rs ================================================ use gtk::glib::object::ObjectType; use std::mem; use system76_keyboard_configurator_widgets::keyboard_backlight_widget; #[no_mangle] pub extern "C" fn pop_keyboard_backlight_widget() -> *mut gtk::ffi::GtkWidget { unsafe { gtk::set_initialized(); } let widget = keyboard_backlight_widget(); let ptr = widget.as_ptr(); mem::forget(widget); ptr } ================================================ FILE: ffi/system76_keyboard_configurator.h ================================================ #pragma once #include GtkWidget *pop_keyboard_backlight_widget (); ================================================ FILE: ffi/system76_keyboard_configurator.pc.in ================================================ Name: {name} Description: {description} Version: {version} Cflags: -I${{includedir}} Libs: -L${{libdir}} -l{name} ================================================ FILE: flake.nix ================================================ { description = "System76 Keyboard Configurator"; inputs = { flake-utils.url = "github:numtide/flake-utils"; nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05"; naersk.url = "github:nix-community/naersk"; }; outputs = { self, nixpkgs, flake-utils, naersk }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; naersk-lib = naersk.lib."${system}"; in { packages = rec { default = system76-keyboard-configurator; system76-keyboard-configurator = naersk-lib.buildPackage { name = "system76-keyboard-configurator"; version = "1.3.12"; src = ./.; buildInputs = with pkgs; [ pkg-config rustc cargo hidapi glib gtk3 ]; }; }; devShells.default = pkgs.mkShell { buildInputs = with pkgs; [ pkg-config rustc cargo hidapi glib gtk3 ]; }; formatter = nixpkgs.legacyPackages."${system}".nixfmt; }); } ================================================ FILE: i18n/cs/system76_keyboard_configurator.ftl ================================================ -name = Nastavení Klávesnice app-about = O {-name} app-title = System76 {-name} board-fake = {$model}, falešný button-cancel = Zrušit button-configure = Nastavit Klávesnici button-disable = Vypnout button-import = Importovat button-test = Vyzkoušet button-start = Start button-stop = Stop error-disable-key = Vypnutí klávesy selhalo error-export-keymap = Exportování mapy kláves selhalo error-import-keymap = Importování mapy kláves selhalo error-key-led = Nastavení LED selhalo. error-open-file = Otevření souboru selhalo error-save-leds = Uložení LED selhalo error-set-keyboard-brightness = Nastavení jasu selhalo error-set-keyboard-mode = Nastavení režimu klávesnice selhalo error-set-keymap = Nastavení mapy kláves selhalo error-set-layer-brightness = Nastavení jasu vrstvy selhalo error-set-layer-color = Nastavení barvy vrstvy selhalo. error-set-layer-mode = Nastavení módu vrstvy selhalo. error-unsupported-keymap = Nepodporovaný soubor mapy kláves error-unsupported-keymap-desc = Soubor mapy kláves z novější verzi konfigurace. firmware-version = Firmware verze {$version} nepodporuje konfiguraci kláves. keyboard-brightness = Jas: keyboard-color = Barva: key-color = Barva klávesy: keymap-for-board = Mapa kláves je pro klávesnici '{$model}' layer-all-brightness = Jas (všechny vrstvy): layer-animation-speed = Rychlost animace vrstvy: layer-color = Barva vrstvy: layer-color-pattern = Vzor barvy vrstvy: layer-saturation = Saturace vrstvy: layout-export = Exportovat vrstvu layout-import = Importovat vrstvu layout-reset = Resetovat vrstvu layout-invert-f-keys = Invertovat F klávesy loading = Klávesnice detekována. Načítání... loading-keyboard = Načítání mapy kláves a LED pro {$keyboard} page-electrical = Electrické page-keycaps = Klávesy page-layer1 = Vrstva 1 page-layer2 = Vrstva 2 page-layer3 = Vrstva 3 page-layer4 = Vrstva 4 page-leds = LEDky page-logical = Logické no-boards = Nebyla detekována klávesnice no-boards-msg = Ujistěte se, že klávesnice má aktualizovaný System76 Otevřený Firmware. Pokud používáte externí klávesnici, ujistěte se, že je správně zapojena. show-help-overlay = Klávesové zkratky stack-keymap = Mapa kláves stack-keymap-desc = Vyberte klávesu na mapě kláves pro změnu nastavení. Shift pro výběr více kláves najednou. Nastavení jsou automaticky ukládány do firmwaru. stack-leds = LEDky stack-leds-desc = Vyberte klávesu pro změnu nastavení. Zvolte 'každá klávesa' pro změnu barvy každé klávesy. Shift pro výběr více kláves najednou. Nastaavení jsou automaticky ukládány do firmwaru. stack-leds-desc-builtin = Nastavení LED se resetují po restartu zařízení. Více funkcí budou přidány do budoucna. stack-testing = Testování test-check-pins = Zkontrolovat piny (chybící) test-check-key = Zkontrolovat klávesy (lepící) test-number-of-runs = Počet testů test-replace-switch = Vyměňte switch test-spurious-keypress = Falešné zmáčknutí klávesy untitled-layout = Vrstva bez nadpisu ================================================ FILE: i18n/cs/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Vypnuto mode-solid-color = Celé rozložení mode-per-key = Každá klávesa mode-active-keys = Nastavené klávesy mode-cycle-all = Kosmické pozadí mode-cycle-left-right = Horizontální mode-cycle-up-down = Vertikální mode-cycle-out-in = Horizont událostí mode-cycle-out-in-dual = Dvojhvězdy mode-rainbow-moving-chevron = Časoprostor mode-cycle-pinwheel = Kolo mode-cycle-spiral = Spirála mode-raindrops = Kapky deště mode-splash = Splashdown mode-multisplash = Meteorový déšť no-board = Žádná klávesnice ================================================ FILE: i18n/cs/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Barva button-cancel = Zrušit button-save = Uložit choose-color = Nastavit barvu error-set-color = Nastavení barvy klávesnice selhalo error-set-brightness = Nastavení jasu klávesnice selhalo label-hue = Odstín label-saturation = Sytost scale-brightness = Jas ================================================ FILE: i18n/da/system76_keyboard_configurator.ftl ================================================ -name = Keyboard Konfigureringsværktøj app-about = Om {-name} app-title = System76 {-name} board-fake = {$model}, Falsk button-cancel = Annuller button-configure = Konfigurer Keyboard button-disable = Slå fra button-import = Importer button-test = Test button-start = Start button-stop = Stop error-disable-key = Fejlede i at slå tast fra error-export-keymap = Fejlede i at exportere keymap error-import-keymap = Fejlede i at importere keymap error-key-led = Fejlede i at key'e LED error-open-file = Fejlede i at åbne fil error-save-leds = Fejlede i at gemme LEDer error-set-keyboard-brightness = Fejlede i at sætte lysstyrke error-set-keyboard-mode = Fejlede i at sætte tastatur mode error-set-keymap = Fejlede i at sætte keymap error-set-layer-brightness = Fejlede i at sætte lag's lysstyrke error-set-layer-color = Fejlede i at sætte lag's farve error-set-layer-mode = Fejlede i at sætte lag's mode error-unsupported-keymap = keymap fil ikke understøttet error-unsupported-keymap-desc = Keymap fil virker til at komme fra en nyere version konfigureringsværktøj. firmware-version = Firmware version {$version} understøtter ikke keymap konfiguration. keyboard-brightness = Lysstyrke: keyboard-color = Farve: key-color = Tast farve: keymap-for-board = Keymap er for tastatur '{$model}' layer-all-brightness = Lysstyrke (alle lag): layer-animation-speed = Lag's Animations fart: layer-color = Lag's farve: layer-color-pattern = Lag's Farve Mønster: layer-saturation = Lag's Saturation: layout-export = Exporter Layout layout-import = Importer Layout layout-reset = Nulstil Layout layout-invert-f-keys = Inverter F Taster flash-to-launch-heavy = Flash til Launch Heavy 1 flash-to-launch-2 = Flash til Launch 2 flash-to-launch-1 = Flash til Launch 1 flash-to-launch-lite-1 = Flash til Launch Lite 1 loading = Tastatur(er) registreret. Loader... loading-keyboard = Loader keymap og LEDer for {$keyboard} firmware-update-required = Keyboard Firmware Opdatering Påkrævet! page-electrical = Electrisk page-keycaps = Keycaps page-layer1 = lag 1 page-layer2 = Lag 2 page-layer3 = Lag 3 page-layer4 = Lag 4 page-leds = LEDer page-logical = Logisk no-boards = Intet Tastatur Registreret no-boards-msg = Vær sikker på dig indbyggede tastatur har oppe til dato System76 Åben Firmware. Hvis du bruger et externt Tastatur, dobbel check den er proppet ind ordentligt show-help-overlay = Keyboard Genveje stack-keymap = Keymap stack-keymap-desc = Vælg en tast på keymap'et for at ændre dens indstillinger. Shift + klik for at vælg mere end et klik. Dine indstillinger bliver automatisk gemt til firmwaren. stack-leds = LEDer stack-leds-desc = Vælg en tast på keymapet for at ændre dens indstillinger. Vælg per tast Solid mønster for at modificere hver tast's LED farve. Shift + klik for at vælge mere end en tast. Dine indstillinger bliver automatisk gemt til firmwaren. stack-leds-desc-builtin = LED indstillinger nulstiller efter genstart. Mere functionalitet kommer i fremtiden. stack-testing = Tester test-check-pins = Checker pins (mangler) test-check-key = Checker tast (klæbning) test-number-of-runs = Mængde af løb test-replace-switch = Udskift switch test-spurious-keypress = Falsk tastklik untitled-layout = Unavngivet Layout ================================================ FILE: i18n/da/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Slået fra mode-solid-color = Per Lag Solid Farve mode-per-key = Per Tast Solid mode-active-keys = Kun Bundede Taster mode-cycle-all = Cosmic Baggrund mode-cycle-left-right = Vandret Scan mode-cycle-up-down = Lodret Scan mode-cycle-out-in = Event Horizon mode-cycle-out-in-dual = Binære Galakser mode-rainbow-moving-chevron = Rumtid mode-cycle-pinwheel = Pinwheel Galaksesr mode-cycle-spiral = Spiral Galaxy mode-raindrops = Elementer mode-splash = Splashdown mode-multisplash = Meteor Regn no-board = Intet tastatur ================================================ FILE: i18n/da/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Farve button-cancel = Annuller button-save = Gem choose-color = Set Farve error-set-color = Fejlede i at sætte tastatur farve error-set-brightness = Fejlede i at sætte tastatur lysstyrke label-hue = Hue label-saturation = Saturation scale-brightness = Lysstyrke ================================================ FILE: i18n/de/system76_keyboard_configurator.ftl ================================================ -name = Tastatur-Konfigurator app-about = Über {-name} app-title = System76 {-name} board-fake = {$model}, Fälschung button-cancel = Abbrechen button-configure = Tastatur einstellen button-disable = Deaktivieren button-import = Importieren button-test = Testen error-disable-key = Taste konnte nicht deaktiviert werden error-export-keymap = Tastaturbelegung konnte nicht exportiert werden error-import-keymap = Tastaturbelegung konnte nicht importiert werden error-key-led = LED konnte nicht getastet werden error-open-file = Datei konnte nicht geöffnet werden error-save-leds = LEDs konnten nicht gespeichert werden error-set-keyboard-brightness = Fehler beim Einstellen der Helligkeit error-set-keyboard-mode = Fehler beim Einstellen der Tastaturart error-set-keymap = Fehler beim Einstellen der Tastaturbelegung error-set-layer-brightness = Schichthelligkeit konnte nicht eingestellt werden error-set-layer-color = Schichtfarbe konnte nicht eingestellt werden error-set-layer-mode = Schichtart konnte nicht eingestellt werden error-unsupported-keymap = Tastaturbelegungsdatei wird nicht unterstützt error-unsupported-keymap-desc = Tastaturbelegungsdatei scheint von einer neueren Konfigurator-Version zu stammen. keyboard-brightness = Helligkeit: keyboard-color = Farbe: key-color = Tastenfarbe: keymap-for-board = Tastaturbelegung ist für Bord '{$model}' layer-all-brightness = Helligkeit (alle Schichten): layer-animation-speed = Schichtenanimationsgeschwindigkeit: layer-color = Schichtenfarbe: layer-color-pattern = Schichtenfarbenmuster: layer-saturation = Schichtensättigung: layout-export = Belegung exportieren layout-import = Belegung importieren layout-reset = Belegung zurücksetzen loading = Tastatur(en) erkannt. Laden... loading-keyboard = Tastaturbelegung und LEDs für {$keyboard} werden geladen page-electrical = Elektronisch page-keycaps = Tastenkappen page-layer1 = Schicht 1 page-layer2 = Schicht 2 page-layer3 = Schicht 3 page-layer4 = Schicht 4 page-leds = LEDs page-logical = Logisch no-boards = Keine Tastatur erkannt no-boards-msg = Stellen Sie sicher, dass Ihre eingebaute Tastatur die neuste System76 Open Firmware hat. Falls Sie eine externe Tastatur verwenden, stellen Sie sicher, dass diese richtig eingesteckt ist show-help-overlay = Tastaturkürzel stack-keymap = Tastaturbelegung stack-keymap-desc = Wählen Sie eine Taste von der Tastaturbelegung um dessen Einstellungen zu ändern. Shift + Klick um mehrere auszuwählen. Ihre Einstellungen werden automatisch auf der Firmware gespeichert. stack-leds = LEDs stack-leds-desc = Wählen Sie eine Taste von der Tastaturbelegung um dessen Einstellungen zu ändern. Wählen Sie Tastenbezogenes Volltonfarbenmuster um jede Tasten-LED-Farbe einzustellen. Shift + Klick um mehrere auszuwählen. Ihre Einstellungen werden automatisch auf der Firmware gespeichert. stack-leds-desc-builtin = LED-Einstellungen werden sich nach einem Neustart zurücksetzen. Mehr Funktionen folgen in der Zukunft. stack-testing = Testen test-check-pins = Pins überprüfen test-number-of-runs = Anzahl der Durchläufe test-replace-switch = Schalter ersetzen test-serial = Seriell untitled-layout = Unbenannte Schicht ================================================ FILE: i18n/de/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Deaktiviert mode-solid-color = Schichtbezogene Volltonfarbe mode-per-key = Tastenbezogene Volltonfarbe mode-active-keys = Nur gebundene Tasten mode-cycle-all = Kosmischer Hintergrund mode-cycle-left-right = Horizontaler Scan mode-cycle-up-down = Vertikaler Scan mode-cycle-out-in = Ereignishorizont mode-cycle-out-in-dual = Binärgalaxien mode-rainbow-moving-chevron = Raumzeit mode-cycle-pinwheel = Windradgalaxie mode-cycle-spiral = Spiralengalaxie mode-raindrops = Elemente mode-splash = Wasserplatsch mode-multisplash = Meteoritenhagel no-board = Kein Bord ================================================ FILE: i18n/de/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Farbe button-cancel = Abbrechen button-save = Speichern choose-color = Farbe auswählen error-set-color = Tastaturfarbe konnte nicht eingestellt werden error-set-brightness = Tastaturhelligkeit konnte nicht eingestellt werden label-hue = Farbton label-saturation = Sättigung scale-brightness = Helligkeit ================================================ FILE: i18n/en/system76_keyboard_configurator.ftl ================================================ -name = Keyboard Configurator app-about = About {-name} app-title = System76 {-name} board-fake = {$model}, fake button-cancel = Cancel button-configure = Configure Keyboard button-disable = Disable button-import = Import button-test = Test button-start = Start button-stop = Stop error-disable-key = Failed to disable key error-export-keymap = Failed to export keymap error-import-keymap = Failed to import keymap error-key-led = Failed to key LED error-open-file = Failed to open file error-save-leds = Failed to save LEDs error-set-keyboard-brightness = Error setting brightness error-set-keyboard-mode = Error setting keyboard mode error-set-keymap = Failed to set keymap error-set-layer-brightness = Failed to set layer brightness error-set-layer-color = Failed to set layer color error-set-layer-mode = Failed to set layer mode error-unsupported-keymap = Unsupported keymap file error-unsupported-keymap-desc = Keymap file appears to be from newer Configurator version. firmware-version = Firmware version {$version} does not support keymap configuration. keyboard-brightness = Brightness: keyboard-color = Color: key-color = Key Color: keymap-for-board = Keymap is for board '{$model}' layer-all-brightness = Brightness (all layers): layer-animation-speed = Layer Animation Speed: layer-color = Layer Color: layer-color-pattern = Layer Color Pattern: layer-saturation = Layer Saturation: layout-export = Export Layout layout-import = Import Layout layout-reset = Reset Layout layout-invert-f-keys = Invert F Keys flash-to-launch-heavy = Flash to Launch Heavy 1 flash-to-launch-2 = Flash to Launch 2 flash-to-launch-1 = Flash to Launch 1 flash-to-launch-lite-1 = Flash to Launch Lite 1 loading = Keyboard(s) detected. Loading... loading-keyboard = Loading keymap and LEDs for {$keyboard} firmware-update-required = Keyboard Firmware Update Required! page-electrical = Electrical page-keycaps = Keycaps page-layer1 = Layer 1 page-layer2 = Layer 2 page-layer3 = Layer 3 page-layer4 = Layer 4 page-leds = LEDs page-logical = Logical no-boards = No keyboard detected no-boards-msg = Make sure your built-in keyboard has up to date System76 Open Firmware. If using an external keyboard, make sure it is plugged in properly show-help-overlay = Keyboard Shortcuts stack-keymap = Keymap stack-keymap-desc = Select a key on the keymap to change its settings. Shift + click to select more than one click. Your settings are automatically saved to firmware. stack-leds = LEDs stack-leds-desc = Select a key on the keymap to change its settings. Choose per key Solid Pattern to customize each key's LED color. Shift + click to select more than one key. Your settings are automatically saved to firmware. stack-leds-desc-builtin = LED settings will reset after reboot. More functionality is coming in the future. stack-testing = Testing test-check-pins = Check pins (missing) test-check-key = Check key (sticking) test-number-of-runs = Number of runs test-replace-switch = Replace switch test-spurious-keypress = Spurious keypress untitled-layout = Untitled Layout ================================================ FILE: i18n/en/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Disabled mode-solid-color = Per Layer Solid Color mode-per-key = Per Key Solid mode-active-keys = Bound Keys Only mode-cycle-all = Cosmic Background mode-cycle-left-right = Horizontal Scan mode-cycle-up-down = Vertical Scan mode-cycle-out-in = Event Horizon mode-cycle-out-in-dual = Binary Galaxies mode-rainbow-moving-chevron = Spacetime mode-cycle-pinwheel = Pinwheel Galaxy mode-cycle-spiral = Spiral Galaxy mode-raindrops = Elements mode-splash = Splashdown mode-multisplash = Meteor Shower no-board = No board ================================================ FILE: i18n/en/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Color button-cancel = Cancel button-save = Save choose-color = Set Color error-set-color = Failed to set keyboard color error-set-brightness = Failed to set keyboard brightness label-hue = Hue label-saturation = Saturation scale-brightness = Brightness ================================================ FILE: i18n/es/system76_keyboard_configurator.ftl ================================================ -name = Configurador del teclado app-about = Acerca de {-name} app-title = {-name} System76 board-fake = {$model}, falso button-cancel = Cancelar button-configure = Configurar teclado button-disable = Desactivar button-import = Importar button-test = Probar button-start = Empezar button-stop = Parar error-disable-key = Fallo al desactivar la tecla error-export-keymap = Fallo al exportar el mapeo error-import-keymap = Fallo al importar el mapeo error-key-led = Fallo a cambiar el LED de la tecla error-open-file = Fallo al abrir el archivo error-save-leds = Fallo al guardar LEDs error-set-keyboard-brightness = Fallo al cambiar el brillo error-set-keyboard-mode = Fallo al cambiar modo del teclado error-set-keymap = Fallo al cambiar mapeo error-set-layer-brightness = Fallo al cambiar el brillo de la capa error-set-layer-color = Fallo al cambiar el color de la capa error-set-layer-mode = Fallo al cambiar el modo de capa error-unsupported-keymap = Archivo de mapeo no respaldado error-unsupported-keymap-desc = El archivo de mapeo parece ser de una versión más reciente del configurador. firmware-version = La versión de firmware {$version} no respalda la configuración del mapeo de teclas. keyboard-brightness = Brillo: keyboard-color = Color: key-color = Color de la tecla: keymap-for-board = El mapeo es para el '{$model}' layer-all-brightness = Brillo (todas las capas): layer-animation-speed = Velocidad de animación de capa: layer-color = Color de capa: layer-color-pattern = Patrón de color de capa: layer-saturation = Saturación de capa: layout-export = Exportar distribución layout-import = Importar distribución layout-reset = Restablecer distribución layout-invert-f-keys = Invertir teclas F loading = Teclado(s) detectado(s). Cargando... loading-keyboard = Cargando mapeo y LEDs para {$keyboard} page-electrical = Eléctrica page-keycaps = Teclas page-layer1 = Capa 1 page-layer2 = Capa 2 page-layer3 = Capa 3 page-layer4 = Capa 4 page-leds = LEDs page-logical = Lógica no-boards = No se detecta ningún teclado no-boards-msg = Asegurate que tu teclado integrado tiene un Firmware System76 actualizado. Si estás usando un teclado externo, asegúrate que esté conectado correctamente. show-help-overlay = Atajos de teclado stack-keymap = Mapeo stack-keymap-desc = Selecciona una tecla en el mapeo para cambiar su configuración. Haz Shift + Click para seleccionar más de una tecla. Tus cambios se guardan automáticamente al Firmware. stack-leds = LEDs stack-leds-desc = Selecciona una tecla en el mapeo para cambiar su configuración. Elige "Patrón Sólido" en una tecla para cambiar su color de el LED. Haz Shift + Click para seleccionar más de una tecla. Tus cambios se guardan automáticamente al Firmware. stack-leds-desc-builtin = La configuración de las LEDs se restablecerá al reiniciar el PC. Más funcionalidad será añadida en el futuro. stack-testing = Probando test-check-pins = Comprueba los pines test-check-key = Comprueba la tecla test-number-of-runs = Número de ciclos test-replace-switch = Cambia el interruptor de la tecla test-spurious-keypress = Pulsaciones falsas untitled-layout = Distribución sin título ================================================ FILE: i18n/es/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Desabilitado mode-solid-color = Color sólido por capa mode-per-key = Sólido por tecla mode-active-keys = Solo teclas enlazadas mode-cycle-all = Fondo cosmico mode-cycle-left-right = Barrido horizontal mode-cycle-up-down = Barrido vertical mode-cycle-out-in = Horizonte de sucesos mode-cycle-out-in-dual = Galaxias binarias mode-rainbow-moving-chevron = Espacio-tiempo mode-cycle-pinwheel = Galaxia de molinillo mode-cycle-spiral = Galaxia espiral mode-raindrops = Elementos mode-splash = Chapuzón mode-multisplash = Lluvia de meteoritos no-board = Sin placa ================================================ FILE: i18n/es/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Color button-cancel = Cancelar button-save = Guardar choose-color = Escoger un color error-set-color = Fallo al aplicar color del teclado error-set-brightness = Fallo al aplicar brillo del teclado label-hue = Matíz label-saturation = Saturación scale-brightness = Brillo ================================================ FILE: i18n/fi/system76_keyboard_configurator.ftl ================================================ -name = Näppäimistön Konfiguraattori app-about = Tietoa {-name} app-title = System76 {-name} board-fake = {$model}, väärennös button-cancel = Peruuta button-configure = Konfiguroi Näppäimistö button-disable = Ota pois päältä button-import = Tuo button-test = Testaa button-start = Aloita button-stop = Pysäytä error-disable-key = Näppäimistön käytöstä poistaminen epäonnistui error-export-keymap = Keymapin vienti epäonnistui error-import-keymap = Keymapin tuonti epäonnistui error-key-led = Taustavalon asetus epäonnistui error-open-file = Tiedostoa ei pystytty avamaan error-save-leds = Taustavalon talletus epäonnistui error-set-keyboard-brightness = Kirkkauden asetusvirhe error-set-keyboard-mode = Näppäimistötilan asetusvirhe error-set-keymap = Keymapin soveltaminen epäonnistui error-set-layer-brightness = Kerroksen kirkkauden asettaminen epäonnistui error-set-layer-color = Kerroksen värin asettaminen epäonnistui error-set-layer-mode = Kerrostilan asettaminen epäonnistui error-unsupported-keymap = Tätä Keymap-tiedostoa ei tueta error-unsupported-keymap-desc = Tämä Keymap-tiedosto näyttäisi olevan uudemmasta Configurator versiosta. firmware-version = Laiteohjelmistoversio {$version} ei tue Keymap-asetusta. keyboard-brightness = Kirkkaus: keyboard-color = Väri: key-color = Näppäin Väri: keymap-for-board = Keymap on näppäimistölle '{$model}' layer-all-brightness = Kirkkaus (kaikki kerrokset): layer-animation-speed = Kerroksen Animaationopeus: layer-color = Kerroksen Väri: layer-color-pattern = Kerroksen värikuvio: layer-saturation = Kerroksen Kylläisyys: layout-export = Vie Asettelu layout-import = Tuo Asettelu layout-reset = Resetoi Asettelu layout-invert-f-keys = Käännä F-näppäimet flash-to-launch-heavy = Väläytä Käynnistääksesi Launch Heavy 1 flash-to-launch-2 = Väläytä Käynnistääksesi Launch 2 flash-to-launch-1 = Väläytä Käynnistääksesi Launch 1 flash-to-launch-lite-1 = Väläytä Käynnistääksesi Launch Lite 1 loading = Näppäimistö(t) havaittu. Ladataan... loading-keyboard = Ladataan keymap ja taustavalo näppäimistölle {$keyboard} firmware-update-required = Näppäimistön laiteohjelmiston päivitys vaaditaan! page-electrical = Sähköinen page-keycaps = Näppäimet page-layer1 = Kerros 1 page-layer2 = Kerros 2 page-layer3 = Kerros 3 page-layer4 = Kerros 4 page-leds = Taustavalot page-logical = Looginen no-boards = Näppäimistöä ei havaittu no-boards-msg = Varmista, että sisäänrakennetussa näppäimistössä on uusin version System76 Open Firmware -ohjelmistosta. Jos käytät ulkoista näppäimistöä, varmista, että se on liitetty oikein ja, että se on kytketty oikein. show-help-overlay = Pikanäppäimet stack-keymap = Keymap stack-keymap-desc = Valitse näppäin keymapista muuttaaksesi sen asetuksia. Valitse useampi kuin yksi näppäin painamalla ja pitämällä samalla Shift-näppäintä painettuna. Asetuksesi tallentuvat automaattisesti laiteohjelmaan. stack-leds = Taustavalot stack-leds-desc = Valitse näppäin keymapista muuttaaksesi sen asetuksia. Valitse näppäimen yksivärisyys-kuvio säätääksesi kunkin näppäimen taustavalaistusta. Valitse useita näppäimiä pitämällä Shift-näppäintä painettuna. Asetuksesi tallentuvat automaattisesti laiteohjelmaan. stack-leds-desc-builtin = Taustavaloasetukset nollataan uudelleenkäynnistyksen jälkeen. Lisää toimintoja on saatavilla tulevaisuudessa. stack-testing = Testataan test-check-pins = Tarkista pinnit (puuttuu) test-check-key = Tarkista näppäimet (tartutaan) test-number-of-runs = Ajojen määrä test-replace-switch = Vaihda kytkin test-spurious-keypress = Väärä näppäintoiminto untitled-layout = Nimetön Asettelu ================================================ FILE: i18n/fi/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Pois Käytöstä mode-solid-color = Yksivärisyys Per Kerros mode-per-key = Yksivärisyys Per Näppäin mode-active-keys = Vain Aktiiviset Näppäimet mode-cycle-all = Cosmic Tausta mode-cycle-left-right = Horisontaali Skannaus mode-cycle-up-down = Vertikaali Skannaus mode-cycle-out-in = Tapahtumahorisontti mode-cycle-out-in-dual = Binäärigalaksit mode-rainbow-moving-chevron = Aika-avaruus mode-cycle-pinwheel = Pinwheel-Galaksi mode-cycle-spiral = Spiraaligalaksi mode-raindrops = Elementit mode-splash = Splashdown mode-multisplash = Meteorisade no-board = Ei näppäimistöä ================================================ FILE: i18n/fi/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Väri button-cancel = Peruuta button-save = Tallenna choose-color = Aseta Väri error-set-color = Näppäimistön värin asettaminen epäonnistui error-set-brightness = Näppäimistön kirkkauden asettaminen epäonnistui label-hue = Värisävy label-saturation = Kylläisyys scale-brightness = Kirkkaus ================================================ FILE: i18n/fr/system76_keyboard_configurator.ftl ================================================ -name = Configurateur de clavier app-about = À propos du {-name} app-title = System76 {-name} board-fake = {$model}, simulé button-cancel = Annuler button-configure = Configurer ce clavier button-disable = Désactiver button-import = Importer button-test = Vérifier error-disable-key = Échec dans la désactivation de la touche. error-export-keymap = Échec lors de l'exportation du plan de codage. error-import-keymap = Échec lors de l'importation du plan de codage. error-key-led = Échec lors de la configuration de la DEL de la touche. error-open-file = Échec lors de la lecture du fichier. error-save-leds = Échec lors de la sauvegarde des DELs. error-set-keyboard-brightness = Échec lors de la configuration de la luminosité du clavier. error-set-keyboard-mode = Échec lors de la configuration du mode du clavier. error-set-keymap = Échec lors de la configuration du plan de codage. error-set-layer-brightness = Échec lors de la configuration de la luminosité de la couche. error-set-layer-color = Échec lors de la configuration de la couleur de la couche. error-set-layer-mode = Échec lors de la configuration du mode de la couche. error-unsupported-keymap = Fichier contenant le plan de codage incompatible. error-unsupported-keymap-desc = Fichier contenant le plan de codage provient d'une version plus récente du logiciel. key-color = Couleur de la touche: keymap-for-board = Plan de codage pour '{$model}' layer-all-brightness = Luminosité (toutes les couches): layer-animation-speed = Vitesse de l'animation de la couche: layer-color = Couleur de la couche: layer-color-pattern = Patron de couleur de la couche: layer-saturation = Saturation de la couche: layout-export = Exporter la configuration layout-import = Importer la configuration layout-reset = Réinitialiser la configuration loading = Clavier(s) détecté(s). Chargement... loading-keyboard = Chargement du plan de codage et DELs pour {$keyboard} page-electrical = Électrique page-keycaps = Capuchon de touche page-layer1 = Couche 1 page-layer2 = Couche 2 page-layer3 = Couche 3 page-layer4 = Couche 4 page-leds = DELs page-logical = Logique no-boards = Aucun clavier détecté. no-boards-msg = Assurer que le System76 Open Firmware est mis à jour pour un clavier intégré. Avec un clavier externe, assurer qu'il est bien connecté. show-help-overlay = Raccourcis du clavier stack-keymap = Plan de codage stack-keymap-desc = Choisir une touche sur le plan de codage afin de modifier ses paramètres. Les changements seront sauvegardés automatiquement dans le microcode. stack-leds = DELs stack-leds-desc = Choisir une touche sur le plan de codage afin de modifier ses paramètres. La couleur de la touche individuelle est réglée à partir de l'option Solide par touche. La sélection de touches multiple se fait à partir de Shift et clique. Les changements seront sauvegardés automatiquement dans le microcode. stack-testing = Vérification test-check-pins = Vérifier les broches test-number-of-runs = Nombre de cycles test-replace-switch = Remplacé l'interrupteur test-serial = Séquentiel untitled-layout = Disposition sans-titre ================================================ FILE: i18n/fr/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Désactiver mode-solid-color = Couleur solide par couche mode-per-key = Solide par touche mode-active-keys = Touches actives seulement mode-cycle-all = Arrière-plan cosmique mode-cycle-left-right = Balayage horizontal mode-cycle-up-down = Balayage vertical mode-cycle-out-in = Horizon du trou noir mode-cycle-out-in-dual = Galaxies binaires mode-rainbow-moving-chevron = Espace-temps mode-cycle-pinwheel = Galaxie du Moulinet mode-cycle-spiral = Galaxie spirale mode-raindrops = Gouttes d'eau mode-splash = Amerrissage mode-multisplash = Pluie de météores no-board = Aucune carte électronique ================================================ FILE: i18n/fr/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Couleur button-cancel = Annuler button-save = Sauvegarder choose-color = Choisir la couleur error-set-color = Échec lors de la configuration de la couleur du clavier error-set-brightness = Échec lors de la configuration de la luminosité du clavier label-hue = Teinte label-saturation = Saturation scale-brightness = Luminosité ================================================ FILE: i18n/hu/system76_keyboard_configurator.ftl ================================================ -name = Billentyűzet-konfigurátor app-about = A {-name} névjegye app-title = System76 {-name} board-fake = {$model}, hamis button-cancel = Mégse button-configure = Billentyűzet beállítása button-disable = Letiltás button-import = Importálás button-test = Teszt button-start = Indítás button-stop = Leállítás error-disable-key = Nem sikerült letiltani a billentyűt error-export-keymap = Nem sikerült exportálni a billentyűkiosztást error-import-keymap = Nem sikerült importálni a billentyűkiosztást error-key-led = Nem sikerült vezérelni a billentyű LED-jét error-open-file = Nem sikerült megnyitni a fájlt error-save-leds = Nem sikerült elmenteni a LED-beállításokat error-set-keyboard-brightness = Hiba a fényerő beállításakor error-set-keyboard-mode = Hiba a billentyűzet mód beállításakor error-set-keymap = Nem sikerült beállítani a billentyűkiosztást error-set-layer-brightness = Nem sikerült beállítani a réteg fényerejét error-set-layer-color = Nem sikerült beállítani a réteg színét error-set-layer-mode = Nem sikerült beállítani a réteg módját error-unsupported-keymap = Nem támogatott billentyűkiosztás-fájl error-unsupported-keymap-desc = A billentyűkiosztás-fájl úgy tűnik, újabb Konfigurátor-verzióból származik. firmware-version = A(z) {$version} verziószámú firmware nem támogatja a billentyűkiosztás beállítását. keyboard-brightness = Fényerő: keyboard-color = Szín: key-color = Billentyű színe: keymap-for-board = A billentyűkiosztás a(z) '{$model}' modellhez készült layer-all-brightness = Fényerő (minden réteg): layer-animation-speed = Réteg animáció sebessége: layer-color = Réteg színe: layer-color-pattern = Rétegszín minta: layer-saturation = Réteg telítettsége: layout-export = Elrendezés exportálása layout-import = Elrendezés importálása layout-reset = Elrendezés visszaállítása layout-invert-f-keys = F billentyűk invertálása flash-to-launch-heavy = Feltöltés a Launch Heavy 1-re flash-to-launch-2 = Feltöltés a Launch 2-re flash-to-launch-1 = Feltöltés a Launch 1-re flash-to-launch-lite-1 = Feltöltés a Launch Lite 1-re loading = Billentyűzet(ek) észlelve. Betöltés... loading-keyboard = Billentyűkiosztás és LED-ek betöltése: {$keyboard} firmware-update-required = Billentyűzet-firmware frissítés szükséges! page-electrical = Elektromos page-keycaps = Billentyűsapkák page-layer1 = 1. réteg page-layer2 = 2. réteg page-layer3 = 3. réteg page-layer4 = 4. réteg page-leds = LED-ek page-logical = Logikai no-boards = Nincs billentyűzet észlelve no-boards-msg = Győződj meg róla, hogy a beépített billentyűzeten a System76 Open Firmware naprakész. Ha külső billentyűzetet használsz, ellenőrizd, hogy megfelelően csatlakozik show-help-overlay = Billentyűparancsok megjelenítése stack-keymap = Billentyűkiosztás stack-keymap-desc = Válassz ki egy billentyűt a kiosztáson a beállításai módosításához. Shift + kattintással többet is kijelölhetsz. A beállításaid automatikusan elmentődnek a firmware-be. stack-leds = LED-ek stack-leds-desc = Válassz ki egy billentyűt a kiosztáson a beállításaihoz. Válaszd az "Egyedi minta" opciót minden billentyű színének külön-külön testreszabásához. Shift + kattintással több billentyű is kijelölhető. A beállításaid automatikusan elmentődnek a firmware-be. stack-leds-desc-builtin = A LED-beállítások újraindítás után visszaállnak. További funkciók később érkeznek. stack-testing = Tesztelés test-check-pins = Ellenőrizd a csatlakozókat (hiányzik) test-check-key = Ellenőrizd a billentyűt (beragadt) test-number-of-runs = Futások száma test-replace-switch = Cseréld ki a kapcsolót test-spurious-keypress = Véletlenszerű billentyűlenyomás untitled-layout = Névtelen elrendezés ================================================ FILE: i18n/hu/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Letiltva mode-solid-color = Egységes szín rétegenként mode-per-key = Egyedi szín billentyűnként mode-active-keys = Csak hozzárendelt billentyűk mode-cycle-all = Kozmikus háttér mode-cycle-left-right = Vízszintes pásztázás mode-cycle-up-down = Függőleges pásztázás mode-cycle-out-in = Eseményhorizont mode-cycle-out-in-dual = Bináris galaxisok mode-rainbow-moving-chevron = Téridő mode-cycle-pinwheel = Forgó galaxis mode-cycle-spiral = Spirálgalaxis mode-raindrops = Elemi erők mode-splash = Becsapódás mode-multisplash = Meteorzápor no-board = Nincs eszköz ================================================ FILE: i18n/hu/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Szín button-cancel = Mégse button-save = Mentés choose-color = Szín beállítása error-set-color = Nem sikerült beállítani a billentyűzet színét error-set-brightness = Nem sikerült beállítani a billentyűzet fényerejét label-hue = Árnyalat label-saturation = Telítettség scale-brightness = Fényerő ================================================ FILE: i18n/it/system76_keyboard_configurator.ftl ================================================ -name = Configuratore Tastiera app-about = About {-name} app-title = System76 {-name} board-fake = {$model}, falso button-cancel = Annulla button-configure = Configura Tastiera button-disable = Disabilita button-import = Importa button-test = Prova button-start = Inizia button-stop = Termina error-disable-key = Disabilitazione tasto fallita error-export-keymap = Esportazione mappa della tastiera fallita error-import-keymap = Importazione mappa della tastiera fallita error-key-led = Impostazione LED fallita error-open-file = Apertura file fallita error-save-leds = Salvataggio LED fallito error-set-keyboard-brightness = Impostazione luminosità fallita error-set-keyboard-mode = Impostazione modalità tastiera fallita error-set-keymap = Impostazione mappa della tastiera fallita error-set-layer-brightness = Impostazione luminosità livello fallita error-set-layer-color = Impostazione colore livello fallita error-set-layer-mode = Impostazione modalità a livelli fallita error-unsupported-keymap = File mappa della tastiera non supportato error-unsupported-keymap-desc = Il file mappa della tastiera sembra provenire da una nuova versione del Configuratore. firmware-version = La versione {$version} del firmware non supporta la configurazione della mappa della tastiera. keyboard-brightness = Luminosità: keyboard-color = Colore: key-color = Colore Tasto: keymap-for-board = La mappa della tastiera è per il modello '{$model}' layer-all-brightness = Luminosità (tutti i livelli): layer-animation-speed = Velocità Animazione Livello: layer-color = Colore Livello: layer-color-pattern = Modello Colore Livello: layer-saturation = Saturazione Livello: layout-export = Esporta Disposizione layout-import = Importa Disposizione layout-reset = Ripristina Disposizione layout-invert-f-keys = Inverti Tasti F flash-to-launch-heavy = Flash to Launch Heavy 1 flash-to-launch-2 = Flash to Launch 2 flash-to-launch-1 = Flash to Launch 1 flash-to-launch-lite-1 = Flash to Launch Lite 1 loading = Tastiera rilevata. Caricamento... loading-keyboard = Caricamento mappa della tastiera e LED per {$keyboard} firmware-update-required = È necessario aggiornare il firmware della tastiera! page-electrical = Elettrica page-keycaps = Copritasti page-layer1 = Livello 1 page-layer2 = Livello 2 page-layer3 = Livello 3 page-layer4 = Livello 4 page-leds = LED page-logical = Logica no-boards = Nessuna tastiera rilevata no-boards-msg = Assicurarsi di che la tastiera integrata abbia l'ultima versione dell'Open Firmware System76. Se si sta utilizzando una tastiera esterna, assicurarsi che sia connessa correttamente show-help-overlay = Scorciatoie Tastiera stack-keymap = Mappa tastiera stack-keymap-desc = Seleziona un tasto sulla mappa per cambiare le sue impostazioni. Maiusc + click per selezionarne più di uno. Le tue impostazioni sono salvate automaticamente sul firmware. stack-leds = LED stack-leds-desc = Seleziona un tasto sulla mappa per cambiare le sue impostazioni. Scegli una tinta unica per modello, per personalizzare il colore del LED per ogni tasto. Maiusc + click per selezionarne più di uno. Le tue impostazioni sono salvate automaticamente sul firmware. stack-leds-desc-builtin = Le impostazioni dei LED saranno ripristinate dopo il riavvio. In futuro arriveranno altre funzionalità. stack-testing = Testing test-check-pins = Controlla perno (mancante) test-check-key = Controlla tasto (aderenza) test-number-of-runs = Numero di esecuzioni test-replace-switch = Sostituisci tasto test-spurious-keypress = Pressione spuria del tasto untitled-layout = Layout Senza Titolo ================================================ FILE: i18n/it/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Disabilitato mode-solid-color = Tinta Unita Per Strato mode-per-key = Colore Per Tasto mode-active-keys = Solo Tasti Vincolati mode-cycle-all = Background Cosmic mode-cycle-left-right = Scansione Orizzontale mode-cycle-up-down = Scansione Verticale mode-cycle-out-in = Orizzonte Degli Eventi mode-cycle-out-in-dual = Galassie Binarie mode-rainbow-moving-chevron = Spaziotempo mode-cycle-pinwheel = Galassia Girandola mode-cycle-spiral = Galassia Spirale mode-raindrops = Elementi mode-splash = Splashdown mode-multisplash = Pioggia Di Meteore no-board = Nessuna tavola ================================================ FILE: i18n/it/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Colore button-cancel = Annulla button-save = Salva choose-color = Imposta Colore error-set-color = Impostazione colore della tastiera fallito error-set-brightness = Impostazione luminosità della tastiera fallito label-hue = Tonalità label-saturation = Saturazione scale-brightness = Luminosità ================================================ FILE: i18n/ko/system76_keyboard_configurator.ftl ================================================ -name = 키보드 설정기 app-about = {-name} 정보 app-title = System76 {-name} board-fake = {$model}, fake button-cancel = 취소 button-configure = 키보드 설정 button-disable = 비활성화 button-import = 가져오기 button-test = 테스트 button-start = 시작 button-stop = 중지 error-disable-key = 키를 비활성화하지 못했습니다. error-export-keymap = 키맵을 내보내지 못했습니다. error-import-keymap = 키맵을 가져오지 못했습니다. error-key-led = LED 키에 실패 했습니다. error-open-file = 파일을 열지 못했습니다. error-save-leds = LED(들)를 저장하지 못했습니다. error-set-keyboard-brightness = 밝기 설정에 실패하였습니다. error-set-keyboard-mode = 키보드 모드 설정에 실패하였습니다. error-set-keymap = 키맵 저장에 실패하였습니다. error-set-layer-brightness = 레이어 밝기 설정에 실패하였습니다. error-set-layer-color = 색상 레이어 설정에 실패하였습니다. error-set-layer-mode = 레이어 모드 설정에 실패하였습니다. error-unsupported-keymap = 지원하지 않는 키맵 파일입니다. error-unsupported-keymap-desc = 키맵 파일이 신규 설정 버젼인것 같습니다. firmware-version = 펌웨어 버젼 {$version} 이 키맵 구성을 지원하지 않습니다. keyboard-brightness = 밝기: keyboard-color = 색상: key-color = 키 색상: keymap-for-board = 캐맵은 보드 '{$model}' 전용입니다. layer-all-brightness = 밝기 (모든 레이어): layer-animation-speed = 레이어 에니메이션 속도: layer-color = 레이어 색상: layer-color-pattern = 레이어 색상 패턴: layer-saturation = 레이어 채도: layout-export = 레이어 내보내기 layout-import = 레이어 가져오기 layout-reset = 레이아웃 재설정 layout-invert-f-keys = 펑션키(F-key) 반전 flash-to-launch-heavy = Flash to Launch Heavy 1 flash-to-launch-2 = Flash to Launch 2 flash-to-launch-1 = Flash to Launch 1 flash-to-launch-lite-1 = Flash to Launch Lite 1 loading = 키보드(들)가 인식되었습니다. 로딩중... loading-keyboard = {$keyboard}에 대한 키맵 및 LED 로딩중 firmware-update-required = 키보드 펌웨어 업데이트 필요! page-electrical = Electrical page-keycaps = 키캡 page-layer1 = 레이어 1 page-layer2 = 레이어 2 page-layer3 = 레이어 3 page-layer4 = 레이어 4 page-leds = LEDs page-logical = Logical no-boards = 키보드 인식 실패 no-boards-msg = 키보드가 최신 버젼인지 확인해주세요. System76에서 펌웨어를 확인해주세요. 만약 외장 키보드를 사용하는 경우, 연결에 문제가 있는지 확인해주세요. show-help-overlay = 키보드 단축기 stack-keymap = 키맵 stack-keymap-desc = 설정을 변경하기 위해 키맵에서 키를 선택하세요. Shift + Click 으로 여러개의 키를 선택할 수 있습니다. 설정은 자동으로 펌웨어에 저장됩니다. stack-leds = LEDs stack-leds-desc = 설정을 변경하기 위해 키맵에서 키를 선택하세요. 각 키에 LED 색상을 설정하기 위해 원하는 색상을 선택하세요. Shift + Click 으로 여러개의 키를 선택할 수 있습니다. 설정은 자동으로 펌웨어에 저장됩니다. stack-leds-desc-builtin = LED 설정은 재부팅 후 초기화됩니다. 햫후 더 많은 기능이 추가될 예정입니다. stack-testing = 테스트 test-check-pins = 핀 확인 (missing) test-check-key = 키 확인 (sticking) test-number-of-runs = 실행 횟수 test-replace-switch = 스위치 교체 test-spurious-keypress = 가짜 키 눌림 untitled-layout = 제목없는 레이아웃 ================================================ FILE: i18n/ko/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = 비활성화 mode-solid-color = 레이어 단위 고정 mode-per-key = 키 단위 고정 mode-active-keys = 지정 키 전용 mode-cycle-all = 코스믹 배경 mode-cycle-left-right = 수평 스캔 mode-cycle-up-down = 수직 스캔 mode-cycle-out-in = 이벤트 호라이즌 mode-cycle-out-in-dual = 바이너리 겔럭시 mode-rainbow-moving-chevron = 시공간 mode-cycle-pinwheel = 바람개비 은하 mode-cycle-spiral = 나선형 은하 mode-raindrops = 엘리먼트 mode-splash = 스플래시 다운 mode-multisplash = 유성우 no-board = 보드 없음 ================================================ FILE: i18n/ko/system76_keyboard_configurator_widgets.ftl ================================================ button-color = 색상 button-cancel = 취소 button-save = 저장 choose-color = 색상 선택 error-set-color = 키보드 색상 설정 실패 error-set-brightness = 키보드 밝기 설정 실패 label-hue = 색조 label-saturation = 채도 scale-brightness = 밝기 ================================================ FILE: i18n/nl/system76_keyboard_configurator.ftl ================================================ -name = Toetsenbordconfigurator app-about = Over {-name} app-title = System76 - {-name} board-fake = {$model}, namaak button-cancel = Annuleren button-configure = Toetsenbord instellen button-disable = Uitschakelen button-import = Importeren button-test = Testen button-start = Start button-stop = Stop error-disable-key = Kon deze toets niet uitschakelen error-export-keymap = Kon de indeling niet exporteren error-import-keymap = Kon de indeling niet importeren error-key-led = Kon gedrag van de led niet aanpassen error-open-file = Kon bestand niet openen error-save-leds = Kon ledinstellingen niet opslaan error-set-keyboard-brightness = Kon toetsenbordhelderheid niet aanpassen error-set-keyboard-mode = Kon toetsenbordmodus niet instellen error-set-keymap = Kon toetsenbordindeling niet instellen error-set-layer-brightness = Kon helderheidslaag niet instellen error-set-layer-color = Kon kleurlaag niet instellen error-set-layer-mode = Kon toetsenbordfunctielaag niet instellen error-unsupported-keymap = Toetsenbordindelingsbestand wordt niet ondersteund error-unsupported-keymap-desc = Dit bestand lijkt afkomstig te zijn van een nieuwere versie van Toetsenbordconfigurator. firmware-version = Versie {$version} van de firmware heeft geen ondersteuning voor deze instellingen. keyboard-brightness = Helderheid: keyboard-color = Kleur: key-color = Toetskleur: keymap-for-board = Deze indeling is gemaakt voor '{$model}' layer-all-brightness = Helderheid (alle lagen): layer-animation-speed = Animatiesnelheid van laag: layer-color = Laagkleur: layer-color-pattern = Kleurpatroon van laag: layer-saturation = Laagverzadiging: layout-export = Indeling exporteren layout-import = Indeling importeren layout-reset = Standaardwaarden layout-invert-f-keys = Primair gedrag functietoetsen omwisselen flash-to-launch-heavy = Firmware flashen voor Launch Heavy 1 flash-to-launch-2 = Firmware flashen voor Launch 2 flash-to-launch-1 = Firmware flashen voor Launch 1 flash-to-launch-lite-1 = Firmware flashen voor Launch Lite 1 loading = Toetsenbord(en) aangetroffen. Bezig met laden... loading-keyboard = Indelingen en ledconfiguraties van {$keyboard} worden geladen page-electrical = Elektrisch page-keycaps = Toetsenkapjes page-layer1 = Laag 1 page-layer2 = Laag 2 page-layer3 = Laag 3 page-layer4 = Laag 4 page-leds = Ledverlichting page-logical = Logisch no-boards = Er is geen toetsenbord aangetroffen no-boards-msg = Zorg er voor dat uw ingebouwde toetsenbord beschikt over de nieuwste System76 Open Firmware. Als u gebruikmaakt van een extern toetsenbord, zorg er dan voor dat het toetsenbord goed is aangesloten. show-help-overlay = Sneltoetsen stack-keymap = Toetsindeling stack-keymap-desc = Selecteer een toets op de toetsindeling om de instellingen ervan te wijzigen. Shift + klik om meerdere toetsen tegelijk te selecteren. De instellingen worden automatisch opgeslagen in de firmware. stack-leds = Ledverlichting stack-leds-desc = Selecteer een toets op de toetsindeling om de instellingen ervan te wijzigen. Kies per toets een vast kleurpatroon om zo de ledkleuren aan te passen. Shift + klik om meerdere toetsen tegelijk te selecteren. De instellingen worden automatisch opgeslagen in de firmware. stack-leds-desc-builtin = Opmerking: uw aanpassingen aan de ledverlichting worden na het opnieuw opstarten van uw computer gereset. Meer functionaliteit komt in de toekomst. stack-testing = Testen test-check-pins = Check missende pinnen test-check-key = Check vastzittende toetsen test-number-of-runs = Aantal checks achter elkaar test-replace-switch = Check te vervangen schakelmechanismen test-spurious-keypress = Check spontane toetsdrukken untitled-layout = Naamloze indeling ================================================ FILE: i18n/nl/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Uitgeschakeld mode-solid-color = Vaste kleur per laag mode-per-key = Vaste kleur per toets mode-active-keys = Alleen toegewezen toetsen mode-cycle-all = Kosmische achtergrond mode-cycle-left-right = Horizontale scan mode-cycle-up-down = Verticale scan mode-cycle-out-in = Waarnemingshorizon mode-cycle-out-in-dual = Binaire sterrenstelsels mode-rainbow-moving-chevron = Ruimtetijd mode-cycle-pinwheel = Windmolenstelsel mode-cycle-spiral = Spiraalvormig sterrenstelsel mode-raindrops = Elementen mode-splash = Waterlanding mode-multisplash = Meteorenzwerm no-board = Geen toetsenbord ================================================ FILE: i18n/nl/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Kleur button-cancel = Annuleren button-save = Opslaan choose-color = Kleur instellen error-set-color = De kleur kan niet worden ingesteld error-set-brightness = De helderheid kan niet worden ingesteld label-hue = Tint label-saturation = Verzadiging scale-brightness = Helderheid ================================================ FILE: i18n/pl/system76_keyboard_configurator.ftl ================================================ -name = Konfiguracja Klawiatury app-about = Na temat {-name} app-title = System76 {-name} board-fake = {$model}, imitacja button-cancel = Anuluj button-configure = Konfiguruj Klawiaturę button-disable = Blokuj button-import = Importuj button-test = Testuj error-disable-key = Błąd blokowania przycisku error-export-keymap = Błąd eksportowania mapowania klawiszy error-import-keymap = Błąd importowania mapowania klawiszy error-key-led = Błąd ustawienia klawisza LED error-open-file = Błąd otwierania pliku error-save-leds = Błąd zapisu ustawień LED error-set-keyboard-brightness = Błąd ustawienia jasności klawiatury error-set-keyboard-mode = Błąd ustawienia trybu klawiatury error-set-keymap = Błąd ustawienia mapowania klawiszy error-set-layer-brightness = Błąd ustawienia jasności warstwy error-set-layer-color = Błąd ustawienia koloru warstwy error-set-layer-mode = Błąd ustawienia trybu warstwy error-unsupported-keymap = Plik mapowania klawiszy nie jest obsługiwany error-unsupported-keymap-desc = Plik mapowania klawiszy może pochodzić z nowszej wersji Konfiguracji. key-color = Kolor klawisza: keymap-for-board = Mapowanie klawisza dla klawiatury '{$model}' layer-all-brightness = Jasność (wszystkie warstwy): layer-animation-speed = Szybkość Animacji Warstwy: layer-color = Kolor Warstwy: layer-color-pattern = Wzór Koloru Warstwy: layer-saturation = Nasycenie Warstwy: layout-export = Eksportuj Układ layout-import = Importuj Układ layout-reset = Zresetuj Układ loading = Klawiatura(-ry) wykryta. Ładowanie... loading-keyboard = Ładowanie mapowania klawiszy i LED dla {$keyboard} page-electrical = Elektryczny page-keycaps = Klawisze klawiatury page-layer1 = Warstwa 1 page-layer2 = Warstwa 2 page-layer3 = Warstwa 3 page-layer4 = Warstwa 4 page-leds = LED page-logical = Logiczny no-boards = Nie wykryto klawiatury no-boards-msg = Upewnij się, że twoja wbudowana klawiatura ma aktualne oprogramowanie System76. Jeśli używasz zewnętrznej klawiatury upewnij się, że jest poprawnie podłączona. show-help-overlay = Skróty klawiszowe klawiatury stack-keymap = Mapowanie klawiatury stack-keymap-desc = Wybierz klawisz w mapowaniu klawiatury aby zmienić jego ustawienia. Twoje ustawienia są automatyczne zapisywane w oprogramowaniu. stack-leds = LED stack-leds-desc = Wybierz klawisz w mapowaniu klawiatury aby zmienić jego ustawienia. Wybierz Jednolity Wzór aby zmienić kolor LED dla każdego pojedyńczego klawisza. Shift + kliknij aby zaznaczyć więcej niż jeden przycisk. Twoje ustawienia są automatyczne zapisywane w oprogramowaniu. stack-testing = Testowanie test-check-pins = Sprawdź złącza test-number-of-runs = Ilość prób testowych test-replace-switch = Zamień przełącznik test-serial = Numer seryjny untitled-layout = Układ Bez Tytułu ================================================ FILE: i18n/pl/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Zablokowany mode-solid-color = Jednolity Kolor na warstwę mode-per-key = Jednolity Kolor na klawisz mode-active-keys = Tylko Powiązane Klawisze mode-cycle-all = Tło Kosmiczne mode-cycle-left-right = Skan Horyzontalny mode-cycle-up-down = Skan Wertykalny mode-cycle-out-in = Horyzont Zdarzeń mode-cycle-out-in-dual = Podwójne Galaktyki mode-rainbow-moving-chevron = Czasoprzestrzeń mode-cycle-pinwheel = Galaktyka Wiatraczek mode-cycle-spiral = Galaktyka Spiralna mode-raindrops = Elementy mode-splash = Wodowanie mode-multisplash = Deszcz Meteorytów no-board = Brak klawiatury ================================================ FILE: i18n/pl/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Kolor button-cancel = Anuluj button-save = Zapisz choose-color = Ustaw Kolor error-set-color = Błąd ustawienia koloru klawiatury error-set-brightness = Błąd ustawienia jasności klawiatury label-hue = Odcień label-saturation = Nasycenie scale-brightness = Jasność ================================================ FILE: i18n/pt-BR/system76_keyboard_configurator.ftl ================================================ -name = Configurador do Teclado app-about = Sobre {-name} app-title = System76 {-name} board-fake = {$model}, falso button-cancel = Cancelar button-configure = Configurar Teclado button-disable = Desabilitar button-import = Importar button-test = Testar button-start = Iniciar button-stop = Parar error-disable-key = Falha ao desabilitar tecla error-export-keymap = Falha ao exportar mapa do teclado error-import-keymap = Falha ao importar mapa do teclado error-key-led = Falha no LED da tecla error-open-file = Falha ao abrir arquivo error-save-leds = Falha ao salvar LEDs error-set-keyboard-brightness = Erro ao configurar brilho error-set-keyboard-mode = Erro ao configurar modo do teclado error-set-keymap = Falha ao definir mapa do teclado error-set-layer-brightness = Falha ao definir brilho da camada error-set-layer-color = Falha ao definir cor da camada error-set-layer-mode = Falha ao definir modo da camada error-unsupported-keymap = Arquivo do mapa do teclado não suportado error-unsupported-keymap-desc = Arquivo do mapa do teclado aparenta ser de uma versão mais recente do Configurador do Teclado. firmware-version = Versão de Firmware {$version} não suporta a configuração do mapa do teclado. keyboard-brightness = Brilho: keyboard-color = Cor: key-color = Cor da tecla: keymap-for-board = Mapa do teclado é para a placa '{$model}' layer-all-brightness = Brilho (tadas camadas): layer-animation-speed = Velociade da Animação da Camada: layer-color = Cor da Camada: layer-color-pattern = Padrão de Cor da Camada: layer-saturation = Saturação da Camada: layout-export = Exportar Layout layout-import = Importar Layout layout-reset = Restaurar Layout layout-invert-f-keys = Inverter Teclas F loading = Teclado(s) detectado(s). Carregando... loading-keyboard = Carregando mapa do teclado e LEDs para {$keyboard} page-electrical = Elétrico page-keycaps = Keycaps page-layer1 = Camada 1 page-layer2 = Camada 2 page-layer3 = Camada 3 page-layer4 = Camada 4 page-leds = LEDs page-logical = Lógico no-boards = Nenhum teclado detectado no-boards-msg = Certifique-se que seu teclado integrado possui atualizado System76 Open Firmware. Se estiver usando um teclado externo, certifique-se que ele está conectado adequadamente show-help-overlay = Atalhos do Teclado stack-keymap = Mapa do Teclado stack-keymap-desc = Selecione a tecla no mapa do teclado para alterar as suas configurações. Shift + clique para selecionar mais de um clique. Suas configurações são salvas automaticamente no firmware. stack-leds = LEDs stack-leds-desc = Selecione a tecla no mapa do teclado para alterar as suas configurações. Escolha um Padrão Sólido para customizar a cor do LED de cada tecla. Shift + clique para selecionar mais de uma tecla. Suas configurações são salvas automaticamente no firmware. stack-leds-desc-builtin = As configurações de LED irão ser restauradas depois de reiniciar. Mais funcionalidades estarão vindo no futuro. stack-testing = Testando test-check-pins = Verifique os pinos test-number-of-runs = Número de tentativas test-replace-switch = Substitua o switch test-serial = Serial test-spurious-keypress = Teclagens não genuínas untitled-layout = Layout sem título ================================================ FILE: i18n/pt-BR/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Desabilitado mode-solid-color = Cor Sólida por Camada mode-per-key = Sólido por Tecla mode-active-keys = Vincular Apenas Teclas mode-cycle-all = Fundo Cósmico mode-cycle-left-right = Varredura Horizontal mode-cycle-up-down = Varredura Vertical mode-cycle-out-in = Horizonte de Eventos mode-cycle-out-in-dual = Galáxias Binárias mode-rainbow-moving-chevron = Tempo no espaço mode-cycle-pinwheel = Galáxia Cata-Vento mode-cycle-spiral = Galáxia Espiral mode-raindrops = Gotas mode-splash = Amaragem mode-multisplash = Chuva de Meteóros no-board = Sem placa ================================================ FILE: i18n/pt-BR/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Cor button-cancel = Cancelar button-save = Salvar choose-color = Definir Cor error-set-color = Falha ao definir a cor do teclado error-set-brightness = Falha ao definir o brilho do teclado label-hue = Matiz label-saturation = Saturação scale-brightness = Brilho ================================================ FILE: i18n/ru/system76_keyboard_configurator.ftl ================================================ -name = Конфигуратор клавиатуры app-about = О программе {-name} app-title = {-name} System76 board-fake = {$model}, подделка button-cancel = Отменить button-configure = Настроить клавиатуру button-disable = Отключить button-import = Импорт button-test = Тест button-start = Начать button-stop = Стоп error-disable-key = Не удалось отключить клавишу error-export-keymap = Не удалось экспортировать раскладку error-import-keymap = Не удалось импортировать раскладку error-key-led = Не удалось установить подсветку error-open-file = Не удалось открыть файл error-save-leds = Не удалось сохранить подсветку error-set-keyboard-brightness = Ошибка установки яркости error-set-keyboard-mode = Ошибка установки режима клавиатуры error-set-keymap = Не удалось применить раскладку error-set-layer-brightness = Не удалось установить яркость слоя error-set-layer-color = Не удалось установить цвет слоя error-set-layer-mode = Не удалось установить режим слоя error-unsupported-keymap = Неподдерживаемый файл карты клавиш error-unsupported-keymap-desc = Похоже, это файл раскладки для более новой версии Конфигуратора. firmware-version = Версия прошивки {$version} не поддерживает настройку раскладки. keyboard-brightness = Яркость: keyboard-color = Цвет: key-color = Цвет клавиши: keymap-for-board = Раскладка для клавиатуры '{$model}' layer-all-brightness = Яркость (все слои): layer-animation-speed = Скорость анимации слоя: layer-color = Цвет слоя: layer-color-pattern = Цветовая схема слоя: layer-saturation = Насыщенность слоя: layout-export = Экспортировать раскладку layout-import = Импортировать раскладку layout-reset = Сбросить раскладку layout-invert-f-keys = Инвертировать F-клавиши flash-to-launch-heavy = Прошить на Launch Heavy 1 flash-to-launch-2 = Прошить на Launch 2 flash-to-launch-1 = Прошить на Launch 1 flash-to-launch-lite-1 = Прошить на Launch Lite 1 loading = Клавиатур(ы) обнаружен(ы). Загрузка... loading-keyboard = Загрузка раскладки и подсветки для {$keyboard} firmware-update-required = Требуется обновление прошивки клавиатуры! page-electrical = Электрика page-keycaps = Кейкапы page-layer1 = Слой 1 page-layer2 = Слой 2 page-layer3 = Слой 3 page-layer4 = Слой 4 page-leds = Подсветка page-logical = Логика no-boards = Клавиатура не обнаружена no-boards-msg = Убедитесь, что встроенная клавиатура имеет актуальную версию System76 Open Firmware. Если используется внешняя клавиатура, убедитесь, что она правильно подключена. show-help-overlay = Сочетания клавиш stack-keymap = Раскладка stack-keymap-desc = Выберите клавишу на схеме, чтобы изменить её настройки. Нажимайте, удерживая Shift, чтобы выбрать несколько клавиш. Ваши настройки будет автоматически сохранены в прошивке. stack-leds = Подсветка stack-leds-desc = Выберите клавишу на схеме, чтобы изменить её настройки. Выберите схему 'Сплошной цвет, поклавишно', чтобы настроить подсветку каждой клавиши. Нажимайте, удерживая Shift, чтобы выбрать несколько клавиш. Ваши настройки будет автоматически сохранены в прошивке. stack-leds-desc-builtin = Настройки подсветки будут сброшены после перезагрузки. В будущем планируется расширение функциональности. В будущем появится больше функций. stack-testing = Тестирование test-check-pins = Проверка пинов (отсутствие) test-check-key = Проверка клавиш (залипание) test-number-of-runs = Количество прогонов test-replace-switch = Замените переключатель test-spurious-keypress = Ложное срабатывание клавиши untitled-layout = Безымянная раскладка ================================================ FILE: i18n/ru/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Нет mode-solid-color = Сплошной цвет, послойно mode-per-key = Сплошной цвет, поклавишно mode-active-keys = Только активные клавиши mode-cycle-all = Космический фон mode-cycle-left-right = Горизонтальная развёртка mode-cycle-up-down = Вертикальная развёртка mode-cycle-out-in = Горизонт событий mode-cycle-out-in-dual = Двойная галактика mode-rainbow-moving-chevron = Пространство-время mode-cycle-pinwheel = Галактика Вертушка mode-cycle-spiral = Спиральная галактика mode-raindrops = Частицы mode-splash = Приводнение mode-multisplash = Метеоритный дождь no-board = Нет клавиатуры ================================================ FILE: i18n/ru/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Цвет button-cancel = Отменить button-save = Сохранить choose-color = Выберите цвет error-set-color = Не удалось установить цвет клавиатуры error-set-brightness = Не удалось установить яркость клавиатуры label-hue = Оттенок label-saturation = Насыщенность scale-brightness = Яркость ================================================ FILE: i18n/sl/system76_keyboard_configurator.ftl ================================================ -name = Keyboard Configurator app-about = O {-name} app-title = System76 {-name} board-fake = {$model}, lažen button-cancel = Prekliči button-configure = Nastavi tipkovnico button-disable = Izklopi button-import = Uvozi button-test = Testiraj error-disable-key = Tipke ni bilo mogoče onemogočiti error-export-keymap = Mape tipk ni bilo mogoče izvoziti error-import-keymap = Mape tipk ni bilo mogoče uvoziti error-key-led = LED ni uspelo vklopiti error-open-file = Datoteke ni bilo mogoče odpreti error-save-leds = LED diod ni bilo mogoče shraniti error-set-keyboard-brightness = Napaka pri nastavitvi svetlosti error-set-keyboard-mode = Napaka pri nastavitvi načina tipkovnice error-set-keymap = Ni bilo mogoče nastaviti mape tipk error-set-layer-brightness = Ni bilo mogoče nastaviti svetlosti plasti error-set-layer-color = Barve sloja ni bilo mogoče nastaviti error-set-layer-mode = Ni bilo mogoče nastaviti načina sloja error-unsupported-keymap = Nepodprta datoteka z zemljevidi tipk error-unsupported-keymap-desc = Zdi se, da je datoteka tipkovnice iz novejše različice programa Configurator. firmware-version = Različica vdelane programske opreme {$version} ne podpira konfiguracije tipkovnice. keyboard-brightness = Svetlost: keyboard-color = Barva: key-color = Barva tipke: keymap-for-board = Mapa tipk je za ploščo '{$model}' layer-all-brightness = Svetlost (vsi sloji): layer-animation-speed = Hitrost animacije sloja: layer-color = Barva sloja: layer-color-pattern = Barvni vzorec sloja: layer-saturation = Nasičenost plasti: layout-export = Izvozi postavitev layout-import = Uvozi postavitev layout-reset = Ponastavi postavitev loading = Tipkovnica/-e zaznana/-e. Nalaganje... loading-keyboard = Nalaganje mape tipk in LED za {$keyboard} page-electrical = Električna page-keycaps = Tipke page-layer1 = Plast 1 page-layer2 = Plast 2 page-layer3 = Plast 3 page-layer4 = Plast 4 page-leds = LED diode page-logical = Logična no-boards = Tipkovnica ni zaznana no-boards-msg = Prepričajte se, da ima vgrajena tipkovnica posodobljeno System76 Odprto vdelano programsko opremo. Če uporabljate zunanjo tipkovnico, se prepričajte, da je pravilno priključena show-help-overlay = Bližnjice na tipkovnici stack-keymap = Mapa tipk stack-keymap-desc = Izberite tipko na mapi tipk, da spremenite njene nastavitve. Shift + klik, da izberete več kot en klik. Vaše nastavitve se samodejno shranijo v vdelano programsko opremo. stack-leds = LED diode stack-leds-desc = Izberite tipko na mapi tipk, da spremenite njene nastavitve. Za vsako tipko izberite Solid Pattern, da prilagodite barvo LED posamezne tipke. Shift + klik, da izberete več kot eno tipko. Vaše nastavitve se samodejno shranijo v vdelano programsko opremo. stack-leds-desc-builtin = Nastavitve LED se bodo ponastavile po ponovnem zagonu. V prihodnosti bo na voljo več funkcionalnosti. stack-testing = Testiranje test-check-pins = Preverite zatiči test-number-of-runs = Število tekov test-replace-switch = Zamenjajte stikalo test-serial = Serijski untitled-layout = Neimenovana postavitev ================================================ FILE: i18n/sl/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Izklopljeno mode-solid-color = Na plast enobarvna mode-per-key = Na tipko trdno mode-active-keys = Samo vezane tipke mode-cycle-all = Kozmično ozadje mode-cycle-left-right = Vodoravno skeniranje mode-cycle-up-down = Navpično skeniranje mode-cycle-out-in = Obzorje dogodkov mode-cycle-out-in-dual = Binarne galaksije mode-rainbow-moving-chevron = Vesolje-čas mode-cycle-pinwheel = Galaksija vrtiljaka mode-cycle-spiral = Spiralna galaksija mode-raindrops = Elementi mode-splash = Pljusk dol mode-multisplash = Meteorni dež no-board = Brez plošče ================================================ FILE: i18n/sl/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Barva button-cancel = Prekliči button-save = Shrani choose-color = Nastavi barvo error-set-color = Ni uspelo nastaviti barve tipkovnice error-set-brightness = Ni uspelo nastaviti svetlost tipkovnice label-hue = Odtenek label-saturation = Nasičenost scale-brightness = Svetlost ================================================ FILE: i18n/tr/system76_keyboard_configurator.ftl ================================================ -name = Klavye Yapılandırıcısı app-about = {-name} Hakkında app-title = System76 {-name} board-fake = {$model}, sahte button-cancel = İptal button-configure = Klavyeyi Yapılandır button-disable = Etkisizleştir button-import = İçeri Aktar button-test = Test error-disable-key = Tuşu etkisizleştirmek başarısız oldu error-export-keymap = Tuş haritasını dışarı aktarmak başarısız oldu error-import-keymap = Tuş haritasını içeri aktarmak başarısız oldu error-key-led = Tuş LED'i hatalı error-open-file = Dosya açılamadı error-save-leds = LED'ler kaydedilemedi error-set-keyboard-brightness = Parlaklık değeri atanamadı error-set-keyboard-mode = Klavye modu atanamadı error-set-keymap = Tuş haritası atanamadı error-set-layer-brightness = Katman parlaklığı atanamadı error-set-layer-color = Katman rengi atanamadı error-set-layer-mode = Katman modu atanamadı error-unsupported-keymap = Tuş haritası dosyası desteklenmiyor error-unsupported-keymap-desc = Tuş haritası dosyası daha yeni bir yapılandırıcıya ait. firmware-version = Aygıt yazılımı {$version} tuş haritası yapılandırmasını desteklemiyor. keyboard-brightness = Parlaklık: keyboard-color = Renk: key-color = Tuş Rengi: keymap-for-board = Tuş haritası şu kart modeline ait '{$model}' layer-all-brightness = Parlaklık (tüm katmanlar): layer-animation-speed = Katman Animasyon Hızı: layer-color = Katman Rengi: layer-color-pattern = Katman Rengi Deseni: layer-saturation = Katman Doygunluğu: layout-export = Düzeni Dışarı Aktar layout-import = Düzeni İçeri Aktar layout-reset = Düzeni Sıfırla loading = Klavye(ler) tanımlandı. Yükleniyor... loading-keyboard = Tuş haritası ve {$keyboard} için LED ayarları yükleniyor page-electrical = Elektronik page-keycaps = Tuş başlıkları page-layer1 = Katman 1 page-layer2 = Katman 2 page-layer3 = Katman 3 page-layer4 = Katman 4 page-leds = LEDler page-logical = Mantıksal no-boards = Hiç bir klavye tanımlanamadı no-boards-msg = Dahili klavyenizin güncel System76 aygıt yazılımına sahip olduğundan emin olun. Eğer harici bir klavye kullanıyorsanız, doğru şekilde takılı olduğundan emin olun. show-help-overlay = Klavye Kısayolları stack-keymap = Tuş haritası stack-keymap-desc = Ayarlarını değiştirmek için tuş haritasından bir tuş seçin. Birden fazla seçmek için Shift tuşunu kullanabilirsiniz. Ayarlarınız otomatik olarak aygıt yazılımına kaydedilir. stack-leds = LEDler stack-leds-desc = Ayarlarını değiştirmek içiin tuş haritasından bir tuş seçin. Tuşların LED rengini değiştirmek için tuş başına tek parça desen seçilmeli. Birden fazla seçmek için Shift tuşunu kullanabilirsiniz. Ayarlarınız otomatik olarak aygıt yazılımına kaydedilir. stack-leds-desc-builtin = Bilgisayar tekrar başlayınca LED ayarları sıfırlanacak. Yakında daha fazla özellik gelecek. stack-testing = Test ediliyor test-check-pins = Pinleri kontrol eidn test-number-of-runs = Çalıştırma sayısı test-replace-switch = Anahtarı değiştir test-serial = Seri untitled-layout = İsimsiz Düzen ================================================ FILE: i18n/tr/system76_keyboard_configurator_backend.ftl ================================================ mode-disabled = Etkisizleştirilmiş mode-solid-color = Katman Başına Tek Parça Renk mode-per-key = Tuş Başına Tek Parça mode-active-keys = Yalnızca Bağlı Tuşlar mode-cycle-all = Cosmic Arkaplanı mode-cycle-left-right = Yatay Tarama mode-cycle-up-down = Dikey Tarama mode-cycle-out-in = Olay Ufku mode-cycle-out-in-dual = İkili Galaksiler mode-rainbow-moving-chevron = Uzay Zamanı mode-cycle-pinwheel = Fırıldak Galaksi mode-cycle-spiral = Sarmal Galaksi mode-raindrops = Elementler mode-splash = Denize İniş mode-multisplash = Meteor Duşu no-board = Kart bulunamadı ================================================ FILE: i18n/tr/system76_keyboard_configurator_widgets.ftl ================================================ button-color = Renk button-cancel = İptal button-save = Kaydet choose-color = Rengi Ata error-set-color = Klavye rengi atanamadı error-set-brightness = Klavye parlaklığı atanamadı label-hue = Ton label-saturation = Doygunluk scale-brightness = Parlaklık ================================================ FILE: i18n.toml ================================================ fallback_language = "en" [fluent] assets_dir = "i18n" ================================================ FILE: layouts/README.md ================================================ `picker.json` defines the groups of keycodes that appear in the keycode picker. The labels here are used both in the picker and on the keyboard. Within each layout: * `default.json` - The default keymap and LED settings, in the same format the Configurator can import/export through its UI. * `meta.json` - Micellanous values associated with the keyboard. `meta.json` includes a `keyboard` key that refers to a subdirectory of `keyboards/`, since multiple laptop models have the same keyboard, so they share this data. In `keyboards/`: * `keymap.json` - Maps keycode names to their numerical values. * `layout.json` - Maps key position to electrical matrix indices. * `leds.json` - For a keyboard with per-key LEDs, maps key position to LED index. * `physical.json` - Defines the physical layout of keys, the colors to display as their backgrounds, and labels (only shown in a tab when `--debug-layers` is passed to the Configurator). Other than `meta.json` and `physical.json`, these files are generated from the EC/QMK source using `layouts.py` from the root of this repository. `meta.json` is written manually, with other keys added by `layouts.py`. `physical.json` is created with . ================================================ FILE: layouts/keyboards/system76/14in_81/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 9, 7 ], "K02": [ 8, 6 ], "K03": [ 8, 7 ], "K04": [ 9, 5 ], "K05": [ 10, 7 ], "K06": [ 10, 6 ], "K07": [ 11, 7 ], "K08": [ 11, 6 ], "K09": [ 12, 7 ], "K0A": [ 12, 6 ], "K0B": [ 13, 5 ], "K0C": [ 15, 4 ], "K0D": [ 13, 2 ], "K0E": [ 13, 6 ], "K0F": [ 14, 5 ], "K0G": [ 14, 7 ], "K10": [ 7, 6 ], "K11": [ 5, 7 ], "K12": [ 7, 5 ], "K13": [ 8, 5 ], "K14": [ 9, 4 ], "K15": [ 8, 4 ], "K16": [ 9, 6 ], "K17": [ 9, 1 ], "K18": [ 10, 5 ], "K19": [ 10, 4 ], "K1A": [ 10, 0 ], "K1B": [ 12, 5 ], "K1C": [ 13, 4 ], "K1D": [ 14, 3 ], "K20": [ 4, 4 ], "K21": [ 4, 7 ], "K22": [ 9, 0 ], "K23": [ 5, 4 ], "K24": [ 6, 4 ], "K25": [ 8, 3 ], "K26": [ 7, 4 ], "K27": [ 6, 2 ], "K28": [ 8, 0 ], "K29": [ 10, 3 ], "K2A": [ 11, 4 ], "K2B": [ 12, 4 ], "K2C": [ 13, 3 ], "K2D": [ 14, 1 ], "K30": [ 4, 2 ], "K31": [ 5, 3 ], "K32": [ 7, 0 ], "K33": [ 4, 3 ], "K34": [ 8, 2 ], "K35": [ 6, 3 ], "K36": [ 7, 2 ], "K37": [ 11, 1 ], "K38": [ 9, 2 ], "K39": [ 10, 2 ], "K3A": [ 11, 3 ], "K3B": [ 12, 3 ], "K3C": [ 15, 2 ], "K40": [ 3, 2 ], "K41": [ 4, 1 ], "K42": [ 5, 1 ], "K43": [ 4, 5 ], "K44": [ 6, 6 ], "K45": [ 6, 1 ], "K46": [ 7, 1 ], "K47": [ 8, 1 ], "K48": [ 10, 1 ], "K49": [ 11, 2 ], "K4A": [ 3, 1 ], "K4B": [ 11, 0 ], "K4C": [ 12, 2 ], "K50": [ 1, 6 ], "K51": [ 6, 0 ], "K52": [ 0, 7 ], "K53": [ 2, 4 ], "K54": [ 0, 3 ], "K55": [ 2, 3 ], "K56": [ 1, 5 ], "K57": [ 14, 2 ], "K58": [ 15, 7 ], "K59": [ 13, 7 ] } ================================================ FILE: layouts/keyboards/system76/14in_81/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/14in_81/physical.json ================================================ [ { "name": "System76 Lemur Pro - 81 Key", "author": "Levi Portenier" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.861, "h": 0.75 }, "Esc", { "a": 4, "w": 0.861, "h": 0.75 }, "F1", { "w": 0.861, "h": 0.75 }, "F2", { "w": 0.861, "h": 0.75 }, "F3", { "w": 0.861, "h": 0.75 }, "F4", { "w": 0.861, "h": 0.75 }, "F5", { "x": 8.881784197001252e-16, "w": 0.861, "h": 0.75 }, "F6", { "w": 0.861, "h": 0.75 }, "F7", { "w": 0.861, "h": 0.75 }, "F8", { "w": 0.861, "h": 0.75 }, "F9", { "w": 0.861, "h": 0.75 }, "F10", { "w": 0.861, "h": 0.75 }, "F11", { "w": 0.861, "h": 0.75 }, "F12", { "x": -1.7763568394002505e-15, "a": 7, "w": 0.861, "h": 0.75 }, "Home", { "w": 0.861, "h": 0.75 }, "End", { "x": -1.7763568394002505e-15, "w": 0.861, "h": 0.75 }, "PrtSc", { "w": 0.861, "h": 0.75 }, "Del" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009 }, "!\n1", { "x": 1.1102230246251565e-15 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 6, "w": 1.75 }, "Backspace" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899, "a": 4 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", "{\n[", "}\n]", { "w": 1.25 }, "|\n\\" ], [ { "a": 6, "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899, "a": 4 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", ":\n;", "\"\n'", { "a": 6, "w": 2 }, "Enter" ], [ { "w": 2.139 }, "Shift", { "x": 0.001000000000000334, "a": 4 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", "<\n,", ">\n.", { "a": 5, "w": 1.5 }, "?\n/", { "a": 6 }, "Shift", { "a": 7 }, "Up" ], [ { "a": 6, "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16, "a": 7 }, "Super", { "a": 6 }, "Alt", { "x": -8.881784197001252e-16, "a": 7, "w": 5 }, "", { "a": 6 }, "Alt", { "w": 1.5 }, "Ctrl", { "a": 7 }, "Left", "Right", "Down" ] ] ================================================ FILE: layouts/keyboards/system76/14in_83/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 8, 7 ], "K02": [ 8, 6 ], "K03": [ 9, 7 ], "K04": [ 9, 6 ], "K05": [ 10, 7 ], "K06": [ 10, 6 ], "K07": [ 11, 7 ], "K08": [ 11, 6 ], "K09": [ 12, 7 ], "K0A": [ 12, 6 ], "K0B": [ 13, 7 ], "K0C": [ 15, 5 ], "K0D": [ 13, 2 ], "K0E": [ 13, 6 ], "K0F": [ 14, 5 ], "K0G": [ 14, 7 ], "K10": [ 7, 6 ], "K11": [ 7, 5 ], "K12": [ 7, 4 ], "K13": [ 8, 5 ], "K14": [ 8, 4 ], "K15": [ 8, 3 ], "K16": [ 9, 5 ], "K17": [ 9, 4 ], "K18": [ 10, 5 ], "K19": [ 10, 4 ], "K1A": [ 11, 5 ], "K1B": [ 12, 5 ], "K1C": [ 13, 4 ], "K1D": [ 14, 3 ], "K20": [ 4, 4 ], "K21": [ 4, 7 ], "K22": [ 9, 0 ], "K23": [ 5, 7 ], "K24": [ 6, 4 ], "K25": [ 6, 5 ], "K26": [ 7, 3 ], "K27": [ 8, 2 ], "K28": [ 8, 0 ], "K29": [ 10, 3 ], "K2A": [ 11, 4 ], "K2B": [ 12, 4 ], "K2C": [ 13, 3 ], "K2D": [ 14, 1 ], "K30": [ 4, 2 ], "K31": [ 4, 3 ], "K32": [ 10, 0 ], "K33": [ 5, 3 ], "K34": [ 6, 2 ], "K35": [ 6, 3 ], "K36": [ 7, 2 ], "K37": [ 9, 1 ], "K38": [ 9, 2 ], "K39": [ 10, 2 ], "K3A": [ 11, 3 ], "K3B": [ 12, 3 ], "K3C": [ 15, 2 ], "K40": [ 3, 6 ], "K41": [ 4, 1 ], "K42": [ 4, 0 ], "K43": [ 5, 1 ], "K44": [ 5, 0 ], "K45": [ 6, 1 ], "K46": [ 7, 1 ], "K47": [ 8, 1 ], "K48": [ 10, 1 ], "K49": [ 11, 2 ], "K4A": [ 12, 2 ], "K4B": [ 3, 7 ], "K50": [ 1, 6 ], "K51": [ 6, 0 ], "K52": [ 0, 6 ], "K53": [ 2, 6 ], "K54": [ 4, 6 ], "K55": [ 2, 7 ], "K56": [ 1, 7 ], "K57": [ 14, 4 ], "K58": [ 11, 1 ], "K59": [ 15, 7 ], "K60": [ 14, 2 ], "K61": [ 15, 4 ], "K62": [ 13, 5 ] } ================================================ FILE: layouts/keyboards/system76/14in_83/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/14in_83/physical.json ================================================ [ { "name": "System76 Lemur Pro - Simple", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.861, "h": 0.75 }, "Esc", { "a": 4, "w": 0.861, "h": 0.75 }, "F1", { "w": 0.861, "h": 0.75 }, "F2", { "w": 0.861, "h": 0.75 }, "F3", { "w": 0.861, "h": 0.75 }, "F4", { "w": 0.861, "h": 0.75 }, "F5", { "x": 8.881784197001252e-16, "w": 0.861, "h": 0.75 }, "F6", { "w": 0.861, "h": 0.75 }, "F7", { "w": 0.861, "h": 0.75 }, "F8", { "w": 0.861, "h": 0.75 }, "F9", { "w": 0.861, "h": 0.75 }, "F10", { "w": 0.861, "h": 0.75 }, "F11", { "w": 0.861, "h": 0.75 }, "F12", { "x": -1.7763568394002505e-15, "a": 7, "w": 0.861, "h": 0.75 }, "Home", { "w": 0.861, "h": 0.75 }, "End", { "x": -1.7763568394002505e-15, "w": 0.861, "h": 0.75 }, "PrtSc", { "w": 0.861, "h": 0.75 }, "Del" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009 }, "!\n1", { "x": 8.881784197001252e-16 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 6, "w": 1.75 }, "Backspace" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899, "a": 4 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", "{\n[", "}\n]", { "w": 1.25 }, "|\n\\" ], [ { "a": 6, "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899, "a": 4 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", ":\n;", "\"\n'", { "a": 6, "w": 2 }, "Enter" ], [ { "w": 2.139 }, "Shift", { "x": 0.001000000000000334, "a": 4 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", "<\n,", ">\n.", "?\n/", { "a": 6, "w": 2.5 }, "Shift" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16, "a": 7 }, "Super", { "a": 6 }, "Alt", { "x": -8.881784197001252e-16, "a": 7, "w": 5 }, "", { "a": 6 }, "Alt", { "w": 1.5 }, "Ctrl", { "a": 7, "h": 0.5 }, "PgUp", { "h": 0.5 }, "Up", { "h": 0.5 }, "PgDn" ], [ { "y": -0.5, "x": 11.64, "h": 0.5 }, "Left", { "h": 0.5 }, "Down", { "h": 0.5 }, "Right" ] ] ================================================ FILE: layouts/keyboards/system76/14in_86/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 8, 7 ], "K02": [ 8, 6 ], "K03": [ 9, 7 ], "K04": [ 9, 6 ], "K05": [ 10, 7 ], "K06": [ 10, 6 ], "K07": [ 11, 7 ], "K08": [ 11, 6 ], "K09": [ 12, 7 ], "K0A": [ 12, 6 ], "K0B": [ 13, 7 ], "K0C": [ 15, 5 ], "K0D": [ 13, 2 ], "K0E": [ 13, 6 ], "K0F": [ 14, 5 ], "K0G": [ 14, 7 ], "K10": [ 7, 6 ], "K11": [ 7, 5 ], "K12": [ 7, 4 ], "K13": [ 8, 5 ], "K14": [ 8, 4 ], "K15": [ 8, 3 ], "K16": [ 9, 5 ], "K17": [ 9, 4 ], "K18": [ 10, 5 ], "K19": [ 10, 4 ], "K1A": [ 11, 5 ], "K1B": [ 12, 5 ], "K1C": [ 13, 4 ], "K1D": [ 14, 3 ], "K1E": [ 14, 6 ], "K20": [ 4, 4 ], "K21": [ 4, 7 ], "K22": [ 9, 0 ], "K23": [ 5, 7 ], "K24": [ 6, 4 ], "K25": [ 6, 5 ], "K26": [ 7, 3 ], "K27": [ 8, 2 ], "K28": [ 8, 0 ], "K29": [ 10, 3 ], "K2A": [ 11, 4 ], "K2B": [ 12, 4 ], "K2C": [ 13, 3 ], "K2D": [ 14, 1 ], "K2E": [ 14, 4 ], "K30": [ 4, 2 ], "K31": [ 4, 3 ], "K32": [ 10, 0 ], "K33": [ 5, 3 ], "K34": [ 6, 2 ], "K35": [ 6, 3 ], "K36": [ 7, 2 ], "K37": [ 9, 1 ], "K38": [ 9, 2 ], "K39": [ 10, 2 ], "K3A": [ 11, 3 ], "K3B": [ 12, 3 ], "K3C": [ 15, 2 ], "K3D": [ 15, 7 ], "K40": [ 3, 6 ], "K41": [ 4, 1 ], "K42": [ 4, 0 ], "K43": [ 5, 1 ], "K44": [ 5, 0 ], "K45": [ 6, 1 ], "K46": [ 7, 1 ], "K47": [ 8, 1 ], "K48": [ 10, 1 ], "K49": [ 11, 2 ], "K4A": [ 12, 2 ], "K4B": [ 3, 7 ], "K4C": [ 11, 1 ], "K4D": [ 15, 6 ], "K50": [ 1, 6 ], "K51": [ 6, 0 ], "K52": [ 0, 6 ], "K53": [ 2, 6 ], "K54": [ 4, 6 ], "K55": [ 2, 7 ], "K56": [ 15, 0 ], "K57": [ 1, 7 ], "K58": [ 14, 2 ], "K59": [ 15, 4 ], "K5A": [ 13, 5 ] } ================================================ FILE: layouts/keyboards/system76/14in_86/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/14in_86/physical.json ================================================ [ { "name": "System76 Galago Pro (galp4)", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.9306, "h": 0.75 }, "Esc", { "x": -0.0006000000000000449, "a": 4, "w": 0.9306, "h": 0.75 }, "F1", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F2", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F3", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F4", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F5", { "x": 0.009400000000000297, "w": 0.9306, "h": 0.75 }, "F6", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F7", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F8", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F9", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F10", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F11", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F12", { "x": -0.000600000000000378, "a": 5, "w": 0.9306, "h": 0.75 }, "PrtSc\nSysRq", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Pause\nBreak", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Insert\nNumLk", { "x": -0.0009999999999976694, "a": 7, "h": 0.75 }, "Del" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009, "a": 5 }, "!\n1", { "x": 2.220446049250313e-16 }, "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 7, "w": 2 }, "Backspace", "Home" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899 }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", { "w": 1.5 }, "|\n\\", { "a": 7 }, "PgUp" ], [ { "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899 }, "A", "S", "D", "F", "G", "H", "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "a": 7, "w": 2.25 }, "Enter", "PgDn" ], [ { "w": 2.139 }, "Shift", { "x": 0.0009999999999998899 }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "a": 7, "w": 1.75 }, "Shift", "Up", "End" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", "Super", "Alt", { "w": 5 }, "", "Alt", "App", { "w": 1.75 }, "Ctrl", "Left", "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/15in_102/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 8, 7 ], "K02": [ 9, 3 ], "K03": [ 12, 5 ], "K04": [ 14, 3 ], "K05": [ 13, 7 ], "K06": [ 10, 6 ], "K07": [ 8, 5 ], "K08": [ 10, 5 ], "K09": [ 13, 3 ], "K0A": [ 14, 1 ], "K0B": [ 16, 6 ], "K0C": [ 16, 7 ], "K0D": [ 13, 2 ], "K0E": [ 14, 5 ], "K0F": [ 14, 6 ], "K0G": [ 16, 1 ], "K0H": [ 16, 0 ], "K0I": [ 5, 0 ], "K0J": [ 6, 0 ], "K10": [ 16, 5 ], "K11": [ 11, 6 ], "K12": [ 10, 7 ], "K13": [ 15, 6 ], "K14": [ 14, 7 ], "K15": [ 13, 6 ], "K16": [ 12, 7 ], "K17": [ 11, 2 ], "K18": [ 8, 6 ], "K19": [ 8, 3 ], "K1A": [ 7, 2 ], "K1B": [ 6, 1 ], "K1C": [ 17, 1 ], "K1D": [ 15, 7 ], "K1E": [ 5, 4 ], "K1F": [ 10, 0 ], "K1G": [ 11, 0 ], "K1H": [ 4, 1 ], "K20": [ 7, 6 ], "K21": [ 14, 0 ], "K22": [ 5, 1 ], "K23": [ 6, 2 ], "K24": [ 7, 3 ], "K25": [ 8, 4 ], "K26": [ 7, 1 ], "K27": [ 15, 4 ], "K28": [ 12, 6 ], "K29": [ 13, 5 ], "K2A": [ 11, 7 ], "K2B": [ 10, 3 ], "K2C": [ 8, 2 ], "K2D": [ 12, 0 ], "K2E": [ 14, 2 ], "K2F": [ 4, 3 ], "K2G": [ 15, 5 ], "K2H": [ 15, 3 ], "K30": [ 5, 7 ], "K31": [ 12, 2 ], "K32": [ 10, 4 ], "K33": [ 11, 3 ], "K34": [ 9, 1 ], "K35": [ 17, 0 ], "K36": [ 9, 2 ], "K37": [ 8, 1 ], "K38": [ 7, 0 ], "K39": [ 6, 3 ], "K3A": [ 7, 5 ], "K3B": [ 9, 6 ], "K3C": [ 15, 2 ], "K3D": [ 5, 5 ], "K3E": [ 14, 4 ], "K3F": [ 5, 6 ], "K40": [ 2, 6 ], "K41": [ 4, 0 ], "K42": [ 15, 1 ], "K43": [ 16, 2 ], "K44": [ 13, 1 ], "K45": [ 9, 7 ], "K46": [ 13, 4 ], "K47": [ 6, 6 ], "K48": [ 10, 1 ], "K49": [ 11, 1 ], "K4A": [ 12, 3 ], "K4B": [ 2, 7 ], "K4C": [ 16, 3 ], "K4D": [ 17, 4 ], "K4E": [ 4, 4 ], "K4F": [ 17, 2 ], "K4G": [ 9, 5 ], "K50": [ 0, 6 ], "K51": [ 17, 3 ], "K52": [ 3, 0 ], "K53": [ 1, 6 ], "K54": [ 3, 7 ], "K55": [ 1, 7 ], "K56": [ 15, 0 ], "K57": [ 0, 7 ], "K58": [ 17, 5 ], "K59": [ 16, 4 ], "K5A": [ 17, 6 ], "K5B": [ 8, 0 ], "K5C": [ 9, 0 ] } ================================================ FILE: layouts/keyboards/system76/15in_102/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/15in_102/physical.json ================================================ [ { "name": "System76 Darter Pro - Simple", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.9306, "h": 0.75 }, "Esc", { "x": -0.0005999999999999339, "a": 4, "w": 0.9306, "h": 0.75 }, "F1", { "x": -0.000600000000000156, "w": 0.9306, "h": 0.75 }, "F2", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F3", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F4", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F5", { "x": 0.009400000000000297, "w": 0.9306, "h": 0.75 }, "F6", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F7", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F8", { "x": -0.0005999999999986017, "w": 0.9306, "h": 0.75 }, "F9", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F10", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F11", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F12", { "x": -0.0005999999999986017, "a": 5, "w": 0.9306, "h": 0.75 }, "PrtSc\nSysRq", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Insert\nScrLk", { "x": -0.000600000000000378, "a": 7, "w": 0.9306, "h": 0.75 }, "Del", { "x": 0.10939999999999905, "w": 0.889, "h": 0.75 }, "Home", { "x": 0.0010000000000012221, "w": 0.889, "h": 0.75 }, "End", { "x": 0.0010000000000012221, "a": 5, "w": 0.889, "h": 0.75 }, "PgUp\nPause", { "x": -0.028999999999999915, "w": 0.889, "h": 0.75 }, "PgDn\nBreak" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009, "a": 5 }, "!\n1", { "x": 6.661338147750939e-16 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 7, "w": 2 }, "Backspace", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "Num\nLk", { "x": 0.0010000000000012221, "a": 7, "w": 0.889 }, "/", { "x": 0.0010000000000012221, "w": 0.889 }, "*", { "x": -0.028999999999999915, "w": 0.889 }, "-" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", { "w": 1.5 }, "|\n\\", { "x": 0.10999999999999943, "w": 0.889 }, "7\nHome", { "x": 0.0010000000000012221, "w": 0.889 }, "8\nUp", { "x": 0.0010000000000012221, "w": 0.889 }, "9\nPgUp", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "+" ], [ { "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "a": 7, "w": 2.25 }, "Enter", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "4\nLeft", { "x": 0.0010000000000012221, "w": 0.889 }, "5", { "x": 0.0010000000000012221, "w": 0.889 }, "6\nRight" ], [ { "a": 7, "w": 2.139 }, "Shift", { "x": 0.001000000000000334 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "a": 7, "w": 1.75 }, "Shift", "Up", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "1\nEnd", { "x": 0.0010000000000012221, "w": 0.889 }, "2\nDown", { "x": 0.0010000000000012221, "w": 0.889 }, "3\nPgDn", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "Enter" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16 }, "Super", "Alt", { "x": -8.881784197001252e-16, "w": 5 }, "", "Alt", "App", { "w": 1.75 }, "Ctrl", "Left", "Down", "Right", { "a": 5, "w": 0.889 }, "0\nIns", { "x": 0.0010000000000012221, "w": 0.889 }, ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/15in_102_nkey/layout.json ================================================ { "K00": [ 6, 0 ], "K01": [ 12, 0 ], "K02": [ 1, 1 ], "K03": [ 7, 1 ], "K04": [ 11, 1 ], "K05": [ 15, 1 ], "K06": [ 4, 2 ], "K07": [ 6, 2 ], "K08": [ 10, 2 ], "K09": [ 6, 3 ], "K0A": [ 11, 3 ], "K0B": [ 13, 3 ], "K0C": [ 6, 4 ], "K0D": [ 9, 4 ], "K0E": [ 6, 5 ], "K0F": [ 11, 5 ], "K0G": [ 12, 5 ], "K0H": [ 4, 6 ], "K0I": [ 13, 6 ], "K0J": [ 10, 7 ], "K10": [ 0, 0 ], "K11": [ 10, 0 ], "K12": [ 2, 1 ], "K13": [ 4, 1 ], "K14": [ 12, 1 ], "K15": [ 1, 2 ], "K16": [ 5, 2 ], "K17": [ 9, 2 ], "K18": [ 2, 3 ], "K19": [ 9, 3 ], "K1A": [ 12, 3 ], "K1B": [ 3, 4 ], "K1C": [ 7, 4 ], "K1D": [ 7, 5 ], "K1E": [ 0, 6 ], "K1F": [ 5, 6 ], "K1G": [ 6, 6 ], "K1H": [ 11, 7 ], "K20": [ 5, 0 ], "K21": [ 8, 0 ], "K22": [ 3, 1 ], "K23": [ 10, 1 ], "K24": [ 13, 1 ], "K25": [ 2, 2 ], "K26": [ 8, 2 ], "K27": [ 0, 3 ], "K28": [ 5, 3 ], "K29": [ 0, 4 ], "K2A": [ 2, 4 ], "K2B": [ 8, 4 ], "K2C": [ 10, 4 ], "K2D": [ 9, 5 ], "K2E": [ 1, 6 ], "K2F": [ 7, 6 ], "K2G": [ 10, 6 ], "K2H": [ 12, 7 ], "K30": [ 2, 0 ], "K31": [ 0, 1 ], "K32": [ 6, 1 ], "K33": [ 8, 1 ], "K34": [ 14, 1 ], "K35": [ 3, 2 ], "K36": [ 1, 3 ], "K37": [ 4, 3 ], "K38": [ 7, 3 ], "K39": [ 10, 3 ], "K3A": [ 4, 4 ], "K3B": [ 1, 5 ], "K3C": [ 8, 5 ], "K3D": [ 2, 6 ], "K3E": [ 9, 6 ], "K3F": [ 11, 6 ], "K40": [ 3, 0 ], "K41": [ 9, 0 ], "K42": [ 5, 1 ], "K43": [ 9, 1 ], "K44": [ 0, 2 ], "K45": [ 7, 2 ], "K46": [ 3, 3 ], "K47": [ 8, 3 ], "K48": [ 1, 4 ], "K49": [ 5, 4 ], "K4A": [ 0, 5 ], "K4B": [ 4, 5 ], "K4C": [ 10, 5 ], "K4D": [ 3, 6 ], "K4E": [ 8, 6 ], "K4F": [ 12, 6 ], "K4G": [ 14, 7 ], "K50": [ 1, 0 ], "K51": [ 4, 0 ], "K52": [ 11, 0 ], "K53": [ 13, 0 ], "K54": [ 15, 0 ], "K55": [ 2, 7 ], "K56": [ 3, 7 ], "K57": [ 4, 7 ], "K58": [ 5, 7 ], "K59": [ 6, 7 ], "K5A": [ 7, 7 ], "K5B": [ 8, 7 ], "K5C": [ 9, 7 ] } ================================================ FILE: layouts/keyboards/system76/15in_102_nkey/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/15in_102_nkey/physical.json ================================================ [ { "name": "System76 Darter Pro - Simple", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.9306, "h": 0.75 }, "Esc", { "x": -0.0005999999999999339, "a": 4, "w": 0.9306, "h": 0.75 }, "F1", { "x": -0.000600000000000156, "w": 0.9306, "h": 0.75 }, "F2", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F3", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F4", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F5", { "x": 0.009400000000000297, "w": 0.9306, "h": 0.75 }, "F6", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F7", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F8", { "x": -0.0005999999999986017, "w": 0.9306, "h": 0.75 }, "F9", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F10", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F11", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F12", { "x": -0.0005999999999986017, "a": 5, "w": 0.9306, "h": 0.75 }, "PrtSc\nSysRq", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Insert\nScrLk", { "x": -0.000600000000000378, "a": 7, "w": 0.9306, "h": 0.75 }, "Del", { "x": 0.10939999999999905, "w": 0.889, "h": 0.75 }, "Home", { "x": 0.0010000000000012221, "w": 0.889, "h": 0.75 }, "End", { "x": 0.0010000000000012221, "a": 5, "w": 0.889, "h": 0.75 }, "PgUp\nPause", { "x": -0.028999999999999915, "w": 0.889, "h": 0.75 }, "PgDn\nBreak" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009, "a": 5 }, "!\n1", { "x": 6.661338147750939e-16 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 7, "w": 2 }, "Backspace", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "Num\nLk", { "x": 0.0010000000000012221, "a": 7, "w": 0.889 }, "/", { "x": 0.0010000000000012221, "w": 0.889 }, "*", { "x": -0.028999999999999915, "w": 0.889 }, "-" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", { "w": 1.5 }, "|\n\\", { "x": 0.10999999999999943, "w": 0.889 }, "7\nHome", { "x": 0.0010000000000012221, "w": 0.889 }, "8\nUp", { "x": 0.0010000000000012221, "w": 0.889 }, "9\nPgUp", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "+" ], [ { "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "a": 7, "w": 2.25 }, "Enter", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "4\nLeft", { "x": 0.0010000000000012221, "w": 0.889 }, "5", { "x": 0.0010000000000012221, "w": 0.889 }, "6\nRight" ], [ { "a": 7, "w": 2.139 }, "Shift", { "x": 0.001000000000000334 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "a": 7, "w": 1.75 }, "Shift", "Up", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "1\nEnd", { "x": 0.0010000000000012221, "w": 0.889 }, "2\nDown", { "x": 0.0010000000000012221, "w": 0.889 }, "3\nPgDn", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "Enter" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16 }, "Super", "Alt", { "x": -8.881784197001252e-16, "w": 5 }, "", "Alt", "App", { "w": 1.75 }, "Ctrl", "Left", "Down", "Right", { "a": 5, "w": 0.889 }, "0\nIns", { "x": 0.0010000000000012221, "w": 0.889 }, ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/18H9LHA04/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 8, 7 ], "K02": [ 9, 3 ], "K03": [ 12, 5 ], "K04": [ 14, 3 ], "K05": [ 13, 7 ], "K06": [ 10, 6 ], "K07": [ 8, 5 ], "K08": [ 10, 5 ], "K09": [ 13, 3 ], "K0A": [ 14, 1 ], "K0B": [ 16, 6 ], "K0C": [ 16, 7 ], "K0D": [ 13, 2 ], "K0E": [ 14, 5 ], "K0F": [ 14, 6 ], "K0G": [ 16, 1 ], "K0H": [ 16, 0 ], "K0I": [ 5, 0 ], "K0J": [ 6, 0 ], "K10": [ 16, 5 ], "K11": [ 11, 6 ], "K12": [ 10, 7 ], "K13": [ 15, 6 ], "K14": [ 14, 7 ], "K15": [ 13, 6 ], "K16": [ 12, 7 ], "K17": [ 11, 2 ], "K18": [ 8, 6 ], "K19": [ 8, 3 ], "K1A": [ 7, 2 ], "K1B": [ 6, 1 ], "K1C": [ 17, 1 ], "K1D": [ 15, 7 ], "K1E": [ 5, 4 ], "K1F": [ 10, 0 ], "K1G": [ 11, 0 ], "K1H": [ 4, 1 ], "K20": [ 7, 6 ], "K21": [ 14, 0 ], "K22": [ 5, 1 ], "K23": [ 6, 2 ], "K24": [ 7, 3 ], "K25": [ 8, 4 ], "K26": [ 7, 1 ], "K27": [ 15, 4 ], "K28": [ 12, 6 ], "K29": [ 13, 5 ], "K2A": [ 11, 7 ], "K2B": [ 10, 3 ], "K2C": [ 8, 2 ], "K2D": [ 12, 0 ], "K2E": [ 14, 2 ], "K2F": [ 4, 3 ], "K2G": [ 15, 5 ], "K2H": [ 15, 3 ], "K30": [ 5, 7 ], "K31": [ 12, 2 ], "K32": [ 10, 4 ], "K33": [ 11, 3 ], "K34": [ 9, 1 ], "K35": [ 17, 0 ], "K36": [ 9, 2 ], "K37": [ 8, 1 ], "K38": [ 7, 0 ], "K39": [ 6, 3 ], "K3A": [ 7, 5 ], "K3B": [ 9, 6 ], "K3C": [ 15, 2 ], "K3D": [ 5, 5 ], "K3E": [ 14, 4 ], "K3F": [ 5, 6 ], "K40": [ 2, 6 ], "K41": [ 4, 0 ], "K42": [ 15, 1 ], "K43": [ 16, 2 ], "K44": [ 13, 1 ], "K45": [ 9, 7 ], "K46": [ 13, 4 ], "K47": [ 6, 6 ], "K48": [ 10, 1 ], "K49": [ 11, 1 ], "K4A": [ 12, 3 ], "K4B": [ 2, 7 ], "K4C": [ 16, 3 ], "K4D": [ 17, 4 ], "K4E": [ 4, 4 ], "K4F": [ 17, 2 ], "K4G": [ 9, 5 ], "K50": [ 0, 6 ], "K51": [ 17, 3 ], "K52": [ 3, 0 ], "K53": [ 1, 6 ], "K54": [ 3, 7 ], "K55": [ 1, 7 ], "K56": [ 15, 0 ], "K57": [ 0, 7 ], "K58": [ 17, 5 ], "K59": [ 16, 4 ], "K5A": [ 17, 6 ], "K5B": [ 8, 0 ], "K5C": [ 9, 0 ] } ================================================ FILE: layouts/keyboards/system76/18H9LHA04/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/18H9LHA04/physical.json ================================================ [ { "name": "System76 Darter Pro - Simple", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.9306, "h": 0.75 }, "Esc", { "x": -0.0005999999999999339, "a": 4, "w": 0.9306, "h": 0.75 }, "F1", { "x": -0.000600000000000156, "w": 0.9306, "h": 0.75 }, "F2", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F3", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F4", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F5", { "x": 0.009400000000000297, "w": 0.9306, "h": 0.75 }, "F6", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F7", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F8", { "x": -0.0005999999999986017, "w": 0.9306, "h": 0.75 }, "F9", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F10", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F11", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F12", { "x": -0.0005999999999986017, "a": 5, "w": 0.9306, "h": 0.75 }, "PrtSc\nSysRq", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Insert\nScrLk", { "x": -0.000600000000000378, "a": 7, "w": 0.9306, "h": 0.75 }, "Del", { "x": 0.10939999999999905, "w": 0.889, "h": 0.75 }, "Home", { "x": 0.0010000000000012221, "w": 0.889, "h": 0.75 }, "End", { "x": 0.0010000000000012221, "a": 5, "w": 0.889, "h": 0.75 }, "PgUp\nPause", { "x": -0.028999999999999915, "w": 0.889, "h": 0.75 }, "PgDn\nBreak" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009, "a": 5 }, "!\n1", { "x": 6.661338147750939e-16 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 7, "w": 2 }, "Backspace", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "Num\nLk", { "x": 0.0010000000000012221, "a": 7, "w": 0.889 }, "/", { "x": 0.0010000000000012221, "w": 0.889 }, "*", { "x": -0.028999999999999915, "w": 0.889 }, "-" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", { "w": 1.5 }, "|\n\\", { "x": 0.10999999999999943, "w": 0.889 }, "7\nHome", { "x": 0.0010000000000012221, "w": 0.889 }, "8\nUp", { "x": 0.0010000000000012221, "w": 0.889 }, "9\nPgUp", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "+" ], [ { "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "a": 7, "w": 2.25 }, "Enter", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "4\nLeft", { "x": 0.0010000000000012221, "w": 0.889 }, "5", { "x": 0.0010000000000012221, "w": 0.889 }, "6\nRight" ], [ { "a": 7, "w": 2.139 }, "Shift", { "x": 0.001000000000000334 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "a": 7, "w": 1.75 }, "Shift", "Up", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "1\nEnd", { "x": 0.0010000000000012221, "w": 0.889 }, "2\nDown", { "x": 0.0010000000000012221, "w": 0.889 }, "3\nPgDn", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "Enter" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16 }, "Super", "Alt", { "x": -8.881784197001252e-16, "w": 5 }, "", "Alt", "App", { "w": 1.75 }, "Ctrl", "Left", "Down", "Right", { "a": 5, "w": 0.889 }, "0\nIns", { "x": 0.0010000000000012221, "w": 0.889 }, ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/18H9LHA05/layout.json ================================================ { "K00": [ 7, 7 ], "K01": [ 8, 7 ], "K02": [ 9, 3 ], "K03": [ 12, 5 ], "K04": [ 14, 3 ], "K05": [ 13, 7 ], "K06": [ 10, 6 ], "K07": [ 8, 5 ], "K08": [ 10, 5 ], "K09": [ 13, 3 ], "K0A": [ 14, 1 ], "K0B": [ 16, 6 ], "K0C": [ 16, 7 ], "K0D": [ 13, 2 ], "K0E": [ 14, 5 ], "K0F": [ 14, 6 ], "K0G": [ 16, 1 ], "K0H": [ 16, 0 ], "K0I": [ 5, 0 ], "K0J": [ 6, 0 ], "K10": [ 16, 5 ], "K11": [ 11, 6 ], "K12": [ 10, 7 ], "K13": [ 15, 6 ], "K14": [ 14, 7 ], "K15": [ 13, 6 ], "K16": [ 12, 7 ], "K17": [ 11, 2 ], "K18": [ 8, 6 ], "K19": [ 8, 3 ], "K1A": [ 7, 2 ], "K1B": [ 6, 1 ], "K1C": [ 17, 1 ], "K1D": [ 15, 7 ], "K1E": [ 5, 4 ], "K1F": [ 10, 0 ], "K1G": [ 11, 0 ], "K1H": [ 4, 1 ], "K20": [ 7, 6 ], "K21": [ 14, 0 ], "K22": [ 5, 1 ], "K23": [ 6, 2 ], "K24": [ 7, 3 ], "K25": [ 8, 4 ], "K26": [ 7, 1 ], "K27": [ 15, 4 ], "K28": [ 12, 6 ], "K29": [ 13, 5 ], "K2A": [ 11, 7 ], "K2B": [ 10, 3 ], "K2C": [ 8, 2 ], "K2D": [ 12, 0 ], "K2E": [ 14, 2 ], "K2F": [ 4, 3 ], "K2G": [ 15, 5 ], "K2H": [ 15, 3 ], "K30": [ 5, 7 ], "K31": [ 12, 2 ], "K32": [ 10, 4 ], "K33": [ 11, 3 ], "K34": [ 9, 1 ], "K35": [ 17, 0 ], "K36": [ 9, 2 ], "K37": [ 8, 1 ], "K38": [ 7, 0 ], "K39": [ 6, 3 ], "K3A": [ 7, 5 ], "K3B": [ 9, 6 ], "K3C": [ 15, 2 ], "K3D": [ 5, 5 ], "K3E": [ 14, 4 ], "K3F": [ 5, 6 ], "K40": [ 2, 6 ], "K41": [ 4, 0 ], "K42": [ 15, 1 ], "K43": [ 16, 2 ], "K44": [ 13, 1 ], "K45": [ 9, 7 ], "K46": [ 13, 4 ], "K47": [ 6, 6 ], "K48": [ 10, 1 ], "K49": [ 11, 1 ], "K4A": [ 12, 3 ], "K4B": [ 2, 7 ], "K4C": [ 16, 3 ], "K4D": [ 17, 4 ], "K4E": [ 4, 4 ], "K4F": [ 17, 2 ], "K4G": [ 9, 5 ], "K50": [ 0, 6 ], "K51": [ 17, 3 ], "K52": [ 3, 0 ], "K53": [ 1, 6 ], "K54": [ 3, 7 ], "K55": [ 1, 7 ], "K56": [ 15, 0 ], "K57": [ 0, 7 ], "K58": [ 17, 5 ], "K59": [ 16, 4 ], "K5A": [ 17, 6 ], "K5B": [ 8, 0 ], "K5C": [ 9, 0 ] } ================================================ FILE: layouts/keyboards/system76/18H9LHA05/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/18H9LHA05/physical.json ================================================ [ { "name": "System76 Darter Pro - Simple", "author": "Jeremy Soller" }, [ { "c": "#141414", "t": "#ffffff", "a": 7, "w": 0.9306, "h": 0.75 }, "Esc", { "x": -0.0005999999999999339, "a": 4, "w": 0.9306, "h": 0.75 }, "F1", { "x": -0.000600000000000156, "w": 0.9306, "h": 0.75 }, "F2", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F3", { "x": -0.0005999999999999339, "w": 0.9306, "h": 0.75 }, "F4", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F5", { "x": 0.009400000000000297, "w": 0.9306, "h": 0.75 }, "F6", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F7", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F8", { "x": -0.0005999999999986017, "w": 0.9306, "h": 0.75 }, "F9", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F10", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F11", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "F12", { "x": -0.0005999999999986017, "a": 5, "w": 0.9306, "h": 0.75 }, "PrtSc\nSysRq", { "x": -0.000600000000000378, "w": 0.9306, "h": 0.75 }, "Insert\nScrLk", { "x": -0.000600000000000378, "a": 7, "w": 0.9306, "h": 0.75 }, "Del", { "x": 0.10939999999999905, "w": 0.889, "h": 0.75 }, "Home", { "x": 0.0010000000000012221, "w": 0.889, "h": 0.75 }, "End", { "x": 0.0010000000000012221, "a": 5, "w": 0.889, "h": 0.75 }, "PgUp\nPause", { "x": -0.028999999999999915, "w": 0.889, "h": 0.75 }, "PgDn\nBreak" ], [ { "y": -0.25, "a": 4, "w": 0.889 }, "~\n`", { "x": 0.0010000000000000009, "a": 5 }, "!\n1", { "x": 6.661338147750939e-16 }, "@\n2", { "x": 4.440892098500626e-16 }, "#\n3", "$\n4", { "x": -8.881784197001252e-16 }, "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "a": 7, "w": 2 }, "Backspace", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "Num\nLk", { "x": 0.0010000000000012221, "a": 7, "w": 0.889 }, "/", { "x": 0.0010000000000012221, "w": 0.889 }, "*", { "x": -0.028999999999999915, "w": 0.889 }, "-" ], [ { "w": 1.389 }, "Tab", { "x": 0.0009999999999998899 }, "Q", { "x": 4.440892098500626e-16 }, "W", "E", { "x": -8.881784197001252e-16 }, "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", { "w": 1.5 }, "|\n\\", { "x": 0.10999999999999943, "w": 0.889 }, "7\nHome", { "x": 0.0010000000000012221, "w": 0.889 }, "8\nUp", { "x": 0.0010000000000012221, "w": 0.889 }, "9\nPgUp", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "+" ], [ { "w": 1.639 }, "Caps Lock", { "x": 0.0009999999999998899 }, "A", { "x": 4.440892098500626e-16 }, "S", "D", { "x": -8.881784197001252e-16 }, "F", "G", "H", "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "a": 7, "w": 2.25 }, "Enter", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "4\nLeft", { "x": 0.0010000000000012221, "w": 0.889 }, "5", { "x": 0.0010000000000012221, "w": 0.889 }, "6\nRight" ], [ { "a": 7, "w": 2.139 }, "Shift", { "x": 0.001000000000000334 }, "Z", "X", { "x": -8.881784197001252e-16 }, "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "a": 7, "w": 1.75 }, "Shift", "Up", { "x": 0.10999999999999943, "a": 5, "w": 0.889 }, "1\nEnd", { "x": 0.0010000000000012221, "w": 0.889 }, "2\nDown", { "x": 0.0010000000000012221, "w": 0.889 }, "3\nPgDn", { "x": 0.0010000000000012221, "a": 7, "w": 0.889, "h": 2 }, "Enter" ], [ { "w": 1.139 }, "Ctrl", { "x": 0.0009999999999998899 }, "Fn", { "x": 4.440892098500626e-16 }, "Super", "Alt", { "x": -8.881784197001252e-16, "w": 5 }, "", "Alt", "App", { "w": 1.75 }, "Ctrl", "Left", "Down", "Right", { "a": 5, "w": 0.889 }, "0\nIns", { "x": 0.0010000000000012221, "w": 0.889 }, ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/launch_1/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 3, 13 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 4, 13 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 5, 13 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 5, 5 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_1/leds.json ================================================ { "K00": [ 69 ], "K01": [ 70 ], "K02": [ 71 ], "K03": [ 72 ], "K04": [ 73 ], "K05": [ 74 ], "K06": [ 75 ], "K07": [ 76 ], "K08": [ 77 ], "K09": [ 78 ], "K0A": [ 79 ], "K0B": [ 80 ], "K0C": [ 81 ], "K0D": [ 82 ], "K0E": [ 83 ], "K10": [ 68 ], "K11": [ 67 ], "K12": [ 66 ], "K13": [ 65 ], "K14": [ 64 ], "K15": [ 63 ], "K16": [ 62 ], "K17": [ 61 ], "K18": [ 60 ], "K19": [ 59 ], "K1A": [ 58 ], "K1B": [ 57 ], "K1C": [ 56 ], "K1D": [ 55 ], "K1E": [ 54 ], "K20": [ 39 ], "K21": [ 40 ], "K22": [ 41 ], "K23": [ 42 ], "K24": [ 43 ], "K25": [ 44 ], "K26": [ 45 ], "K27": [ 46 ], "K28": [ 47 ], "K29": [ 48 ], "K2A": [ 49 ], "K2B": [ 50 ], "K2C": [ 51 ], "K2D": [ 52 ], "K2E": [ 53 ], "K30": [ 38 ], "K31": [ 37 ], "K32": [ 36 ], "K33": [ 35 ], "K34": [ 34 ], "K35": [ 33 ], "K36": [ 32 ], "K37": [ 31 ], "K38": [ 30 ], "K39": [ 29 ], "K3A": [ 28 ], "K3B": [ 27 ], "K3C": [ 26 ], "K3D": [ 25 ], "K40": [ 12 ], "K41": [ 11 ], "K42": [ 10 ], "K43": [ 9 ], "K44": [ 8 ], "K45": [ 7 ], "K46": [ 6 ], "K47": [ 5 ], "K48": [ 4 ], "K49": [ 3 ], "K4A": [ 2 ], "K4B": [ 1 ], "K4C": [ 0 ], "K50": [ 13 ], "K51": [ 14 ], "K52": [ 15 ], "K53": [ 16 ], "K54": [ 17 ], "K55": [ 18 ], "K56": [ 19 ], "K57": [ 20 ], "K58": [ 21 ], "K59": [ 22 ], "K5A": [ 23 ], "K5B": [ 24 ] } ================================================ FILE: layouts/keyboards/system76/launch_1/physical.json ================================================ [ { "name": "System76 Launch Configurable Keyboard 1.0", "author": "Jeremy Soller", "switchMount": "cherry", "switchBrand": "kailh", "plate": true }, [ { "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn" ], [ { "x": 0.25, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End" ], [ { "x": 0.25, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/launch_2/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 3, 13 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 4, 13 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 5, 13 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 5, 5 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_2/leds.json ================================================ { "K00": [ 69 ], "K01": [ 70 ], "K02": [ 71 ], "K03": [ 72 ], "K04": [ 73 ], "K05": [ 74 ], "K06": [ 75 ], "K07": [ 76 ], "K08": [ 77 ], "K09": [ 78 ], "K0A": [ 79 ], "K0B": [ 80 ], "K0C": [ 81 ], "K0D": [ 82 ], "K0E": [ 83 ], "K10": [ 68 ], "K11": [ 67 ], "K12": [ 66 ], "K13": [ 65 ], "K14": [ 64 ], "K15": [ 63 ], "K16": [ 62 ], "K17": [ 61 ], "K18": [ 60 ], "K19": [ 59 ], "K1A": [ 58 ], "K1B": [ 57 ], "K1C": [ 56 ], "K1D": [ 55 ], "K1E": [ 54 ], "K20": [ 39 ], "K21": [ 40 ], "K22": [ 41 ], "K23": [ 42 ], "K24": [ 43 ], "K25": [ 44 ], "K26": [ 45 ], "K27": [ 46 ], "K28": [ 47 ], "K29": [ 48 ], "K2A": [ 49 ], "K2B": [ 50 ], "K2C": [ 51 ], "K2D": [ 52 ], "K2E": [ 53 ], "K30": [ 38 ], "K31": [ 37 ], "K32": [ 36 ], "K33": [ 35 ], "K34": [ 34 ], "K35": [ 33 ], "K36": [ 32 ], "K37": [ 31 ], "K38": [ 30 ], "K39": [ 29 ], "K3A": [ 28 ], "K3B": [ 27 ], "K3C": [ 26 ], "K3D": [ 25 ], "K40": [ 12 ], "K41": [ 11 ], "K42": [ 10 ], "K43": [ 9 ], "K44": [ 8 ], "K45": [ 7 ], "K46": [ 6 ], "K47": [ 5 ], "K48": [ 4 ], "K49": [ 3 ], "K4A": [ 2 ], "K4B": [ 1 ], "K4C": [ 0 ], "K50": [ 13 ], "K51": [ 14 ], "K52": [ 15 ], "K53": [ 16 ], "K54": [ 17 ], "K55": [ 18 ], "K56": [ 19 ], "K57": [ 20 ], "K58": [ 21 ], "K59": [ 22 ], "K5A": [ 23 ], "K5B": [ 24 ] } ================================================ FILE: layouts/keyboards/system76/launch_2/physical.json ================================================ [ { "name": "System76 Launch Configurable Keyboard 1.0", "author": "Jeremy Soller", "switchMount": "cherry", "switchBrand": "kailh", "plate": true }, [ { "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn" ], [ { "x": 0.25, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End" ], [ { "x": 0.25, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/launch_3/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 3, 13 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 4, 13 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 5, 13 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 5, 5 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_3/leds.json ================================================ { "K00": [ 69 ], "K01": [ 70 ], "K02": [ 71 ], "K03": [ 72 ], "K04": [ 73 ], "K05": [ 74 ], "K06": [ 75 ], "K07": [ 76 ], "K08": [ 77 ], "K09": [ 78 ], "K0A": [ 79 ], "K0B": [ 80 ], "K0C": [ 81 ], "K0D": [ 82 ], "K0E": [ 83 ], "K10": [ 68 ], "K11": [ 67 ], "K12": [ 66 ], "K13": [ 65 ], "K14": [ 64 ], "K15": [ 63 ], "K16": [ 62 ], "K17": [ 61 ], "K18": [ 60 ], "K19": [ 59 ], "K1A": [ 58 ], "K1B": [ 57 ], "K1C": [ 56 ], "K1D": [ 55 ], "K1E": [ 54 ], "K20": [ 39 ], "K21": [ 40 ], "K22": [ 41 ], "K23": [ 42 ], "K24": [ 43 ], "K25": [ 44 ], "K26": [ 45 ], "K27": [ 46 ], "K28": [ 47 ], "K29": [ 48 ], "K2A": [ 49 ], "K2B": [ 50 ], "K2C": [ 51 ], "K2D": [ 52 ], "K2E": [ 53 ], "K30": [ 38 ], "K31": [ 37 ], "K32": [ 36 ], "K33": [ 35 ], "K34": [ 34 ], "K35": [ 33 ], "K36": [ 32 ], "K37": [ 31 ], "K38": [ 30 ], "K39": [ 29 ], "K3A": [ 28 ], "K3B": [ 27 ], "K3C": [ 26 ], "K3D": [ 25 ], "K40": [ 12 ], "K41": [ 11 ], "K42": [ 10 ], "K43": [ 9 ], "K44": [ 8 ], "K45": [ 7 ], "K46": [ 6 ], "K47": [ 5 ], "K48": [ 4 ], "K49": [ 3 ], "K4A": [ 2 ], "K4B": [ 1 ], "K4C": [ 0 ], "K50": [ 13 ], "K51": [ 14 ], "K52": [ 15 ], "K53": [ 16 ], "K54": [ 17 ], "K55": [ 18 ], "K56": [ 19 ], "K57": [ 20 ], "K58": [ 21 ], "K59": [ 22 ], "K5A": [ 23 ], "K5B": [ 24 ] } ================================================ FILE: layouts/keyboards/system76/launch_3/physical.json ================================================ [ { "name": "System76 Launch Configurable Keyboard 1.0", "author": "Jeremy Soller", "switchMount": "cherry", "switchBrand": "kailh", "plate": true }, [ { "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn" ], [ { "x": 0.25, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End" ], [ { "x": 0.25, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/launch_alpha_1/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_alpha_1/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/launch_alpha_1/physical.json ================================================ [ { "name": "System76 Launch Configurable Keyboard Alpha 1", "author": "Jeremy Soller", "switchMount": "cherry", "switchBrand": "kailh", "plate": true }, [ { "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\" ], [ { "x": 0.25, "c": "#636363", "a": 7, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter" ], [ { "x": 0.75, "w": 1.5 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7 }, "Shift", { "c": "#755841" }, "Up" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/launch_alpha_2/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 0, 14 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 1, 14 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 2, 14 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 3, 14 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_alpha_2/leds.json ================================================ {} ================================================ FILE: layouts/keyboards/system76/launch_alpha_2/physical.json ================================================ [ { "name": "System76 Launch Configurable Keyboard Alpha 2", "author": "Jeremy Soller", "switchMount": "cherry", "switchBrand": "kailh", "plate": true }, [ { "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn" ], [ { "x": 0.25, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End" ], [ { "x": 0.75, "w": 1.5 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keyboards/system76/launch_heavy_1/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 3, 13 ], "K0F": [ 6, 12 ], "K0G": [ 6, 5 ], "K0H": [ 6, 4 ], "K0I": [ 6, 3 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 4, 13 ], "K1F": [ 7, 12 ], "K1G": [ 7, 5 ], "K1H": [ 7, 4 ], "K1I": [ 7, 3 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 5, 13 ], "K2F": [ 8, 12 ], "K2G": [ 8, 5 ], "K2H": [ 8, 4 ], "K2I": [ 8, 3 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 5, 5 ], "K3E": [ 9, 12 ], "K3F": [ 9, 5 ], "K3G": [ 9, 4 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K4D": [ 10, 12 ], "K4E": [ 10, 5 ], "K4F": [ 10, 4 ], "K4G": [ 10, 3 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ], "K5C": [ 11, 12 ], "K5D": [ 11, 4 ] } ================================================ FILE: layouts/keyboards/system76/launch_heavy_1/leds.json ================================================ { "K00": [ 69 ], "K01": [ 70 ], "K02": [ 71 ], "K03": [ 72 ], "K04": [ 73 ], "K05": [ 74 ], "K06": [ 75 ], "K07": [ 76 ], "K08": [ 77 ], "K09": [ 78 ], "K0A": [ 79 ], "K0B": [ 80 ], "K0C": [ 81 ], "K0D": [ 82 ], "K0E": [ 83 ], "K0F": [ 101 ], "K0G": [ 102 ], "K0H": [ 103 ], "K0I": [ 104 ], "K10": [ 68 ], "K11": [ 67 ], "K12": [ 66 ], "K13": [ 65 ], "K14": [ 64 ], "K15": [ 63 ], "K16": [ 62 ], "K17": [ 61 ], "K18": [ 60 ], "K19": [ 59 ], "K1A": [ 58 ], "K1B": [ 57 ], "K1C": [ 56 ], "K1D": [ 55 ], "K1E": [ 54 ], "K1F": [ 100 ], "K1G": [ 99 ], "K1H": [ 98 ], "K1I": [ 97 ], "K20": [ 39 ], "K21": [ 40 ], "K22": [ 41 ], "K23": [ 42 ], "K24": [ 43 ], "K25": [ 44 ], "K26": [ 45 ], "K27": [ 46 ], "K28": [ 47 ], "K29": [ 48 ], "K2A": [ 49 ], "K2B": [ 50 ], "K2C": [ 51 ], "K2D": [ 52 ], "K2E": [ 53 ], "K2F": [ 93 ], "K2G": [ 94 ], "K2H": [ 95 ], "K2I": [ 96 ], "K30": [ 38 ], "K31": [ 37 ], "K32": [ 36 ], "K33": [ 35 ], "K34": [ 34 ], "K35": [ 33 ], "K36": [ 32 ], "K37": [ 31 ], "K38": [ 30 ], "K39": [ 29 ], "K3A": [ 28 ], "K3B": [ 27 ], "K3C": [ 26 ], "K3D": [ 25 ], "K3E": [ 92 ], "K3F": [ 91 ], "K3G": [ 90 ], "K40": [ 12 ], "K41": [ 11 ], "K42": [ 10 ], "K43": [ 9 ], "K44": [ 8 ], "K45": [ 7 ], "K46": [ 6 ], "K47": [ 5 ], "K48": [ 4 ], "K49": [ 3 ], "K4A": [ 2 ], "K4B": [ 1 ], "K4C": [ 0 ], "K4D": [ 87 ], "K4E": [ 88 ], "K4F": [ 89 ], "K4G": [ 84 ], "K50": [ 13 ], "K51": [ 14 ], "K52": [ 15 ], "K53": [ 16 ], "K54": [ 17 ], "K55": [ 18 ], "K56": [ 19 ], "K57": [ 20 ], "K58": [ 21 ], "K59": [ 22 ], "K5A": [ 23 ], "K5B": [ 24 ], "K5C": [ 86 ], "K5D": [ 85 ] } ================================================ FILE: layouts/keyboards/system76/launch_heavy_1/physical.json ================================================ [ { "backcolor": "#373737", "name": "Launch Heavy", "author": "Levi", "radii": "24px" }, [ { "y": 0.5, "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home", { "x": 0.25 }, "Print Screen", "", " / ", "" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp", { "x": 0.25 }, "Num Lock", { "c": "#ffe8d6" }, "/", "*", "-" ], [ { "c": "#636363", "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn", { "x": 0.25, "c": "#ffe8d6", "a": 5 }, "7\nHome", "8\n↑", "9\nPgUp", { "a": 7, "h": 2 }, "+" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End", { "x": 0.25, "c": "#ffe8d6", "a": 5 }, "4\n←", { "n": true }, "5", "6\n→" ], [ { "x": 0.25, "c": "#636363", "a": 7, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up", { "x": 1.25, "c": "#ffe8d6", "a": 5 }, "1\nEnd", "2\n↓", "3\nPgDn", { "c": "#636363", "a": 7, "h": 2 }, "Enter" ], [ { "x": 0.25, "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right", { "x": 0.25, "c": "#ffe8d6", "a": 5, "w": 2 }, "0\nIns", ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/launch_heavy_3/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 3, 13 ], "K0F": [ 6, 12 ], "K0G": [ 6, 5 ], "K0H": [ 6, 4 ], "K0I": [ 6, 3 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 4, 13 ], "K1F": [ 7, 12 ], "K1G": [ 7, 5 ], "K1H": [ 7, 4 ], "K1I": [ 7, 3 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 2, 13 ], "K2E": [ 5, 13 ], "K2F": [ 8, 12 ], "K2G": [ 8, 5 ], "K2H": [ 8, 4 ], "K2I": [ 8, 3 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 5, 5 ], "K3E": [ 9, 12 ], "K3F": [ 9, 5 ], "K3G": [ 9, 4 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 5 ], "K46": [ 4, 6 ], "K47": [ 4, 7 ], "K48": [ 4, 8 ], "K49": [ 4, 9 ], "K4A": [ 4, 10 ], "K4B": [ 4, 11 ], "K4C": [ 4, 12 ], "K4D": [ 10, 12 ], "K4E": [ 10, 5 ], "K4F": [ 10, 4 ], "K4G": [ 10, 3 ], "K50": [ 5, 0 ], "K51": [ 5, 1 ], "K52": [ 5, 2 ], "K53": [ 5, 3 ], "K54": [ 5, 4 ], "K55": [ 5, 6 ], "K56": [ 5, 7 ], "K57": [ 5, 8 ], "K58": [ 5, 9 ], "K59": [ 5, 10 ], "K5A": [ 5, 11 ], "K5B": [ 5, 12 ], "K5C": [ 11, 12 ], "K5D": [ 11, 4 ] } ================================================ FILE: layouts/keyboards/system76/launch_heavy_3/leds.json ================================================ { "K00": [ 69 ], "K01": [ 70 ], "K02": [ 71 ], "K03": [ 72 ], "K04": [ 73 ], "K05": [ 74 ], "K06": [ 75 ], "K07": [ 76 ], "K08": [ 77 ], "K09": [ 78 ], "K0A": [ 79 ], "K0B": [ 80 ], "K0C": [ 81 ], "K0D": [ 82 ], "K0E": [ 83 ], "K0F": [ 101 ], "K0G": [ 102 ], "K0H": [ 103 ], "K0I": [ 104 ], "K10": [ 68 ], "K11": [ 67 ], "K12": [ 66 ], "K13": [ 65 ], "K14": [ 64 ], "K15": [ 63 ], "K16": [ 62 ], "K17": [ 61 ], "K18": [ 60 ], "K19": [ 59 ], "K1A": [ 58 ], "K1B": [ 57 ], "K1C": [ 56 ], "K1D": [ 55 ], "K1E": [ 54 ], "K1F": [ 100 ], "K1G": [ 99 ], "K1H": [ 98 ], "K1I": [ 97 ], "K20": [ 39 ], "K21": [ 40 ], "K22": [ 41 ], "K23": [ 42 ], "K24": [ 43 ], "K25": [ 44 ], "K26": [ 45 ], "K27": [ 46 ], "K28": [ 47 ], "K29": [ 48 ], "K2A": [ 49 ], "K2B": [ 50 ], "K2C": [ 51 ], "K2D": [ 52 ], "K2E": [ 53 ], "K2F": [ 93 ], "K2G": [ 94 ], "K2H": [ 95 ], "K2I": [ 96 ], "K30": [ 38 ], "K31": [ 37 ], "K32": [ 36 ], "K33": [ 35 ], "K34": [ 34 ], "K35": [ 33 ], "K36": [ 32 ], "K37": [ 31 ], "K38": [ 30 ], "K39": [ 29 ], "K3A": [ 28 ], "K3B": [ 27 ], "K3C": [ 26 ], "K3D": [ 25 ], "K3E": [ 92 ], "K3F": [ 91 ], "K3G": [ 90 ], "K40": [ 12 ], "K41": [ 11 ], "K42": [ 10 ], "K43": [ 9 ], "K44": [ 8 ], "K45": [ 7 ], "K46": [ 6 ], "K47": [ 5 ], "K48": [ 4 ], "K49": [ 3 ], "K4A": [ 2 ], "K4B": [ 1 ], "K4C": [ 0 ], "K4D": [ 87 ], "K4E": [ 88 ], "K4F": [ 89 ], "K4G": [ 84 ], "K50": [ 13 ], "K51": [ 14 ], "K52": [ 15 ], "K53": [ 16 ], "K54": [ 17 ], "K55": [ 18 ], "K56": [ 19 ], "K57": [ 20 ], "K58": [ 21 ], "K59": [ 22 ], "K5A": [ 23 ], "K5B": [ 24 ], "K5C": [ 86 ], "K5D": [ 85 ] } ================================================ FILE: layouts/keyboards/system76/launch_heavy_3/physical.json ================================================ [ { "backcolor": "#373737", "name": "Launch Heavy", "author": "Levi", "radii": "24px" }, [ { "y": 0.5, "c": "#755841", "a": 7 }, "Esc", { "c": "#636363" }, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", { "w": 1.5 }, "Del", { "x": 0.25 }, "Home", { "x": 0.25 }, "Print Screen", "", " / ", "" ], [ { "c": "#ffe8d6", "a": 5 }, "~\n`", "!\n1", "@\n2", "#\n3", "$\n4", "%\n5", "^\n6", "&\n7", "*\n8", "(\n9", ")\n0", "_\n-", "+\n=", { "c": "#636363", "a": 7, "w": 1.5 }, "Bksp", { "x": 0.25 }, "PgUp", { "x": 0.25 }, "Num Lock", { "c": "#ffe8d6" }, "/", "*", "-" ], [ { "c": "#636363", "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgDn", { "x": 0.25, "c": "#ffe8d6", "a": 5 }, "7\nHome", "8\n↑", "9\nPgUp", { "a": 7, "h": 2 }, "+" ], [ { "x": 0.25, "c": "#636363", "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "End", { "x": 0.25, "c": "#ffe8d6", "a": 5 }, "4\n←", { "n": true }, "5", "6\n→" ], [ { "x": 0.25, "c": "#636363", "a": 7, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up", { "x": 1.25, "c": "#ffe8d6", "a": 5 }, "1\nEnd", "2\n↓", "3\nPgDn", { "c": "#636363", "a": 7, "h": 2 }, "Enter" ], [ { "x": 0.25, "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right", { "x": 0.25, "c": "#ffe8d6", "a": 5, "w": 2 }, "0\nIns", ".\nDel" ] ] ================================================ FILE: layouts/keyboards/system76/launch_lite_1/layout.json ================================================ { "K00": [ 0, 0 ], "K01": [ 0, 1 ], "K02": [ 0, 2 ], "K03": [ 0, 3 ], "K04": [ 0, 4 ], "K05": [ 0, 5 ], "K06": [ 0, 6 ], "K07": [ 0, 7 ], "K08": [ 0, 8 ], "K09": [ 0, 9 ], "K0A": [ 0, 10 ], "K0B": [ 0, 11 ], "K0C": [ 0, 12 ], "K0D": [ 0, 13 ], "K0E": [ 2, 13 ], "K10": [ 1, 0 ], "K11": [ 1, 1 ], "K12": [ 1, 2 ], "K13": [ 1, 3 ], "K14": [ 1, 4 ], "K15": [ 1, 5 ], "K16": [ 1, 6 ], "K17": [ 1, 7 ], "K18": [ 1, 8 ], "K19": [ 1, 9 ], "K1A": [ 1, 10 ], "K1B": [ 1, 11 ], "K1C": [ 1, 12 ], "K1D": [ 1, 13 ], "K1E": [ 3, 13 ], "K20": [ 2, 0 ], "K21": [ 2, 1 ], "K22": [ 2, 2 ], "K23": [ 2, 3 ], "K24": [ 2, 4 ], "K25": [ 2, 5 ], "K26": [ 2, 6 ], "K27": [ 2, 7 ], "K28": [ 2, 8 ], "K29": [ 2, 9 ], "K2A": [ 2, 10 ], "K2B": [ 2, 11 ], "K2C": [ 2, 12 ], "K2D": [ 4, 13 ], "K30": [ 3, 0 ], "K31": [ 3, 1 ], "K32": [ 3, 2 ], "K33": [ 3, 3 ], "K34": [ 3, 4 ], "K35": [ 3, 5 ], "K36": [ 3, 6 ], "K37": [ 3, 7 ], "K38": [ 3, 8 ], "K39": [ 3, 9 ], "K3A": [ 3, 10 ], "K3B": [ 3, 11 ], "K3C": [ 3, 12 ], "K3D": [ 4, 5 ], "K40": [ 4, 0 ], "K41": [ 4, 1 ], "K42": [ 4, 2 ], "K43": [ 4, 3 ], "K44": [ 4, 4 ], "K45": [ 4, 6 ], "K46": [ 4, 7 ], "K47": [ 4, 8 ], "K48": [ 4, 9 ], "K49": [ 4, 10 ], "K4A": [ 4, 11 ], "K4B": [ 4, 12 ] } ================================================ FILE: layouts/keyboards/system76/launch_lite_1/leds.json ================================================ { "K00": [ 68 ], "K01": [ 67 ], "K02": [ 66 ], "K03": [ 65 ], "K04": [ 64 ], "K05": [ 63 ], "K06": [ 62 ], "K07": [ 61 ], "K08": [ 60 ], "K09": [ 59 ], "K0A": [ 58 ], "K0B": [ 57 ], "K0C": [ 56 ], "K0D": [ 55 ], "K0E": [ 69 ], "K10": [ 39 ], "K11": [ 40 ], "K12": [ 41 ], "K13": [ 42 ], "K14": [ 43 ], "K15": [ 44 ], "K16": [ 45 ], "K17": [ 46 ], "K18": [ 47 ], "K19": [ 48 ], "K1A": [ 49 ], "K1B": [ 50 ], "K1C": [ 51 ], "K1D": [ 52 ], "K1E": [ 54 ], "K20": [ 38 ], "K21": [ 37 ], "K22": [ 36 ], "K23": [ 35 ], "K24": [ 34 ], "K25": [ 33 ], "K26": [ 32 ], "K27": [ 31 ], "K28": [ 30 ], "K29": [ 29 ], "K2A": [ 28 ], "K2B": [ 27 ], "K2C": [ 26 ], "K2D": [ 53 ], "K30": [ 12 ], "K31": [ 11 ], "K32": [ 10 ], "K33": [ 9 ], "K34": [ 8 ], "K35": [ 7 ], "K36": [ 6 ], "K37": [ 5 ], "K38": [ 4 ], "K39": [ 3 ], "K3A": [ 2 ], "K3B": [ 1 ], "K3C": [ 0 ], "K3D": [ 25 ], "K40": [ 13 ], "K41": [ 14 ], "K42": [ 15 ], "K43": [ 16 ], "K44": [ 17 ], "K45": [ 18 ], "K46": [ 19 ], "K47": [ 20 ], "K48": [ 21 ], "K49": [ 22 ], "K4A": [ 23 ], "K4B": [ 24 ] } ================================================ FILE: layouts/keyboards/system76/launch_lite_1/physical.json ================================================ [ { "backcolor": "#373737", "name": "Launch Lite", "author": "Levi", "radii": "24px" }, [ { "c": "#755841" }, "`\n\n~\n\n\n\n\n\n\n\nEsc", { "c": "#ffe8d6" }, "\n1\n\n!\n\n\n\n\nF1", "\n2\n\n@\n\n\n\n\nF2", "\n3\n\n#\n\n\n\n\nF3", "\n4\n\n$\n\n\n\n\nF4", "\n5\n\n%\n\n\n\n\nF5", "\n6\n\n^\n\n\n\n\nF6", "\n7\n\n&\n\n\n\n\nF7", "\n8\n\n*\n\n\n\n\nF8", "\n9\n\n(\n\n\n\n\nF9", "\n0\n\n)\n\n\n\n\nF10", "\n-\n\n_\n\n\n\n\nF11", "\n=\n\n+\n\n\n\n\nF12", { "c": "#636363", "a": 5, "w": 1.5 }, "Del\nBksp", { "x": 0.25, "a": 7 }, "Home" ], [ { "w": 1.5 }, "Tab", { "c": "#ffe8d6" }, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", { "a": 5 }, "{\n[", "}\n]", "|\n\\", { "x": 0.25, "c": "#636363", "a": 7 }, "PgUp" ], [ { "x": 0.25, "w": 1.5 }, "Caps", { "c": "#ffe8d6" }, "A", "S", "D", { "n": true }, "F", "G", "H", { "n": true }, "J", "K", "L", { "a": 5 }, ":\n;", "\"\n'", { "c": "#636363", "a": 7, "w": 1.5 }, "Enter", { "x": 0.5 }, "PgDn" ], [ { "x": 0.25, "w": 2 }, "Shift", { "c": "#ffe8d6" }, "Z", "X", "C", "V", "B", "N", "M", { "a": 5 }, "<\n,", ">\n.", "?\n/", { "c": "#636363", "a": 7, "w": 1.5 }, "Shift", { "c": "#755841" }, "Up", { "c": "#636363" }, "End" ], [ { "x": 0.25, "w": 1.5 }, "Ctrl", "Alt", "Fn", "Super", { "c": "#ffe8d6", "w": 2 }, "Space", { "w": 2 }, "Space", { "c": "#636363" }, "Ctrl", "Alt", { "w": 1.5 }, "Fn", { "x": 0.5, "c": "#755841" }, "Left", { "n": true }, "Down", "Right" ] ] ================================================ FILE: layouts/keymap/ec.json ================================================ { "NONE": 0, "FN": 4096, "DISPLAY_MODE": 8192, "PRINT_SCREEN": 8193, "PAUSE": 8194, "DISPLAY_TOGGLE": 16395, "BRIGHTNESS_DOWN": 16401, "BRIGHTNESS_UP": 16402, "CAMERA_TOGGLE": 16403, "AIRPLANE_MODE": 16404, "SUSPEND": 16405, "KBD_COLOR": 32896, "KBD_DOWN": 32897, "KBD_UP": 32898, "KBD_BKL": 32906, "KBD_TOGGLE": 32927, "FAN_TOGGLE": 33010, "PLAY_PAUSE": 308, "MUTE": 291, "VOLUME_DOWN": 289, "VOLUME_UP": 306, "MEDIA_NEXT": 333, "MEDIA_PREV": 277, "TOUCHPAD": 355, "MIC_MUTE": 374, "F1": 5, "F2": 6, "F3": 4, "F4": 12, "F5": 3, "F6": 11, "F7": 131, "F8": 10, "F9": 1, "F10": 9, "F11": 120, "F12": 7, "0": 69, "1": 22, "2": 30, "3": 38, "4": 37, "5": 46, "6": 54, "7": 61, "8": 62, "9": 70, "A": 28, "B": 50, "C": 33, "D": 35, "E": 36, "F": 43, "G": 52, "H": 51, "I": 67, "J": 59, "K": 66, "L": 75, "M": 58, "N": 49, "O": 68, "P": 77, "Q": 21, "R": 45, "S": 27, "T": 44, "U": 60, "V": 42, "W": 29, "X": 34, "Y": 53, "Z": 26, "ESC": 118, "SCROLL_LOCK": 126, "TICK": 14, "MINUS": 78, "EQUALS": 85, "BKSP": 102, "TAB": 13, "BRACE_OPEN": 84, "BRACE_CLOSE": 91, "BACKSLASH": 93, "CAPS": 88, "SEMICOLON": 76, "QUOTE": 82, "ENTER": 90, "LEFT_SHIFT": 18, "COMMA": 65, "PERIOD": 73, "SLASH": 74, "RIGHT_SHIFT": 89, "LEFT_CTRL": 20, "LEFT_SUPER": 287, "LEFT_ALT": 17, "SPACE": 41, "RIGHT_ALT": 273, "RIGHT_SUPER": 295, "APP": 303, "RIGHT_CTRL": 276, "INSERT": 368, "DEL": 369, "HOME": 364, "END": 361, "PGUP": 381, "PGDN": 378, "UP": 373, "LEFT": 363, "DOWN": 370, "RIGHT": 372, "NUM_LOCK": 119, "NUM_SLASH": 330, "NUM_ASTERISK": 124, "NUM_MINUS": 123, "NUM_PLUS": 121, "NUM_PERIOD": 113, "NUM_ENTER": 346, "NUM_0": 112, "NUM_1": 105, "NUM_2": 114, "NUM_3": 122, "NUM_4": 107, "NUM_5": 115, "NUM_6": 116, "NUM_7": 108, "NUM_8": 117, "NUM_9": 125, "FNLOCK": 513 } ================================================ FILE: layouts/keymap/qmk.json ================================================ { "NONE": 0, "ROLL_OVER": 1, "A": 4, "B": 5, "C": 6, "D": 7, "E": 8, "F": 9, "G": 10, "H": 11, "I": 12, "J": 13, "K": 14, "L": 15, "M": 16, "N": 17, "O": 18, "P": 19, "Q": 20, "R": 21, "S": 22, "T": 23, "U": 24, "V": 25, "W": 26, "X": 27, "Y": 28, "Z": 29, "1": 30, "2": 31, "3": 32, "4": 33, "5": 34, "6": 35, "7": 36, "8": 37, "9": 38, "0": 39, "ENTER": 40, "ESC": 41, "BKSP": 42, "TAB": 43, "SPACE": 44, "MINUS": 45, "EQUALS": 46, "BRACE_OPEN": 47, "BRACE_CLOSE": 48, "BACKSLASH": 49, "NONUS_HASH": 50, "SEMICOLON": 51, "QUOTE": 52, "TICK": 53, "COMMA": 54, "PERIOD": 55, "SLASH": 56, "CAPS": 57, "F1": 58, "F2": 59, "F3": 60, "F4": 61, "F5": 62, "F6": 63, "F7": 64, "F8": 65, "F9": 66, "F10": 67, "F11": 68, "F12": 69, "PRINT_SCREEN": 70, "SCROLL_LOCK": 71, "PAUSE": 72, "INSERT": 73, "HOME": 74, "PGUP": 75, "DEL": 76, "END": 77, "PGDN": 78, "RIGHT": 79, "LEFT": 80, "DOWN": 81, "UP": 82, "NUM_LOCK": 83, "NUM_SLASH": 84, "NUM_ASTERISK": 85, "NUM_MINUS": 86, "NUM_PLUS": 87, "NUM_ENTER": 88, "NUM_1": 89, "NUM_2": 90, "NUM_3": 91, "NUM_4": 92, "NUM_5": 93, "NUM_6": 94, "NUM_7": 95, "NUM_8": 96, "NUM_9": 97, "NUM_0": 98, "NUM_PERIOD": 99, "NONUS_BACKSLASH": 100, "APP": 101, "KB_POWER": 102, "NUM_EQUALS": 103, "F13": 104, "F14": 105, "F15": 106, "F16": 107, "F17": 108, "F18": 109, "F19": 110, "F20": 111, "F21": 112, "F22": 113, "F23": 114, "F24": 115, "EXECUTE": 116, "HELP": 117, "MENU": 118, "SELECT": 119, "STOP": 120, "AGAIN": 121, "UNDO": 122, "CUT": 123, "COPY": 124, "PASTE": 125, "FIND": 126, "KB_MUTE": 127, "KB_VOLUME_UP": 128, "KB_VOLUME_DOWN": 129, "LOCKING_CAPS_LOCK": 130, "LOCKING_NUM_LOCK": 131, "LOCKING_SCROLL_LOCK": 132, "NUM_COMMA": 133, "KP_EQUAL_AS400": 134, "INT1": 135, "INT2": 136, "INT3": 137, "INT4": 138, "INT5": 139, "INT6": 140, "INT7": 141, "INT8": 142, "INT9": 143, "LANGUAGE_1": 144, "LANGUAGE_2": 145, "LANGUAGE_3": 146, "LANGUAGE_4": 147, "LANGUAGE_5": 148, "LANGUAGE_6": 149, "LANGUAGE_7": 150, "LANGUAGE_8": 151, "LANGUAGE_9": 152, "ALTERNATE_ERASE": 153, "SYSTEM_REQUEST": 154, "CANCEL": 155, "CLEAR": 156, "PRIOR": 157, "RETURN": 158, "SEPARATOR": 159, "OUT": 160, "OPER": 161, "CLEAR_AGAIN": 162, "CRSEL": 163, "EXSEL": 164, "SYSTEM_POWER": 165, "SUSPEND": 166, "SYSTEM_WAKE": 167, "MUTE": 168, "VOLUME_UP": 169, "VOLUME_DOWN": 170, "MEDIA_NEXT": 171, "MEDIA_PREV": 172, "MEDIA_STOP": 173, "PLAY_PAUSE": 174, "MEDIA_SELECT": 175, "MEDIA_EJECT": 176, "MAIL": 177, "CALCULATOR": 178, "MY_COMPUTER": 179, "WWW_SEARCH": 180, "WWW_HOME": 181, "WWW_BACK": 182, "WWW_FORWARD": 183, "WWW_STOP": 184, "WWW_REFRESH": 185, "WWW_FAVORITES": 186, "MEDIA_FAST_FORWARD": 187, "MEDIA_REWIND": 188, "BRIGHTNESS_UP": 189, "BRIGHTNESS_DOWN": 190, "CONTROL_PANEL": 191, "ASSISTANT": 192, "MS_UP": 205, "MS_DOWN": 206, "MS_LEFT": 207, "MS_RIGHT": 208, "MS_BTN1": 209, "MS_BTN2": 210, "MS_BTN3": 211, "MS_BTN4": 212, "MS_BTN5": 213, "MS_BTN6": 214, "MS_BTN7": 215, "MS_BTN8": 216, "MS_WH_UP": 217, "MS_WH_DOWN": 218, "MS_WH_LEFT": 219, "MS_WH_RIGHT": 220, "MS_ACCEL0": 221, "MS_ACCEL1": 222, "MS_ACCEL2": 223, "LEFT_CTRL": 224, "LEFT_SHIFT": 225, "LEFT_ALT": 226, "LEFT_SUPER": 227, "RIGHT_CTRL": 228, "RIGHT_SHIFT": 229, "RIGHT_ALT": 230, "RIGHT_SUPER": 231, "KBD_TOGGLE": 30752, "RGB_MODE_FORWARD": 30753, "RGB_MODE_REVERSE": 30754, "RGB_HUI": 30755, "RGB_HUD": 30756, "RGB_SAI": 30757, "RGB_SAD": 30758, "KBD_UP": 30759, "KBD_DOWN": 30760, "RGB_SPI": 30761, "RGB_SPD": 30762, "RGB_MODE_PLAIN": 30763, "RGB_MODE_BREATHE": 30764, "RGB_MODE_RAINBOW": 30765, "RGB_MODE_SWIRL": 30766, "RGB_MODE_SNAKE": 30767, "RGB_MODE_KNIGHT": 30768, "RGB_MODE_XMAS": 30769, "RGB_MODE_GRADIENT": 30770, "RGB_MODE_RGBTEST": 30771, "RGB_MODE_TWINKLE": 30772, "BASIC_MAX": 255, "MODS": 256, "MODS_MAX": 8191, "MOD_TAP": 8192, "MOD_TAP_MAX": 16383, "LAYER_TAP": 16384, "LAYER_TAP_MAX": 20479, "LAYER_MOD": 20480, "LAYER_MOD_MAX": 20991, "LAYER_SWITCH_1": 20992, "TO_MAX": 21023, "LAYER_ACCESS_1": 21024, "MOMENTARY_MAX": 21055, "DEF_LAYER": 21056, "DEF_LAYER_MAX": 21087, "LAYER_TOGGLE_1": 21088, "TOGGLE_LAYER_MAX": 21119, "ONE_SHOT_LAYER": 21120, "ONE_SHOT_LAYER_MAX": 21151, "ONE_SHOT_MOD": 21152, "ONE_SHOT_MOD_MAX": 21183, "LAYER_TAP_TOGGLE": 21184, "LAYER_TAP_TOGGLE_MAX": 21215, "SWAP_HANDS": 22016, "SWAP_HANDS_MAX": 22271, "TAP_DANCE": 22272, "TAP_DANCE_MAX": 22527, "MAGIC": 28672, "MAGIC_MAX": 28927, "MIDI_ON": 28928, "MIDI_MAX": 29183, "SEQUENCER": 29184, "SEQUENCER_MAX": 29695, "JOYSTICK": 29696, "JOYSTICK_MAX": 29759, "PROGRAMMABLE_BUTTON": 29760, "PROGRAMMABLE_BUTTON_MAX": 29823, "AUDIO_ON": 29824, "AUDIO_MAX": 29887, "STENO": 29888, "STENO_MAX": 29951, "MACRO_0": 30464, "MACRO_MAX": 30591, "BACKLIGHT_ON": 30720, "LIGHTING_MAX": 30975, "RESET": 31744, "QUANTUM_MAX": 32255, "KB": 32256, "KB_MAX": 32511, "USER": 32512, "USER_MAX": 32767, "UNICODE": 32768, "UNICODE_MAX": 65535, "MIDI_OFF": 28929, "MIDI_TOGGLE": 28930, "MIDI_NOTE_C_0": 28944, "MIDI_NOTE_C_SHARP_0": 28945, "MIDI_NOTE_D_0": 28946, "MIDI_NOTE_D_SHARP_0": 28947, "MIDI_NOTE_E_0": 28948, "MIDI_NOTE_F_0": 28949, "MIDI_NOTE_F_SHARP_0": 28950, "MIDI_NOTE_G_0": 28951, "MIDI_NOTE_G_SHARP_0": 28952, "MIDI_NOTE_A_0": 28953, "MIDI_NOTE_A_SHARP_0": 28954, "MIDI_NOTE_B_0": 28955, "MIDI_NOTE_C_1": 28960, "MIDI_NOTE_C_SHARP_1": 28961, "MIDI_NOTE_D_1": 28962, "MIDI_NOTE_D_SHARP_1": 28963, "MIDI_NOTE_E_1": 28964, "MIDI_NOTE_F_1": 28965, "MIDI_NOTE_F_SHARP_1": 28966, "MIDI_NOTE_G_1": 28967, "MIDI_NOTE_G_SHARP_1": 28968, "MIDI_NOTE_A_1": 28969, "MIDI_NOTE_A_SHARP_1": 28970, "MIDI_NOTE_B_1": 28971, "MIDI_NOTE_C_2": 28976, "MIDI_NOTE_C_SHARP_2": 28977, "MIDI_NOTE_D_2": 28978, "MIDI_NOTE_D_SHARP_2": 28979, "MIDI_NOTE_E_2": 28980, "MIDI_NOTE_F_2": 28981, "MIDI_NOTE_F_SHARP_2": 28982, "MIDI_NOTE_G_2": 28983, "MIDI_NOTE_G_SHARP_2": 28984, "MIDI_NOTE_A_2": 28985, "MIDI_NOTE_A_SHARP_2": 28986, "MIDI_NOTE_B_2": 28987, "MIDI_NOTE_C_3": 28992, "MIDI_NOTE_C_SHARP_3": 28993, "MIDI_NOTE_D_3": 28994, "MIDI_NOTE_D_SHARP_3": 28995, "MIDI_NOTE_E_3": 28996, "MIDI_NOTE_F_3": 28997, "MIDI_NOTE_F_SHARP_3": 28998, "MIDI_NOTE_G_3": 28999, "MIDI_NOTE_G_SHARP_3": 29000, "MIDI_NOTE_A_3": 29001, "MIDI_NOTE_A_SHARP_3": 29002, "MIDI_NOTE_B_3": 29003, "MIDI_NOTE_C_4": 29008, "MIDI_NOTE_C_SHARP_4": 29009, "MIDI_NOTE_D_4": 29010, "MIDI_NOTE_D_SHARP_4": 29011, "MIDI_NOTE_E_4": 29012, "MIDI_NOTE_F_4": 29013, "MIDI_NOTE_F_SHARP_4": 29014, "MIDI_NOTE_G_4": 29015, "MIDI_NOTE_G_SHARP_4": 29016, "MIDI_NOTE_A_4": 29017, "MIDI_NOTE_A_SHARP_4": 29018, "MIDI_NOTE_B_4": 29019, "MIDI_NOTE_C_5": 29024, "MIDI_NOTE_C_SHARP_5": 29025, "MIDI_NOTE_D_5": 29026, "MIDI_NOTE_D_SHARP_5": 29027, "MIDI_NOTE_E_5": 29028, "MIDI_NOTE_F_5": 29029, "MIDI_NOTE_F_SHARP_5": 29030, "MIDI_NOTE_G_5": 29031, "MIDI_NOTE_G_SHARP_5": 29032, "MIDI_NOTE_A_5": 29033, "MIDI_NOTE_A_SHARP_5": 29034, "MIDI_NOTE_B_5": 29035, "MIDI_OCTAVE_N2": 29040, "MIDI_OCTAVE_N1": 29041, "MIDI_OCTAVE_0": 29042, "MIDI_OCTAVE_1": 29043, "MIDI_OCTAVE_2": 29044, "MIDI_OCTAVE_3": 29045, "MIDI_OCTAVE_4": 29046, "MIDI_OCTAVE_5": 29047, "MIDI_OCTAVE_6": 29048, "MIDI_OCTAVE_7": 29049, "MIDI_OCTAVE_DOWN": 29050, "MIDI_OCTAVE_UP": 29051, "MIDI_TRANSPOSE_N6": 29056, "MIDI_TRANSPOSE_N5": 29057, "MIDI_TRANSPOSE_N4": 29058, "MIDI_TRANSPOSE_N3": 29059, "MIDI_TRANSPOSE_N2": 29060, "MIDI_TRANSPOSE_N1": 29061, "MIDI_TRANSPOSE_0": 29062, "MIDI_TRANSPOSE_1": 29063, "MIDI_TRANSPOSE_2": 29064, "MIDI_TRANSPOSE_3": 29065, "MIDI_TRANSPOSE_4": 29066, "MIDI_TRANSPOSE_5": 29067, "MIDI_TRANSPOSE_6": 29068, "MIDI_TRANSPOSE_DOWN": 29069, "MIDI_TRANSPOSE_UP": 29070, "MIDI_VELOCITY_0": 29072, "MIDI_VELOCITY_1": 29073, "MIDI_VELOCITY_2": 29074, "MIDI_VELOCITY_3": 29075, "MIDI_VELOCITY_4": 29076, "MIDI_VELOCITY_5": 29077, "MIDI_VELOCITY_6": 29078, "MIDI_VELOCITY_7": 29079, "MIDI_VELOCITY_8": 29080, "MIDI_VELOCITY_9": 29081, "MIDI_VELOCITY_10": 29082, "MIDI_VELOCITY_DOWN": 29083, "MIDI_VELOCITY_UP": 29084, "MIDI_CHANNEL_1": 29088, "MIDI_CHANNEL_2": 29089, "MIDI_CHANNEL_3": 29090, "MIDI_CHANNEL_4": 29091, "MIDI_CHANNEL_5": 29092, "MIDI_CHANNEL_6": 29093, "MIDI_CHANNEL_7": 29094, "MIDI_CHANNEL_8": 29095, "MIDI_CHANNEL_9": 29096, "MIDI_CHANNEL_10": 29097, "MIDI_CHANNEL_11": 29098, "MIDI_CHANNEL_12": 29099, "MIDI_CHANNEL_13": 29100, "MIDI_CHANNEL_14": 29101, "MIDI_CHANNEL_15": 29102, "MIDI_CHANNEL_16": 29103, "MIDI_CHANNEL_DOWN": 29104, "MIDI_CHANNEL_UP": 29105, "MIDI_ALL_NOTES_OFF": 29120, "MIDI_SUSTAIN": 29121, "MIDI_PORTAMENTO": 29122, "MIDI_SOSTENUTO": 29123, "MIDI_SOFT": 29124, "MIDI_LEGATO": 29125, "MIDI_MODULATION": 29126, "MIDI_MODULATION_SPEED_DOWN": 29127, "MIDI_MODULATION_SPEED_UP": 29128, "MIDI_PITCH_BEND_DOWN": 29129, "MIDI_PITCH_BEND_UP": 29130, "JOYSTICK_BUTTON_1": 29697, "JOYSTICK_BUTTON_2": 29698, "JOYSTICK_BUTTON_3": 29699, "JOYSTICK_BUTTON_4": 29700, "JOYSTICK_BUTTON_5": 29701, "JOYSTICK_BUTTON_6": 29702, "JOYSTICK_BUTTON_7": 29703, "JOYSTICK_BUTTON_8": 29704, "JOYSTICK_BUTTON_9": 29705, "JOYSTICK_BUTTON_10": 29706, "JOYSTICK_BUTTON_11": 29707, "JOYSTICK_BUTTON_12": 29708, "JOYSTICK_BUTTON_13": 29709, "JOYSTICK_BUTTON_14": 29710, "JOYSTICK_BUTTON_15": 29711, "JOYSTICK_BUTTON_16": 29712, "JOYSTICK_BUTTON_17": 29713, "JOYSTICK_BUTTON_18": 29714, "JOYSTICK_BUTTON_19": 29715, "JOYSTICK_BUTTON_20": 29716, "JOYSTICK_BUTTON_21": 29717, "JOYSTICK_BUTTON_22": 29718, "JOYSTICK_BUTTON_23": 29719, "JOYSTICK_BUTTON_24": 29720, "JOYSTICK_BUTTON_25": 29721, "JOYSTICK_BUTTON_26": 29722, "JOYSTICK_BUTTON_27": 29723, "JOYSTICK_BUTTON_28": 29724, "JOYSTICK_BUTTON_29": 29725, "JOYSTICK_BUTTON_30": 29726, "JOYSTICK_BUTTON_31": 29727, "PROGRAMMABLE_BUTTON_2": 29761, "PROGRAMMABLE_BUTTON_3": 29762, "PROGRAMMABLE_BUTTON_4": 29763, "PROGRAMMABLE_BUTTON_5": 29764, "PROGRAMMABLE_BUTTON_6": 29765, "PROGRAMMABLE_BUTTON_7": 29766, "PROGRAMMABLE_BUTTON_8": 29767, "PROGRAMMABLE_BUTTON_9": 29768, "PROGRAMMABLE_BUTTON_10": 29769, "PROGRAMMABLE_BUTTON_11": 29770, "PROGRAMMABLE_BUTTON_12": 29771, "PROGRAMMABLE_BUTTON_13": 29772, "PROGRAMMABLE_BUTTON_14": 29773, "PROGRAMMABLE_BUTTON_15": 29774, "PROGRAMMABLE_BUTTON_16": 29775, "PROGRAMMABLE_BUTTON_17": 29776, "PROGRAMMABLE_BUTTON_18": 29777, "PROGRAMMABLE_BUTTON_19": 29778, "PROGRAMMABLE_BUTTON_20": 29779, "PROGRAMMABLE_BUTTON_21": 29780, "PROGRAMMABLE_BUTTON_22": 29781, "PROGRAMMABLE_BUTTON_23": 29782, "PROGRAMMABLE_BUTTON_24": 29783, "PROGRAMMABLE_BUTTON_25": 29784, "PROGRAMMABLE_BUTTON_26": 29785, "PROGRAMMABLE_BUTTON_27": 29786, "PROGRAMMABLE_BUTTON_28": 29787, "PROGRAMMABLE_BUTTON_29": 29788, "PROGRAMMABLE_BUTTON_30": 29789, "PROGRAMMABLE_BUTTON_31": 29790, "PROGRAMMABLE_BUTTON_32": 29791, "AUDIO_OFF": 29825, "AUDIO_TOGGLE": 29826, "AUDIO_CLICKY_TOGGLE": 29834, "AUDIO_CLICKY_ON": 29835, "AUDIO_CLICKY_OFF": 29836, "AUDIO_CLICKY_UP": 29837, "AUDIO_CLICKY_DOWN": 29838, "AUDIO_CLICKY_RESET": 29839, "MUSIC_ON": 29840, "MUSIC_OFF": 29841, "MUSIC_TOGGLE": 29842, "MUSIC_MODE_NEXT": 29843, "AUDIO_VOICE_NEXT": 29844, "AUDIO_VOICE_PREVIOUS": 29845, "STENO_BOLT": 29936, "STENO_GEMINI": 29937, "STENO_COMB": 29938, "STENO_COMB_MAX": 29948, "MACRO_1": 30465, "MACRO_2": 30466, "MACRO_3": 30467, "MACRO_4": 30468, "MACRO_5": 30469, "MACRO_6": 30470, "MACRO_7": 30471, "MACRO_8": 30472, "MACRO_9": 30473, "MACRO_10": 30474, "MACRO_11": 30475, "MACRO_12": 30476, "MACRO_13": 30477, "MACRO_14": 30478, "MACRO_15": 30479, "MACRO_16": 30480, "MACRO_17": 30481, "MACRO_18": 30482, "MACRO_19": 30483, "MACRO_20": 30484, "MACRO_21": 30485, "MACRO_22": 30486, "MACRO_23": 30487, "MACRO_24": 30488, "MACRO_25": 30489, "MACRO_26": 30490, "MACRO_27": 30491, "MACRO_28": 30492, "MACRO_29": 30493, "MACRO_30": 30494, "MACRO_31": 30495, "BACKLIGHT_OFF": 30721, "BACKLIGHT_TOGGLE": 30722, "BACKLIGHT_DOWN": 30723, "BACKLIGHT_UP": 30724, "BACKLIGHT_STEP": 30725, "BACKLIGHT_TOGGLE_BREATHING": 30726, "REBOOT": 31745, "DEBUG_TOGGLE": 31746, "CLEAR_EEPROM": 31747, "MAKE": 31748, "AUTO_SHIFT_DOWN": 31760, "AUTO_SHIFT_UP": 31761, "AUTO_SHIFT_REPORT": 31762, "AUTO_SHIFT_ON": 31763, "AUTO_SHIFT_OFF": 31764, "AUTO_SHIFT_TOGGLE": 31765, "GRAVE_ESCAPE": 31766, "VELOCIKEY_TOGGLE": 31767, "SPACE_CADET_LEFT_CTRL_PARENTHESIS_OPEN": 31768, "SPACE_CADET_RIGHT_CTRL_PARENTHESIS_CLOSE": 31769, "SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN": 31770, "SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE": 31771, "SPACE_CADET_LEFT_ALT_PARENTHESIS_OPEN": 31772, "SPACE_CADET_RIGHT_ALT_PARENTHESIS_CLOSE": 31773, "SPACE_CADET_RIGHT_SHIFT_ENTER": 31774, "OUTPUT_AUTO": 31776, "OUTPUT_USB": 31777, "OUTPUT_BLUETOOTH": 31778, "UNICODE_MODE_NEXT": 31792, "UNICODE_MODE_PREVIOUS": 31793, "UNICODE_MODE_MACOS": 31794, "UNICODE_MODE_LINUX": 31795, "UNICODE_MODE_WINDOWS": 31796, "UNICODE_MODE_BSD": 31797, "UNICODE_MODE_WINCOMPOSE": 31798, "UNICODE_MODE_EMACS": 31799, "HAPTIC_ON": 31808, "HAPTIC_OFF": 31809, "HAPTIC_TOGGLE": 31810, "HAPTIC_RESET": 31811, "HAPTIC_FEEDBACK_TOGGLE": 31812, "HAPTIC_BUZZ_TOGGLE": 31813, "HAPTIC_MODE_NEXT": 31814, "HAPTIC_MODE_PREVIOUS": 31815, "HAPTIC_CONTINUOUS_TOGGLE": 31816, "HAPTIC_CONTINUOUS_UP": 31817, "HAPTIC_CONTINUOUS_DOWN": 31818, "HAPTIC_DWELL_UP": 31819, "HAPTIC_DWELL_DOWN": 31820, "COMBO_ON": 31824, "COMBO_OFF": 31825, "COMBO_TOGGLE": 31826, "DYNAMIC_MACRO_RECORD_START_1": 31827, "DYNAMIC_MACRO_RECORD_START_2": 31828, "DYNAMIC_MACRO_RECORD_STOP": 31829, "DYNAMIC_MACRO_PLAY_1": 31830, "DYNAMIC_MACRO_PLAY_2": 31831, "LEADER": 31832, "LOCK": 31833, "ONE_SHOT_ON": 31834, "ONE_SHOT_OFF": 31835, "ONE_SHOT_TOGGLE": 31836, "KEY_OVERRIDE_TOGGLE": 31837, "KEY_OVERRIDE_ON": 31838, "KEY_OVERRIDE_OFF": 31839, "SECURE_LOCK": 31840, "SECURE_UNLOCK": 31841, "SECURE_TOGGLE": 31842, "SECURE_REQUEST": 31843, "DYNAMIC_TAPPING_TERM_PRINT": 31856, "DYNAMIC_TAPPING_TERM_UP": 31857, "DYNAMIC_TAPPING_TERM_DOWN": 31858, "CAPS_WORD_TOGGLE": 31859, "AUTOCORRECT_ON": 31860, "AUTOCORRECT_OFF": 31861, "AUTOCORRECT_TOGGLE": 31862, "LAYER_TOGGLE_2": 21089, "LAYER_TOGGLE_3": 21090, "LAYER_TOGGLE_4": 21091, "LAYER_SWITCH_2": 20993, "LAYER_SWITCH_3": 20994, "LAYER_SWITCH_4": 20995, "FN": 21025, "LAYER_ACCESS_3": 21026, "LAYER_ACCESS_4": 21027 } ================================================ FILE: layouts/keymap/qmk_legacy.json ================================================ { "NONE": 0, "ROLL_OVER": 1, "POST_FAIL": 2, "UNDEFINED": 3, "A": 4, "B": 5, "C": 6, "D": 7, "E": 8, "F": 9, "G": 10, "H": 11, "I": 12, "J": 13, "K": 14, "L": 15, "M": 16, "N": 17, "O": 18, "P": 19, "Q": 20, "R": 21, "S": 22, "T": 23, "U": 24, "V": 25, "W": 26, "X": 27, "Y": 28, "Z": 29, "1": 30, "2": 31, "3": 32, "4": 33, "5": 34, "6": 35, "7": 36, "8": 37, "9": 38, "0": 39, "ENTER": 40, "ESC": 41, "BKSP": 42, "TAB": 43, "SPACE": 44, "MINUS": 45, "EQUALS": 46, "BRACE_OPEN": 47, "BRACE_CLOSE": 48, "BACKSLASH": 49, "NONUS_HASH": 50, "SEMICOLON": 51, "QUOTE": 52, "TICK": 53, "COMMA": 54, "PERIOD": 55, "SLASH": 56, "CAPS": 57, "F1": 58, "F2": 59, "F3": 60, "F4": 61, "F5": 62, "F6": 63, "F7": 64, "F8": 65, "F9": 66, "F10": 67, "F11": 68, "F12": 69, "PRINT_SCREEN": 70, "SCROLL_LOCK": 71, "PAUSE": 72, "INSERT": 73, "HOME": 74, "PGUP": 75, "DEL": 76, "END": 77, "PGDN": 78, "RIGHT": 79, "LEFT": 80, "DOWN": 81, "UP": 82, "NUM_LOCK": 83, "NUM_SLASH": 84, "NUM_ASTERISK": 85, "NUM_MINUS": 86, "NUM_PLUS": 87, "NUM_ENTER": 88, "NUM_1": 89, "NUM_2": 90, "NUM_3": 91, "NUM_4": 92, "NUM_5": 93, "NUM_6": 94, "NUM_7": 95, "NUM_8": 96, "NUM_9": 97, "NUM_0": 98, "NUM_PERIOD": 99, "NONUS_BSLASH": 100, "APP": 101, "POWER": 102, "NUM_EQUALS": 103, "F13": 104, "F14": 105, "F15": 106, "F16": 107, "F17": 108, "F18": 109, "F19": 110, "F20": 111, "F21": 112, "F22": 113, "F23": 114, "F24": 115, "EXECUTE": 116, "HELP": 117, "MENU": 118, "SELECT": 119, "STOP": 120, "AGAIN": 121, "UNDO": 122, "CUT": 123, "COPY": 124, "PASTE": 125, "FIND": 126, "_MUTE": 127, "_VOLUP": 128, "_VOLDOWN": 129, "LOCKING_CAPS": 130, "LOCKING_NUM": 131, "LOCKING_SCROLL": 132, "NUM_COMMA": 133, "KP_EQUAL_AS400": 134, "INT1": 135, "INT2": 136, "INT3": 137, "INT4": 138, "INT5": 139, "INT6": 140, "INT7": 141, "INT8": 142, "INT9": 143, "LANG1": 144, "LANG2": 145, "LANG3": 146, "LANG4": 147, "LANG5": 148, "LANG6": 149, "LANG7": 150, "LANG8": 151, "LANG9": 152, "ALT_ERASE": 153, "SYSREQ": 154, "CANCEL": 155, "CLEAR": 156, "PRIOR": 157, "RETURN": 158, "SEPARATOR": 159, "OUT": 160, "OPER": 161, "CLEAR_AGAIN": 162, "CRSEL": 163, "EXSEL": 164, "LEFT_CTRL": 224, "LEFT_SHIFT": 225, "LEFT_ALT": 226, "LEFT_SUPER": 227, "RIGHT_CTRL": 228, "RIGHT_SHIFT": 229, "RIGHT_ALT": 230, "RIGHT_SUPER": 231, "SYSTEM_POWER": 165, "SUSPEND": 166, "SYSTEM_WAKE": 167, "MUTE": 168, "VOLUME_UP": 169, "VOLUME_DOWN": 170, "MEDIA_NEXT": 171, "MEDIA_PREV": 172, "MEDIA_STOP": 173, "PLAY_PAUSE": 174, "MEDIA_SELECT": 175, "MEDIA_EJECT": 176, "MAIL": 177, "CALCULATOR": 178, "MY_COMPUTER": 179, "WWW_SEARCH": 180, "WWW_HOME": 181, "WWW_BACK": 182, "WWW_FORWARD": 183, "WWW_STOP": 184, "WWW_REFRESH": 185, "WWW_FAVORITES": 186, "MEDIA_FAST_FORWARD": 187, "MEDIA_REWIND": 188, "BRIGHTNESS_UP": 189, "BRIGHTNESS_DOWN": 190, "FN0": 192, "FN1": 193, "FN2": 194, "FN3": 195, "FN4": 196, "FN5": 197, "FN6": 198, "FN7": 199, "FN8": 200, "FN9": 201, "FN10": 202, "FN11": 203, "FN12": 204, "FN13": 205, "FN14": 206, "FN15": 207, "FN16": 208, "FN17": 209, "FN18": 210, "FN19": 211, "FN20": 212, "FN21": 213, "FN22": 214, "FN23": 215, "FN24": 216, "FN25": 217, "FN26": 218, "FN27": 219, "FN28": 220, "FN29": 221, "FN30": 222, "FN31": 223, "MS_UP": 237, "MS_DOWN": 238, "MS_LEFT": 239, "MS_RIGHT": 240, "MS_BTN1": 241, "MS_BTN2": 242, "MS_BTN3": 243, "MS_BTN4": 244, "MS_BTN5": 245, "MS_BTN6": 246, "MS_BTN7": 247, "MS_BTN8": 248, "MS_WH_UP": 249, "MS_WH_DOWN": 250, "MS_WH_LEFT": 251, "MS_WH_RIGHT": 252, "MS_ACCEL0": 253, "MS_ACCEL1": 254, "MS_ACCEL2": 255, "KBD_TOGGLE": 23747, "RGB_MODE_FORWARD": 23748, "RGB_MODE_REVERSE": 23749, "RGB_HUI": 23750, "RGB_HUD": 23751, "RGB_SAI": 23752, "RGB_SAD": 23753, "KBD_UP": 23754, "KBD_DOWN": 23755, "RGB_SPI": 23756, "RGB_SPD": 23757, "RGB_MODE_PLAIN": 23758, "RGB_MODE_BREATHE": 23759, "RGB_MODE_RAINBOW": 23760, "RGB_MODE_SWIRL": 23761, "RGB_MODE_SNAKE": 23762, "RGB_MODE_KNIGHT": 23763, "RGB_MODE_XMAS": 23764, "RGB_MODE_GRADIENT": 23765, "RGB_MODE_RGBTEST": 23766, "LAYER_TOGGLE_1": 21248, "LAYER_TOGGLE_2": 21249, "LAYER_TOGGLE_3": 21250, "LAYER_TOGGLE_4": 21251, "LAYER_SWITCH_1": 20496, "LAYER_SWITCH_2": 20497, "LAYER_SWITCH_3": 20498, "LAYER_SWITCH_4": 20499, "LAYER_ACCESS_1": 20736, "FN": 20737, "LAYER_ACCESS_3": 20738, "LAYER_ACCESS_4": 20739, "RESET": 23552 } ================================================ FILE: layouts/picker.json ================================================ [ { "label": "Alphabet keys", "cols": 9, "width": 1, "keys": [ { "keysym": "A", "label": "A" }, { "keysym": "B", "label": "B" }, { "keysym": "C", "label": "C" }, { "keysym": "D", "label": "D" }, { "keysym": "E", "label": "E" }, { "keysym": "F", "label": "F" }, { "keysym": "G", "label": "G" }, { "keysym": "H", "label": "H" }, { "keysym": "I", "label": "I" }, { "keysym": "J", "label": "J" }, { "keysym": "K", "label": "K" }, { "keysym": "L", "label": "L" }, { "keysym": "M", "label": "M" }, { "keysym": "N", "label": "N" }, { "keysym": "O", "label": "O" }, { "keysym": "P", "label": "P" }, { "keysym": "Q", "label": "Q" }, { "keysym": "R", "label": "R" }, { "keysym": "S", "label": "S" }, { "keysym": "T", "label": "T" }, { "keysym": "U", "label": "U" }, { "keysym": "V", "label": "V" }, { "keysym": "W", "label": "W" }, { "keysym": "X", "label": "X" }, { "keysym": "Y", "label": "Y" }, { "keysym": "Z", "label": "Z" } ] }, { "label": "Number keys", "cols": 4, "width": 1, "keys": [ { "keysym": "1", "label": "!\n1" }, { "keysym": "2", "label": "@\n2" }, { "keysym": "3", "label": "#\n3" }, { "keysym": "4", "label": "$\n4" }, { "keysym": "5", "label": "%\n5" }, { "keysym": "6", "label": "^\n6" }, { "keysym": "7", "label": "&\n7" }, { "keysym": "8", "label": "*\n8" }, { "keysym": "9", "label": "(\n9" }, { "keysym": "0", "label": ")\n0" } ] }, { "label": "Modifier keys", "cols": 4, "width": 1, "keys": [ { "keysym": "LEFT_ALT", "label": "Left Alt" }, { "keysym": "RIGHT_ALT", "label": "Right Alt" }, { "keysym": "LEFT_CTRL", "label": "Left Ctrl" }, { "keysym": "RIGHT_CTRL", "label": "Right Ctrl" }, { "keysym": "LEFT_SHIFT", "label": "Left Shift" }, { "keysym": "RIGHT_SHIFT", "label": "Right Shift" }, { "keysym": "LEFT_SUPER", "label": "Left Super" }, { "keysym": "RIGHT_SUPER", "label": "Right Super" } ] }, { "label": "Actions", "cols": 4, "width": 1, "keys": [ { "keysym": "ENTER", "label": "Enter" }, { "keysym": "BKSP", "label": "Bksp" }, { "keysym": "DEL", "label": "Del" }, { "keysym": "TAB", "label": "Tab" }, { "keysym": "SPACE", "label": "Space" }, { "keysym": "CAPS", "label": "Caps" }, { "keysym": "APP", "label": "Menu" }, { "keysym": "ESC", "label": "Esc" }, { "keysym": "PRINT_SCREEN", "label": "PrtSc\nSysrq" }, { "keysym": "INSERT", "label": "Ins" }, { "keysym": "SCROLL_LOCK", "label": "Scroll Lock" }, { "keysym": "PAUSE", "label": "Pause\nBreak" }, { "keysym": "RESET", "label": "Reset" }, { "keysym": "ROLL_OVER", "label": "Reuse" }, { "keysym": "NONE", "label": "None" } ] }, { "label": "Function keys", "cols": 4, "width": 1, "keys": [ { "keysym": "F1", "label": "F1" }, { "keysym": "F2", "label": "F2" }, { "keysym": "F3", "label": "F3" }, { "keysym": "F4", "label": "F4" }, { "keysym": "F5", "label": "F5" }, { "keysym": "F6", "label": "F6" }, { "keysym": "F7", "label": "F7" }, { "keysym": "F8", "label": "F8" }, { "keysym": "F9", "label": "F9" }, { "keysym": "F10", "label": "F10" }, { "keysym": "F11", "label": "F11" }, { "keysym": "F12", "label": "F12" } ] }, { "label": "Numpad", "cols": 6, "width": 1, "keys": [ { "keysym": "NUM_LOCK", "label": "Num Lock" }, { "keysym": "NUM_7", "label": "7" }, { "keysym": "NUM_8", "label": "8" }, { "keysym": "NUM_9", "label": "9" }, { "keysym": "NUM_MINUS", "label": "-" }, { "keysym": "NUM_PLUS", "label": "+" }, { "keysym": "NUM_SLASH", "label": "/" }, { "keysym": "NUM_4", "label": "4" }, { "keysym": "NUM_5", "label": "5" }, { "keysym": "NUM_6", "label": "6" }, { "keysym": "NUM_ASTERISK", "label": "*" }, { "keysym": "NUM_ENTER", "label": "Enter" }, { "keysym": "NUM_0", "label": "0" }, { "keysym": "NUM_1", "label": "1" }, { "keysym": "NUM_2", "label": "2" }, { "keysym": "NUM_3", "label": "3" }, { "keysym": "NUM_PERIOD", "label": "." } ] }, { "label": "Symbols", "cols": 6, "width": 1, "keys": [ { "keysym": "TICK", "label": "~\n`" }, { "keysym": "QUOTE", "label": "\"\n'" }, { "keysym": "SEMICOLON", "label": ":\n;" }, { "keysym": "MINUS", "label": "_\n-" }, { "keysym": "EQUALS", "label": "+\n=" }, { "keysym": "SLASH", "label": "?\n/" }, { "keysym": "COMMA", "label": "<\n," }, { "keysym": "PERIOD", "label": ">\n." }, { "keysym": "BACKSLASH", "label": "|\n\\" }, { "keysym": "BRACE_OPEN", "label": "{\n[" }, { "keysym": "BRACE_CLOSE", "label": "}\n]" }, { "keysym": "NONUS_HASH", "label": "Non-US #" }, { "keysym": "NONUS_BSLASH", "label": "Non-US \\" } ] }, { "label": "Navigation", "cols": 4, "width": 1, "keys": [ { "keysym": "LEFT", "label": "Left" }, { "keysym": "UP", "label": "Up" }, { "keysym": "DOWN", "label": "Down" }, { "keysym": "RIGHT", "label": "Right" }, { "keysym": "HOME", "label": "Home" }, { "keysym": "PGUP", "label": "PgUp" }, { "keysym": "PGDN", "label": "PgDn" }, { "keysym": "END", "label": "End" } ] }, { "label": "Media", "cols": 3, "width": 1, "keys": [ { "keysym": "MUTE", "label": "Mute" }, { "keysym": "VOLUME_UP", "label": "Vol Up" }, { "keysym": "VOLUME_DOWN", "label": "Vol Down" }, { "keysym": "PLAY_PAUSE", "label": "Play Pause" }, { "keysym": "MEDIA_NEXT", "label": "Next Track" }, { "keysym": "MEDIA_PREV", "label": "Prev Track" }, { "keysym": "MIC_MUTE", "label": "Mic Mute" } ] }, { "label": "Controls", "cols": 4, "width": 2, "keys": [ { "keysym": "FAN_TOGGLE", "label": "Fan Toggle" }, { "keysym": "DISPLAY_TOGGLE", "label": "Screen Toggle" }, { "keysym": "BRIGHTNESS_UP", "label": "Screen Up" }, { "keysym": "BRIGHTNESS_DOWN", "label": "Screen Down" }, { "keysym": "DISPLAY_MODE", "label": "Screen Mode" }, { "keysym": "SUSPEND", "label": "Suspend" }, { "keysym": "CAMERA_TOGGLE", "label": "Camera Toggle" }, { "keysym": "AIRPLANE_MODE", "label": "Airplane Mode" }, { "keysym": "TOUCHPAD", "label": "Touchpad Toggle" }, { "keysym": "SYSTEM_POWER", "label": "Power" } ] }, { "label": "LED controls", "cols": 4, "width": 1, "keys": [ { "keysym": "KBD_TOGGLE", "label": "LED On Off" }, { "keysym": "KBD_UP", "label": "LED Brighten" }, { "keysym": "KBD_DOWN", "label": "LED Darken" }, { "keysym": "KBD_BKL", "label": "LED Cycle" }, { "keysym": "KBD_COLOR", "label": "LED Color" } ] }, { "label": "Layer keys", "cols": 4, "width": 2, "keys": [ { "keysym": "LAYER_ACCESS_1", "label": "Access Layer\u00a01" }, { "keysym": "FN", "label": "Access Layer\u00a02" }, { "keysym": "LAYER_ACCESS_3", "label": "Access Layer\u00a03" }, { "keysym": "LAYER_ACCESS_4", "label": "Access Layer\u00a04" }, { "keysym": "LAYER_SWITCH_1", "label": "Switch to\nLayer\u00a01" }, { "keysym": "LAYER_SWITCH_2", "label": "Switch to\nLayer\u00a02" }, { "keysym": "LAYER_SWITCH_3", "label": "Switch to\nLayer\u00a03" }, { "keysym": "LAYER_SWITCH_4", "label": "Switch to\nLayer\u00a04" }, { "keysym": "FNLOCK", "label": "FnLock" } ] } ] ================================================ FILE: layouts/system76/addw1/default.json ================================================ { "model": "system76/addw1", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/addw1/meta.json ================================================ { "display_name": "Adder WS", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/addw2/default.json ================================================ { "model": "system76/addw2", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/addw2/meta.json ================================================ { "display_name": "Adder WS", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/addw3/default.json ================================================ { "model": "system76/addw3", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/addw3/meta.json ================================================ { "display_name": "Adder WS", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/addw4/default.json ================================================ { "model": "system76/addw4", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/addw4/meta.json ================================================ { "display_name": "Adder WS", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA04" } ================================================ FILE: layouts/system76/bonw14/default.json ================================================ { "model": "system76/bonw14", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/bonw14/meta.json ================================================ { "display_name": "Bonobo WS", "has_brightness": false, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102_nkey" } ================================================ FILE: layouts/system76/bonw15/default.json ================================================ { "model": "system76/bonw15", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/bonw15/meta.json ================================================ { "display_name": "Bonobo WS", "has_brightness": false, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/darp10/default.json ================================================ { "model": "system76/darp10", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "NUM_SLASH" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp10/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA05" } ================================================ FILE: layouts/system76/darp10-b/default.json ================================================ { "model": "system76/darp10-b", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp10-b/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/darp11/default.json ================================================ { "model": "system76/darp11", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "NUM_SLASH" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp11/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA05" } ================================================ FILE: layouts/system76/darp11-b/default.json ================================================ { "model": "system76/darp11-b", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp11-b/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/darp5/default.json ================================================ { "model": "system76/darp5", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp5/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/darp6/default.json ================================================ { "model": "system76/darp6", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp6/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/darp7/default.json ================================================ { "model": "system76/darp7", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp7/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/darp8/default.json ================================================ { "model": "system76/darp8", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp8/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/darp9/default.json ================================================ { "model": "system76/darp9", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_BKL" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/darp9/meta.json ================================================ { "display_name": "Darter Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA05" } ================================================ FILE: layouts/system76/galp3-c/default.json ================================================ { "model": "system76/galp3-c", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "PAUSE", "PAUSE" ], "K0F": [ "INSERT", "NUM_LOCK" ], "K0G": [ "DEL", "SCROLL_LOCK" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "NUM_7" ], "K18": [ "8", "NUM_8" ], "K19": [ "9", "NUM_9" ], "K1A": [ "0", "NUM_ASTERISK" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "HOME", "HOME" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "NUM_4" ], "K28": [ "I", "NUM_5" ], "K29": [ "O", "NUM_6" ], "K2A": [ "P", "NUM_SLASH" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "PGUP", "PGUP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "NUM_1" ], "K38": [ "K", "NUM_2" ], "K39": [ "L", "NUM_3" ], "K3A": [ "SEMICOLON", "NUM_MINUS" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "NUM_ENTER" ], "K3D": [ "PGDN", "PGDN" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "NUM_0" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "NUM_PERIOD" ], "K4A": [ "SLASH", "NUM_PLUS" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "END", "END" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/galp3-c/meta.json ================================================ { "display_name": "Galago Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_86" } ================================================ FILE: layouts/system76/galp4/default.json ================================================ { "model": "system76/galp4", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "PAUSE", "PAUSE" ], "K0F": [ "INSERT", "NUM_LOCK" ], "K0G": [ "DEL", "SCROLL_LOCK" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "NUM_7" ], "K18": [ "8", "NUM_8" ], "K19": [ "9", "NUM_9" ], "K1A": [ "0", "NUM_ASTERISK" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "HOME", "HOME" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "NUM_4" ], "K28": [ "I", "NUM_5" ], "K29": [ "O", "NUM_6" ], "K2A": [ "P", "NUM_SLASH" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "PGUP", "PGUP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "NUM_1" ], "K38": [ "K", "NUM_2" ], "K39": [ "L", "NUM_3" ], "K3A": [ "SEMICOLON", "NUM_MINUS" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "NUM_ENTER" ], "K3D": [ "PGDN", "PGDN" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "NUM_0" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "NUM_PERIOD" ], "K4A": [ "SLASH", "NUM_PLUS" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "END", "END" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/galp4/meta.json ================================================ { "display_name": "Galago Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_86" } ================================================ FILE: layouts/system76/galp5/default.json ================================================ { "model": "system76/galp5", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/galp5/meta.json ================================================ { "display_name": "Galago Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/galp6/default.json ================================================ { "model": "system76/galp6", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/galp6/meta.json ================================================ { "display_name": "Galago Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/galp7/default.json ================================================ { "model": "system76/galp7", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/galp7/meta.json ================================================ { "display_name": "Galago Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/gaze15/default.json ================================================ { "model": "system76/gaze15", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze15/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze16-3050/default.json ================================================ { "model": "system76/gaze16-3050", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze16-3050/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze16-3060/default.json ================================================ { "model": "system76/gaze16-3060", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze16-3060/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze16-3060-b/default.json ================================================ { "model": "system76/gaze16-3060-b", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze16-3060-b/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze17-3050/default.json ================================================ { "model": "system76/gaze17-3050", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze17-3050/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze17-3060-b/default.json ================================================ { "model": "system76/gaze17-3060-b", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze17-3060-b/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze18/default.json ================================================ { "model": "system76/gaze18", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze18/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/gaze20/default.json ================================================ { "model": "system76/gaze20", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/gaze20/meta.json ================================================ { "display_name": "Gazelle", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/launch_1/default.json ================================================ { "model": "system76/launch_1", "version": 1, "map": { "K00": [ "ESC", "RESET", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "F1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "0", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "MINUS", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "EQUALS", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2E": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K50": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K51": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K52": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K53": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K59": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K5A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K5B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_1/meta.json ================================================ { "display_name": "Launch Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_1" } ================================================ FILE: layouts/system76/launch_2/default.json ================================================ { "model": "system76/launch_2", "version": 1, "map": { "K00": [ "ESC", "RESET", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "F1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "0", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "MINUS", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "EQUALS", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2E": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K50": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K51": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K52": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K53": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K59": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K5A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K5B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_2/meta.json ================================================ { "display_name": "Launch Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_2" } ================================================ FILE: layouts/system76/launch_3/default.json ================================================ { "model": "system76/launch_3", "version": 1, "map": { "K00": [ "ESC", "RESET", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "F1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "0", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "MINUS", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "EQUALS", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2E": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K50": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K51": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K52": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K53": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K59": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K5A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K5B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_3/meta.json ================================================ { "display_name": "Launch Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_3" } ================================================ FILE: layouts/system76/launch_alpha_1/default.json ================================================ { "model": "system76/launch_alpha_1", "version": 1, "map": { "K00": [ "ESC", "RESET" ], "K01": [ "F1", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER" ], "K1A": [ "0", "ROLL_OVER" ], "K1B": [ "MINUS", "ROLL_OVER" ], "K1C": [ "EQUALS", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER" ], "K20": [ "TAB", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER" ], "K26": [ "Y", "ROLL_OVER" ], "K27": [ "U", "ROLL_OVER" ], "K28": [ "I", "ROLL_OVER" ], "K29": [ "O", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER" ], "K36": [ "H", "ROLL_OVER" ], "K37": [ "J", "ROLL_OVER" ], "K38": [ "K", "ROLL_OVER" ], "K39": [ "L", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER" ], "K4C": [ "UP", "PGUP" ], "K50": [ "LEFT_CTRL", "ROLL_OVER" ], "K51": [ "FN", "ROLL_OVER" ], "K52": [ "LEFT_SUPER", "ROLL_OVER" ], "K53": [ "LEFT_ALT", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER" ], "K59": [ "LEFT", "HOME" ], "K5A": [ "DOWN", "PGDN" ], "K5B": [ "RIGHT", "END" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_alpha_1/meta.json ================================================ { "display_name": "Launch Alpha Keyboard", "has_brightness": true, "has_color": true, "is_qmk": true, "pressed_color": "#202020", "keyboard": "system76/launch_alpha_1" } ================================================ FILE: layouts/system76/launch_alpha_2/default.json ================================================ { "model": "system76/launch_alpha_2", "version": 1, "map": { "K00": [ "ESC", "RESET" ], "K01": [ "F1", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER" ], "K0E": [ "HOME", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER" ], "K1A": [ "0", "ROLL_OVER" ], "K1B": [ "MINUS", "ROLL_OVER" ], "K1C": [ "EQUALS", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER" ], "K1E": [ "PGUP", "ROLL_OVER" ], "K20": [ "TAB", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER" ], "K26": [ "Y", "ROLL_OVER" ], "K27": [ "U", "ROLL_OVER" ], "K28": [ "I", "ROLL_OVER" ], "K29": [ "O", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER" ], "K2E": [ "PGDN", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER" ], "K36": [ "H", "ROLL_OVER" ], "K37": [ "J", "ROLL_OVER" ], "K38": [ "K", "ROLL_OVER" ], "K39": [ "L", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER" ], "K3D": [ "END", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER" ], "K4C": [ "UP", "PGUP" ], "K50": [ "LEFT_CTRL", "ROLL_OVER" ], "K51": [ "FN", "ROLL_OVER" ], "K52": [ "LEFT_SUPER", "ROLL_OVER" ], "K53": [ "LEFT_ALT", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER" ], "K59": [ "LEFT", "HOME" ], "K5A": [ "DOWN", "PGDN" ], "K5B": [ "RIGHT", "END" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_alpha_2/meta.json ================================================ { "display_name": "Launch Alpha Keyboard", "has_brightness": true, "has_color": true, "is_qmk": true, "pressed_color": "#202020", "keyboard": "system76/launch_alpha_2" } ================================================ FILE: layouts/system76/launch_heavy_1/default.json ================================================ { "model": "system76/launch_heavy_1", "version": 1, "map": { "K00": [ "ESC", "RESET", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "F1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K0F": [ "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0G": [ "MEDIA_PREV", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0H": [ "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0I": [ "MEDIA_NEXT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "0", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "MINUS", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "EQUALS", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K1F": [ "NUM_LOCK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1G": [ "NUM_SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1H": [ "NUM_ASTERISK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1I": [ "NUM_MINUS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2E": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K2F": [ "NUM_7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2G": [ "NUM_8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2H": [ "NUM_9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2I": [ "NUM_PLUS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K3E": [ "NUM_4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3F": [ "NUM_5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3G": [ "NUM_6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K4D": [ "NUM_1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4E": [ "NUM_2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4F": [ "NUM_3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4G": [ "NUM_ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K50": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K51": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K52": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K53": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K59": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K5A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K5B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ], "K5C": [ "NUM_0", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K5D": [ "NUM_PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K0F": null, "K0G": null, "K0H": null, "K0I": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K1F": null, "K1G": null, "K1H": null, "K1I": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K2F": null, "K2G": null, "K2H": null, "K2I": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K3E": null, "K3F": null, "K3G": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K4D": null, "K4E": null, "K4F": null, "K4G": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null, "K5C": null, "K5D": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_heavy_1/meta.json ================================================ { "display_name": "Launch Heavy Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_heavy_1" } ================================================ FILE: layouts/system76/launch_heavy_3/default.json ================================================ { "model": "system76/launch_heavy_3", "version": 1, "map": { "K00": [ "ESC", "RESET", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "F1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "F2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "F3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "F4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "F5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "F6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "F7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "F8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "F9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "F10", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "F11", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "F12", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "DEL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K0F": [ "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0G": [ "MEDIA_PREV", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0H": [ "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K0I": [ "MEDIA_NEXT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TICK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "0", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "MINUS", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "EQUALS", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BKSP", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K1F": [ "NUM_LOCK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1G": [ "NUM_SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1H": [ "NUM_ASTERISK", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1I": [ "NUM_MINUS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "BRACE_OPEN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "BRACE_CLOSE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "BACKSLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2E": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K2F": [ "NUM_7", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2G": [ "NUM_8", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2H": [ "NUM_9", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2I": [ "NUM_PLUS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K3E": [ "NUM_4", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3F": [ "NUM_5", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3G": [ "NUM_6", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K4D": [ "NUM_1", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4E": [ "NUM_2", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4F": [ "NUM_3", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K4G": [ "NUM_ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K50": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K51": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K52": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K53": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K54": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K55": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K56": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K57": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K58": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K59": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K5A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K5B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ], "K5C": [ "NUM_0", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K5D": [ "NUM_PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K0F": null, "K0G": null, "K0H": null, "K0I": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K1F": null, "K1G": null, "K1H": null, "K1I": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K2E": null, "K2F": null, "K2G": null, "K2H": null, "K2I": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K3E": null, "K3F": null, "K3G": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null, "K4C": null, "K4D": null, "K4E": null, "K4F": null, "K4G": null, "K50": null, "K51": null, "K52": null, "K53": null, "K54": null, "K55": null, "K56": null, "K57": null, "K58": null, "K59": null, "K5A": null, "K5B": null, "K5C": null, "K5D": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_heavy_3/meta.json ================================================ { "display_name": "Launch Heavy Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_heavy_3" } ================================================ FILE: layouts/system76/launch_lite_1/default.json ================================================ { "model": "system76/launch_lite_1", "version": 1, "map": { "K00": [ "ESC", "TICK", "ROLL_OVER", "ROLL_OVER" ], "K01": [ "1", "F1", "ROLL_OVER", "ROLL_OVER" ], "K02": [ "2", "F2", "ROLL_OVER", "ROLL_OVER" ], "K03": [ "3", "F3", "ROLL_OVER", "ROLL_OVER" ], "K04": [ "4", "F4", "ROLL_OVER", "ROLL_OVER" ], "K05": [ "5", "F5", "ROLL_OVER", "ROLL_OVER" ], "K06": [ "6", "F6", "ROLL_OVER", "ROLL_OVER" ], "K07": [ "7", "F7", "ROLL_OVER", "ROLL_OVER" ], "K08": [ "8", "F8", "ROLL_OVER", "ROLL_OVER" ], "K09": [ "9", "F9", "ROLL_OVER", "ROLL_OVER" ], "K0A": [ "0", "F10", "ROLL_OVER", "ROLL_OVER" ], "K0B": [ "MINUS", "F11", "ROLL_OVER", "ROLL_OVER" ], "K0C": [ "EQUALS", "F12", "ROLL_OVER", "ROLL_OVER" ], "K0D": [ "BKSP", "DEL", "ROLL_OVER", "ROLL_OVER" ], "K0E": [ "HOME", "PLAY_PAUSE", "ROLL_OVER", "ROLL_OVER" ], "K10": [ "TAB", "PRINT_SCREEN", "ROLL_OVER", "ROLL_OVER" ], "K11": [ "Q", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K12": [ "W", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K13": [ "E", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K14": [ "R", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K15": [ "T", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K16": [ "Y", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K17": [ "U", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K18": [ "I", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K19": [ "O", "END", "ROLL_OVER", "ROLL_OVER" ], "K1A": [ "P", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K1B": [ "BRACE_OPEN", "KBD_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K1C": [ "BRACE_CLOSE", "KBD_UP", "ROLL_OVER", "ROLL_OVER" ], "K1D": [ "BACKSLASH", "KBD_TOGGLE", "ROLL_OVER", "ROLL_OVER" ], "K1E": [ "PGUP", "VOLUME_UP", "ROLL_OVER", "ROLL_OVER" ], "K20": [ "CAPS", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K21": [ "A", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K22": [ "S", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K23": [ "D", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K24": [ "F", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K25": [ "G", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K26": [ "H", "LEFT", "ROLL_OVER", "ROLL_OVER" ], "K27": [ "J", "DOWN", "ROLL_OVER", "ROLL_OVER" ], "K28": [ "K", "UP", "ROLL_OVER", "ROLL_OVER" ], "K29": [ "L", "RIGHT", "ROLL_OVER", "ROLL_OVER" ], "K2A": [ "SEMICOLON", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2B": [ "QUOTE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2C": [ "ENTER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K2D": [ "PGDN", "VOLUME_DOWN", "ROLL_OVER", "ROLL_OVER" ], "K30": [ "LEFT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K31": [ "Z", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K32": [ "X", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K33": [ "C", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K34": [ "V", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K35": [ "B", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K36": [ "N", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K37": [ "M", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K38": [ "COMMA", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K39": [ "PERIOD", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3A": [ "SLASH", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3B": [ "RIGHT_SHIFT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K3C": [ "UP", "PGUP", "ROLL_OVER", "ROLL_OVER" ], "K3D": [ "END", "MUTE", "ROLL_OVER", "ROLL_OVER" ], "K40": [ "LEFT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K41": [ "LEFT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K42": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K43": [ "LEFT_SUPER", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K44": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K45": [ "SPACE", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K46": [ "RIGHT_CTRL", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K47": [ "RIGHT_ALT", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K48": [ "FN", "ROLL_OVER", "ROLL_OVER", "ROLL_OVER" ], "K49": [ "LEFT", "HOME", "ROLL_OVER", "ROLL_OVER" ], "K4A": [ "DOWN", "PGDN", "ROLL_OVER", "ROLL_OVER" ], "K4B": [ "RIGHT", "END", "ROLL_OVER", "ROLL_OVER" ] }, "key_leds": { "K00": null, "K01": null, "K02": null, "K03": null, "K04": null, "K05": null, "K06": null, "K07": null, "K08": null, "K09": null, "K0A": null, "K0B": null, "K0C": null, "K0D": null, "K0E": null, "K10": null, "K11": null, "K12": null, "K13": null, "K14": null, "K15": null, "K16": null, "K17": null, "K18": null, "K19": null, "K1A": null, "K1B": null, "K1C": null, "K1D": null, "K1E": null, "K20": null, "K21": null, "K22": null, "K23": null, "K24": null, "K25": null, "K26": null, "K27": null, "K28": null, "K29": null, "K2A": null, "K2B": null, "K2C": null, "K2D": null, "K30": null, "K31": null, "K32": null, "K33": null, "K34": null, "K35": null, "K36": null, "K37": null, "K38": null, "K39": null, "K3A": null, "K3B": null, "K3C": null, "K3D": null, "K40": null, "K41": null, "K42": null, "K43": null, "K44": null, "K45": null, "K46": null, "K47": null, "K48": null, "K49": null, "K4A": null, "K4B": null }, "layers": [ { "mode": [ 7, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] }, { "mode": [ 13, 127 ], "brightness": 176, "color": [ 142, 255 ] } ] } ================================================ FILE: layouts/system76/launch_lite_1/meta.json ================================================ { "display_name": "Launch Lite Keyboard", "has_mode": true, "has_per_layer": true, "num_layers": 4, "has_brightness": true, "has_color": true, "is_qmk": true, "has_mod_tap": true, "no_fn_f": true, "pressed_color": "#202020", "keyboard": "system76/launch_lite_1" } ================================================ FILE: layouts/system76/lemp10/default.json ================================================ { "model": "system76/lemp10", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp10/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/lemp11/default.json ================================================ { "model": "system76/lemp11", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp11/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/lemp12/default.json ================================================ { "model": "system76/lemp12", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp12/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/lemp13/default.json ================================================ { "model": "system76/lemp13", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "INSERT" ], "K0F": [ "PAUSE", "PAUSE" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "PGUP" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "LEFT", "HOME" ], "K58": [ "RIGHT", "END" ], "K59": [ "DOWN", "PGDN" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp13/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_81" } ================================================ FILE: layouts/system76/lemp13-b/default.json ================================================ { "model": "system76/lemp13-b", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp13-b/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/lemp9/default.json ================================================ { "model": "system76/lemp9", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "KBD_BKL" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "HOME", "HOME" ], "K0E": [ "END", "END" ], "K0F": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0G": [ "DEL", "DEL" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "RIGHT_CTRL", "APP" ], "K57": [ "PGUP", "PGUP" ], "K58": [ "UP", "UP" ], "K59": [ "PGDN", "PGDN" ], "K60": [ "LEFT", "LEFT" ], "K61": [ "DOWN", "DOWN" ], "K62": [ "RIGHT", "RIGHT" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/lemp9/meta.json ================================================ { "display_name": "Lemur Pro", "has_brightness": true, "has_color": false, "pressed_color": "#dfdfdf", "keyboard": "system76/14in_83" } ================================================ FILE: layouts/system76/oryp10/default.json ================================================ { "model": "system76/oryp10", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp10/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/oryp11/default.json ================================================ { "model": "system76/oryp11", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp11/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA04" } ================================================ FILE: layouts/system76/oryp12/default.json ================================================ { "model": "system76/oryp12", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "MIC_MUTE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp12/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/18H9LHA04" } ================================================ FILE: layouts/system76/oryp5/default.json ================================================ { "model": "system76/oryp5", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp5/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/oryp6/default.json ================================================ { "model": "system76/oryp6", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp6/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/oryp7/default.json ================================================ { "model": "system76/oryp7", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp7/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/oryp8/default.json ================================================ { "model": "system76/oryp8", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp8/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/oryp9/default.json ================================================ { "model": "system76/oryp9", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/oryp9/meta.json ================================================ { "display_name": "Oryx Pro", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts/system76/serw13/default.json ================================================ { "model": "system76/serw13", "version": 1, "map": { "K00": [ "ESC", "ESC" ], "K01": [ "F1", "TOUCHPAD" ], "K02": [ "F2", "DISPLAY_TOGGLE" ], "K03": [ "F3", "MUTE" ], "K04": [ "F4", "F4" ], "K05": [ "F5", "VOLUME_DOWN" ], "K06": [ "F6", "VOLUME_UP" ], "K07": [ "F7", "DISPLAY_MODE" ], "K08": [ "F8", "BRIGHTNESS_DOWN" ], "K09": [ "F9", "BRIGHTNESS_UP" ], "K0A": [ "F10", "CAMERA_TOGGLE" ], "K0B": [ "F11", "AIRPLANE_MODE" ], "K0C": [ "F12", "SUSPEND" ], "K0D": [ "PRINT_SCREEN", "PRINT_SCREEN" ], "K0E": [ "INSERT", "SCROLL_LOCK" ], "K0F": [ "DEL", "DEL" ], "K0G": [ "HOME", "HOME" ], "K0H": [ "END", "END" ], "K0I": [ "PGUP", "PAUSE" ], "K0J": [ "PGDN", "PAUSE" ], "K10": [ "TICK", "PLAY_PAUSE" ], "K11": [ "1", "FAN_TOGGLE" ], "K12": [ "2", "2" ], "K13": [ "3", "3" ], "K14": [ "4", "4" ], "K15": [ "5", "5" ], "K16": [ "6", "6" ], "K17": [ "7", "7" ], "K18": [ "8", "8" ], "K19": [ "9", "9" ], "K1A": [ "0", "0" ], "K1B": [ "MINUS", "MINUS" ], "K1C": [ "EQUALS", "EQUALS" ], "K1D": [ "BKSP", "BKSP" ], "K1E": [ "NUM_LOCK", "NUM_LOCK" ], "K1F": [ "NUM_SLASH", "KBD_COLOR" ], "K1G": [ "NUM_ASTERISK", "KBD_TOGGLE" ], "K1H": [ "NUM_MINUS", "KBD_DOWN" ], "K20": [ "TAB", "TAB" ], "K21": [ "Q", "Q" ], "K22": [ "W", "W" ], "K23": [ "E", "E" ], "K24": [ "R", "R" ], "K25": [ "T", "T" ], "K26": [ "Y", "Y" ], "K27": [ "U", "U" ], "K28": [ "I", "I" ], "K29": [ "O", "O" ], "K2A": [ "P", "P" ], "K2B": [ "BRACE_OPEN", "BRACE_OPEN" ], "K2C": [ "BRACE_CLOSE", "BRACE_CLOSE" ], "K2D": [ "BACKSLASH", "BACKSLASH" ], "K2E": [ "NUM_7", "NUM_7" ], "K2F": [ "NUM_8", "NUM_8" ], "K2G": [ "NUM_9", "NUM_9" ], "K2H": [ "NUM_PLUS", "KBD_UP" ], "K30": [ "CAPS", "CAPS" ], "K31": [ "A", "A" ], "K32": [ "S", "S" ], "K33": [ "D", "D" ], "K34": [ "F", "F" ], "K35": [ "G", "G" ], "K36": [ "H", "H" ], "K37": [ "J", "J" ], "K38": [ "K", "K" ], "K39": [ "L", "L" ], "K3A": [ "SEMICOLON", "SEMICOLON" ], "K3B": [ "QUOTE", "QUOTE" ], "K3C": [ "ENTER", "ENTER" ], "K3D": [ "NUM_4", "NUM_4" ], "K3E": [ "NUM_5", "NUM_5" ], "K3F": [ "NUM_6", "NUM_6" ], "K40": [ "LEFT_SHIFT", "LEFT_SHIFT" ], "K41": [ "Z", "Z" ], "K42": [ "X", "X" ], "K43": [ "C", "C" ], "K44": [ "V", "V" ], "K45": [ "B", "B" ], "K46": [ "N", "N" ], "K47": [ "M", "M" ], "K48": [ "COMMA", "COMMA" ], "K49": [ "PERIOD", "PERIOD" ], "K4A": [ "SLASH", "SLASH" ], "K4B": [ "RIGHT_SHIFT", "RIGHT_SHIFT" ], "K4C": [ "UP", "UP" ], "K4D": [ "NUM_1", "NUM_1" ], "K4E": [ "NUM_2", "NUM_2" ], "K4F": [ "NUM_3", "NUM_3" ], "K4G": [ "NUM_ENTER", "NUM_ENTER" ], "K50": [ "LEFT_CTRL", "LEFT_CTRL" ], "K51": [ "FN", "FN" ], "K52": [ "LEFT_SUPER", "LEFT_SUPER" ], "K53": [ "LEFT_ALT", "LEFT_ALT" ], "K54": [ "SPACE", "SPACE" ], "K55": [ "RIGHT_ALT", "RIGHT_ALT" ], "K56": [ "APP", "APP" ], "K57": [ "RIGHT_CTRL", "RIGHT_CTRL" ], "K58": [ "LEFT", "LEFT" ], "K59": [ "DOWN", "DOWN" ], "K5A": [ "RIGHT", "RIGHT" ], "K5B": [ "NUM_0", "NUM_0" ], "K5C": [ "NUM_PERIOD", "NUM_PERIOD" ] }, "key_leds": {}, "layers": [ { "mode": null, "brightness": 0, "color": [ 0, 0 ] } ] } ================================================ FILE: layouts/system76/serw13/meta.json ================================================ { "display_name": "Serval WS", "has_brightness": true, "has_color": true, "pressed_color": "#dfdfdf", "keyboard": "system76/15in_102" } ================================================ FILE: layouts.py ================================================ #!/usr/bin/env python3 import argparse from collections import OrderedDict import json import os import re import shutil import subprocess import sys import tempfile import typing from typing import List, Tuple, Dict EXCLUDED_SCANCODES = ['INT_1', 'INT_2'] QMK_MAPPING = { 'APPLICATION': 'APP', 'AUDIO_MUTE': 'MUTE', 'AUDIO_MUTE': 'MUTE', 'AUDIO_VOL_DOWN': 'VOLUME_DOWN', 'AUDIO_VOL_UP': 'VOLUME_UP', 'AGIN': 'AGAIN', 'VOLD': 'VOLUME_DOWN', 'VOLU': 'VOLUME_UP', 'BSLASH': 'BACKSLASH', 'BSLS': 'BACKSLASH', 'SLSH': 'SLASH', 'BSPACE': 'BKSP', 'BACKSPACE': 'BKSP', 'BSPC': 'BKSP', 'BOOT': 'RESET', 'BOOTLOADER': 'RESET', 'SPC': 'SPACE', 'SLCT': 'SELECT', 'CAPSLOCK': 'CAPS', 'CAPS_LOCK': 'CAPS', 'LCAP': 'LOCKING_CAPS_LOCK', 'LEAD': 'LEADER', 'DELETE': 'DEL', 'DOT': 'PERIOD', 'EQUAL': 'EQUALS', 'EQL': 'EQUALS', 'ESCAPE': 'ESC', 'EXSL': 'EXSEL', 'GRAVE': 'TICK', 'GESC': 'GRAVE_ESCAPE', 'GRV': 'TICK', 'KP_0': 'NUM_0', 'KP_1': 'NUM_1', 'KP_2': 'NUM_2', 'KP_3': 'NUM_3', 'KP_4': 'NUM_4', 'KP_5': 'NUM_5', 'KP_6': 'NUM_6', 'KP_7': 'NUM_7', 'KP_8': 'NUM_8', 'KP_9': 'NUM_9', 'P0': 'NUM_0', 'P1': 'NUM_1', 'P2': 'NUM_2', 'P3': 'NUM_3', 'P4': 'NUM_4', 'P5': 'NUM_5', 'P6': 'NUM_6', 'P7': 'NUM_7', 'P8': 'NUM_8', 'P9': 'NUM_9', 'KP_ASTERISK': 'NUM_ASTERISK', 'PAST': 'NUM_ASTERISK', 'INS': 'INSERT', 'KP_COMMA': 'NUM_COMMA', 'PCMM': 'NUM_COMMA', 'COMM': 'COMMA', 'CNCL': 'CANCEL', 'CLR': 'CLEAR', 'CLAG': 'CLEAR_AGAIN', 'CRSL': 'CRSEL', 'CALC': 'CALCULATOR', 'KP_DOT': 'NUM_PERIOD', 'PDOT': 'NUM_PERIOD', 'KP_ENTER': 'NUM_ENTER', 'ENT': 'ENTER', 'EXEC': 'EXECUTE', 'PENT': 'NUM_ENTER', 'KP_EQUAL': 'NUM_EQUALS', 'PEQL': 'NUM_EQUALS', 'KP_MINUS': 'NUM_MINUS', 'PMNS': 'NUM_MINUS', 'MINS': 'MINUS', 'KP_PLUS': 'NUM_PLUS', 'PPLS': 'NUM_PLUS', 'KP_SLASH': 'NUM_SLASH', 'PSLS': 'NUM_SLASH', 'LALT': 'LEFT_ALT', 'ALGL': 'LEFT_ALT', 'LOPT': 'LEFT_ALT', 'LBRACKET': 'BRACE_OPEN', 'LEFT_BRACKET': 'BRACE_OPEN', 'LBRC': 'BRACE_OPEN', 'LCTRL': 'LEFT_CTRL', 'LCTL': 'LEFT_CTRL', 'LGUI': 'LEFT_SUPER', 'LWIN': 'LEFT_SUPER', 'LCMD': 'LEFT_SUPER', 'LEFT_GUI': 'LEFT_SUPER', 'LSHIFT': 'LEFT_SHIFT', 'LSFT': 'LEFT_SHIFT', 'NO': 'NONE', 'BASIC': 'NONE', 'MEDIA_NEXT_TRACK': 'MEDIA_NEXT', 'MNXT': 'MEDIA_NEXT', 'MEDIA_PLAY_PAUSE': 'PLAY_PAUSE', 'MPLY': 'PLAY_PAUSE', 'MFFD': 'MEDIA_FAST_FORWARD', 'MRWD': 'MEDIA_REWIND', 'PAUS': 'PAUSE', 'BRK': 'PAUSE', 'BRMU': 'PAUSE', 'ERAS': 'ALTERNATE_ERASE', 'ASST': 'ASSISTANT', 'MEDIA_PREV_TRACK': 'MEDIA_PREV', 'MPRV': 'MEDIA_PREV', 'MSTP': 'MEDIA_STOP', 'MSEL': 'MEDIA_SELECT', 'MS_U': 'MS_UP', 'MS_D': 'MS_DOWN', 'MS_L': 'MS_LEFT', 'MS_R': 'MS_RIGHT', 'EJCT': 'MEDIA_EJECT', 'MYCM': 'MY_COMPUTER', 'COMPUTER': 'MY_COMPUTER', 'CPNL': 'CONTROL_PANEL', 'WSCH': 'WWW_SEARCH', 'WHOM': 'WWW_HOME', 'WBAK': 'WWW_BACK', 'WFWD': 'WWW_FORWARD', 'WSTP': 'WWW_STOP', 'WREF': 'WWW_REFRESH', 'WFAV': 'WWW_FAVORITES', 'WH_U': 'MS_WH_UP', 'WH_D': 'MS_WH_DOWN', 'WH_L': 'MS_WH_LEFT', 'WH_R': 'MS_WH_RIGHT', 'ACL0': 'MS_ACCEL0', 'ACL1': 'MS_ACCEL1', 'ACL2': 'MS_ACCEL2', 'NUMLOCK': 'NUM_LOCK', 'NUM': 'NUM_LOCK', 'LNUM': 'LOCKING_NUM_LOCK', 'NUHS': 'NONUS_HASH', 'NUBS': 'NONUS_BACKSLASH', 'PGDOWN': 'PGDN', 'PAGE_DOWN': 'PGDN', 'PAGE_UP': 'PGUP', 'PSCREEN': 'PRINT_SCREEN', 'PSCR': 'PRINT_SCREEN', 'PRIR': 'PRIOR', 'PWR': 'SYSTEM_POWER', 'INTERNATIONAL_1': 'INT1', 'INTERNATIONAL_2': 'INT2', 'INTERNATIONAL_3': 'INT3', 'INTERNATIONAL_4': 'INT4', 'INTERNATIONAL_5': 'INT5', 'INTERNATIONAL_6': 'INT6', 'INTERNATIONAL_7': 'INT7', 'INTERNATIONAL_8': 'INT8', 'INTERNATIONAL_9': 'INT9', 'LNG1': 'LANGUAGE_1', 'LNG2': 'LANGUAGE_2', 'LNG3': 'LANGUAGE_3', 'LNG4': 'LANGUAGE_4', 'LNG5': 'LANGUAGE_5', 'LNG6': 'LANGUAGE_6', 'LNG7': 'LANGUAGE_7', 'LNG8': 'LANGUAGE_8', 'LNG9': 'LANGUAGE_9', 'PSTE': 'PASTE', 'PROGRAMMABLE_BUTTON_1': 'PROGRAMMABLE_BUTTON', 'QUOT': 'QUOTE', 'QUANTUM': 'RESET', 'RALT': 'RIGHT_ALT', 'ALGR': 'RIGHT_ALT', 'ROPT': 'RIGHT_ALT', 'RBRACKET': 'BRACE_CLOSE', 'RIGHT_BRACKET': 'BRACE_CLOSE', 'RBRC': 'BRACE_CLOSE', 'RCTRL': 'RIGHT_CTRL', 'RCTL': 'RIGHT_CTRL', 'RGB_TOG': 'KBD_TOGGLE', 'RGB_VAD': 'KBD_DOWN', 'RGB_VAI': 'KBD_UP', 'RGB_MOD': 'RGB_MODE_FORWARD', 'RGB_RMOD': 'RGB_MODE_REVERSE', 'RGB_M_P': 'RGB_MODE_PLAIN', 'RGB_M_B': 'RGB_MODE_BREATHE', 'RGB_M_R': 'RGB_MODE_RAINBOW', 'RGB_M_SW': 'RGB_MODE_SWIRL', 'RGB_M_SN': 'RGB_MODE_SNAKE', 'RGB_M_K': 'RGB_MODE_KNIGHT', 'RGB_M_X': 'RGB_MODE_XMAS', 'RGB_M_G': 'RGB_MODE_GRADIENT', 'RGB_M_T': 'RGB_MODE_RGBTEST', 'RGB_MODE_TEST': 'RGB_MODE_RGBTEST', 'RGB_M_TW': 'RGB_MODE_TWINKLE', 'LIGHTING': 'BACKLIGHT_ON', 'BRIU': 'BRIGHTNESS_UP', 'BRID': 'BRIGHTNESS_DOWN', 'RGHT': 'RIGHT', 'RGUI': 'RIGHT_SUPER', 'RWIN': 'RIGHT_SUPER', 'RCMD': 'RIGHT_SUPER', 'RIGHT_GUI': 'RIGHT_SUPER', 'RSHIFT': 'RIGHT_SHIFT', 'RSFT': 'RIGHT_SHIFT', 'RETN': 'RETURN', 'RBT': 'REBOOT', 'SCOLON': 'SEMICOLON', 'SCLN': 'SEMICOLON', 'SCROLLLOCK': 'SCROLL_LOCK', 'LSCR': 'LOCKING_SCROLL_LOCK', 'SCRL': 'SCROLL_LOCK', 'BRMD': 'SCROLL_LOCK', 'JOYSTICK_BUTTON_0': 'JOYSTICK', 'BTN1': 'MS_BTN1', 'BTN2': 'MS_BTN2', 'BTN3': 'MS_BTN3', 'BTN4': 'MS_BTN4', 'BTN5': 'MS_BTN5', 'BTN6': 'MS_BTN6', 'BTN7': 'MS_BTN7', 'BTN8': 'MS_BTN8', 'MIDI': 'MIDI_ON', 'AUDIO': 'AUDIO_ON', 'MACRO': 'MACRO_0', 'SYSTEM_SLEEP': 'SUSPEND', 'SLEP': 'SUSPEND', 'SYRQ': 'SYSTEM_REQUEST', 'WAKE': 'SYSTEM_WAKE', 'SEPR': 'SEPARATOR', 'TRANSPARENT': 'ROLL_OVER', 'TRNS': 'ROLL_OVER', 'TG(0)': 'LAYER_TOGGLE_1', 'TOGGLE_LAYER': 'LAYER_TOGGLE_1', 'TG(1)': 'LAYER_TOGGLE_2', 'TG(2)': 'LAYER_TOGGLE_3', 'TG(3)': 'LAYER_TOGGLE_4', 'TO(0)': 'LAYER_SWITCH_1', 'TO': 'LAYER_SWITCH_1', 'TO(1)': 'LAYER_SWITCH_2', 'TO(2)': 'LAYER_SWITCH_3', 'TO(3)': 'LAYER_SWITCH_4', 'MO(0)': 'LAYER_ACCESS_1', 'MOMENTARY': 'LAYER_ACCESS_1', 'MO(1)': 'FN', 'MO(2)': 'LAYER_ACCESS_3', 'MO(3)': 'LAYER_ACCESS_4', '_______': 'ROLL_OVER', } QMK_EXTRA_SCANCODES = [ "TG(0)", "TG(1)", "TG(2)", "TG(3)", "TO(0)", "TO(1)", "TO(2)", "TO(3)", "MO(0)", "MO(1)", "MO(2)", "MO(3)", ] EXCLUDE_BOARDS = [ 'system76/ortho_split_2u', 'system76/launch_test', 'system76/virgo', ] ALIAS_RE = '#define\s+KC_([A-Z_]*)\s+KC_([A-Z_]+]*)\s*$' # keycode_h = open('tmk_core/common/keycode.h').read() # [(i.group(1), i.group(2)) for i in (re.match('#define\s+KC_([A-Z_]*)\s+KC_([A-Z_]+]*)\s*$', i) for i in keycode_h.splitlines()) if i] def call_preprocessor(input: str) -> str: return subprocess.check_output(["gcc", "-E", "-nostdinc", "-"], stderr=subprocess.DEVNULL, input=input, universal_newlines=True) def read_stripping_includes(path: str) -> str: output = '' with open(path) as f: for line in f: if not line.startswith('#include'): output += line return output def extract_scancodes(ecdir: str, is_qmk: bool) -> Tuple[typing.OrderedDict[str, int], Dict[str, str]]: "Extract mapping from scancode names to numbers" is_old_qmk = False if is_qmk: version = subprocess.check_output(["git", "-C", ecdir, "describe", "--tags"], stderr=subprocess.DEVNULL, universal_newlines=True) is_old_qmk = "0.7.103" in version or "0.7.104" in version or "0.12.20" in version if is_old_qmk: include_paths = [f"{ecdir}/tmk_core/common/keycode.h", f"{ecdir}/quantum/quantum_keycodes.h", f"{ecdir}/tmk_core/common/action_code.h"] includes = [read_stripping_includes(i) for i in include_paths] common_keymap_h = call_preprocessor(includes[0]) quantum_keycode_h = call_preprocessor(includes[1]) scancode_defines = re.findall( ' (KC_[^,\s]+)', common_keymap_h) scancode_defines += re.findall( ' (RGB_[^,\s]+)', quantum_keycode_h) else: include_paths = [ f"{ecdir}/quantum/keycodes.h", f"{ecdir}/quantum/quantum_keycodes.h", f"{ecdir}/quantum/action_code.h" ] includes = [read_stripping_includes(i) for i in include_paths] keycodes_h = call_preprocessor(includes[0]) quantum_keycode_h = call_preprocessor(includes[1]) scancode_defines = re.findall( ' (KC_[^,\s]+)', keycodes_h) scancode_defines += re.findall( ' (RGB_[^,\s]+)', keycodes_h) scancode_defines += re.findall( ' (QK_[^,\s]+)', keycodes_h) scancode_defines += re.findall( ' (QK_[^,\s]+)', quantum_keycode_h) define_aliases = [(i.group(1), i.group(2)) for i in (re.match(ALIAS_RE, i) for i in includes[0].splitlines()) if i] mapping = QMK_MAPPING mapping.update({alias: QMK_MAPPING.get(keycode, keycode) for alias, keycode in define_aliases}) for (alias, keycode) in define_aliases: mapping[alias] = QMK_MAPPING.get(keycode, keycode) scancode_defines += QMK_EXTRA_SCANCODES else: includes = [open(f"{ecdir}/src/common/include/common/keymap.h").read()] common_keymap_h = includes[0] scancode_defines = re.findall( '#define.*((?:K_\S+)|(?:KT_FN))', common_keymap_h) mapping = {} tmpdir = tempfile.mkdtemp() with open(f'{tmpdir}/keysym-extract.c', 'w') as f: f.write('#include \n') for i in includes: f.write(i.replace('#pragma once', '')) f.write('\n') f.write('#include \n') f.write('int main() {\n') for i in scancode_defines: f.write(f'printf("%d ", {i});\n') f.write('}\n') cmd = ['gcc'] cmd += ['-o', f'{tmpdir}/keysym-extract', f'{tmpdir}/keysym-extract.c'] subprocess.check_call(cmd) output = subprocess.check_output( f'{tmpdir}/keysym-extract', universal_newlines=True) scancodes = (int(i) for i in output.split()) shutil.rmtree(tmpdir) scancode_names = [] for name in scancode_defines: if '_' in name and name.split('_')[0] != 'RGB': name = name.split('_', 1)[1] if is_qmk: name = mapping.get(name, name) scancode_names.append(name) scancode_list = OrderedDict(zip(scancode_names, scancodes)) if is_qmk: if is_old_qmk: scancode_list['RESET'] = 0x5C00 else: scancode_list['NONE'] = 0x0000 scancode_list = OrderedDict((name, code) for (name, code) in scancode_list.items() if name not in EXCLUDED_SCANCODES) # Make sure scancodes are unique assert len(scancode_list.keys()) == len(set(scancode_list.values())) return scancode_list, mapping def parse_layout_define(keymap_h: str, is_qmk) -> Tuple[List[str], List[List[str]]]: keymap_h = re.sub(r'/\*.*?\*/', '', keymap_h) # XXX split up regex? m = re.search( r'LAYOUT\((.*?)\)[\s\\]*({[^{}]*({[^{}]*}[^{}]*)+)[^{}]*}', keymap_h, re.MULTILINE | re.DOTALL) assert m is not None physical = m.group(1).replace(',', ' ').replace('\\', '').split() # XXX name? physical2 = [i.replace('\\', '').replace(',', '').split() for i in m.group(2).replace('{', '').split('}')[:-1]] assert is_qmk or all(len(i) == len(physical2[0]) for i in physical2) return physical, physical2 def parse_led_config(led_c: str, physical2: List[List[str]]) -> Dict[str, List[int]]: led_c = re.sub(r'//.*', '', led_c) led_c = re.sub(r'/\*.*?\*/', '', led_c) m = re.search(r'g_led_config.*{ \{(.*?)^},', led_c, re.MULTILINE | re.DOTALL) leds: Dict[str, List[int]] = {} if m is None: return leds for i, line in enumerate(re.findall(r'{(.*)?}', m.group(1))): for j, led_index in enumerate(line.replace(',', ' ').split()): if led_index != '__': leds[physical2[i][j]] = [int(led_index)] return leds def parse_keymap(keymap_c: str, mapping: Dict[str, str], physical: List[str], is_qmk: bool) -> Dict[str, List[str]]: # XXX for launch keymap_c = keymap_c.replace('MO(1)', 'FN') keymap_c = re.sub(r'/\*.*?\*/', '', keymap_c) layer_scancodes: List[List[str]] = [] for layer in re.finditer(r'LAYOUT\((.*?)\)', keymap_c, re.MULTILINE | re.DOTALL): scancodes = layer.group(1).replace(',', ' ').split() assert len(scancodes) == len(physical) def scancode_map(x: int, code: str) -> str: if code == '0': return 'NONE' code = code.replace('QK_', '').replace('K_', '').replace('KC_', '').replace('KT_', '') if is_qmk: code = mapping.get(code, code) return code scancodes = [scancode_map(x, i) for x, i in enumerate(scancodes)] layer_scancodes.append(scancodes) keymap = {} for i, physical_name in enumerate(physical): keymap[physical_name] = [j[i] for j in layer_scancodes] return keymap def gen_layout_json(path: str, physical: List[str], physical2: List[List[str]]) -> None: "Generate layout.json file" layout = {} for p in physical: x, y = next((x, y) for x, i in enumerate(physical2) for y, j in enumerate(i) if j == p) layout[p] = (x, y) write_json_file(path, layout) def gen_keymap_json(path: str, scancodes: typing.OrderedDict[str, int]) -> None: "Generate keymap.json file" write_json_file(path, scancodes) def gen_leds_json(path: str, leds: [str, List[int]]) -> None: "Generate leds.json file" write_json_file(path, leds, sort_keys=True) def gen_default_json(path: str, board: str, keymap: Dict[str, List[str]], is_qmk: bool) -> None: "Generate default.json file" if is_qmk: key_leds = {k: None for k in keymap.keys()} layers = [ {"mode": (7, 127), "brightness": 176, "color": (142, 255)}, {"mode": (13, 127), "brightness": 176, "color": (142, 255)}, {"mode": (13, 127), "brightness": 176, "color": (142, 255)}, {"mode": (13, 127), "brightness": 176, "color": (142, 255)}, ] else: key_leds = {} layers = [{"mode": None, "brightness": 0, "color": (0, 0)}] write_json_file(path, {"model": board, "version": 1, "map": keymap, "key_leds": key_leds, "layers": layers}) def update_meta_json(meta_json: str, has_brightness: bool, has_color: bool, keyboard: str): meta = {} if os.path.exists(meta_json): with open(meta_json, 'r') as f: meta = json.load(f, object_pairs_hook=OrderedDict) meta['has_brightness'] = has_brightness meta['has_color'] = has_color meta['keyboard'] = keyboard write_json_file(meta_json, meta) def write_json_file(path: str, data, sort_keys=False): with open(path, 'w') as f: json.dump(data, f, indent=2, sort_keys=sort_keys) f.write('\n') def generate_layout_dir(ecdir: str, board: str, is_qmk: bool) -> None: print(f'Generating layouts/{board}...') has_brightness = True has_color = True if is_qmk: keymap_h = open( f"{ecdir}/keyboards/{board}/{board.split('/')[-1]}.h").read() default_c = open( f"{ecdir}/keyboards/{board}/keymaps/default/keymap.c").read() led_c = open( f"{ecdir}/keyboards/{board}/{board.split('/')[-1]}.c").read() keyboard = board else: with open(f"{ecdir}/src/board/{board}/board.mk") as f: board_mk = f.read() m = re.search('^KEYBOARD=(.*)$', board_mk, re.MULTILINE) assert m is not None keyboard = board.rsplit('/', 1)[0] + '/' + m.group(1) m = re.search('^KBLED=(.*)$', board_mk, re.MULTILINE) assert m is not None kbled = m.group(1) # Some models use PWM and support RGB, but only ship with a white-backlit keyboard if kbled == 'white_dac' or board in ['system76/darp9', 'system76/darp10', 'system76/darp11']: has_color = False # bonw14/bonw15: Handled through USB. Can configurator support this? elif kbled in ['none', 'bonw14', 'bonw15']: has_brightness = False has_color = False elif kbled not in ['rgb_pwm', 'oryp5', 'darp5']: raise Exception(f"KBLED='{kbled}' not handled by layouts.py") keymap_h = open( f"{ecdir}/src/keyboard/{keyboard}/include/board/keymap.h").read() default_c = open(f"{ecdir}/src/keyboard/{keyboard}/keymap/default.c").read() led_c = "" os.makedirs(f'layouts/{board}', exist_ok=True) os.makedirs(f'layouts/keyboards/{keyboard}', exist_ok=True) physical, physical2 = parse_layout_define(keymap_h, is_qmk) leds = parse_led_config(led_c, physical2) _scancodes, mapping = extract_scancodes(ecdir, is_qmk) default_keymap = parse_keymap(default_c, mapping, physical, is_qmk) gen_layout_json(f'layouts/keyboards/{keyboard}/layout.json', physical, physical2) gen_leds_json(f'layouts/keyboards/{keyboard}/leds.json', leds) gen_default_json(f'layouts/{board}/default.json', board, default_keymap, is_qmk) update_meta_json(f'layouts/{board}/meta.json', has_brightness, has_color, keyboard) parser = argparse.ArgumentParser(usage="./layouts.py --qmk ../qmk_firmware system76/launch_heavy_1") parser.add_argument("ecdir", help='For QMK boards that is the qmk_firmware (github.com/system76/qmk_firmware) directory itself, otherwise use the ec directory (github.com/system76/ec)') parser.add_argument("board", help='The name of the manufacturer and board name. Example: "system76/launch_2"') parser.add_argument("--qmk", action="store_true", help="Required if you plan on using a keyboard with QMK firmware.") parser.add_argument("--qmk-legacy", action="store_true", help="Re-generate keymap json for old qmk version. (pre 0.19)") args = parser.parse_args() # Generate keymap file, used for all ec or qmk boards scancodes, _mapping = extract_scancodes(args.ecdir, args.qmk or args.qmk_legacy) if args.qmk_legacy: keymap_path = 'layouts/keymap/qmk_legacy.json' elif args.qmk: keymap_path = 'layouts/keymap/qmk.json' else: keymap_path = 'layouts/keymap/ec.json' gen_keymap_json(keymap_path, scancodes) if args.qmk_legacy: # Only keymap differs for legacy qmk, so don't generate anything related to individial boards sys.exit(0) if args.board == 'all': if args.qmk: boarddir = f'{args.ecdir}/keyboards/system76' else: boarddir = f'{args.ecdir}/src/board/system76' for i in os.listdir(boarddir): if i == 'common' or not os.path.isdir(f'{boarddir}/{i}') or f"system76/{i}" in EXCLUDE_BOARDS: continue generate_layout_dir(args.ecdir, f'system76/{i}', args.qmk) else: generate_layout_dir(args.ecdir, args.board, args.qmk) ================================================ FILE: linux/build.py ================================================ #!/usr/bin/env python3 import argparse import glob import os import shutil import subprocess from urllib.request import urlopen # Handle commandline arguments parser = argparse.ArgumentParser() parser.add_argument('--release', action='store_true', help="Build in release mode") parser.add_argument('--arm64', action='store_true', help="Build for ARM64 architecture") args = parser.parse_args() # Executables to install TARGET_DIR = "../target/" + ('release' if args.release else 'debug') ICON = "../data/icons/scalable/apps/com.system76.keyboardconfigurator.svg" # Appimage packaging PKG = "keyboard-configurator" APPID = "com.system76.keyboardconfigurator" ARCH = "aarch64" if args.arm64 else "x86_64" # Remove previous build for i in glob.glob(f"{PKG}*.AppImage"): os.remove(i) if os.path.exists(f"{PKG}.AppDir"): shutil.rmtree(f"{PKG}.AppDir") if os.path.exists(PKG): os.remove(PKG) # Build the application cmd = ["cargo", "build", "--features", "appimage"] if args.release: cmd.append('--release') subprocess.check_call(cmd) # Copy executable subprocess.check_call([f"strip", '-o', "system76-keyboard-configurator", f"{TARGET_DIR}/system76-keyboard-configurator"]) # Download linuxdeploy LINUXDEPLOY = f"linuxdeploy-{ARCH}.AppImage" LINUXDEPLOY_URL = f"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/{LINUXDEPLOY}" if not os.path.exists(LINUXDEPLOY): print(f"Downloading {LINUXDEPLOY}...") with urlopen(LINUXDEPLOY_URL) as u: with open(LINUXDEPLOY, 'wb') as f: f.write(u.read()) os.chmod(LINUXDEPLOY, os.stat(LINUXDEPLOY).st_mode | 0o111) print("Download complete.") # Copy appdata os.makedirs(f"{PKG}.AppDir/usr/share/metainfo", exist_ok=True) shutil.copy("com.system76.keyboardconfigurator.appdata.xml", f"{PKG}.AppDir/usr/share/metainfo") # Build appimage print(f"Building AppImage for {ARCH}...") subprocess.check_call([ f"./{LINUXDEPLOY}", f"--appdir={PKG}.AppDir", f"--executable=system76-keyboard-configurator", f"--desktop-file={APPID}.desktop", f"--icon-file={ICON}", "--plugin", "gtk", "--output", "appimage" ]) output_file = f"{PKG}-{ARCH}.AppImage" shutil.move(f"System76_Keyboard_Configurator-{ARCH}.AppImage", output_file) print(f"AppImage built: {output_file}") ================================================ FILE: linux/com.system76.keyboardconfigurator.appdata.xml ================================================ com.system76.keyboardconfigurator CC0-1.0 GPL-3.0-or-later System76 idscott@system76.com https://github.com/pop-os/keyboard-configurator https://github.com/pop-os/keyboard-configurator Keyboard Configurator Configure System76 keyboards

The System76 Keyboard Configrator app places control back into your hands. Remap keys, swap keycaps, and configure multiple layers to your liking. Compatible with Linux, Windows, and macOS, this application will work with the Launch Configurable Keyboard as well as any System76 laptop with Open Firmware.

Utility com.system76.keyboardconfigurator.desktop https://raw.githubusercontent.com/pop-os/keyboard-configurator/master/screenshots/screenshot-01.png Pop!_OS system76-keyboard-configurator
================================================ FILE: linux/com.system76.keyboardconfigurator.desktop ================================================ [Desktop Entry] Name=System76 Keyboard Configurator Name[hu]=System76 Billentyűzet-konfigurátor Exec=system76-keyboard-configurator Icon=com.system76.keyboardconfigurator Type=Application StartupNotify=true Categories=Utility; ================================================ FILE: linux/com.system76.keyboardconfiguratorlaunchtest.desktop ================================================ [Desktop Entry] Name=System76 Keyboard Tester Name[hu]=System76 Billentyűzet-tesztelő Exec=system76-keyboard-configurator --launch-test Icon=com.system76.keyboardconfigurator Type=Application StartupNotify=true Categories=Utility; ================================================ FILE: linux/linuxdeploy-plugin-gtk.sh ================================================ #! /usr/bin/env bash # GTK3 environment variables: https://developer.gnome.org/gtk3/stable/gtk-running.html # GTK4 environment variables: https://developer.gnome.org/gtk4/stable/gtk-running.html # abort on all errors set -e if [ "$DEBUG" != "" ]; then set -x verbose="--verbose" fi SCRIPT="$(basename "$(readlink -f "$0")")" show_usage() { echo "Usage: $SCRIPT --appdir " echo echo "Bundles resources for applications that use GTK into an AppDir" echo echo "Required variables:" echo " LINUXDEPLOY=\".../linuxdeploy\" path to linuxdeploy (e.g., AppImage); set automatically when plugin is run directly by linuxdeploy" echo echo "Optional variables:" echo " DEPLOY_GTK_VERSION (major version of GTK to deploy, e.g. '2', '3' or '4'; auto-detect by default)" } variable_is_true() { local var="$1" if [ -n "$var" ] && { [ "$var" == "true" ] || [ "$var" -gt 0 ]; } 2> /dev/null; then return 0 # true else return 1 # false fi } get_pkgconf_variable() { local variable="$1" local library="$2" local default_value="$3" pkgconfig_ret="$("$PKG_CONFIG" --variable="$variable" "$library")" if [ -n "$pkgconfig_ret" ]; then echo "$pkgconfig_ret" elif [ -n "$default_value" ]; then echo "$default_value" else echo "$0: there is no '$variable' variable for '$library' library." > /dev/stderr echo "Please check the '$library.pc' file is present in \$PKG_CONFIG_PATH (you may need to install the appropriate -dev/-devel package)." > /dev/stderr exit 1 fi } copy_tree() { local src=("${@:1:$#-1}") local dst="${*:$#}" for elem in "${src[@]}"; do mkdir -p "${dst::-1}$elem" cp "$elem" --archive --parents --target-directory="$dst" $verbose done } copy_lib_tree() { # The source lib directory could be /usr/lib, /usr/lib64, or /usr/lib/x86_64-linux-gnu # Therefore, when copying lib directories, we need to transform that target path # to a consistent /usr/lib local src=("${@:1:$#-1}") local dst="${*:$#}" for elem in "${src[@]}"; do mkdir -p "${dst::-1}${elem/$LD_GTK_LIBRARY_PATH//usr/lib}" pushd "$LD_GTK_LIBRARY_PATH" cp "$(realpath --relative-to="$LD_GTK_LIBRARY_PATH" "$elem")" --archive --parents --target-directory="$dst/usr/lib" $verbose popd done } get_triplet_path() { if command -v dpkg-architecture > /dev/null; then echo "/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" fi } search_library_path() { PATH_ARRAY=( "$(get_triplet_path)" "/usr/lib64" "/usr/lib" ) for path in "${PATH_ARRAY[@]}"; do if [ -d "$path" ]; then echo "$path" return 0 fi done } search_tool() { local tool="$1" local directory="$2" if command -v "$tool"; then return 0 fi PATH_ARRAY=( "$(get_triplet_path)/$directory/$tool" "/usr/lib64/$directory/$tool" "/usr/lib/$directory/$tool" "/usr/bin/$tool" "/usr/bin/$tool-64" "/usr/bin/$tool-32" ) for path in "${PATH_ARRAY[@]}"; do if [ -x "$path" ]; then echo "$path" return 0 fi done } DEPLOY_GTK_VERSION="${DEPLOY_GTK_VERSION:-0}" # When not set by user, this variable use the integer '0' as a sentinel value APPDIR= while [ "$1" != "" ]; do case "$1" in --plugin-api-version) echo "0" exit 0 ;; --appdir) APPDIR="$2" shift shift ;; --help) show_usage exit 0 ;; *) echo "Invalid argument: $1" echo show_usage exit 1 ;; esac done if [ "$APPDIR" == "" ]; then show_usage exit 1 fi APPDIR="$(realpath "$APPDIR")" mkdir -p "$APPDIR" . /etc/os-release if [ "$ID" = "debian" ] || [ "$ID" = "ubuntu" ]; then if ! command -v dpkg-architecture &>/dev/null; then echo -e "$0: dpkg-architecture not found.\nInstall dpkg-dev then re-run the plugin." exit 1 fi fi if command -v pkgconf > /dev/null; then PKG_CONFIG="pkgconf" elif command -v pkg-config > /dev/null; then PKG_CONFIG="pkg-config" else echo "$0: pkg-config/pkgconf not found in PATH, aborting" exit 1 fi # GTK's library path *must not* have a trailing slash for later parameter substitution to work properly LD_GTK_LIBRARY_PATH="$(realpath "${LD_GTK_LIBRARY_PATH:-$(search_library_path)}")" if ! command -v find &>/dev/null && ! type find &>/dev/null; then echo -e "$0: find not found.\nInstall findutils then re-run the plugin." exit 1 fi if [ -z "$LINUXDEPLOY" ]; then echo -e "$0: LINUXDEPLOY environment variable is not set.\nDownload a suitable linuxdeploy AppImage, set the environment variable and re-run the plugin." exit 1 fi gtk_versions=0 # Count major versions of GTK when auto-detect GTK version if [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then echo "Determining which GTK version to deploy" while IFS= read -r -d '' file; do if [ "$DEPLOY_GTK_VERSION" -ne 2 ] && ldd "$file" | grep -q "libgtk-x11-2.0.so"; then DEPLOY_GTK_VERSION=2 gtk_versions="$((gtk_versions+1))" fi if [ "$DEPLOY_GTK_VERSION" -ne 3 ] && ldd "$file" | grep -q "libgtk-3.so"; then DEPLOY_GTK_VERSION=3 gtk_versions="$((gtk_versions+1))" fi if [ "$DEPLOY_GTK_VERSION" -ne 4 ] && ldd "$file" | grep -q "libgtk-4.so"; then DEPLOY_GTK_VERSION=4 gtk_versions="$((gtk_versions+1))" fi done < <(find "$APPDIR/usr/bin" -executable -type f -print0) fi if [ "$gtk_versions" -gt 1 ]; then echo "$0: can not deploy multiple GTK versions at the same time." echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." exit 1 elif [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then echo "$0: failed to auto-detect GTK version." echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." exit 1 fi echo "Installing AppRun hook" HOOKSDIR="$APPDIR/apprun-hooks" HOOKFILE="$HOOKSDIR/linuxdeploy-plugin-gtk.sh" mkdir -p "$HOOKSDIR" cat > "$HOOKFILE" <<\EOF #! /usr/bin/env bash COLOR_SCHEME="$(dbus-send --session --dest=org.freedesktop.portal.Desktop --type=method_call --print-reply --reply-timeout=1000 /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read 'string:org.freedesktop.appearance' 'string:color-scheme' 2> /dev/null | tail -n1 | cut -b35- | cut -d' ' -f2 || printf '')" if [ -z "$COLOR_SCHEME" ]; then COLOR_SCHEME="$(gsettings get org.gnome.desktop.interface color-scheme 2> /dev/null || printf '')" fi case "$COLOR_SCHEME" in "1"|"'prefer-dark'") GTK_THEME_VARIANT="dark";; "2"|"'prefer-light'") GTK_THEME_VARIANT="light";; *) GTK_THEME_VARIANT="light";; esac APPIMAGE_GTK_THEME="${APPIMAGE_GTK_THEME:-"Adwaita:$GTK_THEME_VARIANT"}" # Allow user to override theme (discouraged) export APPDIR="${APPDIR:-"$(dirname "$(realpath "$0")")"}" # Workaround to run extracted AppImage export GTK_DATA_PREFIX="$APPDIR" export GTK_THEME="$APPIMAGE_GTK_THEME" # Custom themes are broken export GDK_BACKEND=x11 # Crash with Wayland backend on Wayland export XDG_DATA_DIRS="$APPDIR/usr/share:/usr/share:$XDG_DATA_DIRS" # g_get_system_data_dirs() from GLib EOF echo "Installing GLib schemas" # Note: schemasdir is undefined on Ubuntu 16.04 glib_schemasdir="$(get_pkgconf_variable "schemasdir" "gio-2.0" "/usr/share/glib-2.0/schemas")" copy_tree "$glib_schemasdir" "$APPDIR/" glib-compile-schemas "$APPDIR/$glib_schemasdir" cat >> "$HOOKFILE" <> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" else echo "WARNING: gtk-query-immodules-3.0 not found" fi if [ ! -f "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then echo "WARNING: immodules.cache file is missing" fi sed -i "s|$gtk3_libdir/3.0.0/immodules/||g" "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ;; 4) echo "Installing GTK 4.0 modules" gtk4_exec_prefix="$(get_pkgconf_variable "exec_prefix" "gtk4" "/usr")" gtk4_libdir="$(get_pkgconf_variable "libdir" "gtk4")/gtk-4.0" gtk4_path="$gtk4_libdir" copy_lib_tree "$gtk4_libdir" "$APPDIR/" cat >> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" else echo "WARNING: gdk-pixbuf-query-loaders not found" fi if [ ! -f "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then echo "WARNING: loaders.cache file is missing" fi sed -i "s|$gdk_pixbuf_moduledir/||g" "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" echo "Copying more libraries" gobject_libdir="$(get_pkgconf_variable "libdir" "gobject-2.0" "$LD_GTK_LIBRARY_PATH")" gio_libdir="$(get_pkgconf_variable "libdir" "gio-2.0" "$LD_GTK_LIBRARY_PATH")" librsvg_libdir="$(get_pkgconf_variable "libdir" "librsvg-2.0" "$LD_GTK_LIBRARY_PATH")" pango_libdir="$(get_pkgconf_variable "libdir" "pango" "$LD_GTK_LIBRARY_PATH")" pangocairo_libdir="$(get_pkgconf_variable "libdir" "pangocairo" "$LD_GTK_LIBRARY_PATH")" pangoft2_libdir="$(get_pkgconf_variable "libdir" "pangoft2" "$LD_GTK_LIBRARY_PATH")" FIND_ARRAY=( "$gdk_libdir" "libgdk_pixbuf-*.so*" "$gobject_libdir" "libgobject-*.so*" "$gio_libdir" "libgio-*.so*" "$librsvg_libdir" "librsvg-*.so*" "$pango_libdir" "libpango-*.so*" "$pangocairo_libdir" "libpangocairo-*.so*" "$pangoft2_libdir" "libpangoft2-*.so*" ) LIBRARIES=() for (( i=0; i<${#FIND_ARRAY[@]}; i+=2 )); do directory=${FIND_ARRAY[i]} library=${FIND_ARRAY[i+1]} while IFS= read -r -d '' file; do LIBRARIES+=( "--library=$file" ) done < <(find "$directory" \( -type l -o -type f \) -name "$library" -print0) done env LINUXDEPLOY_PLUGIN_MODE=1 "$LINUXDEPLOY" --appdir="$APPDIR" "${LIBRARIES[@]}" # Create symbolic links as a workaround # Details: https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/issues/24#issuecomment-1030026529 echo "Manually setting rpath for GTK modules" PATCH_ARRAY=( "$gtk3_immodulesdir" "$gtk3_printbackendsdir" "$gdk_pixbuf_moduledir" ) for directory in "${PATCH_ARRAY[@]}"; do while IFS= read -r -d '' file; do ln $verbose -sf "${file/$LD_GTK_LIBRARY_PATH\//}" "$APPDIR/usr/lib" done < <(find "$directory" -name '*.so' -print0) done ================================================ FILE: macos/Info.plist.in ================================================ CFBundleExecutable keyboard-configurator CFBundlePackageType APPL CFBundleVersion {crate_version} CFBundleIconFile keyboard-configurator CFBundleIdentifier com.system76.keyboardconfigurator CFBundleSignature ???? CFBundleDisplayName System76 Keyboard Configurator CFBundleName System76 Keyboard Configurator NSHighResolutionCapable ================================================ FILE: macos/README.md ================================================ ### Files - `build.py` - Builds with Cargo, generates a `.app` bundle, and build a `.dmg` - `Info.plist.in` - Used to generate `Info.plist`, processing with Python `.format()` - `appdmg.json` - Configuration file for [node-appdmg](https://github.com/LinusU/node-appdmg) ### Building `./build.py --release` should generate a `.dmg` ================================================ FILE: macos/appdmg.json ================================================ { "title": "Keyboard Configurator", "icon": "keyboard-configurator.icns", "background": "background.png", "contents": [ { "x": 448, "y": 334, "type": "link", "path": "/Applications" }, { "x": 192, "y": 334, "type": "file", "path": "System76 Keyboard Configurator.app" } ] } ================================================ FILE: macos/build.py ================================================ #!/usr/bin/env python3 import argparse import json import os import shutil import subprocess import sys import tempfile from deploy import deploy_with_deps # Handle commandline arguments parser = argparse.ArgumentParser() parser.add_argument('--release', action='store_true') parser.add_argument('--sign') args = parser.parse_args() # Executables to install TARGET_DIR = "../target/" + ('release' if args.release else 'debug') ICON = "../data/icons/scalable/apps/com.system76.keyboardconfigurator.svg" APPDIR = 'System76 Keyboard Configurator.app' # Build the application cmd = ["cargo", "build"] if args.release: cmd.append('--release') subprocess.check_call(cmd) # Extract crate version from cargo meta_str = subprocess.check_output(["cargo", "metadata", "--format-version", "1", "--no-deps"]) meta = json.loads(meta_str) package = next(i for i in meta['packages'] if i['name'] == 'system76-keyboard-configurator') crate_version = package['version'] # Remove old app dir if os.path.exists(APPDIR): shutil.rmtree(APPDIR) os.makedirs(APPDIR + '/Contents/Resources', exist_ok=True) # Generate Info.plist from Info.plist.in with open("Info.plist.in") as f: plist = f.read().format(crate_version=crate_version) with open(APPDIR + '/Contents/Info.plist', "w") as f: f.write(plist) # Generate .icns icon file with tempfile.TemporaryDirectory('.iconset') as d: for i in [16, 32, 64, 128, 256, 512]: outname = "{}/icon_{}x{}.png".format(d, i, i) subprocess.check_call(["rsvg-convert", "--width", str(i), "--height", str(i), "-o", outname, ICON]) # hidpi icon outname = "{}/icon_{}x{}x2.png".format(d, i, i) subprocess.check_call(["rsvg-convert", "--width", str(i * 2), "--height", str(i * 2), "-o", outname, ICON]) subprocess.check_call(["iconutil", "--convert", "icns", "--output", 'keyboard-configurator.icns', d]) shutil.copy('keyboard-configurator.icns', f'{APPDIR}/Contents/Resources/keyboard-configurator.icns') # Generate background png subprocess.check_call(["rsvg-convert", "--width", "640", "--height", "480", "-o", "background.png", "background.svg"]) # Copy executable subprocess.check_call([f"strip", '-o', f"keyboard-configurator", f"{TARGET_DIR}/system76-keyboard-configurator"]) # Build .app bundle deploy_with_deps('keyboard-configurator') if args.sign is not None: # Sign all .dylib files in the Resources folder subprocess.check_call([ "find", APPDIR + "/Contents/Resources", "-name", "*.dylib", "-exec", "codesign", "--force", "--verbose", "--sign", args.sign, "{}", ";"]) # Sign all .so files in the Resources folder subprocess.check_call([ "find", APPDIR + "/Contents/Resources", "-name", "*.so", "-exec", "codesign", "--force", "--verbose", "--sign", args.sign, "{}", ";"]) # Sign app bundle (with hardened runtime) subprocess.check_call(["codesign", "--force", "--verbose", "--deep", "--options", "runtime", "--sign", args.sign, APPDIR]) # Build .dmg if os.path.exists("keyboard-configurator.dmg"): os.remove("keyboard-configurator.dmg") subprocess.check_call(["appdmg", "appdmg.json", "keyboard-configurator.dmg"]) ================================================ FILE: macos/deploy.py ================================================ import hashlib import platform import os import re import shutil import subprocess APPDIR = 'System76 Keyboard Configurator.app' BINDIR = APPDIR + '/Contents/MacOS' RESOURCEDIR = APPDIR + '/Contents/Resources' if platform.machine() == 'arm64': PREFIX = '/opt/homebrew' else: PREFIX = '/usr/local' if not os.path.exists(PREFIX): if os.path.exists('/opt/local'): print("Homebrew not found, using MacPorts") PREFIX = '/opt/local' else: print("Homebrew and MacPorts not found") sys.exit(1) ADWAITA_FILES = [ 'index.theme', 'symbolic/actions/open-menu-symbolic.svg', 'symbolic/ui/window-close-symbolic.svg', 'symbolic/ui/window-maximize-symbolic.svg', 'symbolic/ui/window-minimize-symbolic.svg', 'symbolic/ui/window-restore-symbolic.svg', 'symbolic/actions/edit-delete-symbolic.svg', 'symbolic/actions/go-previous-symbolic.svg', 'symbolic/actions/list-remove-symbolic.svg', 'symbolic/actions/list-add-symbolic.svg', 'symbolic/actions/edit-find-symbolic.svg', ] ADWAITA_FILES = [f'share/icons/Adwaita/{i}' for i in ADWAITA_FILES] ADDITIONAL_FILES = ['share/glib-2.0/schemas/org.gtk.Settings.FileChooser.gschema.xml'] + ADWAITA_FILES def copy(srcdir, destdir, path): src = f"{srcdir}/{path}" dest = f"{destdir}/{path}" os.makedirs(os.path.dirname(dest), exist_ok=True) print(f"Copy {src} -> {dest}") if os.path.isdir(src): shutil.copytree(src, dest) else: shutil.copy(src, dest) def otool_recursive(path, libs): output = subprocess.check_output(["otool", "-L", path]).decode() for i in output.splitlines(): m = re.match('\t(' + PREFIX + '.*.dylib)', i) if m is not None: dep = m.group(1) if dep not in libs: libs.add(dep) otool_recursive(dep, libs) return libs def shasum(path): m = hashlib.sha256() with open(path, 'rb') as f: m.update(f.read()) return m.digest() def newpath(path): relpath = os.path.relpath(path, PREFIX) return os.path.join(RESOURCEDIR, relpath) def deploy_with_deps(binpath): pixbuf_ver = subprocess.check_output(['pkg-config', '--variable=gdk_pixbuf_binary_version', 'gdk-pixbuf-2.0']).decode().strip() pixbuf_dir = f"{PREFIX}/lib/gdk-pixbuf-2.0/{pixbuf_ver}/loaders" pixbuf_libs = [f"{pixbuf_dir}/{i}" for i in os.listdir(pixbuf_dir) if i.endswith('.so')] deps = set() otool_recursive(binpath, deps) for lib in pixbuf_libs: otool_recursive(lib, deps) # TODO: Parse `LC_RPATH` instead of special casing? rsvg_libdir = subprocess.check_output(['pkg-config', 'librsvg-2.0', '--variable=libdir']).decode().strip() rsvg_lib = f"{rsvg_libdir}/librsvg-2.2.dylib" deps.add(rsvg_lib) duplicates = {} shasums = {} for i in deps: cksum = shasum(i) if cksum in shasums: duplicates[i] = shasums[cksum] else: shasums[cksum] = i cmd = ['install_name_tool'] for i in deps: dest = newpath(duplicates.get(i, i)) cmd += ['-change', i, '@executable_path/' + os.path.relpath(dest, BINDIR)] cmd += ['-change', '@rpath/librsvg-2.2.dylib', '@executable_path/' + os.path.relpath(newpath(rsvg_lib), BINDIR)] def copy_and_install_name_tool(src, dest): os.makedirs(os.path.dirname(dest), exist_ok=True) shutil.copy(src, dest) subprocess.check_call(cmd + [dest]) # Generate new "adhoc" signature for modified binary (required on arm64) subprocess.check_call(['codesign', '-f', '-s', '-', dest]) copy_and_install_name_tool(binpath, os.path.join(BINDIR, os.path.basename(binpath) + '-bin')) for i in deps.union(set(pixbuf_libs)): if i not in duplicates: copy_and_install_name_tool(i, newpath(i)) shutil.copy(f'launcher.sh', os.path.join(BINDIR, os.path.basename(binpath))) with open(f'{APPDIR}/Contents/PkgInfo', 'w') as f: f.write('APPL????') shutil.copytree(f'{PREFIX}/share/icons/hicolor', f'{APPDIR}/Contents/Resources/share/icons/hicolor') for i in ADDITIONAL_FILES: copy(PREFIX, f'{APPDIR}/Contents/Resources', i) subprocess.check_call(["glib-compile-schemas", f"{APPDIR}/Contents/Resources/share/glib-2.0/schemas"]) module_dir = f"{RESOURCEDIR}/lib/gdk-pixbuf-2.0/{pixbuf_ver}" with open(f"{module_dir}/loaders.cache", 'w') as cachefile: cache = subprocess.check_output(['gdk-pixbuf-query-loaders'], env=dict(os.environ, GDK_PIXBUF_MODULEDIR=pixbuf_dir)).decode() cachefile.write(re.sub(f'{PREFIX}/.+/gdk-pixbuf-2.0/', '@executable_path/../Resources/lib/gdk-pixbuf-2.0/', cache)) ================================================ FILE: macos/launcher.sh ================================================ #!/bin/sh # https://gitlab.gnome.org/GNOME/gtk-mac-bundler/-/blob/master/examples/gtk3-launcher.sh if test "x$GTK_DEBUG_LAUNCHER" != x; then set -x fi if test "x$GTK_DEBUG_GDB" != x; then EXEC="gdb --args" else EXEC=exec fi name=`basename "$0"` tmp="$0" tmp=`dirname "$tmp"` tmp=`dirname "$tmp"` bundle=`dirname "$tmp"` bundle_contents="$bundle"/Contents bundle_res="$bundle_contents"/Resources bundle_lib="$bundle_res"/lib bundle_bin="$bundle_res"/bin bundle_data="$bundle_res"/share bundle_etc="$bundle_res"/etc export XDG_CONFIG_DIRS="$bundle_etc"/xdg export XDG_DATA_DIRS="$bundle_data" export GTK_DATA_PREFIX="$bundle_res" export GTK_EXE_PREFIX="$bundle_res" export GTK_PATH="$bundle_res" export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" if [ `uname -r | cut -d . -f 1` -ge 10 ]; then export GTK_IM_MODULE_FILE="$bundle_lib/gtk-3.0/3.0.0/immodules.cache" fi APP=$name I18NDIR="$bundle_data/locale" # Set the locale-related variables appropriately: unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE # Has a language ordering been set? # If so, set LC_MESSAGES and LANG accordingly; otherwise skip it. # First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW. APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' ` if test "$APPLELANGUAGES"; then # A language ordering exists. # Test, item per item, to see whether there is an corresponding locale. for L in $APPLELANGUAGES; do #test for exact matches: if test -f "$I18NDIR/${L}/LC_MESSAGES/$APP.mo"; then export LANG=$L break fi # This is a special case, because often the original strings are in US # English and there is no translation file. if test "x$L" == "xen_US"; then export LANG=$L break fi #OK, now test for just the first two letters: if test -f "$I18NDIR/${L:0:2}/LC_MESSAGES/$APP.mo"; then export LANG=${L:0:2} break fi #Same thing, but checking for any english variant. if test "x${L:0:2}" == "xen"; then export LANG=$L break fi; done fi unset APPLELANGUAGES L # If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists. APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder` if test -z ${LANG} && test -n $APPLECOLLATION; then if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then export LANG=${APPLECOLLATION:0:2} fi fi if test -n $APPLECOLLATION; then export LC_COLLATE=$APPLECOLLATION fi unset APPLECOLLATION # Continue by attempting to find the Locale preference. APPLELOCALE=`defaults read .GlobalPreferences AppleLocale` if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then if test -z $LANG; then export LANG="${APPLELOCALE:0:5}" fi elif test -z $LANG && test -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then export LANG="${APPLELOCALE:0:2}" fi # Next we need to set LC_MESSAGES. If at all possible, we want a full # 5-character locale to avoid the "Locale not supported by C library" # warning from Gtk -- even though Gtk will translate with a # two-character code. if test -n $LANG; then # If the language code matches the applelocale, then that's the message # locale; otherwise, if it's longer than two characters, then it's # probably a good message locale and we'll go with it. if test $LANG == ${APPLELOCALE:0:5} || test $LANG != ${LANG:0:2}; then export LC_MESSAGES=$LANG # Next try if the Applelocale is longer than 2 chars and the language # bit matches $LANG elif test $LANG == ${APPLELOCALE:0:2} && test $APPLELOCALE > ${APPLELOCALE:0:2}; then export LC_MESSAGES=${APPLELOCALE:0:5} # Fail. Get a list of the locales in $I18DIR that match # our two letter language code and pick the first one, special casing # english to set en_US elif test $LANG == "en"; then export LC_MESSAGES="en_US" else LOC=`find $I18DIR -name $LANG???` for L in $LOC; do export LC_MESSAGES=$L done fi else # All efforts have failed, so default to US english export LANG="en_US" export LC_MESSAGES="en_US" fi CURRENCY=`echo $APPLELOCALE | sed -En 's/.*currency=([[:alpha:]]+).*/\1/p'` if test -n "$CURRENCY"; then # The user has set a special currency. Gtk doesn't install # LC_MONETARY files, but Apple does in /usr/share/locale, so we're # going to look there for a locale to set LC_CURRENCY to. if test -f /usr/local/share/$LC_MESSAGES/LC_MONETARY; then if test `cat /usr/local/share/$LC_MESSAGES/LC_MONETARY` == $CURRENCY; then export LC_MONETARY=$LC_MESSAGES fi fi if test -z "$LC_MONETARY"; then FILES=`find /usr/share/locale -name LC_MONETARY -exec grep -H $CURRENCY {} \;` if test -n "$FILES"; then export LC_MONETARY=`echo $FILES | sed -En 's%/usr/share/locale/([[:alpha:]_]+)/LC_MONETARY.*%\1%p'` fi fi fi # No currency value means that the AppleLocale governs: if test -z "$LC_MONETARY"; then LC_MONETARY=${APPLELOCALE:0:5} fi # For Gtk, which only looks at LC_ALL: export LC_ALL=$LC_MESSAGES unset APPLELOCALE FILES LOC if test -f "$bundle_lib/charset.alias"; then export CHARSETALIASDIR="$bundle_lib" fi # Extra arguments can be added in environment.sh. EXTRA_ARGS= if test -f "$bundle_res/environment.sh"; then source "$bundle_res/environment.sh" fi # Strip out the argument added by the OS. if /bin/expr "x$1" : '^x-psn_' > /dev/null; then shift 1 fi $EXEC "$bundle_contents/MacOS/$name-bin" "$@" $EXTRA_ARGS ================================================ FILE: macos/signing.sh ================================================ #!/usr/bin/env bash set -e if [ -z "${MACOS_CERTIFICATE}" ] then echo "Set MACOS_CERTIFICATE to base64 encoded certificate" >&2 exit 1 fi # Set up keychain KEYCHAIN=system76-keyboard-configurator.keychain PASSWORD="$(uuidgen)" security create-keychain -p "${PASSWORD}" "${KEYCHAIN}" security default-keychain -s "${KEYCHAIN}" security unlock-keychain -p "${PASSWORD}" "${KEYCHAIN}" security set-keychain-settings -t 3600 -u "${KEYCHAIN}" echo "${MACOS_CERTIFICATE}" | base64 --decode > certificate.p12 security import certificate.p12 -P "" -k "${KEYCHAIN}" -T /usr/bin/codesign rm -f certificate.p12 security set-key-partition-list -S apple-tool:,apple: -s -k "${PASSWORD}" "${KEYCHAIN}" # Build with signing ./build.py --sign System76 "$@" # Delete keychain security delete-keychain "${KEYCHAIN}" # Submit for notarization xcrun notarytool submit \ --apple-id "${AC_USERNAME}" \ --team-id 'Y3W4TDQXXQ' \ --password "${AC_PASSWORD}" \ --wait \ keyboard-configurator.dmg # Try to staple notarization set +e attempts=30 for attempt in $(seq 1 $attempts) do echo "Staple attempt $attempt/$attempts" xcrun stapler staple keyboard-configurator.dmg exit_status="$?" echo "Staple exit status: ${exit_status}" case "${exit_status}" in 0) echo "Staple successful" exit 0 ;; 65) echo "Notarization may still be in progress" ;; *) echo "Staple exit status unknown" exit 1 ;; esac sleep 10 done echo "Staple timeout" exit 1 ================================================ FILE: rust-toolchain.toml ================================================ [toolchain] channel = "1.70.0" ================================================ FILE: src/about_dialog.rs ================================================ use crate::fl; use cascade::cascade; use gtk::prelude::*; pub fn show_about_dialog() { cascade! { gtk::AboutDialog::new(); ..set_titlebar(Some(&cascade! { gtk::HeaderBar::new(); ..set_show_close_button(true); ..show(); })); ..set_title(&fl!("app-about")); ..set_program_name(&fl!("app-title")); ..set_version(Some(env!("CARGO_PKG_VERSION"))); ..set_license_type(gtk::License::Gpl30); ..set_logo_icon_name(Some("com.system76.keyboardconfigurator")); ..connect_response(|dialog, _| dialog.close()); ..show(); }; } ================================================ FILE: src/backlight.rs ================================================ use crate::fl; use cascade::cascade; use futures::{prelude::*, stream::FuturesUnordered}; use gtk::{ glib::{self, clone, ControlFlow}, prelude::*, subclass::prelude::*, }; use once_cell::sync::Lazy; use std::cell::{Cell, RefCell}; use backend::{Board, DerefCell, Hs, Mode}; use widgets::{KeyboardColor, KeyboardColorIndex, SelectedKeys}; #[derive(Default)] pub struct BacklightInner { board: DerefCell, disable_color_button: DerefCell, keyboard_color: DerefCell, color_label: DerefCell, color_row: DerefCell, brightness_scale: DerefCell, brightness_label: DerefCell, brightness_row: DerefCell, saturation_scale: DerefCell, saturation_row: DerefCell, mode_combobox: DerefCell, mode_row: DerefCell, speed_scale: DerefCell, speed_row: DerefCell, layer: Cell, do_not_set: Cell, selected: RefCell, } #[glib::object_subclass] impl ObjectSubclass for BacklightInner { const NAME: &'static str = "S76Backlight"; type ParentType = gtk::ListBox; type Type = Backlight; } impl ObjectImpl for BacklightInner { fn constructed(&self) { let obj = self.obj(); self.do_not_set.set(true); let mode_combobox = cascade! { gtk::ComboBoxText::new(); ..connect_changed(clone!(@weak obj => move |_| obj.mode_speed_changed(); )); }; for mode in Mode::all() { mode_combobox.append(Some(mode.id), &mode.name); } let speed_scale = cascade! { gtk::Scale::with_range(gtk::Orientation::Horizontal, 0., 255., 1.); ..set_halign(gtk::Align::Fill); ..set_value_pos(gtk::PositionType::Right); ..set_size_request(200, 0); ..connect_value_changed(clone!(@weak obj => move |_| obj.mode_speed_changed(); )); }; let brightness_scale = cascade! { gtk::Scale::with_range(gtk::Orientation::Horizontal, 0., 100., 1.); ..set_halign(gtk::Align::Fill); ..set_value_pos(gtk::PositionType::Right); ..set_size_request(200, 0); ..connect_value_changed(clone!(@weak obj => move |_| obj.brightness_changed(); )); }; let keyboard_color = KeyboardColor::new(None, KeyboardColorIndex::Layer(0)); let saturation_adjustment = cascade! { gtk::Adjustment::new(0., 0., 100., 1., 1., 0.); ..bind_property("value", &keyboard_color, "hs") .transform_from(|_, value: glib::Value| { let hs: &Hs = value.get().unwrap(); Some((hs.s * 100.).to_value()) }) .transform_to(|_, value: glib::Value| { let s: f64 = value.get().unwrap(); Some(Hs::new(0., s / 100.).to_value()) }) .flags(glib::BindingFlags::BIDIRECTIONAL) .build(); }; let saturation_scale = cascade! { gtk::Scale::new(gtk::Orientation::Horizontal, Some(&saturation_adjustment)); ..set_halign(gtk::Align::Fill); ..set_value_pos(gtk::PositionType::Right); ..set_digits(0); ..set_size_request(200, 0); }; fn row(widget: &impl IsA) -> gtk::ListBoxRow { cascade! { gtk::ListBoxRow::new(); ..set_selectable(false); ..set_activatable(false); ..set_margin(8); ..add(widget); } } fn label_row(label: &str, widget: &impl IsA) -> gtk::ListBoxRow { row(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 8); ..add(&cascade! { gtk::Label::new(Some(label)); ..set_halign(gtk::Align::Start); }); ..pack_end(widget, false, false, 0); }) } let disable_color_button = cascade! { gtk::Button::with_label(&fl!("button-disable")); ..set_no_show_all(true); ..connect_clicked(clone!(@weak obj => move |_| obj.disable_color_clicked())); }; let color_label = gtk::Label::new(None); let brightness_label = gtk::Label::new(Some(&fl!("layer-all-brightness"))); let mode_row = label_row(&fl!("layer-color-pattern"), &mode_combobox); let speed_row = label_row(&fl!("layer-animation-speed"), &speed_scale); let saturation_row = label_row(&fl!("layer-saturation"), &saturation_scale); let color_row = row(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 8); ..add(&color_label); ..pack_end(&keyboard_color, false, false, 0); ..pack_end(&disable_color_button, false, false, 0); }); let brightness_row = row(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 8); ..add(&brightness_label); ..pack_end(&brightness_scale, false, false, 0); }); cascade! { obj; ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&mode_row); ..add(&speed_row); ..add(&saturation_row); ..add(&color_row); ..add(&brightness_row); }; self.disable_color_button.set(disable_color_button); self.keyboard_color.set(keyboard_color); self.color_label.set(color_label); self.color_row.set(color_row); self.brightness_label.set(brightness_label); self.brightness_scale.set(brightness_scale); self.brightness_row.set(brightness_row); self.mode_combobox.set(mode_combobox); self.mode_row.set(mode_row); self.speed_scale.set(speed_scale); self.speed_row.set(speed_row); self.saturation_scale.set(saturation_scale); self.saturation_row.set(saturation_row); } fn dispose(&self) { self.obj().led_save(); } fn properties() -> &'static [glib::ParamSpec] { static PROPERTIES: Lazy> = Lazy::new(|| { vec![ glib::ParamSpecString::builder("mode").read_only().build(), glib::ParamSpecBoxed::builder::("selected") .write_only() .build(), glib::ParamSpecBoolean::builder("is-per-key") .read_only() .build(), ] }); PROPERTIES.as_ref() } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "selected" => { let selected: &SelectedKeys = value.get().unwrap(); self.selected.replace(selected.clone()); self.obj().update_per_key(); } _ => unimplemented!(), } } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "mode" => self.obj().mode().id.to_value(), "is-per-key" => self.obj().mode().is_per_key().to_value(), _ => unimplemented!(), } } } impl WidgetImpl for BacklightInner {} impl ContainerImpl for BacklightInner {} impl ListBoxImpl for BacklightInner {} glib::wrapper! { pub struct Backlight(ObjectSubclass) @extends gtk::ListBox, gtk::Container, gtk::Widget; } impl Backlight { pub fn new(board: Board) -> Self { let max_brightness = board.max_brightness() as f64; let has_led_save = board.has_led_save(); let obj: Self = glib::Object::new(); obj.inner().board.set(board.clone()); obj.inner().keyboard_color.set_board(Some(board)); obj.inner().brightness_scale.set_range(0.0, max_brightness); obj.invalidate_filter(); obj.set_layer(0); obj.set_filter_func(Some(Box::new( clone!(@weak obj => @default-panic, move |row| obj.filter_func(row) ), ))); obj.set_header_func(Some(Box::new(clone!(@weak obj => move |row, before| obj.header_func(row, before) )))); if !obj.board().layout().meta.has_per_layer { obj.inner() .brightness_label .set_label(&fl!("keyboard-brightness")); } if has_led_save { glib::timeout_add_seconds_local( 10, clone!(@weak obj => @default-return ControlFlow::Break, move || { obj.led_save(); ControlFlow::Continue }), ); } obj } fn inner(&self) -> &BacklightInner { BacklightInner::from_obj(self) } fn board(&self) -> &Board { &self.inner().board } pub fn mode(&self) -> &'static Mode { if let Some(id) = self.inner().mode_combobox.active_id() { if let Some(mode) = Mode::from_id(id.as_str()) { return mode; } } Mode::from_id("SOLID_COLOR").unwrap() } fn header_func(&self, row: >k::ListBoxRow, before: Option<>k::ListBoxRow>) { if before.is_none() { row.set_header(None::<>k::Widget>) } else if row.header().is_none() { row.set_header(Some(&cascade! { gtk::Separator::new(gtk::Orientation::Horizontal); ..show(); })); } } fn filter_func(&self, row: >k::ListBoxRow) -> bool { let inner = self.inner(); let layout = inner.board.layout(); if row == &*inner.mode_row { layout.meta.has_mode } else if row == &*inner.speed_row { layout.meta.has_mode && self.mode().has_speed } else if row == &*inner.color_row { layout.meta.has_color && (!layout.meta.has_mode || self.mode().has_hue) } else if row == &*inner.saturation_row { !self.mode().has_hue && !self.mode().is_disabled() } else if row == &*inner.brightness_row { layout.meta.has_brightness && (!layout.meta.has_mode || !self.mode().is_disabled()) } else { true } } fn mode_speed_changed(&self) { self.notify("mode"); self.notify("is-per-key"); if self.mode().is_per_key() { self.update_per_key(); self.inner().color_label.set_label(&fl!("key-color")); } else { self.inner().keyboard_color.set_sensitive(true); self.inner() .keyboard_color .set_index(KeyboardColorIndex::Layer(self.inner().layer.get())); if self.board().layout().meta.has_per_layer { self.inner().color_label.set_label(&fl!("layer-color")); } else { self.inner().color_label.set_label(&fl!("keyboard-color")); } } self.inner() .disable_color_button .set_visible(self.mode().is_per_key()); self.invalidate_filter(); if self.inner().do_not_set.get() { return; } let board = self.board().clone(); let speed = self.inner().speed_scale.value(); let mode = self.mode(); let layer = self.inner().layer.get(); glib::MainContext::default().spawn_local(async move { let layer = &board.layers()[layer]; if let Err(err) = layer.set_mode(mode, speed as u8).await { error!("{}: {}", fl!("error-set-keyboard-mode"), err); } }); } fn brightness_changed(&self) { if self.inner().do_not_set.get() { return; } let value = self.inner().brightness_scale.value() as i32; let board = self.board().clone(); glib::MainContext::default().spawn_local(async move { for layer in board.layers() { if let Err(err) = layer.set_brightness(value).await { error!("{}: {}", fl!("error-set-keyboard-brightness"), err); } } }); debug!("Brightness: {}", value) } pub fn set_layer(&self, mut layer: usize) { if !self.board().layout().meta.has_per_layer { layer = 0; } self.inner().layer.set(layer); let layer = &self.board().layers()[layer]; let (mode, speed) = layer.mode().unwrap_or((&Mode::all()[0], 128)); let brightness = layer.brightness() as f64; self.inner().do_not_set.set(true); self.inner().mode_combobox.set_active_id(Some(mode.id)); self.inner().speed_scale.set_value(speed.into()); self.inner().brightness_scale.set_value(brightness); if !self.mode().is_per_key() { self.inner() .keyboard_color .set_index(KeyboardColorIndex::Layer(self.inner().layer.get())); } self.inner().do_not_set.set(false); } fn update_per_key(&self) { if !self.mode().is_per_key() { return; } let selected = self.inner().selected.borrow(); self.inner() .keyboard_color .set_index(KeyboardColorIndex::Keys(selected.clone())); self.inner() .keyboard_color .set_sensitive(!selected.is_empty()); self.inner() .disable_color_button .set_sensitive(!selected.is_empty()); } fn disable_color_clicked(&self) { let self_ = self.clone(); let selected = self.inner().selected.borrow().clone(); glib::MainContext::default().spawn_local(async move { let futures = FuturesUnordered::new(); for i in selected.iter() { futures.push(self_.board().keys()[*i].set_color(None)); } if let Err(err) = futures.try_collect::<()>().await { error!("{}: {}", fl!("error-disable-key"), err); } self_.update_per_key(); }); } fn led_save(&self) { if self.board().has_led_save() { let board = self.board().clone(); glib::MainContext::default().spawn_local(async move { if let Err(err) = board.led_save().await { error!("{}: {}", fl!("error-save-leds"), err); } }); } } } ================================================ FILE: src/configurator_app.rs ================================================ use cascade::cascade; use gtk::{gdk, gio, glib, prelude::*, subclass::prelude::*}; use std::cell::Cell; use std::process::Command; use crate::{about_dialog, fl, MainWindow, Page}; use backend::DerefCell; #[derive(Default)] pub struct ConfiguratorAppInner { phony_board_names: DerefCell>, debug_layers: Cell, launch_test: Cell, } #[glib::object_subclass] impl ObjectSubclass for ConfiguratorAppInner { const NAME: &'static str = "S76ConfiguratorApp"; type ParentType = gtk::Application; type Type = ConfiguratorApp; } impl ObjectImpl for ConfiguratorAppInner { fn constructed(&self) { let app = self.obj(); app.set_application_id(Some("com.system76.keyboardconfigurator")); self.parent_constructed(); app.add_main_option( "fake-keyboard", glib::Char::from(b'k'), glib::OptionFlags::NONE, glib::OptionArg::String, "", None, ); app.add_main_option( "debug-layers", glib::Char::from(b'\0'), glib::OptionFlags::NONE, glib::OptionArg::None, "", None, ); app.add_main_option( "launch-test", glib::Char::from(b'\0'), glib::OptionFlags::NONE, glib::OptionArg::None, "", None, ); } } impl ApplicationImpl for ConfiguratorAppInner { fn handle_local_options(&self, opts: &glib::VariantDict) -> glib::ExitCode { fn lookup(opts: &glib::VariantDict, key: &str) -> Option { opts.lookup_value(key, None)?.get() } let board_names = match lookup::(opts, "fake-keyboard").as_deref() { Some("all") => backend::layouts().iter().map(|s| s.to_string()).collect(), Some(value) => value.split(',').map(str::to_string).collect(), None => vec![], }; self.phony_board_names.set(board_names); self.debug_layers.set(opts.contains("debug-layers")); self.launch_test.set(opts.contains("launch-test")); self.parent_handle_local_options(opts) } fn startup(&self) { self.parent_startup(); let about_action = cascade! { gio::SimpleAction::new("about", None); ..connect_activate(|_, _| about_dialog::show_about_dialog()); }; let flash_1 = cascade! { gio::SimpleAction::new("flash-to-launch-1", None); ..connect_activate(|_, _| { let _ = Command::new("dfu-programmer").args(["atmega32u4", "erase"]).status(); let _ = Command::new("dfu-programmer").args(["atmega32u4", "flash", "/var/lib/system76-keyboard-configurator/system76_launch_1_default.hex", "--suppress-bootloader-mem"]).status(); let _ = Command::new("dfu-programmer").args(["atmega32u4", "start"]).status(); }); }; let flash_2 = cascade! { gio::SimpleAction::new("flash-to-launch-2", None); ..connect_activate(|_, _| { let _ = Command::new("dfu-programmer").args(["at90usb646", "flash", "/var/lib/system76-keyboard-configurator/system76_launch_2_default.hex", "--suppress-bootloader-mem"]).status(); let _ = Command::new("dfu-programmer").args(["at90usb646", "reset"]).status(); }); }; let flash_lite_1 = cascade! { gio::SimpleAction::new("flash-to-launch-lite-1", None); ..connect_activate(|_, _| { let _ = Command::new("dfu-programmer").args(["at90usb646", "flash", "/var/lib/system76-keyboard-configurator/system76_launch_lite_1_default.hex", "--suppress-bootloader-mem"]).status(); let _ = Command::new("dfu-programmer").args(["at90usb646", "reset"]).status(); }); }; let flash_heavy_1 = cascade! { gio::SimpleAction::new("flash-to-launch-heavy-1", None); ..connect_activate(|_, _| { let _ = Command::new("dfu-programmer").args(["at90usb646", "flash", "/var/lib/system76-keyboard-configurator/system76_launch_heavy_1_default.hex", "--suppress-bootloader-mem"]).status(); let _ = Command::new("dfu-programmer").args(["at90usb646", "reset"]).status(); }); }; let app = self.obj(); app.add_action(&about_action); app.add_action(&flash_heavy_1); app.add_action(&flash_2); app.add_action(&flash_1); app.add_action(&flash_lite_1); app.set_accels_for_action("kbd.import", &["o"]); app.set_accels_for_action("kbd.export", &["e"]); for (i, _) in Page::iter_all().enumerate() { app.set_accels_for_action(&format!("kbd.page{}", i), &[&format!("{}", i + 1)]); } } fn activate(&self) { self.parent_activate(); if let Some(window) = self.obj().active_window() { info!("Focusing current window"); window.present(); } else { MainWindow::new(&self.obj()); } } } impl GtkApplicationImpl for ConfiguratorAppInner {} glib::wrapper! { pub struct ConfiguratorApp(ObjectSubclass) @extends gtk::Application, gio::Application, @implements gio::ActionGroup, gio::ActionMap; } impl ConfiguratorApp { fn new() -> Self { glib::Object::new() } fn inner(&self) -> &ConfiguratorAppInner { ConfiguratorAppInner::from_obj(self) } pub fn phony_board_names(&self) -> &[String] { &self.inner().phony_board_names } pub fn debug_layers(&self) -> bool { self.inner().debug_layers.get() } pub fn launch_test(&self) -> bool { self.inner().launch_test.get() } } #[cfg(target_os = "macos")] fn macos_init() { use std::process; let mut prefer_dark = false; // This command returns Dark if we should use the dark theme // defaults read -g AppleInterfaceStyle if let Ok(output) = process::Command::new("defaults") .arg("read") .arg("-g") .arg("AppleInterfaceStyle") .output() { prefer_dark = output.stdout.starts_with(b"Dark"); } if let Some(settings) = gtk::Settings::default() { settings.set_gtk_decoration_layout(Some("close,minimize,maximize:menu")); settings.set_gtk_application_prefer_dark_theme(prefer_dark); settings.set_gtk_enable_animations(false); } let css_provider = cascade! { gtk::CssProvider::new(); ..load_from_data(b" button, button:hover { box-shadow: none; -gtk-icon-shadow: none; text-shadow: none; } ").unwrap(); }; gtk::StyleContext::add_provider_for_screen( &gdk::Screen::default().unwrap(), &css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, ); } #[cfg(target_os = "windows")] fn windows_init() { // This is a dword with a value of 0 if we should use the dark theme: // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme use winreg::RegKey; let mut prefer_dark = false; let hkcu = RegKey::predef(winreg::enums::HKEY_CURRENT_USER); if let Ok(subkey) = hkcu.open_subkey("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize") { if let Ok(dword) = subkey.get_value::("AppsUseLightTheme") { prefer_dark = dword == 0; } } if let Some(settings) = gtk::Settings::default() { settings.set_gtk_application_prefer_dark_theme(prefer_dark); } } pub fn run() -> glib::ExitCode { gtk::init().unwrap(); glib::set_prgname(Some("com.system76.keyboardconfigurator")); glib::set_application_name(&fl!("app-title")); gdk::set_program_class(&fl!("app-title")); #[cfg(target_os = "macos")] macos_init(); #[cfg(target_os = "windows")] windows_init(); gio::resources_register_include!("compiled.gresource").unwrap(); gtk::Window::set_default_icon_name("com.system76.keyboardconfigurator"); let application = ConfiguratorApp::new(); application.run() } ================================================ FILE: src/error_dialog.rs ================================================ use cascade::cascade; use gtk::prelude::*; use std::fmt::Display; pub fn show_error_dialog, E: Display>(parent: &W, title: &str, err: E) { let label = cascade! { gtk::Label::new(Some(&format!("{}:\n{}", title, err))); ..set_use_markup(true); ..show(); }; let dialog = cascade! { gtk::Dialog::with_buttons(Some(title), Some(parent), gtk::DialogFlags::MODAL | gtk::DialogFlags::USE_HEADER_BAR, &[("Ok", gtk::ResponseType::Ok)]); ..connect_response(|dialog, _| dialog.close()); }; let header = dialog.header_bar().unwrap(); header.set_show_close_button(false); let content = dialog.content_area(); content.add(&label); content.set_margin(24); dialog.show(); } ================================================ FILE: src/keyboard.rs ================================================ use crate::fl; use cascade::cascade; use futures::{prelude::*, stream::FuturesUnordered}; use gtk::{ gio, glib::{self, clone, object::WeakRef}, prelude::*, subclass::prelude::*, }; use std::{ cell::{Cell, RefCell}, collections::HashMap, fs::File, pin::Pin, str, }; use crate::{show_error_dialog, Backlight, KeyboardLayer, MainWindow, Page, Picker, Testing}; use backend::{Board, BoardEvent, DerefCell, KeyMap, Layout, Mode}; use widgets::SelectedKeys; #[derive(Default)] pub struct KeyboardInner { action_group: DerefCell, invert_f_action: DerefCell, board: DerefCell, page: Cell, picker: RefCell>, selected: RefCell, layer_stack: DerefCell, stack: DerefCell, picker_box: DerefCell, backlight: DerefCell, testing: DerefCell>, } #[glib::object_subclass] impl ObjectSubclass for KeyboardInner { const NAME: &'static str = "S76Keyboard"; type ParentType = gtk::Box; type Type = Keyboard; } impl ObjectImpl for KeyboardInner { fn constructed(&self) { self.parent_constructed(); let keyboard = self.obj(); let layer_stack = cascade! { gtk::Stack::new(); ..set_transition_duration(0); ..connect_visible_child_notify( clone!(@weak keyboard => move |stack| { let page = stack .visible_child() .map(|c| c.downcast_ref::().unwrap().page()); debug!("{:?}", page); let last_layer = keyboard.layer(); keyboard.inner().page.set(page.unwrap_or(Page::Layer1)); let layer = keyboard.layer(); if layer != last_layer { keyboard.set_selected(keyboard.selected()); keyboard.inner().backlight.set_sensitive(layer.is_some()); if let Some(layer) = layer { keyboard.inner().backlight.set_layer(layer); } } }) ); }; let picker_box = gtk::Box::new(gtk::Orientation::Vertical, 0); let stack = cascade! { gtk::Stack::new(); ..set_homogeneous(false); ..connect_visible_child_notify(clone!(@weak keyboard => move |_| keyboard.update_selectable())); }; let stack_switcher = cascade! { gtk::StackSwitcher::new(); ..set_margin_top(12); ..set_halign(gtk::Align::Center); ..set_stack(Some(&stack)); }; cascade! { &keyboard; ..set_orientation(gtk::Orientation::Vertical); ..set_spacing(32); ..add(&stack_switcher); ..add(&layer_stack); ..add(&stack); }; let invert_f_action = cascade! { gio::SimpleAction::new("invert-f-keys", None); ..connect_activate(clone!(@weak keyboard => move |_, _| glib::MainContext::default().spawn_local(async move { keyboard.invert_f_keys().await; }); )); }; let action_group = cascade! { gio::SimpleActionGroup::new(); ..add_action(&cascade! { gio::SimpleAction::new("import", None); ..connect_activate(clone!(@weak keyboard => move |_, _| keyboard.import(); )); }); ..add_action(&cascade! { gio::SimpleAction::new("export", None); ..connect_activate(clone!(@weak keyboard => move |_, _| keyboard.export(); )); }); ..add_action(&cascade! { gio::SimpleAction::new("reset", None); ..connect_activate(clone!(@weak keyboard => move |_, _| glib::MainContext::default().spawn_local(async move { keyboard.reset().await; }); )); }); ..add_action(&invert_f_action); }; self.action_group.set(action_group); self.invert_f_action.set(invert_f_action); self.layer_stack.set(layer_stack); self.stack.set(stack); self.picker_box.set(picker_box); } fn properties() -> &'static [glib::ParamSpec] { use once_cell::sync::Lazy; static PROPERTIES: Lazy> = Lazy::new(|| vec![glib::ParamSpecBoxed::builder::("selected").build()]); PROPERTIES.as_ref() } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "selected" => self .obj() .set_selected(value.get::<&SelectedKeys>().unwrap().clone()), _ => unimplemented!(), } } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "selected" => self.obj().selected().to_value(), _ => unimplemented!(), } } } impl WidgetImpl for KeyboardInner {} impl ContainerImpl for KeyboardInner {} impl BoxImpl for KeyboardInner {} glib::wrapper! { pub struct Keyboard(ObjectSubclass) @extends gtk::Box, gtk::Container, gtk::Widget, @implements gtk::Orientable; } impl Keyboard { pub fn new(board: Board, debug_layers: bool, launch_test: bool) -> Self { let keyboard: Self = glib::Object::new(); keyboard .inner() .invert_f_action .set_enabled(!board.layout().meta.no_fn_f); let stack = &keyboard.inner().stack; if launch_test { let testing = cascade! { Testing::new(&board, &keyboard); ..set_halign(gtk::Align::Center); }; stack.add_titled(&testing, "testing", &fl!("stack-testing")); keyboard.inner().testing.set(Some(testing)); } else { keyboard.inner().testing.set(None); } stack.add_titled( &cascade! { gtk::Box::new(gtk::Orientation::Vertical, 32); ..add(&cascade! { gtk::Label::new(Some(&fl!("stack-keymap-desc"))); ..set_line_wrap(true); ..set_max_width_chars(100); ..set_halign(gtk::Align::Center); }); ..add(&*keyboard.inner().picker_box); }, "keymap", &fl!("stack-keymap"), ); let backlight = cascade! { Backlight::new(board.clone()); ..set_halign(gtk::Align::Center); ..connect_local("notify::is-per-key", false, clone!(@weak keyboard => @default-panic, move |_| { keyboard.update_selectable(); None })); }; let leds_desc = if board.layout().meta.has_per_layer { fl!("stack-leds-desc") } else { fl!("stack-leds-desc-builtin") }; keyboard .bind_property("selected", &backlight, "selected") .build(); if board.layout().meta.has_brightness { stack.add_titled( &cascade! { gtk::Box::new(gtk::Orientation::Vertical, 32); ..add(&cascade! { gtk::Label::new(Some(&leds_desc)); ..set_line_wrap(true); ..set_max_width_chars(100); ..set_halign(gtk::Align::Center); }); ..add(&backlight); }, "leds", &fl!("stack-leds"), ); } keyboard.inner().board.set(board); keyboard.inner().backlight.set(backlight); keyboard.add_pages(debug_layers); keyboard.update_selectable(); keyboard } fn inner(&self) -> &KeyboardInner { KeyboardInner::from_obj(self) } pub fn handle_backend_event(&self, event: BoardEvent) { match event { BoardEvent::KeymapChanged => self.queue_draw(), BoardEvent::LedsChanged => {} BoardEvent::MatrixChanged => { self.queue_draw(); if let Some(testing) = self.inner().testing.as_ref() { testing.selma_update_colors(); } } } } pub fn action_group(&self) -> &gio::ActionGroup { self.inner().action_group.upcast_ref() } pub fn board(&self) -> &Board { &self.inner().board } pub fn display_name(&self) -> String { let name = &self.layout().meta.display_name; let model = self.board().model().split_once('/').unwrap().1; if self.board().is_fake() { format!("{} ({})", name, fl!("board-fake", model = model)) } else { format!("{} ({})", name, model) } } fn layout(&self) -> &Layout { self.inner().board.layout() } fn window(&self) -> Option { self.toplevel()?.downcast().ok() } pub fn layer(&self) -> Option { self.inner().page.get().layer() } pub fn selected(&self) -> SelectedKeys { self.inner().selected.borrow().clone() } pub fn layer_stack(&self) -> >k::Stack { &self.inner().layer_stack } pub fn has_scancode(&self, scancode_name: &str) -> bool { self.layout().scancode_from_name(scancode_name).is_some() } pub async fn keymap_set(&self, key_index: usize, layer: usize, scancode_name: &str) { if let Err(err) = self.board().keys()[key_index] .set_scancode(layer, scancode_name) .await { error!("{}: {:?}", fl!("error-set-keymap"), err); } self.set_selected(self.selected()); } pub fn export_keymap(&self) -> KeyMap { self.board().export_keymap() } pub async fn import_keymap(&self, keymap: KeyMap) { // TODO: Ideally don't want this function to be O(Keys^2) // TODO: Make sure it doesn't panic with invalid json with invalid indexes? if keymap.model != self.board().model() { show_error_dialog( &self.window().unwrap(), &fl!("error-import-keymap"), fl!("keymap-for-board", model = keymap.model), ); return; } let _loader = self.toplevel().and_then(|x| { Some( x.downcast_ref::()? .display_loader(&fl!("loading-keyboard", keyboard = self.display_name())), ) }); let key_indices = self .board() .keys() .iter() .enumerate() .map(|(i, k)| (&k.logical_name, i)) .collect::>(); let futures = FuturesUnordered::>>>::new(); for (k, v) in &keymap.map { for (layer, scancode_name) in v.iter().enumerate() { let n = key_indices[&k]; futures.push(Box::pin(async move { if let Err(err) = self.board().keys()[n] .set_scancode(layer, scancode_name) .await { error!("{}: {:?}", fl!("error-set-keymap"), err); } })); } } for (k, hs) in &keymap.key_leds { let res = self.board().keys()[key_indices[&k]].set_color(*hs); futures.push(Box::pin(async move { if let Err(err) = res.await { error!("{}: {}", fl!("error-key-led"), err); } })); } for (i, keymap_layer) in keymap.layers.iter().enumerate() { let layer = &self.board().layers()[i]; if let Some((mode, speed)) = keymap_layer.mode { futures.push(Box::pin(async move { if let Err(err) = layer.set_mode(Mode::from_index(mode).unwrap(), speed).await { error!("{}: {}", fl!("error-set-layer-mode"), err) } })); } futures.push(Box::pin(async move { if let Err(err) = layer.set_brightness(keymap_layer.brightness).await { error!("{}: {}", fl!("error-set-layer-brightness"), err) } })); futures.push(Box::pin(async move { if let Err(err) = layer.set_color(keymap_layer.color).await { error!("{}: {}", fl!("error-set-layer-color"), err) } })); } futures.collect::<()>().await; } fn import(&self) { let filter = cascade! { gtk::FileFilter::new(); ..set_name(Some("json")); ..add_pattern("*.json"); }; let chooser = cascade! { gtk::FileChooserNative::new(Some(&fl!("layout-import")), None::<>k::Window>, gtk::FileChooserAction::Open, Some(&fl!("button-import")), Some(&fl!("button-cancel"))); ..add_filter(filter); }; if chooser.run() == gtk::ResponseType::Accept { let path = chooser.filename().unwrap(); match File::open(path) { Ok(file) => match KeyMap::from_reader(file) { Ok(keymap) => { let self_ = self.clone(); glib::MainContext::default().spawn_local(async move { self_.import_keymap(keymap).await; }); } Err(err) => { show_error_dialog(&self.window().unwrap(), "Failed to import keymap", err) } }, Err(err) => show_error_dialog(&self.window().unwrap(), "Failed to open file", err), } } } fn export(&self) { let filter = cascade! { gtk::FileFilter::new(); ..set_name(Some("json")); ..add_pattern("*.json"); }; let chooser = cascade! { gtk::FileChooserNative::new(Some(&fl!("layout-export")), None::<>k::Window>, gtk::FileChooserAction::Save, Some("Export"), Some("Cancel")); ..add_filter(filter); ..set_current_name(&format!("{}.json", fl!("untitled-layout"))); ..set_do_overwrite_confirmation(true); }; if chooser.run() == gtk::ResponseType::Accept { let path = chooser.filename().unwrap(); let keymap = self.export_keymap(); if keymap.version != 1 { show_error_dialog( &self.window().unwrap(), &fl!("error-unsupported-keymap"), fl!("error-unsupported-keymap-desc"), ) } match File::create(path) { Ok(file) => match keymap.to_writer_pretty(file) { Ok(()) => {} Err(err) => { show_error_dialog(&self.window().unwrap(), &fl!("error-export-keymap"), err) } }, Err(err) => { show_error_dialog(&self.window().unwrap(), &fl!("error-open-file"), err) } } } } pub async fn reset(&self) { self.import_keymap(self.layout().default.clone()).await; } async fn invert_f_keys(&self) { let key_indices = self .board() .keys() .iter() .enumerate() .map(|(i, k)| (k.logical_name.as_str(), i)) .collect::>(); let futures = FuturesUnordered::>>>::new(); for i in self.layout().f_keys() { let k = &self.board().keys()[key_indices[i]]; let layer0_keycode = k.get_scancode(0).unwrap().1; let layer1_keycode = k.get_scancode(1).unwrap().1; if layer1_keycode == "ROLL_OVER" { continue; } futures.push(Box::pin(async move { if let Err(err) = k.set_scancode(0, &layer1_keycode).await { error!("{}: {:?}", fl!("error-set-keymap"), err); } })); futures.push(Box::pin(async move { if let Err(err) = k.set_scancode(1, &layer0_keycode).await { error!("{}: {:?}", fl!("error-set-keymap"), err); } })); } futures.collect::<()>().await; } fn update_selectable(&self) { if !self.inner().backlight.is_some() { return; } let tab_name = self.inner().stack.visible_child_name(); let tab_name = tab_name.as_deref(); let is_per_key = self.inner().backlight.mode().is_per_key(); let selectable = tab_name == Some("keymap") || (tab_name == Some("leds") && is_per_key); self.inner().layer_stack.foreach(|layer| { let layer = layer.downcast_ref::().unwrap(); layer.set_selectable(selectable); }); } fn add_pages(&self, debug_layers: bool) { let layer_stack = &*self.inner().layer_stack; for (i, page) in Page::iter_all().enumerate() { if !debug_layers && page.is_debug() { continue; } else if let Some(layer) = page.layer() { if layer >= self.layout().meta.num_layers.into() { continue; } } let keyboard_layer = cascade! { KeyboardLayer::new(page, self.board().clone()); ..set_selectable(true); }; self.bind_property("selected", &keyboard_layer, "selected") .flags(glib::BindingFlags::BIDIRECTIONAL) .build(); if let Some(testing) = &*self.inner().testing { testing .bind_property("colors", &keyboard_layer, "testing-colors") .flags(glib::BindingFlags::SYNC_CREATE) .build(); } layer_stack.add_titled(&keyboard_layer, &page.name(), &page.name()); self.inner().action_group.add_action(&cascade! { gio::SimpleAction::new(&format!("page{}", i), None); ..connect_activate(clone!(@weak layer_stack, @weak keyboard_layer => move |_, _| layer_stack.set_visible_child(&keyboard_layer); )); }); } } pub(super) fn set_picker(&self, picker: Option<&Picker>) { // This function is called by Picker::set_keyboard() *self.inner().picker.borrow_mut() = match picker { Some(picker) => { self.inner().picker_box.add(picker); picker.set_sensitive(!self.selected().is_empty() && self.layer().is_some()); picker.downgrade() } None => WeakRef::new(), }; } fn set_selected(&self, selected: SelectedKeys) { let picker = match self.inner().picker.borrow().upgrade() { Some(picker) => picker, None => { return; } }; let keys = self.board().keys(); let mut selected_scancodes = Vec::new(); for i in selected.iter() { let k = &keys[*i]; debug!("{:#?}", k); if let Some(layer) = self.layer() { if let Some((_scancode, scancode_name)) = k.get_scancode(layer) { selected_scancodes.push(scancode_name); } } } picker.set_selected(selected_scancodes); picker.set_sensitive(selected.len() > 0 && self.layer().is_some()); self.inner().selected.replace(selected); self.queue_draw(); self.notify("selected"); } } ================================================ FILE: src/keyboard_layer.rs ================================================ use cascade::cascade; use gtk::{cairo, gdk, glib, glib::Propagation, pango, prelude::*, subclass::prelude::*}; use once_cell::unsync::OnceCell; use std::{ cell::{Cell, RefCell}, f64::consts::PI, }; use crate::{Page, TestingColors}; use backend::{Board, DerefCell, Key, Rect, Rgb}; use widgets::SelectedKeys; const SCALE: f64 = 64.; const MARGIN: f64 = 2.; const RADIUS: f64 = 4.; const HALF_KEYBOARD_VSPACING: f64 = 16.; #[derive(Default)] pub struct KeyboardLayerInner { page: Cell, board: DerefCell, selected: RefCell, selectable: Cell, wide_width: OnceCell, wide_height: OnceCell, narrow_width: OnceCell, testing_colors: RefCell, } #[glib::object_subclass] impl ObjectSubclass for KeyboardLayerInner { const NAME: &'static str = "S76KeyboardLayer"; type ParentType = gtk::DrawingArea; type Type = KeyboardLayer; } impl ObjectImpl for KeyboardLayerInner { fn constructed(&self) { self.parent_constructed(); self.obj().add_events(gdk::EventMask::BUTTON_PRESS_MASK); } fn properties() -> &'static [glib::ParamSpec] { use once_cell::sync::Lazy; static PROPERTIES: Lazy> = Lazy::new(|| { vec![ glib::ParamSpecBoxed::builder::("selected").build(), glib::ParamSpecBoxed::builder::("testing-colors").build(), ] }); PROPERTIES.as_ref() } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "selected" => self .obj() .set_selected(value.get::<&SelectedKeys>().unwrap().clone()), "testing-colors" => { self.testing_colors .replace(value.get::<&TestingColors>().unwrap().clone()); self.obj().queue_draw(); } _ => unimplemented!(), } } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "selected" => self.selected.borrow().to_value(), "testing-colors" => self.testing_colors.borrow().to_value(), _ => unimplemented!(), } } } impl WidgetImpl for KeyboardLayerInner { fn draw(&self, cr: &cairo::Context) -> Propagation { self.parent_draw(cr); let selected = Rgb::new(0xfb, 0xb8, 0x6c).to_floats(); let testing_colors = self.testing_colors.borrow(); for (i, k) in self.obj().keys().iter().enumerate() { let Rect { x, y, w, h } = self.obj().key_position(k); let mut bg = if let Some(rgb) = testing_colors .0 .get(&(k.electrical.0 as usize, k.electrical.1 as usize)) { rgb } else { &k.background_color } .to_floats(); if k.pressed() { bg = self.board.layout().meta.pressed_color.to_floats(); } let fg = if (bg.0 + bg.1 + bg.2) / 3. >= 0.5 { (0., 0., 0.) } else { (1., 1., 1.) }; let mut text_alpha = 1.; let mut bg_alpha = 1.; if let Some(layer) = self.page.get().layer() { let scancode_name = k.get_scancode(layer).unwrap().1; if scancode_name == "NONE" || scancode_name == "ROLL_OVER" { text_alpha = 0.5; bg_alpha = 0.75; } } // Rounded rectangle cr.new_sub_path(); cr.arc(x + w - RADIUS, y + RADIUS, RADIUS, -0.5 * PI, 0.); cr.arc(x + w - RADIUS, y + h - RADIUS, RADIUS, 0., 0.5 * PI); cr.arc(x + RADIUS, y + h - RADIUS, RADIUS, 0.5 * PI, PI); cr.arc(x + RADIUS, y + RADIUS, RADIUS, PI, 1.5 * PI); cr.close_path(); cr.set_source_rgba(bg.0, bg.1, bg.2, bg_alpha); cr.fill_preserve().unwrap(); if self.selectable.get() && self.obj().selected().contains(&i) { cr.set_source_rgb(selected.0, selected.1, selected.2); cr.set_line_width(4.); cr.stroke().unwrap(); } // Draw label let text = self.obj().page().get_label(k); let layout = cascade! { self.obj().create_pango_layout(Some(&text)); ..set_width((w * pango::SCALE as f64) as i32); ..set_alignment(pango::Alignment::Center); }; let text_height = layout.pixel_size().1 as f64; cr.new_path(); cr.move_to(x, y + (h - text_height) / 2.); cr.set_source_rgba(fg.0, fg.1, fg.2, text_alpha); pangocairo::show_layout(cr, &layout); } Propagation::Proceed } fn button_press_event(&self, evt: &gdk::EventButton) -> Propagation { self.parent_button_press_event(evt); if !self.selectable.get() { return Propagation::Proceed; } let pos = evt.position(); let pressed = self .obj() .keys() .iter() .position(|k| self.obj().key_position(k).contains(pos.0, pos.1)); if let Some(pressed) = pressed { let shift = evt.state().contains(gdk::ModifierType::SHIFT_MASK); let mut selected = self.obj().selected(); if shift { if selected.contains(&pressed) { selected.remove(&pressed); } else { selected.insert(pressed); } } else if selected.contains(&pressed) { selected.clear(); } else { selected.clear(); selected.insert(pressed); } self.obj().set_selected(selected); } Propagation::Proceed } fn request_mode(&self) -> gtk::SizeRequestMode { gtk::SizeRequestMode::HeightForWidth } fn preferred_width(&self) -> (i32, i32) { (self.obj().narrow_width(), self.obj().wide_width()) } fn preferred_height(&self) -> (i32, i32) { let height = self.obj().narrow_height(); (height, height) } fn preferred_height_for_width(&self, width: i32) -> (i32, i32) { let height = if width < self.obj().wide_width() { self.obj().narrow_height() } else { self.obj().wide_height() }; (height, height) } fn preferred_width_for_height(&self, _width: i32) -> (i32, i32) { self.preferred_width() } } impl DrawingAreaImpl for KeyboardLayerInner {} glib::wrapper! { pub struct KeyboardLayer(ObjectSubclass) @extends gtk::DrawingArea, gtk::Widget; } impl KeyboardLayer { pub fn new(page: Page, board: Board) -> Self { let obj = glib::Object::new::(); obj.inner().page.set(page); obj.inner().board.set(board); obj } fn inner(&self) -> &KeyboardLayerInner { KeyboardLayerInner::from_obj(self) } pub fn page(&self) -> Page { self.inner().page.get() } pub fn set_page(&self, page: Page) { self.inner().page.set(page); self.queue_draw(); } pub fn keys(&self) -> &[Key] { self.inner().board.keys() } pub fn selected(&self) -> SelectedKeys { self.inner().selected.borrow().clone() } pub fn set_selected(&self, i: SelectedKeys) { self.inner().selected.replace(i); self.queue_draw(); self.notify("selected"); } pub fn set_selectable(&self, selectable: bool) { self.inner().selectable.set(selectable); self.queue_draw(); } fn keys_maximize i32>(&self, cell: &OnceCell, cb: F) -> i32 { *cell.get_or_init(|| self.keys().iter().map(cb).max().unwrap()) } fn wide_width(&self) -> i32 { self.keys_maximize(&self.inner().wide_width, |k| { let pos = self.key_position_wide(k); (pos.x + pos.w) as i32 }) } fn wide_height(&self) -> i32 { self.keys_maximize(&self.inner().wide_height, |k| { let pos = self.key_position_wide(k); (pos.y + pos.h + 4.) as i32 }) } fn narrow_width(&self) -> i32 { self.keys_maximize(&self.inner().narrow_width, |k| { let mut pos = self.key_position_wide(k); let width = self.wide_width() as f64 / 2.; if pos.x + pos.w / 2. > width { pos.x -= width; } (pos.x + pos.w) as i32 }) } fn narrow_height(&self) -> i32 { self.wide_height() * 2 + HALF_KEYBOARD_VSPACING as i32 } fn key_position_wide(&self, k: &Key) -> Rect { Rect { x: (k.physical.x * SCALE) + MARGIN, y: -(k.physical.y * SCALE) + MARGIN, w: (k.physical.w * SCALE) - MARGIN * 2., h: (k.physical.h * SCALE) - MARGIN * 2., } } fn key_position_narrow(&self, k: &Key) -> Rect { let mut rect = self.key_position_wide(k); let width = self.wide_width() as f64 / 2.; if rect.x + rect.w / 2. > width { rect.x -= (self.wide_width() - self.narrow_width()) as f64; rect.y += self.wide_height() as f64 + HALF_KEYBOARD_VSPACING; } rect } fn key_position(&self, k: &Key) -> Rect { let (mut pos, width) = if self.allocated_width() < self.wide_width() { (self.key_position_narrow(k), self.narrow_width()) } else { (self.key_position_wide(k), self.wide_width()) }; pos.x += (self.allocated_width() - width) as f64 / 2.; pos } } ================================================ FILE: src/localize.rs ================================================ use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DefaultLocalizer, LanguageLoader, Localizer, }; use once_cell::sync::Lazy; use rust_embed::RustEmbed; #[derive(RustEmbed)] #[folder = "i18n/"] struct Localizations; pub static LANGUAGE_LOADER: Lazy = Lazy::new(|| { let loader: FluentLanguageLoader = fluent_language_loader!(); loader .load_fallback_language(&Localizations) .expect("Error while loading fallback language"); loader }); #[macro_export] macro_rules! fl { ($message_id:literal) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id) }}; ($message_id:literal, $($args:expr),*) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *) }}; } // Get the `Localizer` to be used for localizing this library. pub fn localizer() -> Box { Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) } ================================================ FILE: src/main.rs ================================================ #![windows_subsystem = "windows"] #[macro_use] extern crate log; use i18n_embed::DesktopLanguageRequester; use std::env; mod about_dialog; mod backlight; mod configurator_app; mod error_dialog; mod keyboard; mod keyboard_layer; mod localize; mod main_window; mod page; mod picker; mod shortcuts_window; mod testing; use gtk::glib; pub use self::configurator_app::run; use self::{ backlight::*, configurator_app::*, error_dialog::*, keyboard::*, keyboard_layer::*, main_window::*, page::*, picker::*, shortcuts_window::*, testing::*, }; fn main() -> glib::ExitCode { translate(); env_logger::Builder::from_env( env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), ) .format_timestamp(None) .format_module_path(false) .init(); let args = env::args().collect::>(); for arg in args.iter().skip(1) { if arg.as_str() == "--daemon" { backend::run_daemon(); } } crate::run() } fn translate() { let requested_languages = DesktopLanguageRequester::requested_languages(); let localizers = vec![ ("keyboard-configurator", crate::localize::localizer()), ("backend", backend::localizer()), ("widgets", widgets::localizer()), ]; for (crate_name, localizer) in localizers { if let Err(error) = localizer.select(&requested_languages) { eprintln!("Error while loading languages for {} {}", crate_name, error); } } } ================================================ FILE: src/main_window.rs ================================================ use crate::fl; use cascade::cascade; use futures::StreamExt; use gtk::{ gio, glib::{self, clone, ControlFlow}, pango, prelude::*, subclass::prelude::*, }; use std::{ cell::RefCell, sync::atomic::{AtomicBool, Ordering}, time::Duration, }; use crate::{shortcuts_window, ConfiguratorApp, Keyboard, KeyboardLayer, Page, Picker}; use backend::{Backend, Board, BoardId, Bootloaded, DerefCell}; pub struct Loader(MainWindow, gtk::Box); pub static REFRESH_DISABLED: AtomicBool = AtomicBool::new(false); impl Drop for Loader { fn drop(&mut self) { self.0.inner().load_box.remove(&self.1); let mut empty = true; self.0.inner().load_box.foreach(|_| empty = true); if empty { self.0.inner().load_revealer.set_reveal_child(false); } } } #[derive(Default)] pub struct MainWindowInner { backend: DerefCell, back_button: DerefCell, flash_menu: DerefCell, flash_button: DerefCell, header_bar: DerefCell, keyboard_box: DerefCell, layer_switcher: DerefCell, load_box: DerefCell, load_revealer: DerefCell, picker: DerefCell, stack: DerefCell, keyboards: RefCell>, board_loading: RefCell>, board_list_stack: DerefCell, is_testing_mode: DerefCell, } #[glib::object_subclass] impl ObjectSubclass for MainWindowInner { const NAME: &'static str = "S76ConfiguratorMainWindow"; type ParentType = gtk::ApplicationWindow; type Type = MainWindow; } impl ObjectImpl for MainWindowInner { fn constructed(&self) { self.parent_constructed(); let window = self.obj(); let back_button = cascade! { gtk::Button::new(); ..add(>k::Image::from_icon_name(Some("go-previous-symbolic"), gtk::IconSize::Button)); ..connect_clicked(clone!(@weak window => move |_| { window.show_keyboard_list(); })); }; let layer_switcher = cascade! { gtk::StackSwitcher::new(); ..show(); }; let flash_menu = cascade! { gio::Menu::new(); ..append_section(None, &cascade! { gio::Menu::new(); }); }; let flash_button = cascade! { gtk::MenuButton::new(); ..set_menu_model(Some(&flash_menu)); ..add(&cascade! { gtk::Image::from_icon_name(Some("applications-system-symbolic"), gtk::IconSize::Button); }); }; let menu = cascade! { gio::Menu::new(); ..append_section(None, &cascade! { gio::Menu::new(); ..append(Some(&fl!("layout-import")), Some("kbd.import")); ..append(Some(&fl!("layout-export")), Some("kbd.export")); ..append(Some(&fl!("layout-reset")), Some("kbd.reset")); ..append(Some(&fl!("layout-invert-f-keys")), Some("kbd.invert-f-keys")); }); ..append_section(None, &cascade! { gio::Menu::new(); ..append(Some(&fl!("show-help-overlay")), Some("win.show-help-overlay")); ..append(Some(&fl!("app-about")), Some("app.about")); }); }; let header_bar = cascade! { gtk::HeaderBar::new(); ..set_title(Some(&fl!("app-title"))); ..set_show_close_button(true); ..pack_start(&back_button); ..pack_end(&cascade! { gtk::MenuButton::new(); ..set_menu_model(Some(&menu)); ..add(&cascade! { gtk::Image::from_icon_name(Some("open-menu-symbolic"), gtk::IconSize::Button); }); }); ..pack_end(&flash_button); }; let no_boards_msg = format!( "{}\n\n{}", fl!("no-boards"), fl!("no-boards-msg") ); let no_boards = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 24); ..set_vexpand(true); ..set_valign(gtk::Align::Center); ..set_margin(12); ..add(&cascade! { gtk::Image::from_icon_name(Some("launch-keyboard-not-found"), gtk::IconSize::Invalid); ..set_pixel_size(384); ..set_halign(gtk::Align::Center); }); ..add(&cascade! { gtk::Label::new(Some(&no_boards_msg)); ..set_justify(gtk::Justification::Center); ..set_use_markup(true); }); }; let board_list_stack = cascade! { gtk::Stack::new(); ..set_homogeneous(false); ..add_named(&no_boards, "no_boards"); }; let keyboard_box = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 0); ..set_halign(gtk::Align::Center); }; board_list_stack.add_named(&keyboard_box, "keyboards"); let stack = cascade! { gtk::Stack::new(); ..set_margin(6); ..set_homogeneous(false); ..add(&board_list_stack); }; let picker = Picker::new(); let load_box = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 6); ..set_margin(6); ..show(); }; let load_revealer = cascade! { gtk::Revealer::new(); ..set_valign(gtk::Align::Start); ..set_vexpand(false); ..set_transition_type(gtk::RevealerTransitionType::SlideDown); ..add(&load_box); }; cascade! { window; ..set_title(&fl!("app-title")); ..set_position(gtk::WindowPosition::Center); ..set_default_size(1280, 768); ..set_titlebar(Some(&header_bar)); ..add(&cascade! { gtk::Overlay::new(); ..add_overlay(&load_revealer); ..add(&cascade! { gtk::ScrolledWindow::new(None::<>k::Adjustment>, None::<>k::Adjustment>); ..set_hscrollbar_policy(gtk::PolicyType::Never); ..set_overlay_scrolling(false); ..add(&stack); }); }); ..set_help_overlay(Some(&shortcuts_window())); ..set_focus(None::<>k::Widget>); ..show_all(); }; back_button.set_visible(false); flash_button.set_visible(false); self.back_button.set(back_button); self.flash_button.set(flash_button); self.flash_menu.set(flash_menu); self.header_bar.set(header_bar); self.keyboard_box.set(keyboard_box); self.layer_switcher.set(layer_switcher); self.load_box.set(load_box); self.load_revealer.set(load_revealer); self.picker.set(picker); self.stack.set(stack); self.board_list_stack.set(board_list_stack); } } impl WidgetImpl for MainWindowInner { fn destroy(&self) { self.parent_destroy(); info!("Window close"); } } impl ContainerImpl for MainWindowInner {} impl BinImpl for MainWindowInner {} impl WindowImpl for MainWindowInner {} impl ApplicationWindowImpl for MainWindowInner {} glib::wrapper! { pub struct MainWindow(ObjectSubclass) @extends gtk::ApplicationWindow, gtk::Window, gtk::Bin, gtk::Container, gtk::Widget, @implements gio::ActionGroup, gio::ActionMap; } impl MainWindow { pub fn new(app: &ConfiguratorApp) -> Self { let window: Self = glib::Object::new(); let is_testing_mode = app.launch_test(); app.add_window(&window); let (backend, receiver) = daemon(); window.handle_backend_event_stream(receiver, false); backend.refresh(); // Refresh key matrix only when window is visible backend.set_matrix_get_rate(if window.is_active() { Some(Duration::from_millis(50)) } else { None }); window.connect_is_active_notify(|window| { window .inner() .backend .set_matrix_get_rate(if window.is_active() { Some(Duration::from_millis(50)) } else { None }); }); let phony_board_names = app.phony_board_names().to_vec(); if !phony_board_names.is_empty() { match Backend::new_dummy(phony_board_names) { Ok((backend, receiver)) => { window.handle_backend_event_stream(receiver, true); backend.refresh(); } Err(err) => error!("{}", err), } } window.inner().backend.set(backend); window.inner().is_testing_mode.set(is_testing_mode); glib::timeout_add_seconds_local( 1, clone!(@weak window => @default-return ControlFlow::Break, move || { if !REFRESH_DISABLED.load(Ordering::Relaxed) { let inner = window.inner(); inner.backend.refresh(); if *inner.is_testing_mode && !inner.back_button.is_visible() { inner.backend.check_for_bootloader() } } ControlFlow::Continue }), ); window } fn inner(&self) -> &MainWindowInner { MainWindowInner::from_obj(self) } fn handle_backend_event_stream(&self, mut receiver: backend::Events, is_dummy: bool) { let window_weak = self.downgrade(); glib::MainContext::default().spawn_local(async move { while let (Some(event), Some(window)) = (receiver.next().await, window_weak.upgrade()) { window.handle_backend_event(event, is_dummy); } }); } fn handle_backend_event(&self, event: backend::Event, is_dummy: bool) { match event { // Ignore these events for dummy; only use for real keyboard backend::Event::BoardLoading | backend::Event::BoardLoadingDone | backend::Event::BoardNotUpdated if is_dummy => {} backend::Event::BoardLoading => { info!("loading"); let loader = self.display_loader(&fl!("loading")); *self.inner().board_loading.borrow_mut() = Some(loader); } backend::Event::BoardLoadingDone => { self.inner().board_loading.borrow_mut().take(); } backend::Event::BoardNotUpdated => { info!("board not updated"); self.inner().board_loading.borrow_mut().take(); let loader = self.display_loader(&fl!("firmware-update-required")); *self.inner().board_loading.borrow_mut() = Some(loader); } backend::Event::BoardAdded(board) => { self.add_keyboard(board); } backend::Event::Board(id, event) => { if let backend::BoardEvent::MatrixChanged = &event { self.inner().keyboard_box.queue_draw(); } for (keyboard, _) in &*self.inner().keyboards.borrow() { if keyboard.board().board() == id { keyboard.handle_backend_event(event); break; } } } backend::Event::BoardRemoved(id) => { self.remove_keyboard(id); } backend::Event::BootloadedAdded(board) => { self.add_flash_menu(board); } backend::Event::BootloadedRemoved => { self.remove_flash_menu(); } } } fn show_keyboard_list(&self) { let inner = self.inner(); inner .stack .set_transition_type(gtk::StackTransitionType::SlideRight); inner.stack.set_visible_child(&*inner.board_list_stack); inner.header_bar.set_custom_title(None::<>k::Widget>); inner.layer_switcher.set_stack(None::<>k::Stack>); self.insert_action_group("kbd", None::<&gio::ActionGroup>); inner.back_button.set_visible(false); inner.picker.set_keyboard(None); } fn show_keyboard(&self, keyboard: &Keyboard) { let inner = self.inner(); inner .stack .set_transition_type(gtk::StackTransitionType::SlideLeft); inner.stack.set_visible_child(keyboard); inner .header_bar .set_custom_title(Some(&*inner.layer_switcher)); inner.layer_switcher.set_stack(Some(keyboard.layer_stack())); self.insert_action_group("kbd", Some(keyboard.action_group())); inner.back_button.set_visible(true); inner.picker.set_keyboard(Some(keyboard.clone())); } fn add_keyboard(&self, board: Board) { let app: ConfiguratorApp = self.application().unwrap().downcast().unwrap(); let keyboard = cascade! { Keyboard::new(board.clone(), app.debug_layers(), app.launch_test()); ..set_halign(gtk::Align::Center); ..show_all(); }; let attr_list = cascade! { pango::AttrList::new(); ..insert(pango::AttrInt::new_weight(pango::Weight::Bold)); }; let label = cascade! { gtk::Label::new(Some(&keyboard.display_name())); ..set_attributes(Some(&attr_list)); }; let window = self; let button = if !board.is_updated() && *self.inner().is_testing_mode { cascade! { gtk::Button::with_label(&fl!("firmware-update-required")); ..set_halign(gtk::Align::Center); } } else { cascade! { gtk::Button::with_label(&fl!("button-configure")); ..set_halign(gtk::Align::Center); ..connect_clicked(clone!(@weak window, @weak keyboard => move |_| { window.show_keyboard(&keyboard); })); } }; let keyboard_layer = cascade! { KeyboardLayer::new(Page::Layer1, keyboard.board().clone()); ..set_halign(gtk::Align::Center); }; let row = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..set_margin(12); ..add(&label); ..add(&keyboard_layer); ..add(&button); ..show_all(); }; self.inner().keyboard_box.add(&row); if !board.has_keymap() { button.hide(); let label = cascade! { gtk::Label::new(Some(&fl!("firmware-version", version = board.version()))); ..set_attributes(Some(&cascade! { pango::AttrList::new(); ..insert(pango::AttrColor::new_foreground(65535, 0, 0)); })); ..show(); }; row.add(&label); } self.inner().stack.add(&keyboard); self.inner().keyboards.borrow_mut().push((keyboard, row)); self.inner() .board_list_stack .set_visible_child_name("keyboards"); } fn remove_keyboard(&self, id: BoardId) { let mut boards = self.inner().keyboards.borrow_mut(); if let Some(idx) = boards.iter().position(|(kb, _)| kb.board().board() == id) { let (keyboard, row) = boards.remove(idx); if self.inner().stack.visible_child().as_ref() == Some(keyboard.upcast_ref()) { // Set picker keyboard to to `None` before destroying keyboard widget self.inner().picker.set_keyboard(None); self.show_keyboard_list(); } self.inner().stack.remove(&keyboard); self.inner().keyboard_box.remove(&row); if self.num_keyboards() == 0 { self.inner() .board_list_stack .set_visible_child_name("no_boards"); } } } fn add_flash_menu(&self, board: Bootloaded) { let menu = &self.inner().flash_menu; menu.remove_all(); match board { Bootloaded::At90usb646 => { menu.append( Some(&fl!("flash-to-launch-2")), Some("app.flash-to-launch-2"), ); menu.append( Some(&fl!("flash-to-launch-heavy")), Some("app.flash-to-launch-heavy-1"), ); } Bootloaded::At90usb646Lite => { menu.append( Some(&fl!("flash-to-launch-lite-1")), Some("app.flash-to-launch-lite-1"), ); } Bootloaded::AtMega32u4 => { menu.append( Some(&fl!("flash-to-launch-1")), Some("app.flash-to-launch-1"), ); } } self.inner().flash_button.set_visible(true); } fn remove_flash_menu(&self) { self.inner().flash_button.set_visible(false); } fn num_keyboards(&self) -> usize { let mut count = 0; self.inner().keyboard_box.foreach(|_| count += 1); count } pub fn display_loader(&self, text: &str) -> Loader { info!("display loader called with {}", text); let load_hbox = cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 6); ..add(&cascade! { gtk::Spinner::new(); ..start(); }); ..add(>k::Label::new(Some(text))); ..show_all(); }; self.inner().load_box.add(&load_hbox); self.inner().load_revealer.set_reveal_child(true); Loader(self.clone(), load_hbox) } } #[cfg(target_os = "linux")] fn daemon() -> (Backend, backend::Events) { if unsafe { libc::geteuid() == 0 } { info!("Already running as root"); Backend::new() } else { info!("Not running as root, spawning daemon with pkexec"); Backend::new_pkexec() } .expect("Failed to create server") } #[cfg(not(target_os = "linux"))] fn daemon() -> (Backend, backend::Events) { Backend::new().expect("Failed to create server") } ================================================ FILE: src/page.rs ================================================ use crate::fl; use crate::picker::SCANCODE_LABELS; use backend::Key; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Page { Layer1, Layer2, Layer3, Layer4, Keycaps, Logical, Electrical, Leds, } impl Page { pub fn name(&self) -> String { match self { Self::Layer1 => fl!("page-layer1"), Self::Layer2 => fl!("page-layer2"), Self::Layer3 => fl!("page-layer3"), Self::Layer4 => fl!("page-layer4"), Self::Keycaps => fl!("page-keycaps"), Self::Logical => fl!("page-logical"), Self::Electrical => fl!("page-electrical"), Self::Leds => fl!("page-leds"), } } pub fn layer(&self) -> Option { match self { Self::Layer1 => Some(0), Self::Layer2 => Some(1), Self::Layer3 => Some(2), Self::Layer4 => Some(3), _ => None, } } pub fn is_debug(&self) -> bool { matches!( self, Self::Keycaps | Self::Logical | Self::Electrical | Self::Leds ) } pub fn iter_all() -> impl Iterator { vec![ Self::Layer1, Self::Layer2, Self::Layer3, Self::Layer4, Self::Keycaps, Self::Logical, Self::Electrical, Self::Leds, ] .into_iter() } pub fn get_label(&self, key: &Key) -> String { match self { Page::Layer1 | Page::Layer2 | Page::Layer3 | Page::Layer4 => { let scancode_name = key.get_scancode(self.layer().unwrap()).unwrap().1; SCANCODE_LABELS .get(&scancode_name) .unwrap_or(&scancode_name) .into() } Page::Keycaps => key.physical_name.clone(), Page::Logical => key.logical_name.clone(), Page::Electrical => key.electrical_name.clone(), Page::Leds => key.led_name.clone(), } } } impl Default for Page { fn default() -> Self { Self::Layer1 } } ================================================ FILE: src/picker/mod.rs ================================================ use cascade::cascade; use futures::{prelude::*, stream::FuturesUnordered}; use gtk::{ glib::{self, clone}, prelude::*, subclass::prelude::*, }; use once_cell::sync::Lazy; use std::{cell::RefCell, collections::HashMap}; use crate::Keyboard; use backend::DerefCell; mod picker_group; mod picker_group_box; mod picker_json; mod picker_key; use picker_group_box::PickerGroupBox; use picker_json::picker_json; use picker_key::PickerKey; pub static SCANCODE_LABELS: Lazy> = Lazy::new(|| { let mut labels = HashMap::new(); for group in picker_json() { for key in group.keys { labels.insert(key.keysym, key.label); } } labels }); #[derive(Default)] pub struct PickerInner { group_box: DerefCell, keyboard: RefCell>>, } #[glib::object_subclass] impl ObjectSubclass for PickerInner { const NAME: &'static str = "S76KeyboardPicker"; type ParentType = gtk::Box; type Type = Picker; } impl ObjectImpl for PickerInner { fn constructed(&self) { self.parent_constructed(); let picker = self.obj(); let group_box = cascade! { PickerGroupBox::new(); ..connect_key_pressed(clone!(@weak picker => move |name| { picker.key_pressed(name) })); }; cascade! { picker; ..add(&group_box); ..show_all(); }; self.group_box.set(group_box); } } impl BoxImpl for PickerInner {} impl WidgetImpl for PickerInner {} impl ContainerImpl for PickerInner {} glib::wrapper! { pub struct Picker(ObjectSubclass) @extends gtk::Box, gtk::Container, gtk::Widget, @implements gtk::Orientable; } impl Picker { pub fn new() -> Self { glib::Object::new() } fn inner(&self) -> &PickerInner { PickerInner::from_obj(self) } fn keyboard(&self) -> Option { self.inner() .keyboard .borrow() .as_ref() .and_then(|x| x.upgrade()) } pub(crate) fn set_keyboard(&self, keyboard: Option) { if let Some(old_kb) = self.keyboard() { old_kb.set_picker(None); } if let Some(widget) = self.parent() { widget.downcast::().unwrap().remove(self); } if let Some(kb) = &keyboard { // Check that scancode is available for the keyboard self.inner() .group_box .set_key_visibility(|name| kb.has_scancode(name)); kb.set_picker(Some(self)); } *self.inner().keyboard.borrow_mut() = keyboard.map(|x| x.downgrade()); } pub(crate) fn set_selected(&self, scancode_names: Vec) { self.inner().group_box.set_selected(scancode_names); } fn key_pressed(&self, name: String) { let kb = match self.keyboard() { Some(kb) => kb, None => { return; } }; let layer = kb.layer(); if let Some(layer) = layer { let futures = FuturesUnordered::new(); for i in kb.selected().iter() { let i = *i; futures.push(clone!(@strong kb, @strong name => async move { kb.keymap_set(i, layer, &name).await; })); } glib::MainContext::default().spawn_local(async { futures.collect::<()>().await }); } } } impl Default for Picker { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use crate::*; use backend::{layouts, Layout}; use std::collections::HashSet; #[test] fn picker_has_keys() { let mut missing = HashSet::new(); for i in layouts() { let layout = Layout::from_board(i, "dummy").unwrap(); for j in layout.default.map.values().flatten() { if !SCANCODE_LABELS.keys().any(|x| x == j) { missing.insert(j.to_owned()); } } } assert_eq!(missing, HashSet::new()); } } ================================================ FILE: src/picker/picker_group.rs ================================================ use cascade::cascade; use gtk::{pango, prelude::*}; use std::rc::Rc; use super::PickerKey; pub(super) struct PickerGroup { /// Name of keys in this group keys: Vec>, pub vbox: gtk::Box, flow_box: gtk::FlowBox, } impl PickerGroup { pub fn new(name: String, cols: u32) -> Self { let label = cascade! { gtk::Label::new(Some(&name)); ..set_attributes(Some(&cascade! { pango::AttrList::new(); ..insert(pango::AttrInt::new_weight(pango::Weight::Bold)); } )); ..set_halign(gtk::Align::Start); ..set_margin_bottom(8); }; let flow_box = cascade! { gtk::FlowBox::new(); ..set_column_spacing(4); ..set_row_spacing(4); ..set_max_children_per_line(cols); ..set_min_children_per_line(cols); ..set_filter_func(Some(Box::new(|child: >k::FlowBoxChild| child.child().unwrap().is_visible()))); }; let vbox = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 4); ..add(&label); ..add(&flow_box); }; Self { keys: Vec::new(), vbox, flow_box, } } pub fn add_key(&mut self, key: Rc) { self.flow_box.add(&key.gtk); self.keys.push(key); } pub fn iter_keys(&self) -> impl Iterator { self.keys.iter().map(|k| k.as_ref()) } pub fn invalidate_filter(&self) { self.flow_box.invalidate_filter(); } } ================================================ FILE: src/picker/picker_group_box.rs ================================================ use cascade::cascade; use gtk::{ gdk, glib::{self, clone, subclass::Signal, SignalHandlerId}, prelude::*, subclass::prelude::*, }; use once_cell::sync::Lazy; use std::{cell::RefCell, collections::HashMap, rc::Rc}; use backend::DerefCell; use super::{picker_group::PickerGroup, picker_json::picker_json, picker_key::PickerKey}; const DEFAULT_COLS: usize = 3; const HSPACING: i32 = 64; const VSPACING: i32 = 32; const PICKER_CSS: &str = r#" button { margin: 0; padding: 0; } .selected { border-color: #fbb86c; border-width: 4px; } "#; #[derive(Default)] pub struct PickerGroupBoxInner { groups: DerefCell>, keys: DerefCell>>, selected: RefCell>, } #[glib::object_subclass] impl ObjectSubclass for PickerGroupBoxInner { const NAME: &'static str = "S76KeyboardPickerGroupBox"; type ParentType = gtk::Container; type Type = PickerGroupBox; } impl ObjectImpl for PickerGroupBoxInner { fn constructed(&self) { self.parent_constructed(); let style_provider = cascade! { gtk::CssProvider::new(); ..load_from_data(PICKER_CSS.as_bytes()).expect("Failed to parse css"); }; let mut groups = Vec::new(); let mut keys = HashMap::new(); for json_group in picker_json() { let mut group = PickerGroup::new(json_group.label, json_group.cols); for json_key in json_group.keys { let key = PickerKey::new( json_key.keysym.clone(), json_key.label, json_group.width, &style_provider, ); group.add_key(key.clone()); keys.insert(json_key.keysym, key); } groups.push(group); } for group in &groups { group.vbox.show(); group.vbox.set_parent(&*self.obj()); } self.keys.set(keys); self.groups.set(groups); cascade! { self.obj(); ..connect_signals(); ..show_all(); }; } fn signals() -> &'static [Signal] { static SIGNALS: Lazy> = Lazy::new(|| { vec![Signal::builder("key-pressed") .param_types([String::static_type()]) .build()] }); SIGNALS.as_ref() } } impl WidgetImpl for PickerGroupBoxInner { fn request_mode(&self) -> gtk::SizeRequestMode { gtk::SizeRequestMode::HeightForWidth } fn preferred_width(&self) -> (i32, i32) { let minimum_width = self .groups .iter() .map(|x| x.vbox.preferred_width().1) .max() .unwrap(); let natural_width = self .groups .chunks(3) .map(|row| row.iter().map(|x| x.vbox.preferred_width().1).sum::()) .max() .unwrap() + 2 * HSPACING; (minimum_width, natural_width) } fn preferred_height_for_width(&self, width: i32) -> (i32, i32) { let obj = self.obj(); let rows = obj.rows_for_width(width); let height = rows .iter() .map(|row| { row.iter() .map(|x| x.vbox.preferred_height().1) .max() .unwrap() }) .sum::() + (rows.len() as i32 - 1) * VSPACING; (height, height) } fn size_allocate(&self, allocation: >k::Allocation) { self.parent_size_allocate(allocation); let obj = self.obj(); let rows = obj.rows_for_width(allocation.width()); let total_width = rows .iter() .map(|row| { row.iter().map(|x| x.vbox.preferred_width().1).sum::() + (row.len() as i32 - 1) * HSPACING }) .max() .unwrap(); let mut y = 0; for row in rows { let mut x = (allocation.width() - total_width) / 2; for group in row { let height = group.vbox.preferred_height().1; let width = group.vbox.preferred_width().1; group .vbox .size_allocate(>k::Allocation::new(x, y, width, height)); x += width + HSPACING; } y += row .iter() .map(|x| x.vbox.preferred_height().1) .max() .unwrap() + VSPACING; } } fn realize(&self) { let widget = self.obj(); let allocation = widget.allocation(); widget.set_realized(true); let attrs = gdk::WindowAttr { x: Some(allocation.x()), y: Some(allocation.y()), width: allocation.width(), height: allocation.height(), window_type: gdk::WindowType::Child, event_mask: widget.events(), wclass: gdk::WindowWindowClass::InputOutput, ..Default::default() }; let window = gdk::Window::new(widget.parent_window().as_ref(), &attrs); widget.register_window(&window); widget.set_window(window); } } impl ContainerImpl for PickerGroupBoxInner { fn forall(&self, _include_internals: bool, cb: >k::subclass::container::Callback) { for group in self.groups.iter() { cb.call(group.vbox.upcast_ref()); } } fn remove(&self, child: >k::Widget) { child.unparent(); } } glib::wrapper! { pub struct PickerGroupBox(ObjectSubclass) @extends gtk::Container, gtk::Widget, @implements gtk::Orientable; } impl PickerGroupBox { pub fn new() -> Self { glib::Object::new() } fn inner(&self) -> &PickerGroupBoxInner { PickerGroupBoxInner::from_obj(self) } fn connect_signals(&self) { let picker = self; for group in self.inner().groups.iter() { for key in group.iter_keys() { let button = &key.gtk; let name = key.name.to_string(); button.connect_clicked(clone!(@weak picker => @default-panic, move |_| { picker.emit_by_name::<()>("key-pressed", &[&name]); })); } } } pub fn connect_key_pressed(&self, cb: F) -> SignalHandlerId { self.connect_local("key-pressed", false, move |values| { cb(values[1].get::().unwrap()); None }) } fn get_button(&self, scancode_name: &str) -> Option<>k::Button> { self.inner().keys.get(scancode_name).map(|k| &k.gtk) } pub(crate) fn set_key_visibility bool>(&self, f: F) { for key in self.inner().keys.values() { key.gtk.set_visible(f(&key.name)); } for group in self.inner().groups.iter() { group.invalidate_filter(); } } pub(crate) fn set_selected(&self, scancode_names: Vec) { let mut selected = self.inner().selected.borrow_mut(); for i in selected.iter() { if let Some(button) = self.get_button(i) { button.style_context().remove_class("selected"); } } *selected = scancode_names; for i in selected.iter() { if let Some(button) = self.get_button(i) { button.style_context().add_class("selected"); } } } fn rows_for_width(&self, container_width: i32) -> Vec<&[PickerGroup]> { let mut rows = Vec::new(); let groups = &*self.inner().groups; let mut row_start = 0; let mut row_width = 0; for (i, group) in groups.iter().enumerate() { let width = group.vbox.preferred_width().1; row_width += width; if i != 0 { row_width += HSPACING; } if i - row_start >= DEFAULT_COLS || row_width > container_width { rows.push(&groups[row_start..i]); row_start = i; row_width = width; } } if !groups[row_start..].is_empty() { rows.push(&groups[row_start..]); } rows } } impl Default for PickerGroupBox { fn default() -> Self { Self::new() } } ================================================ FILE: src/picker/picker_json.rs ================================================ use serde::Deserialize; #[derive(Deserialize)] pub struct PickerJsonKey { pub keysym: String, pub label: String, } #[derive(Deserialize)] pub struct PickerJsonGroup { pub label: String, pub cols: u32, pub width: i32, pub keys: Vec, } pub fn picker_json() -> Vec { let picker_json = include_str!("../../layouts/picker.json"); serde_json::from_str(picker_json).unwrap() } #[cfg(test)] mod tests { use super::*; #[test] fn test_picker_json() { picker_json(); } } ================================================ FILE: src/picker/picker_key.rs ================================================ use cascade::cascade; use gtk::prelude::*; use std::rc::Rc; pub(super) struct PickerKey { /// Symbolic name of the key pub(super) name: String, // GTK button pub(super) gtk: gtk::Button, } impl PickerKey { pub(super) fn new>( name: String, text: String, width: i32, style_provider: &P, ) -> Rc { let label = cascade! { gtk::Label::new(Some(&text)); ..set_line_wrap(true); ..set_max_width_chars(1); ..set_margin_start(5); ..set_margin_end(5); ..set_justify(gtk::Justification::Center); }; let button = cascade! { gtk::Button::new(); ..set_size_request(48 * width, 48); ..style_context().add_provider(style_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); ..add(&label); }; Rc::new(Self { name, gtk: button }) } } ================================================ FILE: src/shortcuts_window.rs ================================================ use crate::fl; use gtk::prelude::*; pub fn shortcuts_window() -> gtk::ShortcutsWindow { // GtkShortcutWindow docs specifically say it should be used from // GtkBuilder, and lacks things like a new function. let xml = include_str!("shortcuts_window.ui"); let builder = gtk::Builder::from_string(xml); let import: gtk::ShortcutsShortcut = builder.object("import-layout").unwrap(); import.set_title(Some(&fl!("layout-import"))); let export: gtk::ShortcutsShortcut = builder.object("export-layout").unwrap(); export.set_title(Some(&fl!("layout-export"))); builder.object("shortcuts-window").unwrap() } ================================================ FILE: src/shortcuts_window.ui ================================================ 1 keyboard True keyboard True True kbd.import True kbd.export ================================================ FILE: src/testing.rs ================================================ use crate::{fl, Keyboard, REFRESH_DISABLED}; use backend::{Board, DerefCell, NelsonKind, Rgb}; use cascade::cascade; use futures::channel::oneshot; use gtk::{ glib::{self, clone, Propagation}, prelude::*, subclass::prelude::*, }; use once_cell::sync::{Lazy, OnceCell}; use std::{ cell::{Cell, RefCell}, collections::HashMap, sync::{atomic::Ordering, RwLock}, }; struct TestResults { bench: RwLock>>, } impl TestResults { fn global() -> &'static Self { static TEST_RESULTS: OnceCell = OnceCell::new(); TEST_RESULTS.get_or_init(Self::new) } fn new() -> Self { let test_results = Self { bench: RwLock::new(HashMap::new()), }; test_results.reset(); test_results } fn reset(&self) { let mut bench = self.bench.write().unwrap(); bench.clear(); for port_desc in &[ "USB 2.0: USB-A Left", "USB 2.0: USB-A Right", "USB 2.0: USB-C Left", "USB 2.0: USB-C Right", "USB 3.2 Gen 2: USB-A Left", "USB 3.2 Gen 2: USB-A Right", "USB 3.2 Gen 2: USB-C Left", "USB 3.2 Gen 2: USB-C Right", ] { bench.insert(*port_desc, Err("no benchmarks performed".to_string())); } } } #[derive(Clone, Default, glib::Boxed)] #[boxed_type(name = "S76TestingColor")] pub struct TestingColors(pub HashMap<(usize, usize), Rgb>); #[derive(Default)] pub struct TestingInner { board: DerefCell, keyboard: DerefCell>, reset_button: DerefCell, usb_test: DerefCell, bench_button: DerefCell, bench_labels: DerefCell>, num_runs_spin_2: DerefCell, test_buttons: DerefCell<[gtk::Button; 2]>, test_labels: DerefCell<[gtk::Label; 3]>, selma_start_button: DerefCell, selma_stop_button: DerefCell, selma_stop_sender: RefCell>>, selma_running: Cell, colors: RefCell, } #[glib::object_subclass] impl ObjectSubclass for TestingInner { const NAME: &'static str = "S76Testing"; type ParentType = gtk::Box; type Type = Testing; } impl ObjectImpl for TestingInner { fn constructed(&self) { fn row(widget: &impl IsA) -> gtk::ListBoxRow { cascade! { gtk::ListBoxRow::new(); ..set_selectable(false); ..set_activatable(false); ..set_margin(8); ..add(widget); } } fn label_row(label: &str, widget: &impl IsA) -> gtk::ListBoxRow { row(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 8); ..add(&cascade! { gtk::Label::new(Some(label)); ..set_halign(gtk::Align::Start); }); ..pack_end(widget, false, false, 0); }) } fn color_box(r: f64, g: f64, b: f64) -> gtk::DrawingArea { cascade! { gtk::DrawingArea::new(); ..set_size_request(18, 18); ..connect_draw(move |_w, cr| { cr.set_source_rgb(r, g, b); cr.paint().unwrap(); Propagation::Proceed }); } } fn header_func(row: >k::ListBoxRow, before: Option<>k::ListBoxRow>) { if before.is_none() { row.set_header(None::<>k::Widget>) } else if row.header().is_none() { row.set_header(Some(&cascade! { gtk::Separator::new(gtk::Orientation::Horizontal); ..show(); })); } } let reset_button = gtk::Button::with_label("Reset Testing"); self.obj().add(&cascade! { gtk::ListBox::new(); ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&row(&reset_button)); }); let bench_list = gtk::ListBox::new(); let mut bench_labels = HashMap::new(); for (port_desc, _port_result) in TestResults::global().bench.read().unwrap().iter() { let bench_label = gtk::Label::new(None); bench_list.add(&label_row(port_desc, &bench_label)); bench_labels.insert(*port_desc, bench_label); } let bench_button = gtk::ToggleButton::with_label("Run USB test"); let usb_test = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..add(>k::Label::new(Some("USB Port Test"))); ..add(&cascade! { bench_list; ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&row(&bench_button)); ..set_header_func(Some(Box::new(header_func))); }); }; let num_runs_spin_2 = gtk::SpinButton::with_range(1.0, 1000.0, 1.0); num_runs_spin_2.set_value(100.0); let test_buttons = [ gtk::Button::with_label(&fl!("button-test")), gtk::Button::with_label(&fl!("button-test")), ]; let test_labels = [ gtk::Label::new(None), gtk::Label::new(None), gtk::Label::new(None), ]; let nelson_test_1 = &cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..add(>k::Label::new(Some("Nelson Test 1"))); ..add(&cascade! { gtk::ListBox::new(); ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&row(&test_buttons[0])); ..add(&row(&test_labels[0])); ..add(&label_row("Check pins (missing)", &color_box(1., 0., 0.))); ..add(&label_row("Check key (sticking)", &color_box(0., 1., 0.))); ..set_header_func(Some(Box::new(header_func))); }); }; let nelson_test_2 = &cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..add(>k::Label::new(Some("Nelson Test 2"))); ..add(&cascade! { gtk::ListBox::new(); ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&label_row(&fl!("test-number-of-runs"), &num_runs_spin_2)); ..add(&row(&test_buttons[1])); ..add(&row(&test_labels[2])); ..add(&label_row(&fl!("test-check-pins"), &color_box(1., 0., 0.))); ..add(&label_row(&fl!("test-check-key"), &color_box(0., 1., 0.))); ..set_header_func(Some(Box::new(header_func))); }); }; let selma_start_button = gtk::Button::with_label(&fl!("button-start")); let selma_stop_button = cascade! { gtk::Button::with_label(&fl!("button-stop")); ..set_sensitive(false); }; let selma_test = &cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..add(>k::Label::new(Some("Selma Test"))); ..add(&cascade! { gtk::ListBox::new(); ..set_valign(gtk::Align::Start); ..style_context().add_class("frame"); ..add(&row(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 8); ..set_halign(gtk::Align::Center); ..add(&selma_start_button); ..add(&selma_stop_button); })); ..add(&label_row(&fl!("test-spurious-keypress"), &color_box(1., 0., 0.))); ..set_header_func(Some(Box::new(header_func))); }); }; self.obj().add(&cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 18); ..set_valign(gtk::Align::Start); ..add(&cascade! { gtk::Box::new(gtk::Orientation::Vertical, 18); ..set_valign(gtk::Align::Start); ..add(&row(&usb_test)); ..add(&row(selma_test)); }); ..add(&cascade! { gtk::Box::new(gtk::Orientation::Vertical, 18); ..set_valign(gtk::Align::Start); ..add(&row(nelson_test_1)); ..add(&row(nelson_test_2)); }); }); self.reset_button.set(reset_button); self.usb_test.set(usb_test); self.bench_button.set(bench_button); self.bench_labels.set(bench_labels); self.num_runs_spin_2.set(num_runs_spin_2); self.test_buttons.set(test_buttons); self.test_labels.set(test_labels); self.selma_start_button.set(selma_start_button); self.selma_stop_button.set(selma_stop_button); cascade! { self.obj(); ..set_orientation(gtk::Orientation::Vertical); ..set_spacing(18); ..show_all(); }; } fn properties() -> &'static [glib::ParamSpec] { static PROPERTIES: Lazy> = Lazy::new(|| { vec![glib::ParamSpecBoxed::builder::("colors") .read_only() .build()] }); PROPERTIES.as_ref() } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "colors" => self.colors.borrow().to_value(), _ => unimplemented!(), } } } impl WidgetImpl for TestingInner {} impl ContainerImpl for TestingInner {} impl BoxImpl for TestingInner {} glib::wrapper! { pub struct Testing(ObjectSubclass) @extends gtk::Box, gtk::Container, gtk::Widget, @implements gtk::Orientable; } impl Testing { fn update_benchmarks(&self) { for (port_desc, port_result) in TestResults::global().bench.read().unwrap().iter() { if let Some(bench_label) = self.inner().bench_labels.get(port_desc) { match port_result { Ok(ok) => { bench_label.set_text(&format!("{:.2} MB/s ✅", ok)); } Err(err) => { bench_label.set_text(&format!("{} ❌", err)); } } } else { error!("{} label not found", port_desc); } } } async fn bench(&self) { let testing = self.inner(); testing.bench_button.set_label("Running USB test"); while testing.bench_button.is_active() { match testing.board.benchmark().await { Ok(benchmark) => { for (port_desc, port_result) in benchmark.port_results.iter() { let text = format!("{:.2?}", port_result); info!("{}: {}", port_desc, text); if let Some(bench_result) = TestResults::global() .bench .write() .unwrap() .get_mut(port_desc.as_str()) { match bench_result { Ok(old) => match port_result { Ok(new) => { // Replace good results with better results if new > old { *bench_result = Ok(*new); } } Err(_) => (), }, Err(_err) => { // Replace errors with newest results *bench_result = port_result.clone(); } } } else { error!("{} label result not found", port_desc); } } } Err(err) => { let message = format!("Benchmark failed to run: {}", err); error!("{}", message); //TODO: have a global label? for (_, bench_label) in testing.bench_labels.iter() { bench_label.set_text(&message); } } } self.update_benchmarks(); glib::timeout_future(std::time::Duration::new(1, 0)).await; } testing.bench_button.set_label("Run USB test"); } fn connect_bench_button(&self) { self.inner() .bench_button .connect_clicked(clone!(@strong self as self_ => move |_| { glib::MainContext::default().spawn_local(clone!(@strong self_ => async move { self_.bench().await; })); })); } fn test_buttons_sensitive(&self, sensitive: bool) { for i in 0..2 { self.inner().test_buttons[i].set_sensitive(sensitive); } self.inner().selma_start_button.set_sensitive(sensitive); } async fn nelson(&self, test_runs: i32, test_index: usize, nelson_kind: NelsonKind) { let testing = self.inner(); info!("Disabling test buttons"); self.test_buttons_sensitive(false); let test_label = &testing.test_labels[test_index]; info!("Disable keyboard input events"); self.set_no_input(true).await; for test_run in 1..=test_runs { let message = format!("Test {}/{} running", test_run, test_runs); info!("{}", message); test_label.set_text(&message); let nelson = match testing.board.nelson(nelson_kind).await { Ok(ok) => ok, Err(err) => { let message = format!("Test {}/{} failed to run: {}", test_run, test_runs, err); error!("{}", message); test_label.set_text(&message); break; } }; for row in 0..nelson.max_rows() { for col in 0..nelson.max_cols() { let r = if nelson.missing.get(row, col).unwrap_or(false) { 255 } else { 0 }; let g = if nelson.sticking.get(row, col).unwrap_or(false) { 255 } else { 0 }; let b = if nelson.bouncing.get(row, col).unwrap_or(false) { 255 } else { 0 }; if r != 0 || g != 0 || b != 0 { testing .colors .borrow_mut() .0 .insert((row, col), Rgb::new(r, g, b)); } else { testing.colors.borrow_mut().0.remove(&(row, col)); } } } self.notify("colors"); if nelson.success(testing.board.layout().layout()) { let message = format!("Test {}/{} successful", test_run, test_runs); info!("{}", message); test_label.set_text(&message); } else { let message = format!("Test {}/{} failed", test_run, test_runs); error!("{}", message); test_label.set_text(&message); break; } } info!("Re-enable keyboard input events"); self.set_no_input(false).await; info!("Enabling test buttons"); self.test_buttons_sensitive(true); } fn connect_test_button_1(&self) { self.inner().test_buttons[0].connect_clicked(clone!(@strong self as self_ => move |_| { glib::MainContext::default().spawn_local(clone!(@strong self_ => async move { REFRESH_DISABLED.store(true, Ordering::Relaxed); self_.nelson(1, 0, NelsonKind::Normal).await; REFRESH_DISABLED.store(false, Ordering::Relaxed); })); })); } fn connect_test_button_2(&self) { self.inner().test_buttons[1].connect_clicked(clone!(@strong self as self_ => move |_| { glib::MainContext::default().spawn_local(clone!(@strong self_ => async move { REFRESH_DISABLED.store(true, Ordering::Relaxed); self_.nelson( self_.inner().num_runs_spin_2.value_as_int(), 2, NelsonKind::Normal, ).await; REFRESH_DISABLED.store(false, Ordering::Relaxed); })); })); } pub fn selma_update_colors(&self) { if !self.inner().selma_running.get() { return; } let mut colors = self.inner().colors.borrow_mut(); for k in self.inner().board.keys() { let (row, col) = k.electrical; if k.pressed() { colors .0 .insert((row as usize, col as usize), Rgb::new(255, 0, 0)); } } drop(colors); self.notify("colors"); } async fn selma(&self) { let testing = self.inner(); info!("Disabling test buttons"); self.test_buttons_sensitive(false); testing.selma_stop_button.set_sensitive(true); info!("Disable keyboard input events"); self.set_no_input(true).await; testing.colors.borrow_mut().0.clear(); self.selma_update_colors(); self.inner().selma_running.set(true); // Wait for stop button to be pressed let (sender, reciever) = oneshot::channel(); *testing.selma_stop_sender.borrow_mut() = Some(sender); let _ = reciever.await; self.inner().selma_running.set(false); info!("Re-enable keyboard input events"); self.set_no_input(false).await; info!("Enabling test buttons"); self.test_buttons_sensitive(true); testing.selma_stop_button.set_sensitive(false); } fn connect_selma_buttons(&self) { self.inner() .selma_start_button .connect_clicked(clone!(@strong self as self_ => move |_| { glib::MainContext::default().spawn_local(clone!(@strong self_ => async move { self_.selma().await; })); })); self.inner() .selma_stop_button .connect_clicked(clone!(@strong self as self_ => move |_| { glib::MainContext::default().spawn_local(clone!(@strong self_ => async move { if let Some(sender) = self_.inner().selma_stop_sender.borrow_mut().take() { let _ = sender.send(()); } })); })); } fn connect_reset_button(&self) { let obj_btn = self.clone(); self.inner().reset_button.connect_clicked(move |_button| { TestResults::global().reset(); obj_btn.update_benchmarks(); }); } pub fn new(board: &Board, keyboard: &Keyboard) -> Self { let obj: Self = glib::Object::new(); obj.inner().board.set(board.clone()); obj.inner().keyboard.set(keyboard.downgrade()); obj.connect_bench_button(); obj.connect_test_button_1(); obj.connect_test_button_2(); obj.connect_selma_buttons(); obj.connect_reset_button(); obj.update_benchmarks(); if board.is_lite() { obj.inner().usb_test.set_sensitive(false); } obj } fn inner(&self) -> &TestingInner { TestingInner::from_obj(self) } #[allow(dead_code)] fn keyboard(&self) -> Keyboard { self.inner().keyboard.upgrade().unwrap() } async fn set_no_input(&self, no_input: bool) { if let Err(err) = self.inner().board.set_no_input(no_input).await { error!("Error setting no input mode: {}", err); } } } ================================================ FILE: tools/Cargo.toml ================================================ [package] name = "tools" version = "0.1.0" authors = ["Michael Aaron Murphy "] edition = "2018" description = "build tools used by this project" [[bin]] name = "pkgconfig" path = "src/pkgconfig.rs" ================================================ FILE: tools/src/pkgconfig.rs ================================================ use std::{ env, fs::{self, File}, io::{self, Write}, }; const PKGCONFIG: &str = r#"Name: ${name} Description: {description} Version: {version} Cflags: -I${includedir} Libs: -L${libdir} -l${name}"#; fn main() -> io::Result<()> { let mut args = env::args(); let app = args.nth(1).expect("requires APP argument"); let libdir = args.next().expect("requires libdir argument"); let includedir = args.next().expect("requires includedir argument"); fs::create_dir_all("target/")?; let target = ["target/", &app, ".pc"].concat(); let mut file = File::create(target).expect("unable to create pkgconfig file"); writeln!( &mut file, "libdir={}\nincludedir={}\nname={}\n{}", libdir, includedir, app, PKGCONFIG ) } ================================================ FILE: widgets/Cargo.toml ================================================ [package] name = "system76-keyboard-configurator-widgets" version = "0.1.0" authors = ["Ian Douglas Scott ", "Jeremy Soller "] license = "GPL-3.0-or-later" edition = "2021" [dependencies] cascade = "1" futures = "0.3.13" gtk = { version = "0.18.0" } libc = "0.2" once_cell = "1.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = "0.4.0" backend = { package = "system76-keyboard-configurator-backend", features = ["glib"], path = "../backend" } # Translation support i18n-embed = { version = "0.13.0", features = ["fluent-system", "desktop-requester"] } i18n-embed-fl = "0.6.0" rust-embed = { version = "6.2.0", features = ["debug-embed"] } [build-dependencies] gio = "0.18.0" [target.'cfg(target_os = "windows")'.dependencies] winreg = "0.8" [features] appimage = ["backend/appimage"] ================================================ FILE: widgets/examples/keyboard_color.rs ================================================ #![windows_subsystem = "windows"] use cascade::cascade; use gtk::{gio, glib, prelude::*}; use system76_keyboard_configurator_widgets::keyboard_backlight_widget; fn main() -> glib::ExitCode { gtk::init().unwrap(); let application = cascade! { gtk::Application::new(None, gio::ApplicationFlags::FLAGS_NONE); ..connect_activate(move |app| { let backlight_widget = cascade! { keyboard_backlight_widget(); ..set_margin_top(12); ..set_margin_bottom(12); ..set_margin_start(12); ..set_margin_end(12); }; cascade! { gtk::ApplicationWindow::new(app); ..set_default_size(500, 500); ..add(&backlight_widget); ..show_all(); }; }); }; application.run() } ================================================ FILE: widgets/i18n.toml ================================================ fallback_language = "en" [fluent] assets_dir = "../i18n" ================================================ FILE: widgets/src/choose_color.rs ================================================ use crate::fl; use cascade::cascade; use futures::future::abortable; use gtk::{ gio, glib::{self, clone, Propagation}, prelude::*, }; use std::{cell::RefCell, rc::Rc}; use crate::{ColorWheel, KeyboardColorIndex}; use backend::{Board, Hs}; pub async fn choose_color>( board: Board, w: &W, title: &str, color: Option, index: KeyboardColorIndex, cancellable: Option, ) -> Option { let index = Rc::new(index); let original_colors = index.get_colors(&board); let abort_handle = Rc::new(RefCell::new(None)); board.block_led_save(); let color_wheel = cascade! { ColorWheel::new(); ..set_hs(color.unwrap_or_default()); ..set_size_request(300, 300); }; let preview = cascade! { gtk::DrawingArea::new(); ..set_halign(gtk::Align::Center); ..set_size_request(300, 25); ..connect_draw(clone!(@weak color_wheel => @default-panic, move |_w, cr| { let (r, g, b) = color_wheel.hs().to_rgb().to_floats(); cr.set_source_rgb(r, g, b); cr.paint().unwrap(); Propagation::Proceed })); }; color_wheel.connect_hs_changed( clone!(@strong board, @strong index, @weak preview => @default-panic, move |wheel| { glib::MainContext::default().spawn_local(clone!(@strong board, @strong wheel, @strong index, @strong abort_handle => async move { let (res, new_abort_handle) = abortable(index.set_color(&board, wheel.hs())); if let Some(handle) = abort_handle.replace(Some(new_abort_handle)) { handle.abort(); } if let Ok(Err(err)) = res.await { error!("{}: {}", fl!("error-set-color"), err); } })); preview.queue_draw(); }), ); let hue_adjustment = gtk::Adjustment::new(0., 0., 360., 1., 1., 0.); let saturation_adjustment = gtk::Adjustment::new(0., 0., 100., 1., 1., 0.); let flags = glib::BindingFlags::BIDIRECTIONAL | glib::BindingFlags::SYNC_CREATE; color_wheel .bind_property("hue", &hue_adjustment, "value") .flags(flags) .build(); color_wheel .bind_property("saturation", &saturation_adjustment, "value") .flags(flags) .build(); let hue_box = cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 0); ..add(>k::Label::new(Some(&fl!("label-hue")))); ..add(&cascade! { gtk::Scale::new(gtk::Orientation::Horizontal, Some(&hue_adjustment)); ..set_hexpand(true); ..set_draw_value(false); }); ..add(>k::SpinButton::new(Some(&hue_adjustment), 0., 0)); }; let saturation_box = cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 0); ..add(>k::Label::new(Some(&fl!("label-saturation")))); ..add(&cascade! { gtk::Scale::new(gtk::Orientation::Horizontal, Some(&saturation_adjustment)); ..set_hexpand(true); ..set_draw_value(false); }); ..add(>k::SpinButton::new(Some(&saturation_adjustment), 0., 0)); }; let vbox = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..set_margin(24); ..add(&color_wheel); ..add(&preview); ..add(&hue_box); ..add(&saturation_box); }; let window = w.toplevel().and_then(|x| x.downcast::().ok()); let dialog = cascade! { gtk::Dialog::builder() .title(title) .use_header_bar(1) .modal(true) .build(); ..add_button(&fl!("button-cancel"), gtk::ResponseType::Cancel); ..add_button(&fl!("button-save"), gtk::ResponseType::Ok); ..content_area().add(&vbox); ..set_transient_for(window.as_ref()); ..show_all(); }; if let Some(cancellable) = cancellable { cancellable.connect_closure( "cancelled", false, glib::closure_local!(@watch dialog => move |_: glib::Object| dialog.close()), ); } let response = dialog.run_future().await; dialog.close(); board.unblock_led_save(); if response == gtk::ResponseType::Ok { Some(color_wheel.hs()) } else { if let Err(err) = index.set_colors(&board, &original_colors).await { error!("{}: {}", fl!("error-set-color"), err); } None } } ================================================ FILE: widgets/src/color_circle.rs ================================================ use cascade::cascade; use gtk::{cairo, glib, glib::Propagation, prelude::*, subclass::prelude::*}; use std::{cell::RefCell, collections::BTreeSet, f64::consts::PI}; use backend::Hs; const BORDER: f64 = 1.; #[derive(Default)] pub struct ColorCircleInner { colors: RefCell>, } #[glib::object_subclass] impl ObjectSubclass for ColorCircleInner { const NAME: &'static str = "S76ColorCircle"; type ParentType = gtk::Button; type Type = ColorCircle; } impl ObjectImpl for ColorCircleInner {} impl WidgetImpl for ColorCircleInner { fn draw(&self, cr: &cairo::Context) -> Propagation { let width = f64::from(self.obj().allocated_width()); let height = f64::from(self.obj().allocated_height()); let flags = self.obj().state_flags(); let radius = width.min(height) / 2.; let alpha = if flags.contains(gtk::StateFlags::INSENSITIVE) { 0.5 } else { 1. }; let colors = self.colors.borrow(); let total = colors.len() as f64; let mut angle1 = 0.; for hs in colors.iter() { let angle2 = angle1 + (2. * PI) / total; cr.move_to(radius, radius); cr.arc(radius, radius, radius - 2. * BORDER, angle1, angle2); cr.close_path(); let (r, g, b) = hs.to_rgb().to_floats(); cr.set_source_rgba(r, g, b, alpha); cr.fill().unwrap(); angle1 = angle2; } cr.arc(radius, radius, radius - 2. * BORDER, 0., 2. * PI); if flags.contains(gtk::StateFlags::PRELIGHT) { cr.set_source_rgba(0., 0., 0., 0.2); cr.fill_preserve().unwrap(); } cr.set_line_width(BORDER); cr.set_source_rgb(0.5, 0.5, 0.5); cr.stroke().unwrap(); Propagation::Proceed } } impl ContainerImpl for ColorCircleInner {} impl BinImpl for ColorCircleInner {} impl ButtonImpl for ColorCircleInner {} glib::wrapper! { pub struct ColorCircle(ObjectSubclass) @extends gtk::Button, gtk::Bin, gtk::Container, gtk::Widget; } impl ColorCircle { pub fn new(size: i32) -> Self { cascade! { glib::Object::new::(); ..set_size_request(size, size); } } fn inner(&self) -> &ColorCircleInner { ColorCircleInner::from_obj(self) } pub fn set_colors(&self, colors: BTreeSet) { self.inner().colors.replace(colors); self.queue_draw(); } } ================================================ FILE: widgets/src/color_wheel.rs ================================================ // A hue/saturation color wheel that allows a color to be selected. use cascade::cascade; use futures::future::{abortable, AbortHandle}; use gtk::{ cairo, gdk, glib::{self, clone, Propagation}, prelude::*, subclass::prelude::*, }; use std::cell::{Cell, RefCell}; use std::f64::consts::PI; use crate::DerefCell; use backend::{Hs, Rgb}; #[derive(Default)] pub struct ColorWheelInner { selected_hs: Cell, surface: RefCell>, thread_pool: DerefCell, abort_handle: RefCell>, gesture_drag: DerefCell, drag_start_xy: Cell<(f64, f64)>, } #[glib::object_subclass] impl ObjectSubclass for ColorWheelInner { const NAME: &'static str = "S76ColorWheel"; type ParentType = gtk::DrawingArea; type Type = ColorWheel; } impl ObjectImpl for ColorWheelInner { fn constructed(&self) { self.parent_constructed(); self.thread_pool .set(glib::ThreadPool::shared(None).unwrap()); let wheel = self.obj(); self.gesture_drag.set(cascade! { gtk::GestureDrag::new(&*wheel); ..set_propagation_phase(gtk::PropagationPhase::Bubble); ..connect_drag_begin(clone!(@weak wheel => move |_, start_x, start_y| { wheel.mouse_select((start_x, start_y)); wheel.inner().drag_start_xy.set((start_x, start_y)) })); ..connect_drag_update(clone!(@weak wheel => move |_, offset_x, offset_y| { let (start_x, start_y) = wheel.inner().drag_start_xy.get(); wheel.mouse_select((start_x + offset_x, start_y + offset_y)); })); }); } fn properties() -> &'static [glib::ParamSpec] { use once_cell::sync::Lazy; static PROPERTIES: Lazy> = Lazy::new(|| { vec![ glib::ParamSpecBoxed::builder::("hs").build(), glib::ParamSpecDouble::builder("hue") .minimum(0.) .maximum(360.) .default_value(0.) .build(), glib::ParamSpecDouble::builder("saturation") .minimum(0.) .maximum(100.) .default_value(0.) .build(), ] }); PROPERTIES.as_ref() } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "hs" => { self.obj().set_hs(*value.get::<&Hs>().unwrap()); } "hue" => { let mut hue: f64 = value.get().unwrap(); hue = (hue * PI / 180.).max(0.).min(2. * PI); let hs = self.obj().hs(); self.obj().set_hs(Hs::new(hue, *hs.s)); } "saturation" => { let mut saturation: f64 = value.get().unwrap(); saturation = (saturation / 100.).max(0.).min(1.); let hs = self.obj().hs(); self.obj().set_hs(hs); self.obj().set_hs(Hs::new(*hs.h, saturation)); } _ => unimplemented!(), } } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "hs" => self.obj().hs().to_value(), "hue" => { let mut hue = *self.obj().hs().h * 180. / PI; hue = (360. + hue) % 360.; hue.to_value() } "saturation" => (self.obj().hs().s * 100.).to_value(), _ => unimplemented!(), } } } impl WidgetImpl for ColorWheelInner { fn draw(&self, cr: &cairo::Context) -> Propagation { self.parent_draw(cr); let width = f64::from(self.obj().allocated_width()); let height = f64::from(self.obj().allocated_height()); let radius = width.min(height) / 2.; cr.translate(width / 2. - radius, 0.); // Draw color wheel if let Some(surface) = self.surface.borrow().as_ref() { let pattern = cairo::SurfacePattern::create(surface); let scale = surface.width() as f64 / (radius * 2.); let mut matrix = cairo::Matrix::identity(); matrix.scale(scale, scale); pattern.set_matrix(matrix); cr.set_source(&pattern).unwrap(); } else { cr.set_source_rgba(0., 0., 0., 0.); } cr.arc(radius, radius, radius, 0., 2. * PI); cr.fill().unwrap(); // Draw selector circle let hs = self.obj().hs(); let x = radius + hs.h.cos() * (*hs.s) * radius; let y = radius - hs.h.sin() * (*hs.s) * radius; cr.arc(x, y, 7.5, 0., 2. * PI); cr.set_source_rgb(1., 1., 1.); cr.fill_preserve().unwrap(); cr.set_source_rgb(0., 0., 0.); cr.set_line_width(1.); cr.stroke().unwrap(); Propagation::Proceed } fn size_allocate(&self, rect: &gdk::Rectangle) { self.parent_size_allocate(rect); let wheel = self.obj(); let (future, abort_handle) = abortable(clone!(@weak wheel, @strong rect => async move { let surface = Some(wheel.generate_surface(&rect).await); wheel.inner().surface.replace(surface); wheel.queue_draw(); })); if let Some(abort_handle) = self.abort_handle.replace(Some(abort_handle)) { abort_handle.abort(); } glib::MainContext::default().spawn_local(async { let _ = future.await; }); } fn request_mode(&self) -> gtk::SizeRequestMode { gtk::SizeRequestMode::HeightForWidth } fn preferred_width(&self) -> (i32, i32) { (0, 300) } fn preferred_height(&self) -> (i32, i32) { (0, 300) } fn preferred_height_for_width(&self, width: i32) -> (i32, i32) { (0, width) } fn preferred_width_for_height(&self, height: i32) -> (i32, i32) { (0, height) } } impl DrawingAreaImpl for ColorWheelInner {} glib::wrapper! { pub struct ColorWheel(ObjectSubclass) @extends gtk::DrawingArea, gtk::Widget; } impl ColorWheel { pub fn new() -> Self { glib::Object::new() } fn inner(&self) -> &ColorWheelInner { ColorWheelInner::from_obj(self) } pub fn hs(&self) -> Hs { self.inner().selected_hs.get() } pub fn set_hs(&self, hs: Hs) { self.inner().selected_hs.set(hs); self.queue_draw(); self.notify("hs"); self.notify("hue"); self.notify("saturation"); } pub fn connect_hs_changed(&self, f: F) { self.connect_notify_local(Some("hs"), move |wheel, _| f(wheel)); } fn mouse_select(&self, pos: (f64, f64)) { let width = f64::from(self.allocated_width()); let height = f64::from(self.allocated_height()); let radius = width.min(height) / 2.; let (x, y) = (pos.0 - width / 2., radius - pos.1); let angle = y.atan2(x); let distance = y.hypot(x); self.set_hs(Hs::new(angle, (distance / radius).min(1.))); } async fn generate_surface(&self, rect: >k::Rectangle) -> cairo::ImageSurface { let size = rect.width().min(rect.height()); let stride = cairo::Format::Rgb24.stride_for_width(size as u32).unwrap(); let data = self .inner() .thread_pool .push_future(move || { let mut data = vec![0; (size * stride) as usize]; for row in 0..size { for col in 0..size { let radius = size as f64 / 2.; let (x, y) = (col as f64 - radius, radius - row as f64); let angle = y.atan2(x); let distance = y.hypot(x); let Rgb { r, g, b } = Hs::new(angle, distance / radius).to_rgb(); let offset = (row * stride + col * 4) as usize; data[offset] = b; data[offset + 1] = g; data[offset + 2] = r; } } data }) .unwrap() .await .unwrap(); cairo::ImageSurface::create_for_data(data, cairo::Format::Rgb24, size, size, stride) .unwrap() } } impl Default for ColorWheel { fn default() -> Self { Self::new() } } ================================================ FILE: widgets/src/keyboard_backlight_widget.rs ================================================ // Intended for use in Gnome Control Center's Keyboard panel use crate::fl; use cascade::cascade; use futures::StreamExt; use gtk::{ glib::{self, clone, Propagation}, prelude::*, }; use crate::{KeyboardColor, KeyboardColorIndex}; use backend::{Backend, Board}; pub fn keyboard_backlight_widget() -> gtk::Widget { let stack = cascade! { gtk::Stack::new(); ..style_context().add_class("frame"); ..set_transition_type(gtk::StackTransitionType::SlideLeftRight); }; let stack_switcher = cascade! { gtk::StackSwitcher::new(); ..set_stack(Some(&stack)); }; let vbox = cascade! { gtk::Box::new(gtk::Orientation::Vertical, 12); ..add(&stack_switcher); ..add(&stack); }; if let Err(err) = add_boards(&stack) { eprintln!("Failed to get keyboards: {}", err); } vbox.upcast() } fn add_boards(stack: >k::Stack) -> Result<(), String> { let (backend, mut receiver) = Backend::new_s76power()?; glib::MainContext::default().spawn_local(clone!(@strong stack => async move { while let Some(event) = receiver.next().await { if let backend::Event::BoardAdded(board) = event { let name = board.model().to_owned(); stack.add_titled(&page(board), &name, &name); } } })); backend.refresh(); Ok(()) } fn page(board: Board) -> gtk::Widget { let max_brightness = board.max_brightness() as f64; let brightness = board.layers()[0].brightness() as f64; let brightness_scale = cascade! { gtk::Scale::with_range(gtk::Orientation::Horizontal, 0., max_brightness, 1.); ..set_hexpand(true); ..set_draw_value(false); ..set_value(brightness); ..connect_change_value(clone!(@strong board => move |_scale, _, value| { glib::MainContext::default().spawn_local(clone!(@strong board => async move { if let Err(err) = board.layers()[0].set_brightness(value as i32).await { eprintln!("{}: {}", fl!("error-set-brightness"), err); } })); Propagation::Proceed })); }; // TODO detect when brightness changed in daemon let button = KeyboardColor::new(Some(board), KeyboardColorIndex::Layer(0)); let listbox = cascade! { gtk::ListBox::new(); ..set_header_func(Some(Box::new(|row, before| { let separator = gtk::Separator::new(gtk::Orientation::Horizontal); row.set_header(before.and(Some(&separator))); }))); ..add(&row(&fl!("scale-brightness"), &brightness_scale, true)); ..add(&row(&fl!("button-color"), &button, false)); }; listbox.upcast() } fn row>(text: &str, widget: &W, expand: bool) -> gtk::ListBoxRow { let label = cascade! { gtk::Label::new(Some(text)); ..set_justify(gtk::Justification::Left); }; let hbox = cascade! { gtk::Box::new(gtk::Orientation::Horizontal, 24); ..set_hexpand(true); ..set_vexpand(true); ..pack_start(&label, false, false, 0); ..pack_end(widget, expand, expand, 0); }; let list_box_row = cascade! { gtk::ListBoxRow::new(); ..set_selectable(false); ..set_activatable(false); ..set_margin(12); ..add(&hbox); }; list_box_row } ================================================ FILE: widgets/src/keyboard_color.rs ================================================ use crate::fl; use cascade::cascade; use futures::{prelude::*, stream::FuturesUnordered}; use gtk::{ gio, glib::{self, clone}, prelude::*, subclass::prelude::*, }; use std::{ cell::{Cell, Ref, RefCell}, collections::{BTreeSet, HashMap}, }; use crate::{choose_color, ColorCircle, DerefCell, SelectedKeys}; use backend::{Board, Hs}; #[derive(Clone)] pub enum KeyboardColorIndex { Keys(SelectedKeys), Layer(usize), } impl KeyboardColorIndex { pub async fn set_color(&self, board: &Board, hs: Hs) -> Result<(), String> { match self { KeyboardColorIndex::Keys(keys) => { let futures = FuturesUnordered::new(); for i in keys.iter() { futures.push(board.keys()[*i].set_color(Some(hs))); } futures.try_collect::<()>().await? } KeyboardColorIndex::Layer(i) => board.layers()[*i].set_color(hs).await?, }; Ok(()) } pub fn get_color_set(&self, board: &Board) -> BTreeSet { match self { KeyboardColorIndex::Keys(keys) => keys .iter() .filter_map(|i| board.keys()[*i].color()) .collect(), KeyboardColorIndex::Layer(i) => cascade! { BTreeSet::new(); ..insert(board.layers()[*i].color()); }, } } pub fn get_colors(&self, board: &Board) -> HashMap { match self { KeyboardColorIndex::Keys(keys) => keys .iter() .filter_map(|i| Some((*i, board.keys()[*i].color()?))) .collect(), KeyboardColorIndex::Layer(i) => cascade! { HashMap::new(); ..insert(*i, board.layers()[*i].color()); }, } } pub async fn set_colors( &self, board: &Board, colors: &HashMap, ) -> Result<(), String> { match self { KeyboardColorIndex::Keys(keys) => { let futures = FuturesUnordered::new(); for i in keys.iter() { futures.push(board.keys()[*i].set_color(colors.get(i).copied())); } futures.try_collect::<()>().await? } KeyboardColorIndex::Layer(i) => { board.layers()[*i] .set_color(*colors.get(i).unwrap()) .await? } }; Ok(()) } } impl Default for KeyboardColorIndex { fn default() -> Self { Self::Layer(0) } } #[derive(Default)] pub struct KeyboardColorInner { circle: DerefCell, board: RefCell>, hs: Cell, index: RefCell, dialog_cancellable: Cell>, } #[glib::object_subclass] impl ObjectSubclass for KeyboardColorInner { const NAME: &'static str = "S76KeyboardColor"; type ParentType = gtk::Bin; type Type = KeyboardColor; } impl ObjectImpl for KeyboardColorInner { fn constructed(&self) { self.parent_constructed(); let wheel = self.obj(); let circle = cascade! { ColorCircle::new(30); ..connect_clicked(clone!(@weak wheel => move |_| wheel.circle_clicked())); }; self.obj().add(&circle); self.circle.set(circle); } fn properties() -> &'static [glib::ParamSpec] { use once_cell::sync::Lazy; static PROPERTIES: Lazy> = Lazy::new(|| vec![glib::ParamSpecBoxed::builder::("hs").build()]); PROPERTIES.as_ref() } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { match pspec.name() { "hs" => { let hs: &Hs = value.get().unwrap(); self.obj().set_hs(*hs); } _ => unimplemented!(), } } fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { match pspec.name() { "hs" => self.hs.get().to_value(), _ => unimplemented!(), } } } impl WidgetImpl for KeyboardColorInner { fn destroy(&self) { self.obj().cancel_dialog(); } } impl ContainerImpl for KeyboardColorInner {} impl BinImpl for KeyboardColorInner {} glib::wrapper! { pub struct KeyboardColor(ObjectSubclass) @extends gtk::Bin, gtk::Container, gtk::Widget; } impl KeyboardColor { pub fn new(board: Option, index: KeyboardColorIndex) -> Self { cascade! { glib::Object::new::(); ..set_board(board); ..set_index(index); } } fn inner(&self) -> &KeyboardColorInner { KeyboardColorInner::from_obj(self) } fn circle_clicked(&self) { self.cancel_dialog(); let cancellable = gio::Cancellable::new(); glib::MainContext::default().spawn_local( clone!(@weak self as self_, @strong cancellable => async move { let title = fl!("choose-color"); let resp = choose_color( self_.board().unwrap().clone(), &self_, &title, Some(self_.hs()), self_.index().clone(), Some(cancellable), ); if let Some(color) = resp.await { self_.set_hs(color); } }), ); self.inner().dialog_cancellable.set(Some(cancellable)); } fn board(&self) -> Option> { let board = self.inner().board.borrow(); if board.is_some() { Some(Ref::map(board, |x| x.as_ref().unwrap())) } else { None } } pub fn set_board(&self, board: Option) { self.inner().circle.set_sensitive(board.is_some()); *self.inner().board.borrow_mut() = board; self.read_color(); } fn hs(&self) -> Hs { self.inner().hs.get() } fn set_hs(&self, hs: Hs) { let self_ = self.clone(); let board = self.board().unwrap().clone(); if self.inner().hs.replace(hs) != hs { self.inner().circle.set_colors(cascade! { BTreeSet::new(); ..insert(hs); }); glib::MainContext::default().spawn_local(async move { let index = self_.index().clone(); if let Err(err) = index.set_color(&board, hs).await { error!("Failed to set keyboard color: {}", err); } self_.notify("hs"); }); } } fn index(&self) -> Ref { self.inner().index.borrow() } fn read_color(&self) { if let Some(board) = self.board() { let colors = self.index().get_color_set(&board); let hs = colors .iter() .next() .copied() .unwrap_or_else(|| Hs::new(0., 0.)); if self.inner().hs.replace(hs) != hs { self.notify("hs"); } self.inner().circle.set_colors(colors); } } pub fn set_index(&self, value: KeyboardColorIndex) { self.inner().index.replace(value); self.read_color(); } pub fn cancel_dialog(&self) { if let Some(cancellable) = self.inner().dialog_cancellable.take() { cancellable.cancel(); } } } ================================================ FILE: widgets/src/lib.rs ================================================ #[macro_use] extern crate log; mod choose_color; mod color_circle; mod color_wheel; mod keyboard_color; mod localize; mod selected_keys; pub use crate::{ choose_color::*, color_circle::*, color_wheel::*, keyboard_color::*, localize::*, selected_keys::*, }; pub use backend; use backend::DerefCell; #[cfg(target_os = "linux")] mod keyboard_backlight_widget; #[cfg(target_os = "linux")] pub use keyboard_backlight_widget::keyboard_backlight_widget; ================================================ FILE: widgets/src/localize.rs ================================================ use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DefaultLocalizer, LanguageLoader, Localizer, }; use once_cell::sync::Lazy; use rust_embed::RustEmbed; #[derive(RustEmbed)] #[folder = "../i18n/"] struct Localizations; pub static LANGUAGE_LOADER: Lazy = Lazy::new(|| { let loader: FluentLanguageLoader = fluent_language_loader!(); loader .load_fallback_language(&Localizations) .expect("Error while loading fallback language"); loader }); #[macro_export] macro_rules! fl { ($message_id:literal) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id) }}; ($message_id:literal, $($args:expr),*) => {{ i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *) }}; } // Get the `Localizer` to be used for localizing this library. pub fn localizer() -> Box { Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) } ================================================ FILE: widgets/src/selected_keys.rs ================================================ use gtk::glib; use std::collections::BTreeSet; #[derive(Clone, Default, glib::Boxed)] #[boxed_type(name = "S76SelectedKeys")] pub struct SelectedKeys(BTreeSet); impl SelectedKeys { pub fn new() -> Self { Self(BTreeSet::new()) } } impl std::ops::Deref for SelectedKeys { type Target = BTreeSet; fn deref(&self) -> &Self::Target { &self.0 } } impl std::ops::DerefMut for SelectedKeys { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } ================================================ FILE: windows/README.md ================================================ ### Files - `build.py` - When invoked with mingw32 python, this builds with Rustup and generates a `.msi` with WiX. - `build.bat` - Wrapper to invoke `build.py` with the correct python executable. - `keyboard-configurator.wxs` - xml configuration for WiX to generate `.msi`. - `libraries.wxi` - Generated automatically by `build.py` with a list of needed dlls. Included by `keyboard-configurator.wxs`. ### Dependencies - [MSYS2](https://www.msys2.org/) - [WiX Toolset](https://wixtoolset.org/) In msys2, run `pacman -S mingw-w64-i686-gtk3 mingw-w64-i686-rust mingw-w64-i686-toolchain mingw-w64-i686-ntldd mingw-w64-x86_64-imagemagick`. ### Building `.\build.bat` will build and generate a `.msi` installer. ### Installation Click on the `.msi` in Windows explorer, or run `msiexec /i keyboard-configurator.msi`. ### Uninstallation Uninstall from *Add or Remove Programs* or with `msiexec /x keyboard-configurator.msi`. ================================================ FILE: windows/build.bat ================================================ set MSYSTEM_PREFIX=C:\msys64\mingw32 C:\msys64\mingw32\bin\python build.py ================================================ FILE: windows/build.py ================================================ #!/usr/bin/env python3 import argparse import os import re import shlex import shutil import subprocess import sys import json import urllib.request from zipfile import ZipFile # Handle commandline arguments parser = argparse.ArgumentParser() parser.add_argument('--release', action='store_true') parser.add_argument('--sign', action='store_true') parser.add_argument('--cargo', default='cargo') parser.add_argument('--wix', default=None) args = parser.parse_args() if args.wix == None: # look for WiX. # If there are somehow multiple versions, use newest. program_files = "C:/Program Files (x86)/" wix_dirs = sorted(i for i in os.listdir(program_files) if i.startswith("WiX Toolset v")) try: wix_dir = program_files + wix_dirs[-1] except IndexError: sys.exit("WiX not found. Install or pass `--wix`.") else: wix_dir = args.wix CARGO = shlex.split(args.cargo) # Executables to install TARGET_DIR = "../target/" + ('release' if args.release else 'debug') EXES = { f"{TARGET_DIR}/system76-keyboard-configurator.exe", } ICON = "../data/icons/scalable/apps/com.system76.keyboardconfigurator.svg" DLL_RE = r"(?<==> )(.*\\mingw32)\\bin\\(\S+.dll)" # mingw32 version seems to no longer be packaged, and need to avoid unrelated # System32/convert CONVERT = os.path.dirname(os.environ['MSYSTEM_PREFIX']) + r'\mingw64\bin\convert.exe' ADWAITA_FILES = [ 'index.theme', 'symbolic/actions/open-menu-symbolic.svg', 'symbolic/ui/window-close-symbolic.svg', 'symbolic/ui/window-maximize-symbolic.svg', 'symbolic/ui/window-minimize-symbolic.svg', 'symbolic/ui/window-restore-symbolic.svg', 'symbolic/actions/edit-delete-symbolic.svg', 'symbolic/actions/go-previous-symbolic.svg', 'symbolic/actions/list-remove-symbolic.svg', 'symbolic/actions/list-add-symbolic.svg', 'symbolic/actions/edit-find-symbolic.svg', ] ADWAITA_FILES = [f'share/icons/Adwaita/{i}' for i in ADWAITA_FILES] ADDITIONAL_FILES = ['share/glib-2.0/schemas/org.gtk.Settings.FileChooser.gschema.xml', 'share/icons/hicolor/index.theme', 'lib/gdk-pixbuf-2.0'] + ADWAITA_FILES # Use ntldd to find the mingw dlls required by a .exe def find_depends(exe): if not os.path.exists(exe): sys.exit(f"'{exe}' does not exist") output = subprocess.check_output(['ntldd.exe', '-R', exe], universal_newlines=True) dlls = set() mingw_dir = None for l in output.splitlines(): m = re.search(DLL_RE, l, re.IGNORECASE) if m: dlls.add((m.group(0), m.group(2))) mingw_dir = m.group(1) return mingw_dir, dlls def check_call(args, **kwargs): # NOTE: Important not to print all args, for `CodeSignTool` invocation print(f"RUN {args[0]}") try: subprocess.check_call(args, **kwargs) except subprocess.CalledProcessError as e: sys.exit(f"ERROR: {args[0]} failed with code {e.returncode}") # Build application with rustup cmd = CARGO + ['build'] if args.release: cmd.append('--release') check_call(cmd) # Generate set of all required dlls dlls = set() mingw_dir = None for i in EXES: mingw_dir_new, dlls_new = find_depends(i) dlls = dlls.union(dlls_new) mingw_dir = mingw_dir or mingw_dir_new # The svg module is loaded at runtime, so it's dependencies are also needed dlls = dlls.union(find_depends(f"{mingw_dir}/lib/gdk-pixbuf-2.0/2.10.0/loaders/pixbufloader_svg.dll")[1]) def copy(srcdir, destdir, path): src = f"{srcdir}/{path}" dest = f"{destdir}/{path}" os.makedirs(os.path.dirname(dest), exist_ok=True) print(f"Copy {src} -> {dest}") if os.path.isdir(src): shutil.copytree(src, dest) else: shutil.copy(src, dest) def strip(srcdir, destdir, path): src = f"{srcdir}/{path}" dest = f"{destdir}/{path}" os.makedirs(os.path.dirname(dest), exist_ok=True) print(f"Strip {src} -> {dest}") check_call([f"strip.exe", '-o', dest, src]) # Copy executables and libraries if os.path.exists('out'): shutil.rmtree('out') for i in EXES: strip(os.path.dirname(i), 'out', os.path.basename(i)) for src, filename in dlls: copy(os.path.dirname(src), 'out', filename) # This shouldn't be necessary # https://github.com/pop-os/keyboard-configurator/issues/39 copy('../data/icons', 'out/share/icons/Adwaita', 'scalable') # Copy additional data for i in ADDITIONAL_FILES: copy(mingw_dir, 'out', i) check_call(["glib-compile-schemas", "out/share/glib-2.0/schemas"]) # Extract crate version from cargo meta_str = subprocess.check_output(CARGO + ["metadata", "--format-version", "1", "--no-deps"]) meta = json.loads(meta_str) package = next(i for i in meta['packages'] if i['name'] == 'system76-keyboard-configurator') crate_version = package['version'] # Generate Icon and installer banner check_call(["rsvg-convert", "--width", "256", "--height", "256", "-o", "keyboard-configurator.png", ICON]) check_call([CONVERT, "keyboard-configurator.png", "out/keyboard-configurator.ico"]) check_call(["rsvg-convert", "--width", "493", "--height", "58", "-o", "banner.png", "banner.svg"]) check_call([CONVERT, "banner.png", "banner.bmp"]) check_call(["rsvg-convert", "--width", "493", "--height", "312", "-o", "dialog.png", "dialog.svg"]) check_call([CONVERT, "dialog.png", "dialog.bmp"]) # Generate libraries.wxi with open('libraries.wxi', 'w') as f: f.write("\n") f.write('\n') def add_files(dirpath, indent): id_ = os.path.relpath(dirpath, 'out').replace('\\', '_').replace('/', '_').replace('-', '_').replace('.', '_') f.write(f"{indent}\n") for i in os.scandir(dirpath): if i.is_dir(): add_files(i.path, indent + ' ' * 4) else: id_ = i.path.replace('\\', '_').replace('-', '_').replace('.', '_') f.write(f"{indent}\n") f.write(f"{indent} \n") f.write(f"{indent}\n") f.write(f"{indent}\n") for i in ['lib', 'share']: add_files(f"out\\{i}", ' ' * 4) for _, i in dlls: f.write(f" \n") f.write(f" \n") f.write(f" \n") f.write('\n') # Build .msi check_call([f"{wix_dir}/bin/candle.exe", ".\keyboard-configurator.wxs", f"-dcrate_version={crate_version}"]) check_call([f"{wix_dir}/bin/light.exe", "-ext", "WixUIExtension", ".\keyboard-configurator.wixobj"]) if args.sign: if not os.path.isdir('sign'): os.mkdir("sign") # Download signing tool tool_url = "https://www.ssl.com/download/codesigntool-for-windows" tool_zip = "sign/CodeSignTool.zip" if not os.path.isfile(tool_zip): if os.path.isfile(tool_zip + ".partial"): os.remove(tool_zip + ".partial") urllib.request.urlretrieve(tool_url, tool_zip + ".partial") os.rename(tool_zip + ".partial", tool_zip) # Extract signing tool tool_dir = "sign/CodeSignTool" if not os.path.isdir(tool_dir): if os.path.isdir(tool_dir + ".partial"): shutil.rmtree(tool_dir + ".partial") os.mkdir(tool_dir + ".partial") with ZipFile(tool_zip, "r") as zip: zip.extractall(tool_dir + ".partial") os.rename(tool_dir + ".partial", tool_dir) # Sign with specified cloud signing key check_call([ "cmd", "/c", "CodeSignTool.bat", "sign", "-credential_id=" + os.environ["SSL_COM_CREDENTIAL_ID"], "-username=" + os.environ["SSL_COM_USERNAME"], "-password=" + os.environ["SSL_COM_PASSWORD"], "-totp_secret=" + os.environ["SSL_COM_TOTP_SECRET"], "-program_name=System76 Keyboard Configurator", "-input_file_path=../../keyboard-configurator.msi", "-output_dir_path=../", ], cwd="sign/CodeSignTool") # Update MSI os.remove("keyboard-configurator.msi") os.rename("sign/keyboard-configurator.msi", "keyboard-configurator.msi") ================================================ FILE: windows/gpl.rtf ================================================ {\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 Courier;}} {\colortbl;\red255\green0\blue0;\red0\green0\blue255;} \widowctrl\hyphauto {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 GNU GENERAL PUBLIC LICENSE\par} {\pard \ql \f0 \sa180 \li0 \fi0 Version 3, 29 June 2007\par} {\pard \ql \f0 \sa180 \li0 \fi0 Copyright \u169? 2007 Free Software Foundation, Inc. <{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{\ul https://fsf.org/ }}} >\par} {\pard \ql \f0 \sa180 \li0 \fi0 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Preamble\par} {\pard \ql \f0 \sa180 \li0 \fi0 The GNU General Public License is a free, copyleft license for software and other kinds of works.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.\par} {\pard \ql \f0 \sa180 \li0 \fi0 When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\par} {\pard \ql \f0 \sa180 \li0 \fi0 To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.\par} {\pard \ql \f0 \sa180 \li0 \fi0 For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The precise terms and conditions for copying, distribution and modification follow.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 TERMS AND CONDITIONS\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 0. Definitions.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"This License\u8221" refers to version 3 of the GNU General Public License.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"Copyright\u8221" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"The Program\u8221" refers to any copyrightable work licensed under this License. Each licensee is addressed as \u8220"you\u8221". \u8220"Licensees\u8221" and \u8220"recipients\u8221" may be individuals or organizations.\par} {\pard \ql \f0 \sa180 \li0 \fi0 To \u8220"modify\u8221" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a \u8220"modified version\u8221" of the earlier work or a work \u8220"based on\u8221" the earlier work.\par} {\pard \ql \f0 \sa180 \li0 \fi0 A \u8220"covered work\u8221" means either the unmodified Program or a work based on the Program.\par} {\pard \ql \f0 \sa180 \li0 \fi0 To \u8220"propagate\u8221" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\par} {\pard \ql \f0 \sa180 \li0 \fi0 To \u8220"convey\u8221" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\par} {\pard \ql \f0 \sa180 \li0 \fi0 An interactive user interface displays \u8220"Appropriate Legal Notices\u8221" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 1. Source Code.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The \u8220"source code\u8221" for a work means the preferred form of the work for making modifications to it. \u8220"Object code\u8221" means any non-source form of a work.\par} {\pard \ql \f0 \sa180 \li0 \fi0 A \u8220"Standard Interface\u8221" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The \u8220"System Libraries\u8221" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A \u8220"Major Component\u8221", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The \u8220"Corresponding Source\u8221" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The Corresponding Source for a work in source code form is that same work.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 2. Basic Permissions.\par} {\pard \ql \f0 \sa180 \li0 \fi0 All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\par} {\pard \ql \f0 \sa180 \li0 \fi0 No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\par} {\pard \ql \f0 \sa180 \li0 \fi0 When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 4. Conveying Verbatim Copies.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 5. Conveying Modified Source Versions.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab a) The work must carry prominent notices stating that you modified it, and giving a relevant date.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to \u8220"keep intact all notices\u8221".\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an \u8220"aggregate\u8221" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 6. Conveying Non-Source Forms.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\par} {\pard \ql \f0 \sa180 \li0 \fi0 A \u8220"User Product\u8221" is either (1) a \u8220"consumer product\u8221", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, \u8220"normally used\u8221" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"Installation Information\u8221" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\par} {\pard \ql \f0 \sa180 \li0 \fi0 The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 7. Additional Terms.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \u8220"Additional permissions\u8221" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\par} {\pard \ql \f0 \sa180 \li0 \fi0 When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab d) Limiting the use for publicity purposes of names of licensors or authors of the material; or\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 All other non-permissive additional terms are considered \u8220"further restrictions\u8221" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 8. Termination.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\par} {\pard \ql \f0 \sa180 \li0 \fi0 However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 9. Acceptance Not Required for Having Copies.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 10. Automatic Licensing of Downstream Recipients.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\par} {\pard \ql \f0 \sa180 \li0 \fi0 An \u8220"entity transaction\u8221" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\par} {\pard \ql \f0 \sa180 \li0 \fi0 You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 11. Patents.\par} {\pard \ql \f0 \sa180 \li0 \fi0 A \u8220"contributor\u8221" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's \u8220"contributor version\u8221".\par} {\pard \ql \f0 \sa180 \li0 \fi0 A contributor's \u8220"essential patent claims\u8221" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, \u8220"control\u8221" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\par} {\pard \ql \f0 \sa180 \li0 \fi0 In the following three paragraphs, a \u8220"patent license\u8221" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To \u8220"grant\u8221" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. \u8220"Knowingly relying\u8221" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 A patent license is \u8220"discriminatory\u8221" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 12. No Surrender of Others' Freedom.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 13. Use with the GNU Affero General Public License.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 14. Revised Versions of this License.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License \u8220"or any later version\u8221" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 15. Disclaimer of Warranty.\par} {\pard \ql \f0 \sa180 \li0 \fi0 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \u8220"AS IS\u8221" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 16. Limitation of Liability.\par} {\pard \ql \f0 \sa180 \li0 \fi0 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 17. Interpretation of Sections 15 and 16.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\par} {\pard \ql \f0 \sa180 \li0 \fi0 END OF TERMS AND CONDITIONS\par} {\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 How to Apply These Terms to Your New Programs\par} {\pard \ql \f0 \sa180 \li0 \fi0 If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\par} {\pard \ql \f0 \sa180 \li0 \fi0 To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the \u8220"copyright\u8221" line and a pointer to where the full notice is found.\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 \line Copyright (C) \line \line This program is free software: you can redistribute it and/or modify\line it under the terms of the GNU General Public License as published by\line the Free Software Foundation, either version 3 of the License, or\line (at your option) any later version.\line \line This program is distributed in the hope that it will be useful,\line but WITHOUT ANY WARRANTY; without even the implied warranty of\line MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\line GNU General Public License for more details.\line \line You should have received a copy of the GNU General Public License\line along with this program. If not, see .\par} {\pard \ql \f0 \sa180 \li0 \fi0 Also add information on how to contact you by electronic and paper mail.\par} {\pard \ql \f0 \sa180 \li0 \fi0 If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:\par} {\pard \ql \f0 \sa180 \li0 \fi0 \f1 Copyright (C) \line This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\line This is free software, and you are welcome to redistribute it\line under certain conditions; type `show c' for details.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an \u8220"about box\u8221".\par} {\pard \ql \f0 \sa180 \li0 \fi0 You should also get your employer (if you work as a programmer) or school, if any, to sign a \u8220"copyright disclaimer\u8221" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{\ul https://www.gnu.org/licenses/ }}} >.\par} {\pard \ql \f0 \sa180 \li0 \fi0 The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/why-not-lgpl.html"}}{\fldrslt{\ul https://www.gnu.org/licenses/why-not-lgpl.html }}} >.\par} } ================================================ FILE: windows/keyboard-configurator.wxs ================================================