Compare commits

..

3 Commits

65 changed files with 1581 additions and 2474 deletions

View File

@ -14,16 +14,7 @@ before_script:
- 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 -
- apt-get -y update
build_docs:
<<: *tags
stage: build
artifacts:
paths:
- _build
script:
- apt-get -y install python3-recommonmark python3-sphinx
- ./doc/build.sh _build
- apt-get -y build-dep .
build_meson:
<<: *tags
@ -33,33 +24,16 @@ build_meson:
- _build
expire_in: 3h
script:
- apt-get -y build-dep .
- meson . _build/ -Ddepdatadir=/usr/share
- ninja -C _build install
build_deb:
tags:
- librem5
<<: *tags
stage: build
artifacts:
paths:
- "*.deb"
script:
- apt-get -y build-dep .
- apt-get -y install devscripts
- debuild -i -us -uc -b
- cp ../*.deb .
build_deb:arm64:
tags:
- librem5:arm64
allow_failure: true
stage: build
artifacts:
paths:
- "*.deb"
script:
- apt-get -y build-dep .
- apt-get -y install devscripts
- debuild -i -us -uc -b
- cp ../*.deb .
@ -79,5 +53,4 @@ test:
needs:
- build_meson
script:
- apt-get -y build-dep .
- ninja -C _build test

179
Cargo.lock generated
View File

@ -8,14 +8,6 @@ dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atk-sys"
version = "0.7.0"
@ -23,18 +15,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -51,7 +33,7 @@ dependencies = [
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -62,30 +44,16 @@ dependencies = [
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.49"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dtoa"
version = "0.4.4"
@ -111,7 +79,7 @@ dependencies = [
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -126,7 +94,7 @@ dependencies = [
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -137,8 +105,8 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -151,9 +119,9 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -168,7 +136,7 @@ dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -178,8 +146,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -191,7 +159,7 @@ dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -199,8 +167,8 @@ name = "glib-sys"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -209,8 +177,8 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -221,7 +189,7 @@ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -233,7 +201,7 @@ dependencies = [
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -249,17 +217,9 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hermit-abi"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -269,7 +229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.66"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -292,7 +252,7 @@ name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -306,7 +266,7 @@ dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -317,18 +277,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.7"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -339,7 +299,7 @@ name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -364,10 +324,6 @@ name = "rs"
version = "0.1.0"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -375,63 +331,50 @@ dependencies = [
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.104"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.104"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_yaml"
version = "0.8.11"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.13"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
@ -440,11 +383,6 @@ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
@ -455,11 +393,6 @@ name = "utf8-ranges"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
@ -484,7 +417,7 @@ name = "xkbcommon"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -498,14 +431,11 @@ dependencies = [
[metadata]
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7017e53393e713212aed7aea336b6553be4927f58c37070a56c2fe3d107e489"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd940f0d609699e343ef71c4af5f66423afbf30d666f796dabd8fd15229cf5b6"
"checksum cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d25596627380be4381247dba06c69ad05ca21b3b065bd9827e416882ac41dcd2"
"checksum cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)" = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
"checksum fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
"checksum gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc52c7244046df9d959df87289f1fc5cca23f9f850bab0c967963e2ecb83a96"
@ -519,31 +449,26 @@ dependencies = [
"checksum gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08475e4a08f27e6e2287005950114735ed61cec2cb8c1187682a5aec8c69b715"
"checksum gtk 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a6b30f194f09a17bb7ffa95c3ecdb405abd3b75ff981f831b1f6d18fe115ff"
"checksum gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d487d333a4b87072e6bf9f2e55befa0ebef01b9496c2e263c0f4a1ff3d6c04b1"
"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c2cb169402a3eb1ba034a7cc7d95b8b1c106e9be5ba4be79a5a93dc1a2795f4"
"checksum pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6eb49268e69dd0c1da5d3001a61aac08e2e9d2bfbe4ae4b19b9963c998f6453"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea"
"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -11,15 +11,6 @@ serde = { version = "1.0.*", features = ["derive"] }
serde_yaml = "0.8.*"
xkbcommon = { version = "0.4.*", features = ["wayland"] }
[dependencies.cairo-rs]
version = "0.5.*"
[dependencies.cairo-sys-rs]
version = ""
[dependencies.gdk]
version = ""
[dependencies.gio]
version = ""
features = ["v2_44"]
@ -32,6 +23,7 @@ features = ["v2_44"]
version = ""
features = ["v2_44"]
[dependencies.gtk]
version = "0.5.*"
features = ["v3_22"]

View File

@ -3,11 +3,6 @@ Hacking
This document describes the standards for modifying and maintaining the *squeekboard* project.
Sending patches
---------------
By submitting a change to this project, you agree to license it under the [GPL license version 3](./COPYING), or any later version. You also certify that your contribution fulfills the [Developer's Certificate of Origin 1.1](./dco.txt).
Development environment
-----------------------
@ -25,7 +20,7 @@ sudo apt-get -y build-dep .
```
For an explicit list of dependencies check the `Build-Depends` entry in the
[`debian/control`](./debian/control) file.
[debian/control][] file.
Testing
-------
@ -40,7 +35,7 @@ Most common testing is done in CI. Occasionally, and for each release, do perfor
Testing with an application:
```
python3 tools/entry.py
python3 tests/entry.py
```
Testing visibility:
@ -62,24 +57,6 @@ $ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb',
Coding
------
### Project structure
Rust modules should be split into 2 categories: libraries, and user interface. They differ in the way they do error handling.
Libraries should:
- not panic due to external surprises, only due to internal inconsistencies
- pass errors and surprises they can't handle to the callers instead
- not silence errors and surprises
User interface modules should:
- try to provide safe values whenever they encounter an error
- do the logging
- give libraries the ability to report errors and surprises (e.g. via giving them loggers)
### Style
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
@ -140,8 +117,6 @@ sh /source_path/cargo.sh test
### Cargo dependencies
All Cargo dependencies must be selected in the version available in PureOS, and added to the file `debian/control`. Please check with https://software.pureos.net/search_pkg?term=librust .
Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:

View File

@ -1,11 +1,18 @@
# Maintained by: Mark Müller <markmueller86@gmail.com>
---
bounds: { x: 0, y: 1, width: 360, height: 208 }
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 }
default:
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
special:
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
views:
base:

View File

@ -1,11 +1,18 @@
# Maintained by: Mark Müller <markmueller86@gmail.com>
---
bounds: { x: 0, y: 1, width: 540, height: 168 }
outlines:
default: { width: 48, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 108, height: 42 }
spaceline: { width: 216, height: 42 }
special: { width: 48, height: 42 }
default:
bounds: { x: 0, y: 0, width: 48, height: 42 }
altline:
bounds: { x: 0, y: 0, width: 81, height: 42 }
wide:
bounds: { x: 0, y: 0, width: 108, height: 42 }
spaceline:
bounds: { x: 0, y: 0, width: 216, height: 42 }
special:
bounds: { x: 0, y: 0, width: 48, height: 42 }
views:
base:

View File

@ -2,12 +2,19 @@
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
# Sep 2019
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 32, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
base:

View File

@ -1,16 +0,0 @@
---
outlines:
default: { width: 52, height: 52 }
altline: { width: 52, height: 52 }
views:
base:
- "😀 😁 😅 😂 😊 😇 🙃"
- "😍 😘 😋 😜 😎 🥳 😔"
- "😢 😭 😡 😱 🤔 😬 🙄"
- "preferences 🤨 🤓 😴 🤢 🤮 😈"
buttons:
preferences:
action: "show_prefs"
outline: "altline"
icon: "keyboard-mode-symbolic"

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 1, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
special:
bounds: { x: 0, y: 0, width: 44, height: 52 }
views:
base:

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 32, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
base:

View File

@ -1,12 +1,19 @@
# Italian layout created by Antonio Pandolfo
# 03 october 2019
---
bounds: { x: 0, y: 1, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
special:
bounds: { x: 0, y: 0, width: 44, height: 52 }
views:
base:

View File

@ -1,11 +1,18 @@
# Maintained by: Mark Müller <markmueller86@gmail.com>
---
bounds: { x: 0, y: 1, width: 360, height: 208 }
outlines:
default: { width: 62, height: 52 }
default-wide: { width: 62, height: 52 }
altline: { width: 62, height: 52 }
wide: { width: 62, height: 52 }
special: { width: 62, height: 52 }
default:
bounds: { x: 0, y: 0, width: 62, height: 52 }
default-wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 62, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
special:
bounds: { x: 0, y: 0, width: 62, height: 52 }
views:
base: # hiragana

View File

@ -1,525 +0,0 @@
# Maintained by: Mark Müller <markmueller86@gmail.com>
---
outlines:
default: { width: 62, height: 42 }
default-wide: { width: 62, height: 42 }
altline: { width: 62, height: 42 }
wide: { width: 62, height: 42 }
special: { width: 62, height: 42 }
views:
base: # hiragana
- "preferences _a ka sa BackSpace"
- "Left ta na ha Right"
- "カタカナ ma ya ra space"
- "switch2roman symbols wa punct Return"
_a:
- "preferences dummykey _a dummykey BackSpace"
- "あ い う え お"
- "ぁ ぃ ぅ ぇ ぉ" # 2 code points each
- "dummykey dummykey ゔ dummykey dummykey"
ka:
- "preferences dummykey ka dummykey BackSpace"
- "か き く け こ"
- "が ぎ ぐ げ ご"
- "ゕ dummykey dummykey ゖ dummykey"
sa:
- "preferences dummykey sa dummykey BackSpace"
- "さ し す せ そ"
- "ざ じ ず ぜ ぞ"
ta:
- "preferences dummykey ta dummykey BackSpace"
- "た ち つ て と"
- "だ ぢ づ で ど"
- "dummykey dummykey っ dummykey dummykey"
na:
- "preferences dummykey na dummykey BackSpace"
- "な に ぬ ね の"
ha:
- "preferences dummykey ha dummykey BackSpace"
- "は ひ ふ へ ほ"
- "ば び ぶ べ ぼ"
- "ぱ ぴ ぷ ぺ ぽ"
ma:
- "preferences dummykey ma dummykey BackSpace"
- "ま み む め も"
ya:
- "preferences dummykey ya dummykey BackSpace"
- "や dummykey ゆ dummykey よ"
- "ゃ dummykey ゅ dummykey ょ"
ra:
- "preferences dummykey ra dummykey BackSpace"
- "ら り る れ ろ"
wa:
- "preferences dummykey wa dummykey BackSpace"
- "わ ゐ dummykey ゑ を"
- "ゎ dummykey ん dummykey dummykey"
symbols:
- "preferences dummykey symbols dummykey BackSpace"
- "「 」 §"
- "【 】 "
- " "
punct:
- "preferences dummykey punct dummykey BackSpace"
- "。 、 ー"
- " ・ 〜 …"
- "♪ ” ゙ ゚"
#a あア かカ さサ たタ なナ はハ まマ やヤ らラ わワ
#i いイ きキ しシ ちチ にニ ひヒ みミ ※ りリ ゐヰ
#u うウ くク すス つツ ぬヌ ふフ むム ゆユ るル ※
#e えエ けケ せセ てテ ねネ へヘ めメ ※ れレ ゑヱ
#o おオ こコ そソ とト のノ ほホ もモ よヨ ろロ をヲ
# g z d b p n
#a が ガ ざ ザ だ ダ ば バ ぱ パ ん ン
#i ぎ ギ じ ジ ぢ ヂ び ビ ぴ ピ
#u ぐ グ ず ズ づ ヅ ぶ ブ ぷ プ
#e げ ゲ ぜ ゼ で デ べ ベ ぺ ペ
#o ご ゴ ぞ ゾ ど ド ぼ ボ ぽ ポ
カタカナ: # katakana
- "preferences _A KA SA BackSpace"
- "Left TA NA HA Right"
- "ひらがな MA YA RA space"
- "switch2roman SYMBOLS WA PUNCT Return"
_A:
- "preferences DUMMYKEY _A DUMMYKEY BackSpace"
- "ア イ ウ エ オ"
- "ァ ィ ゥ ェ ォ"
- "DUMMYKEY DUMMYKEY ヴ DUMMYKEY DUMMYKEY"
KA:
- "preferences DUMMYKEY KA DUMMYKEY BackSpace"
- "カ キ ク ケ コ"
- "ガ ギ グ ゲ ゴ"
- "ヵ DUMMYKEY ㇰ ヶ DUMMYKEY"
SA:
- "preferences DUMMYKEY SA DUMMYKEY BackSpace"
- "サ シ ス セ ソ"
- "ザ ジ ズ ゼ ゾ"
- "DUMMYKEY ㇱ ㇲ DUMMYKEY DUMMYKEY"
TA:
- "preferences DUMMYKEY TA DUMMYKEY BackSpace"
- "タ チ ツ テ ト"
- "ダ ヂ ヅ デ ド"
- "DUMMYKEY DUMMYKEY ッ DUMMYKEY ㇳ"
NA:
- "preferences DUMMYKEY NA DUMMYKEY BackSpace"
- "ナ ニ ヌ ネ "
- "DUMMYKEY DUMMYKEY ㇴ DUMMYKEY DUMMYKEY"
HA:
- "preferences DUMMYKEY HA DUMMYKEY BackSpace"
- "ハ ヒ フ ヘ ホ"
- "バ ビ ブ ベ ボ"
- "パ ピ プ ペ ポ"
MA:
- "preferences DUMMYKEY MA DUMMYKEY BackSpace"
- "マ ミ ム メ モ"
- "DUMMYKEY DUMMYKEY ㇺ DUMMYKEY DUMMYKEY"
YA:
- "preferences DUMMYKEY YA DUMMYKEY BackSpace"
- "ヤ DUMMYKEY ユ DUMMYKEY ヨ"
- "ャ DUMMYKEY ュ DUMMYKEY ョ"
RA:
- "preferences DUMMYKEY RA DUMMYKEY BackSpace"
- "ラ リ ル レ ロ"
- "ㇻ ㇼ ㇽ ㇾ ㇿ"
WA:
- "preferences DUMMYKEY WA DUMMYKEY BackSpace"
- "ワ ヰ DUMMYKEY ヱ ヲ"
- "ヮ ヸ ン ヹ ヺ"
# numbers view
numbers:
- "preferences 1 2 3 BackSpace"
- "Left 4 5 6 Right"
- "roman 7 8 9 space"
- "switch2kana * 0 # Return"
# Roman alphabet view
roman:
- "preferences RSYM1 ABC DEF BackSpace"
- "Left GHI JKL MNO Right"
- "ひらがな PQRS TUV WXYZ space"
- "switch2num RSYM2 RSYM3 RSYM4 Return"
RSYM1:
- "preferences dummykey RSYM1 dummykey BackSpace"
- "@ # $ § :"
- "| € ¥ £ 1"
ABC:
- "preferences dummykey ABC dummykey BackSpace"
- "A B C Ä ç"
- "a b c ä 2"
DEF:
- "preferences dummykey DEF dummykey BackSpace"
- "D E F dummykey"
- "d e f 3"
GHI:
- "preferences dummykey GHI dummykey BackSpace"
- "G H I dummykey"
- "g h i 4"
JKL:
- "preferences dummykey JKL dummykey BackSpace"
- "J K L dummykey"
- "j k l 5"
MNO:
- "preferences dummykey MNO dummykey BackSpace"
- "M N O Ö dummykey"
- "m n o ö 6"
PQRS:
- "preferences dummykey PQRS dummykey BackSpace"
- "P Q R S ß"
- "p q r s 7"
TUV:
- "preferences dummykey TUV dummykey BackSpace"
- "T U V Ü dummykey"
- "t u v ü 8"
WXYZ:
- "preferences dummykey WXYZ dummykey BackSpace"
- "W X Y Z dummykey"
- "w x y z 9"
RSYM2:
- "preferences dummykey RSYM2 dummykey BackSpace"
- "( ) ' \" ~"
- "[ ] { } _"
RSYM3:
- "preferences dummykey RSYM3 dummykey BackSpace"
- "+ - * / ="
- "< > ^ ° 0"
RSYM4:
- "preferences dummykey RSYM4 dummykey BackSpace"
- ", . ? ! ;"
- "\\ ´ ` · ¶"
buttons:
# following 4 buttons use the corresponding xkb name as keysym
BackSpace:
outline: "wide"
icon: "edit-clear-symbolic"
keysym: "BackSpace"
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
Left:
outline: "wide"
label: "←"
keysym: "Left"
Right:
outline: "wide"
label: "→"
keysym: "Right"
# special button "preferences" is handled in the code
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
# space button using text tag for ideographic space
space:
outline: "default-wide"
label: "␣"
text: " "
# switch to number view
numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
# switch to latin characters
roman:
action:
set_view: "roman"
outline: "wide"
label: "ᴀʙᴄ"
# toggle button with 3 different states
switch2roman: # switch from kana to latin characters view
action:
set_view: "roman"
outline: "wide"
label: "あᴀ₁"
switch2num: # switch from latin characters to numbers view
action:
set_view: "numbers"
outline: "wide"
label: "ぁA₁"
switch2kana: # switch from numbers to hiragana view
action:
set_view: "base"
outline: "wide"
label: "ぁᴀ1"
# Buttons for katakana and symbols
ひらがな:
action:
set_view: "base"
outline: "wide"
label: "あさ"
_a:
action:
locking:
lock_view: "_a"
unlock_view: "base"
outline: "altline"
label: "あ"
ka:
action:
locking:
lock_view: "ka"
unlock_view: "base"
outline: "altline"
label: "か"
sa:
action:
locking:
lock_view: "sa"
unlock_view: "base"
outline: "altline"
label: "さ"
ta:
action:
locking:
lock_view: "ta"
unlock_view: "base"
outline: "altline"
label: "た"
na:
action:
locking:
lock_view: "na"
unlock_view: "base"
outline: "altline"
label: "な"
ha:
action:
locking:
lock_view: "ha"
unlock_view: "base"
outline: "altline"
label: "は"
ma:
action:
locking:
lock_view: "ma"
unlock_view: "base"
outline: "altline"
label: "ま"
ya:
action:
locking:
lock_view: "ya"
unlock_view: "base"
outline: "altline"
label: "や"
ra:
action:
locking:
lock_view: "ra"
unlock_view: "base"
outline: "altline"
label: "ら"
wa:
action:
locking:
lock_view: "wa"
unlock_view: "base"
outline: "altline"
label: "わ"
dummykey:
action:
set_view: "base"
outline: "altline"
label: ""
# buttons available on different views like symbols and punct should go
# back to their corresponding view
symbols:
action:
locking:
lock_view: "symbols"
unlock_view: "base"
outline: "altline"
label: ""
punct:
action:
locking:
lock_view: "punct"
unlock_view: "base"
outline: "altline"
label: "。"
# Buttons for katakana and symbols
カタカナ:
action:
set_view: "カタカナ"
outline: "wide"
label: "アサ"
_A:
action:
locking:
lock_view: "_A"
unlock_view: "カタカナ"
outline: "altline"
label: "ア"
KA:
action:
locking:
lock_view: "KA"
unlock_view: "カタカナ"
outline: "altline"
label: "カ"
SA:
action:
locking:
lock_view: "SA"
unlock_view: "カタカナ"
outline: "altline"
label: "サ"
TA:
action:
locking:
lock_view: "TA"
unlock_view: "カタカナ"
outline: "altline"
label: "タ"
NA:
action:
locking:
lock_view: "NA"
unlock_view: "カタカナ"
outline: "altline"
label: "ナ"
HA:
action:
locking:
lock_view: "HA"
unlock_view: "カタカナ"
outline: "altline"
label: "ハ"
MA:
action:
locking:
lock_view: "MA"
unlock_view: "カタカナ"
outline: "altline"
label: "マ"
YA:
action:
locking:
lock_view: "YA"
unlock_view: "カタカナ"
outline: "altline"
label: "ヤ"
RA:
action:
locking:
lock_view: "RA"
unlock_view: "カタカナ"
outline: "altline"
label: "ラ"
WA:
action:
locking:
lock_view: "WA"
unlock_view: "カタカナ"
outline: "altline"
label: "ワ"
DUMMYKEY:
action:
set_view: "カタカナ"
outline: "altline"
label: ""
SYMBOLS:
action:
locking:
lock_view: "symbols"
unlock_view: "カタカナ"
outline: "altline"
label: ""
PUNCT:
action:
locking:
lock_view: "punct"
unlock_view: "カタカナ"
outline: "altline"
label: "。"
# Buttons for Latin charachters
RSYM1:
action:
locking:
lock_view: "RSYM1"
unlock_view: "roman"
outline: "altline"
label: "@#"
ABC:
action:
locking:
lock_view: "ABC"
unlock_view: "roman"
outline: "altline"
label: "ᴀʙᴄ"
DEF:
action:
locking:
lock_view: "DEF"
unlock_view: "roman"
outline: "altline"
label: "ᴅᴇꜰ"
GHI:
action:
locking:
lock_view: "GHI"
unlock_view: "roman"
outline: "altline"
label: "ɢʜɪ"
JKL:
action:
locking:
lock_view: "JKL"
unlock_view: "roman"
outline: "altline"
label: "ᴊᴋʟ"
MNO:
action:
locking:
lock_view: "MNO"
unlock_view: "roman"
outline: "altline"
label: "ᴍɴᴏ"
PQRS:
action:
locking:
lock_view: "PQRS"
unlock_view: "roman"
outline: "altline"
label: "ᴘǫʀs"
TUV:
action:
locking:
lock_view: "TUV"
unlock_view: "roman"
outline: "altline"
label: "ᴛᴜᴠ"
WXYZ:
action:
locking:
lock_view: "WXYZ"
unlock_view: "roman"
outline: "altline"
label: "xʏ"
RSYM2:
action:
locking:
lock_view: "RSYM2"
unlock_view: "roman"
outline: "altline"
label: "()"
RSYM3:
action:
locking:
lock_view: "RSYM3"
unlock_view: "roman"
outline: "altline"
label: "+-"
RSYM4:
action:
locking:
lock_view: "RSYM4"
unlock_view: "roman"
outline: "altline"
label: ",.?"

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 32, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
base:

View File

@ -1,9 +1,15 @@
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
outlines:
default: { width: 37.46341, height: 52 }
altline: { width: 48.39024, height: 52 }
outline7: { width: 88.97561, height: 52 }
spaceline: { width: 120.5853, height: 52 }
default:
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 120.5853, height: 52 }
views:
base:

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
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 }
default:
bounds: { x: 0, y: 0, width: 32, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
base:

View File

@ -1,159 +0,0 @@
---
outlines:
default: { width: 35.33, height: 52 }
action: { width: 59, height: 52 }
altline: { width: 52.67, height: 52 }
wide: { width: 59, height: 52 }
spaceline: { width: 140, height: 52 }
special: { width: 44, height: 52 }
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_actions space preferences 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 , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
actions:
- "F1 F2 F3 F4 F5 F6"
- "F7 F8 F9 F10 F11 F12"
- "Esc Tab Del PgUp ↑ PgDn"
- "show_letters Home End ← ↓ →"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_numbers_from_symbols:
action:
set_view: "numbers"
outline: "altline"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ABC"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
show_actions:
action:
set_view: "actions"
outline: "altline"
label: ">_"
period:
outline: "special"
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"
Tab:
outline: "action"
keysym: "Tab"
Del:
outline: "action"
keysym: "Delete"
Home:
outline: "action"
keysym: "Home"
End:
outline: "action"
keysym: "End"
PgUp:
outline: "action"
keysym: "Page_Up"
PgDn:
outline: "action"
keysym: "Page_Down"
"↑":
outline: "action"
keysym: "Up"
"↓":
outline: "action"
keysym: "Down"
"←":
outline: "action"
keysym: "Left"
"→":
outline: "action"
keysym: "Right"

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 1, width: 360, height: 208 }
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 }
default:
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
wide:
bounds: { x: 0, y: 0, width: 62, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 142, height: 52 }
special:
bounds: { x: 0, y: 0, width: 44, height: 52 }
views:
base:

View File

@ -1,10 +1,17 @@
---
bounds: { x: 0, y: 1, width: 540, height: 168 }
outlines:
default: { width: 54, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 108, height: 42 }
spaceline: { width: 216, height: 42 }
special: { width: 54, height: 42 }
default:
bounds: { x: 0, y: 0, width: 54, height: 42 }
altline:
bounds: { x: 0, y: 0, width: 81, height: 42 }
wide:
bounds: { x: 0, y: 0, width: 108, height: 42 }
spaceline:
bounds: { x: 0, y: 0, width: 216, height: 42 }
special:
bounds: { x: 0, y: 0, width: 54, height: 42 }
views:
base:

39
dco.txt
View File

@ -1,39 +0,0 @@
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

75
debian/changelog vendored
View File

@ -1,78 +1,3 @@
squeekboard (1.7.0) amber-phone; urgency=medium
* New terminal layout appearing on terminal input hint
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 08 Jan 2020 11:53:07 +0000
squeekboard (1.6.0) amber-phone; urgency=medium
[ Dorota Czaplejewicz ]
* tools: Move entry.py
* build: Move building of squeekboard-test-layout to tools
* packaging: Install entty.py as squeekboard-entry
* Remove unused build dependencies
* Remove unused header generator
* logging: Move all facilities to one file
* logging: Described the design
* logging: Add described log levels
* popover: Install emoji layout
* popover: Show overlays as selected
* Fix old Rust woes
* emoji: Add a passable layout
* Fix g_ and stdlib allocation/free mismatches
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Thu, 02 Jan 2020 12:02:50 +0000
squeekboard (1.5.0) amber-phone; urgency=medium
[ Dorota Czaplejewicz ]
* keycodes: Sort to eliminate runtime indeterminism
* switcher: Switch layout on menu item click
* Drop squeek_key
* renderer: Remove some unneeded vars
* renderer: Simplified outline rendering
* renderer: Drop row from button rendering
* renderer: Drop unused params
* renderer: Simplify surface rendering
* rendering: Simplify Cairo context usage, remove unneeded calls.
* rendering: Remove unneeded redraw after button release
* renderer: Remove unused locked key render function
* renderer: Simply cut off when painting outside bounds
* renderer: Render whole keyboard the same way as pressed buttons
[ Mark Müller ]
* layout: add German wide layout
[ Dorota Czaplejewicz ]
* renderer: Remove unused functions
* cleanup: Remove references to squeek_view
* cleanup: Unbox View and Row
* cleanup: Remove unused single frame draw
* positioning: Calculate sizes instead of storing, move position out of widgets
* positioning: Clean up unused code
* Fix old Rust woes
[ Mark Müller ]
* layout: add Japanese Kana wide layout
[ Dorota Czaplejewicz ]
* Entry test: Add Terminal input purpose
* readme: Add note about Cargo dependencies
* Create a library/UI module separation
* hacking: Add DCO and licensing requirement
* Fix internal .md link
[ Mark Müller ]
* squeekboard-test-layout: add argument parsing and some more output
[ Dorota Czaplejewicz ]
* Use clap in the lockfile
* parsing: Remove bounds which weren't used anyway
* layout: Respect margins
* CI: Build arm64 .deb
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Mon, 23 Dec 2019 11:58:57 +0000
squeekboard (1.4.0) amber-phone; urgency=medium
* "text" property in layouts

8
debian/control vendored
View File

@ -26,6 +26,9 @@ Build-Depends:
libwayland-dev (>= 1.16),
rustc,
wayland-protocols (>= 1.14),
# for running the tests
xvfb,
xauth,
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard
@ -42,12 +45,9 @@ Description: On-screen keyboard for Wayland
Package: squeekboard-devel
Architecture: linux-any
Depends:
python3,
python3-gi,
${shlibs:Depends}
${misc:Depends}
Description: Resources for making Squeekboard layouts
Tools for creating and testing Squeekboard layouts:
Tools for creating Squeekboard layouts:
.
* squeekboard-entry
* squeekboard-test-layout

View File

@ -1,2 +1 @@
usr/bin/squeekboard-test-layout /usr/bin
usr/bin/squeekboard-entry /usr/bin

View File

@ -1,18 +0,0 @@
#!/bin/sh
# Builds the documentation and places in the selected directory,
# or the working directory.
set -e
SCRIPT_PATH="$(realpath "$0")"
DOCS_DIR="$(dirname "$SCRIPT_PATH")"
TARGET_DIR="${1:-./}"
SPHINX=sphinx-build
if ! which sphinx-build ; then
SPHINX=sphinx-build-3
fi
$SPHINX -b html "${DOCS_DIR}" "${TARGET_DIR}"

View File

@ -1,165 +0,0 @@
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'squeekboard'
copyright = 'Squeekboard contributors'
author = 'Dorota Czaplejewicz'
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = ''
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'recommonmark'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.md'
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path .
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'squeekboarddoc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'squeekboard.tex', 'squeekboard Documentation',
'Dorota Czaplejewicz', 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'squeekboard', 'squeekboard Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'squeekboard', 'squeekboard Documentation',
author, 'squeekboard', 'One line description of project.',
'Miscellaneous'),
]
from recommonmark.transform import AutoStructify
def setup(app):
app.add_config_value('recommonmark_config', {
'enable_auto_toc_tree': True,
'auto_toc_tree_section': 'Contents',
}, True)
app.add_transform(AutoStructify)

View File

@ -1,21 +0,0 @@
Welcome to squeekboard's documentation!
=======================================
Contents
--------
* [Tutorial](tutorial.md)
Introduction
------------
Squeekboard is the on-screen keyobard for the Librem 5 phone. For more information, look at the [README](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md).
Layouts
-------
Squeekboard allows user-provided keyboard layouts. They can be created without recompiling the keyboard code. The tutorial](/tutorial.md) explains the process in detail.
Layouts are created using a text-based format, based on YAML.
TODO: Provide a description of the format.

View File

@ -1,53 +0,0 @@
Kareema's guide to creating layouts
===================================
Its long overdue to write a comprehensive guide how to add a keyboard layout from start. But unfortunately, I dont 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.
**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/keyboard/` in the `.yaml` files
* Take a look and try to understand them :slight_smile:
**Fork your own copy of squeekboard**
* Best way would be to start with a fork of the squeekboard repository: Create a user account at https://source.puri.sm/, go the the squeekboard git repository, press “Fork” in the web interface. You can find further instructions [here](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#creating-a-fork).
* Clone your fork locally with `git clone` and use the uri of your forked repo there
**Workflow to edit your keyboard and get it merged**
* 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
* Checkout your branch, edit your keyboard layout and commit your changes
* Push the local changes (to the branch of your fork of squeekboard)
* Create a merge request for the branch to get your changes merged to the official squeekboard git repository
**Compile squeekboard**
* Follow the instructions found in “Building” section of the squeekboards 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)
**Running 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 https://source.puri.sm/Librem5/squeekboard/blob/master/HACKING.md#testing
* You can either test it locally on your Linux system or use the [QEMU Librem 5 image ](https://developer.puri.sm/Librem5/Development_Environment/Boards/emulators.html)
* 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`
Squeekboard can be installed from there as a Debian package, too (thats 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/`
* Dont forget to add your newly created layout or translation to `src/resources.rs` and the layout to `tests/meson.build` (thats 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

View File

@ -61,6 +61,10 @@ typedef struct _EekGtkKeyboardPrivate
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
static void render_pressed_button (GtkWidget *widget, struct button_place *place);
static void render_released_button (GtkWidget *widget,
const struct squeek_button *button);
static void
eek_gtk_keyboard_real_realize (GtkWidget *self)
{
@ -81,7 +85,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
cairo_t *cr)
{
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
gtk_widget_get_allocation (self, &allocation);
@ -97,7 +101,10 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
gtk_widget_get_scale_factor (self));
}
// render the keyboard without any key activity (TODO: from a cached buffer)
eek_renderer_render_keyboard (priv->renderer, cr);
// render only a few remaining changes
squeek_layout_draw_all_changed(priv->keyboard->layout, EEK_GTK_KEYBOARD(self));
return FALSE;
}
@ -106,7 +113,7 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
GtkAllocation *allocation)
{
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->renderer)
eek_renderer_set_allocation_size (priv->renderer,
@ -131,17 +138,14 @@ static void drag(EekGtkKeyboard *self,
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
x, y, eek_renderer_get_transformation(priv->renderer), time,
priv->keyboard->manager, self);
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
}
static void release(EekGtkKeyboard *self, guint32 time)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
eek_renderer_get_transformation(priv->renderer), time,
priv->keyboard->manager, self);
squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, eek_renderer_get_transformation(priv->renderer), time, self);
}
static gboolean
@ -154,6 +158,8 @@ eek_gtk_keyboard_real_button_press_event (GtkWidget *self,
return TRUE;
}
// TODO: this belongs more in gtk_keyboard, with a way to find out which key to re-render
static gboolean
eek_gtk_keyboard_real_button_release_event (GtkWidget *self,
@ -225,7 +231,7 @@ static void
eek_gtk_keyboard_real_unmap (GtkWidget *self)
{
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->keyboard) {
squeek_layout_release_all_only(
@ -242,7 +248,6 @@ eek_gtk_keyboard_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
(void)value;
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -299,9 +304,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
static void
eek_gtk_keyboard_init (EekGtkKeyboard *self)
{
(void)self;
}
{}
/**
* eek_gtk_keyboard_new:
@ -319,7 +322,110 @@ eek_gtk_keyboard_new (LevelKeyboard *keyboard)
return GTK_WIDGET(ret);
}
EekRenderer *eek_gtk_keyboard_get_renderer(EekGtkKeyboard *self) {
static void
render_pressed_button (GtkWidget *widget,
struct button_place *place)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
return priv->renderer;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
/*
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
*/
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
void
eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET(self));
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_render_button (priv->renderer, cr, &place, 1.0, TRUE);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
// TODO: does it really redraw the entire keyboard?
static void
render_released_button (GtkWidget *widget,
const struct squeek_button *button)
{
(void)button;
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_render_keyboard (priv->renderer, cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
void
eek_gtk_on_button_pressed (struct button_place place,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
if (!place.row) {
return;
}
render_pressed_button (GTK_WIDGET(self), &place);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
CA_PROP_EVENT_ID, "button-pressed",
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
NULL);
#endif
}
void
eek_gtk_on_button_released (const struct squeek_button *button,
struct squeek_view *view,
EekGtkKeyboard *self)
{
(void)view;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_button (GTK_WIDGET(self), button);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
CA_PROP_EVENT_ID, "button-released",
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
NULL);
#endif
}

