Compare commits
350 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 914c5d4940 | |||
| b72c6b53e4 | |||
| 701168c32b | |||
| 558a2568e3 | |||
| 9517c347b6 | |||
| 8dd92c81e7 | |||
| 03ccfe77ad | |||
| c103b84fa6 | |||
| 9a72db2fcc | |||
| 61a84c47f1 | |||
| a9ecc13185 | |||
| 7143fb2497 | |||
| dfee95430d | |||
| fcd0eaddf2 | |||
| ba2e191918 | |||
| cc4f14e8c6 | |||
| 103e64b96c | |||
| 2796362d34 | |||
| af00d74f71 | |||
| 02d579d757 | |||
| 01d06d0f5f | |||
| 1d1c98c27a | |||
| 696d77293e | |||
| 225c204e37 | |||
| c3b428e517 | |||
| 1fe6d65525 | |||
| 39a3c40d67 | |||
| 963f52bbc3 | |||
| 9dcc4c9868 | |||
| df8e885983 | |||
| 540c4d9c05 | |||
| 42483234e3 | |||
| c9f9a3b577 | |||
| 81041b8035 | |||
| c731124f7b | |||
| fca8984225 | |||
| bd6ab663c0 | |||
| 4049e66307 | |||
| 046a516a11 | |||
| b5d1e8c3eb | |||
| aee296ad96 | |||
| 5f59db478a | |||
| dda070e84e | |||
| 17db3db296 | |||
| ebbb3b1138 | |||
| 277986bcdf | |||
| 96461cf2aa | |||
| 2029f48b4d | |||
| 943d2de536 | |||
| 5aa7334787 | |||
| 955a138849 | |||
| 44c80a0406 | |||
| 12c9ca1e02 | |||
| 91acfa0138 | |||
| cf09d1b3bc | |||
| 81fb7e0df3 | |||
| 0e533c5e94 | |||
| 8d01d17b8c | |||
| 74a5b0937b | |||
| 17ce0b6b46 | |||
| c0525946ae | |||
| 8bb5c4f16c | |||
| a0322f0d7e | |||
| d07b5ed0d6 | |||
| 153f9c39e5 | |||
| c0b6ea51fa | |||
| 5d81cf78f8 | |||
| 0ed1dd925a | |||
| 39464f9c99 | |||
| eeb7e252c7 | |||
| 65425ff928 | |||
| 229b3bac51 | |||
| a4e7ad06d3 | |||
| db298b0fb8 | |||
| 4373cf7bc3 | |||
| 2f613ea4c7 | |||
| 8f526bd357 | |||
| b77b3f7816 | |||
| 87eb775377 | |||
| f64e5a3627 | |||
| 595bbccfdf | |||
| afd47ef8b4 | |||
| 7e38d17cb7 | |||
| ef7df433d8 | |||
| 8e32de86a9 | |||
| 6871452c7b | |||
| 192824be39 | |||
| 938d3c335e | |||
| 9dd67ad2bc | |||
| 9f4cb3c791 | |||
| 6ed2a47620 | |||
| 4253bf1299 | |||
| d283ced2ce | |||
| 776c0c5f4b | |||
| 8cf6c5f948 | |||
| de3bf54dc9 | |||
| 2219eb67e1 | |||
| 61400c9584 | |||
| b21734bf57 | |||
| 24adba44be | |||
| 5e43a31051 | |||
| 40850267d4 | |||
| 93ac94b83f | |||
| ec5570a547 | |||
| 72bd265065 | |||
| 07bcaa8e2b | |||
| 4357052fe7 | |||
| c16c686592 | |||
| 4b825c26a6 | |||
| 74479ff226 | |||
| 94bfa92c12 | |||
| 50fb124b26 | |||
| 7aa004ceff | |||
| 60056dcf26 | |||
| 5580853f31 | |||
| d93e9c2b11 | |||
| 4ccf11f4fd | |||
| 6c5df02921 | |||
| b137e2e3a0 | |||
| 820a8b6ca1 | |||
| 8bdfb69dc1 | |||
| 1e6bcef055 | |||
| 07faf906d8 | |||
| 53f30324f0 | |||
| 3e212ddab4 | |||
| 966990ad65 | |||
| a8b81172fc | |||
| 97f51591b3 | |||
| 6756fb423a | |||
| eb7673d2c2 | |||
| 24b6a04903 | |||
| b197cd839e | |||
| 857a916402 | |||
| ca68fc2040 | |||
| bd661bd4f4 | |||
| 4228192bda | |||
| 0f7ab99da3 | |||
| e15d317488 | |||
| 93e9ce0dd7 | |||
| 9d63b505ec | |||
| 306c11f1fd | |||
| c26feed8b2 | |||
| 2f4a652f53 | |||
| e5796d0d7b | |||
| 1ee58ce7a0 | |||
| 88821e2e82 | |||
| 81344bb9c2 | |||
| c87b61d065 | |||
| 97da44f059 | |||
| f5a5282219 | |||
| 123faecb7d | |||
| 7ec3053aa4 | |||
| 9512fd8436 | |||
| 0c8feb7687 | |||
| f3f1d58fe1 | |||
| c0c666f1b3 | |||
| ea22afba79 | |||
| d7c7528d3d | |||
| 93ff086e3a | |||
| 4f72779681 | |||
| 762e12431d | |||
| 767bb1745c | |||
| 26e0473fc1 | |||
| 0735d1c6c6 | |||
| 67d8926913 | |||
| 0299527700 | |||
| ecfc45c2de | |||
| 3ba6aca99d | |||
| 40b3172de8 | |||
| 1a2df96c02 | |||
| d2989e8ecd | |||
| ec58442724 | |||
| e89c9b02a0 | |||
| 1b2725250b | |||
| e285ecce93 | |||
| 75ecf9059a | |||
| 5715458d33 | |||
| 8196117269 | |||
| 7fed1339ed | |||
| 0339d13ce4 | |||
| 9f1e49da5d | |||
| c1737c763f | |||
| fe22fc2271 | |||
| f473a47eb8 | |||
| 76bd87686a | |||
| ef85823528 | |||
| 54ac7511cd | |||
| 080bbb4d4e | |||
| 7c35307011 | |||
| cd3255b301 | |||
| f8b6b98633 | |||
| 6414b57e57 | |||
| 46de67a4db | |||
| 2a20bbbf2a | |||
| 13ebf9449f | |||
| fa8449eb1e | |||
| 0bdb5f1f33 | |||
| b631817896 | |||
| 09c78da7a7 | |||
| 7de7dc1b33 | |||
| 323d89e4cb | |||
| a5ce25055f | |||
| 184bdaa0b6 | |||
| 0459d33c4c | |||
| 3d1a641ca3 | |||
| 0466a520f2 | |||
| 9e8aca1cbf | |||
| 334898c5a5 | |||
| 67a5f1bb0b | |||
| eb84e52897 | |||
| 0f7ff1636d | |||
| 8ff8e8ac48 | |||
| d4bb9038c5 | |||
| f3caeb8fc6 | |||
| abaaf04b87 | |||
| 2770e1769c | |||
| 3cd170acc3 | |||
| 24f709ab13 | |||
| 784f9127fa | |||
| 22daefba3a | |||
| 4ff9cf087b | |||
| 61e1ab5c5a | |||
| 7fbc9ed56e | |||
| 67cc4f11cf | |||
| 8ac2b5a713 | |||
| 8bae8fe5bb | |||
| b3cfc8a0f3 | |||
| 5a591127a1 | |||
| 8f3d010349 | |||
| 7eb5c6d466 | |||
| 9f6fe8318c | |||
| 92e9d994fe | |||
| c28f07fcfd | |||
| 80919dbc42 | |||
| cc369f6f81 | |||
| 99f2f286e3 | |||
| 46cbaf8e87 | |||
| 53b4466899 | |||
| c0aee5de26 | |||
| 404f94638f | |||
| cb802cfb50 | |||
| 930f5be0c8 | |||
| 7266f539d4 | |||
| da1f480f7a | |||
| 3c3f00ede8 | |||
| 85be855032 | |||
| 3e642fdac7 | |||
| ea288ca62e | |||
| a57a78aa2e | |||
| b441103674 | |||
| 1c3516d6bf | |||
| 41be2747d5 | |||
| c766fae686 | |||
| a0a2e40fa0 | |||
| aadcdbf276 | |||
| 10178d204b | |||
| 0ac8c620fd | |||
| 80e83781bb | |||
| 37e1ed93a6 | |||
| b770511422 | |||
| 2e9b8581e7 | |||
| 1cbc21ad11 | |||
| 416bc6163e | |||
| 40b79f6209 | |||
| 782d80a007 | |||
| a51d91eb53 | |||
| 687a512e5e | |||
| 500c23beec | |||
| 97d8dfe4cb | |||
| 11213ba13a | |||
| 3d6c656c78 | |||
| 258dd9b926 | |||
| 4eaa8e316e | |||
| cbee649939 | |||
| b9db00c00c | |||
| 99b1439d08 | |||
| 83fe2757ef | |||
| d21d278710 | |||
| e6ca914d65 | |||
| 0d96a647f9 | |||
| 852289b5e3 | |||
| 1f5e9566e4 | |||
| 7a588460bf | |||
| d654b9cc73 | |||
| 3ed601a7e8 | |||
| 63d68c004a | |||
| 34c6d2ff28 | |||
| 7f32c5cf23 | |||
| 9368a188b3 | |||
| a61019c4b7 | |||
| f4f11e5051 | |||
| ab67bd2c5c | |||
| f834fafd67 | |||
| 4b34f18d34 | |||
| d5682de47c | |||
| 2ffbdde758 | |||
| cd252634bd | |||
| de8aaa1a47 | |||
| ac360b610f | |||
| acfa48886d | |||
| f326929634 | |||
| dbb8331294 | |||
| 585ed5e97d | |||
| 09075e57c8 | |||
| 2b65beba44 | |||
| 5129d42577 | |||
| 2ed4862db8 | |||
| 8d06815279 | |||
| c75e085dc8 | |||
| cc418c3609 | |||
| ea84f4f031 | |||
| 38398395bc | |||
| 81e0c15db9 | |||
| 60c68dbf5a | |||
| f3d852f552 | |||
| 42cb73cd8c | |||
| d1bc23e9d8 | |||
| e3f31cc17f | |||
| dca0e55557 | |||
| a78f8e246b | |||
| 9d027426b7 | |||
| 02c24a50d2 | |||
| 26dbcdeb62 | |||
| 0ef02ebfa3 | |||
| 0ce19b4269 | |||
| 326bb9319f | |||
| aafecfac02 | |||
| e5d416fd4f | |||
| 785717d477 | |||
| fdcc4f5aab | |||
| 4e4f8e1932 | |||
| 51f55fbff8 | |||
| 92c9572ac2 | |||
| 357a46ced3 | |||
| 58b087e35a | |||
| 14d5881f1e | |||
| 7dd8bd54c2 | |||
| 4c2cef30f2 | |||
| 3ecfd701d9 | |||
| 033a1cf200 | |||
| 9f59279307 | |||
| 7e72722a47 | |||
| 375daa68c8 | |||
| ed31e40991 | |||
| 34db364a62 | |||
| 950310c8a5 | |||
| e77eccf7db | |||
| e06e23dd4c | |||
| 0bfd846139 | |||
| a93f3c55e7 |
@ -1,4 +1,4 @@
|
||||
image: debian:buster
|
||||
image: debian:bullseye
|
||||
|
||||
stages:
|
||||
- build
|
||||
@ -11,7 +11,7 @@ stages:
|
||||
before_script:
|
||||
- apt-get -y update
|
||||
- apt-get -y install wget ca-certificates gnupg
|
||||
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
|
||||
- echo "deb [trusted=yes] http://ci.puri.sm/ bullseyeci main" > /etc/apt/sources.list.d/ci.list
|
||||
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
|
||||
- apt-get -y update
|
||||
|
||||
@ -22,11 +22,13 @@ build_docs:
|
||||
paths:
|
||||
- _build
|
||||
script:
|
||||
- apt-get -y install python3-recommonmark python3-sphinx
|
||||
- apt-get -y install python3-pip python3-sphinx
|
||||
- pip3 install recommonmark
|
||||
- ./doc/build.sh _build
|
||||
|
||||
build_meson:
|
||||
<<: *tags
|
||||
tags:
|
||||
- librem5
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
@ -34,7 +36,7 @@ build_meson:
|
||||
expire_in: 3h
|
||||
script:
|
||||
- apt-get -y build-dep .
|
||||
- meson . _build/ -Ddepdatadir=/usr/share
|
||||
- meson . _build/ -Ddepdatadir=/usr/share --werror
|
||||
- ninja -C _build install
|
||||
|
||||
build_deb:
|
||||
@ -45,20 +47,73 @@ build_deb:
|
||||
paths:
|
||||
- "*.deb"
|
||||
script:
|
||||
- rm -f ../*.deb
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install devscripts
|
||||
- debuild -i -us -uc -b
|
||||
- cp ../*.deb .
|
||||
|
||||
build_deb:arm64:
|
||||
build_deb:amber:
|
||||
image: pureos/amber
|
||||
tags:
|
||||
- librem5:arm64
|
||||
allow_failure: true
|
||||
- librem5
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
- "*.deb"
|
||||
script:
|
||||
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
|
||||
- apt-get -y update
|
||||
- rm -f ../*.deb
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install devscripts
|
||||
- debuild -i -us -uc -b
|
||||
- cp ../*.deb .
|
||||
|
||||
build_deb:buster:
|
||||
image: "debian:buster"
|
||||
tags:
|
||||
- librem5
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
- "*.deb"
|
||||
script:
|
||||
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
|
||||
- apt-get -y update
|
||||
- rm -f ../*.deb
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install devscripts
|
||||
- debuild -i -us -uc -b
|
||||
- cp ../*.deb .
|
||||
|
||||
|
||||
build_deb:arm64:
|
||||
tags:
|
||||
- librem5:arm64
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
- "*.deb"
|
||||
script:
|
||||
- rm -f ../*.deb
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install devscripts
|
||||
- debuild -i -us -uc -b
|
||||
- cp ../*.deb .
|
||||
|
||||
build_deb:arm64_buster:
|
||||
image: "debian:buster"
|
||||
tags:
|
||||
- librem5:arm64
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
- "*.deb"
|
||||
script:
|
||||
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
|
||||
- apt-get -y update
|
||||
- rm -f ../*.deb
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install devscripts
|
||||
- debuild -i -us -uc -b
|
||||
@ -74,10 +129,24 @@ test_lintian:
|
||||
- lintian *.deb
|
||||
|
||||
test:
|
||||
<<: *tags
|
||||
tags:
|
||||
- librem5
|
||||
stage: test
|
||||
needs:
|
||||
- build_meson
|
||||
script:
|
||||
- apt-get -y build-dep .
|
||||
- apt-get -y install clang-tidy
|
||||
- ninja -C _build test
|
||||
- cd _build
|
||||
- clang-tidy --checks=-clang-diagnostic-missing-braces,readability-braces-around-statements, --warnings-as-errors=readability-braces-around-statements -extra-arg=-Wno-unknown-warning-option ../src/*.c ../eek/*.c ../eekboard/*.c
|
||||
|
||||
check_release:
|
||||
<<: *tags
|
||||
stage: test
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
script:
|
||||
- apt-get -y install git python3
|
||||
- (head -n 1 ./debian/changelog && git tag) | ./debian/check_release.py
|
||||
|
||||
22
Cargo.deps
Normal file
22
Cargo.deps
Normal file
@ -0,0 +1,22 @@
|
||||
# Dependencies which change based on build flags
|
||||
bitflags = "1.2.*"
|
||||
clap = { version = "2.33.*", default-features = false }
|
||||
regex = { version = "1.3.*", default-features = false, features = ["std", "unicode-case"] }
|
||||
|
||||
[dependencies.cairo-rs]
|
||||
version = "0.7.*"
|
||||
|
||||
[dependencies.gdk]
|
||||
version = "0.11.*"
|
||||
|
||||
[dependencies.gio]
|
||||
version = "0.7.*"
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.glib]
|
||||
version = "0.8.*"
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.gtk]
|
||||
version = "0.7.*"
|
||||
features = ["v3_22"]
|
||||
22
Cargo.deps.legacy
Normal file
22
Cargo.deps.legacy
Normal file
@ -0,0 +1,22 @@
|
||||
# Dependencies which change based on build flags
|
||||
bitflags = "1.0.*"
|
||||
clap = { version = "2.32.*", default-features = false }
|
||||
regex = { version = "1.1.*", default-features = false, features = ['use_std'] }
|
||||
|
||||
[dependencies.cairo-rs]
|
||||
version = "0.5.*"
|
||||
|
||||
[dependencies.gdk]
|
||||
version = "0.9.*"
|
||||
|
||||
[dependencies.gio]
|
||||
version = "0.5.*"
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.glib]
|
||||
version = "0.6.*"
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.gtk]
|
||||
version = "0.5.*"
|
||||
features = ["v3_22"]
|
||||
537
Cargo.lock
generated
537
Cargo.lock
generated
@ -1,551 +1,484 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.6"
|
||||
name = "atk"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b7499272acf036bb5820c6e346bbfb5acc5dceb104bc2c4fd7e6e33dfcde6a"
|
||||
dependencies = [
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atk-sys",
|
||||
"bitflags",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atk-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e552c1776737a4c80110d06b36d099f47c727335f9aaa5d942a72b6863a8ec6f"
|
||||
dependencies = [
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
version = "0.5.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05db47de3b0f09a222fa4bba2eab957d920d4243962a86b2d77ab401e4a359c"
|
||||
dependencies = [
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"cairo-sys-rs",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-sys-rs"
|
||||
version = "0.7.0"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63"
|
||||
dependencies = [
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.49"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.32.0"
|
||||
version = "2.33.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.4"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
|
||||
|
||||
[[package]]
|
||||
name = "fragile"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
|
||||
|
||||
[[package]]
|
||||
name = "gdk"
|
||||
version = "0.9.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6243e995f41f3a61a31847e54cc719edce93dd9140c89dca3b9919be1cfe22d5"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf",
|
||||
"gdk-sys",
|
||||
"gio",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf"
|
||||
version = "0.5.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9726408ee1bbada83094326a99b9c68fea275f9dbb515de242a69e72051f4fcc"
|
||||
dependencies = [
|
||||
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf-sys",
|
||||
"gio",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8991b060a9e9161bafd09bf4a202e6fd404f5b4dd1a08d53a1e84256fb34ab0"
|
||||
dependencies = [
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6adf679e91d1bff0c06860287f80403e7db54c2d2424dce0a470023b56c88fbb"
|
||||
dependencies = [
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.5.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6261b5d34c30c2d59f879e643704cf54cb44731f3a2038000b68790c03e360e3"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"fragile",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fad225242b9eae7ec8a063bb86974aca56885014672375e5775dc0ea3533911"
|
||||
dependencies = [
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.6.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be27232841baa43e0fd5ae003f7941925735b2f733a336dc75f07b9eff415e7b"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9"
|
||||
dependencies = [
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk"
|
||||
version = "0.5.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "709f1074259d4685b96133f92b75c7f35b504715b0fcdc96ec95de2607296a60"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atk",
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
"cairo-sys-rs",
|
||||
"cc",
|
||||
"gdk",
|
||||
"gdk-pixbuf",
|
||||
"gdk-pixbuf-sys",
|
||||
"gdk-sys",
|
||||
"gio",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gtk-sys",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"pango",
|
||||
"pango-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1"
|
||||
dependencies = [
|
||||
"atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atk-sys",
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gdk-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.66"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.5.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "393fa071b144f8ffb83ede273758983cf414ca3c0b1d2a5a9ce325b3ba3dd786"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango-sys"
|
||||
version = "0.7.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b93d84907b3cf0819bff8f13598ba72843bee579d5ebc2502e4b0367b4be7d"
|
||||
dependencies = [
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.7"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.1.9"
|
||||
version = "1.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.12"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||
|
||||
[[package]]
|
||||
name = "rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
"cairo-sys-rs",
|
||||
"clap",
|
||||
"gdk",
|
||||
"gio",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gtk",
|
||||
"gtk-sys",
|
||||
"maplit",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"xkbcommon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.104"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.104"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.11"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
|
||||
dependencies = [
|
||||
"dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dtoa",
|
||||
"linked-hash-map",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.13"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc",
|
||||
"memmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
|
||||
dependencies = [
|
||||
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7017e53393e713212aed7aea336b6553be4927f58c37070a56c2fe3d107e489"
|
||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd940f0d609699e343ef71c4af5f66423afbf30d666f796dabd8fd15229cf5b6"
|
||||
"checksum cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d25596627380be4381247dba06c69ad05ca21b3b065bd9827e416882ac41dcd2"
|
||||
"checksum cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)" = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
|
||||
"checksum fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
|
||||
"checksum gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc52c7244046df9d959df87289f1fc5cca23f9f850bab0c967963e2ecb83a96"
|
||||
"checksum gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc3aa730cb4df3de5d9fed59f43afdf9e5fb2d3d10bfcbd04cec031435ce87f5"
|
||||
"checksum gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08284f16ce4d909b10d785a763ba190e222d2c1557b29908bf0a661e27a8ac3b"
|
||||
"checksum gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "108548ebf5329b551f2b97ab356908d14627905abb74b936c3372de1535aee81"
|
||||
"checksum gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29a44b051990573448edc80b1995237f8b97b5734d2aec05105b9242aa10af11"
|
||||
"checksum gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6975ada29f7924dc1c90b30ed3b32d777805a275556c05e420da4fbdc22eb250"
|
||||
"checksum glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a333edf5b9f1411c246ef14e7881b087255f04c56dbef48c64a0cb039b4b340"
|
||||
"checksum glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3573351e846caed9f11207b275cd67bc07f0c2c94fb628e5d7c92ca056c7882d"
|
||||
"checksum gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08475e4a08f27e6e2287005950114735ed61cec2cb8c1187682a5aec8c69b715"
|
||||
"checksum gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a6b30f194f09a17bb7ffa95c3ecdb405abd3b75ff981f831b1f6d18fe115ff"
|
||||
"checksum gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d487d333a4b87072e6bf9f2e55befa0ebef01b9496c2e263c0f4a1ff3d6c04b1"
|
||||
"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
"checksum pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c2cb169402a3eb1ba034a7cc7d95b8b1c106e9be5ba4be79a5a93dc1a2795f4"
|
||||
"checksum pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6eb49268e69dd0c1da5d3001a61aac08e2e9d2bfbe4ae4b19b9963c998f6453"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
|
||||
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
||||
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
|
||||
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
|
||||
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
"checksum xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
|
||||
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
|
||||
|
||||
@ -2,46 +2,40 @@
|
||||
name = "rs"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0.*"
|
||||
clap = "2.32.*"
|
||||
maplit = "1.0.*"
|
||||
regex = "1.1.*"
|
||||
serde = { version = "1.0.*", features = ["derive"] }
|
||||
serde_yaml = "0.8.*"
|
||||
xkbcommon = { version = "0.4.*", features = ["wayland"] }
|
||||
[lib]
|
||||
name = "rs"
|
||||
path = "@path@/src/lib.rs"
|
||||
crate-type = ["staticlib", "rlib"]
|
||||
|
||||
[dependencies.cairo-rs]
|
||||
version = "0.5.*"
|
||||
# Cargo can't do autodiscovery if Cargo.toml is not in the root.
|
||||
[[bin]]
|
||||
name = "test_layout"
|
||||
path = "@path@/src/bin/test_layout.rs"
|
||||
|
||||
[[example]]
|
||||
name = "test_layout"
|
||||
path = "@path@/examples/test_layout.rs"
|
||||
|
||||
[features]
|
||||
gio_v0_5 = []
|
||||
gtk_v0_5 = []
|
||||
rustc_less_1_36 = []
|
||||
|
||||
# Dependencies which don't change based on build flags
|
||||
[dependencies.cairo-sys-rs]
|
||||
version = ""
|
||||
|
||||
[dependencies.gdk]
|
||||
version = ""
|
||||
|
||||
[dependencies.gio]
|
||||
version = ""
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.glib]
|
||||
version = ""
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.glib-sys]
|
||||
version = ""
|
||||
features = ["v2_44"]
|
||||
|
||||
[dependencies.gtk]
|
||||
version = "0.5.*"
|
||||
features = ["v3_22"]
|
||||
|
||||
[dependencies.gtk-sys]
|
||||
version = ""
|
||||
features = ["v3_22"]
|
||||
|
||||
|
||||
[lib]
|
||||
name = "rs"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["staticlib", "rlib"]
|
||||
[dependencies]
|
||||
maplit = "1.0.*"
|
||||
serde = { version = "1.0.*", features = ["derive"] }
|
||||
serde_yaml = "0.8.*"
|
||||
xkbcommon = { version = "0.4.*", features = ["wayland"] }
|
||||
# Here is inserted the Cargo.deps file
|
||||
31
README.md
31
README.md
@ -30,30 +30,43 @@ Building
|
||||
|
||||
### Dependencies
|
||||
|
||||
See `.gitlab-ci.yml`.
|
||||
See `.gitlab-ci.yml` or run `apt-get build-dep .`
|
||||
|
||||
### Build from git repo
|
||||
|
||||
```
|
||||
```bash
|
||||
$ git clone https://source.puri.sm/Librem5/squeekboard.git
|
||||
$ cd squeekboard
|
||||
$ mkdir ../build
|
||||
$ meson ../build/
|
||||
$ cd ../build
|
||||
$ ninja test
|
||||
$ ninja install
|
||||
$ mkdir _build
|
||||
$ meson _build/
|
||||
$ cd _build
|
||||
$ ninja
|
||||
```
|
||||
|
||||
To run tests use `ninja test`. To install squeekboard run `ninja install`.
|
||||
|
||||
Running
|
||||
-------
|
||||
|
||||
```
|
||||
```bash
|
||||
$ phoc # if no compatible Wayland compositor is running yet
|
||||
$ cd ../build/
|
||||
$ src/squeekboard
|
||||
```
|
||||
|
||||
Squeekboard honors the gnome "screen-keyboard-enabled" setting. Either enable this through gnome-settings under accessibility or run:
|
||||
|
||||
```bash
|
||||
$ gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true
|
||||
```
|
||||
|
||||
To make the keyboard show you can use either an application that does so automatically, like a text editor or `python3 ./tests/entry.py`, or you can manually trigger it with:
|
||||
|
||||
```bash
|
||||
busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
|
||||
```
|
||||
|
||||
Developing
|
||||
----------
|
||||
|
||||
See `HACKING.md`
|
||||
See [`doc/hacking.md`](doc/hacking.md) for this copy, or the [official documentation](https://developer.puri.sm/projects/squeekboard/) for the current release.
|
||||
|
||||
7
cargo.sh
7
cargo.sh
@ -13,5 +13,10 @@ CARGO_TARGET_DIR="$(pwd)"
|
||||
export CARGO_TARGET_DIR
|
||||
|
||||
cd "$SOURCE_DIR"
|
||||
cargo "$@"
|
||||
|
||||
# the 'run" command takes arguments at the end,
|
||||
# so --manifest-path must not be last
|
||||
CMD="$1"
|
||||
shift
|
||||
cargo "$CMD" --manifest-path "$CARGO_TARGET_DIR"/Cargo.toml "$@"
|
||||
|
||||
|
||||
49
cargo_build.py
Normal file
49
cargo_build.py
Normal file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""This script manages Cargo builds
|
||||
while keeping the artifact directory within the build tree
|
||||
instead of the source tree.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
source_dir = Path(__file__).absolute().parent
|
||||
|
||||
args = sys.argv[1:]
|
||||
binary_dir = "debug"
|
||||
|
||||
if '--release' in args:
|
||||
binary_dir = "release"
|
||||
|
||||
# The file produced by Cargo will have a special name
|
||||
try:
|
||||
i = args.index('--rename')
|
||||
except ValueError:
|
||||
filename = None
|
||||
else:
|
||||
args.pop(i)
|
||||
filename = args.pop(i)
|
||||
|
||||
# The target destination of the produced file is a positional argument
|
||||
out_path = [arg for arg in args if not arg.startswith('--')]
|
||||
if out_path:
|
||||
out_path = out_path[0]
|
||||
i = args.index(out_path)
|
||||
args.pop(i)
|
||||
|
||||
subprocess.run(['sh', "{}/cargo.sh".format(shlex.quote(source_dir.as_posix())), 'build']
|
||||
+ args,
|
||||
check=True)
|
||||
|
||||
if out_path:
|
||||
out_path = Path(out_path).absolute()
|
||||
out_basename = out_path.name
|
||||
filename = filename or out_basename
|
||||
subprocess.run(['cp', '-a',
|
||||
'./{}/{}'.format(shlex.quote(binary_dir), shlex.quote(filename)),
|
||||
out_path],
|
||||
check=True)
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script manages Cargo builds
|
||||
# while keeping the artifact directory within the build tree
|
||||
# instead of the source tree
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_PATH="$(realpath "$0")"
|
||||
SOURCE_DIR="$(dirname "$SCRIPT_PATH")"
|
||||
|
||||
RELEASE=""
|
||||
BINARY_DIR="debug"
|
||||
if [ "${1}" = "--release" ]; then
|
||||
shift
|
||||
BINARY_DIR="release"
|
||||
RELEASE="--release"
|
||||
fi
|
||||
|
||||
if [ "${1}" = "--rename" ]; then
|
||||
shift
|
||||
FILENAME="${1}"
|
||||
shift
|
||||
fi
|
||||
OUT_PATH="$(realpath "${1}")"
|
||||
shift
|
||||
OUT_BASENAME="$(basename "${OUT_PATH}")"
|
||||
FILENAME="${FILENAME:-"${OUT_BASENAME}"}"
|
||||
|
||||
sh "$SOURCE_DIR"/cargo.sh build $RELEASE "$@"
|
||||
|
||||
if [ -n "${OUT_PATH}" ]; then
|
||||
cp -a ./"${BINARY_DIR}"/"${FILENAME}" "${OUT_PATH}"
|
||||
fi
|
||||
89
data/keyboards/be.yaml
Normal file
89
data/keyboards/be.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 59, height: 52 }
|
||||
spaceline: { width: 140, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "a z e r t y u i o p"
|
||||
- "q s d f g h j k l m"
|
||||
- "Shift_L w x c v b n . BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
upper:
|
||||
- "A Z E R T Y U I O P"
|
||||
- "Q S D F G H J K L M"
|
||||
- "Shift_L W X C V B N , BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
eschars:
|
||||
- "à â ç é è ê î ô ù û"
|
||||
- "À Â Ç É È Ê Î Ô Ù Û"
|
||||
- "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "âÂ"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
89
data/keyboards/be_wide.yaml
Normal file
89
data/keyboards/be_wide.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 42 }
|
||||
altline: { width: 81, height: 42 }
|
||||
wide: { width: 100, height: 42 }
|
||||
spaceline: { width: 205, height: 42 }
|
||||
special: { width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "a z e r t y u i o p"
|
||||
- "q s d f g h j k l m"
|
||||
- "Shift_L w x c v b n . BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
upper:
|
||||
- "A Z E R T Y U I O P"
|
||||
- "Q S D F G H J K L M"
|
||||
- "Shift_L W X C V B N , BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
eschars:
|
||||
- "à â ç é è ê î ô ù û"
|
||||
- "À Â Ç É È Ê Î Ô Ù Û"
|
||||
- "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "âÂ"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
78
data/keyboards/bg.yaml
Normal file
78
data/keyboards/bg.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 32.72, height: 52 }
|
||||
altline: { width: 47, height: 52 }
|
||||
wide: { width: 49.09, height: 52 }
|
||||
spaceline: { width: 185, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "я в е р т ъ у и о п ю"
|
||||
- "а с д ф г х й к л ш щ"
|
||||
- "Shift_L з ь ц ж б н м ч BackSpace"
|
||||
- "show_numbers preferences space . Return"
|
||||
upper:
|
||||
- "Я В Е Р Т Ъ У И О П Ю"
|
||||
- "А С Д Ф Г Х Й К Л Ш Щ"
|
||||
- "Shift_L З Ь Ц Ж Б Н М Ч BackSpace"
|
||||
- "show_numbers preferences space , Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space Return"
|
||||
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
78
data/keyboards/br.yaml
Normal file
78
data/keyboards/br.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
spaceline: { width: 142, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l ç"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space , Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L Ç"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "à À á Á ã Ã â Â é É"
|
||||
- "show_symbols ê Ê í Í ó Ó ô Ô"
|
||||
- "show_letters õ Õ ú Ú ü Ü period BackSpace"
|
||||
symbols:
|
||||
- "@ # $ % - + ÷ × = ≠"
|
||||
- "( ) § & < > / * { }"
|
||||
- "show_numbers_from_symbols º \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "1ã"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "1ã"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
106
data/keyboards/cz+qwerty.yaml
Normal file
106
data/keyboards/cz+qwerty.yaml
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 52.67, height: 52 }
|
||||
spaceline: { width: 106, height: 52 }
|
||||
special: { width: 35.33, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences show_accents space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences show_upper_accents space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
accents:
|
||||
- "ä ě é ř ť ý ů í ó ö"
|
||||
- "á š ď ë ŕ ú ü ô ľ"
|
||||
- "accents_Shift_L ž ß č ç ñ ň ĺ BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
upper_accents:
|
||||
- "Ä Ě É Ř Ť Ý Ů Í Ó Ö"
|
||||
- "Á Š Ď Ë Ŕ Ú Ü Ô Ľ"
|
||||
- "accents_Shift_L Ž ẞ Č Ç Ñ Ň Ĺ BackSpace"
|
||||
- "show_letters preferences show_upper_accents space , . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
accents_Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "á"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "Á"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
106
data/keyboards/cz+qwerty_wide.yaml
Normal file
106
data/keyboards/cz+qwerty_wide.yaml
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 42 }
|
||||
altline: { width: 81, height: 42 }
|
||||
wide: { width: 81, height: 42 }
|
||||
spaceline: { width: 162, height: 42 }
|
||||
special: { width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences show_accents space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences show_upper_accents space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
accents:
|
||||
- "ä ě é ř ť ý ů í ó ö"
|
||||
- "á š ď ë ŕ ú ü ô ľ"
|
||||
- "accents_Shift_L ž ß č ç ñ ň ĺ BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
upper_accents:
|
||||
- "Ä Ě É Ř Ť Ý Ů Í Ó Ö"
|
||||
- "Á Š Ď Ë Ŕ Ú Ü Ô Ľ"
|
||||
- "accents_Shift_L Ž ẞ Č Ç Ñ Ň Ĺ BackSpace"
|
||||
- "show_letters preferences show_upper_accents space , . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
accents_Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "á"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "Á"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
106
data/keyboards/cz.yaml
Normal file
106
data/keyboards/cz.yaml
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 52.67, height: 52 }
|
||||
spaceline: { width: 106, height: 52 }
|
||||
special: { width: 35.33, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t z u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L y x c v b n m BackSpace"
|
||||
- "show_numbers preferences show_accents space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Z U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Y X C V B N M BackSpace"
|
||||
- "show_numbers preferences show_upper_accents space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
accents:
|
||||
- "ä ě é ř ť ž ů í ó ö"
|
||||
- "á š ď ë ŕ ú ü ô ľ"
|
||||
- "accents_Shift_L ý ß č ç ñ ň ĺ BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
upper_accents:
|
||||
- "Ä Ě É Ř Ť Ž Ů Í Ó Ö"
|
||||
- "Á Š Ď Ë Ŕ Ú Ü Ô Ľ"
|
||||
- "accents_Shift_L Ý ẞ Č Ç Ñ Ň Ĺ BackSpace"
|
||||
- "show_letters preferences show_upper_accents space , . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
accents_Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "á"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "Á"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
106
data/keyboards/cz_wide.yaml
Normal file
106
data/keyboards/cz_wide.yaml
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 42 }
|
||||
altline: { width: 81, height: 42 }
|
||||
wide: { width: 81, height: 42 }
|
||||
spaceline: { width: 162, height: 42 }
|
||||
special: { width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t z u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L y x c v b n m BackSpace"
|
||||
- "show_numbers preferences show_accents space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Z U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Y X C V B N M BackSpace"
|
||||
- "show_numbers preferences show_upper_accents space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
accents:
|
||||
- "ä ě é ř ť ž ů í ó ö"
|
||||
- "á š ď ë ŕ ú ü ô ľ"
|
||||
- "accents_Shift_L ý ß č ç ñ ň ĺ BackSpace"
|
||||
- "show_letters preferences show_accents space , . Return"
|
||||
upper_accents:
|
||||
- "Ä Ě É Ř Ť Ž Ů Í Ó Ö"
|
||||
- "Á Š Ď Ë Ŕ Ú Ü Ô Ľ"
|
||||
- "accents_Shift_L Ý ẞ Č Ç Ñ Ň Ĺ BackSpace"
|
||||
- "show_letters preferences show_upper_accents space , . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
accents_Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "á"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "base"
|
||||
outline: "special"
|
||||
label: "Á"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
@ -21,7 +21,7 @@ views:
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' : = < > BackSpace"
|
||||
- "show_symbols ; \" ' : = < > BackSpace"
|
||||
- "show_letters show_eschars preferences space , . Return"
|
||||
symbols:
|
||||
- "~ ` ´ | · √ µ ÷ × ¶"
|
||||
@ -45,7 +45,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
@ -21,7 +21,7 @@ views:
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # % & - _ + ( ) ß"
|
||||
- "show_symbols , \" ' : = < > BackSpace"
|
||||
- "show_symbols ; \" ' : = < > BackSpace"
|
||||
- "show_letters preferences space , . Return"
|
||||
symbols:
|
||||
- "~ ` ´ · © ® ÷ × ¶"
|
||||
@ -45,7 +45,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
98
data/keyboards/dk.yaml
Normal file
98
data/keyboards/dk.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 32, height: 52 }
|
||||
altline: { width: 48.39024, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
outline7: { width: 88.97561, height: 52 }
|
||||
spaceline: { width: 150.5853, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p å"
|
||||
- "a s d f g h j k l ø æ"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P Å"
|
||||
- "A S D F G H J K L Ø Æ"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space . Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' : ; ! ? BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
symbols:
|
||||
- "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }"
|
||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
".":
|
||||
outline: altline
|
||||
space:
|
||||
outline: spaceline
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
U00B7:
|
||||
text: "·"
|
||||
squareroot:
|
||||
text: "√"
|
||||
Greek_pi:
|
||||
text: "π"
|
||||
division:
|
||||
text: "÷"
|
||||
multiply:
|
||||
text: "×"
|
||||
paragraph:
|
||||
text: "¶"
|
||||
Greek_tau:
|
||||
text: "τ"
|
||||
copyright:
|
||||
text: "©"
|
||||
U00AE:
|
||||
text: "®"
|
||||
U00A3:
|
||||
text: "£"
|
||||
EuroSign:
|
||||
text: "€"
|
||||
U00A5:
|
||||
text: "¥"
|
||||
asciicircum:
|
||||
text: "^"
|
||||
degree:
|
||||
text: "°"
|
||||
@ -1,16 +1,80 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 52, height: 52 }
|
||||
altline: { width: 52, height: 52 }
|
||||
altline: { width: 40, height: 52 }
|
||||
narrow: { width: 22, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "😀 😁 😅 😂 😊 😇 🙃"
|
||||
- "😍 😘 😋 😜 😎 🥳 😔"
|
||||
- "😢 😭 😡 😱 🤔 😬 🙄"
|
||||
- "preferences 🤨 🤓 😴 🤢 🤮 😈"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
two:
|
||||
- "🤩 🤨 🤓 😴 🤢 🤮 😈"
|
||||
- "💩 🙌 👏 👍 👎 👌 👋"
|
||||
- "💪 🖕 🙏 💋 🤦♀️ 🤷♀️ 💃"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
three:
|
||||
- "🐶 🐱 🐯 🙈 🐴 🦄 🌳"
|
||||
- "🍀 🌹 💫 ⭐️ ✨ 💥 🔥"
|
||||
- "🌈 ☀️ 🌤 🌧 ⛄️ ☂️ 🌊"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
four:
|
||||
- "🍎 🍓 🍑 🍍 🍆 🥑 🥦"
|
||||
- "🍕 🎂 🍫 🍿 🍻 🍾 🍽"
|
||||
- "⚽️ 🏀 🏓 🏆 🎹 🎸 🎯"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
five:
|
||||
- "🚗 🚌 🚲 🚄 🚂 ✈️ 🛰"
|
||||
- "🚀 🛸 🚁 🚦 🏝 🏔 ⛺️"
|
||||
- "🏠 🏢 🏥 🏛 🛤 🌅 🎇"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
six:
|
||||
- "⌚️ 📱 💻 🖥 🖨 🕹 ✉️"
|
||||
- "📞 ☎️ ⏰ ⏳ 📈 📉 📌"
|
||||
- "🎁 ❤️ 💕 💯 ✅ ❎ 📢"
|
||||
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
|
||||
|
||||
buttons:
|
||||
1:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "1"
|
||||
2:
|
||||
action:
|
||||
set_view: "two"
|
||||
outline: "altline"
|
||||
label: "2"
|
||||
3:
|
||||
action:
|
||||
set_view: "three"
|
||||
outline: "altline"
|
||||
label: "3"
|
||||
4:
|
||||
action:
|
||||
set_view: "four"
|
||||
outline: "altline"
|
||||
label: "4"
|
||||
5:
|
||||
action:
|
||||
set_view: "five"
|
||||
outline: "altline"
|
||||
label: "5"
|
||||
6:
|
||||
action:
|
||||
set_view: "six"
|
||||
outline: "altline"
|
||||
label: "6"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: BackSpace
|
||||
blank:
|
||||
outline: "narrow"
|
||||
text: ""
|
||||
|
||||
81
data/keyboards/epo.yaml
Normal file
81
data/keyboards/epo.yaml
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
spaceline: { width: 99.67, height: 52 }
|
||||
special: { width: 35.33, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers show_eschars preferences space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers show_eschars preferences space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' : ; ! ? BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
eschars:
|
||||
- "ĉ ĝ ĥ ĵ ŝ ŭ ?"
|
||||
- "Ĉ Ĝ Ĥ Ĵ Ŝ Ŭ !"
|
||||
- "show_numbers ' - 🐊 💚 🌐 . BackSpace"
|
||||
- "show_letters show_eschars preferences space „ “ Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "ŭŜ"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
text: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
@ -44,7 +44,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "default"
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
|
||||
89
data/keyboards/fr.yaml
Normal file
89
data/keyboards/fr.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 59, height: 52 }
|
||||
spaceline: { width: 140, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "a z e r t y u i o p"
|
||||
- "q s d f g h j k l m"
|
||||
- "Shift_L w x c v b n . BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
upper:
|
||||
- "A Z E R T Y U I O P"
|
||||
- "Q S D F G H J K L M"
|
||||
- "Shift_L W X C V B N , BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
eschars:
|
||||
- "à â ç é è ê î ô ù û"
|
||||
- "À Â Ç É È Ê Î Ô Ù Û"
|
||||
- "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "âÂ"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
89
data/keyboards/fr_wide.yaml
Normal file
89
data/keyboards/fr_wide.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 42 }
|
||||
altline: { width: 81, height: 42 }
|
||||
wide: { width: 100, height: 42 }
|
||||
spaceline: { width: 205, height: 42 }
|
||||
special: { width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "a z e r t y u i o p"
|
||||
- "q s d f g h j k l m"
|
||||
- "Shift_L w x c v b n . BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
upper:
|
||||
- "A Z E R T Y U I O P"
|
||||
- "Q S D F G H J K L M"
|
||||
- "Shift_L W X C V B N , BackSpace"
|
||||
- "show_numbers preferences space show_eschars Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
eschars:
|
||||
- "à â ç é è ê î ô ù û"
|
||||
- "À Â Ç É È Ê Î Ô Ù Û"
|
||||
- "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace"
|
||||
- "show_letters preferences space show_eschars Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "âÂ"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
@ -46,7 +46,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
92
data/keyboards/it+fur.yaml
Normal file
92
data/keyboards/it+fur.yaml
Normal file
@ -0,0 +1,92 @@
|
||||
# Friulian layout created by Fabio Tomat
|
||||
# 14 october 2020
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
spaceline: { width: 99.67, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers show_eschars preferences space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers show_eschars preferences space “ ” Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! = BackSpace"
|
||||
- "show_letters show_eschars preferences space ? . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||
- "show_letters show_eschars preferences space ? . Return"
|
||||
eschars:
|
||||
- "â ê î ô û Â Ê Î Ô Û"
|
||||
- "à è ì ò ù À È Ì Ò Ù"
|
||||
- "show_numbers ç Ç ᶜ ᵐ ⁿ ᵉ ᵗ BackSpace"
|
||||
- "show_letters show_eschars preferences space ᶠ . Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "eschars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "àê"
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
text: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
@ -13,22 +13,22 @@ views:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers show_eschars preferences space , period Return"
|
||||
- "show_numbers show_eschars preferences space , . Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers show_eschars preferences space ? period Return"
|
||||
- "show_numbers show_eschars preferences space ? . Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters show_eschars preferences space ? period Return"
|
||||
- "show_letters show_eschars preferences space ? . Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||
- "show_letters show_eschars preferences space ? period Return"
|
||||
- "show_letters show_eschars preferences space ? . Return"
|
||||
eschars:
|
||||
- "á é í ó ú Á É Í Ó Ú"
|
||||
- "à è ì ò « » ù ! { }"
|
||||
@ -46,7 +46,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "default"
|
||||
@ -76,12 +76,10 @@ buttons:
|
||||
set_view: "eschars"
|
||||
outline: "altline"
|
||||
label: "àè"
|
||||
period:
|
||||
outline: "default"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
text: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
|
||||
@ -195,7 +195,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "wide"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
|
||||
@ -195,7 +195,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "wide"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
outlines:
|
||||
default: { width: 32, height: 52 }
|
||||
altline: { width: 48.39024, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
outline7: { width: 88.97561, height: 52 }
|
||||
spaceline: { width: 150.5853, height: 52 }
|
||||
wide: { width: 64, height: 52 }
|
||||
spaceline: { width: 142, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
@ -25,7 +25,7 @@ views:
|
||||
symbols:
|
||||
- "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }"
|
||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
|
||||
buttons:
|
||||
@ -39,20 +39,25 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: altline
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
@ -60,7 +65,7 @@ buttons:
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
".":
|
||||
outline: altline
|
||||
outline: "special"
|
||||
space:
|
||||
outline: spaceline
|
||||
text: " "
|
||||
|
||||
@ -16,14 +16,14 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
space:
|
||||
outline: spaceline
|
||||
text: " "
|
||||
Return:
|
||||
outline: outline7
|
||||
icon: "key-enter"
|
||||
keysym: "BackSpace"
|
||||
keysym: "Return"
|
||||
asterisk:
|
||||
text: "*"
|
||||
numbersign:
|
||||
|
||||
110
data/keyboards/pl.yaml
Normal file
110
data/keyboards/pl.yaml
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 59, height: 52 }
|
||||
spaceline: { width: 140, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space show_accents Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space show_upper_accents Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
accents:
|
||||
- "q w ę r t y u i ó p"
|
||||
- "ą ś d f g h j k ł"
|
||||
- "accents_show_upper ż ź ć v b ń m BackSpace"
|
||||
- "show_numbers preferences space show_accents Return"
|
||||
upper_accents:
|
||||
- "Q W Ę R T Y U I Ó P"
|
||||
- "Ą Ś D F G H J K Ł"
|
||||
- "accents_show_upper Ż Ź Ć V B Ń M BackSpace"
|
||||
- "show_numbers preferences space show_upper_accents Return"
|
||||
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
accents_show_upper:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "accents"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "ąę"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "upper"
|
||||
outline: "altline"
|
||||
label: "ĄĘ"
|
||||
period:
|
||||
outline: "altline"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
102
data/keyboards/pl_wide.yaml
Normal file
102
data/keyboards/pl_wide.yaml
Normal file
@ -0,0 +1,102 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 42 }
|
||||
altline: { width: 81, height: 42 }
|
||||
wide: { width: 100, height: 42 }
|
||||
spaceline: { width: 206, height: 42 }
|
||||
special: { width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space show_accents Return"
|
||||
upper:
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space show_upper_accents Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
accents:
|
||||
- "q w ę r t y u i ó p"
|
||||
- "ą ś d f g h j k ł"
|
||||
- "Shift_L ż ź ć v b ń m BackSpace"
|
||||
- "show_numbers preferences space show_accents Return"
|
||||
upper_accents:
|
||||
- "Q W Ę R T Y U I Ó P"
|
||||
- "Ą Ś D F G H J K Ł"
|
||||
- "Shift_L Ż Ź Ć V B Ń M BackSpace"
|
||||
- "show_numbers preferences space show_upper_accents Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accents"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "ąę"
|
||||
show_upper_accents:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper_accents"
|
||||
unlock_view: "upper"
|
||||
outline: "altline"
|
||||
label: "ĄĘ"
|
||||
period:
|
||||
outline: "altline"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
94
data/keyboards/ru.yaml
Normal file
94
data/keyboards/ru.yaml
Normal file
@ -0,0 +1,94 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 32, height: 52 }
|
||||
altline: { width: 32, height: 52 }
|
||||
wide: { width: 57, height: 52 }
|
||||
narrow: { width: 26, height: 52 }
|
||||
spaceline: { width: 107, height: 52 }
|
||||
fill: { width: 159, height: 52 }
|
||||
special: { width: 42, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "й ц у к е н г ш щ з х"
|
||||
- "ф ы в а п р о л д ж э"
|
||||
- "Shift_L я ч с м и т ь б ю BackSpace"
|
||||
- "show_numbers preferences ё space ъ period Return"
|
||||
upper:
|
||||
- "Й Ц У К Е Н Г Ш Щ З Х"
|
||||
- "Ф Ы В А П Р О Л Д Ж Э"
|
||||
- "Shift_L Я Ч С М И Т Ь Б Ю BackSpace"
|
||||
- "show_numbers preferences Ё space Ъ comma Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space_fill period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space_fill period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "АБВ"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "wide"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
text: "."
|
||||
comma:
|
||||
outline: "special"
|
||||
text: ","
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
space_fill:
|
||||
outline: "fill"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
ё:
|
||||
outline: "narrow"
|
||||
Ё:
|
||||
outline: "narrow"
|
||||
ъ:
|
||||
outline: "narrow"
|
||||
Ъ:
|
||||
outline: "narrow"
|
||||
@ -2,9 +2,10 @@
|
||||
outlines:
|
||||
default: { width: 32, height: 52 }
|
||||
altline: { width: 48.39024, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
outline7: { width: 88.97561, height: 52 }
|
||||
spaceline: { width: 150.5853, height: 52 }
|
||||
wide: { width: 64, height: 52 }
|
||||
spaceline: { width: 142, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
|
||||
views:
|
||||
base:
|
||||
@ -25,7 +26,7 @@ views:
|
||||
symbols:
|
||||
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
|
||||
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
|
||||
- "show_numbers_from_symbols backslash slash less greater equal bracketleft bracketright BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
|
||||
buttons:
|
||||
@ -37,22 +38,27 @@ buttons:
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
outline: altline
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
outline: "wide"
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: altline
|
||||
label: "123"
|
||||
show_letters:
|
||||
outline: "wide"
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
@ -60,7 +66,7 @@ buttons:
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
".":
|
||||
outline: altline
|
||||
outline: "special"
|
||||
space:
|
||||
outline: spaceline
|
||||
text: " "
|
||||
@ -156,4 +162,3 @@ buttons:
|
||||
text: "["
|
||||
bracketright:
|
||||
text: "]"
|
||||
|
||||
|
||||
@ -1,38 +1,44 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
action: { width: 59, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 59, height: 52 }
|
||||
spaceline: { width: 140, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
default: { width: 35.33, height: 46 }
|
||||
action: { width: 59, height: 46 }
|
||||
altline: { width: 52.67, height: 46 }
|
||||
wide: { width: 59, height: 46 }
|
||||
spaceline: { width: 140, height: 46 }
|
||||
special: { width: 44, height: 46 }
|
||||
small: { width: 59, height: 22 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "Ctrl Alt ↑ ↓ ← →"
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers show_actions space preferences Return"
|
||||
- "show_numbers preferences space show_actions Return"
|
||||
upper:
|
||||
- "Ctrl Alt PgUp PgDn Home End"
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
- "show_numbers preferences space show_actions Return"
|
||||
numbers:
|
||||
- "Ctrl Alt ↑ ↓ ← →"
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "* # $ / & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "Ctrl Alt ↑ ↓ ← →"
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "© ® £ € ¥ ^ ° @ { }"
|
||||
- "show_numbers_from_symbols \\ % < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
actions:
|
||||
- "Ctrl Alt PgUp PgDn Home End"
|
||||
- "F1 F2 F3 F4 F5 F6"
|
||||
- "F7 F8 F9 F10 F11 F12"
|
||||
- "Esc Tab Del PgUp ↑ PgDn"
|
||||
- "show_letters Home End ← ↓ →"
|
||||
- "Esc Tab Pause Insert Up Del"
|
||||
- "show_letters Menu Break Left Down Right"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
@ -45,7 +51,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
@ -69,14 +75,14 @@ buttons:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
label: "τ=\\"
|
||||
show_actions:
|
||||
action:
|
||||
set_view: "actions"
|
||||
outline: "altline"
|
||||
label: ">_"
|
||||
period:
|
||||
outline: "special"
|
||||
outline: "altline"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
@ -132,28 +138,67 @@ buttons:
|
||||
Del:
|
||||
outline: "action"
|
||||
keysym: "Delete"
|
||||
Home:
|
||||
Insert:
|
||||
outline: "action"
|
||||
keysym: "Insert"
|
||||
Menu:
|
||||
outline: "action"
|
||||
keysym: "Menu"
|
||||
Pause:
|
||||
outline: "action"
|
||||
keysym: "Pause"
|
||||
Menu:
|
||||
outline: "action"
|
||||
keysym: "Menu"
|
||||
Break:
|
||||
outline: "action"
|
||||
keysym: "Break"
|
||||
Home:
|
||||
outline: "small"
|
||||
keysym: "Home"
|
||||
End:
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "End"
|
||||
PgUp:
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "Page_Up"
|
||||
PgDn:
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "Page_Down"
|
||||
"↑":
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "Up"
|
||||
"↓":
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "Down"
|
||||
"←":
|
||||
outline: "action"
|
||||
outline: "small"
|
||||
keysym: "Left"
|
||||
"→":
|
||||
outline: "small"
|
||||
keysym: "Right"
|
||||
Up:
|
||||
label: "↑"
|
||||
outline: "action"
|
||||
keysym: "Up"
|
||||
Left:
|
||||
label: "←"
|
||||
outline: "action"
|
||||
keysym: "Left"
|
||||
Down:
|
||||
label: "↓"
|
||||
outline: "action"
|
||||
keysym: "Down"
|
||||
Right:
|
||||
label: "→"
|
||||
outline: "action"
|
||||
keysym: "Right"
|
||||
Ctrl:
|
||||
modifier: "Control"
|
||||
outline: "small"
|
||||
label: "Ctrl"
|
||||
Alt:
|
||||
modifier: "Alt"
|
||||
outline: "small"
|
||||
label: "Alt"
|
||||
|
||||
|
||||
211
data/keyboards/terminal_wide.yaml
Normal file
211
data/keyboards/terminal_wide.yaml
Normal file
@ -0,0 +1,211 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 54, height: 37 }
|
||||
action: { width: 90, height: 37 }
|
||||
altline: { width: 81, height: 37 }
|
||||
wide: { width: 90, height: 37 }
|
||||
spaceline: { width: 225, height: 37 }
|
||||
special: { width: 54, height: 37 }
|
||||
small: { width: 67.4, height: 22 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →"
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space show_actions Return"
|
||||
upper:
|
||||
- "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End"
|
||||
- "Q W E R T Y U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Z X C V B N M BackSpace"
|
||||
- "show_numbers preferences space show_actions Return"
|
||||
numbers:
|
||||
- "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →"
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "* # $ / & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →"
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° @ { }"
|
||||
- "show_numbers_from_symbols \\ % < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
actions:
|
||||
- "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End"
|
||||
- "F1 F2 F3 F4 F5 F6"
|
||||
- "F7 F8 F9 F10 F11 F12"
|
||||
- "Esc Tab Pause Insert Up Del"
|
||||
- "show_letters Menu Break Left Down Right"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "τ=\\"
|
||||
show_actions:
|
||||
action:
|
||||
set_view: "actions"
|
||||
outline: "altline"
|
||||
label: ">_"
|
||||
period:
|
||||
outline: "altline"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
F1:
|
||||
outline: "action"
|
||||
keysym: "F1"
|
||||
F2:
|
||||
outline: "action"
|
||||
keysym: "F2"
|
||||
F3:
|
||||
outline: "action"
|
||||
keysym: "F3"
|
||||
F4:
|
||||
outline: "action"
|
||||
keysym: "F4"
|
||||
F5:
|
||||
outline: "action"
|
||||
keysym: "F5"
|
||||
F6:
|
||||
outline: "action"
|
||||
keysym: "F6"
|
||||
F7:
|
||||
outline: "action"
|
||||
keysym: "F7"
|
||||
F8:
|
||||
outline: "action"
|
||||
keysym: "F8"
|
||||
F9:
|
||||
outline: "action"
|
||||
keysym: "F9"
|
||||
F10:
|
||||
outline: "action"
|
||||
keysym: "F10"
|
||||
F11:
|
||||
outline: "action"
|
||||
keysym: "F11"
|
||||
F12:
|
||||
outline: "action"
|
||||
keysym: "F12"
|
||||
Esc:
|
||||
outline: "action"
|
||||
keysym: "Escape"
|
||||
EscSmall:
|
||||
outline: "small"
|
||||
keysym: "Escape"
|
||||
label: "Esc"
|
||||
Tab:
|
||||
outline: "action"
|
||||
keysym: "Tab"
|
||||
TabSmall:
|
||||
outline: "small"
|
||||
keysym: "Tab"
|
||||
label: "Tab"
|
||||
Del:
|
||||
outline: "action"
|
||||
keysym: "Delete"
|
||||
Insert:
|
||||
outline: "action"
|
||||
keysym: "Insert"
|
||||
Menu:
|
||||
outline: "action"
|
||||
keysym: "Menu"
|
||||
Pause:
|
||||
outline: "action"
|
||||
keysym: "Pause"
|
||||
Menu:
|
||||
outline: "action"
|
||||
keysym: "Menu"
|
||||
Break:
|
||||
outline: "action"
|
||||
keysym: "Break"
|
||||
Home:
|
||||
outline: "small"
|
||||
keysym: "Home"
|
||||
End:
|
||||
outline: "small"
|
||||
keysym: "End"
|
||||
PgUp:
|
||||
outline: "small"
|
||||
keysym: "Page_Up"
|
||||
PgDn:
|
||||
outline: "small"
|
||||
keysym: "Page_Down"
|
||||
"↑":
|
||||
outline: "small"
|
||||
keysym: "Up"
|
||||
"↓":
|
||||
outline: "small"
|
||||
keysym: "Down"
|
||||
"←":
|
||||
outline: "small"
|
||||
keysym: "Left"
|
||||
"→":
|
||||
outline: "small"
|
||||
keysym: "Right"
|
||||
Up:
|
||||
label: "↑"
|
||||
outline: "action"
|
||||
keysym: "Up"
|
||||
Left:
|
||||
label: "←"
|
||||
outline: "action"
|
||||
keysym: "Left"
|
||||
Down:
|
||||
label: "↓"
|
||||
outline: "action"
|
||||
keysym: "Down"
|
||||
Right:
|
||||
label: "→"
|
||||
outline: "action"
|
||||
keysym: "Right"
|
||||
Ctrl:
|
||||
modifier: "Control"
|
||||
outline: "small"
|
||||
label: "Ctrl"
|
||||
Alt:
|
||||
modifier: "Alt"
|
||||
outline: "small"
|
||||
label: "Alt"
|
||||
80
data/keyboards/th.yaml
Normal file
80
data/keyboards/th.yaml
Normal file
@ -0,0 +1,80 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
spaceline: { width: 142, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "ๅ / _ ภ ถ ุ ึ ค ต จ ข ช"
|
||||
- "ๆ ไ ำ พ ะ ั ี ร น ย บ ล"
|
||||
- "ฟ ห ก ด เ ้ ่ า ส ว ง ฃ"
|
||||
- "Shift_L ผ ป แ อ ิ ื ท ม ใ ฝ BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
upper:
|
||||
- "+ ๑ ๒ ๓ ๔ ู ฿ ๕ ๖ ๗ ๘ ๙"
|
||||
- "๐ \" ฎ ฑ ธ ํ ๊ ณ ฯ ญ ฐ ,"
|
||||
- "ฤ ฆ ฏ โ ฌ ็ ๋ ษ ศ ซ . ฅ"
|
||||
- "Shift_L ( ) ฉ ฮ ฺ ์ ? ฒ ฬ ฦ BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "กขค"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
94
data/keyboards/ua.yaml
Normal file
94
data/keyboards/ua.yaml
Normal file
@ -0,0 +1,94 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 32, height: 52 }
|
||||
altline: { width: 32, height: 52 }
|
||||
wide: { width: 57, height: 52 }
|
||||
narrow: { width: 26, height: 52 }
|
||||
spaceline: { width: 107, height: 52 }
|
||||
fill: { width: 159, height: 52 }
|
||||
special: { width: 42, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "й ц у к е н г ш щ з х"
|
||||
- "ф і в а п р о л д ж є"
|
||||
- "Shift_L я ч с м и т ь б ю BackSpace"
|
||||
- "show_numbers preferences ґ space ї period Return"
|
||||
upper:
|
||||
- "Й Ц У К Е Н Г Ш Щ З Х"
|
||||
- "Ф І В А П Р О Л Д Ж Є"
|
||||
- "Shift_L Я Ч С М И Т Ь Б Ю BackSpace"
|
||||
- "show_numbers preferences Ґ space Ї comma Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space_fill period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space_fill period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "АБВ"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "wide"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
text: "."
|
||||
comma:
|
||||
outline: "special"
|
||||
text: ","
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
space_fill:
|
||||
outline: "fill"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
ґ:
|
||||
outline: "narrow"
|
||||
Ґ:
|
||||
outline: "narrow"
|
||||
ї:
|
||||
outline: "narrow"
|
||||
Ї:
|
||||
outline: "narrow"
|
||||
78
data/keyboards/us+colemak.yaml
Normal file
78
data/keyboards/us+colemak.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
outlines:
|
||||
default: { width: 35.33, height: 52 }
|
||||
altline: { width: 52.67, height: 52 }
|
||||
wide: { width: 62, height: 52 }
|
||||
spaceline: { width: 142, height: 52 }
|
||||
special: { width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w f p g j l u y"
|
||||
- "a r s t d h n e i o"
|
||||
- "Shift_L z x c v b k m BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
upper:
|
||||
- "Q W F P G J L U Y"
|
||||
- "A R S T D H N E I O"
|
||||
- "Shift_L Z X C V B K M BackSpace"
|
||||
- "show_numbers preferences space period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
action: erase
|
||||
preferences:
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
text: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
text: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
keysym: "Return"
|
||||
colon:
|
||||
text: ":"
|
||||
@ -39,9 +39,9 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
13
data/langs/bg-BG.txt
Normal file
13
data/langs/bg-BG.txt
Normal file
@ -0,0 +1,13 @@
|
||||
bg Български
|
||||
de Немски
|
||||
es Испански
|
||||
emoji Емоджи
|
||||
fi Френски
|
||||
gr Гръцки
|
||||
it Италянски
|
||||
no Норевежки
|
||||
pl Полски
|
||||
ru Руски
|
||||
se Шведски
|
||||
terminal Терминал
|
||||
us Английски (САЩ)
|
||||
21
data/langs/cs-CZ.txt
Normal file
21
data/langs/cs-CZ.txt
Normal file
@ -0,0 +1,21 @@
|
||||
be Belgická
|
||||
cz Česká
|
||||
cz+qwerty Česká (QWERTY)
|
||||
de Německá
|
||||
dk Dánská
|
||||
emoji Emoji
|
||||
es Španělská
|
||||
fi Finská
|
||||
fr Francouzská
|
||||
gr Řecká
|
||||
it Italská
|
||||
jp Japonská
|
||||
jp+kana Japonská (Kana)
|
||||
no Norská
|
||||
pl Polská
|
||||
ru Ruská
|
||||
se Švédská
|
||||
terminal Terminál
|
||||
th Thajská
|
||||
ua Ukrajinská
|
||||
us Anglická (USA)
|
||||
@ -1,8 +0,0 @@
|
||||
us Englisch (US)
|
||||
de Deutsch
|
||||
el Griechisch
|
||||
es Spanisch
|
||||
it Italienisch
|
||||
jp+kana Japanisch (Kana)
|
||||
no Norwegisch
|
||||
|
||||
|
||||
@ -1,10 +1,2 @@
|
||||
us English (US)
|
||||
de German
|
||||
el Greek
|
||||
es Spanish
|
||||
fi Finnish
|
||||
it Italian
|
||||
jp+kana Japanese (kana)
|
||||
no Norwegian
|
||||
se Swedish
|
||||
|
||||
emoji Emoji
|
||||
terminal Terminal
|
||||
|
||||
18
data/langs/fur-IT.txt
Normal file
18
data/langs/fur-IT.txt
Normal file
@ -0,0 +1,18 @@
|
||||
be Belgjic
|
||||
br Brasilian
|
||||
de Todesc
|
||||
dk Danês
|
||||
es Spagnûl
|
||||
fi Finlandês
|
||||
fr Francês
|
||||
it+fur Furlan
|
||||
gr Grêc
|
||||
it Talian
|
||||
jp+kana Gjaponês (Kana)
|
||||
no Norvegjês
|
||||
pl Polac
|
||||
ru Rus
|
||||
se Svedês
|
||||
terminal Terminâl
|
||||
ua Ucrain
|
||||
us American (USA)
|
||||
@ -1,8 +0,0 @@
|
||||
us 英語 (US)
|
||||
de ドイツ語
|
||||
el ギリシャ語
|
||||
es スペイン語
|
||||
it イタリア語
|
||||
jp+kana 日本語 (かな)
|
||||
nb ノルウェー語
|
||||
|
||||
|
||||
@ -1,9 +1,2 @@
|
||||
us angielski (USA)
|
||||
de niemiecki
|
||||
el grecki
|
||||
es hiszpański
|
||||
fi fiński
|
||||
it włoski
|
||||
jp+kana japoński (kana)
|
||||
no norweski
|
||||
se szwedzki
|
||||
emoji emoji
|
||||
terminal terminal
|
||||
|
||||
11
data/langs/ru-RU.txt
Normal file
11
data/langs/ru-RU.txt
Normal file
@ -0,0 +1,11 @@
|
||||
de Немецкий
|
||||
es Испанский
|
||||
fi Финский
|
||||
gr Греческий
|
||||
it Итальянский
|
||||
no Норвежский
|
||||
pl Польский
|
||||
ru Русский
|
||||
se Шведский
|
||||
terminal Терминал
|
||||
us Английский (США)
|
||||
@ -7,13 +7,20 @@ squeekboard_resources = gnome.compile_resources(
|
||||
c_name: 'squeekboard',
|
||||
)
|
||||
|
||||
desktopconf = configuration_data()
|
||||
desktopconf.set('bindir', bindir)
|
||||
|
||||
desktop_file = 'sm.puri.Squeekboard.desktop'
|
||||
|
||||
i18n.merge_file('desktop',
|
||||
input: desktop_file + '.in',
|
||||
input: configure_file(
|
||||
input: desktop_file + '.in.in',
|
||||
output: desktop_file + '.in',
|
||||
configuration: desktopconf
|
||||
),
|
||||
output: desktop_file,
|
||||
po_dir: '../po',
|
||||
install: true,
|
||||
install_dir: join_paths(datadir, 'applications'),
|
||||
install_dir: desktopdir,
|
||||
type: 'desktop'
|
||||
)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
Name=Squeekboard
|
||||
GenericName=Squeekboard Virtual Keyboard
|
||||
Comment=Virtual Keyboard
|
||||
Exec=squeekboard
|
||||
Exec=@bindir@/squeekboard
|
||||
Terminal=false
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
@ -2,6 +2,7 @@ sq_view {
|
||||
background-color: rgba(0, 0, 0, 255);
|
||||
color: #ffffff;
|
||||
font-family: cantarell, sans-serif;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
sq_view sq_button {
|
||||
@ -35,6 +36,14 @@ sq_button.locked {
|
||||
color: #2b292f;
|
||||
}
|
||||
|
||||
sq_button.action {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
sq_button.small {
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
#Return {
|
||||
background: #1c71d8;
|
||||
border-color: #1a5fb4;
|
||||
|
||||
@ -2,6 +2,7 @@ sq_view {
|
||||
background-color: @theme_base_color; /*rgba(0, 0, 0, 255);*/
|
||||
color: @theme_text_color; /*#ffffff;*/
|
||||
font-family: cantarell, sans-serif;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
sq_view sq_button {
|
||||
@ -38,6 +39,14 @@ sq_button.locked {
|
||||
color: @theme_bg_color; /*#2b292f;*/
|
||||
}
|
||||
|
||||
sq_button.action {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
sq_button.small {
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
#Return {
|
||||
background: @theme_selected_bg_color; /* #1c71d8; */
|
||||
border-color: @borders; /*#1a5fb4;*/
|
||||
|
||||
310
debian/changelog
vendored
310
debian/changelog
vendored
@ -1,3 +1,313 @@
|
||||
squeekboard (1.11.1) amber-phone; urgency=medium
|
||||
|
||||
[ Mark Müller ]
|
||||
* keyboard: Fix semicolon in German layout
|
||||
* keyboard: Move semicolon in German layout to numbers view replacing redundant comma key
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* imservice: Set up UI according to current needs when it shows up
|
||||
* UI: Keep visibility factors in a central place
|
||||
* cargo: Update deps
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Sat, 21 Nov 2020 11:08:06 +0000
|
||||
|
||||
squeekboard (1.11.0) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* UI: Delay hiding only when leaving a text field
|
||||
* ui: Cancel hiding delay when activity requested again
|
||||
* Update dependencies
|
||||
|
||||
[ Fabio Tomat ]
|
||||
* Update fur-IT.txt fix typo for Spanish
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Sat, 14 Nov 2020 06:46:28 +0000
|
||||
|
||||
squeekboard (1.10.0) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* virtual_keyboard: Fix desynced modifiers state
|
||||
* rust: Fix deprecation warnings
|
||||
* docs: Tutorial syntax cleanups
|
||||
* docs: Reorganize tutorial
|
||||
* build: Error on repeating declarations
|
||||
* keymap: Generate from symbol map, not layout
|
||||
* data: Restore testability of action->keysym conversion
|
||||
* syntax: Let older rustc understand symbolmap's lifetime
|
||||
* debian: Insert a "breaks" for librem5-base < 24
|
||||
* keymap: Keep keymap fd management in one place
|
||||
* vkeyboard: Use a generic slice instead of a vector
|
||||
* tests: Check for missing return in builtin layouts except emoji
|
||||
* keymap: Concentrate special handling of BackSpace, which is implicit in Erase action
|
||||
* keymaps: Use multiple key maps, each within the limit of what Xorg can accept.
|
||||
* build: Avoid MaybeUninit on older Debian
|
||||
* tests: Fix bad field access
|
||||
* cargo: Update dependencies
|
||||
|
||||
[ Guido Günther ]
|
||||
* eekboard-context-service: Return early if schema is unavailable
|
||||
* treewide: Use new style function definitions
|
||||
* build: Enable '-Wold-style-definition' '-Wstrict-prototypes'
|
||||
* build: Enable '-Wunused-function'
|
||||
* eekboard-context-service: Drop EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE
|
||||
* keyboard: Fix warning
|
||||
* layout: Fix warning
|
||||
* gitlab-ci: Enable --Werror
|
||||
* eek-keyboard: Don't ignore return value
|
||||
* build: Enable -Winit-self
|
||||
* build: Enable -Wformat-security
|
||||
* build: Enable -Wmaybe-uninitialized
|
||||
* treewide: Drop redundant declarations
|
||||
* build: Enable -Wredundant-declarations
|
||||
* ServerContextService: Drop GObject boilerplate
|
||||
* build: Enable '-Wformat-nonliteral'
|
||||
* eekboad-context-service: Drop signal class handler
|
||||
* eekboard-context-service: Drop docstrings for inexistent functions
|
||||
* eekboard-context-service: Drop the GObject boilerplate
|
||||
* eekboard-context-service: Drop private struct
|
||||
* server-context-service: Consistenty name self argument 'self'
|
||||
* server-context-service: swap signal arguments
|
||||
* server-context-service: Don't show keyboard when disabled (Closes: #222)
|
||||
|
||||
[ Nazarii Kretovych ]
|
||||
* Add Ukrainian keyboard layout.
|
||||
|
||||
[ Benjamin Schaaf ]
|
||||
* Fix spelling mistakes in doc/hacking.md
|
||||
* Expand the development documentation in the readme
|
||||
* Expand key press detection to the edges of the view's bounding box
|
||||
* Sort layouts by type before sorting by name
|
||||
* Fix leak in level_keyboard_new
|
||||
* Fix leak endlessly adding a resource path to the default theme
|
||||
* Add settings option to popover
|
||||
|
||||
[ Al ]
|
||||
* proposal for belgian layout (copy of fr)
|
||||
* alphabetical order for src/resources.rs tests/meson.build
|
||||
|
||||
[ Arnaud Ferraris ]
|
||||
* eek-gtk-keyboard: use virtual resolution to check arrangement kind
|
||||
* server-context-service: optimize height calculation
|
||||
* keyboards: add wide French layout
|
||||
* keyboards: add wide Belgian layout
|
||||
* keyboards: add wide terminal layout
|
||||
|
||||
[ Fabio Tomat ]
|
||||
* Revert "Add friulian keyboard"
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Mon, 19 Oct 2020 14:07:01 +0000
|
||||
|
||||
squeekboard (1.9.3) amber-phone; urgency=medium
|
||||
|
||||
[ Björn Tantau ]
|
||||
* Show more useful keys at the same time.
|
||||
* Add Ctrl and Alt modifier keys.
|
||||
* Add missing Ê key.
|
||||
* Make f-keys slightly wider.
|
||||
* Add Menu key.
|
||||
|
||||
[ Guido Günther ]
|
||||
* d/rules: Only remove Cargo.lock if it exists
|
||||
* eek: Drop libcanberra usage
|
||||
* debian: Build-depend on libfeedback
|
||||
* eek-gtk-keyboard: Trigger event feedback on button press (Closes: #166)
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* build: Add missing gio-unix dependency
|
||||
* build: Make compatible with Debian Bullseye
|
||||
* debian: Add amber to legacy distro list
|
||||
* ci: Add amber job
|
||||
* debian: Require lsb-release
|
||||
* size: Hardcode size to work around screen rotation
|
||||
* ci: Re-add x64 Buster build
|
||||
* italian: Fix space and period
|
||||
|
||||
[ Sebastian Krzyszkowiak ]
|
||||
* Revert "Merge branch 'btantau-master-patch-76686' into 'master'"
|
||||
* Terminal layout: another approach
|
||||
|
||||
[ Luís Fernando Stürmer da Rosa ]
|
||||
* Brazilian Portuguese Keyboard Layout.
|
||||
|
||||
-- Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm> Wed, 05 Aug 2020 16:16:08 +0200
|
||||
|
||||
squeekboard (1.9.2) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* keyboard: Remove unused code
|
||||
* gsettings: Don't crash when unavailable
|
||||
* dbus: Don't crash if can't make a connection
|
||||
* gsettings: Don't crash on switching when unavailable
|
||||
* layout: Split out choice to a struct on its own
|
||||
* renderer: Simplify by dropping gobjectness
|
||||
* levelkeyboard: Rearrange to make future conversion easier
|
||||
* layout: Minor generalizations
|
||||
* Remove unused code
|
||||
* sizing: Create a standalone UI shape manager
|
||||
* sizing: Ignore scaling factor for layout selection
|
||||
* CI: Fix typo
|
||||
* Update rust deps for release
|
||||
|
||||
[ Andreas Rönnquist ]
|
||||
* Swedish keyboard, wide button switching between numbers, symbols and base
|
||||
* More fixes of button sizes
|
||||
* Folder is doc, not docs
|
||||
|
||||
[ uzanto ]
|
||||
* Add new file
|
||||
* Replace duplicated show_symbols by show_eschars and removed "Delete" button that it's doing nothing
|
||||
|
||||
[ Arnaud Ferraris ]
|
||||
* keyboards: fr: fix keyboard layout
|
||||
* keyboards: fr: make sure the layout fits the screen
|
||||
* resources: include French keyboard layout
|
||||
* keyboards: fr: improve consistency with other layouts
|
||||
* keyboards: fr: improve diacritics layout
|
||||
* tests: add french layout
|
||||
|
||||
[ Vlad ]
|
||||
* Fresh Russian layout
|
||||
|
||||
[ Jordi Masip ]
|
||||
* Removed unused dependency 'libcroco'
|
||||
|
||||
[ Florian Klink ]
|
||||
* sm.puri.Squeekboard.desktop: make path to Exec= absolute
|
||||
|
||||
[ Ole Guldberg ]
|
||||
* Danish keyboard layout
|
||||
* Danish keyboard layout
|
||||
* add test for danish layout
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Mon, 01 Jun 2020 09:39:12 +0000
|
||||
|
||||
squeekboard (1.9.1) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* layout: Improve press handling
|
||||
* settings: Handle empty settings
|
||||
* Variant: Use proper pointer conversion between C and Rust
|
||||
* meta: Add doap file
|
||||
* modifiers: Support Control and Alt
|
||||
* CI: Test that any bump to changelog has a corresponding tag
|
||||
* docs: Add the guiding principle
|
||||
* hacking: Move into docs/
|
||||
|
||||
[ &t ]
|
||||
* Fix minor comment typos
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* cargo: Bump package versions before release
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Sun, 08 Mar 2020 10:04:29 +0000
|
||||
|
||||
squeekboard (1.9.0) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* imservice: Add commit_string method
|
||||
* submission: Handle submitting strings
|
||||
* input_method: Use for erasing
|
||||
* logging: Use in merged functions
|
||||
* translations: Remove redundant ones
|
||||
* translations: Translate builtin layouts
|
||||
* greek: Rename to gr which is used by gnome settings
|
||||
|
||||
[ Sebastian Krzyszkowiak ]
|
||||
* layouts: Add Polish layouts
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* locks: Draw based on current view
|
||||
* locking: Lock keys statelessly
|
||||
* layouts: Better accented uppercase in PL
|
||||
* emoji: Add more choices
|
||||
* row: Eliminate angle
|
||||
* layout: Center views relative to each other and the layout bounds
|
||||
* drawing: Generalized foreach_visible_button
|
||||
* variant: Fix double-free
|
||||
* variant: Fix leak
|
||||
* keyboard_layout: Fix leak
|
||||
* layout: Improve scoping of locked variable
|
||||
* terminal: Make */ easier to reach
|
||||
|
||||
[ Sebastian Krzyszkowiak ]
|
||||
* layouts: terminal: Use altline outline for dot key
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* text input: Disable erasing
|
||||
* cargo: Update deps
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 19 Feb 2020 14:32:39 +0000
|
||||
|
||||
squeekboard (1.8.1) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* action: Rename Level to View
|
||||
* keyboard: Introduce a KeyCode type wrapping u32
|
||||
* layout: Centralize handling key releases
|
||||
* layout: Make handling presses uniform
|
||||
* UI: Drop indirection for show/hide functions
|
||||
* managers: Move visible flag to UI manager
|
||||
* dbus_service: Remove unused function
|
||||
* dbus: Remove unneeded gobjectness
|
||||
* dbus: Rename handler from eekboard_service
|
||||
* context: Moved keymap setting together with its generation
|
||||
* key-emitter: Remove unused
|
||||
* eekboard_context_service: Drop unused enable property
|
||||
* services: Split out layout management from EekboardContextService
|
||||
* submission: Move away from virtual-keyboard
|
||||
* submission: Create a new wrapper over imservice
|
||||
* imservice: Limited scope of unsafe
|
||||
* EekGtkKeyboard: Use a direct reference to EekboardContext
|
||||
* submission: Take over virtual_keyboard handling
|
||||
* keyboard: Cleanups of unused code
|
||||
* levelkeyboard: Drop unused manager references
|
||||
* keyboard: Gather up keymap handling, drop layout
|
||||
* submission: Remove wildcard reexport
|
||||
* imservice: Rename commit_state to done to match protocol
|
||||
* ci: Clean up `..` before it's searched for artifacts
|
||||
* dbus: Log error on dbus exit
|
||||
* logging: Try to improve common operations
|
||||
* imservice: Return something more resembling an Error on failure
|
||||
* logging: Unified to remove random eprint calls
|
||||
* press_key: Use proper logging
|
||||
* number: Fix keysym for Return
|
||||
* build: Strip clap of optional features
|
||||
* layouts: Fix segfault on switching to wide
|
||||
* font: Use font from style context
|
||||
* font: Only pass relevant data to label renderer
|
||||
|
||||
[ Sebastian Krzyszkowiak ]
|
||||
* layout: terminal: Swap positions of preferences and actions button
|
||||
* layout: terminal: Show actions button on all views
|
||||
* layout: terminal: Replace actions button with period on symbols view
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* setup: Connect ui to the state manager
|
||||
* debian: Add missing commas
|
||||
|
||||
[ David Boddie ]
|
||||
* Tidy build file and docs
|
||||
* Use pip to install recommonmark
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Fri, 31 Jan 2020 09:59:12 +0000
|
||||
|
||||
squeekboard (1.8.0) amber-phone; urgency=medium
|
||||
|
||||
[ Dorota Czaplejewicz ]
|
||||
* translations: Use gnome-desktop's xkb info database for layout names
|
||||
* translations: Make the code cleaner
|
||||
* overlay: Add terminal
|
||||
* eek-layout: Remove unused
|
||||
* pre-release: Update deps
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Tue, 14 Jan 2020 13:55:00 +0000
|
||||
|
||||
squeekboard (1.7.0) amber-phone; urgency=medium
|
||||
|
||||
* New terminal layout appearing on terminal input hint
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 08 Jan 2020 11:53:07 +0000
|
||||
|
||||
squeekboard (1.7.0) amber-phone; urgency=medium
|
||||
|
||||
* New terminal layout appearing on terminal input hint
|
||||
|
||||
10
debian/check_release.py
vendored
Executable file
10
debian/check_release.py
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Checks tag before release.
|
||||
Feed it the first changelog line, and then all available tags.
|
||||
"""
|
||||
|
||||
import re, sys
|
||||
tag = "v" + re.findall("\\((.*)\\)", input())[0]
|
||||
if tag not in map(str.strip, sys.stdin.readlines()):
|
||||
raise Exception("Changelog's current version doesn't have a tag. Push the tag!")
|
||||
15
debian/control
vendored
15
debian/control
vendored
@ -9,8 +9,9 @@ Build-Depends:
|
||||
ninja-build,
|
||||
pkg-config,
|
||||
libglib2.0-dev,
|
||||
libgnome-desktop-3-dev,
|
||||
libgtk-3-dev,
|
||||
libcroco3-dev,
|
||||
libfeedback-dev,
|
||||
librust-bitflags-1-dev (>= 1.0),
|
||||
librust-clap-2+default-dev (>= 2.32),
|
||||
librust-gio+v2-44-dev,
|
||||
@ -24,6 +25,8 @@ Build-Depends:
|
||||
librust-serde-yaml-0.8-dev (>= 0.8),
|
||||
librust-xkbcommon-0.4+wayland-dev (>= 0.4),
|
||||
libwayland-dev (>= 1.16),
|
||||
lsb-release,
|
||||
python3,
|
||||
rustc,
|
||||
wayland-protocols (>= 1.14),
|
||||
Standards-Version: 4.1.3
|
||||
@ -34,8 +37,10 @@ Architecture: linux-any
|
||||
Depends:
|
||||
# for the Adwaita-dark theme
|
||||
gnome-themes-extra-data,
|
||||
${shlibs:Depends}
|
||||
${misc:Depends}
|
||||
${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
Breaks:
|
||||
librem5-base (<< 24),
|
||||
Description: On-screen keyboard for Wayland
|
||||
Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.
|
||||
|
||||
@ -44,8 +49,8 @@ Architecture: linux-any
|
||||
Depends:
|
||||
python3,
|
||||
python3-gi,
|
||||
${shlibs:Depends}
|
||||
${misc:Depends}
|
||||
${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
Description: Resources for making Squeekboard layouts
|
||||
Tools for creating and testing Squeekboard layouts:
|
||||
.
|
||||
|
||||
34
debian/rules
vendored
34
debian/rules
vendored
@ -2,14 +2,42 @@
|
||||
|
||||
export CARGO_HOME = $(CURDIR)/debian/cargo
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
# the below avoids an FTBFS on mips64el with a GOT > 64kb
|
||||
DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
|
||||
ifeq ($(DEB_HOST_ARCH),mips64el)
|
||||
export RUSTFLAGS = -Ctarget-feature=+xgot
|
||||
endif
|
||||
|
||||
# the below avoids an FTBFS on mips64el with a GOT > 64kb
|
||||
DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
|
||||
ifeq ($(DEB_HOST_ARCH),mips64el)
|
||||
xgot = -Ctarget-feature=+xgot
|
||||
else
|
||||
xgot =
|
||||
endif
|
||||
|
||||
# Don't use paths that may change between builds.
|
||||
# No need to care about $HOME
|
||||
# because Cargo will not place any source in ~/.cargo.
|
||||
# The build directory is a subdirectory of the source directory,
|
||||
# so it doesn't need to be explicitly taken care of.
|
||||
export RUSTFLAGS = --remap-path-prefix=$(CURDIR)=/remap-pwd $(xgot)
|
||||
|
||||
|
||||
distrel := $(shell lsb_release --codename --short)
|
||||
ifneq (,$(filter $(distrel),buster amber))
|
||||
legacy = true
|
||||
else
|
||||
legacy = false
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@ --builddirectory=_build --buildsystem=meson
|
||||
|
||||
# The Debian version of linked-hash-map doesn't provide any hash,
|
||||
# causing Cargo to refuse to build with a crates.io copy
|
||||
build-arch:
|
||||
rm Cargo.lock
|
||||
dh $@ --builddirectory=_build --buildsystem=meson
|
||||
override_dh_auto_configure:
|
||||
[ ! -f Cargo.lock ] || rm Cargo.lock
|
||||
dh_auto_configure -- -Dlegacy=$(legacy)
|
||||
|
||||
override_dh_autoreconf:
|
||||
|
||||
@ -12,6 +12,10 @@ TARGET_DIR="${1:-./}"
|
||||
|
||||
SPHINX=sphinx-build
|
||||
|
||||
if [ ! -d $DOCS_DIR/_static ]; then
|
||||
mkdir -p $DOCS_DIR/_static
|
||||
fi
|
||||
|
||||
if ! which sphinx-build ; then
|
||||
SPHINX=sphinx-build-3
|
||||
fi
|
||||
|
||||
@ -3,15 +3,47 @@ Hacking
|
||||
|
||||
This document describes the standards for modifying and maintaining the *squeekboard* project.
|
||||
|
||||
Principles
|
||||
----------
|
||||
|
||||
The project was built upon some guiding principles, which should be respected primarily by the maintainers, but also by contributors to avoid needlessly rejected changes.
|
||||
|
||||
The overarching principle of *squeekboard* is to empower users.
|
||||
|
||||
Software is primarily meant to solve problems of its users. Often in the quest to make software better, a hard distinction is made between the developer, who becomes the creator, and the user, who takes the role of the consumer, without direct influence on the software they use.
|
||||
This project aims to give users the power to make the software work for them by blurring the lines between users and developers.
|
||||
|
||||
Notwithstanding its current state, *squeekboard* must be structured in a way that provides users a gradual way to gain more experience and power to adjust it. It must be easy, in order of importance:
|
||||
|
||||
- to use the software,
|
||||
- to modify its resources,
|
||||
- to change its behavior,
|
||||
- to contribute upstream.
|
||||
|
||||
To give an idea of what it means in practice, those are some examples of what has been important for *squeekboard* so far:
|
||||
|
||||
- being quick and usable,
|
||||
- allowing local overrides of resources and config,
|
||||
- storing resources and config as editable, standard files,
|
||||
- having complete, up to date documentation of interfaces,
|
||||
- having an easy process of sending contributions,
|
||||
- adapting to to user's settings and constrains without overriding them,
|
||||
- avoiding compiling whenever possible,
|
||||
- making it easy to build,
|
||||
- having code that is [simple and obvious](https://www.python.org/dev/peps/pep-0020/),
|
||||
- having an easy process of testing and accepting contributions.
|
||||
|
||||
You may notice that they are ordered roughly from "user-focused" to "maintainer-focused". While good properties are desired, sometimes they conflict, and maintainers should give additional weight to those benefiting the user compared to those benefiting regular contributors.
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
By submitting a change to this project, you agree to license it under the [GPL license version 3](./COPYING), or any later version. You also certify that your contribution fulfills the [Developer's Certificate of Origin 1.1](./dco.txt).
|
||||
By submitting a change to this project, you agree to license it under the [GPL license version 3](https://source.puri.sm/Librem5/squeekboard/blob/master/COPYING), or any later version. You also certify that your contribution fulfills the [Developer's Certificate of Origin 1.1](https://source.puri.sm/Librem5/squeekboard/blob/master/dco.txt).
|
||||
|
||||
Development environment
|
||||
-----------------------
|
||||
|
||||
*Squeekboard* is regularly built and tested on [the develpment environment](https://developer.puri.sm/Librem5/Development_Environment.html).
|
||||
*Squeekboard* is regularly built and tested on [the development environment](https://developer.puri.sm/Librem5/Development_Environment.html).
|
||||
|
||||
Recent Fedora releases are likely to be tested as well.
|
||||
|
||||
@ -24,8 +56,7 @@ sudo apt-get -y install build-essential
|
||||
sudo apt-get -y build-dep .
|
||||
```
|
||||
|
||||
For an explicit list of dependencies check the `Build-Depends` entry in the
|
||||
[`debian/control`](./debian/control) file.
|
||||
For an explicit list of dependencies check the `Build-Depends` entry in the [`debian/control`](https://source.puri.sm/Librem5/squeekboard/blob/master/debian/control) file.
|
||||
|
||||
Testing
|
||||
-------
|
||||
@ -82,7 +113,7 @@ User interface modules should:
|
||||
|
||||
Code submitted should roughly match the style of surrounding code. Things that will *not* be accepted are ones that often lead to errors:
|
||||
|
||||
- skipping brackets `{}` after every `if()`, `else`, and similar
|
||||
- skipping brackets `{}` after every `if()`, `else`, and similar ([SCI CERT C: EXP19-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP19-C.+Use+braces+for+the+body+of+an+if%2C+for%2C+or+while+statement))
|
||||
|
||||
Bad example:
|
||||
|
||||
@ -131,7 +162,7 @@ Maintenance
|
||||
|
||||
Squeekboard uses Rust & Cargo for some of its dependencies.
|
||||
|
||||
Use the `cargo.sh` script for maintaining the Cargo part of the build. The script takes the usual Cargo commands, after the first 2 positionsl arguments: source directory, and output artifact. So, `cargo test` becomes:
|
||||
Use the `cargo.sh` script for maintaining the Cargo part of the build. The script takes the usual Cargo commands, after the first 2 positional arguments: source directory, and output artifact. So, `cargo test` becomes:
|
||||
|
||||
```
|
||||
cd build_dir
|
||||
@ -144,10 +175,14 @@ All Cargo dependencies must be selected in the version available in PureOS, and
|
||||
|
||||
Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
|
||||
|
||||
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:
|
||||
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It must correspond to the default dependency configuration: without flags to use older or newer versions of dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:
|
||||
|
||||
```
|
||||
cd build_dir
|
||||
ninja ./Cargo.toml
|
||||
sh /source_path/cargo.sh update
|
||||
ninja test
|
||||
cp ./Cargo.lock /source_path/
|
||||
```
|
||||
|
||||
Since version 1.9.3, `Cargo.lock` is not actually used by the build system, due to `Cargo.toml` being generated at every build.
|
||||
10
doc/index.md
10
doc/index.md
@ -5,17 +5,23 @@ Contents
|
||||
--------
|
||||
|
||||
* [Tutorial](tutorial.md)
|
||||
* [Contributing](hacking.md)
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Squeekboard is the on-screen keyobard for the Librem 5 phone. For more information, look at the [README](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md).
|
||||
Squeekboard is the on-screen keyboard for the Librem 5 phone. For information about building, look at the [README](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md).
|
||||
|
||||
Layouts
|
||||
-------
|
||||
|
||||
Squeekboard allows user-provided keyboard layouts. They can be created without recompiling the keyboard code. The tutorial](/tutorial.md) explains the process in detail.
|
||||
Squeekboard allows user-provided keyboard layouts. They can be created without recompiling the keyboard code. The [tutorial](tutorial.md) explains the process in detail.
|
||||
|
||||
Layouts are created using a text-based format, based on YAML.
|
||||
|
||||
TODO: Provide a description of the format.
|
||||
|
||||
Contributions
|
||||
-------------
|
||||
|
||||
Anyone is free to modify *squeekboard*. See the [contributing document](hacking.md).
|
||||
|
||||
103
doc/tutorial.md
103
doc/tutorial.md
@ -1,53 +1,92 @@
|
||||
Kareema's guide to creating layouts
|
||||
===================================
|
||||
A guide to creating layouts
|
||||
===========================
|
||||
|
||||
It’s long overdue to write a comprehensive guide how to add a keyboard layout from start. But unfortunately, I don’t have much time left ATM. A lot of information can be found in [this ](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5) thread.
|
||||
This guide is based on the original Kareema's [forum post](https://forums.puri.sm/t/translations-and-virtual-touch-keyboards-tracking-localization/7669/48).
|
||||
|
||||
So at least I will try to start writing a short how-to here and edit this post as I find the time. Hope this helps a bit - comments and corrections welcome.
|
||||
It’s long overdue to write a comprehensive guide how to add a keyboard layout from start. But unfortunately, I don’t have much time left ATM. A lot of information can be found in [this](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5) thread.
|
||||
|
||||
**Get one of the existing keyboard layouts**
|
||||
So at least I will try to start writing a short how-to here and edit this post as I find the time. Hope this helps a bit - comments and corrections [welcome](https://source.puri.sm/Librem5/squeekboard/-/merge_requests/)
|
||||
|
||||
* You can get one of the keyboards from the squeekboard git repository : [https://source.puri.sm/Librem5/squeekboard ](https://source.puri.sm/Librem5/squeekboard)
|
||||
* The keyboard layouts are located in the subdirectory `data/keyboard/` in the `.yaml` files
|
||||
## Creating a new layout
|
||||
|
||||
Creating a layout is easy. You don't need to recompile things, just edit and test. It's easiest to start with an existing layout.
|
||||
|
||||
### Get one of the existing keyboard layouts
|
||||
|
||||
* You can get one of the keyboards from the squeekboard git repository : [https://source.puri.sm/Librem5/squeekboard](https://source.puri.sm/Librem5/squeekboard)
|
||||
* The keyboard layouts are located in the subdirectory [`data/keyboards/`](https://source.puri.sm/Librem5/squeekboard/-/tree/master/data/keyboards) in the `.yaml` files
|
||||
* Take a look and try to understand them :slight_smile:
|
||||
|
||||
**Fork your own copy of squeekboard**
|
||||
|
||||
### Creating the keyboard layout
|
||||
|
||||
* To be written: For the time being, take a look at [Using non-latin language on Librem 5](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5)
|
||||
* The correct name of the .yaml file can be found with the command
|
||||
|
||||
```
|
||||
gsettings get org.gnome.desktop.input-sources sources
|
||||
```
|
||||
|
||||
The output should be something like this: `[('xkb', 'us'), ('xkb', 'de')]`
|
||||
So for example “de.yaml” would be the correct name for the German keyboard layout.
|
||||
|
||||
If the name of your layout is not translated correctly in the list, you can fix it by adding it and recompiling Squeekboard.
|
||||
|
||||
### Testing the layout
|
||||
|
||||
Copy your yaml file to `~/.local/share/squeekboard/keyboards/` for testing purposes. From there it should get picked up by squeekboard automatically.
|
||||
|
||||
You can also use the `test_layout` tool from the -devel package to check it for errors:
|
||||
|
||||
```
|
||||
# squeekboard_test_layout ./mylayout.yaml
|
||||
Test result: OK
|
||||
```
|
||||
|
||||
## Contributing your changes
|
||||
|
||||
If you want to share your layout with the world, the best way is to submit it to the Squeekboard project. The workflow is similar to any other Gitlab-based project.
|
||||
|
||||
Above all, your layout should be working, be tested, not break anything, and make sense.
|
||||
|
||||
### Fork your own copy of squeekboard
|
||||
|
||||
* Best way would be to start with a fork of the squeekboard repository: Create a user account at https://source.puri.sm/, go the the squeekboard git repository, press “Fork” in the web interface. You can find further instructions [here](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#creating-a-fork).
|
||||
* Clone your fork locally with `git clone` and use the uri of your forked repo there
|
||||
|
||||
**Workflow to edit your keyboard and get it merged**
|
||||
### Edit your keyboard and get it merged
|
||||
|
||||
* A generic guide how the workflow to contribute works, can be found at https://developer.puri.sm/Librem5/Contact/Contributing.html
|
||||
* It may be useful to check out the [generic guide how the workflow to contribute works](https://developer.puri.sm/Librem5/Contact/Contributing.html)
|
||||
* Create a branch: Name it “keyboard-layout-mylanguage” or whatever
|
||||
* Checkout your branch, edit your keyboard layout and commit your changes
|
||||
* Your layout **must** be correctly named, and in `data/keyboards/`.
|
||||
* Your layout **must** pass the `test_layout` tool with zero problems.
|
||||
* Your translation **must** be correctly named, and in `data/langs/`.
|
||||
* Your layout or translation **must** be added to automatic tests. **Don’t forget to add it** to `src/resources.rs` and the layout to `tests/meson.build` (that’s for me, because I always forget it).
|
||||
|
||||
### Get it merged
|
||||
|
||||
It's always recommended to **compile and run** squeekboard before submitting your changes. This serves as a test that all is working. See instructions in the [compiling section](#compiling-and-running-squeekboard).
|
||||
|
||||
* Push the local changes (to the branch of your fork of squeekboard)
|
||||
* Create a merge request for the branch to get your changes merged to the official squeekboard git repository
|
||||
|
||||
**Compile squeekboard**
|
||||
If your changes pass automated tests (CI), then the merge request will be reviewed by the maintainers, and you might be asked to change a thing or two.
|
||||
|
||||
* Follow the instructions found in “Building” section of the squeekboard’s README: Running squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building ](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building)
|
||||
## Compiling and running Squeekboard
|
||||
|
||||
**Running squeekboard**
|
||||
If you want your change to become part of official Squeekboard, or if you want to add a translation of your layout name, you will have to recompile Squeekboard and test your changes there.
|
||||
|
||||
* Follow these instructions to run squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running ](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running)
|
||||
* Additionally take a look at https://source.puri.sm/Librem5/squeekboard/blob/master/HACKING.md#testing
|
||||
* You can either test it locally on your Linux system or use the [QEMU Librem 5 image ](https://developer.puri.sm/Librem5/Development_Environment/Boards/emulators.html)
|
||||
### Compile squeekboard
|
||||
|
||||
* Follow the instructions found in “Building” section of the squeekboard’s README: Running squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building)
|
||||
|
||||
### Run squeekboard
|
||||
|
||||
* Follow these instructions to run squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running)
|
||||
* Additionally take a look at the contribution document for [testing info](HACKING.md#testing)
|
||||
* You can either test it locally on your Linux system or use the [QEMU Librem 5 image](https://developer.puri.sm/Librem5/Development_Environment/Boards/emulators.html)
|
||||
* To test squeekboard locally, you need phoc. Either compile that from the sources as well or use the CI repository ci.puri.sm for Debian based systems:
|
||||
`deb [arch=amd64] http://ci.puri.sm/ scratch librem5`
|
||||
`deb [arch=amd64] http://ci.puri.sm/ scratch librem5`
|
||||
|
||||
Squeekboard can be installed from there as a Debian package, too (that’s what I often do). But beware - there be dragons! You could bork your system with these packages and you should probably disable this repository again after installing what you need - these packages are not meant for production systems (or so I heard :wink: )
|
||||
|
||||
**Creating the keyboard layout**
|
||||
|
||||
* To be written: For the time being, take a look at [Using non-latin language on Librem 5 ](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5)
|
||||
* The correct name of the .yaml file can be found with the command `gsettings get org.gnome.desktop.input-sources sources`
|
||||
The output should be something like this: `[('xkb', 'us'), ('xkb', 'de')]`
|
||||
So f.ex. “de.yaml” would be the correct name for the German keyboard layout.
|
||||
* The translations for the keyboard layout names in the different languages can be found at `data/langs/`
|
||||
* Don’t forget to add your newly created layout or translation to `src/resources.rs` and the layout to `tests/meson.build` (that’s for me, because I always forget it)
|
||||
|
||||
**Testing the layout**
|
||||
|
||||
* Copy your yaml file to `~/.local/share/squeekboard/keyboards/` for testing purposes. From there it should get picked up by squeekboard
|
||||
* To test the translations in `data/langs/` , you have to compile squeekboard
|
||||
|
||||
|
||||
@ -38,8 +38,6 @@ struct _EekElementClass
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType eek_element_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void eek_element_set_name (EekElement *element,
|
||||
const gchar *name);
|
||||
|
||||
|
||||
@ -25,10 +25,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -39,24 +35,24 @@
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
#include "src/layout.h"
|
||||
#include "src/submission.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LAST
|
||||
};
|
||||
#define LIBFEEDBACK_USE_UNSTABLE_API
|
||||
#include <libfeedback.h>
|
||||
|
||||
/* since 2.91.5 GDK_DRAWABLE was removed and gdk_cairo_create takes
|
||||
GdkWindow as the argument */
|
||||
#ifndef GDK_DRAWABLE
|
||||
#define GDK_DRAWABLE(x) (x)
|
||||
#endif
|
||||
#define SQUEEKBOARD_APP_ID "sm.puri.squeekboard"
|
||||
|
||||
typedef struct _EekGtkKeyboardPrivate
|
||||
{
|
||||
EekRenderer *renderer;
|
||||
LevelKeyboard *keyboard; // unowned reference; it's kept in server-context (FIXME)
|
||||
EekRenderer *renderer; // owned, nullable
|
||||
EekboardContextService *eekboard_context; // unowned reference
|
||||
struct submission *submission; // unowned reference
|
||||
|
||||
struct squeek_layout_state *layout; // unowned
|
||||
LevelKeyboard *keyboard; // unowned reference; it's kept in server-context
|
||||
|
||||
GdkEventSequence *sequence; // unowned reference
|
||||
LfbEvent *event;
|
||||
} EekGtkKeyboardPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
|
||||
@ -85,44 +81,87 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
GtkAllocation allocation;
|
||||
gtk_widget_get_allocation (self, &allocation);
|
||||
|
||||
if (!priv->keyboard) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!priv->renderer) {
|
||||
PangoContext *pcontext = gtk_widget_get_pango_context (self);
|
||||
|
||||
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
|
||||
priv->renderer = eek_renderer_new (
|
||||
priv->keyboard,
|
||||
pcontext);
|
||||
|
||||
eek_renderer_set_allocation_size (priv->renderer,
|
||||
priv->keyboard->layout,
|
||||
allocation.width,
|
||||
allocation.height);
|
||||
eek_renderer_set_scale_factor (priv->renderer,
|
||||
gtk_widget_get_scale_factor (self));
|
||||
}
|
||||
|
||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||
eek_renderer_render_keyboard (priv->renderer, priv->submission, cr, priv->keyboard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Units of virtual pixels size
|
||||
static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) {
|
||||
(void)height;
|
||||
if (width < 540) {
|
||||
return ARRANGEMENT_KIND_BASE;
|
||||
}
|
||||
return ARRANGEMENT_KIND_WIDE;
|
||||
}
|
||||
|
||||
static void
|
||||
eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv =
|
||||
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
||||
// check if the change would switch types
|
||||
enum squeek_arrangement_kind new_type = get_type(
|
||||
(uint32_t)(allocation->width - allocation->x),
|
||||
(uint32_t)(allocation->height - allocation->y));
|
||||
if (priv->layout->arrangement != new_type) {
|
||||
priv->layout->arrangement = new_type;
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
eekboard_context_service_use_layout(priv->eekboard_context, priv->layout, time);
|
||||
}
|
||||
|
||||
if (priv->renderer)
|
||||
if (priv->renderer) {
|
||||
eek_renderer_set_allocation_size (priv->renderer,
|
||||
priv->keyboard->layout,
|
||||
allocation->width,
|
||||
allocation->height);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
|
||||
size_allocate (self, allocation);
|
||||
}
|
||||
|
||||
static void
|
||||
on_event_triggered (LfbEvent *event,
|
||||
GAsyncResult *res,
|
||||
gpointer unused)
|
||||
{
|
||||
g_autoptr (GError) err = NULL;
|
||||
|
||||
if (!lfb_event_trigger_feedback_finish (event, res, &err)) {
|
||||
g_warning ("Failed to trigger feedback for '%s': %s",
|
||||
lfb_event_get_event (event), err->message);
|
||||
}
|
||||
}
|
||||
|
||||
static void depress(EekGtkKeyboard *self,
|
||||
gdouble x, gdouble y, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
squeek_layout_depress(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
if (!priv->keyboard) {
|
||||
return;
|
||||
}
|
||||
squeek_layout_depress(priv->keyboard->layout,
|
||||
priv->submission,
|
||||
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
|
||||
}
|
||||
|
||||
@ -130,18 +169,25 @@ static void drag(EekGtkKeyboard *self,
|
||||
gdouble x, gdouble y, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
if (!priv->keyboard) {
|
||||
return;
|
||||
}
|
||||
squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
|
||||
priv->submission,
|
||||
x, y, eek_renderer_get_transformation(priv->renderer), time,
|
||||
priv->keyboard->manager, self);
|
||||
priv->eekboard_context, self);
|
||||
}
|
||||
|
||||
static void release(EekGtkKeyboard *self, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
if (!priv->keyboard) {
|
||||
return;
|
||||
}
|
||||
squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
|
||||
priv->submission,
|
||||
eek_renderer_get_transformation(priv->renderer), time,
|
||||
priv->keyboard->manager, self);
|
||||
priv->eekboard_context, self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -229,7 +275,8 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
|
||||
|
||||
if (priv->keyboard) {
|
||||
squeek_layout_release_all_only(
|
||||
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
priv->keyboard->layout,
|
||||
priv->submission,
|
||||
gdk_event_get_time(NULL));
|
||||
}
|
||||
|
||||
@ -257,18 +304,24 @@ eek_gtk_keyboard_dispose (GObject *object)
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
if (priv->renderer) {
|
||||
g_object_unref (priv->renderer);
|
||||
eek_renderer_free(priv->renderer);
|
||||
priv->renderer = NULL;
|
||||
priv->renderer = NULL;
|
||||
}
|
||||
|
||||
if (priv->keyboard) {
|
||||
squeek_layout_release_all_only(
|
||||
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
priv->keyboard->layout,
|
||||
priv->submission,
|
||||
gdk_event_get_time(NULL));
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
|
||||
if (priv->event) {
|
||||
g_clear_object (&priv->event);
|
||||
lfb_uninit ();
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -300,26 +353,81 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
|
||||
static void
|
||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
||||
{
|
||||
(void)self;
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
||||
g_autoptr(GError) err = NULL;
|
||||
|
||||
if (lfb_init(SQUEEKBOARD_APP_ID, &err)) {
|
||||
priv->event = lfb_event_new ("button-pressed");
|
||||
} else {
|
||||
g_warning ("Failed to init libfeedback: %s", err->message);
|
||||
}
|
||||
|
||||
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||
|
||||
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify_keyboard (GObject *object,
|
||||
GParamSpec *spec,
|
||||
EekGtkKeyboard *self) {
|
||||
(void)spec;
|
||||
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (self);
|
||||
priv->keyboard = eekboard_context_service_get_keyboard(EEKBOARD_CONTEXT_SERVICE(object));
|
||||
if (priv->renderer) {
|
||||
eek_renderer_free(priv->renderer);
|
||||
}
|
||||
priv->renderer = NULL;
|
||||
gtk_widget_queue_draw(GTK_WIDGET(self));
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_gtk_keyboard_new:
|
||||
* @keyboard: an #EekKeyboard
|
||||
*
|
||||
* Create a new #GtkWidget displaying @keyboard.
|
||||
* Returns: a #GtkWidget
|
||||
*/
|
||||
GtkWidget *
|
||||
eek_gtk_keyboard_new (LevelKeyboard *keyboard)
|
||||
eek_gtk_keyboard_new (EekboardContextService *eekservice,
|
||||
struct submission *submission,
|
||||
struct squeek_layout_state *layout)
|
||||
{
|
||||
EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
|
||||
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
|
||||
priv->keyboard = keyboard;
|
||||
priv->eekboard_context = eekservice;
|
||||
priv->submission = submission;
|
||||
priv->layout = layout;
|
||||
priv->renderer = NULL;
|
||||
g_signal_connect (eekservice,
|
||||
"notify::keyboard",
|
||||
G_CALLBACK(on_notify_keyboard),
|
||||
ret);
|
||||
on_notify_keyboard(G_OBJECT(eekservice), NULL, ret);
|
||||
/* TODO: this is how a compound keyboard
|
||||
* made out of a layout and a suggestion bar could start.
|
||||
* GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
|
||||
GtkEntry *fill = GTK_ENTRY(gtk_entry_new());
|
||||
gtk_box_pack_start(box, GTK_WIDGET(fill), FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(box, GTK_WIDGET(ret), TRUE, TRUE, 0);
|
||||
return GTK_WIDGET(box);*/
|
||||
return GTK_WIDGET(ret);
|
||||
}
|
||||
|
||||
EekRenderer *eek_gtk_keyboard_get_renderer(EekGtkKeyboard *self) {
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
return priv->renderer;
|
||||
/**
|
||||
* eek_gtk_keyboard_emit_feedback:
|
||||
*
|
||||
* Emit button press haptic feedback via libfeedack.
|
||||
*/
|
||||
void
|
||||
eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEK_IS_GTK_KEYBOARD (self));
|
||||
|
||||
priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
||||
if (priv->event) {
|
||||
lfb_event_trigger_feedback_async (priv->event,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)on_event_triggered,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,10 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs
|
||||
#include "eek/eek-types.h"
|
||||
|
||||
struct submission;
|
||||
struct squeek_layout_state;
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type())
|
||||
@ -44,8 +47,8 @@ struct _EekGtkKeyboardClass
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard);
|
||||
GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout);
|
||||
void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_GTK_KEYBOARD_H */
|
||||
|
||||
@ -18,41 +18,85 @@
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eek-keyboard
|
||||
* @short_description: Base class of a keyboard
|
||||
* @see_also: #EekSection
|
||||
*
|
||||
* The #EekKeyboardClass class represents a keyboard, which consists
|
||||
* of one or more sections of the #EekSectionClass class.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
#include "eekboard/key-emitter.h"
|
||||
#include "keymap.h"
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h> // TODO: this is Linux-specific
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
|
||||
void level_keyboard_deinit(LevelKeyboard *self) {
|
||||
xkb_keymap_unref(self->keymap);
|
||||
close(self->keymap_fd);
|
||||
squeek_layout_free(self->layout);
|
||||
/// External linkage for Rust.
|
||||
/// The corresponding deinit is implemented in vkeyboard::KeyMap::drop
|
||||
struct keymap squeek_key_map_from_str(const char *keymap_str) {
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
g_error("No context created");
|
||||
}
|
||||
|
||||
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!keymap) {
|
||||
g_error("Bad keymap:\n%s", keymap_str);
|
||||
}
|
||||
|
||||
xkb_context_unref(context);
|
||||
|
||||
char *xkb_keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
size_t keymap_len = strlen(xkb_keymap_str) + 1;
|
||||
|
||||
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
|
||||
char *r = &path[strlen(path) - 6];
|
||||
if (getrandom(r, 6, GRND_NONBLOCK) < 0) {
|
||||
g_error("Failed to get random numbers: %s", strerror(errno));
|
||||
}
|
||||
for (unsigned i = 0; i < 6; i++) {
|
||||
r[i] = (r[i] & 0b1111111) | 0b1000000; // A-z
|
||||
r[i] = r[i] > 'z' ? '?' : r[i]; // The randomizer doesn't need to be good...
|
||||
}
|
||||
int keymap_fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (keymap_fd < 0) {
|
||||
g_error("Failed to set up keymap fd");
|
||||
}
|
||||
|
||||
shm_unlink(path);
|
||||
if (ftruncate(keymap_fd, (off_t)keymap_len)) {
|
||||
g_error("Failed to increase keymap fd size");
|
||||
}
|
||||
char *ptr = mmap(NULL, keymap_len, PROT_WRITE, MAP_SHARED,
|
||||
keymap_fd, 0);
|
||||
if ((void*)ptr == (void*)-1) {
|
||||
g_error("Failed to set up mmap");
|
||||
}
|
||||
strncpy(ptr, xkb_keymap_str, keymap_len);
|
||||
munmap(ptr, keymap_len);
|
||||
free(xkb_keymap_str);
|
||||
xkb_keymap_unref(keymap);
|
||||
struct keymap km = {
|
||||
.fd = keymap_fd,
|
||||
.fd_len = keymap_len,
|
||||
};
|
||||
return km;
|
||||
}
|
||||
|
||||
void level_keyboard_free(LevelKeyboard *self) {
|
||||
level_keyboard_deinit(self);
|
||||
squeek_layout_free(self->layout);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) {
|
||||
self->layout = layout;
|
||||
}
|
||||
|
||||
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout) {
|
||||
LevelKeyboard*
|
||||
level_keyboard_new (struct squeek_layout *layout)
|
||||
{
|
||||
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
|
||||
level_keyboard_init(keyboard, layout);
|
||||
keyboard->manager = manager;
|
||||
if (!keyboard) {
|
||||
g_error("Failed to create a keyboard");
|
||||
}
|
||||
keyboard->layout = layout;
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
@ -28,29 +28,27 @@
|
||||
#include <glib-object.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "eek-types.h"
|
||||
#include "eek-layout.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/// Keymap container for Rust interoperability.
|
||||
struct keymap {
|
||||
uint32_t fd; // keymap formatted as XKB string
|
||||
size_t fd_len; // length of the data inside keymap_fd
|
||||
};
|
||||
|
||||
/// Keyboard state holder
|
||||
struct _LevelKeyboard {
|
||||
struct squeek_layout *layout; // owned
|
||||
struct xkb_keymap *keymap; // owned
|
||||
int keymap_fd; // keymap formatted as XKB string
|
||||
size_t keymap_len; // length of the data inside keymap_fd
|
||||
|
||||
guint id; // as a key to layout choices
|
||||
|
||||
EekboardContextService *manager; // unowned reference
|
||||
// FIXME: This no longer needs to exist, keymap was folded into layout.
|
||||
};
|
||||
typedef struct _LevelKeyboard LevelKeyboard;
|
||||
|
||||
gchar * eek_keyboard_get_keymap
|
||||
(LevelKeyboard *keyboard);
|
||||
gchar *eek_keyboard_get_keymap(LevelKeyboard *keyboard);
|
||||
|
||||
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout);
|
||||
void level_keyboard_deinit(LevelKeyboard *self);
|
||||
LevelKeyboard*
|
||||
level_keyboard_new (struct squeek_layout *layout);
|
||||
void level_keyboard_free(LevelKeyboard *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eek-layout
|
||||
* @short_description: Base class of a layout engine
|
||||
*
|
||||
* The #EekLayout class is a base class of layout engine which
|
||||
* arranges keyboard elements.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eek-layout.h"
|
||||
#include "eek-keyboard.h"
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
#include "eek-xml-layout.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
eek_layout_class_init (EekLayoutClass *klass)
|
||||
{
|
||||
klass->create_keyboard = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
eek_layout_init (EekLayout *self)
|
||||
{
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
||||
#error "Only <eek/eek.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef EEK_LAYOUT_H
|
||||
#define EEK_LAYOUT_H 1
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "eek-types.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEK_TYPE_LAYOUT (eek_layout_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekLayout, eek_layout, EEK, LAYOUT, GObject)
|
||||
|
||||
/**
|
||||
* EekLayoutClass:
|
||||
* @create_keyboard: virtual function for creating a keyboard
|
||||
*/
|
||||
struct _EekLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
LevelKeyboard* (* create_keyboard) (EekboardContextService *manager,
|
||||
EekLayout *self,
|
||||
gdouble initial_width,
|
||||
gdouble initial_height);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_LAYOUT_H */
|
||||
@ -28,36 +28,10 @@
|
||||
#include "eek-renderer.h"
|
||||
#include "src/style.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PCONTEXT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
typedef struct _EekRendererPrivate
|
||||
{
|
||||
LevelKeyboard *keyboard; // unowned
|
||||
PangoContext *pcontext; // owned
|
||||
GtkCssProvider *css_provider; // owned
|
||||
GtkStyleContext *view_context; // owned
|
||||
GtkStyleContext *button_context; // TODO: maybe move a copy to each button
|
||||
|
||||
gdouble border_width; // FIXME: border of what?
|
||||
|
||||
gdouble allocation_width;
|
||||
gdouble allocation_height;
|
||||
gint scale_factor; /* the outputs scale factor */
|
||||
struct transformation widget_to_layout;
|
||||
|
||||
PangoFontDescription *font; // owned reference
|
||||
|
||||
} EekRendererPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
|
||||
|
||||
/* eek-keyboard-drawing.c */
|
||||
static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, GtkStyleContext *ctx,
|
||||
const struct squeek_button *button);
|
||||
static void render_button_label (cairo_t *cr, GtkStyleContext *ctx,
|
||||
const gchar *label, EekBounds bounds);
|
||||
|
||||
void eek_render_button (EekRenderer *self,
|
||||
cairo_t *cr, const struct squeek_button *button,
|
||||
@ -86,8 +60,7 @@ render_outline (cairo_t *cr,
|
||||
position.x, position.y, position.width, position.height);
|
||||
}
|
||||
|
||||
static void render_button_in_context(EekRenderer *self,
|
||||
gint scale_factor,
|
||||
static void render_button_in_context(gint scale_factor,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
const struct squeek_button *button) {
|
||||
@ -130,7 +103,11 @@ static void render_button_in_context(EekRenderer *self,
|
||||
return;
|
||||
}
|
||||
}
|
||||
eek_renderer_render_button_label (self, cr, ctx, button);
|
||||
|
||||
const gchar *label = squeek_button_get_label(button);
|
||||
if (label) {
|
||||
render_button_label (cr, ctx, label, squeek_button_get_bounds(button));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -140,9 +117,7 @@ eek_render_button (EekRenderer *self,
|
||||
gboolean pressed,
|
||||
gboolean locked)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
GtkStyleContext *ctx = priv->button_context;
|
||||
GtkStyleContext *ctx = self->button_context;
|
||||
/* Set the name of the button on the widget path, using the name obtained
|
||||
from the button's symbol. */
|
||||
g_autoptr (GtkWidgetPath) path = NULL;
|
||||
@ -162,7 +137,7 @@ eek_render_button (EekRenderer *self,
|
||||
}
|
||||
gtk_style_context_add_class(ctx, outline_name);
|
||||
|
||||
render_button_in_context(self, priv->scale_factor, cr, ctx, button);
|
||||
render_button_in_context(self->scale_factor, cr, ctx, button);
|
||||
|
||||
// Save and restore functions don't work if gtk_render_* was used in between
|
||||
gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
|
||||
@ -173,43 +148,16 @@ eek_render_button (EekRenderer *self,
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_render_button_label (EekRenderer *self,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
const struct squeek_button *button)
|
||||
render_button_label (cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
const gchar *label,
|
||||
EekBounds bounds)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
const gchar *label = squeek_button_get_label(button);
|
||||
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
|
||||
PangoFontDescription *font;
|
||||
gdouble scale;
|
||||
|
||||
|
||||
if (!priv->font) {
|
||||
const PangoFontDescription *base_font;
|
||||
gdouble size;
|
||||
|
||||
base_font = pango_context_get_font_description (priv->pcontext);
|
||||
// FIXME: Base font size on the same size unit used for button sizing,
|
||||
// and make the default about 1/3 of the current row height
|
||||
size = 30000.0;
|
||||
priv->font = pango_font_description_copy (base_font);
|
||||
pango_font_description_set_size (priv->font, (gint)round(size * 0.6));
|
||||
}
|
||||
|
||||
EekBounds bounds = squeek_button_get_bounds(button);
|
||||
scale = MIN((bounds.width - priv->border_width) / bounds.width,
|
||||
(bounds.height - priv->border_width) / bounds.height);
|
||||
|
||||
font = pango_font_description_copy (priv->font);
|
||||
pango_font_description_set_size (font,
|
||||
(gint)round(pango_font_description_get_size (font) * scale));
|
||||
|
||||
gtk_style_context_get(ctx,
|
||||
gtk_style_context_get_state(ctx),
|
||||
"font", &font,
|
||||
NULL);
|
||||
PangoLayout *layout = pango_cairo_create_layout (cr);
|
||||
pango_layout_set_font_description (layout, font);
|
||||
pango_font_description_free (font);
|
||||
@ -219,8 +167,7 @@ eek_renderer_render_button_label (EekRenderer *self,
|
||||
if (line->resolved_dir == PANGO_DIRECTION_RTL) {
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
|
||||
}
|
||||
pango_layout_set_width (layout,
|
||||
PANGO_SCALE * bounds.width * scale);
|
||||
pango_layout_set_width (layout, PANGO_SCALE * bounds.width);
|
||||
|
||||
PangoRectangle extents = { 0, };
|
||||
pango_layout_get_extents (layout, NULL, &extents);
|
||||
@ -244,119 +191,46 @@ eek_renderer_render_button_label (EekRenderer *self,
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
// FIXME: Pass just the active modifiers instead of entire submission
|
||||
void
|
||||
eek_renderer_render_keyboard (EekRenderer *self,
|
||||
cairo_t *cr)
|
||||
struct submission *submission,
|
||||
cairo_t *cr,
|
||||
LevelKeyboard *keyboard)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (priv->keyboard);
|
||||
g_return_if_fail (priv->allocation_width > 0.0);
|
||||
g_return_if_fail (priv->allocation_height > 0.0);
|
||||
g_return_if_fail (self->allocation_width > 0.0);
|
||||
g_return_if_fail (self->allocation_height > 0.0);
|
||||
|
||||
/* Paint the background covering the entire widget area */
|
||||
gtk_render_background (priv->view_context,
|
||||
gtk_render_background (self->view_context,
|
||||
cr,
|
||||
0, 0,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
self->allocation_width, self->allocation_height);
|
||||
|
||||
cairo_save(cr);
|
||||
cairo_translate (cr, priv->widget_to_layout.origin_x, priv->widget_to_layout.origin_y);
|
||||
cairo_scale (cr, priv->widget_to_layout.scale, priv->widget_to_layout.scale);
|
||||
cairo_translate (cr, self->widget_to_layout.origin_x, self->widget_to_layout.origin_y);
|
||||
cairo_scale (cr, self->widget_to_layout.scale, self->widget_to_layout.scale);
|
||||
|
||||
squeek_draw_layout_base_view(priv->keyboard->layout, self, cr);
|
||||
squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr);
|
||||
squeek_draw_layout_base_view(keyboard->layout, self, cr);
|
||||
squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
void
|
||||
eek_renderer_free (EekRenderer *self)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (
|
||||
EEK_RENDERER(object));
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PCONTEXT:
|
||||
priv->pcontext = g_value_get_object (value);
|
||||
g_object_ref (priv->pcontext);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
if (self->pcontext) {
|
||||
g_object_unref (self->pcontext);
|
||||
self->pcontext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
(void)value;
|
||||
switch (prop_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_dispose (GObject *object)
|
||||
{
|
||||
EekRenderer *self = EEK_RENDERER (object);
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
if (priv->keyboard) {
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
if (priv->pcontext) {
|
||||
g_object_unref (priv->pcontext);
|
||||
priv->pcontext = NULL;
|
||||
}
|
||||
|
||||
g_object_unref(self->css_provider);
|
||||
g_object_unref(self->view_context);
|
||||
g_object_unref(self->button_context);
|
||||
// this is where renderer-specific surfaces would be released
|
||||
|
||||
G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object);
|
||||
free(self);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_finalize (GObject *object)
|
||||
{
|
||||
EekRenderer *self = EEK_RENDERER(object);
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
g_object_unref(priv->css_provider);
|
||||
g_object_unref(priv->view_context);
|
||||
g_object_unref(priv->button_context);
|
||||
pango_font_description_free (priv->font);
|
||||
G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_class_init (EekRendererClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
gobject_class->set_property = eek_renderer_set_property;
|
||||
gobject_class->get_property = eek_renderer_get_property;
|
||||
gobject_class->dispose = eek_renderer_dispose;
|
||||
gobject_class->finalize = eek_renderer_finalize;
|
||||
|
||||
pspec = g_param_spec_object ("pango-context",
|
||||
"Pango Context",
|
||||
"Pango Context",
|
||||
PANGO_TYPE_CONTEXT,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PCONTEXT,
|
||||
pspec);
|
||||
}
|
||||
|
||||
|
||||
static GType new_type(char *name) {
|
||||
GTypeInfo info = {0};
|
||||
info.class_size = sizeof(GtkWidgetClass);
|
||||
@ -367,7 +241,7 @@ static GType new_type(char *name) {
|
||||
);
|
||||
}
|
||||
|
||||
static GType view_type() {
|
||||
static GType view_type(void) {
|
||||
static GType type = 0;
|
||||
if (!type) {
|
||||
type = new_type("sq_view");
|
||||
@ -375,7 +249,7 @@ static GType view_type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
static GType button_type() {
|
||||
static GType button_type(void) {
|
||||
static GType type = 0;
|
||||
if (!type) {
|
||||
type = new_type("sq_button");
|
||||
@ -384,83 +258,71 @@ static GType button_type() {
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_init (EekRenderer *self)
|
||||
renderer_init (EekRenderer *self)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
self->pcontext = NULL;
|
||||
self->allocation_width = 0.0;
|
||||
self->allocation_height = 0.0;
|
||||
self->scale_factor = 1;
|
||||
|
||||
priv->keyboard = NULL;
|
||||
priv->pcontext = NULL;
|
||||
priv->border_width = 1.0;
|
||||
priv->allocation_width = 0.0;
|
||||
priv->allocation_height = 0.0;
|
||||
priv->scale_factor = 1;
|
||||
priv->font = NULL;
|
||||
|
||||
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||
|
||||
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
|
||||
|
||||
priv->css_provider = squeek_load_style();
|
||||
self->css_provider = squeek_load_style();
|
||||
}
|
||||
|
||||
EekRenderer *
|
||||
eek_renderer_new (LevelKeyboard *keyboard,
|
||||
PangoContext *pcontext)
|
||||
{
|
||||
EekRenderer *renderer = g_object_new (EEK_TYPE_RENDERER,
|
||||
"pango-context", pcontext,
|
||||
NULL);
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
priv->keyboard = keyboard;
|
||||
EekRenderer *renderer = calloc(1, sizeof(EekRenderer));
|
||||
renderer_init(renderer);
|
||||
renderer->pcontext = pcontext;
|
||||
g_object_ref (renderer->pcontext);
|
||||
|
||||
/* Create a style context for the layout */
|
||||
GtkWidgetPath *path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type(path, view_type());
|
||||
|
||||
priv->view_context = gtk_style_context_new();
|
||||
gtk_style_context_set_path(priv->view_context, path);
|
||||
renderer->view_context = gtk_style_context_new();
|
||||
gtk_style_context_set_path(renderer->view_context, path);
|
||||
gtk_widget_path_unref(path);
|
||||
if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
gtk_style_context_add_class(priv->view_context, "wide");
|
||||
if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
gtk_style_context_add_class(renderer->view_context, "wide");
|
||||
}
|
||||
gtk_style_context_add_provider (priv->view_context,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
gtk_style_context_add_provider (renderer->view_context,
|
||||
GTK_STYLE_PROVIDER(renderer->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
|
||||
/* Create a style context for the buttons */
|
||||
path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type(path, view_type());
|
||||
if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
gtk_widget_path_iter_add_class(path, -1, "wide");
|
||||
}
|
||||
gtk_widget_path_append_type(path, button_type());
|
||||
priv->button_context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path(priv->button_context, path);
|
||||
renderer->button_context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path(renderer->button_context, path);
|
||||
gtk_widget_path_unref(path);
|
||||
gtk_style_context_set_parent(priv->button_context, priv->view_context);
|
||||
gtk_style_context_set_state (priv->button_context, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_style_context_add_provider (priv->button_context,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
gtk_style_context_set_parent(renderer->button_context, renderer->view_context);
|
||||
gtk_style_context_set_state (renderer->button_context, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_style_context_add_provider (renderer->button_context,
|
||||
GTK_STYLE_PROVIDER(renderer->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||
struct squeek_layout *layout,
|
||||
gdouble width,
|
||||
gdouble height)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (width > 0.0 && height > 0.0);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
renderer->allocation_width = width;
|
||||
renderer->allocation_height = height;
|
||||
|
||||
priv->allocation_width = width;
|
||||
priv->allocation_height = height;
|
||||
|
||||
priv->widget_to_layout = squeek_layout_calculate_transformation(
|
||||
priv->keyboard->layout,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
renderer->widget_to_layout = squeek_layout_calculate_transformation(
|
||||
layout,
|
||||
renderer->allocation_width, renderer->allocation_height);
|
||||
|
||||
// This is where size-dependent surfaces would be released
|
||||
}
|
||||
@ -468,10 +330,7 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||
void
|
||||
eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
priv->scale_factor = scale;
|
||||
renderer->scale_factor = scale;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
@ -500,9 +359,5 @@ eek_renderer_get_icon_surface (const gchar *icon_name,
|
||||
|
||||
struct transformation
|
||||
eek_renderer_get_transformation (EekRenderer *renderer) {
|
||||
struct transformation failed = {0};
|
||||
g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
return priv->widget_to_layout;
|
||||
return renderer->widget_to_layout;
|
||||
}
|
||||
|
||||
@ -25,31 +25,36 @@
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "eek-types.h"
|
||||
#include "src/submission.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
struct squeek_layout;
|
||||
|
||||
#define EEK_TYPE_RENDERER (eek_renderer_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekRenderer, eek_renderer, EEK, RENDERER, GObject)
|
||||
|
||||
struct _EekRendererClass
|
||||
/// Renders LevelKayboards
|
||||
/// It cannot adjust styles at runtime.
|
||||
typedef struct EekRenderer
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
PangoContext *pcontext; // owned
|
||||
GtkCssProvider *css_provider; // owned
|
||||
GtkStyleContext *view_context; // owned
|
||||
GtkStyleContext *button_context; // TODO: maybe move a copy to each button
|
||||
/// Style class for rendering the view and button CSS.
|
||||
gchar *extra_style; // owned
|
||||
|
||||
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
|
||||
const gchar *icon_name,
|
||||
gint size,
|
||||
gint scale);
|
||||
// Mutable state
|
||||
/// Background extents
|
||||
gdouble allocation_width;
|
||||
gdouble allocation_height;
|
||||
gint scale_factor; /* the outputs scale factor */
|
||||
/// Coords transformation
|
||||
struct transformation widget_to_layout;
|
||||
} EekRenderer;
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[23];
|
||||
};
|
||||
|
||||
GType eek_renderer_get_type (void) G_GNUC_CONST;
|
||||
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
|
||||
PangoContext *pcontext);
|
||||
void eek_renderer_set_allocation_size
|
||||
(EekRenderer *renderer,
|
||||
(EekRenderer *renderer, struct squeek_layout *layout,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
void eek_renderer_set_scale_factor (EekRenderer *renderer,
|
||||
@ -59,8 +64,10 @@ cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name,
|
||||
gint size,
|
||||
gint scale);
|
||||
|
||||
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
cairo_t *cr);
|
||||
void eek_renderer_render_keyboard (EekRenderer *renderer, struct submission *submission,
|
||||
cairo_t *cr, LevelKeyboard *keyboard);
|
||||
void
|
||||
eek_renderer_free (EekRenderer *self);
|
||||
|
||||
struct transformation
|
||||
eek_renderer_get_transformation (EekRenderer *renderer);
|
||||
|
||||
@ -38,6 +38,7 @@ G_BEGIN_DECLS
|
||||
typedef struct _EekBounds EekBounds;
|
||||
|
||||
typedef struct _EekboardContextService EekboardContextService;
|
||||
typedef struct _ServerContextService ServerContextService;
|
||||
typedef struct _LevelKeyboard LevelKeyboard;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eek-xml-layout
|
||||
* @short_description: Layout engine which loads layout information from XML
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
#include "eek-xml-layout.h"
|
||||
|
||||
LevelKeyboard *
|
||||
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
|
||||
EekboardContextService *manager,
|
||||
enum squeek_arrangement_kind t)
|
||||
{
|
||||
struct squeek_layout *layout = squeek_load_layout(keyboard_type, t);
|
||||
return level_keyboard_new(manager, layout);
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
||||
#error "Only <eek/eek.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef EEK_XML_LAYOUT_H
|
||||
#define EEK_XML_LAYOUT_H 1
|
||||
|
||||
#include "eek-types.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
LevelKeyboard *
|
||||
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
|
||||
EekboardContextService *manager,
|
||||
enum squeek_arrangement_kind t);
|
||||
G_END_DECLS
|
||||
#endif /* EEK_XML_LAYOUT_H */
|
||||
@ -23,7 +23,6 @@
|
||||
#define __EEK_H_INSIDE__ 1
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-layout.h"
|
||||
|
||||
void eek_init (void);
|
||||
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
gboolean
|
||||
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
|
||||
guint keyval,
|
||||
GdkKeymapKey **keys,
|
||||
guint *n_keys);
|
||||
@ -590,27 +590,32 @@ phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height)
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->height == height && priv->width == width)
|
||||
if (priv->height == height && priv->width == width) {
|
||||
return;
|
||||
}
|
||||
|
||||
old_width = priv->width;
|
||||
old_height = priv->height;
|
||||
|
||||
if (width != -1)
|
||||
if (width != -1) {
|
||||
priv->width = width;
|
||||
}
|
||||
|
||||
if (height != -1)
|
||||
if (height != -1) {
|
||||
priv->height = height;
|
||||
}
|
||||
|
||||
if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
|
||||
zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
|
||||
}
|
||||
|
||||
if (priv->height != old_height)
|
||||
if (priv->height != old_height) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT]);
|
||||
}
|
||||
|
||||
if (priv->width != old_width)
|
||||
if (priv->width != old_width) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,25 +637,31 @@ phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, g
|
||||
old_right = priv->margin_right;
|
||||
old_bottom = priv->margin_bottom;
|
||||
|
||||
if (old_top == top && old_left == left && old_right == right && old_bottom == bottom)
|
||||
if (old_top == top && old_left == left && old_right == right && old_bottom == bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
priv->margin_top = top;
|
||||
priv->margin_left = left;
|
||||
priv->margin_right = right;
|
||||
priv->margin_bottom = bottom;
|
||||
|
||||
if (priv->layer_surface)
|
||||
if (priv->layer_surface) {
|
||||
zwlr_layer_surface_v1_set_margin(priv->layer_surface, top, right, bottom, left);
|
||||
}
|
||||
|
||||
if (old_top != top)
|
||||
if (old_top != top) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP]);
|
||||
if (old_bottom != bottom)
|
||||
}
|
||||
if (old_bottom != bottom) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM]);
|
||||
if (old_left != left)
|
||||
}
|
||||
if (old_left != left) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT]);
|
||||
if (old_right != right)
|
||||
}
|
||||
if (old_right != right) {
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -669,13 +680,15 @@ phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone)
|
||||
|
||||
old_zone = priv->exclusive_zone;
|
||||
|
||||
if (old_zone == zone)
|
||||
if (old_zone == zone) {
|
||||
return;
|
||||
}
|
||||
|
||||
priv->exclusive_zone = zone;
|
||||
|
||||
if (priv->layer_surface)
|
||||
if (priv->layer_surface) {
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, zone);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]);
|
||||
}
|
||||
@ -693,13 +706,14 @@ phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean int
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->kbd_interactivity == interactivity)
|
||||
if (priv->kbd_interactivity == interactivity) {
|
||||
return;
|
||||
|
||||
}
|
||||
priv->kbd_interactivity = interactivity;
|
||||
|
||||
if (priv->layer_surface)
|
||||
if (priv->layer_surface) {
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]);
|
||||
}
|
||||
@ -717,6 +731,7 @@ phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self)
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->wl_surface)
|
||||
if (priv->wl_surface) {
|
||||
wl_surface_commit (priv->wl_surface);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,31 +16,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eekboard-context-service
|
||||
* @short_description: base server implementation of eekboard input
|
||||
* context service
|
||||
*
|
||||
* The #EekboardService class provides a base server side
|
||||
* implementation of eekboard input context service.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h> // TODO: this is Linux-specific
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "eekboard/key-emitter.h"
|
||||
#include "wayland.h"
|
||||
|
||||
#include "eek/eek-xml-layout.h"
|
||||
#include "eek/eek-keyboard.h"
|
||||
#include "src/server-context-service.h"
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
@ -48,104 +32,42 @@
|
||||
enum {
|
||||
PROP_0, // Magic: without this, keyboard is not useable in g_object_notify
|
||||
PROP_KEYBOARD,
|
||||
PROP_VISIBLE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
#define EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEKBOARD_TYPE_CONTEXT_SERVICE, EekboardContextServicePrivate))
|
||||
|
||||
struct _EekboardContextServicePrivate {
|
||||
gboolean enabled;
|
||||
gboolean visible;
|
||||
/**
|
||||
* EekboardContextService:
|
||||
*
|
||||
* Handles layout state, gsettings, and virtual-keyboard.
|
||||
*
|
||||
* TODO: Restrict to managing keyboard layouts, and maybe button repeats,
|
||||
* and the virtual keyboard protocol.
|
||||
*
|
||||
* The #EekboardContextService structure contains only private data
|
||||
* and should only be accessed using the provided API.
|
||||
*/
|
||||
struct _EekboardContextService {
|
||||
GObject parent;
|
||||
struct squeek_layout_state *layout; // Unowned
|
||||
|
||||
LevelKeyboard *keyboard; // currently used keyboard
|
||||
GHashTable *keyboard_hash; // a table of available keyboards, per layout
|
||||
GSettings *settings; // Owned reference
|
||||
|
||||
char *overlay;
|
||||
|
||||
GSettings *settings;
|
||||
uint32_t hint;
|
||||
uint32_t purpose;
|
||||
// Maybe TODO: it's used only for fetching layout type.
|
||||
// Maybe let UI push the type to this structure?
|
||||
ServerContextService *ui; // unowned reference
|
||||
/// Needed for keymap changes after keyboard updates
|
||||
struct submission *submission; // unowned
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
|
||||
|
||||
static LevelKeyboard *
|
||||
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
|
||||
const gchar *keyboard_type,
|
||||
enum squeek_arrangement_kind t)
|
||||
{
|
||||
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self, t);
|
||||
if (!keyboard) {
|
||||
g_error("Failed to create a keyboard");
|
||||
}
|
||||
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
g_error("No context created");
|
||||
}
|
||||
|
||||
const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout);
|
||||
|
||||
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!keymap)
|
||||
g_error("Bad keymap:\n%s", keymap_str);
|
||||
|
||||
xkb_context_unref(context);
|
||||
keyboard->keymap = keymap;
|
||||
|
||||
keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
keyboard->keymap_len = strlen(keymap_str) + 1;
|
||||
|
||||
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
|
||||
char *r = &path[strlen(path) - 6];
|
||||
getrandom(r, 6, GRND_NONBLOCK);
|
||||
for (unsigned i = 0; i < 6; i++) {
|
||||
r[i] = (r[i] & 0b1111111) | 0b1000000; // A-z
|
||||
r[i] = r[i] > 'z' ? '?' : r[i]; // The randomizer doesn't need to be good...
|
||||
}
|
||||
int keymap_fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (keymap_fd < 0) {
|
||||
g_error("Failed to set up keymap fd");
|
||||
}
|
||||
keyboard->keymap_fd = keymap_fd;
|
||||
shm_unlink(path);
|
||||
if (ftruncate(keymap_fd, (off_t)keyboard->keymap_len)) {
|
||||
g_error("Failed to increase keymap fd size");
|
||||
}
|
||||
char *ptr = mmap(NULL, keyboard->keymap_len, PROT_WRITE, MAP_SHARED,
|
||||
keymap_fd, 0);
|
||||
if ((void*)ptr == (void*)-1) {
|
||||
g_error("Failed to set up mmap");
|
||||
}
|
||||
strncpy(ptr, keymap_str, keyboard->keymap_len);
|
||||
munmap(ptr, keyboard->keymap_len);
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_service_real_show_keyboard (EekboardContextService *self)
|
||||
{
|
||||
self->priv->visible = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_service_real_hide_keyboard (EekboardContextService *self)
|
||||
{
|
||||
self->priv->visible = FALSE;
|
||||
}
|
||||
G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
eekboard_context_service_set_property (GObject *object,
|
||||
@ -153,17 +75,8 @@ eekboard_context_service_set_property (GObject *object,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(object);
|
||||
|
||||
(void)value;
|
||||
switch (prop_id) {
|
||||
case PROP_KEYBOARD:
|
||||
if (context->priv->keyboard)
|
||||
g_object_unref (context->priv->keyboard);
|
||||
context->priv->keyboard = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
context->priv->visible = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -180,10 +93,7 @@ eekboard_context_service_get_property (GObject *object,
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_KEYBOARD:
|
||||
g_value_set_object (value, context->priv->keyboard);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
g_value_set_boolean (value, context->priv->visible);
|
||||
g_value_set_object (value, context->keyboard);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@ -194,13 +104,6 @@ eekboard_context_service_get_property (GObject *object,
|
||||
static void
|
||||
eekboard_context_service_dispose (GObject *object)
|
||||
{
|
||||
EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(object);
|
||||
|
||||
if (context->priv->keyboard_hash) {
|
||||
g_hash_table_destroy (context->priv->keyboard_hash);
|
||||
context->priv->keyboard_hash = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eekboard_context_service_parent_class)->
|
||||
dispose (object);
|
||||
}
|
||||
@ -208,47 +111,58 @@ eekboard_context_service_dispose (GObject *object)
|
||||
static void
|
||||
settings_get_layout(GSettings *settings, char **type, char **layout)
|
||||
{
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
GVariant *inputs = g_settings_get_value(settings, "sources");
|
||||
// current layout is always first
|
||||
g_variant_get_child(inputs, 0, "(ss)", type, layout);
|
||||
if (g_variant_n_children(inputs) == 0) {
|
||||
g_warning("No system layout present");
|
||||
*type = NULL;
|
||||
*layout = NULL;
|
||||
} else {
|
||||
// current layout is always first
|
||||
g_variant_get_child(inputs, 0, "(ss)", type, layout);
|
||||
}
|
||||
g_variant_unref(inputs);
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t)
|
||||
{
|
||||
g_autofree gchar *keyboard_layout = NULL;
|
||||
if (context->priv->overlay) {
|
||||
keyboard_layout = g_strdup(context->priv->overlay);
|
||||
} else {
|
||||
g_autofree gchar *keyboard_type = NULL;
|
||||
settings_get_layout(context->priv->settings,
|
||||
&keyboard_type, &keyboard_layout);
|
||||
}
|
||||
eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *state, uint32_t timestamp) {
|
||||
gchar *layout_name = state->overlay_name;
|
||||
|
||||
if (!keyboard_layout) {
|
||||
keyboard_layout = g_strdup("us");
|
||||
}
|
||||
if (layout_name == NULL) {
|
||||
layout_name = state->layout_name;
|
||||
|
||||
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
|
||||
switch (state->purpose) {
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
|
||||
layout_name = "number";
|
||||
break;
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
|
||||
layout_name = "terminal";
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
switch (priv->purpose) {
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
|
||||
keyboard_layout = g_strdup("number");
|
||||
break;
|
||||
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
|
||||
keyboard_layout = g_strdup("terminal");
|
||||
break;
|
||||
default:
|
||||
;
|
||||
if (layout_name == NULL) {
|
||||
layout_name = "us";
|
||||
}
|
||||
}
|
||||
|
||||
// generic part follows
|
||||
LevelKeyboard *keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout, t);
|
||||
struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement);
|
||||
LevelKeyboard *keyboard = level_keyboard_new(layout);
|
||||
// set as current
|
||||
LevelKeyboard *previous_keyboard = context->priv->keyboard;
|
||||
context->priv->keyboard = keyboard;
|
||||
LevelKeyboard *previous_keyboard = context->keyboard;
|
||||
context->keyboard = keyboard;
|
||||
// Update the keymap if necessary.
|
||||
// TODO: Update submission on change event
|
||||
if (context->submission) {
|
||||
submission_use_layout(context->submission, keyboard->layout, timestamp);
|
||||
}
|
||||
|
||||
// Update UI
|
||||
g_object_notify (G_OBJECT(context), "keyboard");
|
||||
|
||||
// replacing the keyboard above will cause the previous keyboard to get destroyed from the UI side (eek_gtk_keyboard_dispose)
|
||||
@ -257,8 +171,23 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ
|
||||
}
|
||||
}
|
||||
|
||||
static void update_layout_and_type(EekboardContextService *context) {
|
||||
eekboard_context_service_update_layout(context, server_context_service_get_layout_type(context));
|
||||
static void eekboard_context_service_update_settings_layout(EekboardContextService *context) {
|
||||
g_autofree gchar *keyboard_layout = NULL;
|
||||
g_autofree gchar *keyboard_type = NULL;
|
||||
settings_get_layout(context->settings,
|
||||
&keyboard_type, &keyboard_layout);
|
||||
|
||||
if (g_strcmp0(context->layout->layout_name, keyboard_layout) != 0 || context->layout->overlay_name) {
|
||||
g_free(context->layout->overlay_name);
|
||||
context->layout->overlay_name = NULL;
|
||||
if (keyboard_layout) {
|
||||
g_free(context->layout->layout_name);
|
||||
context->layout->layout_name = g_strdup(keyboard_layout);
|
||||
}
|
||||
// This must actually update the UI.
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
eekboard_context_service_use_layout(context, context->layout, time);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -269,23 +198,14 @@ settings_handle_layout_changed(GSettings *s,
|
||||
(void)keys;
|
||||
(void)n_keys;
|
||||
EekboardContextService *context = user_data;
|
||||
g_free(context->priv->overlay);
|
||||
context->priv->overlay = NULL;
|
||||
update_layout_and_type(context);
|
||||
eekboard_context_service_update_settings_layout(context);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_service_constructed (GObject *object)
|
||||
{
|
||||
EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE (object);
|
||||
context->virtual_keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
|
||||
squeek_wayland->virtual_keyboard_manager,
|
||||
squeek_wayland->seat);
|
||||
if (!context->virtual_keyboard) {
|
||||
g_error("Programmer error: Failed to receive a virtual keyboard instance");
|
||||
}
|
||||
update_layout_and_type(context);
|
||||
(void)object;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -294,48 +214,10 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
klass->show_keyboard = eekboard_context_service_real_show_keyboard;
|
||||
klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
|
||||
|
||||
gobject_class->constructed = eekboard_context_service_constructed;
|
||||
gobject_class->set_property = eekboard_context_service_set_property;
|
||||
gobject_class->get_property = eekboard_context_service_get_property;
|
||||
gobject_class->dispose = eekboard_context_service_dispose;
|
||||
|
||||
/**
|
||||
* EekboardContextService::enabled:
|
||||
* @context: an #EekboardContextService
|
||||
*
|
||||
* Emitted when @context is enabled.
|
||||
*/
|
||||
signals[ENABLED] =
|
||||
g_signal_new (I_("enabled"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextServiceClass, enabled),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EekboardContextService::disabled:
|
||||
* @context: an #EekboardContextService
|
||||
*
|
||||
* Emitted when @context is enabled.
|
||||
*/
|
||||
signals[DISABLED] =
|
||||
g_signal_new (I_("disabled"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextServiceClass, disabled),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EekboardContextService::destroyed:
|
||||
* @context: an #EekboardContextService
|
||||
@ -346,7 +228,7 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextServiceClass, destroyed),
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
@ -361,102 +243,39 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
||||
pspec = g_param_spec_pointer("keyboard",
|
||||
"Keyboard",
|
||||
"Keyboard",
|
||||
G_PARAM_READWRITE);
|
||||
G_PARAM_READABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_KEYBOARD,
|
||||
pspec);
|
||||
|
||||
/**
|
||||
* EekboardContextService:visible:
|
||||
*
|
||||
* Flag to indicate if keyboard is visible or not.
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("visible",
|
||||
"Visible",
|
||||
"Visible",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VISIBLE,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_service_init (EekboardContextService *self)
|
||||
{
|
||||
self->priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(self);
|
||||
const char *schema_name = "org.gnome.desktop.input-sources";
|
||||
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default();
|
||||
g_autoptr(GSettingsSchema) schema = NULL;
|
||||
|
||||
self->priv->keyboard_hash =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
|
||||
self->priv->settings = g_settings_new ("org.gnome.desktop.input-sources");
|
||||
gulong conn_id = g_signal_connect(self->priv->settings, "change-event",
|
||||
G_CALLBACK(settings_handle_layout_changed),
|
||||
self);
|
||||
if (conn_id == 0) {
|
||||
g_warning ("Could not connect to gsettings updates, layout"
|
||||
" changing unavailable");
|
||||
if (!ssrc) {
|
||||
g_warning("No gsettings schemas installed. Layout switching unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
self->priv->overlay = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_service_enable:
|
||||
* @context: an #EekboardContextService
|
||||
*
|
||||
* Enable @context. This function is called when @context is pushed
|
||||
* by eekboard_service_push_context().
|
||||
*/
|
||||
void
|
||||
eekboard_context_service_enable (EekboardContextService *context)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
||||
|
||||
if (!context->priv->enabled) {
|
||||
context->priv->enabled = TRUE;
|
||||
g_signal_emit (context, signals[ENABLED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_service_disable:
|
||||
* @context: an #EekboardContextService
|
||||
*
|
||||
* Disable @context. This function is called when @context is pushed
|
||||
* by eekboard_service_pop_context().
|
||||
*/
|
||||
void
|
||||
eekboard_context_service_disable (EekboardContextService *context)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
||||
|
||||
if (context->priv->enabled) {
|
||||
context->priv->enabled = FALSE;
|
||||
g_signal_emit (context, signals[DISABLED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_context_service_show_keyboard (EekboardContextService *context)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
||||
|
||||
if (!context->priv->visible) {
|
||||
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->show_keyboard (context);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_context_service_hide_keyboard (EekboardContextService *context)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
||||
|
||||
if (context->priv->visible) {
|
||||
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->hide_keyboard (context);
|
||||
schema = g_settings_schema_source_lookup(ssrc, schema_name, TRUE);
|
||||
if (schema) {
|
||||
// Not referencing the found schema directly,
|
||||
// because it's not clear how...
|
||||
self->settings = g_settings_new (schema_name);
|
||||
gulong conn_id = g_signal_connect(self->settings, "change-event",
|
||||
G_CALLBACK(settings_handle_layout_changed),
|
||||
self);
|
||||
if (conn_id == 0) {
|
||||
g_warning ("Could not connect to gsettings updates, "
|
||||
"automatic layout changing unavailable");
|
||||
}
|
||||
} else {
|
||||
g_warning("Gsettings schema %s is not installed on the system. "
|
||||
"Layout switching unavailable", schema_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,11 +289,6 @@ void
|
||||
eekboard_context_service_destroy (EekboardContextService *context)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
||||
|
||||
if (context->priv->enabled) {
|
||||
eekboard_context_service_disable (context);
|
||||
}
|
||||
g_free(context->priv->overlay);
|
||||
g_signal_emit (context, signals[DESTROYED], 0);
|
||||
}
|
||||
|
||||
@ -488,36 +302,53 @@ eekboard_context_service_destroy (EekboardContextService *context)
|
||||
LevelKeyboard *
|
||||
eekboard_context_service_get_keyboard (EekboardContextService *context)
|
||||
{
|
||||
return context->priv->keyboard;
|
||||
}
|
||||
|
||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
|
||||
const LevelKeyboard *keyboard)
|
||||
{
|
||||
zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
keyboard->keymap_fd, keyboard->keymap_len);
|
||||
return context->keyboard;
|
||||
}
|
||||
|
||||
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
||||
uint32_t hint, uint32_t purpose)
|
||||
{
|
||||
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
|
||||
|
||||
if (priv->hint != hint || priv->purpose != purpose) {
|
||||
priv->hint = hint;
|
||||
priv->purpose = purpose;
|
||||
update_layout_and_type(context);
|
||||
if (context->layout->hint != hint || context->layout->purpose != purpose) {
|
||||
context->layout->hint = hint;
|
||||
context->layout->purpose = purpose;
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
eekboard_context_service_use_layout(context, context->layout, time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) {
|
||||
context->priv->overlay = g_strdup(name);
|
||||
update_layout_and_type(context);
|
||||
if (g_strcmp0(context->layout->overlay_name, name)) {
|
||||
g_free(context->layout->overlay_name);
|
||||
context->layout->overlay_name = g_strdup(name);
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
eekboard_context_service_use_layout(context, context->layout, time);
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
eekboard_context_service_get_overlay(EekboardContextService *context) {
|
||||
return context->priv->overlay;
|
||||
return context->layout->overlay_name;
|
||||
}
|
||||
|
||||
EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state)
|
||||
{
|
||||
EekboardContextService *context = g_object_new (EEKBOARD_TYPE_CONTEXT_SERVICE, NULL);
|
||||
context->layout = state;
|
||||
eekboard_context_service_update_settings_layout(context);
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
eekboard_context_service_use_layout(context, context->layout, time);
|
||||
return context;
|
||||
}
|
||||
|
||||
void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission) {
|
||||
context->submission = submission;
|
||||
if (context->submission) {
|
||||
uint32_t time = gdk_event_get_time(NULL);
|
||||
submission_use_layout(context->submission, context->keyboard->layout, time);
|
||||
}
|
||||
}
|
||||
|
||||
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui) {
|
||||
context->ui = ui;
|
||||
}
|
||||
|
||||
@ -22,7 +22,8 @@
|
||||
#ifndef EEKBOARD_CONTEXT_SERVICE_H
|
||||
#define EEKBOARD_CONTEXT_SERVICE_H 1
|
||||
|
||||
#include <eek/eek.h>
|
||||
#include "src/submission.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
#include "text-input-unstable-v3-client-protocol.h"
|
||||
@ -33,69 +34,12 @@ G_BEGIN_DECLS
|
||||
#define EEKBOARD_CONTEXT_SERVICE_INTERFACE "org.fedorahosted.Eekboard.Context"
|
||||
|
||||
#define EEKBOARD_TYPE_CONTEXT_SERVICE (eekboard_context_service_get_type())
|
||||
#define EEKBOARD_CONTEXT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_CONTEXT_SERVICE, EekboardContextService))
|
||||
#define EEKBOARD_CONTEXT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_CONTEXT_SERVICE, EekboardContextServiceClass))
|
||||
#define EEKBOARD_IS_CONTEXT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_CONTEXT_SERVICE))
|
||||
#define EEKBOARD_IS_CONTEXT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_CONTEXT_SERVICE))
|
||||
#define EEKBOARD_CONTEXT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_CONTEXT_SERVICE, EekboardContextServiceClass))
|
||||
|
||||
G_DECLARE_FINAL_TYPE(EekboardContextService, eekboard_context_service, EEKBOARD, CONTEXT_SERVICE, GObject)
|
||||
|
||||
typedef struct _EekboardContextServiceClass EekboardContextServiceClass;
|
||||
typedef struct _EekboardContextServicePrivate EekboardContextServicePrivate;
|
||||
|
||||
/**
|
||||
* EekboardContextService:
|
||||
*
|
||||
* TODO: Restrict to managing keyboard layouts, and maybe button repeats,
|
||||
* and the virtual keyboard protocol.
|
||||
*
|
||||
* The #EekboardContextService structure contains only private data
|
||||
* and should only be accessed using the provided API.
|
||||
*/
|
||||
struct _EekboardContextService {
|
||||
GObject parent;
|
||||
|
||||
EekboardContextServicePrivate *priv;
|
||||
|
||||
struct zwp_virtual_keyboard_v1 *virtual_keyboard;
|
||||
};
|
||||
|
||||
/**
|
||||
* EekboardContextServiceClass:
|
||||
* @create_keyboard: virtual function for create a keyboard from string
|
||||
* @show_keyboard: virtual function for show a keyboard
|
||||
* @hide_keyboard: virtual function for hide a keyboard
|
||||
* @enabled: class handler for #EekboardContextService::enabled signal
|
||||
* @disabled: class handler for #EekboardContextService::disabled signal
|
||||
*/
|
||||
struct _EekboardContextServiceClass {
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
struct squeek_view *(*create_keyboard) (EekboardContextService *self,
|
||||
const gchar *keyboard_type);
|
||||
void (*show_keyboard) (EekboardContextService *self);
|
||||
void (*hide_keyboard) (EekboardContextService *self);
|
||||
|
||||
/* signals */
|
||||
void (*enabled) (EekboardContextService *self);
|
||||
void (*disabled) (EekboardContextService *self);
|
||||
void (*destroyed) (EekboardContextService *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eekboard_context_service_get_type
|
||||
(void) G_GNUC_CONST;
|
||||
void eekboard_context_service_enable (EekboardContextService *context);
|
||||
void eekboard_context_service_disable (EekboardContextService *context);
|
||||
void eekboard_context_service_show_keyboard
|
||||
(EekboardContextService *context);
|
||||
void eekboard_context_service_hide_keyboard
|
||||
(EekboardContextService *context);
|
||||
EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state);
|
||||
void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission);
|
||||
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui);
|
||||
void eekboard_context_service_destroy (EekboardContextService *context);
|
||||
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
|
||||
|
||||
@ -106,6 +50,6 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
||||
uint32_t hint,
|
||||
uint32_t purpose);
|
||||
void
|
||||
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t);
|
||||
eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp);
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_CONTEXT_SERVICE_H */
|
||||
|
||||
@ -1,310 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eekboard-service
|
||||
* @short_description: base implementation of eekboard service
|
||||
*
|
||||
* Provides a dbus object, and contains the context.
|
||||
*
|
||||
* The #EekboardService class provides a base server side
|
||||
* implementation of eekboard service.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sm.puri.OSK0.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "eekboard/eekboard-service.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_CONNECTION,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
typedef struct _EekboardServicePrivate
|
||||
{
|
||||
GDBusConnection *connection;
|
||||
SmPuriOSK0 *dbus_interface;
|
||||
GDBusNodeInfo *introspection_data;
|
||||
guint registration_id;
|
||||
char *object_path;
|
||||
|
||||
EekboardContextService *context; // unowned reference
|
||||
} EekboardServicePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardService, eekboard_service, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
eekboard_service_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekboardService *service = EEKBOARD_SERVICE(object);
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
GDBusConnection *connection;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_OBJECT_PATH:
|
||||
if (priv->object_path)
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_CONNECTION:
|
||||
connection = g_value_get_object (value);
|
||||
if (priv->connection)
|
||||
g_object_unref (priv->connection);
|
||||
priv->connection = g_object_ref (connection);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekboardService *service = EEKBOARD_SERVICE(object);
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
case PROP_CONNECTION:
|
||||
g_value_set_object (value, priv->connection);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_dispose (GObject *object)
|
||||
{
|
||||
EekboardService *service = EEKBOARD_SERVICE(object);
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
if (priv->connection) {
|
||||
if (priv->registration_id > 0) {
|
||||
g_dbus_connection_unregister_object (priv->connection,
|
||||
priv->registration_id);
|
||||
priv->registration_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (priv->connection);
|
||||
priv->connection = NULL;
|
||||
}
|
||||
|
||||
if (priv->introspection_data) {
|
||||
g_dbus_node_info_unref (priv->introspection_data);
|
||||
priv->introspection_data = NULL;
|
||||
}
|
||||
|
||||
if (priv->context) {
|
||||
g_signal_handlers_disconnect_by_data (priv->context, service);
|
||||
priv->context = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eekboard_service_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_finalize (GObject *object)
|
||||
{
|
||||
EekboardService *service = EEKBOARD_SERVICE(object);
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
g_free (priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (eekboard_service_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
|
||||
gboolean arg_visible, gpointer user_data) {
|
||||
EekboardService *service = user_data;
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
if (priv->context) {
|
||||
if (arg_visible) {
|
||||
eekboard_context_service_show_keyboard (priv->context);
|
||||
} else {
|
||||
eekboard_context_service_hide_keyboard (priv->context);
|
||||
}
|
||||
}
|
||||
sm_puri_osk0_complete_set_visible(object, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void on_visible(EekboardService *service,
|
||||
GParamSpec *pspec,
|
||||
EekboardContextService *context)
|
||||
{
|
||||
gboolean visible;
|
||||
EekboardServicePrivate *priv;
|
||||
|
||||
g_return_if_fail (EEKBOARD_IS_SERVICE (service));
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE (context));
|
||||
|
||||
priv = eekboard_service_get_instance_private (service);
|
||||
g_object_get (context, "visible", &visible, NULL);
|
||||
|
||||
sm_puri_osk0_set_visible(priv->dbus_interface, visible);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_constructed (GObject *object)
|
||||
{
|
||||
EekboardService *service = EEKBOARD_SERVICE(object);
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
priv->dbus_interface = sm_puri_osk0_skeleton_new();
|
||||
g_signal_connect(priv->dbus_interface, "handle-set-visible",
|
||||
G_CALLBACK(handle_set_visible), service);
|
||||
|
||||
if (priv->connection && priv->object_path) {
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(priv->dbus_interface),
|
||||
priv->connection,
|
||||
priv->object_path,
|
||||
&error)) {
|
||||
g_warning("Error registering dbus object: %s\n", error->message);
|
||||
g_clear_error(&error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_class_init (EekboardServiceClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
klass->create_context = NULL;
|
||||
|
||||
gobject_class->constructed = eekboard_service_constructed;
|
||||
gobject_class->set_property = eekboard_service_set_property;
|
||||
gobject_class->get_property = eekboard_service_get_property;
|
||||
gobject_class->dispose = eekboard_service_dispose;
|
||||
gobject_class->finalize = eekboard_service_finalize;
|
||||
|
||||
/**
|
||||
* EekboardService::destroyed:
|
||||
* @service: an #EekboardService
|
||||
*
|
||||
* The ::destroyed signal is emitted when the service is vanished.
|
||||
*/
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EekboardService:object-path:
|
||||
*
|
||||
* D-Bus object path.
|
||||
*/
|
||||
pspec = g_param_spec_string ("object-path",
|
||||
"Object-path",
|
||||
"Object-path",
|
||||
NULL,
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_OBJECT_PATH,
|
||||
pspec);
|
||||
|
||||
/**
|
||||
* EekboardService:connection:
|
||||
*
|
||||
* D-Bus connection.
|
||||
*/
|
||||
pspec = g_param_spec_object ("connection",
|
||||
"Connection",
|
||||
"Connection",
|
||||
G_TYPE_DBUS_CONNECTION,
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CONNECTION,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_service_init (EekboardService *self)
|
||||
{
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (self);
|
||||
|
||||
priv->context = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_service_new:
|
||||
* @connection: a #GDBusConnection
|
||||
* @object_path: object path
|
||||
*/
|
||||
EekboardService *
|
||||
eekboard_service_new (GDBusConnection *connection,
|
||||
const gchar *object_path)
|
||||
{
|
||||
return g_object_new (EEKBOARD_TYPE_SERVICE,
|
||||
"object-path", object_path,
|
||||
"connection", connection,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
eekboard_service_set_context(EekboardService *service,
|
||||
EekboardContextService *context)
|
||||
{
|
||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||
|
||||
g_return_if_fail (!priv->context);
|
||||
|
||||
priv->context = context;
|
||||
|
||||
g_signal_connect_swapped (priv->context,
|
||||
"notify::visible",
|
||||
G_CALLBACK(on_visible),
|
||||
service);
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef EEKBOARD_SERVICE_H
|
||||
#define EEKBOARD_SERVICE_H 1
|
||||
|
||||
#define __EEKBOARD_SERVICE_H_INSIDE__ 1
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEKBOARD_SERVICE_PATH "/sm/puri/OSK0"
|
||||
#define EEKBOARD_SERVICE_INTERFACE "sm.puri.OSK0"
|
||||
|
||||
#define EEKBOARD_TYPE_SERVICE (eekboard_service_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekboardService, eekboard_service, EEKBOARD, SERVICE, GObject)
|
||||
|
||||
/**
|
||||
* EekboardServiceClass:
|
||||
* @create_context: virtual function for creating a context
|
||||
*/
|
||||
struct _EekboardServiceClass {
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
EekboardContextService *(*create_context) (EekboardService *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eekboard_service_get_type (void) G_GNUC_CONST;
|
||||
EekboardService * eekboard_service_new (GDBusConnection *connection,
|
||||
const gchar *object_path);
|
||||
void eekboard_service_set_context(EekboardService *service,
|
||||
EekboardContextService *context);
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_SERVICE_H */
|
||||
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
* Copyright (C) 2019 Purism, SPC
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file is responsible for managing keycode data and emitting keycodes. */
|
||||
|
||||
#include "eekboard/key-emitter.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
|
||||
// TODO: decide whether it's this struct that carries the keyboard around in key-emitter or if the whole manager should be dragged around
|
||||
// if this is the carrier, then it should be made part of the manager
|
||||
// hint: check which fields need to be persisted between keypresses; which between keyboards
|
||||
typedef struct {
|
||||
struct zwp_virtual_keyboard_v1 *virtual_keyboard; // unowned copy
|
||||
struct xkb_keymap *keymap; // unowned copy
|
||||
XkbDescRec *xkb;
|
||||
guint modifier_keycodes[8];
|
||||
guint modifier_indices[MOD_IDX_LAST];
|
||||
guint group;
|
||||
} SeatEmitter;
|
||||
|
||||
|
||||
int send_virtual_keyboard_key(
|
||||
struct zwp_virtual_keyboard_v1 *keyboard,
|
||||
unsigned int keycode,
|
||||
unsigned is_press,
|
||||
uint32_t timestamp
|
||||
) {
|
||||
zwp_virtual_keyboard_v1_key(keyboard, timestamp, keycode, (unsigned)is_press);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
|
||||
static void
|
||||
update_modifier_info (SeatEmitter *client)
|
||||
{
|
||||
client->modifier_indices[MOD_IDX_SHIFT] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_SHIFT);
|
||||
client->modifier_indices[MOD_IDX_CAPS] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_CAPS);
|
||||
client->modifier_indices[MOD_IDX_CTRL] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_CTRL);
|
||||
client->modifier_indices[MOD_IDX_ALT] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_ALT);
|
||||
client->modifier_indices[MOD_IDX_NUM] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_NUM);
|
||||
client->modifier_indices[MOD_IDX_MOD3] = xkb_keymap_mod_get_index(client->keymap, "Mod3");
|
||||
client->modifier_indices[MOD_IDX_LOGO] = xkb_keymap_mod_get_index(client->keymap, XKB_MOD_NAME_LOGO);
|
||||
client->modifier_indices[MOD_IDX_ALTGR] = xkb_keymap_mod_get_index(client->keymap, "Mod5");
|
||||
client->modifier_indices[MOD_IDX_NUMLK] = xkb_keymap_mod_get_index(client->keymap, "NumLock");
|
||||
client->modifier_indices[MOD_IDX_ALSO_ALT] = xkb_keymap_mod_get_index(client->keymap, "Alt");
|
||||
client->modifier_indices[MOD_IDX_LVL3] = xkb_keymap_mod_get_index(client->keymap, "LevelThree");
|
||||
client->modifier_indices[MOD_IDX_LALT] = xkb_keymap_mod_get_index(client->keymap, "LAlt");
|
||||
client->modifier_indices[MOD_IDX_RALT] = xkb_keymap_mod_get_index(client->keymap, "RAlt");
|
||||
client->modifier_indices[MOD_IDX_RCONTROL] = xkb_keymap_mod_get_index(client->keymap, "RControl");
|
||||
client->modifier_indices[MOD_IDX_LCONTROL] = xkb_keymap_mod_get_index(client->keymap, "LControl");
|
||||
client->modifier_indices[MOD_IDX_SCROLLLK] = xkb_keymap_mod_get_index(client->keymap, "ScrollLock");
|
||||
client->modifier_indices[MOD_IDX_LVL5] = xkb_keymap_mod_get_index(client->keymap, "LevelFive");
|
||||
client->modifier_indices[MOD_IDX_ALSO_ALTGR] = xkb_keymap_mod_get_index(client->keymap, "AltGr");
|
||||
client->modifier_indices[MOD_IDX_META] = xkb_keymap_mod_get_index(client->keymap, "Meta");
|
||||
client->modifier_indices[MOD_IDX_SUPER] = xkb_keymap_mod_get_index(client->keymap, "Super");
|
||||
client->modifier_indices[MOD_IDX_HYPER] = xkb_keymap_mod_get_index(client->keymap, "Hyper");
|
||||
|
||||
/*
|
||||
for (xkb_mod_index_t i = 0;
|
||||
i < xkb_keymap_num_mods(client->keymap);
|
||||
i++) {
|
||||
g_log("squeek", G_LOG_LEVEL_DEBUG, "%s", xkb_keymap_mod_get_name(client->keymap, i));
|
||||
}*/
|
||||
}
|
||||
|
||||
static void
|
||||
send_fake_key (SeatEmitter *emitter,
|
||||
LevelKeyboard *keyboard,
|
||||
guint keycode,
|
||||
gboolean pressed,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, 0, 0, 0, 0);
|
||||
send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
|
||||
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
emit_key_activated (EekboardContextService *manager,
|
||||
LevelKeyboard *keyboard,
|
||||
guint keycode,
|
||||
gboolean pressed,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
/* FIXME: figure out how to deal with Client after key presses go through
|
||||
if (g_strcmp0 (eek_symbol_get_name (symbol), "cycle-keyboard") == 0) {
|
||||
client->keyboards_head = g_slist_next (client->keyboards_head);
|
||||
if (client->keyboards_head == NULL)
|
||||
client->keyboards_head = client->keyboards;
|
||||
eekboard_context_set_keyboard (client->context,
|
||||
GPOINTER_TO_UINT(client->keyboards_head->data),
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (eek_symbol_get_name (symbol), "preferences") == 0) {
|
||||
gchar *argv[2];
|
||||
GError *error;
|
||||
|
||||
argv[0] = g_build_filename (LIBEXECDIR, "eekboard-setup", NULL);
|
||||
argv[1] = NULL;
|
||||
|
||||
error = NULL;
|
||||
if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error)) {
|
||||
g_warning ("can't spawn %s: %s", argv[0], error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_free (argv[0]);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
SeatEmitter emitter = {0};
|
||||
emitter.virtual_keyboard = manager->virtual_keyboard;
|
||||
update_modifier_info (&emitter);
|
||||
send_fake_key (&emitter, keyboard, keycode, pressed, timestamp);
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
#ifndef KEYEMITTER_H
|
||||
#define KEYEMITTER_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "eek/eek.h"
|
||||
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
|
||||
/// Indices obtained by xkb_keymap_mod_get_name
|
||||
enum mod_indices {
|
||||
MOD_IDX_SHIFT,
|
||||
MOD_IDX_CAPS,
|
||||
MOD_IDX_CTRL,
|
||||
MOD_IDX_ALT,
|
||||
MOD_IDX_NUM,
|
||||
MOD_IDX_MOD3,
|
||||
MOD_IDX_LOGO,
|
||||
MOD_IDX_ALTGR,
|
||||
MOD_IDX_NUMLK, // Caution, not sure which is the right one
|
||||
MOD_IDX_ALSO_ALT, // Not sure why, alt emits the first alt on my setup
|
||||
MOD_IDX_LVL3,
|
||||
|
||||
// Not sure if the next 4 are used at all
|
||||
MOD_IDX_LALT,
|
||||
MOD_IDX_RALT,
|
||||
MOD_IDX_RCONTROL,
|
||||
MOD_IDX_LCONTROL,
|
||||
|
||||
MOD_IDX_SCROLLLK,
|
||||
MOD_IDX_LVL5,
|
||||
MOD_IDX_ALSO_ALTGR, // Not used on my layout
|
||||
MOD_IDX_META,
|
||||
MOD_IDX_SUPER,
|
||||
MOD_IDX_HYPER,
|
||||
|
||||
MOD_IDX_LAST,
|
||||
};
|
||||
|
||||
void
|
||||
emit_key_activated (EekboardContextService *manager, LevelKeyboard *keyboard,
|
||||
guint keycode,
|
||||
gboolean pressed, uint32_t timestamp);
|
||||
#endif // KEYEMITTER_H
|
||||
@ -5,6 +5,7 @@ use std::env;
|
||||
|
||||
fn main() -> () {
|
||||
check_builtin_layout(
|
||||
env::args().nth(1).expect("No argument given").as_str()
|
||||
env::args().nth(1).expect("No argument given").as_str(),
|
||||
env::args().nth(2).map(|s| s == "allow_missing_return").unwrap_or(false),
|
||||
);
|
||||
}
|
||||
|
||||
53
meson.build
53
meson.build
@ -1,7 +1,7 @@
|
||||
project(
|
||||
'squeekboard',
|
||||
'c', 'rust',
|
||||
version: '1.7.0',
|
||||
version: '1.10.0',
|
||||
license: 'GPLv3',
|
||||
meson_version: '>=0.51.0',
|
||||
default_options: [
|
||||
@ -19,6 +19,17 @@ add_project_arguments(
|
||||
'-Werror=missing-field-initializers',
|
||||
'-Werror=incompatible-pointer-types',
|
||||
'-Werror=int-conversion',
|
||||
'-Werror=redundant-decls',
|
||||
'-Werror=parentheses',
|
||||
'-Wformat-nonliteral',
|
||||
'-Wformat-security',
|
||||
'-Wformat',
|
||||
'-Winit-self',
|
||||
'-Wmaybe-uninitialized',
|
||||
'-Wold-style-definition',
|
||||
'-Wredundant-decls',
|
||||
'-Wstrict-prototypes',
|
||||
'-Wunused',
|
||||
],
|
||||
language: 'c'
|
||||
)
|
||||
@ -30,6 +41,16 @@ conf_data = configuration_data()
|
||||
if get_option('buildtype').startswith('debug')
|
||||
add_project_arguments('-DDEBUG=1', language : 'c')
|
||||
endif
|
||||
|
||||
if get_option('strict')
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Werror',
|
||||
],
|
||||
language: 'c'
|
||||
)
|
||||
endif
|
||||
|
||||
if get_option('buildtype') != 'plain'
|
||||
add_project_arguments('-fstack-protector-strong', language: 'c')
|
||||
endif
|
||||
@ -42,6 +63,7 @@ endif
|
||||
prefix = get_option('prefix')
|
||||
bindir = join_paths(prefix, get_option('bindir'))
|
||||
datadir = join_paths(prefix, get_option('datadir'))
|
||||
desktopdir = join_paths(datadir, 'applications')
|
||||
pkgdatadir = join_paths(datadir, meson.project_name())
|
||||
if get_option('depdatadir') == ''
|
||||
depdatadir = datadir
|
||||
@ -60,9 +82,36 @@ summary = [
|
||||
]
|
||||
message('\n'.join(summary))
|
||||
|
||||
# Rust deps are changing, depending on compile flags. Cargo can't handle it alone.
|
||||
# As a side effect, Cargo.toml never gets used.
|
||||
cargo_toml_in = files('Cargo.toml.in')
|
||||
path_data = configuration_data()
|
||||
path_data.set('path', meson.source_root())
|
||||
cargo_toml_base = configure_file(
|
||||
input: 'Cargo.toml.in',
|
||||
output: 'Cargo.toml.base',
|
||||
configuration: path_data,
|
||||
)
|
||||
|
||||
|
||||
cargo_deps = files('Cargo.deps')
|
||||
|
||||
if get_option('legacy') == true
|
||||
cargo_build_flags += ['--features', 'gtk_v0_5,gio_v0_5,rustc_less_1_36']
|
||||
cargo_deps = files('Cargo.deps.legacy')
|
||||
endif
|
||||
|
||||
cat = find_program('cat')
|
||||
cargo_toml = custom_target(
|
||||
'Cargo.toml',
|
||||
output: 'Cargo.toml',
|
||||
command: [cat, cargo_toml_base, cargo_deps],
|
||||
capture: true,
|
||||
)
|
||||
|
||||
dep_cargo = find_program('cargo')
|
||||
cargo_script = find_program('cargo.sh')
|
||||
cargo_build = find_program('cargo_build.sh')
|
||||
cargo_build = find_program('cargo_build.py')
|
||||
|
||||
subdir('data')
|
||||
subdir('protocols')
|
||||
|
||||
@ -6,3 +6,11 @@ option('depdatadir',
|
||||
option('tests',
|
||||
type: 'boolean', value: true,
|
||||
description: 'Whether to compile unit tests')
|
||||
|
||||
option('legacy',
|
||||
type: 'boolean', value: false,
|
||||
description: 'Build with Deban Buster versions of dependencies')
|
||||
|
||||
option('strict',
|
||||
type: 'boolean', value: true,
|
||||
description: 'Turn more warnings into errors')
|
||||
|
||||
17
squeekboard.doap
Normal file
17
squeekboard.doap
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:admin="http://webns.net/mvcb/">
|
||||
<name>squeekboard</name>
|
||||
<shortdesc>A Wayland virtual keyboard</shortdesc>
|
||||
<description>A virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.</description>
|
||||
<homepage rdf:resource="https://source.puri.sm/Librem5/squeekboard" />
|
||||
<bug-database rdf:resource="https://source.puri.sm/Librem5/squeekboard/issues" />
|
||||
<os>Linux</os>
|
||||
<license rdf:resource="http://usefulinc.com/doap/licenses/gpl" />
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Dorota Czaplejewicz</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:dorota.czaplejewicz@puri.sm" />
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
</Project>
|
||||
@ -6,12 +6,15 @@ use std::ffi::CString;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct KeySym(pub String);
|
||||
|
||||
/// Use to switch layouts
|
||||
type Level = String;
|
||||
/// Use to switch views
|
||||
type View = String;
|
||||
|
||||
/// Use to send modified keypresses
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Modifier {
|
||||
/// Control and Alt are the only modifiers
|
||||
/// which doesn't interfere with levels,
|
||||
/// so it's simple to implement as levels are deprecated in squeekboard.
|
||||
Control,
|
||||
Alt,
|
||||
}
|
||||
@ -20,21 +23,40 @@ pub enum Modifier {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Action {
|
||||
/// Switch to this view
|
||||
SetLevel(Level),
|
||||
SetView(View),
|
||||
/// Switch to a view and latch
|
||||
LockLevel {
|
||||
lock: Level,
|
||||
LockView {
|
||||
lock: View,
|
||||
/// When unlocked by pressing it or emitting a key
|
||||
unlock: Level,
|
||||
unlock: View,
|
||||
},
|
||||
/// Set this modifier TODO: release?
|
||||
SetModifier(Modifier),
|
||||
/// Hold this modifier for as long as the button is pressed
|
||||
ApplyModifier(Modifier),
|
||||
/// Submit some text
|
||||
Submit {
|
||||
/// Text to submit with input-method
|
||||
/// Text to submit with input-method.
|
||||
/// If None, then keys are to be submitted instead.
|
||||
text: Option<CString>,
|
||||
/// The key events this symbol submits when submitting text is not possible
|
||||
keys: Vec<KeySym>,
|
||||
},
|
||||
/// Erase a position behind the cursor
|
||||
Erase,
|
||||
ShowPreferences,
|
||||
}
|
||||
|
||||
impl Action {
|
||||
pub fn is_locked(&self, view_name: &str) -> bool {
|
||||
match self {
|
||||
Action::LockView { lock, unlock: _ } => lock == view_name,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_active(&self, view_name: &str) -> bool {
|
||||
match self {
|
||||
Action::SetView(view) => view == view_name,
|
||||
Action::LockView { lock, unlock: _ } => lock == view_name,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
545
src/data.rs
545
src/data.rs
@ -15,13 +15,14 @@ use std::vec::Vec;
|
||||
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use ::action;
|
||||
use ::keyboard::{
|
||||
KeyState, PressType,
|
||||
generate_keymap, generate_keycodes, FormattingError
|
||||
generate_keymaps, generate_keycodes, KeyCode, FormattingError
|
||||
};
|
||||
use ::layout;
|
||||
use ::layout::ArrangementKind;
|
||||
use ::logging::PrintWarnings;
|
||||
use ::logging;
|
||||
use ::resources;
|
||||
use ::util::c::as_str;
|
||||
use ::util::hash_map_map;
|
||||
@ -31,7 +32,7 @@ use ::xdg;
|
||||
use serde::Deserialize;
|
||||
use std::io::BufReader;
|
||||
use std::iter::FromIterator;
|
||||
use ::logging::WarningHandler;
|
||||
use ::logging::Warn;
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
@ -96,6 +97,8 @@ impl fmt::Display for DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
type LayoutSource = (ArrangementKind, DataSource);
|
||||
|
||||
/// Lists possible sources, with 0 as the most preferred one
|
||||
/// Trying order: native lang of the right kind, native base,
|
||||
/// fallback lang of the right kind, fallback base
|
||||
@ -103,61 +106,82 @@ fn list_layout_sources(
|
||||
name: &str,
|
||||
kind: ArrangementKind,
|
||||
keyboards_path: Option<PathBuf>,
|
||||
) -> Vec<(ArrangementKind, DataSource)> {
|
||||
let mut ret = Vec::new();
|
||||
{
|
||||
fn name_with_arrangement(name: String, kind: &ArrangementKind)
|
||||
-> String
|
||||
{
|
||||
match kind {
|
||||
ArrangementKind::Base => name,
|
||||
ArrangementKind::Wide => name + "_wide",
|
||||
}
|
||||
}
|
||||
|
||||
let mut add_by_name = |name: &str, kind: &ArrangementKind| {
|
||||
if let Some(path) = keyboards_path.clone() {
|
||||
ret.push((
|
||||
kind.clone(),
|
||||
DataSource::File(
|
||||
path.join(name.to_owned()).with_extension("yaml")
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
) -> Vec<LayoutSource> {
|
||||
// Just a simplification of often called code.
|
||||
let add_by_name = |
|
||||
mut ret: Vec<LayoutSource>,
|
||||
name: &str,
|
||||
kind: &ArrangementKind,
|
||||
| -> Vec<LayoutSource> {
|
||||
if let Some(path) = keyboards_path.clone() {
|
||||
ret.push((
|
||||
kind.clone(),
|
||||
DataSource::Resource(name.into())
|
||||
));
|
||||
};
|
||||
DataSource::File(
|
||||
path.join(name.to_owned()).with_extension("yaml")
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
match &kind {
|
||||
ArrangementKind::Base => {},
|
||||
ret.push((
|
||||
kind.clone(),
|
||||
DataSource::Resource(name.into())
|
||||
));
|
||||
ret
|
||||
};
|
||||
|
||||
// Another grouping.
|
||||
let add_by_kind = |ret, name: &str, kind| {
|
||||
let ret = match kind {
|
||||
&ArrangementKind::Base => ret,
|
||||
kind => add_by_name(
|
||||
&name_with_arrangement(name.into(), &kind),
|
||||
&kind,
|
||||
ret,
|
||||
&name_with_arrangement(name.into(), kind),
|
||||
kind,
|
||||
),
|
||||
};
|
||||
|
||||
add_by_name(name, &ArrangementKind::Base);
|
||||
add_by_name(ret, name, &ArrangementKind::Base)
|
||||
};
|
||||
|
||||
match &kind {
|
||||
ArrangementKind::Base => {},
|
||||
kind => add_by_name(
|
||||
&name_with_arrangement(FALLBACK_LAYOUT_NAME.into(), &kind),
|
||||
&kind,
|
||||
),
|
||||
};
|
||||
|
||||
add_by_name(FALLBACK_LAYOUT_NAME, &ArrangementKind::Base);
|
||||
fn name_with_arrangement(name: String, kind: &ArrangementKind) -> String {
|
||||
match kind {
|
||||
ArrangementKind::Base => name,
|
||||
ArrangementKind::Wide => name + "_wide",
|
||||
}
|
||||
}
|
||||
ret
|
||||
|
||||
let ret = Vec::new();
|
||||
|
||||
// Name as given takes priority.
|
||||
let ret = add_by_kind(ret, name, &kind);
|
||||
|
||||
// Then try non-alternative name if applicable (`us` for `us+colemak`).
|
||||
let ret = {
|
||||
let mut parts = name.splitn(2, '+');
|
||||
match parts.next() {
|
||||
Some(base) => {
|
||||
// The name is already equal to base, so it was already added.
|
||||
if base == name { ret }
|
||||
else {
|
||||
add_by_kind(ret, base, &kind)
|
||||
}
|
||||
},
|
||||
// The layout's base name starts with a "+". Weird but OK.
|
||||
None => {
|
||||
log_print!(logging::Level::Surprise, "Base layout name is empty: {}", name);
|
||||
ret
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// No other choices left, so give anything.
|
||||
add_by_kind(ret, FALLBACK_LAYOUT_NAME.into(), &kind)
|
||||
}
|
||||
|
||||
fn load_layout_data(source: DataSource)
|
||||
-> Result<::layout::LayoutData, LoadError>
|
||||
{
|
||||
let handler = PrintWarnings{};
|
||||
let handler = logging::Print {};
|
||||
match source {
|
||||
DataSource::File(path) => {
|
||||
Layout::from_file(path.clone())
|
||||
@ -190,16 +214,21 @@ fn load_layout_data_with_fallback(
|
||||
(
|
||||
LoadError::BadData(Error::Missing(e)),
|
||||
DataSource::File(file)
|
||||
) => eprintln!( // TODO: print in debug logging level
|
||||
) => log_print!(
|
||||
logging::Level::Debug,
|
||||
"Tried file {:?}, but it's missing: {}",
|
||||
file, e
|
||||
),
|
||||
(e, source) => eprintln!(
|
||||
(e, source) => log_print!(
|
||||
logging::Level::Warning,
|
||||
"Failed to load layout from {}: {}, skipping",
|
||||
source, e
|
||||
),
|
||||
},
|
||||
Ok(layout) => return (kind, layout),
|
||||
Ok(layout) => {
|
||||
log_print!(logging::Level::Info, "Loaded layout {}", source);
|
||||
return (kind, layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,14 +263,20 @@ type ButtonIds = String;
|
||||
#[derive(Debug, Default, Deserialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ButtonMeta {
|
||||
/// Special action to perform on activation. Conflicts with keysym, text.
|
||||
// TODO: structure (action, keysym, text, modifier) as an enum
|
||||
// to detect conflicts and missing values at compile time
|
||||
/// Special action to perform on activation.
|
||||
/// Conflicts with keysym, text, modifier.
|
||||
action: Option<Action>,
|
||||
/// The name of the XKB keysym to emit on activation.
|
||||
/// Conflicts with action, text
|
||||
/// Conflicts with action, text, modifier.
|
||||
keysym: Option<String>,
|
||||
/// The text to submit on activation. Will be derived from ID if not present
|
||||
/// Conflicts with action, keysym
|
||||
/// Conflicts with action, keysym, modifier.
|
||||
text: Option<String>,
|
||||
/// The modifier to apply while the key is locked
|
||||
/// Conflicts with action, keysym, text
|
||||
modifier: Option<Modifier>,
|
||||
/// If not present, will be derived from text or the button ID
|
||||
label: Option<String>,
|
||||
/// Conflicts with label
|
||||
@ -259,6 +294,23 @@ enum Action {
|
||||
SetView(String),
|
||||
#[serde(rename="show_prefs")]
|
||||
ShowPrefs,
|
||||
/// Remove last character
|
||||
#[serde(rename="erase")]
|
||||
Erase,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum Modifier {
|
||||
Control,
|
||||
Shift,
|
||||
Lock,
|
||||
#[serde(alias="Mod1")]
|
||||
Alt,
|
||||
Mod2,
|
||||
Mod3,
|
||||
Mod4,
|
||||
Mod5,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
@ -330,7 +382,7 @@ impl Layout {
|
||||
serde_yaml::from_reader(infile).map_err(Error::Yaml)
|
||||
}
|
||||
|
||||
pub fn build<H: WarningHandler>(self, mut warning_handler: H)
|
||||
pub fn build<H: logging::Handler>(self, mut warning_handler: H)
|
||||
-> (Result<::layout::LayoutData, FormattingError>, H)
|
||||
{
|
||||
let button_names = self.views.values()
|
||||
@ -353,53 +405,45 @@ impl Layout {
|
||||
)
|
||||
)}).collect();
|
||||
|
||||
let keymap: HashMap<String, u32> = generate_keycodes(
|
||||
button_actions.iter()
|
||||
.filter_map(|(_name, action)| {
|
||||
match action {
|
||||
::action::Action::Submit {
|
||||
text: _, keys,
|
||||
} => Some(keys),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.map(|named_keysym| named_keysym.0.as_str())
|
||||
let symbolmap: HashMap<String, KeyCode> = generate_keycodes(
|
||||
extract_symbol_names(&button_actions)
|
||||
);
|
||||
|
||||
let button_states = button_actions.into_iter().map(|(name, action)| {
|
||||
let keycodes = match &action {
|
||||
::action::Action::Submit { text: _, keys } => {
|
||||
keys.iter().map(|named_keycode| {
|
||||
*keymap.get(named_keycode.0.as_str())
|
||||
.expect(
|
||||
format!(
|
||||
"keycode {} in key {} missing from keymap",
|
||||
named_keycode.0,
|
||||
name
|
||||
).as_str()
|
||||
)
|
||||
}).collect()
|
||||
},
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(
|
||||
name.into(),
|
||||
KeyState {
|
||||
pressed: PressType::Released,
|
||||
locked: false,
|
||||
keycodes,
|
||||
action,
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
let button_states = HashMap::<String, KeyState>::from_iter(
|
||||
button_states
|
||||
button_actions.into_iter().map(|(name, action)| {
|
||||
let keycodes = match &action {
|
||||
::action::Action::Submit { text: _, keys } => {
|
||||
keys.iter().map(|named_keysym| {
|
||||
symbolmap.get(named_keysym.0.as_str())
|
||||
.expect(
|
||||
format!(
|
||||
"keysym {} in key {} missing from symbol map",
|
||||
named_keysym.0,
|
||||
name
|
||||
).as_str()
|
||||
)
|
||||
.clone()
|
||||
}).collect()
|
||||
},
|
||||
action::Action::Erase => vec![
|
||||
symbolmap.get("BackSpace")
|
||||
.expect(&format!("BackSpace missing from symbol map"))
|
||||
.clone(),
|
||||
],
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(
|
||||
name.into(),
|
||||
KeyState {
|
||||
pressed: PressType::Released,
|
||||
keycodes,
|
||||
action,
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: generate from symbols
|
||||
let keymap_str = match generate_keymap(&button_states) {
|
||||
let keymaps = match generate_keymaps(symbolmap) {
|
||||
Err(e) => { return (Err(e), warning_handler) },
|
||||
Ok(v) => v,
|
||||
};
|
||||
@ -412,8 +456,8 @@ impl Layout {
|
||||
)}
|
||||
);
|
||||
|
||||
let views = HashMap::from_iter(
|
||||
self.views.iter().map(|(name, view)| {
|
||||
let views: Vec<_> = self.views.iter()
|
||||
.map(|(name, view)| {
|
||||
let rows = view.iter().map(|row| {
|
||||
let buttons = row.split_ascii_whitespace()
|
||||
.map(|name| {
|
||||
@ -427,30 +471,46 @@ impl Layout {
|
||||
&mut warning_handler,
|
||||
))
|
||||
});
|
||||
::layout::Row {
|
||||
angle: 0,
|
||||
buttons: add_offsets(
|
||||
layout::Row::new(
|
||||
add_offsets(
|
||||
buttons,
|
||||
|button| button.size.width,
|
||||
).collect()
|
||||
}
|
||||
)
|
||||
});
|
||||
let rows = add_offsets(rows, |row| row.get_height())
|
||||
let rows = add_offsets(rows, |row| row.get_size().height)
|
||||
.collect();
|
||||
(
|
||||
name.clone(),
|
||||
layout::View::new(rows)
|
||||
)
|
||||
})
|
||||
);
|
||||
}).collect();
|
||||
|
||||
// Center views on the same point.
|
||||
let views = {
|
||||
let total_size = layout::View::calculate_super_size(
|
||||
views.iter().map(|(_name, view)| view).collect()
|
||||
);
|
||||
|
||||
HashMap::from_iter(views.into_iter().map(|(name, view)| (
|
||||
name,
|
||||
(
|
||||
layout::c::Point {
|
||||
x: (total_size.width - view.get_size().width) / 2.0,
|
||||
y: (total_size.height - view.get_size().height) / 2.0,
|
||||
},
|
||||
view,
|
||||
),
|
||||
)))
|
||||
};
|
||||
|
||||
(
|
||||
Ok(::layout::LayoutData {
|
||||
views: views,
|
||||
keymap_str: {
|
||||
keymaps: keymaps.into_iter().map(|keymap_str|
|
||||
CString::new(keymap_str)
|
||||
.expect("Invalid keymap string generated")
|
||||
},
|
||||
).collect(),
|
||||
// FIXME: use a dedicated field
|
||||
margins: layout::Margins {
|
||||
top: self.margins.top,
|
||||
@ -464,7 +524,7 @@ impl Layout {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_action<H: WarningHandler>(
|
||||
fn create_action<H: logging::Handler>(
|
||||
button_info: &HashMap<String, ButtonMeta>,
|
||||
name: &str,
|
||||
view_names: Vec<&String>,
|
||||
@ -482,27 +542,35 @@ fn create_action<H: WarningHandler>(
|
||||
Action(Action),
|
||||
Text(String),
|
||||
Keysym(String),
|
||||
Modifier(Modifier),
|
||||
};
|
||||
|
||||
let submission = match (
|
||||
&symbol_meta.action,
|
||||
&symbol_meta.keysym,
|
||||
&symbol_meta.text
|
||||
&symbol_meta.text,
|
||||
&symbol_meta.modifier,
|
||||
) {
|
||||
(Some(action), None, None) => SubmitData::Action(action.clone()),
|
||||
(None, Some(keysym), None) => SubmitData::Keysym(keysym.clone()),
|
||||
(None, None, Some(text)) => SubmitData::Text(text.clone()),
|
||||
(None, None, None) => SubmitData::Text(name.into()),
|
||||
(Some(action), None, None, None) => SubmitData::Action(action.clone()),
|
||||
(None, Some(keysym), None, None) => SubmitData::Keysym(keysym.clone()),
|
||||
(None, None, Some(text), None) => SubmitData::Text(text.clone()),
|
||||
(None, None, None, Some(modifier)) => {
|
||||
SubmitData::Modifier(modifier.clone())
|
||||
},
|
||||
(None, None, None, None) => SubmitData::Text(name.into()),
|
||||
_ => {
|
||||
warning_handler.handle(&format!(
|
||||
"Button {} has more than one of (action, keysym, text)",
|
||||
name
|
||||
));
|
||||
warning_handler.handle(
|
||||
logging::Level::Warning,
|
||||
&format!(
|
||||
"Button {} has more than one of (action, keysym, text, modifier)",
|
||||
name,
|
||||
),
|
||||
);
|
||||
SubmitData::Text("".into())
|
||||
},
|
||||
};
|
||||
|
||||
fn filter_view_name<H: WarningHandler>(
|
||||
fn filter_view_name<H: logging::Handler>(
|
||||
button_name: &str,
|
||||
view_name: String,
|
||||
view_names: &Vec<&String>,
|
||||
@ -511,10 +579,13 @@ fn create_action<H: WarningHandler>(
|
||||
if view_names.contains(&&view_name) {
|
||||
view_name
|
||||
} else {
|
||||
warning_handler.handle(&format!("Button {} switches to missing view {}",
|
||||
button_name,
|
||||
view_name,
|
||||
));
|
||||
warning_handler.handle(
|
||||
logging::Level::Warning,
|
||||
&format!("Button {} switches to missing view {}",
|
||||
button_name,
|
||||
view_name,
|
||||
),
|
||||
);
|
||||
"base".into()
|
||||
}
|
||||
}
|
||||
@ -522,7 +593,7 @@ fn create_action<H: WarningHandler>(
|
||||
match submission {
|
||||
SubmitData::Action(
|
||||
Action::SetView(view_name)
|
||||
) => ::action::Action::SetLevel(
|
||||
) => ::action::Action::SetView(
|
||||
filter_view_name(
|
||||
name, view_name.clone(), &view_names,
|
||||
warning_handler,
|
||||
@ -530,7 +601,7 @@ fn create_action<H: WarningHandler>(
|
||||
),
|
||||
SubmitData::Action(Action::Locking {
|
||||
lock_view, unlock_view
|
||||
}) => ::action::Action::LockLevel {
|
||||
}) => ::action::Action::LockView {
|
||||
lock: filter_view_name(
|
||||
name,
|
||||
lock_view.clone(),
|
||||
@ -547,33 +618,31 @@ fn create_action<H: WarningHandler>(
|
||||
SubmitData::Action(
|
||||
Action::ShowPrefs
|
||||
) => ::action::Action::ShowPreferences,
|
||||
SubmitData::Action(Action::Erase) => action::Action::Erase,
|
||||
SubmitData::Keysym(keysym) => ::action::Action::Submit {
|
||||
text: None,
|
||||
keys: vec!(::action::KeySym(
|
||||
match keysym_valid(keysym.as_str()) {
|
||||
true => keysym.clone(),
|
||||
false => {
|
||||
warning_handler.handle(&format!(
|
||||
"Keysym name invalid: {}",
|
||||
keysym,
|
||||
));
|
||||
warning_handler.handle(
|
||||
logging::Level::Warning,
|
||||
&format!(
|
||||
"Keysym name invalid: {}",
|
||||
keysym,
|
||||
),
|
||||
);
|
||||
"space".into() // placeholder
|
||||
},
|
||||
}
|
||||
)),
|
||||
},
|
||||
SubmitData::Text(text) => ::action::Action::Submit {
|
||||
text: {
|
||||
CString::new(text.clone())
|
||||
.map_err(|e| {
|
||||
warning_handler.handle(&format!(
|
||||
"Text {} contains problems: {:?}",
|
||||
text,
|
||||
e
|
||||
));
|
||||
e
|
||||
}).ok()
|
||||
},
|
||||
text: CString::new(text.clone()).or_warn(
|
||||
warning_handler,
|
||||
logging::Problem::Warning,
|
||||
&format!("Text {} contains problems", text),
|
||||
),
|
||||
keys: text.chars().map(|codepoint| {
|
||||
let codepoint_string = codepoint.to_string();
|
||||
::action::KeySym(match keysym_valid(codepoint_string.as_str()) {
|
||||
@ -581,13 +650,33 @@ fn create_action<H: WarningHandler>(
|
||||
false => format!("U{:04X}", codepoint as u32),
|
||||
})
|
||||
}).collect(),
|
||||
}
|
||||
},
|
||||
SubmitData::Modifier(modifier) => match modifier {
|
||||
Modifier::Control => action::Action::ApplyModifier(
|
||||
action::Modifier::Control,
|
||||
),
|
||||
Modifier::Alt => action::Action::ApplyModifier(
|
||||
action::Modifier::Alt,
|
||||
),
|
||||
unsupported_modifier => {
|
||||
warning_handler.handle(
|
||||
logging::Level::Bug,
|
||||
&format!(
|
||||
"Modifier {:?} unsupported", unsupported_modifier,
|
||||
),
|
||||
);
|
||||
action::Action::Submit {
|
||||
text: None,
|
||||
keys: Vec::new(),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Since this will receive user-provided data,
|
||||
/// all .expect() on them should be turned into soft fails
|
||||
fn create_button<H: WarningHandler>(
|
||||
fn create_button<H: logging::Handler>(
|
||||
button_info: &HashMap<String, ButtonMeta>,
|
||||
outlines: &HashMap<String, Outline>,
|
||||
name: &str,
|
||||
@ -611,14 +700,11 @@ fn create_button<H: WarningHandler>(
|
||||
} else if let Some(text) = &button_meta.text {
|
||||
::layout::Label::Text(
|
||||
CString::new(text.as_str())
|
||||
.unwrap_or_else(|e| {
|
||||
warning_handler.handle(&format!(
|
||||
"Text {} is invalid: {}",
|
||||
text,
|
||||
e,
|
||||
));
|
||||
CString::new("").unwrap()
|
||||
})
|
||||
.or_warn(
|
||||
warning_handler,
|
||||
logging::Problem::Warning,
|
||||
&format!("Text {} is invalid", text),
|
||||
).unwrap_or_else(|| CString::new("").unwrap())
|
||||
)
|
||||
} else {
|
||||
::layout::Label::Text(cname.clone())
|
||||
@ -629,7 +715,10 @@ fn create_button<H: WarningHandler>(
|
||||
if outlines.contains_key(outline) {
|
||||
outline.clone()
|
||||
} else {
|
||||
warning_handler.handle(&format!("Outline named {} does not exist! Using default for button {}", outline, name));
|
||||
warning_handler.handle(
|
||||
logging::Level::Warning,
|
||||
&format!("Outline named {} does not exist! Using default for button {}", outline, name)
|
||||
);
|
||||
"default".into()
|
||||
}
|
||||
}
|
||||
@ -638,12 +727,11 @@ fn create_button<H: WarningHandler>(
|
||||
|
||||
let outline = outlines.get(&outline_name)
|
||||
.map(|outline| (*outline).clone())
|
||||
.unwrap_or_else(|| {
|
||||
warning_handler.handle(
|
||||
&format!("No default outline defined! Using 1x1!")
|
||||
);
|
||||
Outline { width: 1f64, height: 1f64 }
|
||||
});
|
||||
.or_warn(
|
||||
warning_handler,
|
||||
logging::Problem::Warning,
|
||||
"No default outline defined! Using 1x1!",
|
||||
).unwrap_or(Outline { width: 1f64, height: 1f64 });
|
||||
|
||||
layout::Button {
|
||||
name: cname,
|
||||
@ -658,17 +746,50 @@ fn create_button<H: WarningHandler>(
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_symbol_names<'a>(actions: &'a [(&str, action::Action)])
|
||||
-> impl Iterator<Item=String> + 'a
|
||||
{
|
||||
actions.iter()
|
||||
.filter_map(|(_name, act)| {
|
||||
match act {
|
||||
action::Action::Submit {
|
||||
text: _, keys,
|
||||
} => Some(keys.clone()),
|
||||
action::Action::Erase => Some(vec!(action::KeySym("BackSpace".into()))),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.map(|named_keysym| named_keysym.0)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::error::Error as ErrorTrait;
|
||||
use ::logging::PanicWarn;
|
||||
|
||||
use ::logging::ProblemPanic;
|
||||
|
||||
fn path_from_root(file: &'static str) -> PathBuf {
|
||||
let source_dir = env::var("SOURCE_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|e| {
|
||||
if let env::VarError::NotPresent = e {
|
||||
let this_file = file!();
|
||||
PathBuf::from(this_file)
|
||||
.parent().unwrap()
|
||||
.parent().unwrap()
|
||||
.into()
|
||||
} else {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
});
|
||||
source_dir.join(file)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_path() {
|
||||
assert_eq!(
|
||||
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
|
||||
Layout::from_file(path_from_root("tests/layout.yaml")).unwrap(),
|
||||
Layout {
|
||||
margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
|
||||
views: hashmap!(
|
||||
@ -680,6 +801,7 @@ mod tests {
|
||||
keysym: None,
|
||||
action: None,
|
||||
text: None,
|
||||
modifier: None,
|
||||
label: Some("test".into()),
|
||||
outline: None,
|
||||
}
|
||||
@ -694,13 +816,14 @@ mod tests {
|
||||
/// Check if the default protection works
|
||||
#[test]
|
||||
fn test_empty_views() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout2.yaml"));
|
||||
let out = Layout::from_file(path_from_root("tests/layout2.yaml"));
|
||||
match out {
|
||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||
Err(e) => {
|
||||
let mut handled = false;
|
||||
if let Error::Yaml(ye) = &e {
|
||||
handled = ye.description() == "missing field `views`";
|
||||
handled = ye.to_string()
|
||||
.starts_with("missing field `views`");
|
||||
};
|
||||
if !handled {
|
||||
println!("Unexpected error {:?}", e);
|
||||
@ -712,13 +835,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_extra_field() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout3.yaml"));
|
||||
let out = Layout::from_file(path_from_root("tests/layout3.yaml"));
|
||||
match out {
|
||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||
Err(e) => {
|
||||
let mut handled = false;
|
||||
if let Error::Yaml(ye) = &e {
|
||||
handled = ye.description()
|
||||
handled = ye.to_string()
|
||||
.starts_with("unknown field `bad_field`");
|
||||
};
|
||||
if !handled {
|
||||
@ -731,14 +854,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_layout_punctuation() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key1.yaml"))
|
||||
let out = Layout::from_file(path_from_root("tests/layout_key1.yaml"))
|
||||
.unwrap()
|
||||
.build(PanicWarn).0
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.get_buttons()[0].1
|
||||
.label,
|
||||
::layout::Label::Text(CString::new("test").unwrap())
|
||||
);
|
||||
@ -746,14 +869,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_layout_unicode() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key2.yaml"))
|
||||
let out = Layout::from_file(path_from_root("tests/layout_key2.yaml"))
|
||||
.unwrap()
|
||||
.build(PanicWarn).0
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.get_buttons()[0].1
|
||||
.label,
|
||||
::layout::Label::Text(CString::new("test").unwrap())
|
||||
);
|
||||
@ -762,24 +885,41 @@ mod tests {
|
||||
/// Test multiple codepoints
|
||||
#[test]
|
||||
fn test_layout_unicode_multi() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key3.yaml"))
|
||||
let out = Layout::from_file(path_from_root("tests/layout_key3.yaml"))
|
||||
.unwrap()
|
||||
.build(PanicWarn).0
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.buttons[0].1
|
||||
.get_buttons()[0].1
|
||||
.state.borrow()
|
||||
.keycodes.len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
/// Test if erase yields a useable keycode
|
||||
#[test]
|
||||
fn test_layout_erase() {
|
||||
let out = Layout::from_file(path_from_root("tests/layout_erase.yaml"))
|
||||
.unwrap()
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"].1
|
||||
.get_rows()[0].1
|
||||
.get_buttons()[0].1
|
||||
.state.borrow()
|
||||
.keycodes.len(),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parsing_fallback() {
|
||||
assert!(Layout::from_resource(FALLBACK_LAYOUT_NAME)
|
||||
.map(|layout| layout.build(PanicWarn).0.unwrap())
|
||||
.map(|layout| layout.build(ProblemPanic).0.unwrap())
|
||||
.is_ok()
|
||||
);
|
||||
}
|
||||
@ -800,7 +940,26 @@ mod tests {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// If layout contains a "+", it should reach for what's in front of it too.
|
||||
#[test]
|
||||
fn fallbacks_order_base() {
|
||||
let sources = list_layout_sources("nb+aliens", ArrangementKind::Base, None);
|
||||
|
||||
assert_eq!(
|
||||
sources,
|
||||
vec!(
|
||||
(ArrangementKind::Base, DataSource::Resource("nb+aliens".into())),
|
||||
(ArrangementKind::Base, DataSource::Resource("nb".into())),
|
||||
(
|
||||
ArrangementKind::Base,
|
||||
DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn unicode_keysym() {
|
||||
let keysym = xkb::keysym_from_name(
|
||||
@ -821,13 +980,14 @@ mod tests {
|
||||
keysym: None,
|
||||
text: None,
|
||||
action: None,
|
||||
modifier: None,
|
||||
label: Some("test".into()),
|
||||
outline: None,
|
||||
}
|
||||
},
|
||||
".",
|
||||
Vec::new(),
|
||||
&mut PanicWarn,
|
||||
&mut ProblemPanic,
|
||||
),
|
||||
::action::Action::Submit {
|
||||
text: Some(CString::new(".").unwrap()),
|
||||
@ -838,9 +998,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_layout_margins() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_margins.yaml"))
|
||||
let out = Layout::from_file(path_from_root("tests/layout_margins.yaml"))
|
||||
.unwrap()
|
||||
.build(PanicWarn).0
|
||||
.build(ProblemPanic).0
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.margins,
|
||||
@ -852,4 +1012,35 @@ mod tests {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_symbols() {
|
||||
let actions = [(
|
||||
"ac",
|
||||
action::Action::Submit {
|
||||
text: None,
|
||||
keys: vec![
|
||||
action::KeySym("a".into()),
|
||||
action::KeySym("c".into()),
|
||||
],
|
||||
},
|
||||
)];
|
||||
assert_eq!(
|
||||
extract_symbol_names(&actions[..]).collect::<Vec<_>>(),
|
||||
vec!["a", "c"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_symbols_erase() {
|
||||
let actions = [(
|
||||
"Erase",
|
||||
action::Action::Erase,
|
||||
)];
|
||||
assert_eq!(
|
||||
extract_symbol_names(&actions[..]).collect::<Vec<_>>(),
|
||||
vec!["BackSpace"],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
124
src/dbus.c
Normal file
124
src/dbus.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "dbus.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
void
|
||||
dbus_handler_destroy(DBusHandler *service)
|
||||
{
|
||||
g_free (service->object_path);
|
||||
|
||||
if (service->connection) {
|
||||
if (service->registration_id > 0) {
|
||||
g_dbus_connection_unregister_object (service->connection,
|
||||
service->registration_id);
|
||||
service->registration_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (service->connection);
|
||||
service->connection = NULL;
|
||||
}
|
||||
|
||||
if (service->introspection_data) {
|
||||
g_dbus_node_info_unref (service->introspection_data);
|
||||
service->introspection_data = NULL;
|
||||
}
|
||||
|
||||
if (service->context) {
|
||||
g_signal_handlers_disconnect_by_data (service->context, service);
|
||||
service->context = NULL;
|
||||
}
|
||||
|
||||
free(service);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
|
||||
gboolean arg_visible, gpointer user_data) {
|
||||
DBusHandler *service = user_data;
|
||||
|
||||
if (service->context) {
|
||||
if (arg_visible) {
|
||||
server_context_service_show_keyboard (service->context);
|
||||
} else {
|
||||
server_context_service_hide_keyboard (service->context);
|
||||
}
|
||||
}
|
||||
sm_puri_osk0_complete_set_visible(object, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void on_visible(DBusHandler *service,
|
||||
GParamSpec *pspec,
|
||||
ServerContextService *context)
|
||||
{
|
||||
(void)pspec;
|
||||
gboolean visible;
|
||||
|
||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (context));
|
||||
|
||||
g_object_get (context, "visible", &visible, NULL);
|
||||
|
||||
sm_puri_osk0_set_visible(service->dbus_interface, visible);
|
||||
}
|
||||
|
||||
DBusHandler *
|
||||
dbus_handler_new (GDBusConnection *connection,
|
||||
const gchar *object_path)
|
||||
{
|
||||
DBusHandler *self = calloc(1, sizeof(DBusHandler));
|
||||
self->object_path = g_strdup(object_path);
|
||||
self->connection = connection;
|
||||
|
||||
self->dbus_interface = sm_puri_osk0_skeleton_new();
|
||||
g_signal_connect(self->dbus_interface, "handle-set-visible",
|
||||
G_CALLBACK(handle_set_visible), self);
|
||||
|
||||
if (self->connection && self->object_path) {
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(self->dbus_interface),
|
||||
self->connection,
|
||||
self->object_path,
|
||||
&error)) {
|
||||
g_warning("Error registering dbus object: %s\n", error->message);
|
||||
g_clear_error(&error);
|
||||
// TODO: return an error
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
dbus_handler_set_ui_context(DBusHandler *service,
|
||||
ServerContextService *context)
|
||||
{
|
||||
g_return_if_fail (!service->context);
|
||||
|
||||
service->context = context;
|
||||
|
||||
g_signal_connect_swapped (service->context,
|
||||
"notify::visible",
|
||||
G_CALLBACK(on_visible),
|
||||
service);
|
||||
}
|
||||
48
src/dbus.h
Normal file
48
src/dbus.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
* Copyright (C) 2019-2020 Purism, SPC
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DBUS_H_
|
||||
#define DBUS_H_ 1
|
||||
|
||||
#include "server-context-service.h"
|
||||
|
||||
#include "sm.puri.OSK0.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define DBUS_SERVICE_PATH "/sm/puri/OSK0"
|
||||
#define DBUS_SERVICE_INTERFACE "sm.puri.OSK0"
|
||||
|
||||
typedef struct _DBusHandler
|
||||
{
|
||||
GDBusConnection *connection;
|
||||
SmPuriOSK0 *dbus_interface;
|
||||
GDBusNodeInfo *introspection_data;
|
||||
guint registration_id;
|
||||
char *object_path;
|
||||
|
||||
ServerContextService *context; // unowned reference
|
||||
} DBusHandler;
|
||||
|
||||
DBusHandler * dbus_handler_new (GDBusConnection *connection,
|
||||
const gchar *object_path);
|
||||
void dbus_handler_set_ui_context(DBusHandler *service,
|
||||
ServerContextService *context);
|
||||
void dbus_handler_destroy(DBusHandler*);
|
||||
G_END_DECLS
|
||||
#endif /* DBUS_H_ */
|
||||
@ -3,9 +3,11 @@
|
||||
use cairo;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use ::action::Action;
|
||||
use ::keyboard;
|
||||
use ::layout::{ Button, Layout };
|
||||
use ::layout::c::{ EekGtkKeyboard, Point };
|
||||
use ::submission::Submission;
|
||||
|
||||
use glib::translate::FromGlibPtrNone;
|
||||
use gtk::WidgetExt;
|
||||
@ -37,30 +39,37 @@ mod c {
|
||||
);
|
||||
}
|
||||
|
||||
/// Draws all buttons that are not in the base state
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_draw_all_changed(
|
||||
layout: *mut Layout,
|
||||
renderer: EekRenderer,
|
||||
cr: *mut cairo_sys::cairo_t,
|
||||
submission: *const Submission,
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let submission = unsafe { &*submission };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
let active_modifiers = submission.get_active_modifiers();
|
||||
|
||||
let view = layout.get_current_view();
|
||||
for (row_offset, row) in &view.get_rows() {
|
||||
for (x_offset, button) in &row.buttons {
|
||||
let state = RefCell::borrow(&button.state).clone();
|
||||
if state.pressed == keyboard::PressType::Pressed || state.locked {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
||||
button.as_ref(),
|
||||
state.pressed, state.locked,
|
||||
);
|
||||
}
|
||||
layout.foreach_visible_button(|offset, button| {
|
||||
let state = RefCell::borrow(&button.state).clone();
|
||||
let active_mod = match &state.action {
|
||||
Action::ApplyModifier(m) => active_modifiers.contains(m),
|
||||
_ => false,
|
||||
};
|
||||
let locked = state.action.is_active(&layout.current_view)
|
||||
| active_mod;
|
||||
if state.pressed == keyboard::PressType::Pressed || locked {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
offset,
|
||||
button.as_ref(),
|
||||
state.pressed, locked,
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -72,17 +81,15 @@ mod c {
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
let view = layout.get_current_view();
|
||||
for (row_offset, row) in &view.get_rows() {
|
||||
for (x_offset, button) in &row.buttons {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
row_offset + Point { x: *x_offset, y: 0.0 },
|
||||
button.as_ref(),
|
||||
keyboard::PressType::Released, false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
layout.foreach_visible_button(|offset, button| {
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
offset,
|
||||
button.as_ref(),
|
||||
keyboard::PressType::Released, false,
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,17 @@
|
||||
#include "imservice.h"
|
||||
#include "submission.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
struct imservice;
|
||||
|
||||
void imservice_handle_input_method_activate(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method,
|
||||
const char *text, uint32_t cursor, uint32_t anchor);
|
||||
void imservice_handle_done(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose);
|
||||
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause);
|
||||
void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method);
|
||||
|
||||
static const struct zwp_input_method_v2_listener input_method_listener = {
|
||||
.activate = imservice_handle_input_method_activate,
|
||||
@ -11,29 +19,52 @@ static const struct zwp_input_method_v2_listener input_method_listener = {
|
||||
.surrounding_text = imservice_handle_surrounding_text,
|
||||
.text_change_cause = imservice_handle_text_change_cause,
|
||||
.content_type = imservice_handle_content_type,
|
||||
.done = imservice_handle_commit_state,
|
||||
.done = imservice_handle_done,
|
||||
.unavailable = imservice_handle_unavailable,
|
||||
};
|
||||
|
||||
struct imservice* get_imservice(EekboardContextService *context,
|
||||
struct zwp_input_method_manager_v2 *manager,
|
||||
struct wl_seat *seat) {
|
||||
struct zwp_input_method_v2 *im = zwp_input_method_manager_v2_get_input_method(manager, seat);
|
||||
struct imservice *imservice = imservice_new(im, context);
|
||||
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
||||
struct zwp_virtual_keyboard_manager_v1 *vkmanager,
|
||||
struct vis_manager *vis_manager,
|
||||
struct wl_seat *seat,
|
||||
EekboardContextService *state) {
|
||||
struct zwp_input_method_v2 *im = NULL;
|
||||
if (immanager) {
|
||||
im = zwp_input_method_manager_v2_get_input_method(immanager, seat);
|
||||
}
|
||||
struct zwp_virtual_keyboard_v1 *vk = NULL;
|
||||
if (vkmanager) {
|
||||
vk = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkmanager, seat);
|
||||
}
|
||||
return submission_new(im, vk, state, vis_manager);
|
||||
}
|
||||
|
||||
/* Add a listener, passing the imservice instance to make it available to
|
||||
callbacks. */
|
||||
/// Un-inlined
|
||||
struct zwp_input_method_v2 *imservice_manager_get_input_method(struct zwp_input_method_manager_v2 *manager,
|
||||
struct wl_seat *seat) {
|
||||
return zwp_input_method_manager_v2_get_input_method(manager, seat);
|
||||
}
|
||||
|
||||
/// Un-inlined to let Rust link to it
|
||||
void imservice_connect_listeners(struct zwp_input_method_v2 *im, struct imservice* imservice) {
|
||||
zwp_input_method_v2_add_listener(im, &input_method_listener, imservice);
|
||||
|
||||
return imservice;
|
||||
}
|
||||
|
||||
void imservice_make_visible(EekboardContextService *context) {
|
||||
eekboard_context_service_show_keyboard (context);
|
||||
void
|
||||
eek_input_method_commit_string(struct zwp_input_method_v2 *zwp_input_method_v2, const char *text)
|
||||
{
|
||||
zwp_input_method_v2_commit_string(zwp_input_method_v2, text);
|
||||
}
|
||||
|
||||
void imservice_try_hide(EekboardContextService *context) {
|
||||
eekboard_context_service_hide_keyboard (context);
|
||||
void
|
||||
eek_input_method_delete_surrounding_text(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t before_length, uint32_t after_length) {
|
||||
zwp_input_method_v2_delete_surrounding_text(zwp_input_method_v2, before_length, after_length);
|
||||
};
|
||||
|
||||
void
|
||||
eek_input_method_commit(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t serial)
|
||||
{
|
||||
zwp_input_method_v2_commit(zwp_input_method_v2, serial);
|
||||
}
|
||||
|
||||
/// Declared explicitly because _destroy is inline,
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
#ifndef __IMSERVICE_H
|
||||
#define __IMSERVICE_H
|
||||
|
||||
#include "input-method-unstable-v2-client-protocol.h"
|
||||
#include "eek/eek-types.h"
|
||||
|
||||
struct imservice;
|
||||
|
||||
struct imservice* get_imservice(EekboardContextService *context,
|
||||
struct zwp_input_method_manager_v2 *manager,
|
||||
struct wl_seat *seat);
|
||||
|
||||
// Defined in Rust
|
||||
struct imservice* imservice_new(struct zwp_input_method_v2 *im,
|
||||
EekboardContextService *context);
|
||||
void imservice_handle_input_method_activate(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method,
|
||||
const char *text, uint32_t cursor, uint32_t anchor);
|
||||
void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method);
|
||||
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose);
|
||||
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause);
|
||||
void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method);
|
||||
|
||||
#endif
|
||||
|
||||
225
src/imservice.rs
225
src/imservice.rs
@ -1,58 +1,53 @@
|
||||
/*! Manages zwp_input_method_v2 protocol.
|
||||
*
|
||||
* Library module.
|
||||
*/
|
||||
|
||||
use std::boxed::Box;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::num::Wrapping;
|
||||
use std::string::String;
|
||||
|
||||
use ::logging;
|
||||
use ::util::c::into_cstring;
|
||||
|
||||
// Traits
|
||||
use std::convert::TryFrom;
|
||||
use ::logging::Warn;
|
||||
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use super::*;
|
||||
|
||||
|
||||
use std::os::raw::{c_char, c_void};
|
||||
|
||||
pub use ::ui_manager::c::UIManager;
|
||||
pub use ::submission::c::StateManager;
|
||||
|
||||
// The following defined in C
|
||||
|
||||
/// struct zwp_input_method_v2*
|
||||
#[repr(transparent)]
|
||||
pub struct InputMethod(*const c_void);
|
||||
|
||||
/// EekboardContextService*
|
||||
#[repr(transparent)]
|
||||
pub struct UIManager(*const c_void);
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" {
|
||||
fn imservice_destroy_im(im: *mut c::InputMethod);
|
||||
fn eekboard_context_service_set_hint_purpose(imservice: *const UIManager, hint: u32, purpose: u32);
|
||||
fn eekboard_context_service_show_keyboard(imservice: *const UIManager);
|
||||
fn eekboard_context_service_hide_keyboard(imservice: *const UIManager);
|
||||
#[allow(improper_ctypes)] // IMService will never be dereferenced in C
|
||||
pub fn imservice_connect_listeners(im: *mut InputMethod, imservice: *const IMService);
|
||||
pub fn eek_input_method_commit_string(im: *mut InputMethod, text: *const c_char);
|
||||
pub fn eek_input_method_delete_surrounding_text(im: *mut InputMethod, before: u32, after: u32);
|
||||
pub fn eek_input_method_commit(im: *mut InputMethod, serial: u32);
|
||||
fn eekboard_context_service_set_hint_purpose(state: *const StateManager, hint: u32, purpose: u32);
|
||||
}
|
||||
|
||||
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
fn imservice_new(im: *const InputMethod, ui_manager: *const UIManager) -> *mut IMService {
|
||||
Box::<IMService>::into_raw(Box::new(
|
||||
IMService {
|
||||
im: im,
|
||||
ui_manager: ui_manager,
|
||||
pending: IMProtocolState::default(),
|
||||
current: IMProtocolState::default(),
|
||||
preedit_string: String::new(),
|
||||
serial: Wrapping(0u32),
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
// TODO: is unsafe needed here?
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_input_method_activate(imservice: *mut IMService,
|
||||
im: *const InputMethod)
|
||||
{
|
||||
@ -65,7 +60,7 @@ pub mod c {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_input_method_deactivate(imservice: *mut IMService,
|
||||
im: *const InputMethod)
|
||||
{
|
||||
@ -77,7 +72,7 @@ pub mod c {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_surrounding_text(imservice: *mut IMService,
|
||||
im: *const InputMethod,
|
||||
text: *const c_char, cursor: u32, _anchor: u32)
|
||||
@ -93,7 +88,7 @@ pub mod c {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_content_type(imservice: *mut IMService,
|
||||
im: *const InputMethod,
|
||||
hint: u32, purpose: u32)
|
||||
@ -101,23 +96,27 @@ pub mod c {
|
||||
let imservice = check_imservice(imservice, im).unwrap();
|
||||
imservice.pending = IMProtocolState {
|
||||
content_hint: {
|
||||
ContentHint::from_bits(hint).unwrap_or_else(|| {
|
||||
eprintln!("Warning: received invalid hint flags");
|
||||
ContentHint::NONE
|
||||
})
|
||||
ContentHint::from_bits(hint)
|
||||
.or_print(
|
||||
logging::Problem::Warning,
|
||||
"Received invalid hint flags",
|
||||
)
|
||||
.unwrap_or(ContentHint::NONE)
|
||||
},
|
||||
content_purpose: {
|
||||
ContentPurpose::try_from(purpose).unwrap_or_else(|_e| {
|
||||
eprintln!("Warning: Received invalid purpose value");
|
||||
ContentPurpose::Normal
|
||||
})
|
||||
ContentPurpose::try_from(purpose)
|
||||
.or_print(
|
||||
logging::Problem::Warning,
|
||||
"Received invalid purpose value",
|
||||
)
|
||||
.unwrap_or(ContentPurpose::Normal)
|
||||
},
|
||||
..imservice.pending.clone()
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_text_change_cause(imservice: *mut IMService,
|
||||
im: *const InputMethod,
|
||||
cause: u32)
|
||||
@ -125,56 +124,65 @@ pub mod c {
|
||||
let imservice = check_imservice(imservice, im).unwrap();
|
||||
imservice.pending = IMProtocolState {
|
||||
text_change_cause: {
|
||||
ChangeCause::try_from(cause).unwrap_or_else(|_e| {
|
||||
eprintln!("Warning: received invalid cause value");
|
||||
ChangeCause::InputMethod
|
||||
})
|
||||
ChangeCause::try_from(cause)
|
||||
.or_print(
|
||||
logging::Problem::Warning,
|
||||
"Received invalid cause value",
|
||||
)
|
||||
.unwrap_or(ChangeCause::InputMethod)
|
||||
},
|
||||
..imservice.pending.clone()
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
fn imservice_handle_commit_state(imservice: *mut IMService,
|
||||
pub extern "C"
|
||||
fn imservice_handle_done(imservice: *mut IMService,
|
||||
im: *const InputMethod)
|
||||
{
|
||||
let imservice = check_imservice(imservice, im).unwrap();
|
||||
let active_changed = imservice.current.active ^ imservice.pending.active;
|
||||
|
||||
imservice.serial += Wrapping(1u32);
|
||||
|
||||
imservice.current = imservice.pending.clone();
|
||||
imservice.pending = IMProtocolState {
|
||||
active: imservice.current.active,
|
||||
..IMProtocolState::default()
|
||||
};
|
||||
|
||||
if active_changed {
|
||||
if imservice.current.active {
|
||||
eekboard_context_service_show_keyboard(imservice.ui_manager);
|
||||
(imservice.active_callback)(imservice.current.active);
|
||||
let (hint, purpose) = if imservice.current.active {(
|
||||
imservice.current.content_hint,
|
||||
imservice.current.content_purpose.clone(),
|
||||
)} else {(
|
||||
ContentHint::NONE,
|
||||
ContentPurpose::Normal,
|
||||
)};
|
||||
unsafe {
|
||||
eekboard_context_service_set_hint_purpose(
|
||||
imservice.ui_manager,
|
||||
imservice.current.content_hint.bits(),
|
||||
imservice.current.content_purpose.clone() as u32);
|
||||
} else {
|
||||
eekboard_context_service_hide_keyboard(imservice.ui_manager);
|
||||
imservice.state_manager,
|
||||
hint.bits(),
|
||||
purpose as u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this is really untested
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C"
|
||||
pub extern "C"
|
||||
fn imservice_handle_unavailable(imservice: *mut IMService,
|
||||
im: *mut InputMethod)
|
||||
{
|
||||
let imservice = check_imservice(imservice, im).unwrap();
|
||||
imservice_destroy_im(im);
|
||||
unsafe { imservice_destroy_im(im); }
|
||||
|
||||
// no need to care about proper double-buffering,
|
||||
// the keyboard is already decommissioned
|
||||
imservice.current.active = false;
|
||||
|
||||
eekboard_context_service_hide_keyboard(imservice.ui_manager);
|
||||
}
|
||||
(imservice.active_callback)(imservice.current.active);
|
||||
}
|
||||
|
||||
// FIXME: destroy and deallocate
|
||||
|
||||
@ -246,10 +254,17 @@ pub enum ContentPurpose {
|
||||
Terminal = 13,
|
||||
}
|
||||
|
||||
// Utilities from ::logging need a printable error type
|
||||
pub struct UnrecognizedValue;
|
||||
|
||||
impl fmt::Display for UnrecognizedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Unrecognized value")
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for ContentPurpose {
|
||||
// There's only one way to fail: number not in protocol,
|
||||
// so no special error type is needed
|
||||
type Error = ();
|
||||
type Error = UnrecognizedValue;
|
||||
fn try_from(num: u32) -> Result<Self, Self::Error> {
|
||||
use self::ContentPurpose::*;
|
||||
match num {
|
||||
@ -267,7 +282,7 @@ impl TryFrom<u32> for ContentPurpose {
|
||||
11 => Ok(Time),
|
||||
12 => Ok(Datetime),
|
||||
13 => Ok(Terminal),
|
||||
_ => Err(()),
|
||||
_ => Err(UnrecognizedValue),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,14 +295,12 @@ pub enum ChangeCause {
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for ChangeCause {
|
||||
// There's only one way to fail: number not in protocol,
|
||||
// so no special error type is needed
|
||||
type Error = ();
|
||||
type Error = UnrecognizedValue;
|
||||
fn try_from(num: u32) -> Result<Self, Self::Error> {
|
||||
match num {
|
||||
0 => Ok(ChangeCause::InputMethod),
|
||||
1 => Ok(ChangeCause::Other),
|
||||
_ => Err(())
|
||||
_ => Err(UnrecognizedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,12 +331,92 @@ impl Default for IMProtocolState {
|
||||
|
||||
pub struct IMService {
|
||||
/// Owned reference (still created and destroyed in C)
|
||||
pub im: *const c::InputMethod,
|
||||
pub im: *mut c::InputMethod,
|
||||
/// Unowned reference. Be careful, it's shared with C at large
|
||||
ui_manager: *const c::UIManager,
|
||||
state_manager: *const c::StateManager,
|
||||
active_callback: Box<dyn Fn(bool)>,
|
||||
|
||||
pending: IMProtocolState,
|
||||
current: IMProtocolState, // turn current into an idiomatic representation?
|
||||
preedit_string: String,
|
||||
serial: Wrapping<u32>,
|
||||
}
|
||||
|
||||
pub enum SubmitError {
|
||||
/// The input method had not been activated
|
||||
NotActive,
|
||||
}
|
||||
|
||||
impl IMService {
|
||||
pub fn new(
|
||||
im: *mut c::InputMethod,
|
||||
state_manager: *const c::StateManager,
|
||||
active_callback: Box<dyn Fn(bool)>,
|
||||
) -> Box<IMService> {
|
||||
// IMService will be referenced to by C,
|
||||
// so it needs to stay in the same place in memory via Box
|
||||
let imservice = Box::new(IMService {
|
||||
im,
|
||||
active_callback,
|
||||
state_manager,
|
||||
pending: IMProtocolState::default(),
|
||||
current: IMProtocolState::default(),
|
||||
preedit_string: String::new(),
|
||||
serial: Wrapping(0u32),
|
||||
});
|
||||
unsafe {
|
||||
c::imservice_connect_listeners(
|
||||
im,
|
||||
imservice.as_ref() as *const IMService,
|
||||
);
|
||||
}
|
||||
imservice
|
||||
}
|
||||
|
||||
pub fn commit_string(&self, text: &CString) -> Result<(), SubmitError> {
|
||||
match self.current.active {
|
||||
true => {
|
||||
unsafe {
|
||||
c::eek_input_method_commit_string(self.im, text.as_ptr())
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
false => Err(SubmitError::NotActive),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_surrounding_text(
|
||||
&self,
|
||||
before: u32, after: u32,
|
||||
) -> Result<(), SubmitError> {
|
||||
match self.current.active {
|
||||
true => {
|
||||
unsafe {
|
||||
c::eek_input_method_delete_surrounding_text(
|
||||
self.im,
|
||||
before, after,
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
false => Err(SubmitError::NotActive),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn commit(&mut self) -> Result<(), SubmitError> {
|
||||
match self.current.active {
|
||||
true => {
|
||||
unsafe {
|
||||
c::eek_input_method_commit(self.im, self.serial.0)
|
||||
}
|
||||
self.serial += Wrapping(1u32);
|
||||
Ok(())
|
||||
},
|
||||
false => Err(SubmitError::NotActive),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
self.current.active
|
||||
}
|
||||
}
|
||||
|
||||
278
src/keyboard.rs
278
src/keyboard.rs
@ -1,13 +1,19 @@
|
||||
/*! State of the emulated keyboard and keys.
|
||||
* Regards the keyboard as if it was composed of switches. */
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use ::action::Action;
|
||||
use ::util;
|
||||
|
||||
// Traits
|
||||
use std::io::Write;
|
||||
use std::iter::{ FromIterator, IntoIterator };
|
||||
|
||||
@ -17,21 +23,74 @@ pub enum PressType {
|
||||
Pressed = 1,
|
||||
}
|
||||
|
||||
/// The extended, unambiguous layout-keycode
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyCode {
|
||||
pub code: u32,
|
||||
pub keymap_idx: usize,
|
||||
}
|
||||
|
||||
bitflags!{
|
||||
/// Map to `virtual_keyboard.modifiers` modifiers values
|
||||
/// From https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Keyboard_State
|
||||
pub struct Modifiers: u8 {
|
||||
const SHIFT = 0x1;
|
||||
const LOCK = 0x2;
|
||||
const CONTROL = 0x4;
|
||||
/// Alt
|
||||
const MOD1 = 0x8;
|
||||
const MOD2 = 0x10;
|
||||
const MOD3 = 0x20;
|
||||
/// Meta
|
||||
const MOD4 = 0x40;
|
||||
/// AltGr
|
||||
const MOD5 = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/// When the submitted actions of keys need to be tracked,
|
||||
/// they need a stable, comparable ID
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct KeyStateId(*const KeyState);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyState {
|
||||
pub pressed: PressType,
|
||||
pub locked: bool,
|
||||
/// A cache of raw keycodes derived from Action::Sumbit given a keymap
|
||||
pub keycodes: Vec<u32>,
|
||||
/// A cache of raw keycodes derived from Action::Submit given a keymap
|
||||
pub keycodes: Vec<KeyCode>,
|
||||
/// Static description of what the key does when pressed or released
|
||||
pub action: Action,
|
||||
}
|
||||
|
||||
impl KeyState {
|
||||
#[must_use]
|
||||
pub fn into_released(self) -> KeyState {
|
||||
KeyState {
|
||||
pressed: PressType::Released,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn into_pressed(self) -> KeyState {
|
||||
KeyState {
|
||||
pressed: PressType::Pressed,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// KeyStates instances are the unique identifiers of pressed keys,
|
||||
/// and the actions submitted with them.
|
||||
pub fn get_id(keystate: &Rc<RefCell<KeyState>>) -> KeyStateId {
|
||||
KeyStateId(keystate.as_ptr() as *const KeyState)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sorts an iterator by converting it to a Vector and back
|
||||
fn sorted<'a, I: Iterator<Item=&'a str>>(
|
||||
fn sorted<'a, I: Iterator<Item=String>>(
|
||||
iter: I
|
||||
) -> impl Iterator<Item=&'a str> {
|
||||
let mut v: Vec<&'a str> = iter.collect();
|
||||
) -> impl Iterator<Item=String> {
|
||||
let mut v: Vec<String> = iter.collect();
|
||||
v.sort();
|
||||
v.into_iter()
|
||||
}
|
||||
@ -39,14 +98,17 @@ fn sorted<'a, I: Iterator<Item=&'a str>>(
|
||||
/// Generates a mapping where each key gets a keycode, starting from ~~8~~
|
||||
/// HACK: starting from 9, because 8 results in keycode 0,
|
||||
/// which the compositor likes to discard
|
||||
pub fn generate_keycodes<'a, C: IntoIterator<Item=&'a str>>(
|
||||
key_names: C
|
||||
) -> HashMap<String, u32> {
|
||||
pub fn generate_keycodes<'a, C: IntoIterator<Item=String>>(
|
||||
key_names: C,
|
||||
) -> HashMap<String, KeyCode> {
|
||||
HashMap::from_iter(
|
||||
// sort to remove a source of indeterminism in keycode assignment
|
||||
// Sort to remove a source of indeterminism in keycode assignment.
|
||||
sorted(key_names.into_iter())
|
||||
.map(|name| String::from(name))
|
||||
.zip(9..)
|
||||
.zip(util::cycle_count(9..255))
|
||||
.map(|(name, (code, keymap_idx))| (
|
||||
String::from(name),
|
||||
KeyCode { code, keymap_idx },
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
@ -71,9 +133,54 @@ impl From<io::Error> for FormattingError {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a de-facto single level keymap. TODO: actually drop second level
|
||||
pub fn generate_keymap(
|
||||
keystates: &HashMap::<String, KeyState>
|
||||
/// Index is the key code, String is the occupant.
|
||||
/// Starts all empty.
|
||||
/// https://gitlab.freedesktop.org/xorg/xserver/-/issues/260
|
||||
type SingleKeyMap = [Option<String>; 256];
|
||||
|
||||
fn single_key_map_new() -> SingleKeyMap {
|
||||
// Why can't we just initialize arrays without tricks -_- ?
|
||||
unsafe {
|
||||
// Inspired by
|
||||
// https://www.reddit.com/r/rust/comments/5n7bh1/how_to_create_an_array_of_a_type_with_clone_but/
|
||||
#[cfg(feature = "rustc_less_1_36")]
|
||||
let mut array: SingleKeyMap = mem::uninitialized();
|
||||
#[cfg(not(feature = "rustc_less_1_36"))]
|
||||
let mut array: SingleKeyMap = mem::MaybeUninit::uninit().assume_init();
|
||||
|
||||
for element in array.iter_mut() {
|
||||
ptr::write(element, None);
|
||||
}
|
||||
array
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_keymaps(symbolmap: HashMap::<String, KeyCode>)
|
||||
-> Result<Vec<String>, FormattingError>
|
||||
{
|
||||
let mut bins: Vec<SingleKeyMap> = Vec::new();
|
||||
|
||||
for (name, KeyCode { code, keymap_idx }) in symbolmap.into_iter() {
|
||||
if keymap_idx >= bins.len() {
|
||||
bins.resize_with(
|
||||
keymap_idx + 1,
|
||||
|| single_key_map_new(),
|
||||
);
|
||||
}
|
||||
bins[keymap_idx][code as usize] = Some(name);
|
||||
}
|
||||
|
||||
let mut out = Vec::new();
|
||||
for bin in bins {
|
||||
out.push(generate_keymap(&bin)?);
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Generates a de-facto single level keymap.
|
||||
/// Key codes must not repeat and must remain between 9 and 255.
|
||||
fn generate_keymap(
|
||||
symbolmap: &SingleKeyMap,
|
||||
) -> Result<String, FormattingError> {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
writeln!(
|
||||
@ -84,61 +191,80 @@ pub fn generate_keymap(
|
||||
minimum = 8;
|
||||
maximum = 255;"
|
||||
)?;
|
||||
|
||||
let pairs: Vec<(&String, usize)> = symbolmap.iter()
|
||||
// Attach a key code to each cell.
|
||||
.enumerate()
|
||||
// Get rid of empty keycodes.
|
||||
.filter_map(|(code, name)| name.as_ref().map(|n| (n, code)))
|
||||
.collect();
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
if let Action::Submit { text: _, keys } = &state.action {
|
||||
if let 0 = keys.len() { eprintln!("Key {} has no keysyms", name); };
|
||||
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
<{}> = {};",
|
||||
named_keysym.0,
|
||||
keycode,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
// Xorg can only consume up to 255 keys, so this may not work in Xwayland.
|
||||
// Two possible solutions:
|
||||
// - use levels to cram multiple characters into one key
|
||||
// - swap layouts on key presses
|
||||
for (_name, keycode) in &pairs {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
<I{}> = {0};",
|
||||
keycode,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"
|
||||
indicator 1 = \"Caps Lock\"; // Xwayland won't accept without it.
|
||||
}};
|
||||
|
||||
xkb_symbols \"squeekboard\" {{
|
||||
|
||||
name[Group1] = \"Letters\";
|
||||
name[Group2] = \"Numbers/Symbols\";"
|
||||
"
|
||||
)?;
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
if let Action::Submit { text: _, keys } = &state.action {
|
||||
for keysym in keys.iter() {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
key <{}> {{ [ {0} ] }};",
|
||||
keysym.0,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
for (name, keycode) in pairs {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
key <I{}> {{ [ {} ] }};",
|
||||
keycode,
|
||||
name,
|
||||
)?;
|
||||
}
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"
|
||||
}};
|
||||
|
||||
xkb_types \"squeekboard\" {{
|
||||
virtual_modifiers Squeekboard; // No modifiers! Needed for Xorg for some reason.
|
||||
|
||||
// Those names are needed for Xwayland.
|
||||
type \"ONE_LEVEL\" {{
|
||||
modifiers= none;
|
||||
level_name[Level1]= \"Any\";
|
||||
}};
|
||||
type \"TWO_LEVEL\" {{
|
||||
level_name[Level1]= \"Base\";
|
||||
}};
|
||||
type \"ALPHABETIC\" {{
|
||||
level_name[Level1]= \"Base\";
|
||||
}};
|
||||
type \"KEYPAD\" {{
|
||||
level_name[Level1]= \"Base\";
|
||||
}};
|
||||
type \"SHIFT+ALT\" {{
|
||||
level_name[Level1]= \"Base\";
|
||||
}};
|
||||
|
||||
type \"TWO_LEVEL\" {{
|
||||
modifiers = Shift;
|
||||
map[Shift] = Level2;
|
||||
level_name[Level1] = \"Base\";
|
||||
level_name[Level2] = \"Shift\";
|
||||
}};
|
||||
}};
|
||||
|
||||
xkb_compatibility \"squeekboard\" {{
|
||||
// Needed for Xwayland again.
|
||||
interpret Any+AnyOf(all) {{
|
||||
action= SetMods(modifiers=modMapMods,clearLocks);
|
||||
}};
|
||||
}};
|
||||
}};"
|
||||
)?;
|
||||
@ -153,23 +279,15 @@ mod tests {
|
||||
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use ::action::KeySym;
|
||||
|
||||
#[test]
|
||||
fn test_keymap_multi() {
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
fn test_keymap_single_resolve() {
|
||||
let mut key_map = single_key_map_new();
|
||||
key_map[9] = Some("a".into());
|
||||
key_map[10] = Some("c".into());
|
||||
|
||||
let keymap_str = generate_keymap(&hashmap!{
|
||||
"ac".into() => KeyState {
|
||||
action: Action::Submit {
|
||||
text: None,
|
||||
keys: vec!(KeySym("a".into()), KeySym("c".into())),
|
||||
},
|
||||
keycodes: vec!(9, 10),
|
||||
locked: false,
|
||||
pressed: PressType::Released,
|
||||
},
|
||||
}).unwrap();
|
||||
let keymap_str = generate_keymap(&key_map).unwrap();
|
||||
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
@ -183,4 +301,36 @@ mod tests {
|
||||
assert_eq!(state.key_get_one_sym(9), xkb::KEY_a);
|
||||
assert_eq!(state.key_get_one_sym(10), xkb::KEY_c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keymap_second_resolve() {
|
||||
let keymaps = generate_keymaps(hashmap!(
|
||||
"a".into() => KeyCode { keymap_idx: 1, code: 9 },
|
||||
)).unwrap();
|
||||
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
keymaps[1].clone(), // this index is part of the test
|
||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||
).expect("Failed to create keymap");
|
||||
|
||||
let state = xkb::State::new(&keymap);
|
||||
|
||||
assert_eq!(state.key_get_one_sym(9), xkb::KEY_a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_symbolmap_overflow() {
|
||||
// The 257th key (U1101) is interesting.
|
||||
// Use Unicode encoding for being able to use in xkb keymaps.
|
||||
let keynames = (0..258).map(|num| format!("U{:04X}", 0x1000 + num));
|
||||
let keycodes = generate_keycodes(keynames);
|
||||
|
||||
// test now
|
||||
let code = keycodes.get("U1101").expect("Did not find the tested keysym");
|
||||
assert_eq!(code.keymap_idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
26
src/layout.h
26
src/layout.h
@ -7,13 +7,23 @@
|
||||
#include "eek/eek-gtk-keyboard.h"
|
||||
#include "eek/eek-renderer.h"
|
||||
#include "eek/eek-types.h"
|
||||
#include "src/submission.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
#include "text-input-unstable-v3-client-protocol.h"
|
||||
|
||||
enum squeek_arrangement_kind {
|
||||
ARRANGEMENT_KIND_BASE = 0,
|
||||
ARRANGEMENT_KIND_WIDE = 1,
|
||||
};
|
||||
|
||||
struct squeek_layout_state {
|
||||
enum squeek_arrangement_kind arrangement;
|
||||
enum zwp_text_input_v3_content_purpose purpose;
|
||||
enum zwp_text_input_v3_content_hint hint;
|
||||
char *layout_name;
|
||||
char *overlay_name;
|
||||
};
|
||||
|
||||
struct squeek_layout;
|
||||
|
||||
EekBounds squeek_button_get_bounds(const struct squeek_button*);
|
||||
@ -29,25 +39,29 @@ struct transformation squeek_layout_calculate_transformation(
|
||||
double allocation_width, double allocation_size);
|
||||
|
||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
|
||||
const char *squeek_layout_get_keymap(const struct squeek_layout*);
|
||||
enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *);
|
||||
void squeek_layout_free(struct squeek_layout*);
|
||||
|
||||
void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
|
||||
void squeek_layout_release(struct squeek_layout *layout,
|
||||
struct submission *submission,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp,
|
||||
EekboardContextService *manager,
|
||||
EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp);
|
||||
void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
|
||||
void squeek_layout_release_all_only(struct squeek_layout *layout,
|
||||
struct submission *submission,
|
||||
uint32_t timestamp);
|
||||
void squeek_layout_depress(struct squeek_layout *layout,
|
||||
struct submission *submission,
|
||||
double x_widget, double y_widget,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
|
||||
void squeek_layout_drag(struct squeek_layout *layout,
|
||||
struct submission *submission,
|
||||
double x_widget, double y_widget,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp, EekboardContextService *manager,
|
||||
EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
|
||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission);
|
||||
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
|
||||
#endif
|
||||
|
||||
783
src/layout.rs
783
src/layout.rs
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user