Compare commits

...

44 Commits

Author SHA1 Message Date
273423f626 Release 1.7.0 "Mycelium"
Enables a terminal layout, which will activate whenever the terminal input hint is received.

Arm64 .debs are produced by the CI again.
2020-01-08 12:19:59 +00:00
d80cbf880f cargo: Refresh deps for release 2020-01-08 12:19:53 +00:00
1924a8e634 v1.6.0: Fix suite 2020-01-08 11:52:46 +00:00
647fde26f5 Merge branch 'arm64' into 'master'
CI: Use Librem5 arm64 runner

See merge request Librem5/squeekboard!297
2020-01-07 16:10:25 +00:00
23f8f9b091 Merge branch '1.6' into 'master'
Release 1.6.0 "Specific impulse"

See merge request Librem5/squeekboard!295
2020-01-07 16:08:43 +00:00
c3c1e1c76d CI: Use Librem5 arm64 runner 2020-01-07 14:39:30 +00:00
7a21b992dc Merge branch 'terminal_layout' into 'master'
Terminal layout

See merge request Librem5/squeekboard!279
2020-01-07 12:55:08 +00:00
5485153599 Merge branch 'fix_build' into 'master'
CI: Fix build-dep removed by merge

See merge request Librem5/squeekboard!296
2020-01-04 13:56:23 +00:00
4a92489de8 CI: Fix build-dep removed by merge 2020-01-04 13:34:30 +00:00
825409c97f Merge branch 'osk_entry' into 'master'
tools: Add GTK's INHIBIT_OSK flag to the entry tester

See merge request Librem5/squeekboard!290
2020-01-04 10:49:35 +00:00
6ad85d79e4 Merge branch 'doc' into 'master'
docs: Create with tutorial

See merge request Librem5/squeekboard!285
2020-01-04 10:49:03 +00:00
7e57df3434 Release 1.6.0 "Specific impulse"
New emoji layout, `entry.py` becomes part of the -devel package under the name `squeekboard-entry`.
2020-01-02 12:06:19 +00:00
24cacf988b Merge branch 'type_fixes' into 'master'
Fix g_ and stdlib allocation/free mismatches

See merge request Librem5/squeekboard!294
2019-12-24 22:09:16 +00:00
2657b5ef1f terminal: A more fleshed out layout 2019-12-24 14:33:58 +00:00
674bef2b00 terminal: Use a rudimentary layout on input hint 2019-12-24 14:33:58 +00:00
8e55e9ee56 Fix g_ and stdlib allocation/free mismatches 2019-12-24 14:28:50 +00:00
e1a012cf50 Merge branch 'enoji' into 'master'
Enoji: implemented mechanism

See merge request Librem5/squeekboard!276
2019-12-24 14:21:51 +00:00
50dab14754 emoji: Add a passable layout 2019-12-24 10:41:02 +00:00
733cbe94ee Fix old Rust woes 2019-12-24 10:41:02 +00:00
01a8afad0d popover: Show overlays as selected 2019-12-24 10:41:02 +00:00
bafd1e6eb3 popover: Install emoji layout
In order to do that, an additional piece of state (layout switcher) was exposed to the event handlers, a separation between squeekboard-only and system layouts was introduced, along with a Translation structure to prevent mixing up strings.
2019-12-24 10:41:02 +00:00
a799178b6a Merge branch 'logging' into 'master'
Logging

See merge request Librem5/squeekboard!288
2019-12-24 10:10:30 +00:00
12be3e980f Merge branch 'cleanup' into 'master'
Build cleanups

See merge request Librem5/squeekboard!287
2019-12-23 21:34:18 +00:00
ca8a2baefa Merge branch 'devel' into 'master'
Entry test added to -devel package

See merge request Librem5/squeekboard!286
2019-12-23 21:33:41 +00:00
6b72d09fb8 Merge branch '1.5' into 'master'
Release 1.5.0 "The bends"

See merge request Librem5/squeekboard!293
2019-12-23 15:09:28 +00:00
d76deb0655 Release 1.5.0 "The bends"
This release introduces some renderer improvements, including relating to speed.

Mire importantly, layout files have an incompatible change in format: bounds on the layout are replaced by margins. This removes the possibility that buttons don't fit in the layout and frees layout makers from having to calculate the size of the layout manually.
2019-12-23 12:08:45 +00:00
3b0456b5cd Merge branch 'margins' into 'master'
Use margins, remove bounds

See merge request Librem5/squeekboard!283
2019-12-23 11:56:30 +00:00
77a6ca1900 Merge branch 'arm64' into 'master'
CI: Build arm64 .deb

See merge request Librem5/squeekboard!292
2019-12-20 08:32:54 +00:00
c0331434d7 CI: Build arm64 .deb 2019-12-19 19:38:34 +00:00
f335ea92d4 Merge branch 'readme' into 'master'
Readme updates