View File

@ -30,9 +30,12 @@
#include "config.h"
#include <glib/gprintf.h>
#include "eek-enumtypes.h"
#include "eekboard/eekboard-context-service.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
#include "src/keyboard.h"
#include "eek-keyboard.h"
void level_keyboard_deinit(LevelKeyboard *self) {
@ -56,3 +59,8 @@ LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek
keyboard->manager = manager;
return keyboard;
}
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
{
return squeek_layout_get_current_view(keyboard->layout);
}

View File

@ -49,6 +49,7 @@ typedef struct _LevelKeyboard LevelKeyboard;
gchar * eek_keyboard_get_keymap
(LevelKeyboard *keyboard);
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard);
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout);
void level_keyboard_deinit(LevelKeyboard *self);
void level_keyboard_free(LevelKeyboard *self);

View File

@ -42,14 +42,17 @@ typedef struct _EekRendererPrivate
GtkStyleContext *view_context; // owned
GtkStyleContext *button_context; // TODO: maybe move a copy to each button
gdouble border_width; // FIXME: border of what?
gdouble border_width;
gdouble allocation_width;
gdouble allocation_height;
gdouble scale;
gint scale_factor; /* the outputs scale factor */
struct transformation widget_to_layout;
gint origin_x;
gint origin_y;
PangoFontDescription *font; // owned reference
cairo_surface_t *keyboard_surface;
} EekRendererPrivate;
@ -59,10 +62,110 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, GtkStyleContext *ctx,
const struct squeek_button *button);
void eek_render_button (EekRenderer *self,
cairo_t *cr, const struct squeek_button *button,
static void invalidate (EekRenderer *renderer);
static void render_button (EekRenderer *self,
cairo_t *cr, EekBounds view_bounds, struct button_place *place,
gboolean pressed, gboolean locked);
struct _CreateKeyboardSurfaceCallbackData {
cairo_t *cr;
EekRenderer *renderer;
struct squeek_view *view;
struct squeek_row *row;
};
typedef struct _CreateKeyboardSurfaceCallbackData CreateKeyboardSurfaceCallbackData;
static void
create_keyboard_surface_button_callback (struct squeek_button *button,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekBounds bounds = squeek_button_get_bounds(button);
cairo_save (data->cr);
cairo_translate (data->cr, bounds.x, bounds.y);
cairo_rectangle (data->cr,
0.0,
0.0,
bounds.width + 100,
bounds.height + 100);
cairo_clip (data->cr);
struct button_place place = {
.row = data->row,
.button = button,
};
render_button (data->renderer, data->cr, squeek_view_get_bounds(data->view), &place, FALSE, FALSE);
cairo_restore (data->cr);
}
static void
create_keyboard_surface_row_callback (struct squeek_row *row,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekBounds bounds = squeek_row_get_bounds(row);
cairo_save (data->cr);
cairo_translate (data->cr, bounds.x, bounds.y);
gint angle = squeek_row_get_angle (row);
cairo_rotate (data->cr, angle * G_PI / 180);
data->row = row;
squeek_row_foreach(row, create_keyboard_surface_button_callback, data);
cairo_restore (data->cr);
}
static void
render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
GdkRGBA color = {0};
gtk_style_context_get_color (priv->view_context, GTK_STATE_FLAG_NORMAL, &color);
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
CreateKeyboardSurfaceCallbackData data = {
.cr = cairo_create (priv->keyboard_surface),
.renderer = renderer,
.view = view,
};
/* Paint the background covering the entire widget area */
gtk_render_background (priv->view_context,
data.cr,
0, 0,
priv->allocation_width, priv->allocation_height);
gtk_render_frame (priv->view_context,
data.cr,
0, 0,
priv->allocation_width, priv->allocation_height);
cairo_save (data.cr);
cairo_scale (data.cr, priv->scale, priv->scale);
cairo_translate (data.cr, bounds.x, bounds.y);
cairo_set_source_rgba (data.cr,
color.red,
color.green,
color.blue,
color.alpha);
/* draw rows */
squeek_view_foreach(level_keyboard_current(priv->keyboard),
create_keyboard_surface_row_callback,
&data);
cairo_restore (data.cr);
cairo_destroy (data.cr);
}
static void
render_outline (cairo_t *cr,
GtkStyleContext *ctx,
@ -87,20 +190,46 @@ render_outline (cairo_t *cr,
}
static void render_button_in_context(EekRenderer *self,
gdouble scale,
gint scale_factor,
cairo_t *cr,
GtkStyleContext *ctx,
const struct squeek_button *button) {
/* blank background */
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
cairo_paint (cr);
EekBounds view_bounds,
struct button_place *place,
gboolean active) {
cairo_surface_t *outline_surface = NULL;
EekBounds bounds = squeek_button_get_bounds(button);
render_outline (cr, ctx, bounds);
/* render outline */
EekBounds bounds = squeek_button_get_bounds(place->button);
{
cairo_t *cr;
// Outline will be drawn on the outside of the button, so the
// surface needs to be bigger than the button
outline_surface =
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
(int)ceil(bounds.width) + 10,
(int)ceil(bounds.height) + 10);
cr = cairo_create (outline_surface);
/* blank background */
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
cairo_paint (cr);
cairo_save (cr);
eek_renderer_apply_transformation_for_button (cr, view_bounds, place, 1.0, FALSE);
render_outline (cr, ctx, bounds);
cairo_restore (cr);
cairo_destroy (cr);
}
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
cairo_surface_destroy(outline_surface);
cairo_paint (cr);
/* render icon (if any) */
const char *icon_name = squeek_button_get_icon_name(button);
const char *icon_name = squeek_button_get_icon_name(place->button);
if (icon_name) {
cairo_surface_t *icon_surface =
@ -130,13 +259,14 @@ static void render_button_in_context(EekRenderer *self,
return;
}
}
eek_renderer_render_button_label (self, cr, ctx, button);
eek_renderer_render_button_label (self, cr, ctx, place->button);
}
void
eek_render_button (EekRenderer *self,
static void
render_button (EekRenderer *self,
cairo_t *cr,
const struct squeek_button *button,
EekBounds view_bounds,
struct button_place *place,
gboolean pressed,
gboolean locked)
{
@ -147,7 +277,7 @@ eek_render_button (EekRenderer *self,
from the button's symbol. */
g_autoptr (GtkWidgetPath) path = NULL;
path = gtk_widget_path_copy (gtk_style_context_get_path (ctx));
const char *name = squeek_button_get_name(button);
const char *name = squeek_button_get_name(place->button);
gtk_widget_path_iter_set_name (path, -1, name);
/* Update the style context with the updated widget path. */
@ -156,13 +286,13 @@ eek_render_button (EekRenderer *self,
(pressed) or normal. */
gtk_style_context_set_state(ctx,
pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
const char *outline_name = squeek_button_get_outline_name(button);
const char *outline_name = squeek_button_get_outline_name(place->button);
if (locked) {
gtk_style_context_add_class(ctx, "locked");
}
gtk_style_context_add_class(ctx, outline_name);
render_button_in_context(self, priv->scale_factor, cr, ctx, button);
render_button_in_context(self, priv->scale, priv->scale_factor, cr, ctx, view_bounds, place, pressed);
// Save and restore functions don't work if gtk_render_* was used in between
gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
@ -172,6 +302,47 @@ eek_render_button (EekRenderer *self,
}
}
/**
* eek_renderer_apply_transformation_for_key:
* @self: The renderer used to render the key
* @cr: The Cairo rendering context used for rendering
* @key: The key to be transformed
* @scale: The factor used to scale the key bounds before rendering
* @rotate: Whether to rotate the key by the angle defined for the key's
* in its section definition
*
* Applies a transformation, consisting of scaling and rotation, to the
* current rendering context using the bounds for the given key. The scale
* factor is separate to the normal scale factor for the keyboard as a whole
* and is applied cumulatively. It is typically used to render larger than
* normal keys for popups.
*/
void
eek_renderer_apply_transformation_for_button (cairo_t *cr,
EekBounds view_bounds,
struct button_place *place,
gdouble scale,
gboolean rotate)
{
EekBounds bounds, rotated_bounds;
gdouble s;
eek_renderer_get_button_bounds (view_bounds, place, &bounds, FALSE);
eek_renderer_get_button_bounds (view_bounds, place, &rotated_bounds, TRUE);
gint angle = squeek_row_get_angle (place->row);
cairo_scale (cr, scale, scale);
if (rotate) {
s = sin (angle * G_PI / 180);
if (s < 0)
cairo_translate (cr, 0, - bounds.width * s);
else
cairo_translate (cr, bounds.height * s, 0);
cairo_rotate (cr, angle * G_PI / 180);
}
}
static void
eek_renderer_render_button_label (EekRenderer *self,
cairo_t *cr,
@ -244,28 +415,76 @@ eek_renderer_render_button_label (EekRenderer *self,
g_object_unref (layout);
}
void
eek_renderer_render_keyboard (EekRenderer *self,
/*
* eek_renderer_real_render_key:
* @self: The renderer used to render the key
* @cr: The Cairo rendering context used for rendering
* @key: The key to be transformed
* @scale: The factor used to scale the key bounds before rendering
* @rotate: Whether to rotate the key by the angle defined for the key's
* in its section definition
*
* Renders a key separately from the normal keyboard rendering.
*/
static void
eek_renderer_real_render_button (EekRenderer *self,
cairo_t *cr,
struct button_place *place,
gdouble scale,
gboolean rotate)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekBounds bounds;
EekBounds view_bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
eek_renderer_get_button_bounds (view_bounds, place, &bounds, rotate);
cairo_save (cr);
/* Because this function is called separately from the keyboard rendering
function, the transformation for the context needs to be set up */
cairo_translate (cr, priv->origin_x, priv->origin_y);
cairo_scale (cr, priv->scale, priv->scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_apply_transformation_for_button (cr, view_bounds, place, scale, rotate);
struct squeek_key *key = squeek_button_get_key(place->button);
render_button (
self, cr, view_bounds, place,
squeek_key_is_pressed(key) != 0,
squeek_key_is_locked (key) != 0
);
cairo_restore (cr);
}
static void
eek_renderer_real_render_keyboard (EekRenderer *self,
cairo_t *cr)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
cairo_pattern_t *source;
g_return_if_fail (priv->keyboard);
g_return_if_fail (priv->allocation_width > 0.0);
g_return_if_fail (priv->allocation_height > 0.0);
/* Paint the background covering the entire widget area */
gtk_render_background (priv->view_context,
cr,
0, 0,
priv->allocation_width, priv->allocation_height);
cairo_save (cr);
cairo_save(cr);
cairo_translate (cr, priv->widget_to_layout.origin_x, priv->widget_to_layout.origin_y);
cairo_scale (cr, priv->widget_to_layout.scale, priv->widget_to_layout.scale);
cairo_translate (cr, priv->origin_x, priv->origin_y);
if (priv->keyboard_surface)
cairo_surface_destroy (priv->keyboard_surface);
priv->keyboard_surface = cairo_surface_create_for_rectangle (
cairo_get_target (cr), 0, 0,
priv->allocation_width, priv->allocation_height);
render_keyboard_surface (self, squeek_layout_get_current_view(priv->keyboard->layout));
cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0);
source = cairo_get_source (cr);
cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
cairo_paint (cr);
squeek_draw_layout_base_view(priv->keyboard->layout, self, cr);
squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr);
cairo_restore (cr);
}
@ -295,7 +514,6 @@ eek_renderer_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
(void)value;
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -317,7 +535,8 @@ eek_renderer_dispose (GObject *object)
priv->pcontext = NULL;
}
// this is where renderer-specific surfaces would be released
/* this will release all allocated surfaces and font if any */
invalidate (EEK_RENDERER(object));
G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object);
}
@ -341,6 +560,9 @@ eek_renderer_class_init (EekRendererClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->render_button = eek_renderer_real_render_button;
klass->render_keyboard = eek_renderer_real_render_keyboard;
gobject_class->set_property = eek_renderer_set_property;
gobject_class->get_property = eek_renderer_get_property;
gobject_class->dispose = eek_renderer_dispose;
@ -393,8 +615,10 @@ eek_renderer_init (EekRenderer *self)
priv->border_width = 1.0;
priv->allocation_width = 0.0;
priv->allocation_height = 0.0;
priv->scale = 1.0;
priv->scale_factor = 1;
priv->font = NULL;
priv->keyboard_surface = NULL;
GtkIconTheme *theme = gtk_icon_theme_get_default ();
@ -403,6 +627,17 @@ eek_renderer_init (EekRenderer *self)
priv->css_provider = squeek_load_style();
}
static void
invalidate (EekRenderer *renderer)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
if (priv->keyboard_surface) {
cairo_surface_destroy (priv->keyboard_surface);
priv->keyboard_surface = NULL;
}
}
EekRenderer *
eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext)
@ -450,6 +685,8 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
gdouble width,
gdouble height)
{
gdouble scale;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (width > 0.0 && height > 0.0);
@ -458,11 +695,99 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
priv->allocation_width = width;
priv->allocation_height = height;
priv->widget_to_layout = squeek_layout_calculate_transformation(
priv->keyboard->layout,
priv->allocation_width, priv->allocation_height);
/* Calculate a scale factor to use when rendering the keyboard into the
available space. */
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
// This is where size-dependent surfaces would be released
gdouble w = (bounds.x * 2) + bounds.width;
gdouble h = (bounds.y * 2) + bounds.height;
scale = MIN(width / w, height / h);
priv->scale = scale;
/* Set the rendering offset in widget coordinates to center the keyboard */
priv->origin_x = (gint)floor((width - (scale * w)) / 2);
priv->origin_y = (gint)floor((height - (scale * h)) / 2);
invalidate (renderer);
}
void
eek_renderer_get_size (EekRenderer *renderer,
gdouble *width,
gdouble *height)
{
g_return_if_fail (EEK_IS_RENDERER(renderer));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
if (width)
*width = bounds.width;
if (height)
*height = bounds.height;
}
void
eek_renderer_get_button_bounds (EekBounds view_bounds,
struct button_place *place,
EekBounds *bounds,
gboolean rotate)
{
gint angle = 0;
EekPoint points[4], min, max;
g_return_if_fail (place);
g_return_if_fail (bounds != NULL);
EekBounds button_bounds = squeek_button_get_bounds(place->button);
EekBounds row_bounds = squeek_row_get_bounds (place->row);
if (!rotate) {
button_bounds.x += view_bounds.x + row_bounds.x;
button_bounds.y += view_bounds.y + row_bounds.y;
*bounds = button_bounds;
return;
}
points[0].x = button_bounds.x;
points[0].y = button_bounds.y;
points[1].x = points[0].x + button_bounds.width;
points[1].y = points[0].y;
points[2].x = points[1].x;
points[2].y = points[1].y + button_bounds.height;
points[3].x = points[0].x;
points[3].y = points[2].y;
if (rotate) {
angle = squeek_row_get_angle (place->row);
}
min = points[2];
max = points[0];
for (unsigned i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], angle);
if (points[i].x < min.x)
min.x = points[i].x;
if (points[i].x > max.x)
max.x = points[i].x;
if (points[i].y < min.y)
min.y = points[i].y;
if (points[i].y > max.y)
max.y = points[i].y;
}
bounds->x = view_bounds.x + row_bounds.x + min.x;
bounds->y = view_bounds.y + row_bounds.y + min.y;
bounds->width = (max.x - min.x);
bounds->height = (max.y - min.y);
}
gdouble
eek_renderer_get_scale (EekRenderer *renderer)
{
g_return_val_if_fail (EEK_IS_RENDERER(renderer), 0);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
return priv->scale;
}
void
@ -498,11 +823,86 @@ eek_renderer_get_icon_surface (const gchar *icon_name,
return surface;
}
void
eek_renderer_render_button (EekRenderer *renderer,
cairo_t *cr,
struct button_place *place,
gdouble scale,
gboolean rotate)
{
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (place);
g_return_if_fail (scale >= 0.0);
EEK_RENDERER_GET_CLASS(renderer)->
render_button (renderer, cr, place, scale, rotate);
}
void
eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr)
{
g_return_if_fail (EEK_IS_RENDERER(renderer));
EEK_RENDERER_GET_CLASS(renderer)->render_keyboard (renderer, cr);
}
static gboolean
sign (EekPoint *p1, EekPoint *p2, EekPoint *p3)
{
// FIXME: what is this actually checking?
return (p1->x - p3->x) * (p2->y - p3->y) -
(p2->x - p3->x) * (p1->y - p3->y);
}
uint32_t
eek_are_bounds_inside (EekBounds bounds, EekPoint point, EekPoint origin, int32_t angle)
{
EekPoint points[4];
gboolean b1, b2, b3;
points[0].x = bounds.x;
points[0].y = bounds.y;
points[1].x = points[0].x + bounds.width;
points[1].y = points[0].y;
points[2].x = points[1].x;
points[2].y = points[1].y + bounds.height;
points[3].x = points[0].x;
points[3].y = points[2].y;
for (unsigned i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], angle);
points[i].x += origin.x;
points[i].y += origin.y;
}
b1 = sign (&point, &points[0], &points[1]) < 0.0;
b2 = sign (&point, &points[1], &points[2]) < 0.0;
b3 = sign (&point, &points[2], &points[0]) < 0.0;
if (b1 == b2 && b2 == b3) {
return 1;
}
b1 = sign (&point, &points[2], &points[3]) < 0.0;
b2 = sign (&point, &points[3], &points[0]) < 0.0;
b3 = sign (&point, &points[0], &points[2]) < 0.0;
if (b1 == b2 && b2 == b3) {
return 1;
}
return 0;
}
struct transformation
eek_renderer_get_transformation (EekRenderer *renderer) {
struct transformation failed = {0};
g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
return priv->widget_to_layout;
struct transformation ret = {
.origin_x = priv->origin_x,
.origin_y = priv->origin_y,
.scale = priv->scale,
};
return ret;
}

