Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ce2cf254b | |||
| 6d7360a230 | |||
| 33039e65cb | |||
| 4007754de9 | |||
| 6abaa36db8 | |||
| 710509a671 | |||
| 16d7fcae7c | |||
| e504154571 | |||
| b19938da01 | |||
| b409df15bb | |||
| 7dd2866b17 | |||
| f6fc6c83dc | |||
| fa5c7c63d9 | |||
| 1093e32325 |
@ -1,4 +1,4 @@
|
|||||||
image: debian:bullseye
|
image: debian:buster
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
@ -11,7 +11,7 @@ stages:
|
|||||||
before_script:
|
before_script:
|
||||||
- apt-get -y update
|
- apt-get -y update
|
||||||
- apt-get -y install wget ca-certificates gnupg
|
- apt-get -y install wget ca-certificates gnupg
|
||||||
- echo "deb [trusted=yes] http://ci.puri.sm/ bullseyeci main" > /etc/apt/sources.list.d/ci.list
|
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
|
||||||
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
|
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
|
||||||
- apt-get -y update
|
- apt-get -y update
|
||||||
|
|
||||||
@ -27,8 +27,7 @@ build_docs:
|
|||||||
- ./doc/build.sh _build
|
- ./doc/build.sh _build
|
||||||
|
|
||||||
build_meson:
|
build_meson:
|
||||||
tags:
|
<<: *tags
|
||||||
- librem5
|
|
||||||
stage: build
|
stage: build
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
@ -36,7 +35,7 @@ build_meson:
|
|||||||
expire_in: 3h
|
expire_in: 3h
|
||||||
script:
|
script:
|
||||||
- apt-get -y build-dep .
|
- apt-get -y build-dep .
|
||||||
- meson . _build/ -Ddepdatadir=/usr/share --werror
|
- meson . _build/ -Ddepdatadir=/usr/share
|
||||||
- ninja -C _build install
|
- ninja -C _build install
|
||||||
|
|
||||||
build_deb:
|
build_deb:
|
||||||
@ -53,44 +52,10 @@ build_deb:
|
|||||||
- debuild -i -us -uc -b
|
- debuild -i -us -uc -b
|
||||||
- cp ../*.deb .
|
- cp ../*.deb .
|
||||||
|
|
||||||
build_deb:amber:
|
|
||||||
image: pureos/amber
|
|
||||||
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: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:
|
build_deb:arm64:
|
||||||
tags:
|
tags:
|
||||||
- librem5:arm64
|
- librem5:arm64
|
||||||
|
allow_failure: true
|
||||||
stage: build
|
stage: build
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
@ -102,23 +67,6 @@ build_deb:arm64:
|
|||||||
- debuild -i -us -uc -b
|
- debuild -i -us -uc -b
|
||||||
- cp ../*.deb .
|
- 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
|
|
||||||
- cp ../*.deb .
|
|
||||||
|
|
||||||
test_lintian:
|
test_lintian:
|
||||||
<<: *tags
|
<<: *tags
|
||||||
stage: test
|
stage: test
|
||||||
@ -129,17 +77,13 @@ test_lintian:
|
|||||||
- lintian *.deb
|
- lintian *.deb
|
||||||
|
|
||||||
test:
|
test:
|
||||||
tags:
|
<<: *tags
|
||||||
- librem5
|
|
||||||
stage: test
|
stage: test
|
||||||
needs:
|
needs:
|
||||||
- build_meson
|
- build_meson
|
||||||
script:
|
script:
|
||||||
- apt-get -y build-dep .
|
- apt-get -y build-dep .
|
||||||
- apt-get -y install clang-tidy
|
|
||||||
- ninja -C _build test
|
- 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:
|
check_release:
|
||||||
<<: *tags
|
<<: *tags
|
||||||
|
|||||||
22
Cargo.deps
22
Cargo.deps
@ -1,22 +0,0 @@
|
|||||||
# 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"]
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
# 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"]
|
|
||||||
492
Cargo.lock
generated
492
Cargo.lock
generated
@ -1,484 +1,506 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atk"
|
name = "aho-corasick"
|
||||||
version = "0.7.0"
|
version = "0.7.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86b7499272acf036bb5820c6e346bbfb5acc5dceb104bc2c4fd7e6e33dfcde6a"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk-sys",
|
"memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitflags",
|
|
||||||
"glib",
|
|
||||||
"glib-sys",
|
|
||||||
"gobject-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atk-sys"
|
name = "atk-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e552c1776737a4c80110d06b36d099f47c727335f9aaa5d942a72b6863a8ec6f"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.7.1"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e05db47de3b0f09a222fa4bba2eab957d920d4243962a86b2d77ab401e4a359c"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-sys-rs",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-sys-rs"
|
name = "cairo-sys-rs"
|
||||||
version = "0.9.2"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.65"
|
version = "1.0.50"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.3"
|
version = "2.32.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"textwrap",
|
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-width",
|
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "0.4.6"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fragile"
|
name = "fragile"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk"
|
name = "gdk"
|
||||||
version = "0.11.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6243e995f41f3a61a31847e54cc719edce93dd9140c89dca3b9919be1cfe22d5"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-rs",
|
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-pixbuf",
|
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-sys",
|
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio",
|
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango",
|
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-pixbuf"
|
name = "gdk-pixbuf"
|
||||||
version = "0.7.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9726408ee1bbada83094326a99b9c68fea275f9dbb515de242a69e72051f4fcc"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio",
|
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-pixbuf-sys"
|
name = "gdk-pixbuf-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8991b060a9e9161bafd09bf4a202e6fd404f5b4dd1a08d53a1e84256fb34ab0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-sys"
|
name = "gdk-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6adf679e91d1bff0c06860287f80403e7db54c2d2424dce0a470023b56c88fbb"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango-sys",
|
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio"
|
name = "gio"
|
||||||
version = "0.7.0"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6261b5d34c30c2d59f879e643704cf54cb44731f3a2038000b68790c03e360e3"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fragile",
|
"fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio-sys"
|
name = "gio-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fad225242b9eae7ec8a063bb86974aca56885014672375e5775dc0ea3533911"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib"
|
name = "glib"
|
||||||
version = "0.8.2"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be27232841baa43e0fd5ae003f7941925735b2f733a336dc75f07b9eff415e7b"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib-sys"
|
name = "glib-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gobject-sys"
|
name = "gobject-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk"
|
name = "gtk"
|
||||||
version = "0.7.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "709f1074259d4685b96133f92b75c7f35b504715b0fcdc96ec95de2607296a60"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitflags",
|
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-rs",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-sys-rs",
|
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc",
|
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk",
|
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-pixbuf",
|
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-sys",
|
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gtk-sys",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango",
|
|
||||||
"pango-sys",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk-sys"
|
name = "gtk-sys"
|
||||||
version = "0.9.2"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk-sys",
|
"atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk-sys",
|
"gdk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio-sys",
|
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango-sys",
|
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.80"
|
version = "0.2.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.5.3"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maplit"
|
name = "maplit"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap"
|
name = "memmap"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.7.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "393fa071b144f8ffb83ede273758983cf414ca3c0b1d2a5a9ce325b3ba3dd786"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pango-sys",
|
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango-sys"
|
name = "pango-sys"
|
||||||
version = "0.9.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86b93d84907b3cf0819bff8f13598ba72843bee579d5ebc2502e4b0367b4be7d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gobject-sys",
|
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pkg-config",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.19"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.7"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.3.9"
|
version = "1.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex-syntax",
|
"aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex-syntax 0.6.14 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.21"
|
version = "0.6.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rs"
|
name = "rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-rs",
|
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap",
|
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gdk",
|
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gio",
|
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib",
|
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib-sys",
|
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gtk",
|
"gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gtk-sys",
|
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"maplit",
|
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex",
|
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml",
|
"serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"xkbcommon",
|
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.117"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.117"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote",
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn",
|
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yaml"
|
name = "serde_yaml"
|
||||||
version = "0.8.14"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dtoa",
|
"dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"linked-hash-map",
|
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"yaml-rust",
|
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.48"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote",
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid",
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-width",
|
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.8"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-i686-pc-windows-gnu",
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xkbcommon"
|
name = "xkbcommon"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memmap",
|
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yaml-rust"
|
name = "yaml-rust"
|
||||||
version = "0.4.4"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"linked-hash-map",
|
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
|
||||||
|
"checksum atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7017e53393e713212aed7aea336b6553be4927f58c37070a56c2fe3d107e489"
|
||||||
|
"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.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||||
|
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||||
|
"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
||||||
|
"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 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.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978"
|
||||||
|
"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.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
|
||||||
|
"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.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
|
||||||
|
"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 syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
|
||||||
|
"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 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,40 +2,46 @@
|
|||||||
name = "rs"
|
name = "rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[lib]
|
[dependencies]
|
||||||
name = "rs"
|
bitflags = "1.0.*"
|
||||||
path = "@path@/src/lib.rs"
|
clap = { version = "2.32.*", default-features = false }
|
||||||
crate-type = ["staticlib", "rlib"]
|
maplit = "1.0.*"
|
||||||
|
regex = "1.1.*"
|
||||||
|
serde = { version = "1.0.*", features = ["derive"] }
|
||||||
|
serde_yaml = "0.8.*"
|
||||||
|
xkbcommon = { version = "0.4.*", features = ["wayland"] }
|
||||||
|
|
||||||
# Cargo can't do autodiscovery if Cargo.toml is not in the root.
|
[dependencies.cairo-rs]
|
||||||
[[bin]]
|
version = "0.5.*"
|
||||||
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]
|
[dependencies.cairo-sys-rs]
|
||||||
version = ""
|
version = ""
|
||||||
|
|
||||||
|
[dependencies.gdk]
|
||||||
|
version = ""
|
||||||
|
|
||||||
|
[dependencies.gio]
|
||||||
|
version = ""
|
||||||
|
features = ["v2_44"]
|
||||||
|
|
||||||
|
[dependencies.glib]
|
||||||
|
version = ""
|
||||||
|
features = ["v2_44"]
|
||||||
|
|
||||||
[dependencies.glib-sys]
|
[dependencies.glib-sys]
|
||||||
version = ""
|
version = ""
|
||||||
features = ["v2_44"]
|
features = ["v2_44"]
|
||||||
|
|
||||||
|
[dependencies.gtk]
|
||||||
|
version = "0.5.*"
|
||||||
|
features = ["v3_22"]
|
||||||
|
|
||||||
[dependencies.gtk-sys]
|
[dependencies.gtk-sys]
|
||||||
version = ""
|
version = ""
|
||||||
features = ["v3_22"]
|
features = ["v3_22"]
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
maplit = "1.0.*"
|
[lib]
|
||||||
serde = { version = "1.0.*", features = ["derive"] }
|
name = "rs"
|
||||||
serde_yaml = "0.8.*"
|
path = "src/lib.rs"
|
||||||
xkbcommon = { version = "0.4.*", features = ["wayland"] }
|
crate-type = ["staticlib", "rlib"]
|
||||||
# Here is inserted the Cargo.deps file
|
|
||||||
31
README.md
31
README.md
@ -30,43 +30,30 @@ Building
|
|||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
See `.gitlab-ci.yml` or run `apt-get build-dep .`
|
See `.gitlab-ci.yml`.
|
||||||
|
|
||||||
### Build from git repo
|
### Build from git repo
|
||||||
|
|
||||||
```bash
|
```
|
||||||
$ git clone https://source.puri.sm/Librem5/squeekboard.git
|
$ git clone https://source.puri.sm/Librem5/squeekboard.git
|
||||||
$ cd squeekboard
|
$ cd squeekboard
|
||||||
$ mkdir _build
|
$ mkdir ../build
|
||||||
$ meson _build/
|
$ meson ../build/
|
||||||
$ cd _build
|
$ cd ../build
|
||||||
$ ninja
|
$ ninja test
|
||||||
|
$ ninja install
|
||||||
```
|
```
|
||||||
|
|
||||||
To run tests use `ninja test`. To install squeekboard run `ninja install`.
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
-------
|
-------
|
||||||
|
|
||||||
```bash
|
```
|
||||||
$ phoc # if no compatible Wayland compositor is running yet
|
$ phoc # if no compatible Wayland compositor is running yet
|
||||||
$ cd ../build/
|
$ cd ../build/
|
||||||
$ src/squeekboard
|
$ 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
|
Developing
|
||||||
----------
|
----------
|
||||||
|
|
||||||
See [`doc/hacking.md`](doc/hacking.md) for this copy, or the [official documentation](https://developer.puri.sm/projects/squeekboard/) for the current release.
|
See [`docs/hacking.md`](docs/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,10 +13,5 @@ CARGO_TARGET_DIR="$(pwd)"
|
|||||||
export CARGO_TARGET_DIR
|
export CARGO_TARGET_DIR
|
||||||
|
|
||||||
cd "$SOURCE_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 "$@"
|
|
||||||
|
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
|
|
||||||
34
cargo_build.sh
Executable file
34
cargo_build.sh
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/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
|
||||||
@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
---
|
|
||||||
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:
|
numbers:
|
||||||
- "1 2 3 4 5 6 7 8 9 0"
|
- "1 2 3 4 5 6 7 8 9 0"
|
||||||
- "@ # € % & - _ + ( )"
|
- "@ # € % & - _ + ( )"
|
||||||
- "show_symbols ; \" ' : = < > BackSpace"
|
- "show_symbols , \" ' : = < > BackSpace"
|
||||||
- "show_letters show_eschars preferences space , . Return"
|
- "show_letters show_eschars preferences space , . Return"
|
||||||
symbols:
|
symbols:
|
||||||
- "~ ` ´ | · √ µ ÷ × ¶"
|
- "~ ` ´ | · √ µ ÷ × ¶"
|
||||||
|
|||||||
@ -21,7 +21,7 @@ views:
|
|||||||
numbers:
|
numbers:
|
||||||
- "1 2 3 4 5 6 7 8 9 0"
|
- "1 2 3 4 5 6 7 8 9 0"
|
||||||
- "@ # % & - _ + ( ) ß"
|
- "@ # % & - _ + ( ) ß"
|
||||||
- "show_symbols ; \" ' : = < > BackSpace"
|
- "show_symbols , \" ' : = < > BackSpace"
|
||||||
- "show_letters preferences space , . Return"
|
- "show_letters preferences space , . Return"
|
||||||
symbols:
|
symbols:
|
||||||
- "~ ` ´ · © ® ÷ × ¶"
|
- "~ ` ´ · © ® ÷ × ¶"
|
||||||
|
|||||||
@ -1,98 +0,0 @@
|
|||||||
---
|
|
||||||
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,81 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
# 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"
|
- "q w e r t y u i o p"
|
||||||
- "a s d f g h j k l"
|
- "a s d f g h j k l"
|
||||||
- "Shift_L z x c v b n m BackSpace"
|
- "Shift_L z x c v b n m BackSpace"
|
||||||
- "show_numbers show_eschars preferences space , . Return"
|
- "show_numbers show_eschars preferences space , period Return"
|
||||||
upper:
|
upper:
|
||||||
- "Q W E R T Y U I O P"
|
- "Q W E R T Y U I O P"
|
||||||
- "A S D F G H J K L"
|
- "A S D F G H J K L"
|
||||||
- "Shift_L Z X C V B N M BackSpace"
|
- "Shift_L Z X C V B N M BackSpace"
|
||||||
- "show_numbers show_eschars preferences space ? . Return"
|
- "show_numbers show_eschars preferences space ? period Return"
|
||||||
numbers:
|
numbers:
|
||||||
- "1 2 3 4 5 6 7 8 9 0"
|
- "1 2 3 4 5 6 7 8 9 0"
|
||||||
- "@ # € % & - _ + ( )"
|
- "@ # € % & - _ + ( )"
|
||||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||||
- "show_letters show_eschars preferences space ? . Return"
|
- "show_letters show_eschars preferences space ? period Return"
|
||||||
symbols:
|
symbols:
|
||||||
- "~ ` | · √ π τ ÷ × ¶"
|
- "~ ` | · √ π τ ÷ × ¶"
|
||||||
- "© ® £ $ ¥ ^ ° * { }"
|
- "© ® £ $ ¥ ^ ° * { }"
|
||||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||||
- "show_letters show_eschars preferences space ? . Return"
|
- "show_letters show_eschars preferences space ? period Return"
|
||||||
eschars:
|
eschars:
|
||||||
- "á é í ó ú Á É Í Ó Ú"
|
- "á é í ó ú Á É Í Ó Ú"
|
||||||
- "à è ì ò « » ù ! { }"
|
- "à è ì ò « » ù ! { }"
|
||||||
@ -76,10 +76,12 @@ buttons:
|
|||||||
set_view: "eschars"
|
set_view: "eschars"
|
||||||
outline: "altline"
|
outline: "altline"
|
||||||
label: "àè"
|
label: "àè"
|
||||||
|
period:
|
||||||
|
outline: "default"
|
||||||
|
label: "."
|
||||||
space:
|
space:
|
||||||
outline: "spaceline"
|
outline: "spaceline"
|
||||||
label: " "
|
label: " "
|
||||||
text: " "
|
|
||||||
Return:
|
Return:
|
||||||
outline: "altline"
|
outline: "altline"
|
||||||
icon: "key-enter"
|
icon: "key-enter"
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
outlines:
|
outlines:
|
||||||
default: { width: 32, height: 52 }
|
default: { width: 32, height: 52 }
|
||||||
altline: { width: 48.39024, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
wide: { width: 64, height: 52 }
|
wide: { width: 62, height: 52 }
|
||||||
spaceline: { width: 142, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
special: { width: 44, height: 52 }
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
@ -25,7 +25,7 @@ views:
|
|||||||
symbols:
|
symbols:
|
||||||
- "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
- "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }"
|
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }"
|
||||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||||
- "show_letters preferences space . Return"
|
- "show_letters preferences space . Return"
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
@ -42,22 +42,17 @@ buttons:
|
|||||||
action: erase
|
action: erase
|
||||||
preferences:
|
preferences:
|
||||||
action: "show_prefs"
|
action: "show_prefs"
|
||||||
outline: "special"
|
outline: "altline"
|
||||||
icon: "keyboard-mode-symbolic"
|
icon: "keyboard-mode-symbolic"
|
||||||
show_numbers:
|
show_numbers:
|
||||||
action:
|
action:
|
||||||
set_view: "numbers"
|
set_view: "numbers"
|
||||||
outline: "wide"
|
outline: "altline"
|
||||||
label: "123"
|
|
||||||
show_numbers_from_symbols:
|
|
||||||
action:
|
|
||||||
set_view: "numbers"
|
|
||||||
outline: altline
|
|
||||||
label: "123"
|
label: "123"
|
||||||
show_letters:
|
show_letters:
|
||||||
action:
|
action:
|
||||||
set_view: "base"
|
set_view: "base"
|
||||||
outline: "wide"
|
outline: "altline"
|
||||||
label: "ABC"
|
label: "ABC"
|
||||||
show_symbols:
|
show_symbols:
|
||||||
action:
|
action:
|
||||||
@ -65,7 +60,7 @@ buttons:
|
|||||||
outline: "altline"
|
outline: "altline"
|
||||||
label: "*/="
|
label: "*/="
|
||||||
".":
|
".":
|
||||||
outline: "special"
|
outline: altline
|
||||||
space:
|
space:
|
||||||
outline: spaceline
|
outline: spaceline
|
||||||
text: " "
|
text: " "
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
---
|
|
||||||
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,10 +2,9 @@
|
|||||||
outlines:
|
outlines:
|
||||||
default: { width: 32, height: 52 }
|
default: { width: 32, height: 52 }
|
||||||
altline: { width: 48.39024, height: 52 }
|
altline: { width: 48.39024, height: 52 }
|
||||||
wide: { width: 64, height: 52 }
|
wide: { width: 62, height: 52 }
|
||||||
spaceline: { width: 142, height: 52 }
|
outline7: { width: 88.97561, height: 52 }
|
||||||
special: { width: 44, height: 52 }
|
spaceline: { width: 150.5853, height: 52 }
|
||||||
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
@ -26,7 +25,7 @@ views:
|
|||||||
symbols:
|
symbols:
|
||||||
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
|
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
|
||||||
- "show_numbers_from_symbols backslash slash less greater equal bracketleft bracketright BackSpace"
|
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
|
||||||
- "show_letters preferences space . Return"
|
- "show_letters preferences space . Return"
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
@ -38,27 +37,22 @@ buttons:
|
|||||||
outline: "altline"
|
outline: "altline"
|
||||||
icon: "key-shift"
|
icon: "key-shift"
|
||||||
BackSpace:
|
BackSpace:
|
||||||
outline: altline
|
outline: "altline"
|
||||||
icon: "edit-clear-symbolic"
|
icon: "edit-clear-symbolic"
|
||||||
action: erase
|
action: erase
|
||||||
preferences:
|
preferences:
|
||||||
action: "show_prefs"
|
action: "show_prefs"
|
||||||
outline: "special"
|
outline: "altline"
|
||||||
icon: "keyboard-mode-symbolic"
|
icon: "keyboard-mode-symbolic"
|
||||||
show_numbers:
|
show_numbers:
|
||||||
outline: "wide"
|
|
||||||
action:
|
action:
|
||||||
set_view: "numbers"
|
set_view: "numbers"
|
||||||
label: "123"
|
outline: "altline"
|
||||||
show_numbers_from_symbols:
|
|
||||||
action:
|
|
||||||
set_view: "numbers"
|
|
||||||
outline: altline
|
|
||||||
label: "123"
|
label: "123"
|
||||||
show_letters:
|
show_letters:
|
||||||
outline: "wide"
|
|
||||||
action:
|
action:
|
||||||
set_view: "base"
|
set_view: "base"
|
||||||
|
outline: "altline"
|
||||||
label: "ABC"
|
label: "ABC"
|
||||||
show_symbols:
|
show_symbols:
|
||||||
action:
|
action:
|
||||||
@ -66,7 +60,7 @@ buttons:
|
|||||||
outline: "altline"
|
outline: "altline"
|
||||||
label: "*/="
|
label: "*/="
|
||||||
".":
|
".":
|
||||||
outline: "special"
|
outline: altline
|
||||||
space:
|
space:
|
||||||
outline: spaceline
|
outline: spaceline
|
||||||
text: " "
|
text: " "
|
||||||
@ -162,3 +156,4 @@ buttons:
|
|||||||
text: "["
|
text: "["
|
||||||
bracketright:
|
bracketright:
|
||||||
text: "]"
|
text: "]"
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +1,38 @@
|
|||||||
---
|
---
|
||||||
outlines:
|
outlines:
|
||||||
default: { width: 35.33, height: 46 }
|
default: { width: 35.33, height: 52 }
|
||||||
action: { width: 59, height: 46 }
|
action: { width: 59, height: 52 }
|
||||||
altline: { width: 52.67, height: 46 }
|
altline: { width: 52.67, height: 52 }
|
||||||
wide: { width: 59, height: 46 }
|
wide: { width: 59, height: 52 }
|
||||||
spaceline: { width: 140, height: 46 }
|
spaceline: { width: 140, height: 52 }
|
||||||
special: { width: 44, height: 46 }
|
special: { width: 44, height: 52 }
|
||||||
small: { width: 59, height: 22 }
|
|
||||||
|
|
||||||
views:
|
views:
|
||||||
base:
|
base:
|
||||||
- "Ctrl Alt ↑ ↓ ← →"
|
|
||||||
- "q w e r t y u i o p"
|
- "q w e r t y u i o p"
|
||||||
- "a s d f g h j k l"
|
- "a s d f g h j k l"
|
||||||
- "Shift_L z x c v b n m BackSpace"
|
- "Shift_L z x c v b n m BackSpace"
|
||||||
- "show_numbers preferences space show_actions Return"
|
- "show_numbers preferences space show_actions Return"
|
||||||
upper:
|
upper:
|
||||||
- "Ctrl Alt PgUp PgDn Home End"
|
|
||||||
- "Q W E R T Y U I O P"
|
- "Q W E R T Y U I O P"
|
||||||
- "A S D F G H J K L"
|
- "A S D F G H J K L"
|
||||||
- "Shift_L Z X C V B N M BackSpace"
|
- "Shift_L Z X C V B N M BackSpace"
|
||||||
- "show_numbers preferences space show_actions Return"
|
- "show_numbers preferences space show_actions Return"
|
||||||
numbers:
|
numbers:
|
||||||
- "Ctrl Alt ↑ ↓ ← →"
|
|
||||||
- "1 2 3 4 5 6 7 8 9 0"
|
- "1 2 3 4 5 6 7 8 9 0"
|
||||||
- "* # $ / & - _ + ( )"
|
- "* # $ / & - _ + ( )"
|
||||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||||
- "show_letters preferences space period Return"
|
- "show_letters preferences space period Return"
|
||||||
symbols:
|
symbols:
|
||||||
- "Ctrl Alt ↑ ↓ ← →"
|
|
||||||
- "~ ` | · √ π τ ÷ × ¶"
|
- "~ ` | · √ π τ ÷ × ¶"
|
||||||
- "© ® £ € ¥ ^ ° @ { }"
|
- "© ® £ € ¥ ^ ° @ { }"
|
||||||
- "show_numbers_from_symbols \\ % < > = [ ] BackSpace"
|
- "show_numbers_from_symbols \\ % < > = [ ] BackSpace"
|
||||||
- "show_letters preferences space period Return"
|
- "show_letters preferences space period Return"
|
||||||
actions:
|
actions:
|
||||||
- "Ctrl Alt PgUp PgDn Home End"
|
|
||||||
- "F1 F2 F3 F4 F5 F6"
|
- "F1 F2 F3 F4 F5 F6"
|
||||||
- "F7 F8 F9 F10 F11 F12"
|
- "F7 F8 F9 F10 F11 F12"
|
||||||
- "Esc Tab Pause Insert Up Del"
|
- "Esc Tab Del PgUp ↑ PgDn"
|
||||||
- "show_letters Menu Break Left Down Right"
|
- "show_letters Home End ← ↓ →"
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
Shift_L:
|
Shift_L:
|
||||||
@ -138,67 +132,28 @@ buttons:
|
|||||||
Del:
|
Del:
|
||||||
outline: "action"
|
outline: "action"
|
||||||
keysym: "Delete"
|
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:
|
Home:
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Home"
|
keysym: "Home"
|
||||||
End:
|
End:
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "End"
|
keysym: "End"
|
||||||
PgUp:
|
PgUp:
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Page_Up"
|
keysym: "Page_Up"
|
||||||
PgDn:
|
PgDn:
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Page_Down"
|
keysym: "Page_Down"
|
||||||
"↑":
|
"↑":
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Up"
|
keysym: "Up"
|
||||||
"↓":
|
"↓":
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Down"
|
keysym: "Down"
|
||||||
"←":
|
"←":
|
||||||
outline: "small"
|
outline: "action"
|
||||||
keysym: "Left"
|
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"
|
outline: "action"
|
||||||
keysym: "Right"
|
keysym: "Right"
|
||||||
Ctrl:
|
|
||||||
modifier: "Control"
|
|
||||||
outline: "small"
|
|
||||||
label: "Ctrl"
|
|
||||||
Alt:
|
|
||||||
modifier: "Alt"
|
|
||||||
outline: "small"
|
|
||||||
label: "Alt"
|
|
||||||
|
|
||||||
|
|||||||
@ -1,211 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
---
|
|
||||||
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"
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
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: ":"
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
bg Български
|
|
||||||
de Немски
|
|
||||||
es Испански
|
|
||||||
emoji Емоджи
|
|
||||||
fi Френски
|
|
||||||
gr Гръцки
|
|
||||||
it Италянски
|
|
||||||
no Норевежки
|
|
||||||
pl Полски
|
|
||||||
ru Руски
|
|
||||||
se Шведски
|
|
||||||
terminal Терминал
|
|
||||||
us Английски (САЩ)
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
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,18 +0,0 @@
|
|||||||
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,11 +0,0 @@
|
|||||||
de Немецкий
|
|
||||||
es Испанский
|
|
||||||
fi Финский
|
|
||||||
gr Греческий
|
|
||||||
it Итальянский
|
|
||||||
no Норвежский
|
|
||||||
pl Польский
|
|
||||||
ru Русский
|
|
||||||
se Шведский
|
|
||||||
terminal Терминал
|
|
||||||
us Английский (США)
|
|
||||||
@ -7,20 +7,13 @@ squeekboard_resources = gnome.compile_resources(
|
|||||||
c_name: 'squeekboard',
|
c_name: 'squeekboard',
|
||||||
)
|
)
|
||||||
|
|
||||||
desktopconf = configuration_data()
|
|
||||||
desktopconf.set('bindir', bindir)
|
|
||||||
|
|
||||||
desktop_file = 'sm.puri.Squeekboard.desktop'
|
desktop_file = 'sm.puri.Squeekboard.desktop'
|
||||||
|
|
||||||
i18n.merge_file('desktop',
|
i18n.merge_file('desktop',
|
||||||
input: configure_file(
|
input: desktop_file + '.in',
|
||||||
input: desktop_file + '.in.in',
|
|
||||||
output: desktop_file + '.in',
|
|
||||||
configuration: desktopconf
|
|
||||||
),
|
|
||||||
output: desktop_file,
|
output: desktop_file,
|
||||||
po_dir: '../po',
|
po_dir: '../po',
|
||||||
install: true,
|
install: true,
|
||||||
install_dir: desktopdir,
|
install_dir: join_paths(datadir, 'applications'),
|
||||||
type: 'desktop'
|
type: 'desktop'
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
Name=Squeekboard
|
Name=Squeekboard
|
||||||
GenericName=Squeekboard Virtual Keyboard
|
GenericName=Squeekboard Virtual Keyboard
|
||||||
Comment=Virtual Keyboard
|
Comment=Virtual Keyboard
|
||||||
Exec=@bindir@/squeekboard
|
Exec=squeekboard
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
NoDisplay=true
|
NoDisplay=true
|
||||||
@ -40,10 +40,6 @@ sq_button.action {
|
|||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
sq_button.small {
|
|
||||||
font-size: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Return {
|
#Return {
|
||||||
background: #1c71d8;
|
background: #1c71d8;
|
||||||
border-color: #1a5fb4;
|
border-color: #1a5fb4;
|
||||||
|
|||||||
@ -43,10 +43,6 @@ sq_button.action {
|
|||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
sq_button.small {
|
|
||||||
font-size: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Return {
|
#Return {
|
||||||
background: @theme_selected_bg_color; /* #1c71d8; */
|
background: @theme_selected_bg_color; /* #1c71d8; */
|
||||||
border-color: @borders; /*#1a5fb4;*/
|
border-color: @borders; /*#1a5fb4;*/
|
||||||
|
|||||||
203
debian/changelog
vendored
203
debian/changelog
vendored
@ -1,206 +1,3 @@
|
|||||||
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
|
squeekboard (1.9.0) amber-phone; urgency=medium
|
||||||
|
|
||||||
[ Dorota Czaplejewicz ]
|
[ Dorota Czaplejewicz ]
|
||||||
|
|||||||
6
debian/control
vendored
6
debian/control
vendored
@ -11,7 +11,7 @@ Build-Depends:
|
|||||||
libglib2.0-dev,
|
libglib2.0-dev,
|
||||||
libgnome-desktop-3-dev,
|
libgnome-desktop-3-dev,
|
||||||
libgtk-3-dev,
|
libgtk-3-dev,
|
||||||
libfeedback-dev,
|
libcroco3-dev,
|
||||||
librust-bitflags-1-dev (>= 1.0),
|
librust-bitflags-1-dev (>= 1.0),
|
||||||
librust-clap-2+default-dev (>= 2.32),
|
librust-clap-2+default-dev (>= 2.32),
|
||||||
librust-gio+v2-44-dev,
|
librust-gio+v2-44-dev,
|
||||||
@ -25,8 +25,6 @@ Build-Depends:
|
|||||||
librust-serde-yaml-0.8-dev (>= 0.8),
|
librust-serde-yaml-0.8-dev (>= 0.8),
|
||||||
librust-xkbcommon-0.4+wayland-dev (>= 0.4),
|
librust-xkbcommon-0.4+wayland-dev (>= 0.4),
|
||||||
libwayland-dev (>= 1.16),
|
libwayland-dev (>= 1.16),
|
||||||
lsb-release,
|
|
||||||
python3,
|
|
||||||
rustc,
|
rustc,
|
||||||
wayland-protocols (>= 1.14),
|
wayland-protocols (>= 1.14),
|
||||||
Standards-Version: 4.1.3
|
Standards-Version: 4.1.3
|
||||||
@ -39,8 +37,6 @@ Depends:
|
|||||||
gnome-themes-extra-data,
|
gnome-themes-extra-data,
|
||||||
${shlibs:Depends},
|
${shlibs:Depends},
|
||||||
${misc:Depends},
|
${misc:Depends},
|
||||||
Breaks:
|
|
||||||
librem5-base (<< 24),
|
|
||||||
Description: On-screen keyboard for Wayland
|
Description: On-screen keyboard for Wayland
|
||||||
Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.
|
Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.
|
||||||
|
|
||||||
|
|||||||
34
debian/rules
vendored
34
debian/rules
vendored
@ -2,42 +2,14 @@
|
|||||||
|
|
||||||
export CARGO_HOME = $(CURDIR)/debian/cargo
|
export CARGO_HOME = $(CURDIR)/debian/cargo
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
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
|
dh $@ --builddirectory=_build --buildsystem=meson
|
||||||
|
|
||||||
# The Debian version of linked-hash-map doesn't provide any hash,
|
# The Debian version of linked-hash-map doesn't provide any hash,
|
||||||
# causing Cargo to refuse to build with a crates.io copy
|
# causing Cargo to refuse to build with a crates.io copy
|
||||||
override_dh_auto_configure:
|
build-arch:
|
||||||
[ ! -f Cargo.lock ] || rm Cargo.lock
|
rm Cargo.lock
|
||||||
dh_auto_configure -- -Dlegacy=$(legacy)
|
dh $@ --builddirectory=_build --buildsystem=meson
|
||||||
|
|
||||||
override_dh_autoreconf:
|
override_dh_autoreconf:
|
||||||
|
|||||||
@ -13,16 +13,16 @@ 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.
|
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.
|
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:
|
Nonwithstanding 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 use the software,
|
||||||
- to modify its resources,
|
- to modify its resources,
|
||||||
- to change its behavior,
|
- to change its behaviour,
|
||||||
- to contribute upstream.
|
- 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:
|
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,
|
- being quick and useable,
|
||||||
- allowing local overrides of resources and config,
|
- allowing local overrides of resources and config,
|
||||||
- storing resources and config as editable, standard files,
|
- storing resources and config as editable, standard files,
|
||||||
- having complete, up to date documentation of interfaces,
|
- having complete, up to date documentation of interfaces,
|
||||||
@ -33,7 +33,7 @@ To give an idea of what it means in practice, those are some examples of what ha
|
|||||||
- having code that is [simple and obvious](https://www.python.org/dev/peps/pep-0020/),
|
- having code that is [simple and obvious](https://www.python.org/dev/peps/pep-0020/),
|
||||||
- having an easy process of testing and accepting contributions.
|
- 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.
|
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 benefitting the user compared to those benefitting regular contributors.
|
||||||
|
|
||||||
Sending patches
|
Sending patches
|
||||||
---------------
|
---------------
|
||||||
@ -43,7 +43,7 @@ By submitting a change to this project, you agree to license it under the [GPL l
|
|||||||
Development environment
|
Development environment
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
*Squeekboard* is regularly built and tested on [the development environment](https://developer.puri.sm/Librem5/Development_Environment.html).
|
*Squeekboard* is regularly built and tested on [the develpment environment](https://developer.puri.sm/Librem5/Development_Environment.html).
|
||||||
|
|
||||||
Recent Fedora releases are likely to be tested as well.
|
Recent Fedora releases are likely to be tested as well.
|
||||||
|
|
||||||
@ -113,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:
|
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 ([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))
|
- skipping brackets `{}` after every `if()`, `else`, and similar
|
||||||
|
|
||||||
Bad example:
|
Bad example:
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ Maintenance
|
|||||||
|
|
||||||
Squeekboard uses Rust & Cargo for some of its dependencies.
|
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 positional 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 positionsl arguments: source directory, and output artifact. So, `cargo test` becomes:
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build_dir
|
cd build_dir
|
||||||
@ -175,14 +175,10 @@ 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.
|
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 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:
|
`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:
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build_dir
|
cd build_dir
|
||||||
ninja ./Cargo.toml
|
|
||||||
sh /source_path/cargo.sh update
|
sh /source_path/cargo.sh update
|
||||||
ninja test
|
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.
|
|
||||||
|
|||||||
@ -1,92 +1,55 @@
|
|||||||
A guide to creating layouts
|
Kareema's guide to creating layouts
|
||||||
===========================
|
===================================
|
||||||
|
|
||||||
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).
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
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/)
|
**Get one of the existing keyboard layouts**
|
||||||
|
|
||||||
## Creating a new layout
|
* 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 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:
|
* 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).
|
* 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
|
* Clone your fork locally with `git clone` and use the uri of your forked repo there
|
||||||
|
|
||||||
### Edit your keyboard and get it merged
|
**Workflow to edit your keyboard and get it merged**
|
||||||
|
|
||||||
* It may be useful to check out the [generic guide how the workflow to contribute works](https://developer.puri.sm/Librem5/Contact/Contributing.html)
|
* A generic guide how the workflow to contribute works, can be found at https://developer.puri.sm/Librem5/Contact/Contributing.html
|
||||||
* Create a branch: Name it “keyboard-layout-mylanguage” or whatever
|
* Create a branch: Name it “keyboard-layout-mylanguage” or whatever
|
||||||
* Checkout your branch, edit your keyboard layout and commit your changes
|
* 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)
|
* 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
|
* Create a merge request for the branch to get your changes merged to the official squeekboard git repository
|
||||||
|
|
||||||
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.
|
**Compile squeekboard**
|
||||||
|
|
||||||
## Compiling and running 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)
|
||||||
|
|
||||||
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.
|
**Running squeekboard**
|
||||||
|
|
||||||
### Compile 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)
|
||||||
|
|
||||||
* 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)
|
* 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)
|
* 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:
|
* 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: )
|
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,6 +38,8 @@ struct _EekElementClass
|
|||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GType eek_element_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
void eek_element_set_name (EekElement *element,
|
void eek_element_set_name (EekElement *element,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCANBERRA
|
||||||
|
#include <canberra-gtk.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -37,22 +41,17 @@
|
|||||||
#include "src/layout.h"
|
#include "src/layout.h"
|
||||||
#include "src/submission.h"
|
#include "src/submission.h"
|
||||||
|
|
||||||
#define LIBFEEDBACK_USE_UNSTABLE_API
|
|
||||||
#include <libfeedback.h>
|
|
||||||
|
|
||||||
#define SQUEEKBOARD_APP_ID "sm.puri.squeekboard"
|
|
||||||
|
|
||||||
typedef struct _EekGtkKeyboardPrivate
|
typedef struct _EekGtkKeyboardPrivate
|
||||||
{
|
{
|
||||||
EekRenderer *renderer; // owned, nullable
|
EekRenderer *renderer; // owned, nullable
|
||||||
EekboardContextService *eekboard_context; // unowned reference
|
LayoutHolder *eekboard_context; // unowned reference
|
||||||
struct submission *submission; // unowned reference
|
struct submission *submission; // unowned reference
|
||||||
|
|
||||||
struct squeek_layout_state *layout; // unowned
|
struct squeek_layout_state *layout; // unowned
|
||||||
LevelKeyboard *keyboard; // unowned reference; it's kept in server-context
|
LevelKeyboard *keyboard; // unowned reference; it's kept in server-context
|
||||||
|
|
||||||
GdkEventSequence *sequence; // unowned reference
|
GdkEventSequence *sequence; // unowned reference
|
||||||
LfbEvent *event;
|
|
||||||
} EekGtkKeyboardPrivate;
|
} EekGtkKeyboardPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
|
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
|
||||||
@ -104,10 +103,10 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Units of virtual pixels size
|
// Units of pixel size
|
||||||
static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) {
|
static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) {
|
||||||
(void)height;
|
(void)height;
|
||||||
if (width < 540) {
|
if (width < 1080) {
|
||||||
return ARRANGEMENT_KIND_BASE;
|
return ARRANGEMENT_KIND_BASE;
|
||||||
}
|
}
|
||||||
return ARRANGEMENT_KIND_WIDE;
|
return ARRANGEMENT_KIND_WIDE;
|
||||||
@ -119,40 +118,28 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
|
|||||||
{
|
{
|
||||||
EekGtkKeyboardPrivate *priv =
|
EekGtkKeyboardPrivate *priv =
|
||||||
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
||||||
|
uint32_t scale = (uint32_t)gtk_widget_get_scale_factor(self);
|
||||||
// check if the change would switch types
|
// check if the change would switch types
|
||||||
enum squeek_arrangement_kind new_type = get_type(
|
enum squeek_arrangement_kind new_type = get_type(
|
||||||
(uint32_t)(allocation->width - allocation->x),
|
(uint32_t)(allocation->width - allocation->x) * scale,
|
||||||
(uint32_t)(allocation->height - allocation->y));
|
(uint32_t)(allocation->height - allocation->y) * scale);
|
||||||
if (priv->layout->arrangement != new_type) {
|
if (priv->layout->arrangement != new_type) {
|
||||||
priv->layout->arrangement = new_type;
|
struct squeek_layout_state layout = *priv->layout;
|
||||||
uint32_t time = gdk_event_get_time(NULL);
|
layout.arrangement = new_type;
|
||||||
eekboard_context_service_use_layout(priv->eekboard_context, priv->layout, time);
|
|
||||||
|
eek_layout_holder_use_layout(priv->eekboard_context, &layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->renderer) {
|
if (priv->renderer)
|
||||||
eek_renderer_set_allocation_size (priv->renderer,
|
eek_renderer_set_allocation_size (priv->renderer,
|
||||||
priv->keyboard->layout,
|
priv->keyboard->layout,
|
||||||
allocation->width,
|
allocation->width,
|
||||||
allocation->height);
|
allocation->height);
|
||||||
}
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
|
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
|
||||||
size_allocate (self, allocation);
|
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,
|
static void depress(EekGtkKeyboard *self,
|
||||||
gdouble x, gdouble y, guint32 time)
|
gdouble x, gdouble y, guint32 time)
|
||||||
{
|
{
|
||||||
@ -172,7 +159,7 @@ static void drag(EekGtkKeyboard *self,
|
|||||||
if (!priv->keyboard) {
|
if (!priv->keyboard) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
|
squeek_layout_drag(eek_layout_holder_get_keyboard(priv->eekboard_context)->layout,
|
||||||
priv->submission,
|
priv->submission,
|
||||||
x, y, eek_renderer_get_transformation(priv->renderer), time,
|
x, y, eek_renderer_get_transformation(priv->renderer), time,
|
||||||
priv->eekboard_context, self);
|
priv->eekboard_context, self);
|
||||||
@ -184,7 +171,7 @@ static void release(EekGtkKeyboard *self, guint32 time)
|
|||||||
if (!priv->keyboard) {
|
if (!priv->keyboard) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
|
squeek_layout_release(eek_layout_holder_get_keyboard(priv->eekboard_context)->layout,
|
||||||
priv->submission,
|
priv->submission,
|
||||||
eek_renderer_get_transformation(priv->renderer), time,
|
eek_renderer_get_transformation(priv->renderer), time,
|
||||||
priv->eekboard_context, self);
|
priv->eekboard_context, self);
|
||||||
@ -317,11 +304,6 @@ eek_gtk_keyboard_dispose (GObject *object)
|
|||||||
priv->keyboard = NULL;
|
priv->keyboard = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->event) {
|
|
||||||
g_clear_object (&priv->event);
|
|
||||||
lfb_uninit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,18 +335,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
|
|||||||
static void
|
static void
|
||||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
||||||
{
|
{
|
||||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
(void)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
|
static void
|
||||||
@ -373,7 +344,7 @@ on_notify_keyboard (GObject *object,
|
|||||||
EekGtkKeyboard *self) {
|
EekGtkKeyboard *self) {
|
||||||
(void)spec;
|
(void)spec;
|
||||||
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (self);
|
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (self);
|
||||||
priv->keyboard = eekboard_context_service_get_keyboard(EEKBOARD_CONTEXT_SERVICE(object));
|
priv->keyboard = eek_layout_holder_get_keyboard(LAYOUT_HOLDER(object));
|
||||||
if (priv->renderer) {
|
if (priv->renderer) {
|
||||||
eek_renderer_free(priv->renderer);
|
eek_renderer_free(priv->renderer);
|
||||||
}
|
}
|
||||||
@ -386,7 +357,7 @@ on_notify_keyboard (GObject *object,
|
|||||||
* Returns: a #GtkWidget
|
* Returns: a #GtkWidget
|
||||||
*/
|
*/
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
eek_gtk_keyboard_new (EekboardContextService *eekservice,
|
eek_gtk_keyboard_new (LayoutHolder *eekservice,
|
||||||
struct submission *submission,
|
struct submission *submission,
|
||||||
struct squeek_layout_state *layout)
|
struct squeek_layout_state *layout)
|
||||||
{
|
{
|
||||||
@ -410,24 +381,3 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice,
|
|||||||
return GTK_WIDGET(box);*/
|
return GTK_WIDGET(box);*/
|
||||||
return GTK_WIDGET(ret);
|
return GTK_WIDGET(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -47,8 +47,8 @@ struct _EekGtkKeyboardClass
|
|||||||
gpointer pdummy[24];
|
gpointer pdummy[24];
|
||||||
};
|
};
|
||||||
|
|
||||||
GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout);
|
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
||||||
void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self);
|
GtkWidget *eek_gtk_keyboard_new (LayoutHolder *eekservice, struct submission *submission, struct squeek_layout_state *layout);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_GTK_KEYBOARD_H */
|
#endif /* EEK_GTK_KEYBOARD_H */
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define _XOPEN_SOURCE 500
|
#define _XOPEN_SOURCE 500
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@ -31,61 +30,9 @@
|
|||||||
|
|
||||||
#include "eek-keyboard.h"
|
#include "eek-keyboard.h"
|
||||||
|
|
||||||
/// 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) {
|
void level_keyboard_free(LevelKeyboard *self) {
|
||||||
|
xkb_keymap_unref(self->keymap);
|
||||||
|
close(self->keymap_fd);
|
||||||
squeek_layout_free(self->layout);
|
squeek_layout_free(self->layout);
|
||||||
g_free(self);
|
g_free(self);
|
||||||
}
|
}
|
||||||
@ -94,9 +41,53 @@ LevelKeyboard*
|
|||||||
level_keyboard_new (struct squeek_layout *layout)
|
level_keyboard_new (struct squeek_layout *layout)
|
||||||
{
|
{
|
||||||
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
|
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
|
||||||
|
|
||||||
if (!keyboard) {
|
if (!keyboard) {
|
||||||
g_error("Failed to create a keyboard");
|
g_error("Failed to create a keyboard");
|
||||||
}
|
}
|
||||||
keyboard->layout = layout;
|
keyboard->layout = layout;
|
||||||
|
|
||||||
|
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;
|
return keyboard;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
* as published by the Free Software Foundation; either version 2 of
|
* as published by the Free Software Foundation; either version 2 of
|
||||||
* the License, or (at your option) any later version.
|
* the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful, but
|
* This library is distributed in the hope that it will be useful, but
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
@ -32,20 +32,19 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
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
|
/// Keyboard state holder
|
||||||
struct _LevelKeyboard {
|
struct _LevelKeyboard {
|
||||||
struct squeek_layout *layout; // owned
|
struct squeek_layout *layout; // owned
|
||||||
// FIXME: This no longer needs to exist, keymap was folded into layout.
|
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
|
||||||
};
|
};
|
||||||
typedef struct _LevelKeyboard LevelKeyboard;
|
typedef struct _LevelKeyboard LevelKeyboard;
|
||||||
|
|
||||||
gchar *eek_keyboard_get_keymap(LevelKeyboard *keyboard);
|
gchar * eek_keyboard_get_keymap
|
||||||
|
(LevelKeyboard *keyboard);
|
||||||
|
|
||||||
LevelKeyboard*
|
LevelKeyboard*
|
||||||
level_keyboard_new (struct squeek_layout *layout);
|
level_keyboard_new (struct squeek_layout *layout);
|
||||||
|
|||||||
@ -241,7 +241,7 @@ static GType new_type(char *name) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GType view_type(void) {
|
static GType view_type() {
|
||||||
static GType type = 0;
|
static GType type = 0;
|
||||||
if (!type) {
|
if (!type) {
|
||||||
type = new_type("sq_view");
|
type = new_type("sq_view");
|
||||||
@ -249,7 +249,7 @@ static GType view_type(void) {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GType button_type(void) {
|
static GType button_type() {
|
||||||
static GType type = 0;
|
static GType type = 0;
|
||||||
if (!type) {
|
if (!type) {
|
||||||
type = new_type("sq_button");
|
type = new_type("sq_button");
|
||||||
@ -265,6 +265,10 @@ renderer_init (EekRenderer *self)
|
|||||||
self->allocation_height = 0.0;
|
self->allocation_height = 0.0;
|
||||||
self->scale_factor = 1;
|
self->scale_factor = 1;
|
||||||
|
|
||||||
|
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||||
|
|
||||||
|
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
|
||||||
|
|
||||||
self->css_provider = squeek_load_style();
|
self->css_provider = squeek_load_style();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
typedef struct _EekBounds EekBounds;
|
typedef struct _EekBounds EekBounds;
|
||||||
|
|
||||||
typedef struct _EekboardContextService EekboardContextService;
|
typedef struct _LayoutHolder LayoutHolder;
|
||||||
typedef struct _ServerContextService ServerContextService;
|
typedef struct _ServerContextService ServerContextService;
|
||||||
typedef struct _LevelKeyboard LevelKeyboard;
|
typedef struct _LevelKeyboard LevelKeyboard;
|
||||||
|
|
||||||
|
|||||||
@ -590,32 +590,27 @@ phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height)
|
|||||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||||
priv = phosh_layer_surface_get_instance_private (self);
|
priv = phosh_layer_surface_get_instance_private (self);
|
||||||
|
|
||||||
if (priv->height == height && priv->width == width) {
|
if (priv->height == height && priv->width == width)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
old_width = priv->width;
|
old_width = priv->width;
|
||||||
old_height = priv->height;
|
old_height = priv->height;
|
||||||
|
|
||||||
if (width != -1) {
|
if (width != -1)
|
||||||
priv->width = width;
|
priv->width = width;
|
||||||
}
|
|
||||||
|
|
||||||
if (height != -1) {
|
if (height != -1)
|
||||||
priv->height = height;
|
priv->height = height;
|
||||||
}
|
|
||||||
|
|
||||||
if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
|
if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
|
||||||
zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
|
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]);
|
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]);
|
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -637,31 +632,25 @@ phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, g
|
|||||||
old_right = priv->margin_right;
|
old_right = priv->margin_right;
|
||||||
old_bottom = priv->margin_bottom;
|
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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
priv->margin_top = top;
|
priv->margin_top = top;
|
||||||
priv->margin_left = left;
|
priv->margin_left = left;
|
||||||
priv->margin_right = right;
|
priv->margin_right = right;
|
||||||
priv->margin_bottom = bottom;
|
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);
|
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]);
|
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]);
|
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]);
|
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]);
|
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -680,15 +669,13 @@ phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone)
|
|||||||
|
|
||||||
old_zone = priv->exclusive_zone;
|
old_zone = priv->exclusive_zone;
|
||||||
|
|
||||||
if (old_zone == zone) {
|
if (old_zone == zone)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
priv->exclusive_zone = zone;
|
priv->exclusive_zone = zone;
|
||||||
|
|
||||||
if (priv->layer_surface) {
|
if (priv->layer_surface)
|
||||||
zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, zone);
|
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]);
|
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]);
|
||||||
}
|
}
|
||||||
@ -706,14 +693,13 @@ phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean int
|
|||||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||||
priv = phosh_layer_surface_get_instance_private (self);
|
priv = phosh_layer_surface_get_instance_private (self);
|
||||||
|
|
||||||
if (priv->kbd_interactivity == interactivity) {
|
if (priv->kbd_interactivity == interactivity)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
priv->kbd_interactivity = interactivity;
|
priv->kbd_interactivity = interactivity;
|
||||||
|
|
||||||
if (priv->layer_surface) {
|
if (priv->layer_surface)
|
||||||
zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity);
|
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]);
|
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]);
|
||||||
}
|
}
|
||||||
@ -731,7 +717,6 @@ phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self)
|
|||||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||||
priv = phosh_layer_surface_get_instance_private (self);
|
priv = phosh_layer_surface_get_instance_private (self);
|
||||||
|
|
||||||
if (priv->wl_surface) {
|
if (priv->wl_surface)
|
||||||
wl_surface_commit (priv->wl_surface);
|
wl_surface_commit (priv->wl_surface);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,39 +35,17 @@ enum {
|
|||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
#define LAYOUT_HOLDER_GET_PRIVATE(obj) \
|
||||||
DESTROYED,
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEKBOARD_TYPE_LAYOUT_HOLDER, LayoutHolderPrivate))
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0, };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
|
|
||||||
|
struct _LayoutHolderPrivate {
|
||||||
LevelKeyboard *keyboard; // currently used keyboard
|
LevelKeyboard *keyboard; // currently used keyboard
|
||||||
GSettings *settings; // Owned reference
|
|
||||||
|
|
||||||
// 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
|
/// Needed for keymap changes after keyboard updates
|
||||||
struct submission *submission; // unowned
|
struct submission *submission; // unowned
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
|
G_DEFINE_TYPE_WITH_PRIVATE (LayoutHolder, layout_holder, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eekboard_context_service_set_property (GObject *object,
|
eekboard_context_service_set_property (GObject *object,
|
||||||
@ -84,16 +62,16 @@ eekboard_context_service_set_property (GObject *object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eekboard_context_service_get_property (GObject *object,
|
layout_holder_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(object);
|
LayoutHolder *context = LAYOUT_HOLDER(object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_KEYBOARD:
|
case PROP_KEYBOARD:
|
||||||
g_value_set_object (value, context->keyboard);
|
g_value_set_object (value, context->priv->keyboard);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
@ -101,13 +79,6 @@ eekboard_context_service_get_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_context_service_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
G_OBJECT_CLASS (eekboard_context_service_parent_class)->
|
|
||||||
dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
settings_get_layout(GSettings *settings, char **type, char **layout)
|
settings_get_layout(GSettings *settings, char **type, char **layout)
|
||||||
{
|
{
|
||||||
@ -127,7 +98,8 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *state, uint32_t timestamp) {
|
eek_layout_holder_use_layout(LayoutHolder *context, struct squeek_layout_state *state) {
|
||||||
|
*context->layout = *state;
|
||||||
gchar *layout_name = state->overlay_name;
|
gchar *layout_name = state->overlay_name;
|
||||||
|
|
||||||
if (layout_name == NULL) {
|
if (layout_name == NULL) {
|
||||||
@ -154,12 +126,12 @@ eekboard_context_service_use_layout(EekboardContextService *context, struct sque
|
|||||||
struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement);
|
struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement);
|
||||||
LevelKeyboard *keyboard = level_keyboard_new(layout);
|
LevelKeyboard *keyboard = level_keyboard_new(layout);
|
||||||
// set as current
|
// set as current
|
||||||
LevelKeyboard *previous_keyboard = context->keyboard;
|
LevelKeyboard *previous_keyboard = context->priv->keyboard;
|
||||||
context->keyboard = keyboard;
|
context->priv->keyboard = keyboard;
|
||||||
// Update the keymap if necessary.
|
// Update the keymap if necessary.
|
||||||
// TODO: Update submission on change event
|
// TODO: Update submission on change event
|
||||||
if (context->submission) {
|
if (context->priv->submission) {
|
||||||
submission_use_layout(context->submission, keyboard->layout, timestamp);
|
submission_set_keyboard(context->priv->submission, keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
@ -171,74 +143,22 @@ eekboard_context_service_use_layout(EekboardContextService *context, struct sque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eekboard_context_service_update_settings_layout(EekboardContextService *context) {
|
static void
|
||||||
g_autofree gchar *keyboard_layout = NULL;
|
layout_holder_init (LayoutHolder *self) {
|
||||||
g_autofree gchar *keyboard_type = NULL;
|
self->priv = LAYOUT_HOLDER_GET_PRIVATE(self);
|
||||||
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
|
|
||||||
settings_handle_layout_changed(GSettings *s,
|
|
||||||
gpointer keys, gint n_keys,
|
|
||||||
gpointer user_data) {
|
|
||||||
(void)s;
|
|
||||||
(void)keys;
|
|
||||||
(void)n_keys;
|
|
||||||
EekboardContextService *context = user_data;
|
|
||||||
eekboard_context_service_update_settings_layout(context);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eekboard_context_service_constructed (GObject *object)
|
layout_holder_class_init (LayoutHolderClass *klass)
|
||||||
{
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
|
|
||||||
gobject_class->constructed = eekboard_context_service_constructed;
|
|
||||||
gobject_class->set_property = eekboard_context_service_set_property;
|
gobject_class->set_property = eekboard_context_service_set_property;
|
||||||
gobject_class->get_property = eekboard_context_service_get_property;
|
gobject_class->get_property = layout_holder_get_property;
|
||||||
gobject_class->dispose = eekboard_context_service_dispose;
|
|
||||||
/**
|
|
||||||
* EekboardContextService::destroyed:
|
|
||||||
* @context: an #EekboardContextService
|
|
||||||
*
|
|
||||||
* Emitted when @context is destroyed.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EekboardContextService:keyboard:
|
* An #LevelKeyboard currently active in this context.
|
||||||
*
|
|
||||||
* An #EekKeyboard currently active in this context.
|
|
||||||
*/
|
*/
|
||||||
pspec = g_param_spec_pointer("keyboard",
|
pspec = g_param_spec_pointer("keyboard",
|
||||||
"Keyboard",
|
"Keyboard",
|
||||||
@ -249,106 +169,115 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
|||||||
pspec);
|
pspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_context_service_init (EekboardContextService *self)
|
|
||||||
{
|
|
||||||
const char *schema_name = "org.gnome.desktop.input-sources";
|
|
||||||
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default();
|
|
||||||
g_autoptr(GSettingsSchema) schema = NULL;
|
|
||||||
|
|
||||||
if (!ssrc) {
|
|
||||||
g_warning("No gsettings schemas installed. Layout switching unavailable.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eekboard_context_service_destroy:
|
|
||||||
* @context: an #EekboardContextService
|
|
||||||
*
|
|
||||||
* Destroy @context.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
eekboard_context_service_destroy (EekboardContextService *context)
|
|
||||||
{
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
|
|
||||||
g_signal_emit (context, signals[DESTROYED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_context_service_get_keyboard:
|
|
||||||
* @context: an #EekboardContextService
|
|
||||||
*
|
|
||||||
* Get keyboard currently active in @context.
|
* Get keyboard currently active in @context.
|
||||||
* Returns: (transfer none): an #EekKeyboard
|
* Returns: (transfer none): a LevelKeyboard
|
||||||
*/
|
*/
|
||||||
LevelKeyboard *
|
LevelKeyboard *
|
||||||
eekboard_context_service_get_keyboard (EekboardContextService *context)
|
eek_layout_holder_get_keyboard (LayoutHolder *context)
|
||||||
{
|
{
|
||||||
return context->keyboard;
|
return context->priv->keyboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
void eekboard_context_service_set_hint_purpose(LayoutHolder *context,
|
||||||
uint32_t hint, uint32_t purpose)
|
uint32_t hint, uint32_t purpose)
|
||||||
{
|
{
|
||||||
if (context->layout->hint != hint || context->layout->purpose != purpose) {
|
if (context->layout->hint != hint || context->layout->purpose != purpose) {
|
||||||
context->layout->hint = hint;
|
context->layout->hint = hint;
|
||||||
context->layout->purpose = purpose;
|
context->layout->purpose = purpose;
|
||||||
uint32_t time = gdk_event_get_time(NULL);
|
eek_layout_holder_use_layout(context, context->layout);
|
||||||
eekboard_context_service_use_layout(context, context->layout, time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) {
|
eekboard_context_service_set_overlay(LayoutHolder *context, const char* name) {
|
||||||
if (g_strcmp0(context->layout->overlay_name, name)) {
|
if (g_strcmp0(context->layout->overlay_name, name)) {
|
||||||
g_free(context->layout->overlay_name);
|
g_free(context->layout->overlay_name);
|
||||||
context->layout->overlay_name = g_strdup(name);
|
context->layout->overlay_name = g_strdup(name);
|
||||||
uint32_t time = gdk_event_get_time(NULL);
|
eek_layout_holder_use_layout(context, context->layout);
|
||||||
eekboard_context_service_use_layout(context, context->layout, time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
eekboard_context_service_get_overlay(EekboardContextService *context) {
|
eekboard_context_service_get_overlay(LayoutHolder *context) {
|
||||||
return context->layout->overlay_name;
|
return context->layout->overlay_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state)
|
LayoutHolder *eek_layout_holder_new(struct squeek_layout_state *state)
|
||||||
{
|
{
|
||||||
EekboardContextService *context = g_object_new (EEKBOARD_TYPE_CONTEXT_SERVICE, NULL);
|
LayoutHolder *context = g_object_new (EEKBOARD_TYPE_LAYOUT_HOLDER, NULL);
|
||||||
context->layout = state;
|
context->layout = state;
|
||||||
eekboard_context_service_update_settings_layout(context);
|
eek_layout_holder_use_layout(context, context->layout);
|
||||||
uint32_t time = gdk_event_get_time(NULL);
|
|
||||||
eekboard_context_service_use_layout(context, context->layout, time);
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission) {
|
void eek_layout_holder_set_submission(LayoutHolder *context, struct submission *submission) {
|
||||||
context->submission = submission;
|
context->priv->submission = submission;
|
||||||
if (context->submission) {
|
if (context->priv->submission) {
|
||||||
uint32_t time = gdk_event_get_time(NULL);
|
submission_set_keyboard(context->priv->submission, context->priv->keyboard);
|
||||||
submission_use_layout(context->submission, context->keyboard->layout, time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui) {
|
static void settings_update_layout(struct gsettings_tracker *self) {
|
||||||
context->ui = ui;
|
// The layout in the param must be the same layout as held by context.
|
||||||
|
g_autofree gchar *keyboard_layout = NULL;
|
||||||
|
g_autofree gchar *keyboard_type = NULL;
|
||||||
|
settings_get_layout(self->gsettings,
|
||||||
|
&keyboard_type, &keyboard_layout);
|
||||||
|
|
||||||
|
if (g_strcmp0(self->layout->layout_name, keyboard_layout) != 0 || self->layout->overlay_name) {
|
||||||
|
g_free(self->layout->overlay_name);
|
||||||
|
self->layout->overlay_name = NULL;
|
||||||
|
if (keyboard_layout) {
|
||||||
|
g_free(self->layout->layout_name);
|
||||||
|
self->layout->layout_name = g_strdup(keyboard_layout);
|
||||||
|
}
|
||||||
|
// This must actually update the UI.
|
||||||
|
eek_layout_holder_use_layout(self->context, self->layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_layout_changed(GSettings *s,
|
||||||
|
gpointer keys, gint n_keys,
|
||||||
|
gpointer user_data) {
|
||||||
|
(void)s;
|
||||||
|
(void)keys;
|
||||||
|
(void)n_keys;
|
||||||
|
struct gsettings_tracker *self = user_data;
|
||||||
|
settings_update_layout(self);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eek_gsettings_tracker_init(struct gsettings_tracker *tracker, LayoutHolder *context, struct squeek_layout_state *layout)
|
||||||
|
{
|
||||||
|
tracker->layout = layout;
|
||||||
|
tracker->context = context;
|
||||||
|
|
||||||
|
const char *schema_name = "org.gnome.desktop.input-sources";
|
||||||
|
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default();
|
||||||
|
if (ssrc) {
|
||||||
|
GSettingsSchema *schema = g_settings_schema_source_lookup(ssrc,
|
||||||
|
schema_name,
|
||||||
|
TRUE);
|
||||||
|
if (schema) {
|
||||||
|
// Not referencing the found schema directly,
|
||||||
|
// because it's not clear how...
|
||||||
|
tracker->gsettings = g_settings_new (schema_name);
|
||||||
|
gulong conn_id = g_signal_connect(tracker->gsettings, "change-event",
|
||||||
|
G_CALLBACK(handle_layout_changed),
|
||||||
|
tracker);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_warning("No gsettings schemas installed. Layout switching unavailable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_update_layout(tracker);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,26 +30,60 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define EEKBOARD_CONTEXT_SERVICE_PATH "/org/fedorahosted/Eekboard/Context_%d"
|
#define EEKBOARD_TYPE_LAYOUT_HOLDER (layout_holder_get_type())
|
||||||
#define EEKBOARD_CONTEXT_SERVICE_INTERFACE "org.fedorahosted.Eekboard.Context"
|
#define LAYOUT_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_LAYOUT_HOLDER, LayoutHolder))
|
||||||
|
#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))
|
||||||
|
|
||||||
#define EEKBOARD_TYPE_CONTEXT_SERVICE (eekboard_context_service_get_type())
|
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(EekboardContextService, eekboard_context_service, EEKBOARD, CONTEXT_SERVICE, GObject)
|
typedef struct _LayoutHolderClass LayoutHolderClass;
|
||||||
|
typedef struct _LayoutHolderPrivate LayoutHolderPrivate;
|
||||||
|
|
||||||
EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state);
|
/**
|
||||||
void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission);
|
* Handles layout state, and virtual-keyboard.
|
||||||
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui);
|
*
|
||||||
void eekboard_context_service_destroy (EekboardContextService *context);
|
* TODO: Restrict to managing keyboard layouts, and maybe button repeats,
|
||||||
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
|
* and the virtual keyboard protocol.
|
||||||
|
*/
|
||||||
|
struct _LayoutHolder {
|
||||||
|
GObject parent;
|
||||||
|
LayoutHolderPrivate *priv;
|
||||||
|
struct squeek_layout_state *layout; // Unowned
|
||||||
|
};
|
||||||
|
|
||||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
|
struct _LayoutHolderClass {
|
||||||
|
/*< private >*/
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
/* padding */
|
||||||
|
gpointer pdummy[24];
|
||||||
|
};
|
||||||
|
|
||||||
|
GType layout_holder_get_type(void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/// Handles gsettings os-level keyboard layout switches.
|
||||||
|
struct gsettings_tracker {
|
||||||
|
GSettings *gsettings; // Owned reference
|
||||||
|
LayoutHolder *context; // Unowned
|
||||||
|
struct squeek_layout_state *layout; // Unowned
|
||||||
|
};
|
||||||
|
|
||||||
|
void eek_gsettings_tracker_init(struct gsettings_tracker* tracker, LayoutHolder *context, struct squeek_layout_state *layout);
|
||||||
|
|
||||||
|
LayoutHolder *eek_layout_holder_new(struct squeek_layout_state *state);
|
||||||
|
void eek_layout_holder_set_submission(LayoutHolder *context, struct submission *submission);
|
||||||
|
LevelKeyboard *eek_layout_holder_get_keyboard(LayoutHolder *context);
|
||||||
|
|
||||||
|
void eekboard_context_service_set_keymap(LayoutHolder *context,
|
||||||
const LevelKeyboard *keyboard);
|
const LevelKeyboard *keyboard);
|
||||||
|
|
||||||
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
void eekboard_context_service_set_hint_purpose(LayoutHolder *context,
|
||||||
uint32_t hint,
|
uint32_t hint,
|
||||||
uint32_t purpose);
|
uint32_t purpose);
|
||||||
void
|
void
|
||||||
eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp);
|
eek_layout_holder_use_layout(LayoutHolder *context, struct squeek_layout_state *layout);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEKBOARD_CONTEXT_SERVICE_H */
|
#endif /* EEKBOARD_CONTEXT_SERVICE_H */
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use std::env;
|
|||||||
|
|
||||||
fn main() -> () {
|
fn main() -> () {
|
||||||
check_builtin_layout(
|
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(
|
project(
|
||||||
'squeekboard',
|
'squeekboard',
|
||||||
'c', 'rust',
|
'c', 'rust',
|
||||||
version: '1.10.0',
|
version: '1.8.0',
|
||||||
license: 'GPLv3',
|
license: 'GPLv3',
|
||||||
meson_version: '>=0.51.0',
|
meson_version: '>=0.51.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
@ -19,17 +19,6 @@ add_project_arguments(
|
|||||||
'-Werror=missing-field-initializers',
|
'-Werror=missing-field-initializers',
|
||||||
'-Werror=incompatible-pointer-types',
|
'-Werror=incompatible-pointer-types',
|
||||||
'-Werror=int-conversion',
|
'-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'
|
language: 'c'
|
||||||
)
|
)
|
||||||
@ -41,16 +30,6 @@ conf_data = configuration_data()
|
|||||||
if get_option('buildtype').startswith('debug')
|
if get_option('buildtype').startswith('debug')
|
||||||
add_project_arguments('-DDEBUG=1', language : 'c')
|
add_project_arguments('-DDEBUG=1', language : 'c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('strict')
|
|
||||||
add_project_arguments(
|
|
||||||
[
|
|
||||||
'-Werror',
|
|
||||||
],
|
|
||||||
language: 'c'
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('buildtype') != 'plain'
|
if get_option('buildtype') != 'plain'
|
||||||
add_project_arguments('-fstack-protector-strong', language: 'c')
|
add_project_arguments('-fstack-protector-strong', language: 'c')
|
||||||
endif
|
endif
|
||||||
@ -63,7 +42,6 @@ endif
|
|||||||
prefix = get_option('prefix')
|
prefix = get_option('prefix')
|
||||||
bindir = join_paths(prefix, get_option('bindir'))
|
bindir = join_paths(prefix, get_option('bindir'))
|
||||||
datadir = join_paths(prefix, get_option('datadir'))
|
datadir = join_paths(prefix, get_option('datadir'))
|
||||||
desktopdir = join_paths(datadir, 'applications')
|
|
||||||
pkgdatadir = join_paths(datadir, meson.project_name())
|
pkgdatadir = join_paths(datadir, meson.project_name())
|
||||||
if get_option('depdatadir') == ''
|
if get_option('depdatadir') == ''
|
||||||
depdatadir = datadir
|
depdatadir = datadir
|
||||||
@ -82,36 +60,9 @@ summary = [
|
|||||||
]
|
]
|
||||||
message('\n'.join(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')
|
dep_cargo = find_program('cargo')
|
||||||
cargo_script = find_program('cargo.sh')
|
cargo_script = find_program('cargo.sh')
|
||||||
cargo_build = find_program('cargo_build.py')
|
cargo_build = find_program('cargo_build.sh')
|
||||||
|
|
||||||
subdir('data')
|
subdir('data')
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
|
|||||||
@ -6,11 +6,3 @@ option('depdatadir',
|
|||||||
option('tests',
|
option('tests',
|
||||||
type: 'boolean', value: true,
|
type: 'boolean', value: true,
|
||||||
description: 'Whether to compile unit tests')
|
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')
|
|
||||||
|
|||||||
329
src/data.rs
329
src/data.rs
@ -18,7 +18,7 @@ use xkbcommon::xkb;
|
|||||||
use ::action;
|
use ::action;
|
||||||
use ::keyboard::{
|
use ::keyboard::{
|
||||||
KeyState, PressType,
|
KeyState, PressType,
|
||||||
generate_keymaps, generate_keycodes, KeyCode, FormattingError
|
generate_keymap, generate_keycodes, FormattingError
|
||||||
};
|
};
|
||||||
use ::layout;
|
use ::layout;
|
||||||
use ::layout::ArrangementKind;
|
use ::layout::ArrangementKind;
|
||||||
@ -97,8 +97,6 @@ impl fmt::Display for DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LayoutSource = (ArrangementKind, DataSource);
|
|
||||||
|
|
||||||
/// Lists possible sources, with 0 as the most preferred one
|
/// Lists possible sources, with 0 as the most preferred one
|
||||||
/// Trying order: native lang of the right kind, native base,
|
/// Trying order: native lang of the right kind, native base,
|
||||||
/// fallback lang of the right kind, fallback base
|
/// fallback lang of the right kind, fallback base
|
||||||
@ -106,76 +104,55 @@ fn list_layout_sources(
|
|||||||
name: &str,
|
name: &str,
|
||||||
kind: ArrangementKind,
|
kind: ArrangementKind,
|
||||||
keyboards_path: Option<PathBuf>,
|
keyboards_path: Option<PathBuf>,
|
||||||
) -> Vec<LayoutSource> {
|
) -> Vec<(ArrangementKind, DataSource)> {
|
||||||
// Just a simplification of often called code.
|
let mut ret = Vec::new();
|
||||||
let add_by_name = |
|
{
|
||||||
mut ret: Vec<LayoutSource>,
|
fn name_with_arrangement(name: String, kind: &ArrangementKind)
|
||||||
name: &str,
|
-> String
|
||||||
kind: &ArrangementKind,
|
{
|
||||||
| -> Vec<LayoutSource> {
|
match kind {
|
||||||
if let Some(path) = keyboards_path.clone() {
|
ArrangementKind::Base => name,
|
||||||
ret.push((
|
ArrangementKind::Wide => name + "_wide",
|
||||||
kind.clone(),
|
}
|
||||||
DataSource::File(
|
|
||||||
path.join(name.to_owned()).with_extension("yaml")
|
|
||||||
)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push((
|
let mut add_by_name = |name: &str, kind: &ArrangementKind| {
|
||||||
kind.clone(),
|
if let Some(path) = keyboards_path.clone() {
|
||||||
DataSource::Resource(name.into())
|
ret.push((
|
||||||
));
|
kind.clone(),
|
||||||
ret
|
DataSource::File(
|
||||||
};
|
path.join(name.to_owned()).with_extension("yaml")
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push((
|
||||||
|
kind.clone(),
|
||||||
|
DataSource::Resource(name.into())
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
// Another grouping.
|
match &kind {
|
||||||
let add_by_kind = |ret, name: &str, kind| {
|
ArrangementKind::Base => {},
|
||||||
let ret = match kind {
|
|
||||||
&ArrangementKind::Base => ret,
|
|
||||||
kind => add_by_name(
|
kind => add_by_name(
|
||||||
ret,
|
&name_with_arrangement(name.into(), &kind),
|
||||||
&name_with_arrangement(name.into(), kind),
|
&kind,
|
||||||
kind,
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
add_by_name(ret, name, &ArrangementKind::Base)
|
add_by_name(name, &ArrangementKind::Base);
|
||||||
};
|
|
||||||
|
|
||||||
fn name_with_arrangement(name: String, kind: &ArrangementKind) -> String {
|
match &kind {
|
||||||
match kind {
|
ArrangementKind::Base => {},
|
||||||
ArrangementKind::Base => name,
|
kind => add_by_name(
|
||||||
ArrangementKind::Wide => name + "_wide",
|
&name_with_arrangement(FALLBACK_LAYOUT_NAME.into(), &kind),
|
||||||
}
|
&kind,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
add_by_name(FALLBACK_LAYOUT_NAME, &ArrangementKind::Base);
|
||||||
}
|
}
|
||||||
|
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)
|
fn load_layout_data(source: DataSource)
|
||||||
@ -405,45 +382,56 @@ impl Layout {
|
|||||||
)
|
)
|
||||||
)}).collect();
|
)}).collect();
|
||||||
|
|
||||||
let symbolmap: HashMap<String, KeyCode> = generate_keycodes(
|
let keymap: HashMap<String, u32> = generate_keycodes(
|
||||||
extract_symbol_names(&button_actions)
|
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 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()
|
||||||
|
},
|
||||||
|
action::Action::Erase => vec![
|
||||||
|
*keymap.get("BackSpace")
|
||||||
|
.expect(&format!("BackSpace missing from keymap")),
|
||||||
|
],
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
(
|
||||||
|
name.into(),
|
||||||
|
KeyState {
|
||||||
|
pressed: PressType::Released,
|
||||||
|
keycodes,
|
||||||
|
action,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let button_states = HashMap::<String, KeyState>::from_iter(
|
let button_states = HashMap::<String, KeyState>::from_iter(
|
||||||
button_actions.into_iter().map(|(name, action)| {
|
button_states
|
||||||
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,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let keymaps = match generate_keymaps(symbolmap) {
|
// TODO: generate from symbols
|
||||||
|
let keymap_str = match generate_keymap(&button_states) {
|
||||||
Err(e) => { return (Err(e), warning_handler) },
|
Err(e) => { return (Err(e), warning_handler) },
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
};
|
};
|
||||||
@ -471,14 +459,14 @@ impl Layout {
|
|||||||
&mut warning_handler,
|
&mut warning_handler,
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
layout::Row::new(
|
layout::Row {
|
||||||
add_offsets(
|
buttons: add_offsets(
|
||||||
buttons,
|
buttons,
|
||||||
|button| button.size.width,
|
|button| button.size.width,
|
||||||
).collect()
|
).collect()
|
||||||
)
|
}
|
||||||
});
|
});
|
||||||
let rows = add_offsets(rows, |row| row.get_size().height)
|
let rows = add_offsets(rows, |row| row.get_height())
|
||||||
.collect();
|
.collect();
|
||||||
(
|
(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
@ -496,8 +484,8 @@ impl Layout {
|
|||||||
name,
|
name,
|
||||||
(
|
(
|
||||||
layout::c::Point {
|
layout::c::Point {
|
||||||
x: (total_size.width - view.get_size().width) / 2.0,
|
x: (total_size.width - view.get_width()) / 2.0,
|
||||||
y: (total_size.height - view.get_size().height) / 2.0,
|
y: (total_size.height - view.get_height()) / 2.0,
|
||||||
},
|
},
|
||||||
view,
|
view,
|
||||||
),
|
),
|
||||||
@ -507,10 +495,10 @@ impl Layout {
|
|||||||
(
|
(
|
||||||
Ok(::layout::LayoutData {
|
Ok(::layout::LayoutData {
|
||||||
views: views,
|
views: views,
|
||||||
keymaps: keymaps.into_iter().map(|keymap_str|
|
keymap_str: {
|
||||||
CString::new(keymap_str)
|
CString::new(keymap_str)
|
||||||
.expect("Invalid keymap string generated")
|
.expect("Invalid keymap string generated")
|
||||||
).collect(),
|
},
|
||||||
// FIXME: use a dedicated field
|
// FIXME: use a dedicated field
|
||||||
margins: layout::Margins {
|
margins: layout::Margins {
|
||||||
top: self.margins.top,
|
top: self.margins.top,
|
||||||
@ -746,50 +734,17 @@ fn create_button<H: logging::Handler>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use std::error::Error as ErrorTrait;
|
||||||
use ::logging::ProblemPanic;
|
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]
|
#[test]
|
||||||
fn test_parse_path() {
|
fn test_parse_path() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Layout::from_file(path_from_root("tests/layout.yaml")).unwrap(),
|
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
|
||||||
Layout {
|
Layout {
|
||||||
margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
|
margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
|
||||||
views: hashmap!(
|
views: hashmap!(
|
||||||
@ -816,14 +771,13 @@ mod tests {
|
|||||||
/// Check if the default protection works
|
/// Check if the default protection works
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_views() {
|
fn test_empty_views() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout2.yaml"));
|
let out = Layout::from_file(PathBuf::from("tests/layout2.yaml"));
|
||||||
match out {
|
match out {
|
||||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut handled = false;
|
let mut handled = false;
|
||||||
if let Error::Yaml(ye) = &e {
|
if let Error::Yaml(ye) = &e {
|
||||||
handled = ye.to_string()
|
handled = ye.description() == "missing field `views`";
|
||||||
.starts_with("missing field `views`");
|
|
||||||
};
|
};
|
||||||
if !handled {
|
if !handled {
|
||||||
println!("Unexpected error {:?}", e);
|
println!("Unexpected error {:?}", e);
|
||||||
@ -835,13 +789,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extra_field() {
|
fn test_extra_field() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout3.yaml"));
|
let out = Layout::from_file(PathBuf::from("tests/layout3.yaml"));
|
||||||
match out {
|
match out {
|
||||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut handled = false;
|
let mut handled = false;
|
||||||
if let Error::Yaml(ye) = &e {
|
if let Error::Yaml(ye) = &e {
|
||||||
handled = ye.to_string()
|
handled = ye.description()
|
||||||
.starts_with("unknown field `bad_field`");
|
.starts_with("unknown field `bad_field`");
|
||||||
};
|
};
|
||||||
if !handled {
|
if !handled {
|
||||||
@ -854,14 +808,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_layout_punctuation() {
|
fn test_layout_punctuation() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout_key1.yaml"))
|
let out = Layout::from_file(PathBuf::from("tests/layout_key1.yaml"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"].1
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.get_buttons()[0].1
|
.buttons[0].1
|
||||||
.label,
|
.label,
|
||||||
::layout::Label::Text(CString::new("test").unwrap())
|
::layout::Label::Text(CString::new("test").unwrap())
|
||||||
);
|
);
|
||||||
@ -869,14 +823,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_layout_unicode() {
|
fn test_layout_unicode() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout_key2.yaml"))
|
let out = Layout::from_file(PathBuf::from("tests/layout_key2.yaml"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"].1
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.get_buttons()[0].1
|
.buttons[0].1
|
||||||
.label,
|
.label,
|
||||||
::layout::Label::Text(CString::new("test").unwrap())
|
::layout::Label::Text(CString::new("test").unwrap())
|
||||||
);
|
);
|
||||||
@ -885,37 +839,20 @@ mod tests {
|
|||||||
/// Test multiple codepoints
|
/// Test multiple codepoints
|
||||||
#[test]
|
#[test]
|
||||||
fn test_layout_unicode_multi() {
|
fn test_layout_unicode_multi() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout_key3.yaml"))
|
let out = Layout::from_file(PathBuf::from("tests/layout_key3.yaml"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out.views["base"].1
|
out.views["base"].1
|
||||||
.get_rows()[0].1
|
.get_rows()[0].1
|
||||||
.get_buttons()[0].1
|
.buttons[0].1
|
||||||
.state.borrow()
|
.state.borrow()
|
||||||
.keycodes.len(),
|
.keycodes.len(),
|
||||||
2
|
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]
|
#[test]
|
||||||
fn parsing_fallback() {
|
fn parsing_fallback() {
|
||||||
assert!(Layout::from_resource(FALLBACK_LAYOUT_NAME)
|
assert!(Layout::from_resource(FALLBACK_LAYOUT_NAME)
|
||||||
@ -940,26 +877,7 @@ 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]
|
#[test]
|
||||||
fn unicode_keysym() {
|
fn unicode_keysym() {
|
||||||
let keysym = xkb::keysym_from_name(
|
let keysym = xkb::keysym_from_name(
|
||||||
@ -998,7 +916,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_layout_margins() {
|
fn test_layout_margins() {
|
||||||
let out = Layout::from_file(path_from_root("tests/layout_margins.yaml"))
|
let out = Layout::from_file(PathBuf::from("tests/layout_margins.yaml"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.build(ProblemPanic).0
|
.build(ProblemPanic).0
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -1012,35 +930,4 @@ 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"],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,9 +25,8 @@ static const struct zwp_input_method_v2_listener input_method_listener = {
|
|||||||
|
|
||||||
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
||||||
struct zwp_virtual_keyboard_manager_v1 *vkmanager,
|
struct zwp_virtual_keyboard_manager_v1 *vkmanager,
|
||||||
struct vis_manager *vis_manager,
|
|
||||||
struct wl_seat *seat,
|
struct wl_seat *seat,
|
||||||
EekboardContextService *state) {
|
LayoutHolder *state) {
|
||||||
struct zwp_input_method_v2 *im = NULL;
|
struct zwp_input_method_v2 *im = NULL;
|
||||||
if (immanager) {
|
if (immanager) {
|
||||||
im = zwp_input_method_manager_v2_get_input_method(immanager, seat);
|
im = zwp_input_method_manager_v2_get_input_method(immanager, seat);
|
||||||
@ -36,7 +35,7 @@ struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
|||||||
if (vkmanager) {
|
if (vkmanager) {
|
||||||
vk = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkmanager, seat);
|
vk = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkmanager, seat);
|
||||||
}
|
}
|
||||||
return submission_new(im, vk, state, vis_manager);
|
return submission_new(im, vk, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Un-inlined
|
/// Un-inlined
|
||||||
|
|||||||
@ -23,7 +23,7 @@ pub mod c {
|
|||||||
|
|
||||||
use std::os::raw::{c_char, c_void};
|
use std::os::raw::{c_char, c_void};
|
||||||
|
|
||||||
pub use ::ui_manager::c::UIManager;
|
pub use ::submission::c::UIManager;
|
||||||
pub use ::submission::c::StateManager;
|
pub use ::submission::c::StateManager;
|
||||||
|
|
||||||
// The following defined in C
|
// The following defined in C
|
||||||
@ -41,6 +41,8 @@ pub mod c {
|
|||||||
pub fn eek_input_method_delete_surrounding_text(im: *mut InputMethod, before: u32, after: u32);
|
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);
|
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);
|
fn eekboard_context_service_set_hint_purpose(state: *const StateManager, hint: u32, purpose: u32);
|
||||||
|
fn server_context_service_show_keyboard(imservice: *const UIManager);
|
||||||
|
fn server_context_service_hide_keyboard(imservice: *const UIManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
||||||
@ -150,20 +152,21 @@ pub mod c {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if active_changed {
|
if active_changed {
|
||||||
(imservice.active_callback)(imservice.current.active);
|
if imservice.current.active {
|
||||||
let (hint, purpose) = if imservice.current.active {(
|
if let Some(ui) = imservice.ui_manager {
|
||||||
imservice.current.content_hint,
|
unsafe { server_context_service_show_keyboard(ui); }
|
||||||
imservice.current.content_purpose.clone(),
|
}
|
||||||
)} else {(
|
unsafe {
|
||||||
ContentHint::NONE,
|
eekboard_context_service_set_hint_purpose(
|
||||||
ContentPurpose::Normal,
|
imservice.state_manager,
|
||||||
)};
|
imservice.current.content_hint.bits(),
|
||||||
unsafe {
|
imservice.current.content_purpose.clone() as u32,
|
||||||
eekboard_context_service_set_hint_purpose(
|
);
|
||||||
imservice.state_manager,
|
}
|
||||||
hint.bits(),
|
} else {
|
||||||
purpose as u32,
|
if let Some(ui) = imservice.ui_manager {
|
||||||
);
|
unsafe { server_context_service_hide_keyboard(ui); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +184,9 @@ pub mod c {
|
|||||||
// the keyboard is already decommissioned
|
// the keyboard is already decommissioned
|
||||||
imservice.current.active = false;
|
imservice.current.active = false;
|
||||||
|
|
||||||
(imservice.active_callback)(imservice.current.active);
|
if let Some(ui) = imservice.ui_manager {
|
||||||
|
unsafe { server_context_service_hide_keyboard(ui); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: destroy and deallocate
|
// FIXME: destroy and deallocate
|
||||||
@ -334,7 +339,8 @@ pub struct IMService {
|
|||||||
pub im: *mut c::InputMethod,
|
pub im: *mut c::InputMethod,
|
||||||
/// Unowned reference. Be careful, it's shared with C at large
|
/// Unowned reference. Be careful, it's shared with C at large
|
||||||
state_manager: *const c::StateManager,
|
state_manager: *const c::StateManager,
|
||||||
active_callback: Box<dyn Fn(bool)>,
|
/// Unowned reference. Be careful, it's shared with C at large
|
||||||
|
pub ui_manager: Option<*const c::UIManager>,
|
||||||
|
|
||||||
pending: IMProtocolState,
|
pending: IMProtocolState,
|
||||||
current: IMProtocolState, // turn current into an idiomatic representation?
|
current: IMProtocolState, // turn current into an idiomatic representation?
|
||||||
@ -351,13 +357,12 @@ impl IMService {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
im: *mut c::InputMethod,
|
im: *mut c::InputMethod,
|
||||||
state_manager: *const c::StateManager,
|
state_manager: *const c::StateManager,
|
||||||
active_callback: Box<dyn Fn(bool)>,
|
|
||||||
) -> Box<IMService> {
|
) -> Box<IMService> {
|
||||||
// IMService will be referenced to by C,
|
// IMService will be referenced to by C,
|
||||||
// so it needs to stay in the same place in memory via Box
|
// so it needs to stay in the same place in memory via Box
|
||||||
let imservice = Box::new(IMService {
|
let imservice = Box::new(IMService {
|
||||||
im,
|
im,
|
||||||
active_callback,
|
ui_manager: None,
|
||||||
state_manager,
|
state_manager,
|
||||||
pending: IMProtocolState::default(),
|
pending: IMProtocolState::default(),
|
||||||
current: IMProtocolState::default(),
|
current: IMProtocolState::default(),
|
||||||
@ -372,7 +377,7 @@ impl IMService {
|
|||||||
}
|
}
|
||||||
imservice
|
imservice
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit_string(&self, text: &CString) -> Result<(), SubmitError> {
|
pub fn commit_string(&self, text: &CString) -> Result<(), SubmitError> {
|
||||||
match self.current.active {
|
match self.current.active {
|
||||||
true => {
|
true => {
|
||||||
|
|||||||
254
src/keyboard.rs
254
src/keyboard.rs
@ -5,13 +5,11 @@ use std::cell::RefCell;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
|
||||||
use std::ptr;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
use ::action::Action;
|
use ::action::Action;
|
||||||
use ::util;
|
use ::logging;
|
||||||
|
|
||||||
// Traits
|
// Traits
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -23,12 +21,7 @@ pub enum PressType {
|
|||||||
Pressed = 1,
|
Pressed = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The extended, unambiguous layout-keycode
|
pub type KeyCode = u32;
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct KeyCode {
|
|
||||||
pub code: u32,
|
|
||||||
pub keymap_idx: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags!{
|
bitflags!{
|
||||||
/// Map to `virtual_keyboard.modifiers` modifiers values
|
/// Map to `virtual_keyboard.modifiers` modifiers values
|
||||||
@ -50,7 +43,7 @@ bitflags!{
|
|||||||
|
|
||||||
/// When the submitted actions of keys need to be tracked,
|
/// When the submitted actions of keys need to be tracked,
|
||||||
/// they need a stable, comparable ID
|
/// they need a stable, comparable ID
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct KeyStateId(*const KeyState);
|
pub struct KeyStateId(*const KeyState);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -87,10 +80,10 @@ impl KeyState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sorts an iterator by converting it to a Vector and back
|
/// Sorts an iterator by converting it to a Vector and back
|
||||||
fn sorted<'a, I: Iterator<Item=String>>(
|
fn sorted<'a, I: Iterator<Item=&'a str>>(
|
||||||
iter: I
|
iter: I
|
||||||
) -> impl Iterator<Item=String> {
|
) -> impl Iterator<Item=&'a str> {
|
||||||
let mut v: Vec<String> = iter.collect();
|
let mut v: Vec<&'a str> = iter.collect();
|
||||||
v.sort();
|
v.sort();
|
||||||
v.into_iter()
|
v.into_iter()
|
||||||
}
|
}
|
||||||
@ -98,17 +91,15 @@ fn sorted<'a, I: Iterator<Item=String>>(
|
|||||||
/// Generates a mapping where each key gets a keycode, starting from ~~8~~
|
/// Generates a mapping where each key gets a keycode, starting from ~~8~~
|
||||||
/// HACK: starting from 9, because 8 results in keycode 0,
|
/// HACK: starting from 9, because 8 results in keycode 0,
|
||||||
/// which the compositor likes to discard
|
/// which the compositor likes to discard
|
||||||
pub fn generate_keycodes<'a, C: IntoIterator<Item=String>>(
|
pub fn generate_keycodes<'a, C: IntoIterator<Item=&'a str>>(
|
||||||
key_names: C,
|
key_names: C
|
||||||
) -> HashMap<String, KeyCode> {
|
) -> HashMap<String, u32> {
|
||||||
|
let special_keysyms = ["BackSpace", "Return"].iter().map(|&s| s);
|
||||||
HashMap::from_iter(
|
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())
|
sorted(key_names.into_iter().chain(special_keysyms))
|
||||||
.zip(util::cycle_count(9..255))
|
.map(|name| String::from(name))
|
||||||
.map(|(name, (code, keymap_idx))| (
|
.zip(9..)
|
||||||
String::from(name),
|
|
||||||
KeyCode { code, keymap_idx },
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,54 +124,12 @@ impl From<io::Error> for FormattingError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
/// Generates a de-facto single level keymap.
|
||||||
/// Key codes must not repeat and must remain between 9 and 255.
|
// TODO: don't rely on keys and their order,
|
||||||
fn generate_keymap(
|
// but rather on what keysyms and keycodes are in use.
|
||||||
symbolmap: &SingleKeyMap,
|
// Iterating actions makes it hard to deduplicate keysyms.
|
||||||
|
pub fn generate_keymap(
|
||||||
|
keystates: &HashMap::<String, KeyState>
|
||||||
) -> Result<String, FormattingError> {
|
) -> Result<String, FormattingError> {
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -191,80 +140,86 @@ fn generate_keymap(
|
|||||||
minimum = 8;
|
minimum = 8;
|
||||||
maximum = 255;"
|
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();
|
|
||||||
|
|
||||||
// Xorg can only consume up to 255 keys, so this may not work in Xwayland.
|
for (name, state) in keystates.iter() {
|
||||||
// Two possible solutions:
|
match &state.action {
|
||||||
// - use levels to cram multiple characters into one key
|
Action::Submit { text: _, keys } => {
|
||||||
// - swap layouts on key presses
|
if let 0 = keys.len() {
|
||||||
for (_name, keycode) in &pairs {
|
log_print!(
|
||||||
write!(
|
logging::Level::Warning,
|
||||||
buf,
|
"Key {} has no keysyms", name,
|
||||||
"
|
);
|
||||||
<I{}> = {0};",
|
};
|
||||||
keycode,
|
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
|
||||||
)?;
|
write!(
|
||||||
|
buf,
|
||||||
|
"
|
||||||
|
<{}> = {};",
|
||||||
|
named_keysym.0,
|
||||||
|
keycode,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Action::Erase => {
|
||||||
|
let mut keycodes = state.keycodes.iter();
|
||||||
|
write!(
|
||||||
|
buf,
|
||||||
|
"
|
||||||
|
<BackSpace> = {};",
|
||||||
|
keycodes.next().expect("Erase key has no keycode"),
|
||||||
|
)?;
|
||||||
|
if let Some(_) = keycodes.next() {
|
||||||
|
log_print!(
|
||||||
|
logging::Level::Bug,
|
||||||
|
"Erase key has multiple keycodes",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
buf,
|
buf,
|
||||||
"
|
"
|
||||||
indicator 1 = \"Caps Lock\"; // Xwayland won't accept without it.
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
xkb_symbols \"squeekboard\" {{
|
xkb_symbols \"squeekboard\" {{
|
||||||
"
|
|
||||||
|
name[Group1] = \"Letters\";
|
||||||
|
name[Group2] = \"Numbers/Symbols\";
|
||||||
|
|
||||||
|
key <BackSpace> {{ [ BackSpace ] }};"
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (name, keycode) in pairs {
|
for (name, state) in keystates.iter() {
|
||||||
write!(
|
if let Action::Submit { text: _, keys } = &state.action {
|
||||||
buf,
|
for keysym in keys.iter() {
|
||||||
"
|
write!(
|
||||||
key <I{}> {{ [ {} ] }};",
|
buf,
|
||||||
keycode,
|
"
|
||||||
name,
|
key <{}> {{ [ {0} ] }};",
|
||||||
)?;
|
keysym.0,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
buf,
|
buf,
|
||||||
"
|
"
|
||||||
}};
|
}};
|
||||||
|
|
||||||
xkb_types \"squeekboard\" {{
|
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\" {{
|
xkb_compatibility \"squeekboard\" {{
|
||||||
// Needed for Xwayland again.
|
|
||||||
interpret Any+AnyOf(all) {{
|
|
||||||
action= SetMods(modifiers=modMapMods,clearLocks);
|
|
||||||
}};
|
|
||||||
}};
|
}};
|
||||||
}};"
|
}};"
|
||||||
)?;
|
)?;
|
||||||
@ -279,16 +234,23 @@ mod tests {
|
|||||||
|
|
||||||
use xkbcommon::xkb;
|
use xkbcommon::xkb;
|
||||||
|
|
||||||
|
use ::action::KeySym;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keymap_single_resolve() {
|
fn test_keymap_multi() {
|
||||||
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(&key_map).unwrap();
|
|
||||||
|
|
||||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
|
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),
|
||||||
|
pressed: PressType::Released,
|
||||||
|
},
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
let keymap = xkb::Keymap::new_from_string(
|
let keymap = xkb::Keymap::new_from_string(
|
||||||
&context,
|
&context,
|
||||||
keymap_str.clone(),
|
keymap_str.clone(),
|
||||||
@ -301,36 +263,4 @@ mod tests {
|
|||||||
assert_eq!(state.key_get_one_sym(9), xkb::KEY_a);
|
assert_eq!(state.key_get_one_sym(9), xkb::KEY_a);
|
||||||
assert_eq!(state.key_get_one_sym(10), xkb::KEY_c);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ struct transformation squeek_layout_calculate_transformation(
|
|||||||
double allocation_width, double allocation_size);
|
double allocation_width, double allocation_size);
|
||||||
|
|
||||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
|
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 *);
|
enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *);
|
||||||
void squeek_layout_free(struct squeek_layout*);
|
void squeek_layout_free(struct squeek_layout*);
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ void squeek_layout_release(struct squeek_layout *layout,
|
|||||||
struct submission *submission,
|
struct submission *submission,
|
||||||
struct transformation widget_to_layout,
|
struct transformation widget_to_layout,
|
||||||
uint32_t timestamp,
|
uint32_t timestamp,
|
||||||
EekboardContextService *manager,
|
LayoutHolder *manager,
|
||||||
EekGtkKeyboard *ui_keyboard);
|
EekGtkKeyboard *ui_keyboard);
|
||||||
void squeek_layout_release_all_only(struct squeek_layout *layout,
|
void squeek_layout_release_all_only(struct squeek_layout *layout,
|
||||||
struct submission *submission,
|
struct submission *submission,
|
||||||
@ -60,7 +61,7 @@ void squeek_layout_drag(struct squeek_layout *layout,
|
|||||||
struct submission *submission,
|
struct submission *submission,
|
||||||
double x_widget, double y_widget,
|
double x_widget, double y_widget,
|
||||||
struct transformation widget_to_layout,
|
struct transformation widget_to_layout,
|
||||||
uint32_t timestamp, EekboardContextService *manager,
|
uint32_t timestamp, LayoutHolder *manager,
|
||||||
EekGtkKeyboard *ui_keyboard);
|
EekGtkKeyboard *ui_keyboard);
|
||||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission);
|
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);
|
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
|
||||||
|
|||||||
278
src/layout.rs
278
src/layout.rs
@ -52,14 +52,6 @@ pub mod c {
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
|
pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" {
|
|
||||||
#[allow(improper_ctypes)]
|
|
||||||
pub fn eek_gtk_keyboard_emit_feedback(
|
|
||||||
keyboard: EekGtkKeyboard,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Defined in eek-types.h
|
/// Defined in eek-types.h
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -107,8 +99,8 @@ pub mod c {
|
|||||||
|
|
||||||
impl Bounds {
|
impl Bounds {
|
||||||
pub fn contains(&self, point: &Point) -> bool {
|
pub fn contains(&self, point: &Point) -> bool {
|
||||||
point.x > self.x && point.x < self.x + self.width
|
(point.x > self.x && point.x < self.x + self.width
|
||||||
&& point.y > self.y && point.y < self.y + self.height
|
&& point.y > self.y && point.y < self.y + self.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +228,13 @@ pub mod c {
|
|||||||
height: allocation_height,
|
height: allocation_height,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C"
|
||||||
|
fn squeek_layout_get_keymap(layout: *const Layout) -> *const c_char {
|
||||||
|
let layout = unsafe { &*layout };
|
||||||
|
layout.keymap_str.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
@ -342,9 +341,6 @@ pub mod c {
|
|||||||
);
|
);
|
||||||
// maybe TODO: draw on the display buffer here
|
// maybe TODO: draw on the display buffer here
|
||||||
drawing::queue_redraw(ui_keyboard);
|
drawing::queue_redraw(ui_keyboard);
|
||||||
unsafe {
|
|
||||||
eek_gtk_keyboard_emit_feedback(ui_keyboard);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,9 +404,6 @@ pub mod c {
|
|||||||
&state,
|
&state,
|
||||||
);
|
);
|
||||||
// maybe TODO: draw on the display buffer here
|
// maybe TODO: draw on the display buffer here
|
||||||
unsafe {
|
|
||||||
eek_gtk_keyboard_emit_feedback(ui_keyboard);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for wrapped_key in pressed {
|
for wrapped_key in pressed {
|
||||||
@ -486,63 +479,38 @@ pub struct Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The graphical representation of a row of buttons
|
/// The graphical representation of a row of buttons
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Row {
|
pub struct Row {
|
||||||
/// Buttons together with their offset from the left relative to the row.
|
/// Buttons together with their offset from the left
|
||||||
/// ie. the first button always start at 0.
|
pub buttons: Vec<(f64, Box<Button>)>,
|
||||||
buttons: Vec<(f64, Box<Button>)>,
|
|
||||||
|
|
||||||
/// Total size of the row
|
|
||||||
size: Size,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Row {
|
impl Row {
|
||||||
pub fn new(buttons: Vec<(f64, Box<Button>)>) -> Row {
|
pub fn get_height(&self) -> f64 {
|
||||||
// Make sure buttons are sorted by offset.
|
find_max_double(
|
||||||
debug_assert!({
|
self.buttons.iter(),
|
||||||
let mut sorted = buttons.clone();
|
|
||||||
sorted.sort_by(|(f1, _), (f2, _)| f1.partial_cmp(f2).unwrap());
|
|
||||||
|
|
||||||
sorted.iter().map(|(f, _)| *f).collect::<Vec<_>>()
|
|
||||||
== buttons.iter().map(|(f, _)| *f).collect::<Vec<_>>()
|
|
||||||
});
|
|
||||||
|
|
||||||
let width = buttons.iter().next_back()
|
|
||||||
.map(|(x_offset, button)| button.size.width + x_offset)
|
|
||||||
.unwrap_or(0.0);
|
|
||||||
|
|
||||||
let height = find_max_double(
|
|
||||||
buttons.iter(),
|
|
||||||
|(_offset, button)| button.size.height,
|
|(_offset, button)| button.size.height,
|
||||||
);
|
)
|
||||||
|
|
||||||
Row { buttons, size: Size { width, height } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size(&self) -> Size {
|
fn get_width(&self) -> f64 {
|
||||||
self.size.clone()
|
self.buttons.iter().next_back()
|
||||||
}
|
.map(|(x_offset, button)| button.size.width + x_offset)
|
||||||
|
.unwrap_or(0.0)
|
||||||
pub fn get_buttons(&self) -> &Vec<(f64, Box<Button>)> {
|
|
||||||
&self.buttons
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the first button that covers the specified point
|
/// Finds the first button that covers the specified point
|
||||||
/// relative to row's position's origin
|
/// relative to row's position's origin
|
||||||
fn find_button_by_position(&self, x: f64) -> &(f64, Box<Button>)
|
fn find_button_by_position(&self, point: c::Point)
|
||||||
|
-> Option<(f64, &Box<Button>)>
|
||||||
{
|
{
|
||||||
// Buttons are sorted so we can use a binary search to find the clicked
|
self.buttons.iter().find(|(x_offset, button)| {
|
||||||
// button. Note this doesn't check whether the point is actually within
|
c::Bounds {
|
||||||
// a button. This is on purpose as we want a click past the left edge of
|
x: *x_offset, y: 0.0,
|
||||||
// the left-most button to register as a click.
|
width: button.size.width,
|
||||||
let result = self.buttons.binary_search_by(
|
height: button.size.height,
|
||||||
|&(f, _)| f.partial_cmp(&x).unwrap()
|
}.contains(&point)
|
||||||
);
|
})
|
||||||
|
.map(|(x_offset, button)| (*x_offset, button))
|
||||||
let index = result.unwrap_or_else(|r| r);
|
|
||||||
let index = if index > 0 { index - 1 } else { 0 };
|
|
||||||
|
|
||||||
&self.buttons[index]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,85 +521,56 @@ pub struct Spacing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct View {
|
pub struct View {
|
||||||
/// Rows together with their offsets from the top left
|
/// Rows together with their offsets from the top
|
||||||
rows: Vec<(c::Point, Row)>,
|
rows: Vec<(f64, Row)>,
|
||||||
|
|
||||||
/// Total size of the view
|
|
||||||
size: Size,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
pub fn new(rows: Vec<(f64, Row)>) -> View {
|
pub fn new(rows: Vec<(f64, Row)>) -> View {
|
||||||
// Make sure rows are sorted by offset.
|
View { rows }
|
||||||
debug_assert!({
|
|
||||||
let mut sorted = rows.clone();
|
|
||||||
sorted.sort_by(|(f1, _), (f2, _)| f1.partial_cmp(f2).unwrap());
|
|
||||||
|
|
||||||
sorted.iter().map(|(f, _)| *f).collect::<Vec<_>>()
|
|
||||||
== rows.iter().map(|(f, _)| *f).collect::<Vec<_>>()
|
|
||||||
});
|
|
||||||
|
|
||||||
// No need to call `get_rows()`,
|
|
||||||
// as the biggest row is the most far reaching in both directions
|
|
||||||
// because they are all centered.
|
|
||||||
let width = find_max_double(rows.iter(), |(_offset, row)| row.size.width);
|
|
||||||
|
|
||||||
let height = rows.iter().next_back()
|
|
||||||
.map(|(y_offset, row)| row.size.height + y_offset)
|
|
||||||
.unwrap_or(0.0);
|
|
||||||
|
|
||||||
// Center the rows
|
|
||||||
let rows = rows.into_iter().map(|(y_offset, row)| {(
|
|
||||||
c::Point {
|
|
||||||
x: (width - row.size.width) / 2.0,
|
|
||||||
y: y_offset,
|
|
||||||
},
|
|
||||||
row,
|
|
||||||
)}).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
View { rows, size: Size { width, height } }
|
|
||||||
}
|
}
|
||||||
/// Finds the first button that covers the specified point
|
/// Finds the first button that covers the specified point
|
||||||
/// relative to view's position's origin
|
/// relative to view's position's origin
|
||||||
fn find_button_by_position(&self, point: c::Point)
|
fn find_button_by_position(&self, point: c::Point)
|
||||||
-> Option<ButtonPlace>
|
-> Option<ButtonPlace>
|
||||||
{
|
{
|
||||||
// Only test bounds of the view here, letting rows/column search extend
|
self.get_rows().iter().find_map(|(row_offset, row)| {
|
||||||
// to the edges of these bounds.
|
// make point relative to the inside of the row
|
||||||
let bounds = c::Bounds {
|
row.find_button_by_position({
|
||||||
x: 0.0,
|
c::Point { x: point.x, y: point.y } - row_offset
|
||||||
y: 0.0,
|
}).map(|(button_x_offset, button)| ButtonPlace {
|
||||||
width: self.size.width,
|
button,
|
||||||
height: self.size.height,
|
offset: row_offset + c::Point {
|
||||||
};
|
x: button_x_offset,
|
||||||
if !bounds.contains(&point) {
|
y: 0.0,
|
||||||
return None;
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
// Rows are sorted so we can use a binary search to find the row.
|
|
||||||
let result = self.rows.binary_search_by(
|
|
||||||
|(f, _)| f.y.partial_cmp(&point.y).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
let index = result.unwrap_or_else(|r| r);
|
|
||||||
let index = if index > 0 { index - 1 } else { 0 };
|
|
||||||
|
|
||||||
let row = &self.rows[index];
|
|
||||||
let button = row.1.find_button_by_position(point.x - row.0.x);
|
|
||||||
|
|
||||||
Some(ButtonPlace {
|
|
||||||
button: &button.1,
|
|
||||||
offset: &row.0 + c::Point { x: button.0, y: 0.0 },
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size(&self) -> Size {
|
pub fn get_width(&self) -> f64 {
|
||||||
self.size.clone()
|
// No need to call `get_rows()`,
|
||||||
|
// as the biggest row is the most far reaching in both directions
|
||||||
|
// because they are all centered.
|
||||||
|
find_max_double(self.rows.iter(), |(_offset, row)| row.get_width())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_height(&self) -> f64 {
|
||||||
|
self.rows.iter().next_back()
|
||||||
|
.map(|(y_offset, row)| row.get_height() + y_offset)
|
||||||
|
.unwrap_or(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns positioned rows, with appropriate x offsets (centered)
|
/// Returns positioned rows, with appropriate x offsets (centered)
|
||||||
pub fn get_rows(&self) -> &Vec<(c::Point, Row)> {
|
pub fn get_rows(&self) -> Vec<(c::Point, &Row)> {
|
||||||
&self.rows
|
let available_width = self.get_width();
|
||||||
|
self.rows.iter().map(|(y_offset, row)| {(
|
||||||
|
c::Point {
|
||||||
|
x: (available_width - row.get_width()) / 2.0,
|
||||||
|
y: *y_offset,
|
||||||
|
},
|
||||||
|
row,
|
||||||
|
)}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a size which contains all the views
|
/// Returns a size which contains all the views
|
||||||
@ -640,11 +579,11 @@ impl View {
|
|||||||
Size {
|
Size {
|
||||||
height: find_max_double(
|
height: find_max_double(
|
||||||
views.iter(),
|
views.iter(),
|
||||||
|view| view.size.height,
|
|view| view.get_height(),
|
||||||
),
|
),
|
||||||
width: find_max_double(
|
width: find_max_double(
|
||||||
views.iter(),
|
views.iter(),
|
||||||
|view| view.size.width,
|
|view| view.get_width(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,8 +618,8 @@ pub struct Layout {
|
|||||||
pub views: HashMap<String, (c::Point, View)>,
|
pub views: HashMap<String, (c::Point, View)>,
|
||||||
|
|
||||||
// Non-UI stuff
|
// Non-UI stuff
|
||||||
/// xkb keymaps applicable to the contained keys. Unchangeable
|
/// xkb keymap applicable to the contained keys. Unchangeable
|
||||||
pub keymaps: Vec<CString>,
|
pub keymap_str: CString,
|
||||||
// Changeable state
|
// Changeable state
|
||||||
// a Vec would be enough, but who cares, this will be small & fast enough
|
// a Vec would be enough, but who cares, this will be small & fast enough
|
||||||
// TODO: turn those into per-input point *_buttons to track dragging.
|
// TODO: turn those into per-input point *_buttons to track dragging.
|
||||||
@ -696,7 +635,7 @@ pub struct Layout {
|
|||||||
pub struct LayoutData {
|
pub struct LayoutData {
|
||||||
/// Point is the offset within layout
|
/// Point is the offset within layout
|
||||||
pub views: HashMap<String, (c::Point, View)>,
|
pub views: HashMap<String, (c::Point, View)>,
|
||||||
pub keymaps: Vec<CString>,
|
pub keymap_str: CString,
|
||||||
pub margins: Margins,
|
pub margins: Margins,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,7 +658,7 @@ impl Layout {
|
|||||||
kind,
|
kind,
|
||||||
current_view: "base".to_owned(),
|
current_view: "base".to_owned(),
|
||||||
views: data.views,
|
views: data.views,
|
||||||
keymaps: data.keymaps,
|
keymap_str: data.keymap_str,
|
||||||
pressed_keys: HashSet::new(),
|
pressed_keys: HashSet::new(),
|
||||||
margins: data.margins,
|
margins: data.margins,
|
||||||
}
|
}
|
||||||
@ -792,7 +731,7 @@ impl Layout {
|
|||||||
where F: FnMut(c::Point, &Box<Button>)
|
where F: FnMut(c::Point, &Box<Button>)
|
||||||
{
|
{
|
||||||
let (view_offset, view) = self.get_current_view_position();
|
let (view_offset, view) = self.get_current_view_position();
|
||||||
for (row_offset, row) in view.get_rows() {
|
for (row_offset, row) in &view.get_rows() {
|
||||||
for (x_offset, button) in &row.buttons {
|
for (x_offset, button) in &row.buttons {
|
||||||
let offset = view_offset
|
let offset = view_offset
|
||||||
+ row_offset.clone()
|
+ row_offset.clone()
|
||||||
@ -805,7 +744,7 @@ impl Layout {
|
|||||||
pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
|
pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let view = self.get_current_view();
|
let view = self.get_current_view();
|
||||||
for (_, row) in view.get_rows() {
|
for (_, row) in &view.get_rows() {
|
||||||
for (_, button) in &row.buttons {
|
for (_, button) in &row.buttons {
|
||||||
let locked = {
|
let locked = {
|
||||||
let state = RefCell::borrow(&button.state).clone();
|
let state = RefCell::borrow(&button.state).clone();
|
||||||
@ -867,9 +806,13 @@ mod procedures {
|
|||||||
let button = make_button_with_state("1".into(), state);
|
let button = make_button_with_state("1".into(), state);
|
||||||
let button_ptr = as_ptr(&button);
|
let button_ptr = as_ptr(&button);
|
||||||
|
|
||||||
let row = Row::new(vec!((0.1, button)));
|
let row = Row {
|
||||||
|
buttons: vec!((0.1, button)),
|
||||||
|
};
|
||||||
|
|
||||||
let view = View::new(vec!((1.2, row)));
|
let view = View {
|
||||||
|
rows: vec!((1.2, row)),
|
||||||
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_key_places(&view, &state_clone.clone()).into_iter()
|
find_key_places(&view, &state_clone.clone()).into_iter()
|
||||||
@ -880,7 +823,9 @@ mod procedures {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let view = View::new(vec![]);
|
let view = View {
|
||||||
|
rows: Vec::new(),
|
||||||
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_key_places(&view, &state_clone.clone()).is_empty(),
|
find_key_places(&view, &state_clone.clone()).is_empty(),
|
||||||
true
|
true
|
||||||
@ -1123,56 +1068,37 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_centering() {
|
fn check_centering() {
|
||||||
// A B
|
// foo
|
||||||
// ---bar---
|
// ---bar---
|
||||||
let view = View::new(vec![
|
let view = View::new(vec![
|
||||||
(
|
(
|
||||||
0.0,
|
0.0,
|
||||||
Row::new(vec![
|
Row {
|
||||||
(
|
buttons: vec![(
|
||||||
0.0,
|
0.0,
|
||||||
Box::new(Button {
|
Box::new(Button {
|
||||||
size: Size { width: 5.0, height: 10.0 },
|
size: Size { width: 10.0, height: 10.0 },
|
||||||
..*make_button_with_state("A".into(), make_state())
|
..*make_button_with_state("foo".into(), make_state())
|
||||||
}),
|
}),
|
||||||
),
|
)]
|
||||||
(
|
},
|
||||||
5.0,
|
|
||||||
Box::new(Button {
|
|
||||||
size: Size { width: 5.0, height: 10.0 },
|
|
||||||
..*make_button_with_state("B".into(), make_state())
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
10.0,
|
10.0,
|
||||||
Row::new(vec![
|
Row {
|
||||||
(
|
buttons: vec![(
|
||||||
0.0,
|
0.0,
|
||||||
Box::new(Button {
|
Box::new(Button {
|
||||||
size: Size { width: 30.0, height: 10.0 },
|
size: Size { width: 30.0, height: 10.0 },
|
||||||
..*make_button_with_state("bar".into(), make_state())
|
..*make_button_with_state("bar".into(), make_state())
|
||||||
}),
|
}),
|
||||||
),
|
)]
|
||||||
]),
|
},
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
assert!(
|
assert!(
|
||||||
view.find_button_by_position(c::Point { x: 5.0, y: 5.0 })
|
view.find_button_by_position(c::Point { x: 5.0, y: 5.0 })
|
||||||
.unwrap().button.name.to_str().unwrap() == "A"
|
.is_none()
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
view.find_button_by_position(c::Point { x: 14.99, y: 5.0 })
|
|
||||||
.unwrap().button.name.to_str().unwrap() == "A"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
view.find_button_by_position(c::Point { x: 15.01, y: 5.0 })
|
|
||||||
.unwrap().button.name.to_str().unwrap() == "B"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
view.find_button_by_position(c::Point { x: 25.0, y: 5.0 })
|
|
||||||
.unwrap().button.name.to_str().unwrap() == "B"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,18 +1108,20 @@ mod test {
|
|||||||
let view = View::new(vec![
|
let view = View::new(vec![
|
||||||
(
|
(
|
||||||
0.0,
|
0.0,
|
||||||
Row::new(vec![(
|
Row {
|
||||||
0.0,
|
buttons: vec![(
|
||||||
Box::new(Button {
|
0.0,
|
||||||
size: Size { width: 1.0, height: 1.0 },
|
Box::new(Button {
|
||||||
..*make_button_with_state("foo".into(), make_state())
|
size: Size { width: 1.0, height: 1.0 },
|
||||||
}),
|
..*make_button_with_state("foo".into(), make_state())
|
||||||
)]),
|
}),
|
||||||
|
)]
|
||||||
|
},
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
let layout = Layout {
|
let layout = Layout {
|
||||||
current_view: String::new(),
|
current_view: String::new(),
|
||||||
keymaps: Vec::new(),
|
keymap_str: CString::new("").unwrap(),
|
||||||
kind: ArrangementKind::Base,
|
kind: ArrangementKind::Base,
|
||||||
pressed_keys: HashSet::new(),
|
pressed_keys: HashSet::new(),
|
||||||
// Lots of bottom margin
|
// Lots of bottom margin
|
||||||
|
|||||||
@ -31,16 +31,22 @@ pub enum Error {
|
|||||||
|
|
||||||
impl ::std::fmt::Display for Error {
|
impl ::std::fmt::Display for Error {
|
||||||
fn fmt(&self, out: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, out: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
out.write_str(match self {
|
use ::std::error::Error;
|
||||||
|
out.write_str(self.description())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::error::Error for Error {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match self {
|
||||||
&Error::NotWellFormed => "Language tag is not well-formed.",
|
&Error::NotWellFormed => "Language tag is not well-formed.",
|
||||||
// this is exception: here we do want exhaustive match so we don't publish version with
|
// this is exception: here we do want exhaustive match so we don't publish version with
|
||||||
// missing descriptions by mistake.
|
// missing descriptions by mistake.
|
||||||
&Error::__NonExhaustive => panic!("Placeholder error must not be instantiated!"),
|
&Error::__NonExhaustive => panic!("Placeholder error must not be instantiated!"),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Convenience Result alias.
|
/// Convenience Result alias.
|
||||||
type Result<T> = ::std::result::Result<T, Error>;
|
type Result<T> = ::std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,8 @@ sources = [
|
|||||||
config_h,
|
config_h,
|
||||||
'dbus.c',
|
'dbus.c',
|
||||||
'imservice.c',
|
'imservice.c',
|
||||||
'popover.c',
|
|
||||||
'server-context-service.c',
|
'server-context-service.c',
|
||||||
|
'ui_manager.c',
|
||||||
'wayland.c',
|
'wayland.c',
|
||||||
'../eek/eek.c',
|
'../eek/eek.c',
|
||||||
'../eek/eek-element.c',
|
'../eek/eek-element.c',
|
||||||
@ -37,10 +37,9 @@ cc = meson.get_compiler('c')
|
|||||||
deps = [
|
deps = [
|
||||||
# dependency('glib-2.0', version: '>=2.26.0'),
|
# dependency('glib-2.0', version: '>=2.26.0'),
|
||||||
dependency('gio-2.0', version: '>=2.26.0'),
|
dependency('gio-2.0', version: '>=2.26.0'),
|
||||||
dependency('gio-unix-2.0'),
|
|
||||||
dependency('gnome-desktop-3.0', version: '>=3.0'),
|
dependency('gnome-desktop-3.0', version: '>=3.0'),
|
||||||
dependency('gtk+-3.0', version: '>=3.0'),
|
dependency('gtk+-3.0', version: '>=3.0'),
|
||||||
dependency('libfeedback-0.0'),
|
dependency('libcroco-0.6'),
|
||||||
dependency('wayland-client', version: '>=1.14'),
|
dependency('wayland-client', version: '>=1.14'),
|
||||||
dependency('xkbcommon'),
|
dependency('xkbcommon'),
|
||||||
cc.find_library('m'),
|
cc.find_library('m'),
|
||||||
@ -57,8 +56,7 @@ rslibs = custom_target(
|
|||||||
output: ['librs.a'],
|
output: ['librs.a'],
|
||||||
install: false,
|
install: false,
|
||||||
console: true,
|
console: true,
|
||||||
command: [cargo_build] + ['@OUTPUT@', '--lib'] + cargo_build_flags,
|
command: [cargo_build] + cargo_build_flags + ['@OUTPUT@', '--lib']
|
||||||
depends: cargo_toml,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
build_rstests = custom_target(
|
build_rstests = custom_target(
|
||||||
@ -72,18 +70,17 @@ build_rstests = custom_target(
|
|||||||
output: ['src'],
|
output: ['src'],
|
||||||
install: false,
|
install: false,
|
||||||
console: true,
|
console: true,
|
||||||
command: [cargo_script, 'test', '--no-run'] + cargo_build_flags,
|
command: [cargo_script, 'test', '--no-run'],
|
||||||
depends: [rslibs, cargo_toml], # no point building tests if the code itself fails
|
depends: rslibs, # no point building tests if the code itself fails
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'rstest',
|
'rstest',
|
||||||
cargo_script,
|
cargo_script,
|
||||||
args: ['test'] + cargo_build_flags,
|
args: ['test'],
|
||||||
env: ['SOURCE_DIR=' + meson.source_root()],
|
|
||||||
# this is a whole Carg-based test suite, let it run for a while
|
# this is a whole Carg-based test suite, let it run for a while
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
depends: [build_rstests, cargo_toml],
|
depends: build_rstests,
|
||||||
)
|
)
|
||||||
|
|
||||||
libsqueekboard = static_library('libsqueekboard',
|
libsqueekboard = static_library('libsqueekboard',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ struct squeek_output_handle {
|
|||||||
struct squeek_outputs *outputs;
|
struct squeek_outputs *outputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct squeek_outputs *squeek_outputs_new(void);
|
struct squeek_outputs *squeek_outputs_new();
|
||||||
void squeek_outputs_free(struct squeek_outputs*);
|
void squeek_outputs_free(struct squeek_outputs*);
|
||||||
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output);
|
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output);
|
||||||
struct squeek_output_handle squeek_outputs_get_current(struct squeek_outputs*);
|
struct squeek_output_handle squeek_outputs_get_current(struct squeek_outputs*);
|
||||||
|
|||||||
152
src/outputs.rs
152
src/outputs.rs
@ -1,5 +1,10 @@
|
|||||||
|
/* Copyright (C) 2019-2020 Purism SPC
|
||||||
|
* SPDX-License-Identifier: GPL-3.0+
|
||||||
|
*/
|
||||||
|
|
||||||
/*! Managing Wayland outputs */
|
/*! Managing Wayland outputs */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use ::logging;
|
use ::logging;
|
||||||
|
|
||||||
@ -17,7 +22,7 @@ pub mod c {
|
|||||||
// Defined in C
|
// Defined in C
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy, Hash)]
|
||||||
pub struct WlOutput(*const c_void);
|
pub struct WlOutput(*const c_void);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -63,7 +68,7 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Map to `wl_output.transform` values
|
/// Map to `wl_output.transform` values
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum Transform {
|
pub enum Transform {
|
||||||
Normal = 0,
|
Normal = 0,
|
||||||
Rotated90 = 1,
|
Rotated90 = 1,
|
||||||
@ -103,7 +108,7 @@ pub mod c {
|
|||||||
) -> i32;
|
) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
type COutputs = ::util::c::Wrapped<Outputs>;
|
pub type COutputs = ::util::c::Wrapped<Outputs>;
|
||||||
|
|
||||||
/// A stable reference to an output.
|
/// A stable reference to an output.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -121,6 +126,10 @@ pub mod c {
|
|||||||
let outputs = outputs.borrow();
|
let outputs = outputs.borrow();
|
||||||
find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone())
|
find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_id(&self) -> OutputId {
|
||||||
|
OutputId { wl_output: self.wl_output }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined in Rust
|
// Defined in Rust
|
||||||
@ -129,7 +138,7 @@ pub mod c {
|
|||||||
outputs: COutputs,
|
outputs: COutputs,
|
||||||
wl_output: WlOutput,
|
wl_output: WlOutput,
|
||||||
_x: i32, _y: i32,
|
_x: i32, _y: i32,
|
||||||
_phys_width: i32, _phys_height: i32,
|
phys_width: i32, phys_height: i32,
|
||||||
_subpixel: i32,
|
_subpixel: i32,
|
||||||
_make: *const c_char, _model: *const c_char,
|
_make: *const c_char, _model: *const c_char,
|
||||||
transform: i32,
|
transform: i32,
|
||||||
@ -145,8 +154,23 @@ pub mod c {
|
|||||||
let output_state: Option<&mut OutputState>
|
let output_state: Option<&mut OutputState>
|
||||||
= find_output_mut(&mut collection, wl_output)
|
= find_output_mut(&mut collection, wl_output)
|
||||||
.map(|o| &mut o.pending);
|
.map(|o| &mut o.pending);
|
||||||
|
|
||||||
match output_state {
|
match output_state {
|
||||||
Some(state) => { state.transform = Some(transform) },
|
Some(state) => {
|
||||||
|
state.transform = Some(transform);
|
||||||
|
state.phys_size = {
|
||||||
|
if (phys_width > 0) & (phys_height > 0) {
|
||||||
|
Some(SizeMM { width: phys_width, height: phys_height })
|
||||||
|
} else {
|
||||||
|
log_print!(
|
||||||
|
logging::Level::Surprise,
|
||||||
|
"Impossible physical dimensions: {}mm × {}mm",
|
||||||
|
phys_width, phys_height,
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
None => log_print!(
|
None => log_print!(
|
||||||
logging::Level::Warning,
|
logging::Level::Warning,
|
||||||
"Got geometry on unknown output",
|
"Got geometry on unknown output",
|
||||||
@ -187,19 +211,27 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern fn outputs_handle_done(
|
extern fn outputs_handle_done(
|
||||||
outputs: COutputs,
|
outputs_raw: COutputs,
|
||||||
wl_output: WlOutput,
|
wl_output: WlOutput,
|
||||||
) {
|
) {
|
||||||
let outputs = outputs.clone_ref();
|
let outputs = outputs_raw.clone_ref();
|
||||||
let mut collection = outputs.borrow_mut();
|
{
|
||||||
let output = find_output_mut(&mut collection, wl_output);
|
let mut collection = RefCell::borrow_mut(&outputs);
|
||||||
match output {
|
let output = find_output_mut(&mut collection, wl_output);
|
||||||
Some(output) => { output.current = output.pending.clone(); }
|
match output {
|
||||||
None => log_print!(
|
Some(output) => { output.current = output.pending.clone(); }
|
||||||
logging::Level::Warning,
|
None => log_print!(
|
||||||
"Got done on unknown output",
|
logging::Level::Warning,
|
||||||
),
|
"Got done on unknown output",
|
||||||
};
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let collection = RefCell::borrow(&outputs);
|
||||||
|
if let Some(ref cb) = &collection.update_cb {
|
||||||
|
let mut cb = RefCell::borrow_mut(cb);
|
||||||
|
let cb = Box::as_mut(&mut cb);
|
||||||
|
cb(OutputHandle { wl_output, outputs: outputs_raw });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn outputs_handle_scale(
|
extern fn outputs_handle_scale(
|
||||||
@ -224,7 +256,10 @@ pub mod c {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn squeek_outputs_new() -> COutputs {
|
fn squeek_outputs_new() -> COutputs {
|
||||||
COutputs::new(Outputs { outputs: Vec::new() })
|
COutputs::new(Outputs {
|
||||||
|
outputs: Vec::new(),
|
||||||
|
update_cb: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -293,22 +328,29 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic size
|
/// Generic size
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct SizeMM {
|
||||||
|
pub width: i32,
|
||||||
|
pub height: i32,
|
||||||
|
}
|
||||||
|
|
||||||
/// wl_output mode
|
/// wl_output mode
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
struct Mode {
|
struct Mode {
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct OutputState {
|
pub struct OutputState {
|
||||||
current_mode: Option<Mode>,
|
current_mode: Option<Mode>,
|
||||||
|
phys_size: Option<SizeMM>,
|
||||||
transform: Option<c::Transform>,
|
transform: Option<c::Transform>,
|
||||||
pub scale: i32,
|
pub scale: i32,
|
||||||
}
|
}
|
||||||
@ -323,6 +365,7 @@ impl OutputState {
|
|||||||
fn uninitialized() -> OutputState {
|
fn uninitialized() -> OutputState {
|
||||||
OutputState {
|
OutputState {
|
||||||
current_mode: None,
|
current_mode: None,
|
||||||
|
phys_size: None,
|
||||||
transform: None,
|
transform: None,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
}
|
}
|
||||||
@ -334,6 +377,35 @@ impl OutputState {
|
|||||||
OutputState {
|
OutputState {
|
||||||
current_mode: Some(Mode { width, height } ),
|
current_mode: Some(Mode { width, height } ),
|
||||||
transform: Some(transform),
|
transform: Some(transform),
|
||||||
|
phys_size: _,
|
||||||
|
scale: _,
|
||||||
|
} => Some(
|
||||||
|
match transform {
|
||||||
|
Transform::Normal
|
||||||
|
| Transform::Rotated180
|
||||||
|
| Transform::Flipped
|
||||||
|
| Transform::FlippedRotated180 => Size {
|
||||||
|
width: *width as u32,
|
||||||
|
height: *height as u32,
|
||||||
|
},
|
||||||
|
_ => Size {
|
||||||
|
width: *height as u32,
|
||||||
|
height: *width as u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns transformed dimensions
|
||||||
|
pub fn get_phys_size(&self) -> Option<Size> {
|
||||||
|
use self::c::Transform;
|
||||||
|
match self {
|
||||||
|
OutputState {
|
||||||
|
current_mode: _,
|
||||||
|
transform: Some(transform),
|
||||||
|
phys_size: Some(SizeMM { width, height }),
|
||||||
scale: _,
|
scale: _,
|
||||||
} => Some(
|
} => Some(
|
||||||
match transform {
|
match transform {
|
||||||
@ -355,12 +427,52 @@ impl OutputState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A comparable ID of an output
|
||||||
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
|
pub struct OutputId {
|
||||||
|
// WlOutput is a unique pointer, so it will not repeat
|
||||||
|
// even if there are multiple output managers.
|
||||||
|
wl_output: c::WlOutput,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
output: c::WlOutput,
|
output: c::WlOutput,
|
||||||
pending: OutputState,
|
pending: OutputState,
|
||||||
current: OutputState,
|
current: OutputState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The manager of all outputs.
|
||||||
|
// This is the target of several callbacks,
|
||||||
|
// so it should only be used with a stable place in memory, like `Rc<RefCell>`.
|
||||||
|
// It should not be instantiated externally or copied,
|
||||||
|
// or it will not receive those callbacks and be somewhat of an empty shell.
|
||||||
|
// It should be safe to use as long as the fields are not `pub`,
|
||||||
|
// and there's no `Clone`, and this module's API only ever gives out
|
||||||
|
// references wrapped in `Rc<RefCell>`.
|
||||||
|
// For perfectness, it would only ever give out immutable opaque references,
|
||||||
|
// but that's not practical at the moment.
|
||||||
|
// `mem::swap` could replace the value inside,
|
||||||
|
// but as long as the swap is atomic,
|
||||||
|
// that should not cause an inconsistent state.
|
||||||
pub struct Outputs {
|
pub struct Outputs {
|
||||||
outputs: Vec<Output>,
|
outputs: Vec<Output>,
|
||||||
|
// The RefCell is here to let the function be called
|
||||||
|
// while holding only a read-reference to `Outputs`.
|
||||||
|
// Otherwise anything trying to get useful data from OutputHandle
|
||||||
|
// will fail to acquire reference to Outputs.
|
||||||
|
// TODO: Maybe pass only current state along with Outputs and Output hash.
|
||||||
|
// The only reason a full OutputHandle is here
|
||||||
|
// is to be able to track the right Output.
|
||||||
|
update_cb: Option<RefCell<Box<dyn FnMut(c::OutputHandle)>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Outputs {
|
||||||
|
/// The function will get called whenever
|
||||||
|
/// any output changes or is removed or created.
|
||||||
|
/// If output handle doesn't return state, the output just went down.
|
||||||
|
/// It cannot modify anything in Outputs.
|
||||||
|
// FIXME: handle output destruction
|
||||||
|
pub fn set_update_cb(&mut self, callback: Box<dyn FnMut(c::OutputHandle)>) {
|
||||||
|
self.update_cb = Some(RefCell::new(callback));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
#include <gio/gio.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
call_dbus_cb (GDBusProxy *proxy,
|
|
||||||
GAsyncResult *res,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
g_autoptr (GError) err = NULL;
|
|
||||||
g_autoptr (GVariant) output = NULL;
|
|
||||||
|
|
||||||
output = g_dbus_proxy_call_finish (proxy, res, &err);
|
|
||||||
if (err) {
|
|
||||||
g_warning ("Can't open panel %s", err->message);
|
|
||||||
}
|
|
||||||
g_object_unref (proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
create_dbus_proxy_cb (GObject *source_object, GAsyncResult *res, char *panel)
|
|
||||||
{
|
|
||||||
GDBusProxy *proxy;
|
|
||||||
g_autoptr (GError) err = NULL;
|
|
||||||
GVariantBuilder builder;
|
|
||||||
GVariant *params[3];
|
|
||||||
GVariant *array[1];
|
|
||||||
|
|
||||||
proxy = g_dbus_proxy_new_for_bus_finish (res, &err);
|
|
||||||
|
|
||||||
if (err != NULL) {
|
|
||||||
g_warning ("Can't open panel %s: %s", panel, err->message);
|
|
||||||
g_free (panel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
|
|
||||||
g_variant_builder_add (&builder, "v", g_variant_new_string (""));
|
|
||||||
|
|
||||||
array[0] = g_variant_new ("v", g_variant_new ("(sav)", panel, &builder));
|
|
||||||
|
|
||||||
params[0] = g_variant_new_string ("launch-panel");
|
|
||||||
params[1] = g_variant_new_array (G_VARIANT_TYPE ("v"), array, 1);
|
|
||||||
params[2] = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
|
|
||||||
|
|
||||||
g_dbus_proxy_call (proxy,
|
|
||||||
"Activate",
|
|
||||||
g_variant_new_tuple (params, 3),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
NULL,
|
|
||||||
(GAsyncReadyCallback) call_dbus_cb,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
g_free (panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
popover_open_settings_panel (char *panel)
|
|
||||||
{
|
|
||||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
|
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
|
||||||
NULL,
|
|
||||||
"org.gnome.ControlCenter",
|
|
||||||
"/org/gnome/ControlCenter",
|
|
||||||
"org.gtk.Actions",
|
|
||||||
NULL,
|
|
||||||
(GAsyncReadyCallback) create_dbus_proxy_cb,
|
|
||||||
g_strdup (panel));
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -3,7 +3,6 @@
|
|||||||
use gio;
|
use gio;
|
||||||
use gtk;
|
use gtk;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::cmp::Ordering;
|
|
||||||
use ::layout::c::{ Bounds, EekGtkKeyboard };
|
use ::layout::c::{ Bounds, EekGtkKeyboard };
|
||||||
use ::locale;
|
use ::locale;
|
||||||
use ::locale::{ OwnedTranslation, Translation, compare_current_locale };
|
use ::locale::{ OwnedTranslation, Translation, compare_current_locale };
|
||||||
@ -12,29 +11,16 @@ use ::logging;
|
|||||||
use ::manager;
|
use ::manager;
|
||||||
use ::resources;
|
use ::resources;
|
||||||
|
|
||||||
// Traits
|
|
||||||
use gio::ActionMapExt;
|
use gio::ActionMapExt;
|
||||||
use gio::SettingsExt;
|
use gio::SettingsExt;
|
||||||
#[cfg(feature = "gio_v0_5")]
|
|
||||||
use gio::SimpleActionExt;
|
use gio::SimpleActionExt;
|
||||||
use glib::translate::FromGlibPtrNone;
|
use glib::translate::FromGlibPtrNone;
|
||||||
use glib::variant::ToVariant;
|
use glib::variant::ToVariant;
|
||||||
#[cfg(not(feature = "gtk_v0_5"))]
|
|
||||||
use gtk::BuilderExtManual;
|
|
||||||
use gtk::PopoverExt;
|
use gtk::PopoverExt;
|
||||||
use gtk::WidgetExt;
|
use gtk::WidgetExt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use ::logging::Warn;
|
use ::logging::Warn;
|
||||||
|
|
||||||
mod c {
|
|
||||||
use std::os::raw::c_char;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" {
|
|
||||||
pub fn popover_open_settings_panel(panel: *const c_char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod variants {
|
mod variants {
|
||||||
use glib;
|
use glib;
|
||||||
use glib::Variant;
|
use glib::Variant;
|
||||||
@ -138,12 +124,6 @@ fn make_menu_builder(inputs: Vec<(&str, OwnedTranslation)>) -> gtk::Builder {
|
|||||||
xml,
|
xml,
|
||||||
"
|
"
|
||||||
</section>
|
</section>
|
||||||
<section>
|
|
||||||
<item>
|
|
||||||
<attribute name=\"label\" translatable=\"yes\">Keyboard Settings</attribute>
|
|
||||||
<attribute name=\"action\">settings</attribute>
|
|
||||||
</item>
|
|
||||||
</section>
|
|
||||||
</menu>
|
</menu>
|
||||||
</interface>"
|
</interface>"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
@ -350,13 +330,8 @@ pub fn show(
|
|||||||
.zip(all_layouts.clone().into_iter())
|
.zip(all_layouts.clone().into_iter())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
human_names.sort_unstable_by(|(tr_a, layout_a), (tr_b, layout_b)| {
|
human_names.sort_unstable_by(|(tr_a, _), (tr_b, _)| {
|
||||||
// Sort first by layout then name
|
compare_current_locale(&tr_a.0, &tr_b.0)
|
||||||
match (layout_a, layout_b) {
|
|
||||||
(LayoutId::Local(_), LayoutId::System { .. }) => Ordering::Greater,
|
|
||||||
(LayoutId::System { .. }, LayoutId::Local(_)) => Ordering::Less,
|
|
||||||
_ => compare_current_locale(&tr_a.0, &tr_b.0)
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// GVariant doesn't natively support `enum`s,
|
// GVariant doesn't natively support `enum`s,
|
||||||
@ -435,14 +410,8 @@ pub fn show(
|
|||||||
menu_inner.popdown();
|
menu_inner.popdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
let settings_action = gio::SimpleAction::new("settings", None);
|
|
||||||
settings_action.connect_activate(move |_, _| {
|
|
||||||
unsafe { c::popover_open_settings_panel(CString::new("region").unwrap().as_ptr()) };
|
|
||||||
});
|
|
||||||
|
|
||||||
let action_group = gio::SimpleActionGroup::new();
|
let action_group = gio::SimpleActionGroup::new();
|
||||||
action_group.add_action(&layout_action);
|
action_group.add_action(&layout_action);
|
||||||
action_group.add_action(&settings_action);
|
|
||||||
|
|
||||||
menu.insert_action_group("popup", Some(&action_group));
|
menu.insert_action_group("popup", Some(&action_group));
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,27 +11,13 @@ use std::iter::FromIterator;
|
|||||||
// and what a convenience layout. "_wide" is not a layout,
|
// and what a convenience layout. "_wide" is not a layout,
|
||||||
// neither is "number"
|
// neither is "number"
|
||||||
const KEYBOARDS: &[(*const str, *const str)] = &[
|
const KEYBOARDS: &[(*const str, *const str)] = &[
|
||||||
// layouts: us must be left as first, as it is the,
|
// layouts
|
||||||
// fallback layout. The others should be alphabetical.
|
|
||||||
("us", include_str!("../data/keyboards/us.yaml")),
|
("us", include_str!("../data/keyboards/us.yaml")),
|
||||||
("us+colemak", include_str!("../data/keyboards/us+colemak.yaml")),
|
|
||||||
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
|
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
|
||||||
("br", include_str!("../data/keyboards/br.yaml")),
|
|
||||||
("de", include_str!("../data/keyboards/de.yaml")),
|
("de", include_str!("../data/keyboards/de.yaml")),
|
||||||
("be", include_str!("../data/keyboards/be.yaml")),
|
|
||||||
("be_wide", include_str!("../data/keyboards/be_wide.yaml")),
|
|
||||||
("de_wide", include_str!("../data/keyboards/de_wide.yaml")),
|
("de_wide", include_str!("../data/keyboards/de_wide.yaml")),
|
||||||
("cz", include_str!("../data/keyboards/cz.yaml")),
|
|
||||||
("cz_wide", include_str!("../data/keyboards/cz_wide.yaml")),
|
|
||||||
("cz+qwerty", include_str!("../data/keyboards/cz+qwerty.yaml")),
|
|
||||||
("cz+qwerty_wide", include_str!("../data/keyboards/cz+qwerty_wide.yaml")),
|
|
||||||
("dk", include_str!("../data/keyboards/dk.yaml")),
|
|
||||||
("epo", include_str!("../data/keyboards/epo.yaml")),
|
|
||||||
("es", include_str!("../data/keyboards/es.yaml")),
|
("es", include_str!("../data/keyboards/es.yaml")),
|
||||||
("fi", include_str!("../data/keyboards/fi.yaml")),
|
("fi", include_str!("../data/keyboards/fi.yaml")),
|
||||||
("fr", include_str!("../data/keyboards/fr.yaml")),
|
|
||||||
("fr_wide", include_str!("../data/keyboards/fr_wide.yaml")),
|
|
||||||
("it+fur", include_str!("../data/keyboards/it+fur.yaml")),
|
|
||||||
("gr", include_str!("../data/keyboards/gr.yaml")),
|
("gr", include_str!("../data/keyboards/gr.yaml")),
|
||||||
("it", include_str!("../data/keyboards/it.yaml")),
|
("it", include_str!("../data/keyboards/it.yaml")),
|
||||||
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
|
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
|
||||||
@ -40,14 +26,9 @@ const KEYBOARDS: &[(*const str, *const str)] = &[
|
|||||||
("number", include_str!("../data/keyboards/number.yaml")),
|
("number", include_str!("../data/keyboards/number.yaml")),
|
||||||
("pl", include_str!("../data/keyboards/pl.yaml")),
|
("pl", include_str!("../data/keyboards/pl.yaml")),
|
||||||
("pl_wide", include_str!("../data/keyboards/pl_wide.yaml")),
|
("pl_wide", include_str!("../data/keyboards/pl_wide.yaml")),
|
||||||
("ru", include_str!("../data/keyboards/ru.yaml")),
|
|
||||||
("se", include_str!("../data/keyboards/se.yaml")),
|
("se", include_str!("../data/keyboards/se.yaml")),
|
||||||
("th", include_str!("../data/keyboards/th.yaml")),
|
|
||||||
("ua", include_str!("../data/keyboards/ua.yaml")),
|
|
||||||
("bg", include_str!("../data/keyboards/bg.yaml")),
|
|
||||||
// layout+overlay
|
// layout+overlay
|
||||||
("terminal", include_str!("../data/keyboards/terminal.yaml")),
|
("terminal", include_str!("../data/keyboards/terminal.yaml")),
|
||||||
("terminal_wide", include_str!("../data/keyboards/terminal_wide.yaml")),
|
|
||||||
// Overlays
|
// Overlays
|
||||||
("emoji", include_str!("../data/keyboards/emoji.yaml")),
|
("emoji", include_str!("../data/keyboards/emoji.yaml")),
|
||||||
];
|
];
|
||||||
@ -84,10 +65,8 @@ const LAYOUT_NAMES: &[(*const str, *const str)] = &[
|
|||||||
("de-DE", include_str!("../data/langs/de-DE.txt")),
|
("de-DE", include_str!("../data/langs/de-DE.txt")),
|
||||||
("en-US", include_str!("../data/langs/en-US.txt")),
|
("en-US", include_str!("../data/langs/en-US.txt")),
|
||||||
("es-ES", include_str!("../data/langs/es-ES.txt")),
|
("es-ES", include_str!("../data/langs/es-ES.txt")),
|
||||||
("fur-IT", include_str!("../data/langs/fur-IT.txt")),
|
|
||||||
("ja-JP", include_str!("../data/langs/ja-JP.txt")),
|
("ja-JP", include_str!("../data/langs/ja-JP.txt")),
|
||||||
("pl-PL", include_str!("../data/langs/pl-PL.txt")),
|
("pl-PL", include_str!("../data/langs/pl-PL.txt")),
|
||||||
("ru-RU", include_str!("../data/langs/ru-RU.txt")),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn get_layout_names(lang: &str)
|
pub fn get_layout_names(lang: &str)
|
||||||
|
|||||||
@ -31,19 +31,19 @@
|
|||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_VISIBLE,
|
PROP_VISIBLE,
|
||||||
PROP_ENABLED,
|
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _ServerContextServiceClass ServerContextServiceClass;
|
||||||
|
|
||||||
struct _ServerContextService {
|
struct _ServerContextService {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
EekboardContextService *state; // unowned
|
LayoutHolder *state; // unowned
|
||||||
/// Needed for instantiating the widget
|
/// Needed for instantiating the widget
|
||||||
struct submission *submission; // unowned
|
struct submission *submission; // unowned
|
||||||
struct squeek_layout_state *layout;
|
struct squeek_layout_state *layout;
|
||||||
struct ui_manager *manager; // unowned
|
struct ui_manager *manager; // unowned
|
||||||
struct vis_manager *vis_manager; // owned
|
|
||||||
|
|
||||||
gboolean visible;
|
gboolean visible;
|
||||||
PhoshLayerSurface *window;
|
PhoshLayerSurface *window;
|
||||||
@ -52,97 +52,52 @@ struct _ServerContextService {
|
|||||||
guint last_requested_height;
|
guint last_requested_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _ServerContextServiceClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(ServerContextService, server_context_service, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(ServerContextService, server_context_service, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_destroy (ServerContextService *self, GtkWidget *widget)
|
on_destroy (GtkWidget *widget, gpointer user_data)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
ServerContextService *context = user_data;
|
||||||
|
|
||||||
g_assert (widget == GTK_WIDGET(self->window));
|
g_assert (widget == GTK_WIDGET(context->window));
|
||||||
|
|
||||||
self->window = NULL;
|
context->window = NULL;
|
||||||
self->widget = NULL;
|
context->widget = NULL;
|
||||||
|
|
||||||
//eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
|
//eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_notify_map (ServerContextService *self, GtkWidget *widget)
|
on_notify_map (GObject *object,
|
||||||
|
ServerContextService *context)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
g_object_set (context, "visible", TRUE, NULL);
|
||||||
|
|
||||||
g_object_set (self, "visible", TRUE, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_notify_unmap (ServerContextService *self, GtkWidget *widget)
|
on_notify_unmap (GObject *object,
|
||||||
|
ServerContextService *context)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
(void)object;
|
||||||
|
g_object_set (context, "visible", FALSE, NULL);
|
||||||
g_object_set (self, "visible", FALSE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
calculate_height(int32_t width, GdkRectangle *geometry)
|
|
||||||
{
|
|
||||||
uint32_t height;
|
|
||||||
if (geometry->width > geometry->height) {
|
|
||||||
// 1:5 ratio works fine on lanscape mode, and makes sure there's
|
|
||||||
// room left for the app window
|
|
||||||
height = width / 5;
|
|
||||||
} else {
|
|
||||||
if (width < 540 && width > 0) {
|
|
||||||
height = ((unsigned)width * 7 / 12); // to match 360×210
|
|
||||||
} else {
|
|
||||||
// Here we switch to wide layout, less height needed
|
|
||||||
height = ((unsigned)width * 7 / 22);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_surface_configure(ServerContextService *self, PhoshLayerSurface *surface)
|
on_surface_configure(PhoshLayerSurface *surface, ServerContextService *context)
|
||||||
{
|
{
|
||||||
GdkDisplay *display = NULL;
|
|
||||||
GdkWindow *window = NULL;
|
|
||||||
GdkMonitor *monitor = NULL;
|
|
||||||
GdkRectangle geometry;
|
|
||||||
gint width;
|
gint width;
|
||||||
gint height;
|
gint height;
|
||||||
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
|
||||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (surface));
|
|
||||||
|
|
||||||
g_object_get(G_OBJECT(surface),
|
g_object_get(G_OBJECT(surface),
|
||||||
"configured-width", &width,
|
"configured-width", &width,
|
||||||
"configured-height", &height,
|
"configured-height", &height,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
// In order to improve height calculation, we need the monitor geometry so
|
guint desired_height = squeek_uiman_get_perceptual_height(context->manager);
|
||||||
// we can use different algorithms for portrait and landscape mode.
|
|
||||||
// Note: this is a temporary fix until the size manager is complete.
|
|
||||||
display = gdk_display_get_default ();
|
|
||||||
if (display) {
|
|
||||||
window = gtk_widget_get_window (GTK_WIDGET (surface));
|
|
||||||
}
|
|
||||||
if (window) {
|
|
||||||
monitor = gdk_display_get_monitor_at_window (display, window);
|
|
||||||
}
|
|
||||||
if (monitor) {
|
|
||||||
gdk_monitor_get_geometry (monitor, &geometry);
|
|
||||||
} else {
|
|
||||||
geometry.width = geometry.height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the geometry event comes after surface.configure,
|
|
||||||
// this entire height calculation does nothing.
|
|
||||||
// guint desired_height = squeek_uiman_get_perceptual_height(context->manager);
|
|
||||||
// Temporarily use old method, until the size manager is complete.
|
|
||||||
guint desired_height = calculate_height(width, &geometry);
|
|
||||||
|
|
||||||
guint configured_height = (guint)height;
|
guint configured_height = (guint)height;
|
||||||
// if height was already requested once but a different one was given
|
// if height was already requested once but a different one was given
|
||||||
// (for the same set of surrounding properties),
|
// (for the same set of surrounding properties),
|
||||||
@ -150,8 +105,8 @@ on_surface_configure(ServerContextService *self, PhoshLayerSurface *surface)
|
|||||||
// as it's likely to create pointless loops
|
// as it's likely to create pointless loops
|
||||||
// of request->reject->request_again->...
|
// of request->reject->request_again->...
|
||||||
if (desired_height != configured_height
|
if (desired_height != configured_height
|
||||||
&& self->last_requested_height != desired_height) {
|
&& context->last_requested_height != desired_height) {
|
||||||
self->last_requested_height = desired_height;
|
context->last_requested_height = desired_height;
|
||||||
phosh_layer_surface_set_size(surface, 0,
|
phosh_layer_surface_set_size(surface, 0,
|
||||||
(gint)desired_height);
|
(gint)desired_height);
|
||||||
phosh_layer_surface_set_exclusive_zone(surface, (gint)desired_height);
|
phosh_layer_surface_set_exclusive_zone(surface, (gint)desired_height);
|
||||||
@ -160,17 +115,16 @@ on_surface_configure(ServerContextService *self, PhoshLayerSurface *surface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
make_window (ServerContextService *self)
|
make_window (ServerContextService *context)
|
||||||
{
|
{
|
||||||
if (self->window) {
|
if (context->window)
|
||||||
g_error("Window already present");
|
g_error("Window already present");
|
||||||
}
|
|
||||||
|
|
||||||
struct squeek_output_handle output = squeek_outputs_get_current(squeek_wayland->outputs);
|
struct squeek_output_handle output = squeek_outputs_get_current(squeek_wayland->outputs);
|
||||||
squeek_uiman_set_output(self->manager, output);
|
squeek_uiman_set_output(context->manager, output);
|
||||||
uint32_t height = squeek_uiman_get_perceptual_height(self->manager);
|
uint32_t height = squeek_uiman_get_perceptual_height(context->manager);
|
||||||
|
|
||||||
self->window = g_object_new (
|
context->window = g_object_new (
|
||||||
PHOSH_TYPE_LAYER_SURFACE,
|
PHOSH_TYPE_LAYER_SURFACE,
|
||||||
"layer-shell", squeek_wayland->layer_shell,
|
"layer-shell", squeek_wayland->layer_shell,
|
||||||
"wl-output", output.output,
|
"wl-output", output.output,
|
||||||
@ -185,11 +139,12 @@ make_window (ServerContextService *self)
|
|||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_connect (self->window,
|
squeek_uiman_set_surface(context->manager, context->window);
|
||||||
"swapped-signal::destroy", G_CALLBACK(on_destroy), self,
|
g_object_connect (context->window,
|
||||||
"swapped-signal::map", G_CALLBACK(on_notify_map), self,
|
"signal::destroy", G_CALLBACK(on_destroy), context,
|
||||||
"swapped-signal::unmap", G_CALLBACK(on_notify_unmap), self,
|
"signal::map", G_CALLBACK(on_notify_map), context,
|
||||||
"swapped-signal::configured", G_CALLBACK(on_surface_configure), self,
|
"signal::unmap", G_CALLBACK(on_notify_unmap), context,
|
||||||
|
"signal::configured", G_CALLBACK(on_surface_configure), context,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
// The properties below are just to make hacking easier.
|
// The properties below are just to make hacking easier.
|
||||||
@ -197,110 +152,88 @@ make_window (ServerContextService *self)
|
|||||||
// and there's no space in the protocol for others.
|
// and there's no space in the protocol for others.
|
||||||
// Those may still be useful in the future,
|
// Those may still be useful in the future,
|
||||||
// or for hacks with regular windows.
|
// or for hacks with regular windows.
|
||||||
gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
|
gtk_widget_set_can_focus (GTK_WIDGET(context->window), FALSE);
|
||||||
g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
|
g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL);
|
||||||
gtk_window_set_title (GTK_WINDOW(self->window),
|
gtk_window_set_title (GTK_WINDOW(context->window),
|
||||||
_("Squeekboard"));
|
_("Squeekboard"));
|
||||||
gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
|
gtk_window_set_icon_name (GTK_WINDOW(context->window), "squeekboard");
|
||||||
gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
|
gtk_window_set_keep_above (GTK_WINDOW(context->window), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_window (ServerContextService *self)
|
destroy_window (ServerContextService *context)
|
||||||
{
|
{
|
||||||
gtk_widget_destroy (GTK_WIDGET (self->window));
|
gtk_widget_destroy (GTK_WIDGET (context->window));
|
||||||
self->window = NULL;
|
context->window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
make_widget (ServerContextService *self)
|
make_widget (ServerContextService *context)
|
||||||
{
|
{
|
||||||
if (self->widget) {
|
if (context->widget) {
|
||||||
gtk_widget_destroy(self->widget);
|
gtk_widget_destroy(context->widget);
|
||||||
self->widget = NULL;
|
context->widget = NULL;
|
||||||
}
|
}
|
||||||
self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout);
|
context->widget = eek_gtk_keyboard_new (context->state, context->submission, context->layout);
|
||||||
|
|
||||||
gtk_widget_set_has_tooltip (self->widget, TRUE);
|
gtk_widget_set_has_tooltip (context->widget, TRUE);
|
||||||
gtk_container_add (GTK_CONTAINER(self->window), self->widget);
|
gtk_container_add (GTK_CONTAINER(context->window), context->widget);
|
||||||
gtk_widget_show_all(self->widget);
|
gtk_widget_show_all(context->widget);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
server_context_service_real_show_keyboard (ServerContextService *self)
|
|
||||||
{
|
|
||||||
if (!self->window) {
|
|
||||||
make_window (self);
|
|
||||||
}
|
|
||||||
if (!self->widget) {
|
|
||||||
make_widget (self);
|
|
||||||
}
|
|
||||||
self->visible = TRUE;
|
|
||||||
gtk_widget_show (GTK_WIDGET(self->window));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
server_context_service_real_hide_keyboard (ServerContextService *self)
|
|
||||||
{
|
|
||||||
gtk_widget_hide (GTK_WIDGET(self->window));
|
|
||||||
self->visible = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
on_hide (ServerContextService *self)
|
on_hide (ServerContextService *context)
|
||||||
{
|
{
|
||||||
server_context_service_real_hide_keyboard(self);
|
gtk_widget_hide (GTK_WIDGET(context->window));
|
||||||
self->hiding = 0;
|
context->hiding = 0;
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
server_context_service_show_keyboard (ServerContextService *self)
|
server_context_service_real_show_keyboard (ServerContextService *context)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
if (context->hiding) {
|
||||||
|
g_source_remove (context->hiding);
|
||||||
if (self->hiding) {
|
context->hiding = 0;
|
||||||
g_source_remove (self->hiding);
|
|
||||||
self->hiding = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->visible) {
|
if (!context->window)
|
||||||
server_context_service_real_show_keyboard (self);
|
make_window (context);
|
||||||
}
|
if (!context->widget)
|
||||||
}
|
make_widget (context);
|
||||||
|
|
||||||
void
|
context->visible = TRUE;
|
||||||
server_context_service_hide_keyboard (ServerContextService *self)
|
gtk_widget_show (GTK_WIDGET(context->window));
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
|
||||||
|
|
||||||
if (self->visible) {
|
|
||||||
server_context_service_real_hide_keyboard (self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Meant for use by the input-method handler:
|
|
||||||
/// the visible keyboard is no longer needed.
|
|
||||||
/// The implementation will delay it slightly,
|
|
||||||
/// because the release may be due to switching from one text field to another.
|
|
||||||
/// In this case, the user doesn't really need the keyboard surface
|
|
||||||
/// to disappear completely.
|
|
||||||
void
|
|
||||||
server_context_service_release_visibility (ServerContextService *self)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
|
||||||
|
|
||||||
if (!self->hiding && self->visible) {
|
|
||||||
self->hiding = g_timeout_add (200, (GSourceFunc) on_hide, self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
server_context_service_set_physical_keyboard_present (ServerContextService *self, gboolean physical_keyboard_present)
|
server_context_service_real_hide_keyboard (ServerContextService *context)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
if (!context->hiding)
|
||||||
squeek_visman_set_keyboard_present(self->vis_manager, physical_keyboard_present);
|
context->hiding = g_timeout_add (200, (GSourceFunc) on_hide, context);
|
||||||
|
|
||||||
|
context->visible = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_context_service_show_keyboard (ServerContextService *context)
|
||||||
|
{
|
||||||
|
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(context));
|
||||||
|
|
||||||
|
if (!context->visible) {
|
||||||
|
server_context_service_real_show_keyboard (context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_context_service_hide_keyboard (ServerContextService *context)
|
||||||
|
{
|
||||||
|
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(context));
|
||||||
|
|
||||||
|
if (context->visible) {
|
||||||
|
server_context_service_real_hide_keyboard (context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -309,15 +242,13 @@ server_context_service_set_property (GObject *object,
|
|||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_VISIBLE:
|
case PROP_VISIBLE:
|
||||||
self->visible = g_value_get_boolean (value);
|
context->visible = g_value_get_boolean (value);
|
||||||
break;
|
|
||||||
case PROP_ENABLED:
|
|
||||||
server_context_service_set_physical_keyboard_present (self, !g_value_get_boolean (value));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -330,10 +261,10 @@ server_context_service_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_VISIBLE:
|
case PROP_VISIBLE:
|
||||||
g_value_set_boolean (value, self->visible);
|
g_value_set_boolean (value, context->visible);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
@ -344,10 +275,10 @@ server_context_service_get_property (GObject *object,
|
|||||||
static void
|
static void
|
||||||
server_context_service_dispose (GObject *object)
|
server_context_service_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
|
||||||
|
|
||||||
destroy_window (self);
|
destroy_window (context);
|
||||||
self->widget = NULL;
|
context->widget = NULL;
|
||||||
|
|
||||||
G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
|
G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@ -373,66 +304,20 @@ server_context_service_class_init (ServerContextServiceClass *klass)
|
|||||||
g_object_class_install_property (gobject_class,
|
g_object_class_install_property (gobject_class,
|
||||||
PROP_VISIBLE,
|
PROP_VISIBLE,
|
||||||
pspec);
|
pspec);
|
||||||
|
|
||||||
/**
|
|
||||||
* ServerContextServie:keyboard:
|
|
||||||
*
|
|
||||||
* Does the user want the keyboard to show up automatically?
|
|
||||||
*/
|
|
||||||
pspec =
|
|
||||||
g_param_spec_boolean ("enabled",
|
|
||||||
"Enabled",
|
|
||||||
"Whether the keyboard is enabled",
|
|
||||||
TRUE,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
|
||||||
g_object_class_install_property (gobject_class,
|
|
||||||
PROP_ENABLED,
|
|
||||||
pspec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
server_context_service_init (ServerContextService *self) {}
|
server_context_service_init (ServerContextService *state) {
|
||||||
|
(void)state;
|
||||||
static void
|
|
||||||
init (ServerContextService *self) {
|
|
||||||
const char *schema_name = "org.gnome.desktop.a11y.applications";
|
|
||||||
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default();
|
|
||||||
g_autoptr(GSettingsSchema) schema = NULL;
|
|
||||||
|
|
||||||
if (!ssrc) {
|
|
||||||
g_warning("No gsettings schemas installed.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
schema = g_settings_schema_source_lookup(ssrc, schema_name, TRUE);
|
|
||||||
if (schema) {
|
|
||||||
g_autoptr(GSettings) settings = g_settings_new (schema_name);
|
|
||||||
g_settings_bind (settings, "screen-keyboard-enabled",
|
|
||||||
self, "enabled", G_SETTINGS_BIND_GET);
|
|
||||||
} else {
|
|
||||||
g_warning("Gsettings schema %s is not installed on the system. "
|
|
||||||
"Enabling by default.", schema_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerContextService *
|
ServerContextService *
|
||||||
server_context_service_new (EekboardContextService *self, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman, struct vis_manager *visman)
|
server_context_service_new (LayoutHolder *state, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman)
|
||||||
{
|
{
|
||||||
ServerContextService *ui = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL);
|
ServerContextService *ui = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL);
|
||||||
ui->submission = submission;
|
ui->submission = submission;
|
||||||
ui->state = self;
|
ui->state = state;
|
||||||
ui->layout = layout;
|
ui->layout = layout;
|
||||||
ui->manager = uiman;
|
ui->manager = uiman;
|
||||||
ui->vis_manager = visman;
|
|
||||||
init(ui);
|
|
||||||
return ui;
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
server_context_service_update_visible (ServerContextService *self, gboolean visible) {
|
|
||||||
if (visible) {
|
|
||||||
server_context_service_show_keyboard(self);
|
|
||||||
} else {
|
|
||||||
server_context_service_hide_keyboard(self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -25,14 +25,22 @@
|
|||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define SERVER_TYPE_CONTEXT_SERVICE (server_context_service_get_type())
|
#define SERVER_TYPE_CONTEXT_SERVICE (server_context_service_get_type())
|
||||||
|
#define SERVER_CONTEXT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SERVER_TYPE_CONTEXT_SERVICE, ServerContextService))
|
||||||
|
#define SERVER_CONTEXT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SERVER_TYPE_CONTEXT_SERVICE, ServerContextServiceClass))
|
||||||
|
#define SERVER_IS_CONTEXT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SERVER_TYPE_CONTEXT_SERVICE))
|
||||||
|
#define SERVER_IS_CONTEXT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SERVER_TYPE_CONTEXT_SERVICE))
|
||||||
|
#define SERVER_CONTEXT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SERVER_TYPE_CONTEXT_SERVICE, ServerContextServiceClass))
|
||||||
|
|
||||||
/** Manages the lifecycle of the window displaying layouts. */
|
/** Manages the lifecycle of the window displaying layouts. */
|
||||||
G_DECLARE_FINAL_TYPE (ServerContextService, server_context_service, SERVER, CONTEXT_SERVICE, GObject)
|
typedef struct _ServerContextService ServerContextService;
|
||||||
|
|
||||||
ServerContextService *server_context_service_new(EekboardContextService *self, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman, struct vis_manager *visman);
|
GType server_context_service_get_type
|
||||||
|
(void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ServerContextService *server_context_service_new(LayoutHolder *state, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman);
|
||||||
enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *);
|
enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *);
|
||||||
void server_context_service_show_keyboard (ServerContextService *self);
|
void server_context_service_show_keyboard (ServerContextService *context);
|
||||||
void server_context_service_hide_keyboard (ServerContextService *self);
|
void server_context_service_hide_keyboard (ServerContextService *context);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* SERVER_CONTEXT_SERVICE_H */
|
#endif /* SERVER_CONTEXT_SERVICE_H */
|
||||||
|
|
||||||
|
|||||||
@ -42,11 +42,12 @@
|
|||||||
struct squeekboard {
|
struct squeekboard {
|
||||||
struct squeek_wayland wayland; // Just hooks.
|
struct squeek_wayland wayland; // Just hooks.
|
||||||
DBusHandler *dbus_handler; // Controls visibility of the OSK.
|
DBusHandler *dbus_handler; // Controls visibility of the OSK.
|
||||||
EekboardContextService *settings_context; // Gsettings hooks.
|
LayoutHolder *layout_holder; // Currently used layout & keyboard.
|
||||||
ServerContextService *ui_context; // mess, includes the entire UI
|
ServerContextService *ui_context; // mess, includes the entire UI
|
||||||
struct submission *submission; // Wayland text input handling.
|
struct submission *submission; // Wayland text input handling.
|
||||||
struct squeek_layout_state layout_choice; // Currently wanted layout.
|
struct squeek_layout_state layout_choice; // Currently wanted layout.
|
||||||
struct ui_manager *ui_manager; // UI shape tracker/chooser. TODO: merge with layuot choice
|
struct ui_manager *ui_manager; // UI shape tracker/chooser. TODO: merge with layuot choice
|
||||||
|
struct gsettings_tracker gsettings_tracker; // Gsettings handling.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -203,23 +204,22 @@ main (int argc, char **argv)
|
|||||||
g_warning("Wayland input method interface not available");
|
g_warning("Wayland input method interface not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.ui_manager = squeek_uiman_new();
|
instance.ui_manager = squeek_uiman_new(instance.wayland.outputs);
|
||||||
|
|
||||||
instance.settings_context = eekboard_context_service_new(&instance.layout_choice);
|
|
||||||
|
|
||||||
|
instance.layout_holder = eek_layout_holder_new(&instance.layout_choice);
|
||||||
|
eek_gsettings_tracker_init(&instance.gsettings_tracker, instance.layout_holder, &instance.layout_choice);
|
||||||
// set up dbus
|
// set up dbus
|
||||||
|
|
||||||
// TODO: make dbus errors non-always-fatal
|
// TODO: make dbus errors non-always-fatal
|
||||||
// dbus is not strictly necessary for the useful operation
|
// dbus is not strictly necessary for the useful operation
|
||||||
// if text-input is used, as it can bring the keyboard in and out
|
// if text-input is used, as it can bring the keyboard in and out
|
||||||
GBusType bus_type;
|
GBusType bus_type;
|
||||||
if (opt_system) {
|
if (opt_system)
|
||||||
bus_type = G_BUS_TYPE_SYSTEM;
|
bus_type = G_BUS_TYPE_SYSTEM;
|
||||||
} else if (opt_address) {
|
else if (opt_address)
|
||||||
bus_type = G_BUS_TYPE_NONE;
|
bus_type = G_BUS_TYPE_NONE;
|
||||||
} else {
|
else
|
||||||
bus_type = G_BUS_TYPE_SESSION;
|
bus_type = G_BUS_TYPE_SESSION;
|
||||||
}
|
|
||||||
|
|
||||||
GDBusConnection *connection = NULL;
|
GDBusConnection *connection = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -277,33 +277,29 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct vis_manager *vis_manager = squeek_visman_new();
|
|
||||||
|
|
||||||
instance.submission = get_submission(instance.wayland.input_method_manager,
|
instance.submission = get_submission(instance.wayland.input_method_manager,
|
||||||
instance.wayland.virtual_keyboard_manager,
|
instance.wayland.virtual_keyboard_manager,
|
||||||
vis_manager,
|
|
||||||
instance.wayland.seat,
|
instance.wayland.seat,
|
||||||
instance.settings_context);
|
instance.layout_holder);
|
||||||
|
|
||||||
eekboard_context_service_set_submission(instance.settings_context, instance.submission);
|
eek_layout_holder_set_submission(instance.layout_holder, instance.submission);
|
||||||
|
|
||||||
ServerContextService *ui_context = server_context_service_new(
|
ServerContextService *ui_context = server_context_service_new(
|
||||||
instance.settings_context,
|
instance.layout_holder,
|
||||||
instance.submission,
|
instance.submission,
|
||||||
&instance.layout_choice,
|
&instance.layout_choice,
|
||||||
instance.ui_manager,
|
instance.ui_manager);
|
||||||
vis_manager);
|
|
||||||
if (!ui_context) {
|
if (!ui_context) {
|
||||||
g_error("Could not initialize GUI");
|
g_error("Could not initialize GUI");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
instance.ui_context = ui_context;
|
instance.ui_context = ui_context;
|
||||||
squeek_visman_set_ui(vis_manager, instance.ui_context);
|
if (instance.submission) {
|
||||||
|
submission_set_ui(instance.submission, instance.ui_context);
|
||||||
|
}
|
||||||
if (instance.dbus_handler) {
|
if (instance.dbus_handler) {
|
||||||
dbus_handler_set_ui_context(instance.dbus_handler, instance.ui_context);
|
dbus_handler_set_ui_context(instance.dbus_handler, instance.ui_context);
|
||||||
}
|
}
|
||||||
eekboard_context_service_set_ui(instance.settings_context, instance.ui_context);
|
|
||||||
|
|
||||||
session_register();
|
session_register();
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
#define __STYLE_H
|
#define __STYLE_H
|
||||||
#include "gtk/gtk.h"
|
#include "gtk/gtk.h"
|
||||||
|
|
||||||
GtkCssProvider *squeek_load_style(void);
|
GtkCssProvider *squeek_load_style();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,19 +4,16 @@
|
|||||||
#include "input-method-unstable-v2-client-protocol.h"
|
#include "input-method-unstable-v2-client-protocol.h"
|
||||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||||
#include "eek/eek-types.h"
|
#include "eek/eek-types.h"
|
||||||
#include "src/ui_manager.h"
|
|
||||||
|
|
||||||
struct submission;
|
struct submission;
|
||||||
struct squeek_layout;
|
|
||||||
|
|
||||||
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
|
||||||
struct zwp_virtual_keyboard_manager_v1 *vkmanager,
|
struct zwp_virtual_keyboard_manager_v1 *vkmanager,
|
||||||
struct vis_manager *vis_manager,
|
|
||||||
struct wl_seat *seat,
|
struct wl_seat *seat,
|
||||||
EekboardContextService *state);
|
LayoutHolder *state);
|
||||||
|
|
||||||
// Defined in Rust
|
// Defined in Rust
|
||||||
struct submission* submission_new(struct zwp_input_method_v2 *im, struct zwp_virtual_keyboard_v1 *vk, EekboardContextService *state, struct vis_manager *vis_manager);
|
struct submission* submission_new(struct zwp_input_method_v2 *im, struct zwp_virtual_keyboard_v1 *vk, LayoutHolder *state);
|
||||||
void submission_set_ui(struct submission *self, ServerContextService *ui_context);
|
void submission_set_ui(struct submission *self, ServerContextService *ui_context);
|
||||||
void submission_use_layout(struct submission *self, struct squeek_layout *layout, uint32_t time);
|
void submission_set_keyboard(struct submission *self, LevelKeyboard *keyboard);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -23,10 +23,7 @@ use ::action::Modifier;
|
|||||||
use ::imservice;
|
use ::imservice;
|
||||||
use ::imservice::IMService;
|
use ::imservice::IMService;
|
||||||
use ::keyboard::{ KeyCode, KeyStateId, Modifiers, PressType };
|
use ::keyboard::{ KeyCode, KeyStateId, Modifiers, PressType };
|
||||||
use ::layout;
|
|
||||||
use ::ui_manager::VisibilityManager;
|
|
||||||
use ::util::vec_remove;
|
use ::util::vec_remove;
|
||||||
use ::vkeyboard;
|
|
||||||
use ::vkeyboard::VirtualKeyboard;
|
use ::vkeyboard::VirtualKeyboard;
|
||||||
|
|
||||||
// traits
|
// traits
|
||||||
@ -39,11 +36,15 @@ pub mod c {
|
|||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
use ::imservice::c::InputMethod;
|
use ::imservice::c::InputMethod;
|
||||||
use ::util::c::Wrapped;
|
use ::layout::c::LevelKeyboard;
|
||||||
use ::vkeyboard::c::ZwpVirtualKeyboardV1;
|
use ::vkeyboard::c::ZwpVirtualKeyboardV1;
|
||||||
|
|
||||||
// The following defined in C
|
// The following defined in C
|
||||||
|
|
||||||
|
/// ServerContextService*
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct UIManager(*const c_void);
|
||||||
|
|
||||||
/// EekboardContextService*
|
/// EekboardContextService*
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct StateManager(*const c_void);
|
pub struct StateManager(*const c_void);
|
||||||
@ -53,18 +54,12 @@ pub mod c {
|
|||||||
fn submission_new(
|
fn submission_new(
|
||||||
im: *mut InputMethod,
|
im: *mut InputMethod,
|
||||||
vk: ZwpVirtualKeyboardV1,
|
vk: ZwpVirtualKeyboardV1,
|
||||||
state_manager: *const StateManager,
|
state_manager: *const StateManager
|
||||||
visibility_manager: Wrapped<VisibilityManager>,
|
|
||||||
) -> *mut Submission {
|
) -> *mut Submission {
|
||||||
let imservice = if im.is_null() {
|
let imservice = if im.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let visibility_manager = visibility_manager.clone_ref();
|
Some(IMService::new(im, state_manager))
|
||||||
Some(IMService::new(
|
|
||||||
im,
|
|
||||||
state_manager,
|
|
||||||
Box::new(move |active| visibility_manager.borrow_mut().set_im_active(active)),
|
|
||||||
))
|
|
||||||
};
|
};
|
||||||
// TODO: add vkeyboard too
|
// TODO: add vkeyboard too
|
||||||
Box::<Submission>::into_raw(Box::new(
|
Box::<Submission>::into_raw(Box::new(
|
||||||
@ -73,32 +68,41 @@ pub mod c {
|
|||||||
modifiers_active: Vec::new(),
|
modifiers_active: Vec::new(),
|
||||||
virtual_keyboard: VirtualKeyboard(vk),
|
virtual_keyboard: VirtualKeyboard(vk),
|
||||||
pressed: Vec::new(),
|
pressed: Vec::new(),
|
||||||
keymap_fds: Vec::new(),
|
|
||||||
keymap_idx: None,
|
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use to initialize the UI reference
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn submission_use_layout(
|
fn submission_set_ui(submission: *mut Submission, ui_manager: *const UIManager) {
|
||||||
submission: *mut Submission,
|
|
||||||
layout: *const layout::Layout,
|
|
||||||
time: u32,
|
|
||||||
) {
|
|
||||||
if submission.is_null() {
|
if submission.is_null() {
|
||||||
panic!("Null submission pointer");
|
panic!("Null submission pointer");
|
||||||
}
|
}
|
||||||
let submission: &mut Submission = unsafe { &mut *submission };
|
let submission: &mut Submission = unsafe { &mut *submission };
|
||||||
let layout = unsafe { &*layout };
|
if let Some(ref mut imservice) = &mut submission.imservice {
|
||||||
submission.use_layout(layout, Timestamp(time));
|
imservice.ui_manager = if ui_manager.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(ui_manager)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C"
|
||||||
|
fn submission_set_keyboard(submission: *mut Submission, keyboard: LevelKeyboard) {
|
||||||
|
if submission.is_null() {
|
||||||
|
panic!("Null submission pointer");
|
||||||
|
}
|
||||||
|
let submission: &mut Submission = unsafe { &mut *submission };
|
||||||
|
submission.virtual_keyboard.update_keymap(keyboard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Timestamp(pub u32);
|
pub struct Timestamp(pub u32);
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum SubmittedAction {
|
enum SubmittedAction {
|
||||||
/// A collection of keycodes that were pressed
|
/// A collection of keycodes that were pressed
|
||||||
VirtualKeyboard(Vec<KeyCode>),
|
VirtualKeyboard(Vec<KeyCode>),
|
||||||
@ -110,8 +114,6 @@ pub struct Submission {
|
|||||||
virtual_keyboard: VirtualKeyboard,
|
virtual_keyboard: VirtualKeyboard,
|
||||||
modifiers_active: Vec<(KeyStateId, Modifier)>,
|
modifiers_active: Vec<(KeyStateId, Modifier)>,
|
||||||
pressed: Vec<(KeyStateId, SubmittedAction)>,
|
pressed: Vec<(KeyStateId, SubmittedAction)>,
|
||||||
keymap_fds: Vec<vkeyboard::c::KeyMap>,
|
|
||||||
keymap_idx: Option<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SubmitData<'a> {
|
pub enum SubmitData<'a> {
|
||||||
@ -170,34 +172,11 @@ impl Submission {
|
|||||||
let submit_action = match was_committed_as_text {
|
let submit_action = match was_committed_as_text {
|
||||||
true => SubmittedAction::IMService,
|
true => SubmittedAction::IMService,
|
||||||
false => {
|
false => {
|
||||||
let keycodes_count = keycodes.len();
|
self.virtual_keyboard.switch(
|
||||||
for keycode in keycodes.iter() {
|
keycodes,
|
||||||
self.select_keymap(keycode.keymap_idx, time);
|
PressType::Pressed,
|
||||||
let keycode = keycode.code;
|
time,
|
||||||
match keycodes_count {
|
);
|
||||||
// Pressing a key made out of a single keycode is simple:
|
|
||||||
// press on press, release on release.
|
|
||||||
1 => self.virtual_keyboard.switch(
|
|
||||||
keycode,
|
|
||||||
PressType::Pressed,
|
|
||||||
time,
|
|
||||||
),
|
|
||||||
// A key made of multiple keycodes
|
|
||||||
// has to submit them one after the other.
|
|
||||||
_ => {
|
|
||||||
self.virtual_keyboard.switch(
|
|
||||||
keycode.clone(),
|
|
||||||
PressType::Pressed,
|
|
||||||
time,
|
|
||||||
);
|
|
||||||
self.virtual_keyboard.switch(
|
|
||||||
keycode.clone(),
|
|
||||||
PressType::Released,
|
|
||||||
time,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
SubmittedAction::VirtualKeyboard(keycodes.clone())
|
SubmittedAction::VirtualKeyboard(keycodes.clone())
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -215,21 +194,11 @@ impl Submission {
|
|||||||
// no matter if the imservice got activated,
|
// no matter if the imservice got activated,
|
||||||
// keys must be released
|
// keys must be released
|
||||||
SubmittedAction::VirtualKeyboard(keycodes) => {
|
SubmittedAction::VirtualKeyboard(keycodes) => {
|
||||||
let keycodes_count = keycodes.len();
|
self.virtual_keyboard.switch(
|
||||||
match keycodes_count {
|
&keycodes,
|
||||||
1 => {
|
PressType::Released,
|
||||||
let keycode = &keycodes[0];
|
time,
|
||||||
self.select_keymap(keycode.keymap_idx, time);
|
)
|
||||||
self.virtual_keyboard.switch(
|
|
||||||
keycode.code,
|
|
||||||
PressType::Released,
|
|
||||||
time,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
// Design choice here: submit multiple all at press time
|
|
||||||
// and do nothing at release time.
|
|
||||||
_ => {},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -274,64 +243,4 @@ impl Submission {
|
|||||||
self.modifiers_active.iter().map(|(_id, m)| m.clone())
|
self.modifiers_active.iter().map(|(_id, m)| m.clone())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_all_modifiers(&mut self) {
|
|
||||||
// Looks like an optimization,
|
|
||||||
// but preemptive cleaning is needed before setting a new keymap,
|
|
||||||
// so removing this check would break keymap setting.
|
|
||||||
if self.modifiers_active.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.modifiers_active = Vec::new();
|
|
||||||
self.virtual_keyboard.set_modifiers_state(Modifiers::empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn release_all_virtual_keys(&mut self, time: Timestamp) {
|
|
||||||
let virtual_pressed = self.pressed
|
|
||||||
.clone().into_iter()
|
|
||||||
.filter_map(|(id, action)| {
|
|
||||||
match action {
|
|
||||||
SubmittedAction::VirtualKeyboard(_) => Some(id),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for id in virtual_pressed {
|
|
||||||
self.handle_release(id, time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Changes keymap and clears pressed keys and modifiers.
|
|
||||||
///
|
|
||||||
/// It's not obvious if clearing is the right thing to do,
|
|
||||||
/// but keymap update may (or may not) do that,
|
|
||||||
/// possibly putting self.modifiers_active and self.pressed out of sync,
|
|
||||||
/// so a consistent stance is adopted to avoid that.
|
|
||||||
/// Alternatively, modifiers could be restored on the new keymap.
|
|
||||||
/// That approach might be difficult
|
|
||||||
/// due to modifiers meaning different things in different keymaps.
|
|
||||||
fn select_keymap(&mut self, idx: usize, time: Timestamp) {
|
|
||||||
if self.keymap_idx != Some(idx) {
|
|
||||||
self.keymap_idx = Some(idx);
|
|
||||||
self.clear_all_modifiers();
|
|
||||||
self.release_all_virtual_keys(time);
|
|
||||||
let keymap = &self.keymap_fds[idx];
|
|
||||||
self.virtual_keyboard.update_keymap(keymap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn use_layout(&mut self, layout: &layout::Layout, time: Timestamp) {
|
|
||||||
self.keymap_fds = layout.keymaps.iter()
|
|
||||||
.map(|keymap_str| vkeyboard::c::KeyMap::from_cstr(
|
|
||||||
keymap_str.as_c_str()
|
|
||||||
))
|
|
||||||
.collect();
|
|
||||||
self.keymap_idx = None;
|
|
||||||
|
|
||||||
// This can probably be eliminated,
|
|
||||||
// because key presses can trigger an update anyway.
|
|
||||||
// However, self.keymap_idx needs to become Option<>
|
|
||||||
// in order to force update on new layouts.
|
|
||||||
self.select_keymap(0, time);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
103
src/tests.rs
103
src/tests.rs
@ -26,104 +26,49 @@ impl CountAndPrint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_builtin_layout(name: &str, missing_return: bool) {
|
pub fn check_builtin_layout(name: &str) {
|
||||||
check_layout(
|
check_layout(Layout::from_resource(name).expect("Invalid layout data"))
|
||||||
Layout::from_resource(name).expect("Invalid layout data"),
|
|
||||||
missing_return,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_layout_file(path: &str) {
|
pub fn check_layout_file(path: &str) {
|
||||||
check_layout(
|
check_layout(Layout::from_file(path.into()).expect("Invalid layout file"))
|
||||||
Layout::from_file(path.into()).expect("Invalid layout file"),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_sym_in_keymap(state: &xkb::State, sym_name: &str) -> bool {
|
fn check_layout(layout: Layout) {
|
||||||
let sym = xkb::keysym_from_name(sym_name, xkb::KEYSYM_NO_FLAGS);
|
|
||||||
if sym == xkb::KEY_NoSymbol {
|
|
||||||
panic!(format!("Entered invalid keysym: {}", sym_name));
|
|
||||||
}
|
|
||||||
let map = state.get_keymap();
|
|
||||||
let range = map.min_keycode()..=map.max_keycode();
|
|
||||||
range.flat_map(|code| state.key_get_syms(code))
|
|
||||||
.find(|s| **s == sym)
|
|
||||||
.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_sym_presence(
|
|
||||||
states: &[xkb::State],
|
|
||||||
sym_name: &str,
|
|
||||||
handler: &mut dyn logging::Handler,
|
|
||||||
) {
|
|
||||||
let found = states.iter()
|
|
||||||
.position(|state| {
|
|
||||||
check_sym_in_keymap(&state, sym_name)
|
|
||||||
});
|
|
||||||
|
|
||||||
if let None = found {
|
|
||||||
handler.handle(
|
|
||||||
logging::Level::Surprise,
|
|
||||||
&format!("There's no way to input the keysym {} on this layout", sym_name),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_layout(layout: Layout, allow_missing_return: bool) {
|
|
||||||
let handler = CountAndPrint::new();
|
let handler = CountAndPrint::new();
|
||||||
let (layout, mut handler) = layout.build(handler);
|
let (layout, handler) = layout.build(handler);
|
||||||
|
|
||||||
if handler.0 > 0 {
|
if handler.0 > 0 {
|
||||||
println!("{} problems while parsing layout", handler.0)
|
println!("{} problems while parsing layout", handler.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = layout.expect("layout broken");
|
let layout = layout.expect("layout broken");
|
||||||
|
|
||||||
|
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
let xkb_states: Vec<xkb::State> = layout.keymaps.iter()
|
let keymap_str = layout.keymap_str
|
||||||
.map(|keymap_str| {
|
.clone()
|
||||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
.into_string().expect("Failed to decode keymap string");
|
||||||
let keymap_str = keymap_str
|
|
||||||
.clone()
|
let keymap = xkb::Keymap::new_from_string(
|
||||||
.into_string().expect("Failed to decode keymap string");
|
&context,
|
||||||
let keymap = xkb::Keymap::new_from_string(
|
keymap_str.clone(),
|
||||||
&context,
|
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||||
keymap_str.clone(),
|
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
).expect("Failed to create keymap");
|
||||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
|
||||||
).expect("Failed to create keymap");
|
|
||||||
xkb::State::new(&keymap)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
check_sym_presence(&xkb_states, "BackSpace", &mut handler);
|
|
||||||
let mut printer = logging::Print;
|
|
||||||
check_sym_presence(
|
|
||||||
&xkb_states,
|
|
||||||
"Return",
|
|
||||||
if allow_missing_return { &mut printer }
|
|
||||||
else { &mut handler },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
let state = xkb::State::new(&keymap);
|
||||||
|
|
||||||
// "Press" each button with keysyms
|
// "Press" each button with keysyms
|
||||||
for (_pos, view) in layout.views.values() {
|
for (_pos, view) in layout.views.values() {
|
||||||
for (_y, row) in view.get_rows() {
|
for (_y, row) in &view.get_rows() {
|
||||||
for (_x, button) in row.get_buttons() {
|
for (_x, button) in &row.buttons {
|
||||||
let keystate = button.state.borrow();
|
let keystate = button.state.borrow();
|
||||||
for keycode in &keystate.keycodes {
|
for keycode in &keystate.keycodes {
|
||||||
match xkb_states[keycode.keymap_idx].key_get_one_sym(keycode.code) {
|
match state.key_get_one_sym(*keycode) {
|
||||||
xkb::KEY_NoSymbol => {
|
xkb::KEY_NoSymbol => {
|
||||||
eprintln!(
|
eprintln!("{}", keymap_str);
|
||||||
"keymap {}: {}",
|
panic!("Keysym {} on key {:?} can't be resolved", keycode, button.name);
|
||||||
keycode.keymap_idx,
|
|
||||||
layout.keymaps[keycode.keymap_idx].to_str().unwrap(),
|
|
||||||
);
|
|
||||||
panic!(
|
|
||||||
"Keysym for code {:?} on key {} ({:?}) can't be resolved",
|
|
||||||
keycode,
|
|
||||||
button.name.to_string_lossy(),
|
|
||||||
button.name,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/ui_manager.c
Normal file
8
src/ui_manager.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "eek/layersurface.h"
|
||||||
|
|
||||||
|
void squeek_manager_set_surface_height(PhoshLayerSurface *surface, uint32_t desired_height) {
|
||||||
|
phosh_layer_surface_set_size(surface, 0,
|
||||||
|
(gint)desired_height);
|
||||||
|
phosh_layer_surface_set_exclusive_zone(surface, (gint)desired_height);
|
||||||
|
phosh_layer_surface_wl_surface_commit (surface);
|
||||||
|
}
|
||||||
@ -2,19 +2,14 @@
|
|||||||
#define UI_MANAGER__
|
#define UI_MANAGER__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "eek/layersurface.h"
|
||||||
#include "eek/eek-types.h"
|
|
||||||
#include "outputs.h"
|
#include "outputs.h"
|
||||||
|
|
||||||
struct ui_manager;
|
struct ui_manager;
|
||||||
|
|
||||||
struct ui_manager *squeek_uiman_new(void);
|
struct ui_manager *squeek_uiman_new(struct squeek_outputs *outputs);
|
||||||
void squeek_uiman_set_output(struct ui_manager *uiman, struct squeek_output_handle output);
|
void squeek_uiman_set_output(struct ui_manager *uiman, struct squeek_output_handle output);
|
||||||
|
void squeek_uiman_set_surface(struct ui_manager *uiman, PhoshLayerSurface *surface);
|
||||||
uint32_t squeek_uiman_get_perceptual_height(struct ui_manager *uiman);
|
uint32_t squeek_uiman_get_perceptual_height(struct ui_manager *uiman);
|
||||||
|
|
||||||
struct vis_manager;
|
|
||||||
|
|
||||||
struct vis_manager *squeek_visman_new(void);
|
|
||||||
void squeek_visman_set_ui(struct vis_manager *visman, ServerContextService *ui_context);
|
|
||||||
void squeek_visman_set_keyboard_present(struct vis_manager *visman, uint32_t keyboard_present);
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,57 +7,48 @@
|
|||||||
* Coordinates this based on information collated from all possible sources.
|
* Coordinates this based on information collated from all possible sources.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use ::logging;
|
||||||
|
use ::outputs::{ OutputId, Outputs, OutputState};
|
||||||
use ::outputs::c::OutputHandle;
|
use ::outputs::c::OutputHandle;
|
||||||
|
|
||||||
pub mod c {
|
// Traits
|
||||||
|
use ::logging::Warn;
|
||||||
|
|
||||||
|
mod c {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
use ::outputs::c::COutputs;
|
||||||
use ::util::c::Wrapped;
|
use ::util::c::Wrapped;
|
||||||
|
|
||||||
/// ServerContextService*
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct UIManager(*const c_void);
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PhoshLayerSurface(*const c_void);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn server_context_service_update_visible(imservice: *const UIManager, active: u32);
|
// Rustc wrongly assumes
|
||||||
pub fn server_context_service_release_visibility(imservice: *const UIManager);
|
// that COutputs allows C direct access to the underlying RefCell.
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
|
pub fn squeek_manager_set_surface_height(
|
||||||
|
surface: PhoshLayerSurface,
|
||||||
|
height: u32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn squeek_visman_new() -> Wrapped<VisibilityManager> {
|
fn squeek_uiman_new(outputs: COutputs) -> Wrapped<Manager> {
|
||||||
Wrapped::new(VisibilityManager {
|
let uiman_raw = Wrapped::new(Manager::new());
|
||||||
ui_manager: None,
|
if !outputs.is_null() {
|
||||||
visibility_state: VisibilityFactors {
|
let uiman = uiman_raw.clone_ref();
|
||||||
im_active: false,
|
let outputs = outputs.clone_ref();
|
||||||
physical_keyboard_present: false,
|
let mut outputs = outputs.borrow_mut();
|
||||||
}
|
register_output_man(uiman, &mut outputs);
|
||||||
})
|
}
|
||||||
}
|
uiman_raw
|
||||||
|
|
||||||
/// Use to initialize the UI reference
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C"
|
|
||||||
fn squeek_visman_set_ui(visman: Wrapped<VisibilityManager>, ui_manager: *const UIManager) {
|
|
||||||
let visman = visman.clone_ref();
|
|
||||||
let mut visman = visman.borrow_mut();
|
|
||||||
visman.set_ui_manager(Some(ui_manager))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C"
|
|
||||||
fn squeek_visman_set_keyboard_present(visman: Wrapped<VisibilityManager>, present: u32) {
|
|
||||||
let visman = visman.clone_ref();
|
|
||||||
let mut visman = visman.borrow_mut();
|
|
||||||
visman.set_keyboard_present(present != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C"
|
|
||||||
fn squeek_uiman_new() -> Wrapped<Manager> {
|
|
||||||
Wrapped::new(Manager { output: None })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to size the layer surface containing all the OSK widgets.
|
/// Used to size the layer surface containing all the OSK widgets.
|
||||||
@ -69,7 +60,7 @@ pub mod c {
|
|||||||
let uiman = uiman.clone_ref();
|
let uiman = uiman.clone_ref();
|
||||||
let uiman = uiman.borrow();
|
let uiman = uiman.borrow();
|
||||||
// TODO: what to do when there's no output?
|
// TODO: what to do when there's no output?
|
||||||
uiman.get_perceptual_height().unwrap_or(0)
|
uiman.state.get_perceptual_height().unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -80,29 +71,75 @@ pub mod c {
|
|||||||
) {
|
) {
|
||||||
let uiman = uiman.clone_ref();
|
let uiman = uiman.clone_ref();
|
||||||
let mut uiman = uiman.borrow_mut();
|
let mut uiman = uiman.borrow_mut();
|
||||||
uiman.output = Some(output);
|
uiman.set_output(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C"
|
||||||
|
fn squeek_uiman_set_surface(
|
||||||
|
uiman: Wrapped<Manager>,
|
||||||
|
surface: PhoshLayerSurface,
|
||||||
|
) {
|
||||||
|
let uiman = uiman.clone_ref();
|
||||||
|
let mut uiman = uiman.borrow_mut();
|
||||||
|
// Surface is not state, so doesn't need to propagate updates.
|
||||||
|
uiman.surface = Some(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores current state of all things influencing what the UI should look like.
|
/// Stores current state of all things influencing what the UI should look like.
|
||||||
pub struct Manager {
|
#[derive(Clone, PartialEq)]
|
||||||
/// Shared output handle, current state updated whenever it's needed.
|
pub struct ManagerState {
|
||||||
// TODO: Stop assuming that the output never changes.
|
current_output: Option<(OutputId, OutputState)>,
|
||||||
// (There's no way for the output manager to update the ui manager.)
|
|
||||||
// FIXME: Turn into an OutputState and apply relevant connections elsewhere.
|
|
||||||
// Otherwise testability and predictablity is low.
|
|
||||||
output: Option<OutputHandle>,
|
|
||||||
//// Pixel size of the surface. Needs explicit updating.
|
//// Pixel size of the surface. Needs explicit updating.
|
||||||
//surface_size: Option<Size>,
|
//surface_size: Option<Size>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl ManagerState {
|
||||||
|
/// The largest ideal heigth for the keyboard as a whole
|
||||||
|
/// judged by the ease of hitting targets within.
|
||||||
|
/// Ideally related to finger size, the crammedness of the layout,
|
||||||
|
/// distance from display, and motor skills of the user.
|
||||||
|
// FIXME: Start by making this aware of display's dpi,
|
||||||
|
// then layout number of rows.
|
||||||
|
fn get_max_target_height(output: &OutputState) -> u32 {
|
||||||
|
let layout_rows = 4; // FIXME: use number from layout.
|
||||||
|
let px_size = output.get_pixel_size();
|
||||||
|
let phys_size = output.get_phys_size();
|
||||||
|
|
||||||
|
let finger_height_px = match (px_size, phys_size) {
|
||||||
|
(Some(px_size), Some(phys_size)) => {
|
||||||
|
// Fudged to result in 420px from the original design.
|
||||||
|
// That gives about 9.5mm per finger height.
|
||||||
|
// Maybe floats are not the best choice here,
|
||||||
|
// but it gets rounded ASAP. Consider rationals.
|
||||||
|
let keyboard_fraction_of_display: f64 = 420. / 1440.;
|
||||||
|
let keyboard_mm = keyboard_fraction_of_display * 130.;
|
||||||
|
let finger_height_mm = keyboard_mm / 4.;
|
||||||
|
// TODO: Take into account target shape/area, not just height.
|
||||||
|
finger_height_mm * px_size.height as f64 / phys_size.height as f64
|
||||||
|
},
|
||||||
|
(_, None) => output.scale as f64 * 52.5, // match total 420px at scale 2 from original design
|
||||||
|
(None, Some(_)) => {
|
||||||
|
log_print!(
|
||||||
|
logging::Level::Surprise,
|
||||||
|
"Output has physical size data but no pixel info",
|
||||||
|
);
|
||||||
|
output.scale as f64 * 52.5
|
||||||
|
},
|
||||||
|
};
|
||||||
|
(layout_rows as f64 * finger_height_px) as u32
|
||||||
|
}
|
||||||
|
|
||||||
fn get_perceptual_height(&self) -> Option<u32> {
|
fn get_perceptual_height(&self) -> Option<u32> {
|
||||||
let output_info = (&self.output).as_ref()
|
let output_info = (&self.current_output).as_ref()
|
||||||
.and_then(|o| o.get_state())
|
.map(|(_id, os)| (
|
||||||
.map(|os| (os.scale as u32, os.get_pixel_size()));
|
os.scale as u32,
|
||||||
|
os.get_pixel_size(),
|
||||||
|
ManagerState::get_max_target_height(&os),
|
||||||
|
));
|
||||||
match output_info {
|
match output_info {
|
||||||
Some((scale, Some(px_size))) => Some({
|
Some((scale, Some(px_size), target_height)) => Some({
|
||||||
let height = if (px_size.width < 720) & (px_size.width > 0) {
|
let height = if (px_size.width < 720) & (px_size.width > 0) {
|
||||||
px_size.width * 7 / 12 // to match 360×210
|
px_size.width * 7 / 12 // to match 360×210
|
||||||
} else if px_size.width < 1080 {
|
} else if px_size.width < 1080 {
|
||||||
@ -111,139 +148,94 @@ impl Manager {
|
|||||||
360
|
360
|
||||||
};
|
};
|
||||||
|
|
||||||
// Don't exceed half the display size
|
// Don't exceed half the display size.
|
||||||
min(height, px_size.height / 2) / scale
|
let height = min(height, px_size.height / 2);
|
||||||
|
// Don't waste screen space by exceeding best target height.
|
||||||
|
let height = min(height, target_height);
|
||||||
|
height / scale
|
||||||
}),
|
}),
|
||||||
Some((scale, None)) => Some(360 / scale),
|
Some((scale, None, _)) => Some(360 / scale),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
pub struct Manager {
|
||||||
enum Visibility {
|
state: ManagerState,
|
||||||
Hidden,
|
surface: Option<c::PhoshLayerSurface>,
|
||||||
Visible,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl Manager {
|
||||||
enum VisibilityTransition {
|
fn new() -> Manager {
|
||||||
/// Hide immediately
|
Manager {
|
||||||
Hide,
|
state: ManagerState { current_output: None, },
|
||||||
/// Hide if no show request comes soon
|
surface: None,
|
||||||
Release,
|
|
||||||
/// Show instantly
|
|
||||||
Show,
|
|
||||||
/// Don't do anything
|
|
||||||
NoTransition,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Contains visibility policy
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct VisibilityFactors {
|
|
||||||
im_active: bool,
|
|
||||||
physical_keyboard_present: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VisibilityFactors {
|
|
||||||
/// Static policy.
|
|
||||||
/// Use when transitioning from an undefined state (e.g. no UI before).
|
|
||||||
fn desired(&self) -> Visibility {
|
|
||||||
match self {
|
|
||||||
VisibilityFactors {
|
|
||||||
im_active: true,
|
|
||||||
physical_keyboard_present: false,
|
|
||||||
} => Visibility::Visible,
|
|
||||||
_ => Visibility::Hidden,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Stateful policy
|
fn set_output(&mut self, output: OutputHandle) {
|
||||||
fn transition_to(&self, next: &Self) -> VisibilityTransition {
|
let output_state = output.get_state()
|
||||||
use self::Visibility::*;
|
.or_warn(
|
||||||
let im_deactivation = self.im_active && !next.im_active;
|
&mut logging::Print,
|
||||||
match (self.desired(), next.desired(), im_deactivation) {
|
logging::Problem::Bug,
|
||||||
(Visible, Hidden, true) => VisibilityTransition::Release,
|
// This is really bad. It only happens when the layer surface
|
||||||
(Visible, Hidden, _) => VisibilityTransition::Hide,
|
// is placed, and it happens once.
|
||||||
(Hidden, Visible, _) => VisibilityTransition::Show,
|
// The layer surface is on an output that can't be tracked.
|
||||||
_ => VisibilityTransition::NoTransition,
|
"Tried to set output that's not known to exist. Ignoring.",
|
||||||
}
|
);
|
||||||
|
self.state.current_output = output_state.map(
|
||||||
|
|state| (output.get_id(), state)
|
||||||
|
);
|
||||||
|
// TODO: At the time of writing, this function is only used once,
|
||||||
|
// before the layer surface is initialized.
|
||||||
|
// Therefore it doesn't update anything. Maybe it should in the future,
|
||||||
|
// if it sees more use.
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Temporary struct for migration. Should be integrated with Manager eventually.
|
fn handle_output_change(&mut self, output: OutputHandle) {
|
||||||
pub struct VisibilityManager {
|
let (id, output_state) = match &self.state.current_output {
|
||||||
/// Owned reference. Be careful, it's shared with C at large
|
Some((id, state)) => {
|
||||||
ui_manager: Option<*const c::UIManager>,
|
if *id != output.get_id() { return } // Not the current output.
|
||||||
visibility_state: VisibilityFactors,
|
else { (id.clone(), state.clone()) }
|
||||||
}
|
},
|
||||||
|
None => return, // Keyboard isn't on any output.
|
||||||
impl VisibilityManager {
|
|
||||||
fn set_ui_manager(&mut self, ui_manager: Option<*const c::UIManager>) {
|
|
||||||
let new = VisibilityManager {
|
|
||||||
ui_manager,
|
|
||||||
..unsafe { self.clone() }
|
|
||||||
};
|
};
|
||||||
self.apply_changes(new);
|
if let Some(new_output_state) = output.get_state() {
|
||||||
}
|
if new_output_state != output_state {
|
||||||
|
let new_state = ManagerState {
|
||||||
fn apply_changes(&mut self, new: Self) {
|
current_output: Some((id.clone(), new_output_state)),
|
||||||
if let Some(ui) = &new.ui_manager {
|
..self.state.clone()
|
||||||
if self.ui_manager.is_none() {
|
};
|
||||||
// Previous state was never applied, so effectively undefined.
|
if let Some(surface) = &self.surface {
|
||||||
// Just apply the new one.
|
let new_height = new_state.get_perceptual_height();
|
||||||
let new_state = new.visibility_state.desired();
|
if new_height != self.state.get_perceptual_height() {
|
||||||
unsafe {
|
// TODO: here hard-size the keyboard and suggestion box too.
|
||||||
c::server_context_service_update_visible(
|
match new_height {
|
||||||
*ui,
|
Some(new_height) => unsafe {
|
||||||
(new_state == Visibility::Visible) as u32,
|
c::squeek_manager_set_surface_height(
|
||||||
);
|
*surface,
|
||||||
}
|
new_height,
|
||||||
} else {
|
)
|
||||||
match self.visibility_state.transition_to(&new.visibility_state) {
|
}
|
||||||
VisibilityTransition::Hide => unsafe {
|
None => log_print!(
|
||||||
c::server_context_service_update_visible(*ui, 0);
|
logging::Level::Bug,
|
||||||
},
|
"Can't calculate new size",
|
||||||
VisibilityTransition::Show => unsafe {
|
),
|
||||||
c::server_context_service_update_visible(*ui, 1);
|
}
|
||||||
},
|
}
|
||||||
VisibilityTransition::Release => unsafe {
|
|
||||||
c::server_context_service_release_visibility(*ui);
|
|
||||||
},
|
|
||||||
VisibilityTransition::NoTransition => {}
|
|
||||||
}
|
}
|
||||||
|
self.state = new_state;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
*self = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_im_active(&mut self, im_active: bool) {
|
|
||||||
let new = VisibilityManager {
|
|
||||||
visibility_state: VisibilityFactors {
|
|
||||||
im_active,
|
|
||||||
..self.visibility_state.clone()
|
|
||||||
},
|
|
||||||
..unsafe { self.clone() }
|
|
||||||
};
|
};
|
||||||
self.apply_changes(new);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_keyboard_present(&mut self, keyboard_present: bool) {
|
|
||||||
let new = VisibilityManager {
|
|
||||||
visibility_state: VisibilityFactors {
|
|
||||||
physical_keyboard_present: keyboard_present,
|
|
||||||
..self.visibility_state.clone()
|
|
||||||
},
|
|
||||||
..unsafe { self.clone() }
|
|
||||||
};
|
|
||||||
self.apply_changes(new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The struct is not really safe to clone due to the ui_manager reference.
|
|
||||||
/// This is only a helper for getting desired visibility.
|
|
||||||
unsafe fn clone(&self) -> Self {
|
|
||||||
VisibilityManager {
|
|
||||||
ui_manager: self.ui_manager.clone(),
|
|
||||||
visibility_state: self.visibility_state.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_output_man(
|
||||||
|
ui_man: Rc<RefCell<Manager>>,
|
||||||
|
output_man: &mut Outputs,
|
||||||
|
) {
|
||||||
|
let ui_man = ui_man.clone();
|
||||||
|
output_man.set_update_cb(Box::new(move |output: OutputHandle| {
|
||||||
|
let mut ui_man = ui_man.borrow_mut();
|
||||||
|
ui_man.handle_output_change(output)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|||||||
30
src/util.rs
30
src/util.rs
@ -94,6 +94,7 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
/// Extracts the reference to the data.
|
/// Extracts the reference to the data.
|
||||||
/// It may cause problems if attempted in more than one place
|
/// It may cause problems if attempted in more than one place
|
||||||
|
// FIXME: check for null
|
||||||
pub unsafe fn unwrap(self) -> Rc<RefCell<T>> {
|
pub unsafe fn unwrap(self) -> Rc<RefCell<T>> {
|
||||||
Rc::from_raw(self.0)
|
Rc::from_raw(self.0)
|
||||||
}
|
}
|
||||||
@ -107,6 +108,10 @@ pub mod c {
|
|||||||
Rc::into_raw(used_rc); // prevent dropping the original reference
|
Rc::into_raw(used_rc); // prevent dropping the original reference
|
||||||
rc
|
rc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_null(&self) -> bool {
|
||||||
|
self.0.is_null()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for Wrapped<T> {
|
impl<T> Clone for Wrapped<T> {
|
||||||
@ -203,23 +208,6 @@ pub fn vec_remove<T, F: FnMut(&T) -> bool>(v: &mut Vec<T>, pred: F) -> Option<T>
|
|||||||
idx.map(|idx| v.remove(idx))
|
idx.map(|idx| v.remove(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Repeats all the items of the iterator forever,
|
|
||||||
/// but returns the cycle number alongside.
|
|
||||||
/// Inefficient due to all the vectors, but doesn't have to be fast.
|
|
||||||
pub fn cycle_count<T, I: Clone + Iterator<Item=T>>(iter: I)
|
|
||||||
-> impl Iterator<Item=(T, usize)>
|
|
||||||
{
|
|
||||||
let numbered_copies = vec![iter].into_iter()
|
|
||||||
.cycle()
|
|
||||||
.enumerate();
|
|
||||||
numbered_copies.flat_map(|(idx, cycle)|
|
|
||||||
// Pair each element from the cycle with a copy of the index.
|
|
||||||
cycle.zip(
|
|
||||||
vec![idx].into_iter().cycle() // Repeat the index forever.
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -234,12 +222,4 @@ mod tests {
|
|||||||
assert_eq!(s.insert(Pointer(Rc::new(2u32))), true);
|
assert_eq!(s.insert(Pointer(Rc::new(2u32))), true);
|
||||||
assert_eq!(s.remove(&Pointer(first)), true);
|
assert_eq!(s.remove(&Pointer(first)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_count() {
|
|
||||||
assert_eq!(
|
|
||||||
cycle_count(5..8).take(7).collect::<Vec<_>>(),
|
|
||||||
vec![(5, 0), (6, 0), (7, 0), (5, 1), (6, 1), (7, 1), (5, 2)]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,47 +1,20 @@
|
|||||||
/*! Managing the events belonging to virtual-keyboard interface. */
|
/*! Managing the events belonging to virtual-keyboard interface. */
|
||||||
|
|
||||||
use ::keyboard::{ Modifiers, PressType };
|
use ::keyboard::{ KeyCode, Modifiers, PressType };
|
||||||
|
use ::layout::c::LevelKeyboard;
|
||||||
use ::submission::Timestamp;
|
use ::submission::Timestamp;
|
||||||
|
|
||||||
/// Standard xkb keycode
|
|
||||||
type KeyCode = u32;
|
|
||||||
|
|
||||||
/// Gathers stuff defined in C or called by C
|
/// Gathers stuff defined in C or called by C
|
||||||
pub mod c {
|
pub mod c {
|
||||||
use std::ffi::CStr;
|
use super::*;
|
||||||
use std::os::raw::{ c_char, c_void };
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct ZwpVirtualKeyboardV1(*const c_void);
|
pub struct ZwpVirtualKeyboardV1(*const c_void);
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct KeyMap {
|
|
||||||
fd: u32,
|
|
||||||
fd_len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyMap {
|
|
||||||
pub fn from_cstr(s: &CStr) -> KeyMap {
|
|
||||||
unsafe {
|
|
||||||
squeek_key_map_from_str(s.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for KeyMap {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
close(self.fd as u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// From libc, to let KeyMap get deallocated.
|
|
||||||
fn close(fd: u32);
|
|
||||||
|
|
||||||
pub fn eek_virtual_keyboard_v1_key(
|
pub fn eek_virtual_keyboard_v1_key(
|
||||||
virtual_keyboard: ZwpVirtualKeyboardV1,
|
virtual_keyboard: ZwpVirtualKeyboardV1,
|
||||||
timestamp: u32,
|
timestamp: u32,
|
||||||
@ -51,15 +24,13 @@ pub mod c {
|
|||||||
|
|
||||||
pub fn eek_virtual_keyboard_update_keymap(
|
pub fn eek_virtual_keyboard_update_keymap(
|
||||||
virtual_keyboard: ZwpVirtualKeyboardV1,
|
virtual_keyboard: ZwpVirtualKeyboardV1,
|
||||||
keymap: *const KeyMap,
|
keyboard: LevelKeyboard,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn eek_virtual_keyboard_set_modifiers(
|
pub fn eek_virtual_keyboard_set_modifiers(
|
||||||
virtual_keyboard: ZwpVirtualKeyboardV1,
|
virtual_keyboard: ZwpVirtualKeyboardV1,
|
||||||
modifiers: u32,
|
modifiers: u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn squeek_key_map_from_str(keymap_str: *const c_char) -> KeyMap;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,15 +41,35 @@ impl VirtualKeyboard {
|
|||||||
// TODO: error out if keymap not set
|
// TODO: error out if keymap not set
|
||||||
pub fn switch(
|
pub fn switch(
|
||||||
&self,
|
&self,
|
||||||
keycode: KeyCode,
|
keycodes: &Vec<KeyCode>,
|
||||||
action: PressType,
|
action: PressType,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
) {
|
) {
|
||||||
let keycode = keycode - 8;
|
let keycodes_count = keycodes.len();
|
||||||
unsafe {
|
for keycode in keycodes.iter() {
|
||||||
c::eek_virtual_keyboard_v1_key(
|
let keycode = keycode - 8;
|
||||||
self.0, timestamp.0, keycode, action.clone() as u32
|
match (action, keycodes_count) {
|
||||||
);
|
// Pressing a key made out of a single keycode is simple:
|
||||||
|
// press on press, release on release.
|
||||||
|
(_, 1) => unsafe {
|
||||||
|
c::eek_virtual_keyboard_v1_key(
|
||||||
|
self.0, timestamp.0, keycode, action.clone() as u32
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// A key made of multiple keycodes
|
||||||
|
// has to submit them one after the other
|
||||||
|
(PressType::Pressed, _) => unsafe {
|
||||||
|
c::eek_virtual_keyboard_v1_key(
|
||||||
|
self.0, timestamp.0, keycode, PressType::Pressed as u32
|
||||||
|
);
|
||||||
|
c::eek_virtual_keyboard_v1_key(
|
||||||
|
self.0, timestamp.0, keycode, PressType::Released as u32
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// Design choice here: submit multiple all at press time
|
||||||
|
// and do nothing at release time
|
||||||
|
(PressType::Released, _) => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,12 +80,9 @@ impl VirtualKeyboard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_keymap(&self, keymap: &c::KeyMap) {
|
pub fn update_keymap(&self, keyboard: LevelKeyboard) {
|
||||||
unsafe {
|
unsafe {
|
||||||
c::eek_virtual_keyboard_update_keymap(
|
c::eek_virtual_keyboard_update_keymap(self.0, keyboard);
|
||||||
self.0,
|
|
||||||
keymap as *const c::KeyMap,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,10 +14,10 @@ eek_virtual_keyboard_v1_key(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void eek_virtual_keyboard_update_keymap(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, struct keymap *keymap) {
|
void eek_virtual_keyboard_update_keymap(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, const LevelKeyboard *keyboard) {
|
||||||
zwp_virtual_keyboard_v1_keymap(zwp_virtual_keyboard_v1,
|
zwp_virtual_keyboard_v1_keymap(zwp_virtual_keyboard_v1,
|
||||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||||
keymap->fd, keymap->fd_len);
|
keyboard->keymap_fd, keyboard->keymap_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
# Erase only
|
|
||||||
views:
|
|
||||||
base:
|
|
||||||
- "BackSpace"
|
|
||||||
outlines:
|
|
||||||
default: { width: 0, height: 0 }
|
|
||||||
buttons:
|
|
||||||
BackSpace:
|
|
||||||
action: erase
|
|
||||||
@ -48,55 +48,25 @@ endforeach
|
|||||||
# due to the way Cargo builds executables
|
# due to the way Cargo builds executables
|
||||||
# and the need to call it manually
|
# and the need to call it manually
|
||||||
foreach layout : [
|
foreach layout : [
|
||||||
'us', 'us+colemak', 'us_wide',
|
'us', 'us_wide',
|
||||||
'br',
|
|
||||||
'be', 'be_wide',
|
|
||||||
'bg',
|
|
||||||
'cz', 'cz_wide',
|
|
||||||
'cz+qwerty', 'cz+qwerty_wide',
|
|
||||||
'de', 'de_wide',
|
'de', 'de_wide',
|
||||||
'dk',
|
|
||||||
'epo',
|
|
||||||
'es',
|
'es',
|
||||||
'fi',
|
'fi',
|
||||||
'fr', 'fr_wide',
|
|
||||||
'it+fur',
|
|
||||||
'gr',
|
'gr',
|
||||||
'it',
|
'it',
|
||||||
'jp+kana','jp+kana_wide',
|
'jp+kana','jp+kana_wide',
|
||||||
'no',
|
'no',
|
||||||
'number',
|
'number',
|
||||||
'pl', 'pl_wide',
|
'pl', 'pl_wide',
|
||||||
'ru',
|
|
||||||
'se',
|
'se',
|
||||||
'ua',
|
'terminal',
|
||||||
'th',
|
|
||||||
'terminal', 'terminal_wide',
|
|
||||||
|
|
||||||
'emoji',
|
'emoji',
|
||||||
]
|
]
|
||||||
extra = []
|
|
||||||
if layout == 'emoji'
|
|
||||||
extra += ['allow_missing_return']
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Older Cargo seens to be sensitive to something
|
|
||||||
# about the RUST_FLAGS env var, and rebuilds all tests when it's set,
|
|
||||||
# increasing test time by 2 orders of magnitude.
|
|
||||||
# Let it have its way.
|
|
||||||
if get_option('legacy') == true
|
|
||||||
timeout = 300
|
|
||||||
else
|
|
||||||
timeout = 30
|
|
||||||
endif
|
|
||||||
test(
|
test(
|
||||||
'test_layout_' + layout,
|
'test_layout_' + layout,
|
||||||
cargo_script,
|
cargo_script,
|
||||||
args: ['run'] + cargo_build_flags
|
args: ['run', '--example', 'test_layout', layout]
|
||||||
+ ['--example', 'test_layout', '--', layout]
|
|
||||||
+ extra,
|
|
||||||
timeout: timeout,
|
|
||||||
workdir: meson.build_root(),
|
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,8 @@ test_layout = custom_target('squeekboard-test-layout',
|
|||||||
build_always_stale: true,
|
build_always_stale: true,
|
||||||
output: ['squeekboard-test-layout'],
|
output: ['squeekboard-test-layout'],
|
||||||
console: true,
|
console: true,
|
||||||
command: [cargo_build, '--rename', 'test_layout', '@OUTPUT@', '--bin', 'test_layout']
|
command: [cargo_build] + cargo_build_flags
|
||||||
+ cargo_build_flags,
|
+ ['--rename', 'test_layout', '@OUTPUT@', '--bin', 'test_layout'],
|
||||||
install: true,
|
install: true,
|
||||||
install_dir: bindir,
|
install_dir: bindir,
|
||||||
depends: cargo_toml,
|
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user