See merge request Librem5/squeekboard!281
2019-12-18 19:49:59 +00:00
c8dd34c829 logging: Add described log levels
Not used yet due to conflicts with other MRs.
2019-12-16 19:56:16 +00:00
4d656ff54d logging: Described the design 2019-12-16 19:36:02 +00:00
e2b89e85f7 logging: Move all facilities to one file 2019-12-16 19:15:40 +00:00
b6f3d9c1ea Remove unused header generator 2019-12-16 18:52:50 +00:00
9ff11dc511 Remove unused build dependencies 2019-12-16 18:22:23 +00:00
1cffdda09d packaging: Install entty.py as squeekboard-entry 2019-12-16 18:13:24 +00:00
d9f284b19a build: Move building of squeekboard-test-layout to tools 2019-12-16 17:47:00 +00:00
ed602faeaf tools: Move entry.py 2019-12-16 17:46:42 +00:00
0e1bf19737 docs: Create with tutorial
Create docs, based on Sphinx with Commonmark, seeding it with https://forums.puri.sm/t/translations-and-virtual-touch-keyboards-tracking-localization/7669/48?u=dcz
2019-12-15 21:53:18 +00:00
257b97e9ca layout: Respect margins 2019-12-15 18:43:56 +00:00
5e700219f9 parsing: Remove bounds which weren't used anyway 2019-12-15 18:43:56 +00:00
d5c8f32088 Fix internal .md link 2019-12-11 15:50:28 +00:00
7641b4da6f Create a library/UI module separation 2019-12-11 15:33:29 +00:00
a84730198d readme: Add note about Cargo dependencies 2019-12-11 15:26:27 +00:00
54 changed files with 1250 additions and 405 deletions

View File