View File

@ -25,6 +25,7 @@
#include <pango/pangocairo.h>
#include "eek-types.h"
#include "src/layout.h"
G_BEGIN_DECLS
@ -35,6 +36,15 @@ struct _EekRendererClass
{
GObjectClass parent_class;
void (* render_button) (EekRenderer *self,
cairo_t *cr,
struct button_place *place,
gdouble scale,
gboolean rotate);
void (* render_keyboard) (EekRenderer *self,
cairo_t *cr);
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
const gchar *icon_name,
gint size,
@ -52,15 +62,38 @@ void eek_renderer_set_allocation_size
(EekRenderer *renderer,
gdouble width,
gdouble height);
void eek_renderer_get_size (EekRenderer *renderer,
gdouble *width,
gdouble *height);
void eek_renderer_get_button_bounds (EekBounds view_bounds,
struct button_place *button,
EekBounds *bounds,
gboolean rotate);
gdouble eek_renderer_get_scale (EekRenderer *renderer);
void eek_renderer_set_scale_factor (EekRenderer *renderer,
gint scale);
void eek_renderer_render_button (EekRenderer *renderer,
cairo_t *cr,
struct button_place *place,
gdouble scale,
gboolean rotate);
cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name,
gint size,
gint scale);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
void eek_renderer_apply_transformation_for_button
(cairo_t *cr,
EekBounds view_bounds,
struct button_place *place,
gdouble scale,
gboolean rotate);
struct transformation
eek_renderer_get_transformation (EekRenderer *renderer);

View File

@ -88,14 +88,5 @@ struct transformation {
gdouble origin_y;
gdouble scale;
};
struct squeek_button;
struct squeek_row;
/// Represents the path to the button within a view
struct button_place {
const struct squeek_row *row;
const struct squeek_button *button;
};
G_END_DECLS
#endif /* EEK_TYPES_H */

View File

@ -24,6 +24,7 @@
#include "config.h"
#include "eek-keyboard.h"
#include "src/keyboard.h"
#include "src/layout.h"
#include "eek-xml-layout.h"
@ -34,5 +35,6 @@ eek_xml_layout_real_create_keyboard (const char *keyboard_type,
enum squeek_arrangement_kind t)
{
struct squeek_layout *layout = squeek_load_layout(keyboard_type, t);
squeek_layout_place_contents(layout);
return level_keyboard_new(manager, layout);
}

8
eek/meson.build Normal file
View File

@ -0,0 +1,8 @@
gnome = import('gnome')
enum_headers = [
'eek-types.h',
]
enums = gnome.mkenums_simple('eek-enumtypes', sources: enum_headers)

View File

@ -71,8 +71,6 @@ struct _EekboardContextServicePrivate {
LevelKeyboard *keyboard; // currently used keyboard
GHashTable *keyboard_hash; // a table of available keyboards, per layout
char *overlay;
GSettings *settings;
uint32_t hint;
uint32_t purpose;
@ -216,17 +214,15 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
void
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t)
{
g_autofree gchar *keyboard_type = NULL;
g_autofree gchar *keyboard_layout = NULL;
if (context->priv->overlay) {
keyboard_layout = g_strdup(context->priv->overlay);
} else {
g_autofree gchar *keyboard_type = NULL;
settings_get_layout(context->priv->settings,
&keyboard_type, &keyboard_layout);
}
settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
if (!keyboard_type) {
keyboard_type = g_strdup("us");
}
if (!keyboard_layout) {
keyboard_layout = g_strdup("us");
keyboard_layout = g_strdup("undefined");
}
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
@ -236,9 +232,6 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("number");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
keyboard_layout = g_strdup("terminal");
break;
default:
;
}
@ -269,8 +262,6 @@ settings_handle_layout_changed(GSettings *s,
(void)keys;
(void)n_keys;
EekboardContextService *context = user_data;
g_free(context->priv->overlay);
context->priv->overlay = NULL;
update_layout_and_type(context);
return TRUE;
}
@ -400,8 +391,6 @@ eekboard_context_service_init (EekboardContextService *self)
g_warning ("Could not connect to gsettings updates, layout"
" changing unavailable");
}
self->priv->overlay = NULL;
}
/**
@ -474,7 +463,6 @@ eekboard_context_service_destroy (EekboardContextService *context)
if (context->priv->enabled) {
eekboard_context_service_disable (context);
}
g_free(context->priv->overlay);
g_signal_emit (context, signals[DESTROYED], 0);
}
@ -510,14 +498,3 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
update_layout_and_type(context);
}
}
void
eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) {
context->priv->overlay = g_strdup(name);
update_layout_and_type(context);
}
const char*
eekboard_context_service_get_overlay(EekboardContextService *context) {
return context->priv->overlay;
}

View File

@ -1,7 +1,7 @@
project(
'squeekboard',
'c', 'rust',
version: '1.7.0',
version: '1.4.0',
license: 'GPLv3',
meson_version: '>=0.51.0',
default_options: [
@ -40,7 +40,6 @@ else
endif
prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir'))
pkgdatadir = join_paths(datadir, meson.project_name())
if get_option('depdatadir') == ''
@ -66,6 +65,6 @@ cargo_build = find_program('cargo_build.sh')
subdir('data')
subdir('protocols')
subdir('eek')
subdir('src')
subdir('tools')
subdir('tests')

View File

@ -1,7 +1,5 @@
/**! The parsing of the data files for layouts */
// TODO: find a nice way to make sure non-positive sizes don't break layouts
use std::cell::RefCell;
use std::collections::{ HashMap, HashSet };
use std::env;
@ -19,19 +17,18 @@ use ::keyboard::{
KeyState, PressType,
generate_keymap, generate_keycodes, FormattingError
};
use ::layout;
use ::layout::ArrangementKind;
use ::logging::PrintWarnings;
use ::resources;
use ::util::c::as_str;
use ::util::hash_map_map;
use ::xdg;
// traits, derives
use serde::Deserialize;
use std::io::BufReader;
use std::iter::FromIterator;
use ::logging::WarningHandler;
use serde::Deserialize;
use util::WarningHandler;
/// Gathers stuff defined in C or called by C
pub mod c {
@ -154,6 +151,14 @@ fn list_layout_sources(
ret
}
struct PrintWarnings;
impl WarningHandler for PrintWarnings {
fn handle(&mut self, warning: &str) {
println!("{}", warning);
}
}
fn load_layout_data(source: DataSource)
-> Result<::layout::LayoutData, LoadError>
{
@ -210,20 +215,20 @@ fn load_layout_data_with_fallback(
#[derive(Debug, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Layout {
#[serde(default)]
margins: Margins,
bounds: Bounds,
views: HashMap<String, Vec<ButtonIds>>,
#[serde(default)]
buttons: HashMap<String, ButtonMeta>,
outlines: HashMap<String, Outline>
}
#[derive(Debug, Clone, Deserialize, PartialEq, Default)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
struct Margins {
top: f64,
bottom: f64,
side: f64,
struct Bounds {
x: f64,
y: f64,
width: f64,
height: f64,
}
/// Buttons are embedded in a single string
@ -264,8 +269,7 @@ enum Action {
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
struct Outline {
width: f64,
height: f64,
bounds: Bounds,
}
/// Errors encountered loading the layout into yaml
@ -299,20 +303,6 @@ impl From<io::Error> for Error {
}
}
pub fn add_offsets<'a, I: 'a, T, F: 'a>(iterator: I, get_size: F)
-> impl Iterator<Item=(f64, T)> + 'a
where I: Iterator<Item=T>,
F: Fn(&T) -> f64,
{
let mut offset = 0.0;
iterator.map(move |item| {
let size = get_size(&item);
let value = (offset, item);
offset += size;
value
})
}
impl Layout {
pub fn from_resource(name: &str) -> Result<Layout, LoadError> {
let data = resources::get_keyboard(name)
@ -413,35 +403,34 @@ impl Layout {
);
let views = HashMap::from_iter(
self.views.iter().map(|(name, view)| {
let rows = view.iter().map(|row| {
let buttons = row.split_ascii_whitespace()
.map(|name| {
Box::new(create_button(
&self.buttons,
&self.outlines,
name,
button_states_cache.get(name.into())
.expect("Button state not created")
.clone(),
&mut warning_handler,
))
});
::layout::Row {
angle: 0,
buttons: add_offsets(
buttons,
|button| button.size.width,
).collect()
}
});
let rows = add_offsets(rows, |row| row.get_height())
.collect();
(
name.clone(),
layout::View::new(rows)
)
})
self.views.iter().map(|(name, view)| {(
name.clone(),
Box::new(::layout::View {
bounds: ::layout::c::Bounds {
x: self.bounds.x,
y: self.bounds.y,
width: self.bounds.width,
height: self.bounds.height,
},
rows: view.iter().map(|row| {
Box::new(::layout::Row {
angle: 0,
bounds: None,
buttons: row.split_ascii_whitespace().map(|name| {
Box::new(create_button(
&self.buttons,
&self.outlines,
name,
button_states_cache.get(name.into())
.expect("Button state not created")
.clone(),
&mut warning_handler,
))
}).collect(),
})
}).collect(),
})
)})
);
(
@ -451,13 +440,6 @@ impl Layout {
CString::new(keymap_str)
.expect("Invalid keymap string generated")
},
// FIXME: use a dedicated field
margins: layout::Margins {
top: self.margins.top,
left: self.margins.side,
bottom: self.margins.bottom,
right: self.margins.side,
},
}),
warning_handler,
)
@ -642,16 +624,20 @@ fn create_button<H: WarningHandler>(
warning_handler.handle(
&format!("No default outline defined! Using 1x1!")
);
Outline { width: 1f64, height: 1f64 }
Outline {
bounds: Bounds { x: 0f64, y: 0f64, width: 1f64, height: 1f64 },
}
});
layout::Button {
::layout::Button {
name: cname,
outline_name: CString::new(outline_name).expect("Bad outline"),
// TODO: do layout before creating buttons
size: layout::Size {
width: outline.width,
height: outline.height,
bounds: ::layout::c::Bounds {
x: outline.bounds.x,
y: outline.bounds.y,
width: outline.bounds.width,
height: outline.bounds.height,
},
label: label,
state: state,
@ -663,14 +649,21 @@ mod tests {
use super::*;
use std::error::Error as ErrorTrait;
use ::logging::PanicWarn;
struct PanicWarn;
impl WarningHandler for PanicWarn {
fn handle(&mut self, warning: &str) {
panic!("{}", warning);
}
}
#[test]
fn test_parse_path() {
assert_eq!(
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
Layout {
margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
bounds: Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 },
views: hashmap!(
"base".into() => vec!("test".into()),
),
@ -685,7 +678,11 @@ mod tests {
}
},
outlines: hashmap!{
"default".into() => Outline { width: 0f64, height: 0f64 },
"default".into() => Outline {
bounds: Bounds {
x: 0f64, y: 0f64, width: 0f64, height: 0f64
},
}
},
}
);
@ -737,8 +734,8 @@ mod tests {
.unwrap();
assert_eq!(
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.rows[0]
.buttons[0]
.label,
::layout::Label::Text(CString::new("test").unwrap())
);
@ -752,8 +749,8 @@ mod tests {
.unwrap();
assert_eq!(
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.rows[0]
.buttons[0]
.label,
::layout::Label::Text(CString::new("test").unwrap())
);
@ -768,8 +765,8 @@ mod tests {
.unwrap();
assert_eq!(
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.rows[0]
.buttons[0]
.state.borrow()
.keycodes.len(),
2
@ -835,21 +832,4 @@ mod tests {
},
);
}
#[test]
fn test_layout_margins() {
let out = Layout::from_file(PathBuf::from("tests/layout_margins.yaml"))
.unwrap()
.build(PanicWarn).0
.unwrap();
assert_eq!(
out.margins,
layout::Margins {
top: 1.0,
bottom: 3.0,
left: 2.0,
right: 2.0,
}
);
}
}

View File

@ -1,120 +0,0 @@
/*! Drawing the UI */
use cairo;
use std::cell::RefCell;
use ::keyboard;
use ::layout::{ Button, Layout };
use ::layout::c::{ EekGtkKeyboard, Point };
use glib::translate::FromGlibPtrNone;
use gtk::WidgetExt;
mod c {
use super::*;
use cairo_sys;
use std::os::raw::c_void;
// This is constructed only in C, no need for warnings
#[allow(dead_code)]
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct EekRenderer(*const c_void);
#[no_mangle]
extern "C" {
// Button and View inside CButtonPlace are safe to pass to C
// as long as they don't outlive the call
// and nothing dereferences them
#[allow(improper_ctypes)]
pub fn eek_render_button(
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
button: *const Button,
pressed: u64,
locked: u64,
);
}
#[no_mangle]
pub extern "C"
fn squeek_layout_draw_all_changed(
layout: *mut Layout,
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
) {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
let state = RefCell::borrow(&button.state).clone();
if state.pressed == keyboard::PressType::Pressed || state.locked {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
state.pressed, state.locked,
);
}
}
}
}
#[no_mangle]
pub extern "C"
fn squeek_draw_layout_base_view(
layout: *mut Layout,
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
) {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
keyboard::PressType::Released, false,
);
}
}
}
}
/// Renders a button at a position (button's own bounds ignored)
pub fn render_button_at_position(
renderer: c::EekRenderer,
cr: &cairo::Context,
position: Point,
button: &Button,
pressed: keyboard::PressType,
locked: bool,
) {
cr.save();
cr.translate(position.x, position.y);
cr.rectangle(
0.0, 0.0,
button.size.width, button.size.height
);
cr.clip();
unsafe {
c::eek_render_button(
renderer,
cairo::Context::to_raw_none(&cr),
button as *const Button,
pressed as u64,
locked as u64,
)
};
cr.restore();
}
pub fn queue_redraw(keyboard: EekGtkKeyboard) {
let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) };
widget.queue_draw();
}