@ -14,7 +14,16 @@ before_script:
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list - echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add - - wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
- apt-get -y update - apt-get -y update
- apt-get -y build-dep .
build_docs:
<<: *tags
stage: build
artifacts:
paths:
- _build
script:
- apt-get -y install python3-recommonmark python3-sphinx
- ./doc/build.sh _build
build_meson: build_meson:
<<: *tags <<: *tags
@ -24,16 +33,33 @@ build_meson:
- _build - _build
expire_in: 3h expire_in: 3h
script: script:
- apt-get -y build-dep .
- meson . _build/ -Ddepdatadir=/usr/share - meson . _build/ -Ddepdatadir=/usr/share
- ninja -C _build install - ninja -C _build install
build_deb: build_deb:
<<: *tags tags:
- librem5
stage: build stage: build
artifacts: artifacts:
paths: paths:
- "*.deb" - "*.deb"
script: 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 - apt-get -y install devscripts
- debuild -i -us -uc -b - debuild -i -us -uc -b
- cp ../*.deb . - cp ../*.deb .
@ -53,4 +79,5 @@ test:
needs: needs:
- build_meson - build_meson
script: script:
- apt-get -y build-dep .
- ninja -C _build test - ninja -C _build test

122
Cargo.lock generated
View File

@ -23,16 +23,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"glib-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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.13" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -50,7 +51,7 @@ dependencies = [
"glib 0.6.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)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -61,14 +62,14 @@ dependencies = [
"glib 0.6.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)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.45" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -77,7 +78,7 @@ version = "2.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.13 (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)", "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)", "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)", "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -110,7 +111,7 @@ dependencies = [
"glib 0.6.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)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -125,7 +126,7 @@ dependencies = [
"glib 0.6.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)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -136,8 +137,8 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -150,9 +151,9 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -167,7 +168,7 @@ dependencies = [
"glib-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)", "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)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -177,8 +178,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"glib-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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -190,7 +191,7 @@ dependencies = [
"glib-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)", "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)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -198,8 +199,8 @@ name = "glib-sys"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -208,8 +209,8 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"glib-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)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -220,7 +221,7 @@ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "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-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)", "cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdk 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 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -232,7 +233,7 @@ dependencies = [
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -248,9 +249,17 @@ dependencies = [
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (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)",
] ]
[[package]] [[package]]
@ -260,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.62" version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -283,7 +292,7 @@ name = "memmap"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.62 (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)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -297,7 +306,7 @@ dependencies = [
"glib-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)", "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)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -308,18 +317,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"glib-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)", "gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.16" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.4" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -330,7 +339,7 @@ name = "quote"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -366,37 +375,37 @@ dependencies = [
"gtk-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)",
"maplit 1.0.2 (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)", "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (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.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.101" version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.101" version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.8.9" version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -407,10 +416,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.5" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -475,7 +484,7 @@ name = "xkbcommon"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -491,11 +500,11 @@ dependencies = [
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "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 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 atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7017e53393e713212aed7aea336b6553be4927f58c37070a56c2fe3d107e489"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "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 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-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 cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d25596627380be4381247dba06c69ad05ca21b3b065bd9827e416882ac41dcd2"
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "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 clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum 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 fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
@ -510,24 +519,25 @@ dependencies = [
"checksum gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08475e4a08f27e6e2287005950114735ed61cec2cb8c1187682a5aec8c69b715" "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 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 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 lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum 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 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 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 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 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 pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6eb49268e69dd0c1da5d3001a61aac08e2e9d2bfbe4ae4b19b9963c998f6453"
"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" "checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum 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 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 regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "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 strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "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 textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum 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-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"

View File

@ -25,7 +25,7 @@ sudo apt-get -y build-dep .
``` ```
For an explicit list of dependencies check the `Build-Depends` entry in the For an explicit list of dependencies check the `Build-Depends` entry in the
[debian/control][] file. [`debian/control`](./debian/control) file.
Testing Testing
------- -------
@ -40,7 +40,7 @@ Most common testing is done in CI. Occasionally, and for each release, do perfor
Testing with an application: Testing with an application:
``` ```
python3 tests/entry.py python3 tools/entry.py
``` ```
Testing visibility: Testing visibility:
@ -62,6 +62,24 @@ $ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb',
Coding 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: Code submitted should roughly match the style of surrounding code. Things that will *not* be accepted are ones that often lead to errors:
- skipping brackets `{}` after every `if()`, `else`, and similar - skipping brackets `{}` after every `if()`, `else`, and similar
@ -122,6 +140,8 @@ sh /source_path/cargo.sh test
### Cargo dependencies ### 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. Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own: `Cargo.lock` is used for remembering the revisions of all Rust dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:

View File

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

View File

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

View File

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

16
data/keyboards/emoji.yaml Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

75
debian/changelog vendored
View File

@ -1,3 +1,78 @@
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 squeekboard (1.4.0) amber-phone; urgency=medium
* "text" property in layouts * "text" property in layouts

8
debian/control vendored
View File

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

View File

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

18
doc/build.sh Executable file
View File

@ -0,0 +1,18 @@
#!/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}"

165
doc/conf.py Normal file
View File

@ -0,0 +1,165 @@
# -*- 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)

21
doc/index.md Normal file
View File

@ -0,0 +1,21 @@
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.

53
doc/tutorial.md Normal file
View File

@ -0,0 +1,53 @@
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

@ -131,14 +131,17 @@ static void drag(EekGtkKeyboard *self,
{ {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
x, y, eek_renderer_get_transformation(priv->renderer), time, self); x, y, eek_renderer_get_transformation(priv->renderer), time,
priv->keyboard->manager, self);
} }
static void release(EekGtkKeyboard *self, guint32 time) static void release(EekGtkKeyboard *self, guint32 time)
{ {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); 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, self); squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
eek_renderer_get_transformation(priv->renderer), time,
priv->keyboard->manager, self);
} }
static gboolean static gboolean

View File

@ -30,7 +30,6 @@
#include "config.h" #include "config.h"
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include "eek-enumtypes.h"
#include "eekboard/eekboard-context-service.h" #include "eekboard/eekboard-context-service.h"
#include "eekboard/key-emitter.h" #include "eekboard/key-emitter.h"
#include "keymap.h" #include "keymap.h"

View File

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

View File

@ -71,6 +71,8 @@ struct _EekboardContextServicePrivate {
LevelKeyboard *keyboard; // currently used keyboard LevelKeyboard *keyboard; // currently used keyboard
GHashTable *keyboard_hash; // a table of available keyboards, per layout GHashTable *keyboard_hash; // a table of available keyboards, per layout
char *overlay;
GSettings *settings; GSettings *settings;
uint32_t hint; uint32_t hint;
uint32_t purpose; uint32_t purpose;
@ -214,15 +216,17 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
void void
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t) eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t)
{ {
g_autofree gchar *keyboard_type = NULL;
g_autofree gchar *keyboard_layout = NULL; g_autofree gchar *keyboard_layout = NULL;
settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout); if (context->priv->overlay) {
keyboard_layout = g_strdup(context->priv->overlay);
if (!keyboard_type) { } else {
keyboard_type = g_strdup("us"); g_autofree gchar *keyboard_type = NULL;
settings_get_layout(context->priv->settings,
&keyboard_type, &keyboard_layout);
} }
if (!keyboard_layout) { if (!keyboard_layout) {
keyboard_layout = g_strdup("undefined"); keyboard_layout = g_strdup("us");
} }
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context); EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
@ -232,6 +236,9 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE: case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("number"); keyboard_layout = g_strdup("number");
break; break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
keyboard_layout = g_strdup("terminal");
break;
default: default:
; ;
} }
@ -262,6 +269,8 @@ settings_handle_layout_changed(GSettings *s,
(void)keys; (void)keys;
(void)n_keys; (void)n_keys;
EekboardContextService *context = user_data; EekboardContextService *context = user_data;
g_free(context->priv->overlay);
context->priv->overlay = NULL;
update_layout_and_type(context); update_layout_and_type(context);
return TRUE; return TRUE;
} }
@ -391,6 +400,8 @@ eekboard_context_service_init (EekboardContextService *self)
g_warning ("Could not connect to gsettings updates, layout" g_warning ("Could not connect to gsettings updates, layout"
" changing unavailable"); " changing unavailable");
} }
self->priv->overlay = NULL;
} }
/** /**
@ -463,6 +474,7 @@ eekboard_context_service_destroy (EekboardContextService *context)
if (context->priv->enabled) { if (context->priv->enabled) {
eekboard_context_service_disable (context); eekboard_context_service_disable (context);
} }
g_free(context->priv->overlay);
g_signal_emit (context, signals[DESTROYED], 0); g_signal_emit (context, signals[DESTROYED], 0);
} }
@ -498,3 +510,14 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
update_layout_and_type(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( project(
'squeekboard', 'squeekboard',
'c', 'rust', 'c', 'rust',
version: '1.4.0', version: '1.7.0',
license: 'GPLv3', license: 'GPLv3',
meson_version: '>=0.51.0', meson_version: '>=0.51.0',
default_options: [ default_options: [
@ -40,6 +40,7 @@ else
endif endif
prefix = get_option('prefix') prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir')) datadir = join_paths(prefix, get_option('datadir'))
pkgdatadir = join_paths(datadir, meson.project_name()) pkgdatadir = join_paths(datadir, meson.project_name())
if get_option('depdatadir') == '' if get_option('depdatadir') == ''
@ -65,6 +66,6 @@ cargo_build = find_program('cargo_build.sh')
subdir('data') subdir('data')
subdir('protocols') subdir('protocols')
subdir('eek')
subdir('src') subdir('src')
subdir('tools')
subdir('tests') subdir('tests')

View File

@ -1,5 +1,7 @@
/**! The parsing of the data files for layouts */ /**! 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::cell::RefCell;
use std::collections::{ HashMap, HashSet }; use std::collections::{ HashMap, HashSet };
use std::env; use std::env;
@ -19,17 +21,17 @@ use ::keyboard::{
}; };
use ::layout; use ::layout;
use ::layout::ArrangementKind; use ::layout::ArrangementKind;
use ::logging::PrintWarnings;
use ::resources; use ::resources;
use ::util::c::as_str; use ::util::c::as_str;
use ::util::hash_map_map; use ::util::hash_map_map;
use ::xdg; use ::xdg;
// traits, derives // traits, derives
use serde::Deserialize;
use std::io::BufReader; use std::io::BufReader;
use std::iter::FromIterator; use std::iter::FromIterator;
use serde::Deserialize; use ::logging::WarningHandler;
use util::WarningHandler;
/// Gathers stuff defined in C or called by C /// Gathers stuff defined in C or called by C
pub mod c { pub mod c {
@ -152,14 +154,6 @@ fn list_layout_sources(
ret ret
} }
struct PrintWarnings;
impl WarningHandler for PrintWarnings {
fn handle(&mut self, warning: &str) {
println!("{}", warning);
}
}
fn load_layout_data(source: DataSource) fn load_layout_data(source: DataSource)
-> Result<::layout::LayoutData, LoadError> -> Result<::layout::LayoutData, LoadError>
{ {
@ -216,21 +210,20 @@ fn load_layout_data_with_fallback(
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Layout { pub struct Layout {
/// FIXME: deprecate in favor of margins #[serde(default)]
bounds: Bounds, margins: Margins,
views: HashMap<String, Vec<ButtonIds>>, views: HashMap<String, Vec<ButtonIds>>,
#[serde(default)] #[serde(default)]
buttons: HashMap<String, ButtonMeta>, buttons: HashMap<String, ButtonMeta>,
outlines: HashMap<String, Outline> outlines: HashMap<String, Outline>
} }
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq, Default)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct Bounds { struct Margins {
x: f64, top: f64,
y: f64, bottom: f64,
width: f64, side: f64,
height: f64,
} }
/// Buttons are embedded in a single string /// Buttons are embedded in a single string
@ -271,8 +264,8 @@ enum Action {
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct Outline { struct Outline {
/// FIXME: replace with Size width: f64,
bounds: Bounds, height: f64,
} }
/// Errors encountered loading the layout into yaml /// Errors encountered loading the layout into yaml
@ -460,10 +453,10 @@ impl Layout {
}, },
// FIXME: use a dedicated field // FIXME: use a dedicated field
margins: layout::Margins { margins: layout::Margins {
top: self.bounds.x, top: self.margins.top,
left: self.bounds.y, left: self.margins.side,
bottom: 0.0, bottom: self.margins.bottom,
right: self.bounds.y, right: self.margins.side,
}, },
}), }),
warning_handler, warning_handler,
@ -649,9 +642,7 @@ fn create_button<H: WarningHandler>(
warning_handler.handle( warning_handler.handle(
&format!("No default outline defined! Using 1x1!") &format!("No default outline defined! Using 1x1!")
); );
Outline { Outline { width: 1f64, height: 1f64 }
bounds: Bounds { x: 0f64, y: 0f64, width: 1f64, height: 1f64 },
}
}); });
layout::Button { layout::Button {
@ -659,8 +650,8 @@ fn create_button<H: WarningHandler>(
outline_name: CString::new(outline_name).expect("Bad outline"), outline_name: CString::new(outline_name).expect("Bad outline"),
// TODO: do layout before creating buttons // TODO: do layout before creating buttons
size: layout::Size { size: layout::Size {
width: outline.bounds.width, width: outline.width,
height: outline.bounds.height, height: outline.height,
}, },
label: label, label: label,
state: state, state: state,
@ -672,21 +663,14 @@ mod tests {
use super::*; use super::*;
use std::error::Error as ErrorTrait; use std::error::Error as ErrorTrait;
use ::logging::PanicWarn;
struct PanicWarn;
impl WarningHandler for PanicWarn {
fn handle(&mut self, warning: &str) {
panic!("{}", warning);
}
}
#[test] #[test]
fn test_parse_path() { fn test_parse_path() {
assert_eq!( assert_eq!(
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(), Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
Layout { Layout {
bounds: Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 }, margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 },
views: hashmap!( views: hashmap!(
"base".into() => vec!("test".into()), "base".into() => vec!("test".into()),
), ),
@ -701,11 +685,7 @@ mod tests {
} }
}, },
outlines: hashmap!{ outlines: hashmap!{
"default".into() => Outline { "default".into() => Outline { width: 0f64, height: 0f64 },
bounds: Bounds {
x: 0f64, y: 0f64, width: 0f64, height: 0f64
},
}
}, },
} }
); );
@ -855,4 +835,21 @@ 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

@ -36,6 +36,7 @@ void squeek_layout_free(struct squeek_layout*);
void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
struct transformation widget_to_layout, struct transformation widget_to_layout,
uint32_t timestamp, uint32_t timestamp,
EekboardContextService *manager,
EekGtkKeyboard *ui_keyboard); 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_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp);
void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
@ -45,7 +46,8 @@ 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, void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
double x_widget, double y_widget, double x_widget, double y_widget,
struct transformation widget_to_layout, struct transformation widget_to_layout,
uint32_t timestamp, EekGtkKeyboard *ui_keyboard); uint32_t timestamp, EekboardContextService *manager,
EekGtkKeyboard *ui_keyboard);
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
#endif #endif

View File

@ -26,6 +26,7 @@ use std::vec::Vec;
use ::action::Action; use ::action::Action;
use ::drawing; use ::drawing;
use ::keyboard::{ KeyState, PressType }; use ::keyboard::{ KeyState, PressType };
use ::manager;
use ::submission::{ Timestamp, VirtualKeyboard }; use ::submission::{ Timestamp, VirtualKeyboard };
use ::util::find_max_double; use ::util::find_max_double;
@ -99,7 +100,7 @@ pub mod c {
} }
} }
/// Scale + translate /// Translate and then scale
#[repr(C)] #[repr(C)]
pub struct Transformation { pub struct Transformation {
pub origin_x: f64, pub origin_x: f64,
@ -108,6 +109,14 @@ pub mod c {
} }
impl Transformation { impl Transformation {
/// Applies the new transformation after this one
pub fn chain(self, next: Transformation) -> Transformation {
Transformation {
origin_x: self.origin_x + self.scale * next.origin_x,
origin_y: self.origin_y + self.scale * next.origin_y,
scale: self.scale * next.scale,
}
}
fn forward(&self, p: Point) -> Point { fn forward(&self, p: Point) -> Point {
Point { Point {
x: (p.x - self.origin_x) / self.scale, x: (p.x - self.origin_x) / self.scale,
@ -195,7 +204,8 @@ pub mod c {
println!("{:?}", button); println!("{:?}", button);
} }
/// Positions the layout within the available space /// Positions the layout contents within the available space.
/// The origin of the transformation is the point inside the margins.
#[no_mangle] #[no_mangle]
pub extern "C" pub extern "C"
fn squeek_layout_calculate_transformation( fn squeek_layout_calculate_transformation(
@ -204,15 +214,10 @@ pub mod c {
allocation_height: f64, allocation_height: f64,
) -> Transformation { ) -> Transformation {
let layout = unsafe { &*layout }; let layout = unsafe { &*layout };
let size = layout.calculate_size(); layout.calculate_transformation(Size {
let h_scale = allocation_width / size.width; width: allocation_width,
let v_scale = allocation_height / size.height; height: allocation_height,
let scale = if h_scale < v_scale { h_scale } else { v_scale }; })
Transformation {
origin_x: (allocation_width - (scale * size.width)) / 2.0,
origin_y: (allocation_height - (scale * size.height)) / 2.0,
scale: scale,
}
} }
#[no_mangle] #[no_mangle]
@ -254,6 +259,7 @@ pub mod c {
virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend
widget_to_layout: Transformation, widget_to_layout: Transformation,
time: u32, time: u32,
manager: manager::c::Manager,
ui_keyboard: EekGtkKeyboard, ui_keyboard: EekGtkKeyboard,
) { ) {
let time = Timestamp(time); let time = Timestamp(time);
@ -269,6 +275,7 @@ pub mod c {
&widget_to_layout, &widget_to_layout,
time, time,
ui_keyboard, ui_keyboard,
manager,
key, key,
); );
} }
@ -340,6 +347,7 @@ pub mod c {
x_widget: f64, y_widget: f64, x_widget: f64, y_widget: f64,
widget_to_layout: Transformation, widget_to_layout: Transformation,
time: u32, time: u32,
manager: manager::c::Manager,
ui_keyboard: EekGtkKeyboard, ui_keyboard: EekGtkKeyboard,
) { ) {
let time = Timestamp(time); let time = Timestamp(time);
@ -374,6 +382,7 @@ pub mod c {
&widget_to_layout, &widget_to_layout,
time, time,
ui_keyboard, ui_keyboard,
manager,
key, key,
); );
} }
@ -391,6 +400,7 @@ pub mod c {
&widget_to_layout, &widget_to_layout,
time, time,
ui_keyboard, ui_keyboard,
manager,
key, key,
); );
} }
@ -427,7 +437,7 @@ pub struct ButtonPlace<'a> {
offset: c::Point, offset: c::Point,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub struct Size { pub struct Size {
pub width: f64, pub width: f64,
pub height: f64, pub height: f64,
@ -560,6 +570,7 @@ pub enum ArrangementKind {
Wide = 1, Wide = 1,
} }
#[derive(Debug, PartialEq)]
pub struct Margins { pub struct Margins {
pub top: f64, pub top: f64,
pub bottom: f64, pub bottom: f64,
@ -713,7 +724,8 @@ impl Layout {
}; };
} }
fn calculate_size(&self) -> Size { /// Calculates size without margins
fn calculate_inner_size(&self) -> Size {
Size { Size {
height: find_max_double( height: find_max_double(
self.views.iter(), self.views.iter(),
@ -725,6 +737,39 @@ impl Layout {
), ),
} }
} }
/// Size including margins
fn calculate_size(&self) -> Size {
let inner_size = self.calculate_inner_size();
Size {
width: self.margins.left + inner_size.width + self.margins.right,
height: (
self.margins.top
+ inner_size.height
+ self.margins.bottom
),
}
}
pub fn calculate_transformation(
&self,
available: Size,
) -> c::Transformation {
let size = self.calculate_size();
let h_scale = available.width / size.width;
let v_scale = available.height / size.height;
let scale = if h_scale < v_scale { h_scale } else { v_scale };
let outside_margins = c::Transformation {
origin_x: (available.width - (scale * size.width)) / 2.0,
origin_y: (available.height - (scale * size.height)) / 2.0,
scale: scale,
};
outside_margins.chain(c::Transformation {
origin_x: self.margins.left,
origin_y: self.margins.top,
scale: 1.0,
})
}
} }
mod procedures { mod procedures {
@ -814,6 +859,7 @@ mod seat {
widget_to_layout: &c::Transformation, widget_to_layout: &c::Transformation,
time: Timestamp, time: Timestamp,
ui_keyboard: c::EekGtkKeyboard, ui_keyboard: c::EekGtkKeyboard,
manager: manager::c::Manager,
key: &Rc<RefCell<KeyState>>, key: &Rc<RefCell<KeyState>>,
) { ) {
layout.release_key(virtual_keyboard, &mut key.clone(), time); layout.release_key(virtual_keyboard, &mut key.clone(), time);
@ -835,7 +881,8 @@ mod seat {
}; };
::popover::show( ::popover::show(
ui_keyboard, ui_keyboard,
widget_to_layout.reverse_bounds(bounds) widget_to_layout.reverse_bounds(bounds),
manager,
); );
} }
} }
@ -907,4 +954,58 @@ mod test {
.is_none() .is_none()
); );
} }
#[test]
fn check_bottom_margin() {
// just one button
let view = View::new(vec![
(
0.0,
Row {
angle: 0,
buttons: vec![(
0.0,
Box::new(Button {
size: Size { width: 1.0, height: 1.0 },
..*make_button_with_state("foo".into(), make_state())
}),
)]
},
),
]);
let layout = Layout {
current_view: String::new(),
keymap_str: CString::new("").unwrap(),
kind: ArrangementKind::Base,
locked_keys: HashSet::new(),
pressed_keys: HashSet::new(),
// Lots of bottom margin
margins: Margins {
top: 0.0,
left: 0.0,
right: 0.0,
bottom: 1.0,
},
views: hashmap! {
String::new() => view,
},
};
assert_eq!(
layout.calculate_inner_size(),
Size { width: 1.0, height: 1.0 }
);
assert_eq!(
layout.calculate_size(),
Size { width: 1.0, height: 2.0 }
);
// Don't change those values randomly!
// They take advantage of incidental precise float representation
// to even be comparable.
let transformation = layout.calculate_transformation(
Size { width: 2.0, height: 2.0 }
);
assert_eq!(transformation.scale, 1.0);
assert_eq!(transformation.origin_x, 0.5);
assert_eq!(transformation.origin_y, 0.0);
}
} }

View File

@ -24,6 +24,8 @@ mod keyboard;
mod layout; mod layout;
mod locale; mod locale;
mod locale_config; mod locale_config;
mod logging;
mod manager;
mod outputs; mod outputs;
mod popover; mod popover;
mod resources; mod resources;

View File

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

110
src/logging.rs Normal file
View File

@ -0,0 +1,110 @@
/*! 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);
}
}

34
src/manager.rs Normal file
View File

@ -0,0 +1,34 @@
/*! 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,7 +25,6 @@ sources = [
'../eek/eek-xml-layout.c', '../eek/eek-xml-layout.c',
'../eek/layersurface.c', '../eek/layersurface.c',
dbus_src, dbus_src,
enums,
'../eekboard/key-emitter.c', '../eekboard/key-emitter.c',
'../eekboard/eekboard-context-service.c', '../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-service.c', '../eekboard/eekboard-service.c',
@ -112,16 +111,3 @@ squeekboard = executable('squeekboard',
'-DEEK_COMPILATION=1'], '-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,9 +2,11 @@
use gio; use gio;
use gtk; use gtk;
use ::layout::c::EekGtkKeyboard; use std::ffi::CString;
use ::locale::compare_current_locale; use ::layout::c::{ Bounds, EekGtkKeyboard };
use ::locale::{ Translation, compare_current_locale };
use ::locale_config::system_locale; use ::locale_config::system_locale;
use ::manager;
use ::resources; use ::resources;
use gio::ActionMapExt; use gio::ActionMapExt;
@ -92,7 +94,7 @@ mod variants {
} }
} }
fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder { fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder {
let mut xml: Vec<u8> = Vec::new(); let mut xml: Vec<u8> = Vec::new();
writeln!( writeln!(
xml, xml,
@ -101,7 +103,7 @@ fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder {
<menu id=\"app-menu\"> <menu id=\"app-menu\">
<section>" <section>"
).unwrap(); ).unwrap();
for (input_name, human_name) in inputs { for (input_name, translation) in inputs {
writeln!( writeln!(
xml, xml,
" "
@ -110,7 +112,7 @@ fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder {
<attribute name=\"action\">layout</attribute> <attribute name=\"action\">layout</attribute>
<attribute name=\"target\">{}</attribute> <attribute name=\"target\">{}</attribute>
</item>", </item>",
human_name, translation.0,
input_name, input_name,
).unwrap(); ).unwrap();
} }
@ -141,16 +143,79 @@ fn set_layout(kind: String, name: String) {
settings.apply(); settings.apply();
} }
pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { /// 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,
) {
unsafe { gtk::set_initialized() }; unsafe { gtk::set_initialized() };
let window = unsafe { gtk::Widget::from_glib_none(window.0) }; 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 settings = gio::Settings::new("org.gnome.desktop.input-sources");
let inputs = settings.get_value("sources").unwrap(); let inputs = settings.get_value("sources").unwrap();
let inputs = variants::get_tuples(inputs); let inputs = variants::get_tuples(inputs);
let input_names: Vec<&str> = inputs.iter() let system_layouts: Vec<LayoutId> = inputs.into_iter()
.map(|(_kind, name)| name.as_str()) .map(|(kind, name)| LayoutId::System { kind, name })
.collect();
let all_layouts: Vec<LayoutId> = system_layouts.clone()
.into_iter()
.chain(overlay_layouts)
.collect(); .collect();
let translations = system_locale() let translations = system_locale()
@ -162,26 +227,56 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) {
) )
.and_then(|lang| resources::get_layout_names(lang.as_str())); .and_then(|lang| resources::get_layout_names(lang.as_str()));
// sorted collection of human and machine names let translated_names = all_layouts.iter()
let mut human_names: Vec<(&str, &str)> = match translations { .map(LayoutId::get_name);
let translated_names: Vec<Translation> = match translations {
Some(translations) => { Some(translations) => {
input_names.iter() translated_names
.map(|name| (*name, *translations.get(name).unwrap_or(name))) .map(move |name| {
translations.get(name)
.map(|translation| translation.clone())
.unwrap_or(Translation(name))
})
.collect() .collect()
}, },
// display bare codes
None => { None => {
input_names.iter() translated_names.map(|name| Translation(name))
.map(|n| (*n, *n)) // turns &&str into &str
.collect() .collect()
} },
}; };
human_names.sort_unstable_by(|(_, human_label_a), (_, human_label_b)| { // sorted collection of human and machine names
compare_current_locale(human_label_a, human_label_b) 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)
}); });
let builder = make_menu_builder(human_names); // 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();
// Much more debuggable to populate the model & menu // Much more debuggable to populate the model & menu
// from a string representation // from a string representation
// than add items imperatively // than add items imperatively
@ -195,16 +290,21 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) {
height: position.width.floor() as i32, height: position.width.floor() as i32,
}); });
if let Some(current_name) = input_names.get(0) { if let Some(current_layout) = get_current_layout(manager, &system_layouts) {
let current_name = current_name.to_variant(); let current_name_variant = choices.iter()
.find(
|(_id, layout)| layout == &current_layout
).unwrap()
.0.to_variant();
let layout_action = gio::SimpleAction::new_stateful( let layout_action = gio::SimpleAction::new_stateful(
"layout", "layout",
Some(current_name.type_()), Some(current_name_variant.type_()),
&current_name, &current_name_variant,
); );
layout_action.connect_change_state(|_action, state| { let menu_inner = menu.clone();
layout_action.connect_change_state(move |_action, state| {
match state { match state {
Some(v) => { Some(v) => {
v.get::<String>() v.get::<String>()
@ -212,10 +312,20 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) {
eprintln!("Variant is not string: {:?}", v); eprintln!("Variant is not string: {:?}", v);
None None
}) })
.map(|state| set_layout("xkb".into(), state)); .map(|state| {
let (_id, layout) = choices.iter()
.find(
|choices| state == choices.0
).unwrap();
set_visible_layout(
manager,
layout.clone(),
)
});
}, },
None => eprintln!("No variant selected"), None => eprintln!("No variant selected"),
}; };
menu_inner.popdown();
}); });
let action_group = gio::SimpleActionGroup::new(); let action_group = gio::SimpleActionGroup::new();

View File

@ -3,6 +3,7 @@
*/ */
use std::collections::HashMap; use std::collections::HashMap;
use ::locale::Translation;
use std::iter::FromIterator; use std::iter::FromIterator;
@ -23,6 +24,9 @@ const KEYBOARDS: &[(*const str, *const str)] = &[
("no", include_str!("../data/keyboards/no.yaml")), ("no", include_str!("../data/keyboards/no.yaml")),
("number", include_str!("../data/keyboards/number.yaml")), ("number", include_str!("../data/keyboards/number.yaml")),
("se", include_str!("../data/keyboards/se.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> { pub fn get_keyboard(needle: &str) -> Option<&'static str> {
@ -39,6 +43,18 @@ 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 /// Translations of the layout identifier strings
const LAYOUT_NAMES: &[(*const str, *const str)] = &[ const LAYOUT_NAMES: &[(*const str, *const str)] = &[
("de-DE", include_str!("../data/langs/de-DE.txt")), ("de-DE", include_str!("../data/langs/de-DE.txt")),
@ -49,7 +65,7 @@ const LAYOUT_NAMES: &[(*const str, *const str)] = &[
]; ];
pub fn get_layout_names(lang: &str) pub fn get_layout_names(lang: &str)
-> Option<HashMap<&'static str, &'static str>> -> Option<HashMap<&'static str, Translation<'static>>>
{ {
let translations = LAYOUT_NAMES.iter() let translations = LAYOUT_NAMES.iter()
.find(|(name, _data)| { .find(|(name, _data)| {
@ -63,7 +79,7 @@ pub fn get_layout_names(lang: &str)
translations.map(make_mapping) translations.map(make_mapping)
} }
fn parse_line(line: &str) -> Option<(&str, &str)> { fn parse_line(line: &str) -> Option<(&str, Translation)> {
let comment = line.trim().starts_with("#"); let comment = line.trim().starts_with("#");
if comment { if comment {
None None
@ -71,11 +87,11 @@ fn parse_line(line: &str) -> Option<(&str, &str)> {
let mut iter = line.splitn(2, " "); let mut iter = line.splitn(2, " ");
let name = iter.next().unwrap(); let name = iter.next().unwrap();
// will skip empty and unfinished lines // will skip empty and unfinished lines
iter.next().map(|tr| (name, tr.trim())) iter.next().map(|tr| (name, Translation(tr.trim())))
} }
} }
fn make_mapping(data: &str) -> HashMap<&str, &str> { fn make_mapping(data: &str) -> HashMap<&str, Translation> {
HashMap::from_iter( HashMap::from_iter(
data.split("\n") data.split("\n")
.filter_map(parse_line) .filter_map(parse_line)
@ -86,10 +102,17 @@ fn make_mapping(data: &str) -> HashMap<&str, &str> {
mod test { mod test {
use super::*; use super::*;
#[test]
fn check_overlays_present() {
for name in get_overlays() {
assert!(get_keyboard(name).is_some());
}
}
#[test] #[test]
fn mapping_line() { fn mapping_line() {
assert_eq!( assert_eq!(
Some(("name", "translation")), Some(("name", Translation("translation"))),
parse_line("name translation") parse_line("name translation")
); );
} }

View File

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

View File

@ -3,7 +3,7 @@
use ::data::Layout; use ::data::Layout;
use xkbcommon::xkb; use xkbcommon::xkb;
use ::util::WarningHandler; use ::logging::WarningHandler;
pub struct CountAndPrint(u32); pub struct CountAndPrint(u32);

View File

@ -21,6 +21,7 @@ pub mod c {
use std::borrow::ToOwned; 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> { pub fn as_str(s: &*const c_char) -> Result<Option<&str>, Utf8Error> {
if s.is_null() { if s.is_null() {
Ok(None) Ok(None)
@ -189,27 +190,6 @@ 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -58,6 +58,9 @@ foreach layout : [
'no', 'no',
'number', 'number',
'se', 'se',
'terminal',
'emoji',
] ]
test( test(
'test_layout_' + layout, 'test_layout_' + layout,

19
tools/meson.build Normal file
View File

@ -0,0 +1,19 @@
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,
)