12
src/keyboard.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __KEYBOARD_H
#define __KEYBOARD_H
#include "inttypes.h"
#include "stdbool.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
struct squeek_key;
uint32_t squeek_key_is_pressed(struct squeek_key *key);
uint32_t squeek_key_is_locked(struct squeek_key *key);
#endif

View File

@ -10,8 +10,32 @@ use ::action::Action;
use std::io::Write;
use std::iter::{ FromIterator, IntoIterator };
use ::util::CloneOwned;
#[derive(Debug, Clone, Copy, PartialEq)]
/// Gathers stuff defined in C or called by C
pub mod c {
use super::*;
use ::util::c;
pub type CKeyState = c::Wrapped<KeyState>;
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
#[no_mangle]
pub extern "C"
fn squeek_key_is_pressed(key: CKeyState) -> u32 {
//let key = unsafe { Rc::from_raw(key.0) };
return key.clone_owned().pressed as u32;
}
#[no_mangle]
pub extern "C"
fn squeek_key_is_locked(key: CKeyState) -> u32 {
return key.clone_owned().locked as u32;
}
}
#[derive(Debug, Clone, Copy)]
pub enum PressType {
Released = 0,
Pressed = 1,

View File

@ -5,8 +5,8 @@
#include <glib.h>
#include "eek/eek-element.h"
#include "eek/eek-gtk-keyboard.h"
#include "eek/eek-renderer.h"
#include "eek/eek-types.h"
#include "src/keyboard.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
enum squeek_arrangement_kind {
@ -14,19 +14,48 @@ enum squeek_arrangement_kind {
ARRANGEMENT_KIND_WIDE = 1,
};
struct squeek_button;
struct squeek_row;
struct squeek_view;
struct squeek_layout;
/// Represents the path to the button within a view
struct button_place {
const struct squeek_row *row;
const struct squeek_button *button;
};
int32_t squeek_row_get_angle(const struct squeek_row*);
EekBounds squeek_row_get_bounds(const struct squeek_row*);
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
void squeek_row_foreach(struct squeek_row*,
ButtonCallback callback,
gpointer user_data);
EekBounds squeek_button_get_bounds(const struct squeek_button*);
const char *squeek_button_get_label(const struct squeek_button*);
const char *squeek_button_get_icon_name(const struct squeek_button*);
const char *squeek_button_get_name(const struct squeek_button*);
const char *squeek_button_get_outline_name(const struct squeek_button*);
struct squeek_key *squeek_button_get_key(const struct squeek_button*);
uint32_t *squeek_button_has_key(const struct squeek_button* button,
const struct squeek_key *key);
void squeek_button_print(const struct squeek_button* button);
struct transformation squeek_layout_calculate_transformation(
const struct squeek_layout *layout,
double allocation_width, double allocation_size);
EekBounds squeek_view_get_bounds(const struct squeek_view*);
typedef void (*RowCallback) (struct squeek_row *row, gpointer user_data);
void squeek_view_foreach(struct squeek_view*,
RowCallback callback,
gpointer user_data);
void
squeek_layout_place_contents(struct squeek_layout*);
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
const char *squeek_layout_get_keymap(const struct squeek_layout*);
@ -36,7 +65,6 @@ void squeek_layout_free(struct squeek_layout*);
void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
struct transformation widget_to_layout,
uint32_t timestamp,
EekboardContextService *manager,
EekGtkKeyboard *ui_keyboard);
void squeek_layout_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp);
void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
@ -46,8 +74,6 @@ void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyb
void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
double x_widget, double y_widget,
struct transformation widget_to_layout,
uint32_t timestamp, EekboardContextService *manager,
EekGtkKeyboard *ui_keyboard);
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekGtkKeyboard *ui_keyboard);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,5 @@
#[macro_use]
extern crate bitflags;
extern crate cairo;
extern crate cairo_sys;
extern crate gdk;
extern crate gio;
extern crate glib;
extern crate glib_sys;
@ -17,15 +14,12 @@ extern crate xkbcommon;
mod action;
pub mod data;
mod drawing;
pub mod float_ord;
pub mod imservice;
mod keyboard;
mod layout;
mod locale;
mod locale_config;
mod logging;
mod manager;
mod outputs;
mod popover;
mod resources;

View File

@ -16,9 +16,6 @@ mod c {
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Translation<'a>(pub &'a str);
fn cstring_safe(s: &str) -> CString {
CString::new(s)
.unwrap_or(CString::new("").unwrap())

View File

@ -1,110 +0,0 @@
/*! Logging library.
*
* This is probably the only part of squeekboard
* that should be doing any direct printing.
*
* There are several approaches to logging,
* in the order of increasing flexibility and/or purity:
*
* 1. `println!` directly
*
* It can't be easily replaced by a different solution
*
* 2. simple `log!` macro
*
* Replacing the destination at runtime other than globally would be awkward,
* so no easy way to suppress errors for things that don't matter,
* but formatting is still easy.
*
* 3. logging to a mutable destination type
*
* Can be easily replaced, but logging `Result` types,
* which should be done by calling a method on the result,
* can't be formatted directly.
* Cannot be parallelized.
*
* 4. logging to an immutable destination type
*
* Same as above, except it can be parallelized.
* It seems more difficult to pass the logger around,
* but this may be a solved problem from the area of functional programming.
*
* This library generally aims at the approach in 3.
* */
use std::error::Error;
/// Levels are not in order.
pub enum Level {
// Levels for reporting violated constraints
/// The program violated a self-imposed constraint,
/// ended up in an inconsistent state, and cannot recover.
/// Handlers must not actually panic. (should they?)
Panic,
/// The program violated a self-imposed constraint,
/// ended up in an inconsistent state, but some state can be recovered.
Bug,
/// Invalid data given by an external source,
/// some state of the program must be dropped.
Error,
// Still violated constraints, but harmless
/// Invalid data given by an external source, parts of data are ignored.
/// No previous program state needs to be dropped.
Warning,
/// External source not in an expected state,
/// but not violating any protocols (including no relevant protocol).
Surprise,
// Informational
/// A change in internal state that results in a change of behaviour
/// that a user can observe, and a tinkerer might find useful.
/// E.g. selection of external sources, like loading user's UI files,
/// language switch, overrides.
Info,
/// Information useful for application developer only.
/// Should be limited to information gotten from external sources,
/// and more tricky parts of internal state.
Debug,
}
/// Sugar for logging errors in results.
/// Approach 2.
pub trait Warn {
type Value;
fn ok_warn(self, msg: &str) -> Option<Self::Value>;
}
impl<T, E: Error> Warn for Result<T, E> {
type Value = T;
fn ok_warn(self, msg: &str) -> Option<T> {
self.map_err(|e| {
eprintln!("{}: {}", msg, e);
e
}).ok()
}
}
/// A mutable handler for text warnings.
/// Approach 3.
pub trait WarningHandler {
/// Handle a warning
fn handle(&mut self, warning: &str);
}
/// Prints warnings to stderr
pub struct PrintWarnings;
impl WarningHandler for PrintWarnings {
fn handle(&mut self, warning: &str) {
eprintln!("{}", warning);
}
}
/// Warning handler that will panic at any warning.
/// Don't use except in tests
pub struct PanicWarn;
impl WarningHandler for PanicWarn {
fn handle(&mut self, warning: &str) {
panic!("{}", warning);
}
}

View File

@ -1,34 +0,0 @@
/*! Procedures relating to the management of the switching of layouts */
use ::util;
pub mod c {
use std::os::raw::{c_char, c_void};
/// EekboardContextService*
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct Manager(*const c_void);
#[no_mangle]
extern "C" {
pub fn eekboard_context_service_set_overlay(
manager: Manager,
name: *const c_char,
);
pub fn eekboard_context_service_get_overlay(
manager: Manager,
) -> *const c_char;
}
}
/// Returns the overlay name.
/// The result lifetime is "as long as the C copy lives"
pub fn get_overlay(manager: c::Manager) -> Option<String> {
let raw_str = unsafe {
c::eekboard_context_service_get_overlay(manager)
};
// this string is generated from Rust, should never be invalid
util::c::as_str(&raw_str).unwrap()
.map(String::from)
}

View File

@ -25,6 +25,7 @@ sources = [
'../eek/eek-xml-layout.c',
'../eek/layersurface.c',
dbus_src,
enums,
'../eekboard/key-emitter.c',
'../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-service.c',
@ -111,3 +112,16 @@ squeekboard = executable('squeekboard',
'-DEEK_COMPILATION=1'],
)
bindir = join_paths(prefix, get_option('bindir'))
test_layout = custom_target('squeekboard-test-layout',
build_by_default: true,
# meson doesn't track all inputs, cargo does
build_always_stale: true,
output: ['squeekboard-test-layout'],
console: true,
command: [cargo_build] + cargo_build_flags
+ ['--rename', 'test_layout', '@OUTPUT@', '--bin', 'test_layout'],
install: true,
install_dir: bindir,
)

View File

@ -2,11 +2,9 @@
use gio;
use gtk;
use std::ffi::CString;
use ::layout::c::{ Bounds, EekGtkKeyboard };
use ::locale::{ Translation, compare_current_locale };
use ::layout::c::EekGtkKeyboard;
use ::locale::compare_current_locale;
use ::locale_config::system_locale;
use ::manager;
use ::resources;
use gio::ActionMapExt;
@ -94,7 +92,7 @@ mod variants {
}
}
fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder {
fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder {
let mut xml: Vec<u8> = Vec::new();
writeln!(
xml,
@ -103,7 +101,7 @@ fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder {
<menu id=\"app-menu\">
<section>"
).unwrap();
for (input_name, translation) in inputs {
for (input_name, human_name) in inputs {
writeln!(
xml,
"
@ -112,7 +110,7 @@ fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder {
<attribute name=\"action\">layout</attribute>
<attribute name=\"target\">{}</attribute>
</item>",
translation.0,
human_name,
input_name,
).unwrap();
}
@ -143,79 +141,16 @@ fn set_layout(kind: String, name: String) {
settings.apply();
}
/// A reference to what the user wants to see
#[derive(PartialEq, Clone, Debug)]
enum LayoutId {
/// Affects the layout in system settings
System {
kind: String,
name: String,
},
/// Only affects what this input method presents
Local(String),
}
impl LayoutId {
fn get_name(&self) -> &str {
match &self {
LayoutId::System { kind: _, name } => name.as_str(),
LayoutId::Local(name) => name.as_str(),
}
}
}
fn set_visible_layout(
manager: manager::c::Manager,
layout_id: LayoutId,
) {
match layout_id {
LayoutId::System { kind, name } => set_layout(kind, name),
LayoutId::Local(name) => {
let name = CString::new(name.as_str()).unwrap();
let name_ptr = name.as_ptr();
unsafe {
manager::c::eekboard_context_service_set_overlay(
manager,
name_ptr,
)
}
},
}
}
/// Takes into account first any overlays, then system layouts from the list
fn get_current_layout(
manager: manager::c::Manager,
system_layouts: &Vec<LayoutId>,
) -> Option<LayoutId> {
match manager::get_overlay(manager) {
Some(name) => Some(LayoutId::Local(name)),
None => system_layouts.get(0).map(LayoutId::clone),
}
}
pub fn show(
window: EekGtkKeyboard,
position: Bounds,
manager: manager::c::Manager,
) {
pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) {
unsafe { gtk::set_initialized() };
let window = unsafe { gtk::Widget::from_glib_none(window.0) };
let overlay_layouts = resources::get_overlays().into_iter()
.map(|name| LayoutId::Local(name.to_string()));
let settings = gio::Settings::new("org.gnome.desktop.input-sources");
let inputs = settings.get_value("sources").unwrap();
let inputs = variants::get_tuples(inputs);
let system_layouts: Vec<LayoutId> = inputs.into_iter()
.map(|(kind, name)| LayoutId::System { kind, name })
.collect();
let all_layouts: Vec<LayoutId> = system_layouts.clone()
.into_iter()
.chain(overlay_layouts)
let input_names: Vec<&str> = inputs.iter()
.map(|(_kind, name)| name.as_str())
.collect();
let translations = system_locale()
@ -227,56 +162,26 @@ pub fn show(
)
.and_then(|lang| resources::get_layout_names(lang.as_str()));
let translated_names = all_layouts.iter()
.map(LayoutId::get_name);
let translated_names: Vec<Translation> = match translations {
// sorted collection of human and machine names
let mut human_names: Vec<(&str, &str)> = match translations {
Some(translations) => {
translated_names
.map(move |name| {
translations.get(name)
.map(|translation| translation.clone())
.unwrap_or(Translation(name))
})
input_names.iter()
.map(|name| (*name, *translations.get(name).unwrap_or(name)))
.collect()
},
// display bare codes
None => {
translated_names.map(|name| Translation(name))
input_names.iter()
.map(|n| (*n, *n)) // turns &&str into &str
.collect()
},
}
};
// sorted collection of human and machine names
let mut human_names: Vec<(Translation, LayoutId)> = translated_names
.into_iter()
.zip(all_layouts.clone().into_iter())
.collect();
human_names.sort_unstable_by(|(tr_a, _), (tr_b, _)| {
compare_current_locale(tr_a.0, tr_b.0)
human_names.sort_unstable_by(|(_, human_label_a), (_, human_label_b)| {
compare_current_locale(human_label_a, human_label_b)
});
// GVariant doesn't natively support `enum`s,
// so the `choices` vector will serve as a lookup table.
let choices_with_translations: Vec<(String, (Translation, LayoutId))>
= human_names.into_iter()
.enumerate()
.map(|(i, human_entry)| {(
format!("{}_{}", i, human_entry.1.get_name()),
human_entry,
)}).collect();
let builder = make_menu_builder(
choices_with_translations.iter()
.map(|(id, (translation, _))| (id.as_str(), translation.clone()))
.collect()
);
let choices: Vec<(String, LayoutId)>
= choices_with_translations.into_iter()
.map(|(id, (_tr, layout))| (id, layout))
.collect();
let builder = make_menu_builder(human_names);
// Much more debuggable to populate the model & menu
// from a string representation
// than add items imperatively
@ -290,21 +195,16 @@ pub fn show(
height: position.width.floor() as i32,
});
if let Some(current_layout) = get_current_layout(manager, &system_layouts) {
let current_name_variant = choices.iter()
.find(
|(_id, layout)| layout == &current_layout
).unwrap()
.0.to_variant();
if let Some(current_name) = input_names.get(0) {
let current_name = current_name.to_variant();
let layout_action = gio::SimpleAction::new_stateful(
"layout",
Some(current_name_variant.type_()),
&current_name_variant,
Some(current_name.type_()),
&current_name,
);
let menu_inner = menu.clone();
layout_action.connect_change_state(move |_action, state| {
layout_action.connect_change_state(|_action, state| {
match state {
Some(v) => {
v.get::<String>()
@ -312,20 +212,10 @@ pub fn show(
eprintln!("Variant is not string: {:?}", v);
None
})
.map(|state| {
let (_id, layout) = choices.iter()
.find(
|choices| state == choices.0
).unwrap();
set_visible_layout(
manager,
layout.clone(),
)
});
.map(|state| set_layout("xkb".into(), state));
},
None => eprintln!("No variant selected"),
};
menu_inner.popdown();
});
let action_group = gio::SimpleActionGroup::new();

View File

@ -3,7 +3,6 @@
*/
use std::collections::HashMap;
use ::locale::Translation;
use std::iter::FromIterator;
@ -20,13 +19,9 @@ const KEYBOARDS: &[(*const str, *const str)] = &[
("fi", include_str!("../data/keyboards/fi.yaml")),
("it", include_str!("../data/keyboards/it.yaml")),
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
("jp+kana_wide", include_str!("../data/keyboards/jp+kana_wide.yaml")),
("no", include_str!("../data/keyboards/no.yaml")),
("number", include_str!("../data/keyboards/number.yaml")),
("se", include_str!("../data/keyboards/se.yaml")),
("terminal", include_str!("../data/keyboards/terminal.yaml")),
// Overlays
("emoji", include_str!("../data/keyboards/emoji.yaml")),
];
pub fn get_keyboard(needle: &str) -> Option<&'static str> {
@ -43,18 +38,6 @@ pub fn get_keyboard(needle: &str) -> Option<&'static str> {
})
}
const OVERLAY_NAMES: &[*const str] = &[
"emoji"
];
pub fn get_overlays() -> Vec<&'static str> {
OVERLAY_NAMES.iter()
.map(|name| {
let name: *const str = *name;
unsafe { &*name }
}).collect()
}
/// Translations of the layout identifier strings
const LAYOUT_NAMES: &[(*const str, *const str)] = &[
("de-DE", include_str!("../data/langs/de-DE.txt")),
@ -65,7 +48,7 @@ const LAYOUT_NAMES: &[(*const str, *const str)] = &[
];
pub fn get_layout_names(lang: &str)
-> Option<HashMap<&'static str, Translation<'static>>>
-> Option<HashMap<&'static str, &'static str>>
{
let translations = LAYOUT_NAMES.iter()
.find(|(name, _data)| {
@ -79,7 +62,7 @@ pub fn get_layout_names(lang: &str)
translations.map(make_mapping)
}
fn parse_line(line: &str) -> Option<(&str, Translation)> {
fn parse_line(line: &str) -> Option<(&str, &str)> {
let comment = line.trim().starts_with("#");
if comment {
None
@ -87,11 +70,11 @@ fn parse_line(line: &str) -> Option<(&str, Translation)> {
let mut iter = line.splitn(2, " ");
let name = iter.next().unwrap();
// will skip empty and unfinished lines
iter.next().map(|tr| (name, Translation(tr.trim())))
iter.next().map(|tr| (name, tr.trim()))
}
}
fn make_mapping(data: &str) -> HashMap<&str, Translation> {
fn make_mapping(data: &str) -> HashMap<&str, &str> {
HashMap::from_iter(
data.split("\n")
.filter_map(parse_line)
@ -102,17 +85,10 @@ fn make_mapping(data: &str) -> HashMap<&str, Translation> {
mod test {
use super::*;
#[test]
fn check_overlays_present() {
for name in get_overlays() {
assert!(get_keyboard(name).is_some());
}
}
#[test]
fn mapping_line() {
assert_eq!(
Some(("name", Translation("translation"))),
Some(("name", "translation")),
parse_line("name translation")
);
}

View File

@ -21,7 +21,7 @@
use std::env;
use glib::object::ObjectExt;
use logging::Warn;
use util::Warn;
/// Gathers stuff defined in C or called by C
pub mod c {

View File

@ -3,7 +3,7 @@
use ::data::Layout;
use xkbcommon::xkb;
use ::logging::WarningHandler;
use ::util::WarningHandler;
pub struct CountAndPrint(u32);
@ -56,8 +56,8 @@ fn check_layout(layout: Layout) {
// "Press" each button with keysyms
for view in layout.views.values() {
for (_y, row) in &view.get_rows() {
for (_x, button) in &row.buttons {
for row in &view.rows {
for button in &row.buttons {
let keystate = button.state.borrow();
for keycode in &keystate.keycodes {
match state.key_get_one_sym(*keycode) {

View File

@ -2,8 +2,6 @@
use std::collections::HashMap;
use std::rc::Rc;
use ::float_ord::FloatOrd;
use std::borrow::Borrow;
use std::hash::{ Hash, Hasher };
use std::iter::FromIterator;
@ -21,7 +19,6 @@ pub mod c {
use std::borrow::ToOwned;
// The lifetime on input limits the existence of the result
pub fn as_str(s: &*const c_char) -> Result<Option<&str>, Utf8Error> {
if s.is_null() {
Ok(None)
@ -145,16 +142,6 @@ pub fn hash_map_map<K, V, F, K1, V1>(map: HashMap<K, V>, mut f: F)
)
}
pub fn find_max_double<T, I, F>(iterator: I, get: F)
-> f64
where I: Iterator<Item=T>,
F: Fn(&T) -> f64
{
iterator.map(|value| FloatOrd(get(&value)))
.max().unwrap_or(FloatOrd(0f64))
.0
}
/// Compares pointers but not internal values of Rc
pub struct Pointer<T>(pub Rc<T>);
@ -190,6 +177,27 @@ impl<T> Borrow<Rc<T>> for Pointer<T> {
}
}
/// Sugar for logging errors in results
pub trait Warn {
type Value;
fn ok_warn(self, msg: &str) -> Option<Self::Value>;
}
impl<T, E: std::error::Error> Warn for Result<T, E> {
type Value = T;
fn ok_warn(self, msg: &str) -> Option<T> {
self.map_err(|e| {
eprintln!("{}: {}", msg, e);
e
}).ok()
}
}
pub trait WarningHandler {
/// Handle a warning
fn handle(&mut self, warning: &str);
}
#[cfg(test)]
mod tests {
use super::*;

41
tests/entry.py Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import gi
import sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class App(Gtk.Application):
purposes = [
("Free form", Gtk.InputPurpose.FREE_FORM),
("Alphabetical", Gtk.InputPurpose.ALPHA),
("Digits", Gtk.InputPurpose.DIGITS),
("Number", Gtk.InputPurpose.NUMBER),
("Phone", Gtk.InputPurpose.PHONE),
("URL", Gtk.InputPurpose.URL),
("E-mail", Gtk.InputPurpose.EMAIL),
("Name", Gtk.InputPurpose.NAME),
("Password", Gtk.InputPurpose.PASSWORD),
("PIN", Gtk.InputPurpose.PIN)
]
def do_activate(self):
w = Gtk.ApplicationWindow(application=self)
grid = Gtk.Grid(orientation='vertical', column_spacing=8, row_spacing=8)
i = 0
for text, purpose in self.purposes:
l = Gtk.Label(label=text)
e = Gtk.Entry(hexpand=True)
e.set_input_purpose(purpose)
grid.attach(l, 0, i, 1, 1)
grid.attach(e, 1, i, 1, 1)
i += 1
w.add(grid)
w.show_all()
app = App()
app.run(sys.argv)

View File

@ -1,9 +1,15 @@
---
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "test"
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }
buttons:
test:

View File

@ -1,5 +1,11 @@
---
# missing views
bounds:
x: 0
y: 0
width: 0
height: 0
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }

View File

@ -1,9 +1,15 @@
---
# extra field
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "test"
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }
bad_field: false

View File

@ -1,10 +1,16 @@
---
# punctuation
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "."
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }
buttons:
".":

View File

@ -1,10 +1,16 @@
---
# punctuation
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "å"
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }
buttons:
å:

View File

@ -1,8 +1,14 @@
---
# punctuation
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "か゚" # 2 codepoints
outlines:
default: { width: 0, height: 0 }
default:
bounds: { x: 0, y: 0, width: 0, height: 0 }

View File

@ -1,9 +0,0 @@
---
# Margins present
margins: { top: 1, side: 2, bottom: 3 }
views:
base:
- "test"
outlines:
default: { width: 1, height: 1 }

View File

@ -1,9 +0,0 @@
---
# Margins present
margins: { top: 1, side: 2, bottom: 3 }
views:
base:
- "test"
outlines:
default: { width: 1, height: 1 }

View File

@ -54,13 +54,10 @@ foreach layout : [
'es',
'fi',
'it',
'jp+kana','jp+kana_wide',
'jp+kana',
'no',
'number',
'se',
'terminal',
'emoji',
]
test(
'test_layout_' + layout,

View File

@ -1,63 +0,0 @@
#!/usr/bin/env python3
import gi
import sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
try:
terminal = [("Terminal", Gtk.InputPurpose.TERMINAL)]
except AttributeError:
print("Terminal purpose not available on this GTK version", file=sys.stderr)
terminal = []
def new_grid(items, set_type):
grid = Gtk.Grid(orientation='vertical', column_spacing=8, row_spacing=8)
i = 0
for text, value in items:
l = Gtk.Label(label=text)
e = Gtk.Entry(hexpand=True)
set_type(e, value)
grid.attach(l, 0, i, 1, 1)
grid.attach(e, 1, i, 1, 1)
i += 1
return grid
class App(Gtk.Application):
purposes = [
("Free form", Gtk.InputPurpose.FREE_FORM),
("Alphabetical", Gtk.InputPurpose.ALPHA),
("Digits", Gtk.InputPurpose.DIGITS),
("Number", Gtk.InputPurpose.NUMBER),
("Phone", Gtk.InputPurpose.PHONE),
("URL", Gtk.InputPurpose.URL),
("E-mail", Gtk.InputPurpose.EMAIL),
("Name", Gtk.InputPurpose.NAME),
("Password", Gtk.InputPurpose.PASSWORD),
("PIN", Gtk.InputPurpose.PIN),
] + terminal
hints = [
("OSK provided", Gtk.InputHints.INHIBIT_OSK)
]
def do_activate(self):
w = Gtk.ApplicationWindow(application=self)
notebook = Gtk.Notebook()
def add_purpose(entry, purpose):
entry.set_input_purpose(purpose)
def add_hint(entry, hint):
entry.set_input_hints(hint)
purpose_grid = new_grid(self.purposes, add_purpose)
hint_grid = new_grid(self.hints, add_hint)
notebook.append_page(purpose_grid, Gtk.Label(label="Purposes"))
notebook.append_page(hint_grid, Gtk.Label(label="Hints"))
w.add(notebook)
w.show_all()
app = App()
app.run(sys.argv)

View File

@ -1,19 +0,0 @@
entry = configure_file(
copy: true,
input: 'entry.py',
output: 'squeekboard-entry',
install: true,
install_dir: bindir,
)
test_layout = custom_target('squeekboard-test-layout',
build_by_default: true,
# meson doesn't track all inputs, cargo does
build_always_stale: true,
output: ['squeekboard-test-layout'],
console: true,
command: [cargo_build] + cargo_build_flags
+ ['--rename', 'test_layout', '@OUTPUT@', '--bin', 'test_layout'],
install: true,
install_dir: bindir,
)