Compare commits

...

51 Commits

Author SHA1 Message Date
cb338129ca Release 1.18.0 "Dunbar's number"
New translations:
- Portugese
- Serbian
- Hungarian
- Turkish
- Polish
- Spanish
- Italian
- Korean
- Occitan
- Georgian

Updated layouts: greek, polytonic

Bug ixes and improvements:
- better panel sizing
- possible to enable debugging messages while Squeekboard is running
- input method state fix
2022-04-25 13:14:00 +00:00
9e8a243439 Update Cargo lock 2022-04-25 13:00:44 +00:00
dcz
d3e0ee8c0d Merge branch 'dc' into 'master'
docs improvements

See merge request World/Phosh/squeekboard!547
2022-04-25 12:14:32 +00:00
2e2c8ab2cb Add Georgian translation 2022-04-23 16:52:05 +00:00
dcz
36474d3e9d Merge branch 'output_fix' into 'master'
Panel handling cleanup

See merge request World/Phosh/squeekboard!529
2022-04-21 07:28:38 +00:00
dcz
e6438503a5 Merge branch 'fix-i386-build' into 'master'
layout: fix build on i386

See merge request World/Phosh/squeekboard!548
2022-04-20 11:22:39 +00:00
58c7fe98b8 layout: fix build on i386
Due to the (lack of) precision of floating-point values, comparison
results may differ slightly between architectures, leading to the
`check_stretching` test failing when building for i386. This can be
fixed by adjusting the value against which we compare the ratio between
x/y scaling factors in `calculate_transformation`.
2022-04-20 12:43:20 +02:00
6867f48bf9 docs: Make index more logical 2022-04-17 07:35:32 +00:00
71942f7221 docs: Link to reference 2022-04-17 07:31:29 +00:00
c486ad1eb3 docs: Update location 2022-04-17 07:25:56 +00:00
05e7cde8fa Add Occitan translation 2022-04-17 07:21:42 +00:00
dcz
9adb593e8e Merge branch 'docs' into 'master'
Add docs to gitlab pages

See merge request World/Phosh/squeekboard!545
2022-04-17 06:24:37 +00:00
073326f31b Merge branch 'zbus' into 'master'
cargo: Add zbus to newer Debian

See merge request World/Phosh/squeekboard!546
2022-04-15 22:36:05 +00:00
dae324f86d cargo: Add zbus to newer Debian 2022-04-13 18:06:13 +00:00
2eec3372f3 panel: Split away panel handling
This reduces ServerContextService to a mere handler of "docked mode" gsetting.
2022-04-13 16:49:33 +00:00
dcz
f6724c0948 Merge branch 'debug' into 'master'
Enable debugging at runtime

See merge request World/Phosh/squeekboard!526
2022-04-13 16:40:36 +00:00
af8b688d94 Add Korean translation 2022-04-13 09:31:50 +00:00
dcz
d21dba6a8f Merge branch 'clap' into 'master'
build: Update clap on newer Debian

See merge request World/Phosh/squeekboard!537
2022-04-12 14:11:02 +00:00
0e2d459d5a CI: Add gitlab pages deployment 2022-04-09 18:34:14 +00:00
89ad302255 CI: Build Rust code reference 2022-04-09 18:34:14 +00:00
dcz
494f9442c4 Merge branch 'allow-stretching' into 'master'
layout: allow stretching the layout by a small amount

See merge request World/Phosh/squeekboard!544
2022-04-09 18:05:20 +00:00
68087a125c layout: allow stretching the layout by a small amount
Due to the way the panel size is calculated, there might be a small
empty space on the sides or top of the layout. This can be an issue,
especially when this empty space is located on the sides, as touch
events in this area are not taken into account.

By allowing a small difference in horizontal and vertical scaling, we
can ensure the panel occupies the whole display width in cases where
this would be problematic.
2022-04-09 16:43:06 +02:00
dcz
323fd7ea14 Merge branch 'phys_size' into 'master'
Physically-based sizing

See merge request World/Phosh/squeekboard!543
2022-04-08 17:30:04 +00:00
dcz
3167cfce9c Merge branch 'gr' into 'master'
layouts: Register gr_wide

See merge request World/Phosh/squeekboard!539
2022-04-07 15:16:03 +00:00
8ea6f6d5c1 layouts: Register gr_wide 2022-04-07 14:59:06 +00:00
dcz
3b70116a15 Merge branch 'gro' into 'master'
layouts: Add Greek Polytonic

See merge request World/Phosh/squeekboard!540
2022-04-07 14:33:23 +00:00
397f5e126e state: Add sizing unit test 2022-04-07 14:30:46 +00:00
14d7d5d4e0 Clean up size types 2022-04-06 16:03:31 +00:00
6528879fed state: Derive panel size from physical click target size 2022-04-06 15:53:37 +00:00
57aeeaa882 output: Store physical size 2022-04-06 08:58:41 +00:00
bbceba7e9b debug: Add dbus interface to control debug prints 2022-04-05 14:19:52 +00:00
dcz
5a210712f6 Merge branch 'fix' into 'master'
Fix scaling to set height

See merge request World/Phosh/squeekboard!535
2022-04-05 11:55:55 +00:00
bb8bba163e layouts: Add Greek Polytonic
By Antonis Tsolomitis <atsol@aegean.gr>
2022-04-05 11:41:27 +00:00
83b0d1553f state: fix "wide mode" detection in portrait orientation
We need to check if we should use the wide layout based on the
*logical* display width, not its *physical* resolution.
2022-04-05 10:16:22 +00:00
dcz
a1664630ed Merge branch 'testing_updated_gr_and_new_gr_wide' into 'master'
Update gr.yaml to take advantage of more space per symbol. Creation of a wide variant...

See merge request World/Phosh/squeekboard!532
2022-04-05 10:02:05 +00:00
529ac89150 Update gr.yaml to take advantage of more space per symbol. Creation of a wide variant... 2022-04-05 10:02:05 +00:00
479f1befc9 Merge branch 'dont-reset-state-on-done' into HEAD 2022-04-05 09:59:56 +00:00
29b30fbe22 panel: Use scaling to set height 2022-04-05 09:26:11 +00:00
1ccc663c48 build: Update clap on newer Debian 2022-04-05 09:17:04 +00:00
dcz
7c43528ebf Merge branch 'fix_meson' into 'master'
build: Replace missing crates.io dependency with Purism-hosted one

See merge request World/Phosh/squeekboard!536
2022-04-05 09:16:12 +00:00
7f4c823c1e ci: Allow failure on sid 2022-04-04 17:54:31 +00:00
d19050e06d build: Replace missing crates.io dependency with Purism-hosted one 2022-04-04 17:48:54 +00:00
b5142ac765 Add Italian translation 2022-04-04 07:07:48 +00:00
b456889fe9 Add Spanish translation 2022-03-23 11:19:44 +00:00
3fdbcf905b Add Polish translation 2022-03-20 13:14:03 +00:00
8a2de2fdf2 Add Turkish translation 2022-03-19 09:34:34 +00:00
bd390894c5 Add Hungarian translation 2022-03-16 00:57:01 +00:00
04018a8c06 Do not reset pending state on zwp_input_method_v2.done 2022-03-15 15:51:09 -04:00
b4cd5659cb Add Serbian translation 2022-03-12 12:03:51 +00:00
dcz
59c3da0344 Merge branch 'v1.17.0' into 'master'
Release 1.17.0 "Ergodicity"

See merge request World/Phosh/squeekboard!531
2022-03-08 10:15:13 +00:00
c5eb41292c Add Portuguese translation 2022-02-26 18:28:13 +00:00
56 changed files with 2315 additions and 393 deletions

View File

@ -3,6 +3,7 @@ image: pureos/byzantium
stages: stages:
- build - build
- test - test
- deploy
before_script: before_script:
- apt-get -y update - apt-get -y update
@ -74,6 +75,7 @@ build_deb:arm64:
build_deb:future: build_deb:future:
image: debian:sid image: debian:sid
allow_failure: true
tags: tags:
- aarch64 - aarch64
stage: build stage: build
@ -93,6 +95,22 @@ build_deb:future:
- debuild -i -us -uc -b - debuild -i -us -uc -b
- cp ../*.deb . - cp ../*.deb .
build_reference:
stage: build
needs:
- job: build_meson
artifacts: true
artifacts:
paths:
- _build/doc
script:
- apt-get -y install cargo
- cd _build
- ../cargo.sh doc --no-deps --document-private-items
except:
variables:
- $PKG_ONLY == "1"
test_lintian: test_lintian:
stage: test stage: test
needs: needs:
@ -141,3 +159,17 @@ check_release:
except: except:
variables: variables:
- $PKG_ONLY == "1" - $PKG_ONLY == "1"
pages:
stage: deploy
needs:
- build_docs
- build_reference
script:
- mv _build/ public/
artifacts:
paths:
- public
only:
refs:
- master

View File

@ -1,6 +1,10 @@
# Dependencies which change based on build flags # Dependencies which change based on build flags
bitflags = "1.2.*" bitflags = "1.2.*"
clap = { version = "2.33.*", default-features = false } clap = { version = "2.33.*", default-features = false }
zbus = "1.0.*"
zvariant = "2.0.*"
# Newer versions seem to confuse the version of Cargo on Debian Bullseye
zvariant_derive = "2.0.*"
[dependencies.cairo-rs] [dependencies.cairo-rs]
version = "0.7.*" version = "0.7.*"
@ -29,4 +33,4 @@ features = ["v3_22"]
[dependencies.gtk-sys] [dependencies.gtk-sys]
version = "0.9" version = "0.9"
features = ["v3_22"] features = ["v3_22"]

View File

@ -1,7 +1,11 @@
# Dependencies which change based on build flags # Dependencies which change based on build flags
# For the newer-than-Byzantium config # For the newer-than-Byzantium config
bitflags = "1.3.*" bitflags = "1.3.*"
clap = { version = "2.33.*", default-features = false } clap = { version = "3.1.*", features=["std"], default-features = false }
zbus = "1.9.*"
zvariant = "2.10.*"
# Newer versions seem to confuse the version of Cargo on Debian Bullseye
zvariant_derive = "2.10.*"
[dependencies.cairo-rs] [dependencies.cairo-rs]
version = "0.14.*" version = "0.14.*"

4
Cargo.deps.online Normal file
View File

@ -0,0 +1,4 @@
# Dependencies which are only used with online, crates.io builds.
[patch.crates-io]
# Dependency was yanked, but gio 0.7 needs it.
fragile = { git = "https://source.puri.sm/dorota.czaplejewicz/fragile.git", tag = "0.3.0" }

205
Cargo.lock generated
View File

@ -40,6 +40,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.7.1" version = "0.7.1"
@ -71,6 +77,18 @@ version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.33.4" version = "2.33.4"
@ -82,11 +100,51 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "enumflags2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
dependencies = [
"enumflags2_derive",
"serde",
]
[[package]]
name = "enumflags2_derive"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]] [[package]]
name = "fragile" name = "fragile"
version = "0.3.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://source.puri.sm/dorota.czaplejewicz/fragile.git?tag=0.3.0#51048ca11824279c2114c77fef5bcb950838fc09"
checksum = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9"
[[package]] [[package]]
name = "gdk" name = "gdk"
@ -267,14 +325,23 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.8.0" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown",
] ]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -283,9 +350,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.119" version = "0.2.124"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
[[package]] [[package]]
name = "linked-hash-map" name = "linked-hash-map"
@ -309,6 +376,19 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "nix"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.7.0" version = "0.7.0"
@ -338,24 +418,33 @@ dependencies = [
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.24" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro-crate"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
dependencies = [
"toml",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.36" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.15" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -378,6 +467,9 @@ dependencies = [
"serde", "serde",
"serde_yaml", "serde_yaml",
"xkbcommon", "xkbcommon",
"zbus",
"zvariant",
"zvariant_derive",
] ]
[[package]] [[package]]
@ -386,6 +478,12 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.136" version = "1.0.136"
@ -406,6 +504,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_repr"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.8.23" version = "0.8.23"
@ -420,9 +529,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.86" version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -438,6 +547,15 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.9" version = "0.1.9"
@ -450,6 +568,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -490,3 +614,56 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [ dependencies = [
"linked-hash-map", "linked-hash-map",
] ]
[[package]]
name = "zbus"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cb97c72cbfd5c7537ca730eeb810da7348f345ba67ab7673bcbe0d81c076427"
dependencies = [
"byteorder",
"derivative",
"enumflags2",
"fastrand",
"nix",
"scoped-tls",
"serde",
"serde_repr",
"zbus_macros",
"zvariant",
"zvariant_derive",
]
[[package]]
name = "zbus_macros"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0c1f2a20a4cb90922b44d3bebd232b246e52b3dd95ed5bea8aec83cde3a5a8a"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zvariant"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0bf85e67d1a3780cb1c56c80227532354f21907cba14805a773eb507b444580"
dependencies = [
"byteorder",
"enumflags2",
"serde",
]
[[package]]
name = "zvariant_derive"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68726e8c12757384a8d1485080527e263dea67d91f19e97cd71b9292f22d7c5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -86,4 +86,4 @@ It's strongly recommended to support:
Developing Developing
---------- ----------
See [`doc/hacking.md`](doc/hacking.md) for this copy, or the [official documentation](https://developer.puri.sm/projects/squeekboard/) for the current release. See [`doc/hacking.md`](doc/hacking.md) for this copy, or the [official documentation](https://world.pages.gitlab.gnome.org/Phosh/squeekboard) for the current release.

View File

@ -0,0 +1,326 @@
# Greek polytonic layout by Antonis Tsolomitis
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
# March 2022
#
---
outlines:
default: { width: 40, height: 60 }
altline: { width: 52.67, height: 60 }
wide: { width: 62, height: 60 }
extrawide: { width: 66, height: 60 }
spaceline: { width: 140, height: 60 }
special: { width: 44, height: 60 }
views:
base:
- "semicolon ς ε ρ τ υ θ ι ο π"
- "α σ δ φ γ η ξ κ λ show_accents"
- "Shift_L ζ χ ψ ω β ν μ BackSpace"
- "show_numbers preferences space period comma Return"
upper:
- "colon EuroSign Ε Ρ Τ Υ Θ Ι Ο Π"
- "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accents"
- "Shift_L Ζ Χ Ψ Ω Β Ν Μ BackSpace"
- "show_numbers preferences space exclam period_upper Return"
accents:
- "show_psiliordasiaandvaria show_psiliordasiaandoxia show_psiliordasia show_bariaorperispomeni show_oxia"
- "show_PsiliOrDasiaAndVaria show_PsiliOrDasiaAndOxia show_PsiliOrDasia show_BariaOrPerispomeni show_Oxia show_base"
- "show_PsiliOrDasiaAndPerispomeni show_psiliordasiaandperispomeni ᾿ BackSpace"
- "show_numbers preferences space Return"
oxia:
- "ά έ ή ί ϊ ΐ ό ύ ϋ ώ"
- "show_Oxia ᾳ ᾴ ῃ ῄ ῳ ῴ show_base"
- "Ϗ ϐ ϑ ϗ ϖ ΰ ϕ — BackSpace"
- "show_numbers preferences space eis_l eis_r Return"
Oxia:
- "Ά Έ Ή Ί Ϊ Ό Ύ Ϋ Ώ"
- "show_oxia ᾼ ῌ ῼ show_base"
- "Ϗ ϐ ϑ ϗ ϖ ϕ — BackSpace"
- "show_numbers preferences space eis_l eis_r Return"
bariaorperispomeni:
- "ὰ ὲ ὴ ὶ ῒ ὸ ὺ ὼ ῐ ῑ"
- "show_BariaOrPerispomeni ᾳ ᾲ ῃ ῂ ῳ ῲ ῠ show_base"
- "ᾶ ᾷ ῆ ῖ ῗ ῦ ῧ ῶ ῡ BackSpace"
- "show_numbers preferences space ῇ ῷ Return"
BariaOrPerispomeni:
- "Ὰ Ὲ Ὴ Ὶ Ὸ Ὺ Ὼ"
- "show_bariaorperispomeni ᾼ ῌ ῼ show_base"
- "show_numbers preferences space BackSpace Return"
psiliordasia:
- "ἀ ἐ ἠ ἰ ὀ ὐ ὠ ᾀ ᾐ ᾠ"
- "show_PsiliOrDasia ἁ ἑ ἡ ἱ ὁ ὑ ὡ show_base"
- "ᾁ ᾑ ᾡ ῤ ῥ BackSpace"
- "show_numbers preferences space Return"
PsiliOrDasia:
- "Ἀ Ἐ Ἠ Ἰ Ὀ Ὠ ᾈ ᾘ ᾨ"
- "show_psiliordasia Ἁ Ἑ Ἡ Ἱ Ὁ Ὑ Ὡ show_base"
- "ᾉ ᾙ ᾩ Ῥ BackSpace"
- "show_numbers preferences space Return"
psiliordasiaandoxia:
- "ἄ ἔ ἤ ἴ ὄ ὔ ὤ ᾄ ᾔ ᾤ"
- "show_PsiliOrDasiaAndOxia ἅ ἕ ἥ ἵ ὅ ὕ ὥ show_base"
- "ᾅ ᾕ ᾥ BackSpace"
- "show_numbers preferences space Return"
PsiliOrDasiaAndOxia:
- "Ἄ Ἔ Ἤ Ἴ Ὄ Ὤ ᾌ ᾜ ᾬ"
- "show_psiliordasiaandoxia Ἅ Ἕ Ἥ Ἵ Ὅ Ὕ Ὥ show_base"
- "ᾍ ᾝ ᾭ BackSpace"
- "show_numbers preferences space Return"
psiliordasiaandvaria:
- "ἂ ἒ ἢ ἲ ὂ ὒ ὢ ᾂ ᾒ ᾢ"
- "show_PsiliOrDasiaAndVaria ἃ ἓ ἣ ἳ ὃ ὓ ὣ show_base"
- "ᾃ ᾓ ᾣ BackSpace"
- "show_numbers preferences space Return"
PsiliOrDasiaAndVaria:
- "Ἂ Ἒ Ἢ Ἲ Ὂ Ὢ ᾊ ᾚ ᾪ"
- "show_psiliordasiaandvaria Ἃ Ἓ Ἣ Ἳ Ὃ Ὓ Ὣ show_base"
- "ᾋ ᾛ ᾫ BackSpace"
- "show_numbers preferences space Return"
psiliordasiaandperispomeni:
- "ἆ ἦ ἶ ὖ ὦ ᾆ ᾖ ᾦ"
- "show_PsiliOrDasiaAndPerispomeni ἇ ἧ ἷ ὗ ὧ show_base"
- "ᾇ ᾗ ᾧ BackSpace"
- "show_numbers preferences space Return"
PsiliOrDasiaAndPerispomeni:
- "Ἆ Ἦ Ἶ Ὦ ᾎ ᾞ ᾮ"
- "show_psiliordasiaandperispomeni Ἇ Ἧ Ἷ Ὗ Ὧ show_base"
- "ᾏ ᾟ ᾯ BackSpace"
- "show_numbers preferences space Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "at numbersign dollar percent ampersand minus underscore plus parenleft parenright"
- "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace"
- "show_letters preferences space period comma Return"
symbols:
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
- "show_letters preferences space period comma Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
preferences:
action: "show_prefs"
outline: "altline"
icon: "keyboard-mode-symbolic"
show_oxia:
action:
set_view: "oxia"
outline: "extrawide"
label: " ΅"
show_Oxia:
action:
set_view: "Oxia"
outline: "extrawide"
label: "´¨↑"
show_bariaorperispomeni:
action:
set_view: "bariaorperispomeni"
outline: "extrawide"
label: " "
show_BariaOrPerispomeni:
action:
set_view: "BariaOrPerispomeni"
outline: "extrawide"
label: "`῀↑"
show_psiliordasia:
action:
set_view: "psiliordasia"
outline: "extrawide"
label: "᾿ "
show_PsiliOrDasia:
action:
set_view: "PsiliOrDasia"
outline: "extrawide"
label: "᾿῾↑"
show_psiliordasiaandoxia:
action:
set_view: "psiliordasiaandoxia"
outline: "extrawide"
label: "῎ ῞"
show_PsiliOrDasiaAndOxia:
action:
set_view: "PsiliOrDasiaAndOxia"
outline: "extrawide"
label: "῎῞↑"
show_psiliordasiaandvaria:
action:
set_view: "psiliordasiaandvaria"
outline: "extrawide"
label: "῍ ῝"
show_PsiliOrDasiaAndVaria:
action:
set_view: "PsiliOrDasiaAndVaria"
outline: "extrawide"
label: "῍῝↑"
show_psiliordasiaandperispomeni:
action:
set_view: "psiliordasiaandperispomeni"
outline: "extrawide"
label: "῏ ῟"
show_PsiliOrDasiaAndPerispomeni:
action:
set_view: "PsiliOrDasiaAndPerispomeni"
outline: "extrawide"
label: "῏῟↑"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ΑΒΓ"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
show_accents:
action:
locking:
lock_view: "accents"
unlock_view: "base"
outline: "altline"
label: "ᾦ"
show_base:
action:
set_view: "base"
outline: "altline"
label: "αι"
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
period:
outline: "special"
text: "."
period_upper:
outline: "special"
text: "·"
comma:
outline: "special"
text: ","
colon:
outline: "special"
text: ":"
semicolon:
outline: "special"
text: ";"
exclam:
outline: "special"
text: "!"
eis_l:
outline: "special"
text: "«"
eis_r:
outline: "special"
text: "»"
aring:
text: "å"
Aring:
text: "Å"
oslash:
text: "ø"
Oslash:
text: "Ø"
ae:
text: "æ"
AE:
text: "Æ"
asterisk:
text: "*"
asciitilde:
text: "~"
quoteleft:
text: "`"
bar:
text: "|"
U00B7:
text: "·"
squareroot:
text: "√"
Greek_pi:
text: "π"
division:
text: "÷"
multiply:
text: "×"
paragraph:
text: "¶"
Greek_tau:
text: "τ"
copyright:
text: "©"
numbersign:
text: "#"
U00AE:
text: "®"
at:
text: "@"
dollar:
text: "$"
U00A3:
text: "£"
percent:
text: "%"
EuroSign:
outline: "special"
text: "€"
ampersand:
text: "&"
U00A5:
text: "¥"
minus:
text: "-"
asciicircum:
text: "^"
underscore:
text: "_"
degree:
text: "°"
plus:
text: "+"
equal:
text: "="
parenleft:
text: "("
parenright:
text: ")"
braceleft:
text: "{"
braceright:
text: "}"
backslash:
text: "\\"
slash:
text: "/"
quotedbl:
text: "\""
quoteright:
text: "'"
less:
text: "<"
greater:
text: ">"
question:
text: "?"
bracketleft:
text: "["
bracketright:
text: "]"

View File

@ -1,40 +1,41 @@
# Greek layout created by Antonis Tsolomitis # Greek layout originally created by Antonis Tsolomitis
# University of the Aegean, Department of Mathematics, atsol@aegean.gr # University of the Aegean, Department of Mathematics, atsol@aegean.gr
# Sep 2019 # Sep 2019
# Edited by Sotiris Papadopoulos, sotirios.papadopoulos@inserm.fr
--- ---
outlines: outlines:
default: { width: 32, height: 52 } default: { width: 40, height: 60 }
altline: { width: 48.39024, height: 52 } altline: { width: 52.67, height: 60 }
wide: { width: 62, height: 52 } wide: { width: 62, height: 60 }
outline7: { width: 88.97561, height: 52 } spaceline: { width: 140, height: 60 }
spaceline: { width: 150.5853, height: 52 } special: { width: 44, height: 60 }
views: views:
base: base:
- "; ς ε ρ τ υ θ ι ο π !" - "semicolon ς ε ρ τ υ θ ι ο π"
- "α σ δ φ γ η ξ κ λ show_accented" - "α σ δ φ γ η ξ κ λ show_accented"
- "Shift_L ζ χ ψ ω β ν μ , BackSpace" - "Shift_L ζ χ ψ ω β ν μ BackSpace"
- "show_numbers preferences space period Return" - "show_numbers preferences space period comma Return"
upper: upper:
- ": EuroSign Ε Ρ Τ Υ Θ Ι Ο Π" - "colon exclam Ε Ρ Τ Υ Θ Ι Ο Π"
- "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accented" - "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accented"
- "Shift_L Ζ Χ Ψ Ω Β Ν Μ · BackSpace" - "Shift_L Ζ Χ Ψ Ω Β Ν Μ BackSpace"
- "show_numbers preferences space « » Return" - "show_numbers preferences space period_upper apostrophe Return"
accented: accented:
- "ά έ ή ί ό ύ ώ ϊ ϋ ΐ" - "ά έ ή ί ϊ ΐ ό ύ ϋ ώ "
- "ΰ Ά Έ Ή Ί Ό Ύ Ώ Ϊ show_base" - "Ά Έ Ή Ί Ϊ Ό Ύ Ϋ Ώ show_base"
- "Ϋ Ϗ ϐ ϑ ϕ ϖ ϗ — BackSpace" - "Ϗ ϐ ϑ ϗ ϖ ΰ ϕ — BackSpace"
- "show_numbers preferences space quoteleft quoteright Return" - "show_numbers preferences space eis_l eis_r Return"
numbers: numbers:
- "1 2 3 4 5 6 7 8 9 0" - "1 2 3 4 5 6 7 8 9 0"
- "at numbersign dollar percent ampersand minus underscore plus parenleft parenright" - "at numbersign dollar percent ampersand minus underscore plus parenleft parenright"
- "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace" - "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace"
- "show_letters preferences space period Return" - "show_letters preferences space period comma Return"
symbols: symbols:
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace" - "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
- "show_letters preferences space period Return" - "show_letters preferences space period comma Return"
buttons: buttons:
Shift_L: Shift_L:
action: action:
@ -54,12 +55,12 @@ buttons:
show_numbers: show_numbers:
action: action:
set_view: "numbers" set_view: "numbers"
outline: "altline" outline: "wide"
label: "123" label: "123"
show_letters: show_letters:
action: action:
set_view: "base" set_view: "base"
outline: "altline" outline: "wide"
label: "ΑΒΓ" label: "ΑΒΓ"
show_symbols: show_symbols:
action: action:
@ -78,16 +79,40 @@ buttons:
set_view: "base" set_view: "base"
outline: "altline" outline: "altline"
label: "αι" label: "αι"
period:
outline: "altline"
text: "."
space: space:
outline: spaceline outline: "spaceline"
text: " " text: " "
Return: Return:
outline: "wide" outline: "wide"
icon: "key-enter" icon: "key-enter"
keysym: "Return" keysym: "Return"
period:
outline: "special"
text: "."
period_upper:
outline: "special"
text: "·"
comma:
outline: "special"
text: ","
colon:
outline: "special"
text: ":"
semicolon:
outline: "special"
text: ";"
apostrophe:
outline: "special"
text: "᾿"
exclam:
outline: "special"
text: "!"
eis_l:
outline: "special"
text: "«"
eis_r:
outline: "special"
text: "»"
aring: aring:
text: "å" text: "å"
Aring: Aring:
@ -162,8 +187,6 @@ buttons:
text: "{" text: "{"
braceright: braceright:
text: "}" text: "}"
comma:
text: ","
backslash: backslash:
text: "\\" text: "\\"
slash: slash:
@ -176,12 +199,6 @@ buttons:
text: "<" text: "<"
greater: greater:
text: ">" text: ">"
colon:
text: ":"
semicolon:
text: ";"
exclam:
text: "!"
question: question:
text: "?" text: "?"
bracketleft: bracketleft:

204
data/keyboards/gr_wide.yaml Normal file
View File

@ -0,0 +1,204 @@
# Creaed by Sotiris Papadopoulos, sotirios.papadopoulos@inserm.fr
---
outlines:
default: { width: 80, height: 60 }
altline: { width: 110, height: 60 }
wide: { width: 120, height: 60 }
spaceline: { width: 250, height: 60 }
special: { width: 75, height: 60 }
views:
base:
- "semicolon ς ε ρ τ υ θ ι ο π"
- "α σ δ φ γ η ξ κ λ show_accented"
- "Shift_L ζ χ ψ ω β ν μ BackSpace"
- "show_numbers preferences space period comma Return"
upper:
- "colon exclam Ε Ρ Τ Υ Θ Ι Ο Π"
- "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accented"
- "Shift_L Ζ Χ Ψ Ω Β Ν Μ BackSpace"
- "show_numbers preferences space period_upper apostrophe Return"
accented:
- "ά έ ή ί ϊ ΐ ό ύ ϋ ώ "
- "Ά Έ Ή Ί Ϊ Ό Ύ Ϋ Ώ show_base"
- "Ϗ ϐ ϑ ϗ ΰ ϕ ϖ — BackSpace"
- "show_numbers preferences space eis_l eis_r Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "at numbersign dollar percent ampersand minus underscore plus parenleft parenright"
- "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace"
- "show_letters preferences space period comma Return"
symbols:
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
- "show_letters preferences space period comma Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ΑΒΓ"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
show_accented:
action:
locking:
lock_view: "accented"
unlock_view: "base"
outline: "altline"
label: "άΐ"
show_base:
action:
set_view: "base"
outline: "altline"
label: "αι"
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
period:
outline: "special"
text: "."
period_upper:
outline: "special"
text: "·"
comma:
outline: "special"
text: ","
colon:
outline: "special"
text: ":"
semicolon:
outline: "special"
text: ";"
apostrophe:
outline: "special"
text: "᾿"
exclam:
outline: "special"
text: "!"
eis_l:
outline: "special"
text: "«"
eis_r:
outline: "special"
text: "»"
aring:
text: "å"
Aring:
text: "Å"
oslash:
text: "ø"
Oslash:
text: "Ø"
ae:
text: "æ"
AE:
text: "Æ"
asterisk:
text: "*"
asciitilde:
text: "~"
quoteleft:
text: "`"
bar:
text: "|"
U00B7:
text: "·"
squareroot:
text: "√"
Greek_pi:
text: "π"
division:
text: "÷"
multiply:
text: "×"
paragraph:
text: "¶"
Greek_tau:
text: "τ"
copyright:
text: "©"
numbersign:
text: "#"
U00AE:
text: "®"
at:
text: "@"
dollar:
text: "$"
U00A3:
text: "£"
percent:
text: "%"
EuroSign:
text: "€"
ampersand:
text: "&"
U00A5:
text: "¥"
minus:
text: "-"
asciicircum:
text: "^"
underscore:
text: "_"
degree:
text: "°"
plus:
text: "+"
equal:
text: "="
parenleft:
text: "("
parenright:
text: ")"
braceleft:
text: "{"
braceright:
text: "}"
backslash:
text: "\\"
slash:
text: "/"
quotedbl:
text: "\""
quoteright:
text: "'"
less:
text: "<"
greater:
text: ">"
question:
text: "?"
bracketleft:
text: "["
bracketright:
text: "]"

1
debian/cargo/config vendored
View File

@ -9,4 +9,3 @@ replace-with = 'vendored-sources'
[source.vendored-sources] [source.vendored-sources]
directory = '/usr/share/cargo/registry' directory = '/usr/share/cargo/registry'

66
debian/changelog vendored
View File

@ -1,3 +1,69 @@
squeekboard (1.18.0-1) experimental; urgency=medium
[ Hugo Carvalho ]
* Add Portuguese translation
[ Мирослав Николић ]
* Add Serbian translation
[ William Wold ]
* Do not reset pending state on zwp_input_method_v2.done
[ Balázs Úr ]
* Add Hungarian translation
[ Emin Tufan Çetin ]
* Add Turkish translation
[ Piotr Drąg ]
* Add Polish translation
[ Pablo Correa Gómez ]
* Add Spanish translation
[ Vittorio Monti ]
* Add Italian translation
[ Dorota Czaplejewicz ]
* build: Replace missing crates.io dependency with Purism-hosted one
* ci: Allow failure on sid
* build: Update clap on newer Debian
* panel: Use scaling to set height
* layouts: Add Greek Polytonic
* debug: Add dbus interface to control debug prints
* output: Store physical size
* state: Derive panel size from physical click target size
* Clean up size types
* state: Add sizing unit test
* layouts: Register gr_wide
* CI: Build Rust code reference
* CI: Add gitlab pages deployment
* panel: Split away panel handling
* cargo: Add zbus to newer Debian
* docs: Update location
* docs: Link to reference
* docs: Make index more logical
* Update Cargo lock
[ Sotiris Papadopoulos ]
* Update gr.yaml to take advantage of more space per symbol. Creation of a wide variant...
[ Arnaud Ferraris ]
* state: fix "wide mode" detection in portrait orientation
* layout: allow stretching the layout by a small amount
* layout: fix build on i386
[ Sungjoon Moon ]
* Add Korean translation
[ Quentin PAGÈS ]
* Add Occitan translation
[ Zurab Kargareteli ]
* Add Georgian translation
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Mon, 25 Apr 2022 13:12:36 +0000
squeekboard (1.17.0-1) experimental; urgency=medium squeekboard (1.17.0-1) experimental; urgency=medium
[ Dorota Czaplejewicz ] [ Dorota Czaplejewicz ]

1
debian/control vendored
View File

@ -23,6 +23,7 @@ Build-Depends:
librust-serde-derive-1-dev (>= 1.0), librust-serde-derive-1-dev (>= 1.0),
librust-serde-yaml-0.8-dev (>= 0.8), librust-serde-yaml-0.8-dev (>= 0.8),
librust-xkbcommon-0.4+wayland-dev (>= 0.4), librust-xkbcommon-0.4+wayland-dev (>= 0.4),
librust-zbus-dev (>=1.0),
libwayland-dev (>= 1.16), libwayland-dev (>= 1.16),
lsb-release, lsb-release,
python3, python3,

View File

@ -23,6 +23,7 @@ Build-Depends:
librust-serde-derive-1-dev (>= 1.0), librust-serde-derive-1-dev (>= 1.0),
librust-serde-yaml-0.8-dev (>= 0.8), librust-serde-yaml-0.8-dev (>= 0.8),
librust-xkbcommon-0.4+wayland-dev (>= 0.4), librust-xkbcommon-0.4+wayland-dev (>= 0.4),
librust-zbus-dev (>= 1.9),
libwayland-dev (>= 1.16), libwayland-dev (>= 1.16),
lsb-release, lsb-release,
python3, python3,

2
debian/rules vendored
View File

@ -38,6 +38,6 @@ endif
# causing Cargo to refuse to build with a crates.io copy # causing Cargo to refuse to build with a crates.io copy
override_dh_auto_configure: override_dh_auto_configure:
[ ! -f Cargo.lock ] || rm Cargo.lock [ ! -f Cargo.lock ] || rm Cargo.lock
dh_auto_configure -- -Dnewer=$(newer) dh_auto_configure -- -Dnewer=$(newer) -Donline=false
override_dh_autoreconf: override_dh_autoreconf:

View File

@ -102,6 +102,17 @@ contain a comma separated list of:
Coding Coding
------ ------
### Reference docs
Reference documentation can be generated using:
```
cd squeekboard_build/
../squeekboard_source/cargo.sh doc --no-deps --document-private-items
```
as well as found [online](https://world.pages.gitlab.gnome.org/Phosh/squeekboard/doc/rs/).
### Project structure ### Project structure
Rust modules should be split into 2 categories: libraries, and user interface. They differ in the way they do error handling. Rust modules should be split into 2 categories: libraries, and user interface. They differ in the way they do error handling.

View File

@ -1,13 +1,6 @@
Welcome to squeekboard's documentation! Welcome to squeekboard's documentation!
======================================= =======================================
Contents
--------
* [Tutorial](tutorial.md)
* [Contributing](hacking.md)
* [Switching views](views.md)
Introduction Introduction
------------ ------------
@ -22,9 +15,15 @@ Layouts are created using a text-based format, based on YAML.
TODO: Provide a description of the format. TODO: Provide a description of the format.
### Views
Squeekboard layouts are separated into *views* and use a *room metaphor* to [switch views](views.md). Squeekboard layouts are separated into *views* and use a *room metaphor* to [switch views](views.md).
Contributions Contributions
------------- -------------
Anyone is free to modify *squeekboard*. See the [contributing document](hacking.md). Anyone is free to modify *squeekboard*. See the [contributing document](hacking.md).
### Code documentation
To expose the structure of Squeekboard in detail, there's a [code reference](doc/rs).

View File

@ -55,6 +55,8 @@ typedef struct _EekGtkKeyboardPrivate
GdkEventSequence *sequence; // unowned reference GdkEventSequence *sequence; // unowned reference
LfbEvent *event; LfbEvent *event;
gulong kb_signal;
} EekGtkKeyboardPrivate; } EekGtkKeyboardPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA) G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
@ -307,12 +309,19 @@ eek_gtk_keyboard_set_property (GObject *object,
} }
} }
// This may actually get called multiple times in a row
// if both a parent object and its parent get destroyed
static void static void
eek_gtk_keyboard_dispose (GObject *object) eek_gtk_keyboard_dispose (GObject *object)
{ {
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (object); EekGtkKeyboard *self = EEK_GTK_KEYBOARD (object);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
if (priv->kb_signal != 0) {
g_signal_handler_disconnect(priv->eekboard_context, priv->kb_signal);
priv->kb_signal = 0;
}
if (priv->renderer) { if (priv->renderer) {
eek_renderer_free(priv->renderer); eek_renderer_free(priv->renderer);
priv->renderer = NULL; priv->renderer = NULL;
@ -418,12 +427,13 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice,
.widget_to_layout = { .widget_to_layout = {
.origin_x = 0, .origin_x = 0,
.origin_y = 0, .origin_y = 0,
.scale = 1, .scale_x = 1,
.scale_y = 1,
}, },
}; };
priv->render_geometry = initial_geometry; priv->render_geometry = initial_geometry;
g_signal_connect (eekservice, priv->kb_signal = g_signal_connect (eekservice,
"notify::keyboard", "notify::keyboard",
G_CALLBACK(on_notify_keyboard), G_CALLBACK(on_notify_keyboard),
ret); ret);

View File

@ -219,7 +219,7 @@ eek_renderer_render_keyboard (EekRenderer *self,
cairo_save(cr); cairo_save(cr);
cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y); cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y);
cairo_scale (cr, geometry.widget_to_layout.scale, geometry.widget_to_layout.scale); cairo_scale (cr, geometry.widget_to_layout.scale_x, geometry.widget_to_layout.scale_y);
squeek_draw_layout_base_view(keyboard->layout, self, cr); squeek_draw_layout_base_view(keyboard->layout, self, cr);
squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission); squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission);

View File

@ -87,7 +87,8 @@ void eek_bounds_free (EekBounds *bounds);
struct transformation { struct transformation {
gdouble origin_x; gdouble origin_x;
gdouble origin_y; gdouble origin_y;
gdouble scale; gdouble scale_x;
gdouble scale_y;
}; };
G_END_DECLS G_END_DECLS

View File

@ -60,10 +60,10 @@ struct _EekboardContextService {
LevelKeyboard *keyboard; // currently used keyboard LevelKeyboard *keyboard; // currently used keyboard
GSettings *settings; // Owned reference GSettings *settings; // Owned reference
// Maybe TODO: it's used only for fetching layout type. /// Needed for keymap changes after keyboard updates.
// Maybe let UI push the type to this structure? // TODO: can the main loop access submission to change the key maps instead?
ServerContextService *ui; // unowned reference // This should probably land together with passing buttons through state,
/// Needed for keymap changes after keyboard updates // to avoid race conditions between setting buttons and key maps.
struct submission *submission; // unowned struct submission *submission; // unowned
}; };
@ -297,6 +297,8 @@ eekboard_context_service_get_keyboard (EekboardContextService *context)
return context->keyboard; return context->keyboard;
} }
// Used from Rust.
// TODO: move hint management to Rust entirely
void eekboard_context_service_set_hint_purpose(EekboardContextService *context, void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint, uint32_t purpose) uint32_t hint, uint32_t purpose)
{ {
@ -340,7 +342,3 @@ void eekboard_context_service_set_submission(EekboardContextService *context, st
submission_use_layout(context->submission, context->keyboard->layout, time); submission_use_layout(context->submission, context->keyboard->layout, time);
} }
} }
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui) {
context->ui = ui;
}

View File

@ -39,16 +39,12 @@ G_DECLARE_FINAL_TYPE(EekboardContextService, eekboard_context_service, EEKBOARD,
EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state); EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state);
void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission); void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission);
void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui);
void eekboard_context_service_destroy (EekboardContextService *context); void eekboard_context_service_destroy (EekboardContextService *context);
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context); LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
void eekboard_context_service_set_keymap(EekboardContextService *context, void eekboard_context_service_set_keymap(EekboardContextService *context,
const LevelKeyboard *keyboard); const LevelKeyboard *keyboard);
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint,
uint32_t purpose);
void void
eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp); eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp);
G_END_DECLS G_END_DECLS

View File

@ -1,7 +1,7 @@
project( project(
'squeekboard', 'squeekboard',
'c', 'rust', 'c', 'rust',
version: '1.17.0', version: '1.18.0',
license: 'GPLv3', license: 'GPLv3',
meson_version: '>=0.51.0', meson_version: '>=0.51.0',
default_options: [ default_options: [
@ -96,19 +96,23 @@ cargo_toml_base = configure_file(
configuration: path_data, configuration: path_data,
) )
cargo_patch = []
cargo_deps = files('Cargo.deps')
if get_option('newer') == true if get_option('newer') == true
cargo_build_flags += ['--features', 'glib_v0_14'] cargo_build_flags += ['--features', 'glib_v0_14']
cargo_deps = files('Cargo.deps.newer') cargo_deps = files('Cargo.deps.newer')
else
cargo_deps = files('Cargo.deps')
if get_option('online') == true
cargo_patch = [files('Cargo.deps.online')]
endif
endif endif
cat = find_program('cat') cat = find_program('cat')
cargo_toml = custom_target( cargo_toml = custom_target(
'Cargo.toml', 'Cargo.toml',
output: 'Cargo.toml', output: 'Cargo.toml',
command: [cat, cargo_toml_base, cargo_deps], command: [cat, cargo_toml_base, cargo_deps] + cargo_patch,
capture: true, capture: true,
) )

View File

@ -11,6 +11,10 @@ option('newer',
type: 'boolean', value: false, type: 'boolean', value: false,
description: 'Build with dependencies newer than those of Byzantium') description: 'Build with dependencies newer than those of Byzantium')
option('online',
type: 'boolean', value: true,
description: 'Pull packages from the internet while building, as opposed to a local regstry.')
option('strict', option('strict',
type: 'boolean', value: true, type: 'boolean', value: true,
description: 'Turn more warnings into errors') description: 'Turn more warnings into errors')

View File

@ -1,13 +1,23 @@
ca ca
de de
es
fa fa
fi fi
fur fur
gl gl
he he
hu
it
ka
ko
nl nl
oc
pl
pt
pt_BR pt_BR
ro ro
sl sl
sr
tr
uk uk
sv sv

47
po/es.po Normal file
View File

@ -0,0 +1,47 @@
# Spanish translation for squeekboard.
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# Pablo Correa Gómez <ablocorrea@hotmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-03-20 13:14+0000\n"
"PO-Revision-Date: 2022-03-22 21:33+0100\n"
"Last-Translator: Pablo Correa Gómez <ablocorrea@hotmail.com>\n"
"Language-Team: Spanish; Castilian <gnome-es-list@gnome.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 3.36.0\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminal"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Ajustes de teclado"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Teclado en pantala"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Un teclado virtual en pantalla"

46
po/hu.po Normal file
View File

@ -0,0 +1,46 @@
# Hungarian translation for squeekboard.
# Copyright (C) 2022 Free Software Foundation, Inc.
# This file is distributed under the same license as the squeekboard package.
#
# Balázs Úr <ur.balazs at fsf dot hu>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/issues"
"\n"
"POT-Creation-Date: 2022-03-12 12:04+0000\n"
"PO-Revision-Date: 2022-03-16 01:55+0100\n"
"Last-Translator: Balázs Úr <ur.balazs at fsf dot hu>\n"
"Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 19.12.3\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emodzsi"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminál"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Billentyűzetbeállítások"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Képernyő-billentyűzet"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Egy virtuális képernyő-billentyűzet"

47
po/it.po Normal file
View File

@ -0,0 +1,47 @@
# Italian translation for squeekboard.
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Vittorio <postav@pm.me>, 2021.
# Vittorio Monti <postav@pm.me>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2021-12-22 19:14+0000\n"
"PO-Revision-Date: 2021-12-22 20:37+0100\n"
"Last-Translator: Vittorio Monti <postav@pm.me>\n"
"Language-Team: Italian <gnome-it-list@gnome.org>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 3.30.1\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminale"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Impostazioni tastiera"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Tastiera su schermo"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Una tastiera virtuale su schermo"

46
po/ka.po Normal file
View File

@ -0,0 +1,46 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-02-04 15:22+0000\n"
"PO-Revision-Date: 2022-02-08 03:15+0100\n"
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
"Language-Team: \n"
"Language: ka\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "ემოჯი"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "ტერმინალი"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "კლავიატურის მორგება"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "ეკრანის კლავიატურა"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "ეკრანზე ვირტუალური კლავიატურის ჩვენება"

46
po/ko.po Normal file
View File

@ -0,0 +1,46 @@
# Korean translation for squeekboard.
# Copyright (C) 2022 squeekboard'S COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Moon Sungjoon <sumoon@seoulsaram.org>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-04-09 18:43+0000\n"
"PO-Revision-Date: 2022-04-11 19:23+0900\n"
"Last-Translator: Moon Sungjoon <sumoon@seoulsaram.org>\n"
"Language-Team: \n"
"Language: ko\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.0.1\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "이모지"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "터미널"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "키보드 설정"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "스퀴크 보드"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "화상 키보드"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "가상 키보드"

45
po/oc.po Normal file
View File

@ -0,0 +1,45 @@
# Occitan translation for squeekboard.
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Quentin PAGÈS <pages_quentin@hotmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-04-17 06:24+0000\n"
"PO-Revision-Date: 2022-04-17 09:17+0200\n"
"Last-Translator: Quentin PAGÈS\n"
"Language-Team: Occitan <totenoc@gmail.com>\n"
"Language: oc\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0.1\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminal"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Paramètres del clavièr"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Clavièr visual"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Un clavièr virtual sus lecran"

47
po/pl.po Normal file
View File

@ -0,0 +1,47 @@
# Polish translation for squeekboard.
# Copyright © 2022 the squeekboard authors.
# This file is distributed under the same license as the squeekboard package.
# Piotr Drąg <piotrdrag@gmail.com>, 2022.
# Aviary.pl <community-poland@mozilla.org>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-03-19 09:34+0000\n"
"PO-Revision-Date: 2022-03-20 14:12+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminal"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Ustawienia klawiatury"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Klawiatura ekranowa"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Wirtualna klawiatura ekranowa"

46
po/pt.po Normal file
View File

@ -0,0 +1,46 @@
# Portuguese translation for squeekboard.
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Hugo Carvalho <hugokarvalho@hotmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-02-26 10:49+0000\n"
"PO-Revision-Date: 2022-02-26 18:27+0000\n"
"Last-Translator: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
"Language-Team: Portuguese <pt@li.org>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Terminal"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Definições do teclado"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Teclado no ecrã"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Um teclado virtual no ecrã"

45
po/sr.po Normal file
View File

@ -0,0 +1,45 @@
# Serbian translation for squeekboard.
# Copyright © 2022 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-03-08 10:15+0000\n"
"PO-Revision-Date: 2022-03-12 13:00+0200\n"
"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <(nothing)>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n"
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Емоџи"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Терминал"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Поставке тастатуре"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Сквик-табла"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Тастатура на екрану"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Виртуелна тастатура на екрану"

46
po/tr.po Normal file
View File

@ -0,0 +1,46 @@
# Turkish translation for squeekboard.
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
# This file is distributed under the same license as the squeekboard package.
# Emin Tufan Çetin <etcetin@gmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: squeekboard master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
"issues\n"
"POT-Creation-Date: 2022-03-16 00:57+0000\n"
"PO-Revision-Date: 2022-03-19 12:33+0300\n"
"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n"
"Language-Team: Turkish <gnometurk@gnome.org>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.4.3\n"
#. translators: This is a emmoji keyboard layout
#: data/popover.ui:6
msgid "Emoji"
msgstr "Emoji"
#. translators: This is a terminal keyboard layout
#: data/popover.ui:12
msgid "Terminal"
msgstr "Uçbirim"
#: data/popover.ui:18
msgid "Keyboard Settings"
msgstr "Klavye Ayarları"
#: data/sm.puri.Squeekboard.desktop.in.in:3
msgid "Squeekboard"
msgstr "Squeekboard"
#: data/sm.puri.Squeekboard.desktop.in.in:4
msgid "On Screen Keyboard"
msgstr "Ekran Klavyesi"
#: data/sm.puri.Squeekboard.desktop.in.in:5
msgid "An on screen virtual keyboard"
msgstr "Sanal ekran klavyesi"

View File

@ -7,6 +7,7 @@
use std::time::Duration; use std::time::Duration;
use crate::outputs::OutputId; use crate::outputs::OutputId;
use crate::panel::PixelSize;
/// The keyboard should hide after this has elapsed to prevent flickering. /// The keyboard should hide after this has elapsed to prevent flickering.
pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200); pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200);
@ -16,7 +17,7 @@ pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200);
pub enum Outcome { pub enum Outcome {
Visible { Visible {
output: OutputId, output: OutputId,
height: u32, height: PixelSize,
}, },
Hidden, Hidden,
} }

71
src/debug.rs Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2022 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
use std::thread;
use zbus::{Connection, ObjectServer, dbus_interface, fdo};
use crate::event_loop;
use crate::state;
use std::convert::TryInto;
/// Accepts commands controlling the debug mode
struct Manager {
sender: event_loop::driver::Threaded,
enabled: bool,
}
#[dbus_interface(name = "sm.puri.SqueekDebug")]
impl Manager {
#[dbus_interface(property, name = "Enabled")]
fn get_enabled(&self) -> bool {
self.enabled
}
#[dbus_interface(property, name = "Enabled")]
fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
self.sender
.send(state::Event::Debug(
if enabled { Event::Enable }
else { Event::Disable }
))
.unwrap();
}
}
fn start(mgr: Manager) -> Result<(), Box<dyn std::error::Error>> {
let connection = Connection::new_session()?;
fdo::DBusProxy::new(&connection)?.request_name(
"sm.puri.SqueekDebug",
fdo::RequestNameFlags::ReplaceExisting.into(),
)?;
let mut object_server = ObjectServer::new(&connection);
object_server.at(&"/sm/puri/SqueekDebug".try_into()?, mgr)?;
loop {
if let Err(err) = object_server.try_handle_next() {
eprintln!("{}", err);
}
}
}
pub fn init(sender: event_loop::driver::Threaded) {
let mgr = Manager {
sender,
enabled: false,
};
thread::spawn(move || {
start(mgr).unwrap();
});
}
#[derive(Debug, Clone, Copy)]
pub enum Event {
Enable,
Disable,
}

View File

@ -151,7 +151,7 @@ mod test {
use super::*; use super::*;
use crate::animation; use crate::animation;
use crate::imservice::{ ContentHint, ContentPurpose }; use crate::imservice::{ ContentHint, ContentPurpose };
use crate::main::PanelCommand; use crate::panel;
use crate::state::{ Application, InputMethod, InputMethodDetails, Presence, visibility }; use crate::state::{ Application, InputMethod, InputMethodDetails, Presence, visibility };
use crate::state::test::application_with_fake_output; use crate::state::test::application_with_fake_output;
@ -176,13 +176,13 @@ mod test {
let l = State::new(state, now); let l = State::new(state, now);
let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now); let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now);
assert_matches!(commands.panel_visibility, Some(PanelCommand::Show{..})); assert_matches!(commands.panel_visibility, Some(panel::Command::Show{..}));
assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT)); assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT));
now += animation::HIDING_TIMEOUT; now += animation::HIDING_TIMEOUT;
let (l, commands) = handle_event(l, Event::TimeoutReached(now), now); let (l, commands) = handle_event(l, Event::TimeoutReached(now), now);
assert_eq!(commands.panel_visibility, Some(PanelCommand::Hide)); assert_eq!(commands.panel_visibility, Some(panel::Command::Hide));
assert_eq!(l.scheduled_wakeup, None); assert_eq!(l.scheduled_wakeup, None);
} }
} }

View File

@ -1,6 +1,7 @@
#include "submission.h" #include "input-method-unstable-v2-client-protocol.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
#include <glib.h> #include "submission.h"
struct imservice; struct imservice;

View File

@ -154,11 +154,6 @@ pub mod c {
let imservice = check_imservice(imservice, im).unwrap(); let imservice = check_imservice(imservice, im).unwrap();
imservice.current = imservice.pending.clone(); imservice.current = imservice.pending.clone();
imservice.pending = IMProtocolState {
active: imservice.current.active,
..IMProtocolState::default()
};
imservice.serial += Wrapping(1u32); imservice.serial += Wrapping(1u32);
imservice.send_event(); imservice.send_event();
} }

View File

@ -18,6 +18,7 @@
*/ */
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp;
use std::collections::{ HashMap, HashSet }; use std::collections::{ HashMap, HashSet };
use std::ffi::CString; use std::ffi::CString;
use std::fmt; use std::fmt;
@ -26,6 +27,7 @@ use std::vec::Vec;
use ::action::Action; use ::action::Action;
use ::drawing; use ::drawing;
use ::float_ord::FloatOrd;
use ::keyboard::KeyState; use ::keyboard::KeyState;
use ::logging; use ::logging;
use ::manager; use ::manager;
@ -117,28 +119,30 @@ pub mod c {
pub struct Transformation { pub struct Transformation {
pub origin_x: f64, pub origin_x: f64,
pub origin_y: f64, pub origin_y: f64,
pub scale: f64, pub scale_x: f64,
pub scale_y: f64,
} }
impl Transformation { impl Transformation {
/// Applies the new transformation after this one /// Applies the new transformation after this one
pub fn chain(self, next: Transformation) -> Transformation { pub fn chain(self, next: Transformation) -> Transformation {
Transformation { Transformation {
origin_x: self.origin_x + self.scale * next.origin_x, origin_x: self.origin_x + self.scale_x * next.origin_x,
origin_y: self.origin_y + self.scale * next.origin_y, origin_y: self.origin_y + self.scale_y * next.origin_y,
scale: self.scale * next.scale, scale_x: self.scale_x * next.scale_x,
scale_y: self.scale_y * next.scale_y,
} }
} }
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_x,
y: (p.y - self.origin_y) / self.scale, y: (p.y - self.origin_y) / self.scale_y,
} }
} }
fn reverse(&self, p: Point) -> Point { fn reverse(&self, p: Point) -> Point {
Point { Point {
x: p.x * self.scale + self.origin_x, x: p.x * self.scale_x + self.origin_x,
y: p.y * self.scale + self.origin_y, y: p.y * self.scale_y + self.origin_y,
} }
} }
pub fn reverse_bounds(&self, b: Bounds) -> Bounds { pub fn reverse_bounds(&self, b: Bounds) -> Bounds {
@ -394,7 +398,8 @@ pub mod c {
let transform = Transformation { let transform = Transformation {
origin_x: 10f64, origin_x: 10f64,
origin_y: 11f64, origin_y: 11f64,
scale: 12f64, scale_x: 12f64,
scale_y: 13f64,
}; };
let point = Point { x: 1f64, y: 1f64 }; let point = Point { x: 1f64, y: 1f64 };
let transformed = transform.reverse(transform.forward(point.clone())); let transformed = transform.reverse(transform.forward(point.clone()));
@ -755,16 +760,20 @@ impl Layout {
let size = self.calculate_size(); let size = self.calculate_size();
let h_scale = available.width / size.width; let h_scale = available.width / size.width;
let v_scale = available.height / size.height; let v_scale = available.height / size.height;
let scale = if h_scale < v_scale { h_scale } else { v_scale }; // Allow up to 5% (and a bit more) horizontal stretching for filling up available space
let scale_x = if (h_scale / v_scale) < 1.055 { h_scale } else { v_scale };
let scale_y = cmp::min(FloatOrd(h_scale), FloatOrd(v_scale)).0;
let outside_margins = c::Transformation { let outside_margins = c::Transformation {
origin_x: (available.width - (scale * size.width)) / 2.0, origin_x: (available.width - (scale_x * size.width)) / 2.0,
origin_y: (available.height - (scale * size.height)) / 2.0, origin_y: (available.height - (scale_y * size.height)) / 2.0,
scale: scale, scale_x: scale_x,
scale_y: scale_y,
}; };
outside_margins.chain(c::Transformation { outside_margins.chain(c::Transformation {
origin_x: self.margins.left, origin_x: self.margins.left,
origin_y: self.margins.top, origin_y: self.margins.top,
scale: 1.0, scale_x: 1.0,
scale_y: 1.0,
}) })
} }
@ -1471,8 +1480,63 @@ mod test {
let transformation = layout.calculate_transformation( let transformation = layout.calculate_transformation(
Size { width: 2.0, height: 2.0 } Size { width: 2.0, height: 2.0 }
); );
assert_eq!(transformation.scale, 1.0); assert_eq!(transformation.scale_x, 1.0);
assert_eq!(transformation.scale_y, 1.0);
assert_eq!(transformation.origin_x, 0.5); assert_eq!(transformation.origin_x, 0.5);
assert_eq!(transformation.origin_y, 0.0); assert_eq!(transformation.origin_y, 0.0);
} }
#[test]
fn check_stretching() {
// just one button
let view = View::new(vec![
(
0.0,
Row::new(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(),
view_latched: LatchedState::Not,
keymaps: Vec::new(),
kind: ArrangementKind::Base,
pressed_keys: HashSet::new(),
margins: Margins {
top: 0.0,
left: 0.0,
right: 0.0,
bottom: 0.0,
},
views: hashmap! {
String::new() => (c::Point { x: 0.0, y: 0.0 }, view),
},
purpose: ContentPurpose::Normal,
};
let transformation = layout.calculate_transformation(
Size { width: 100.0, height: 100.0 }
);
assert_eq!(transformation.scale_x, 100.0);
assert_eq!(transformation.scale_y, 100.0);
let transformation = layout.calculate_transformation(
Size { width: 95.0, height: 100.0 }
);
assert_eq!(transformation.scale_x, 95.0);
assert_eq!(transformation.scale_y, 95.0);
let transformation = layout.calculate_transformation(
Size { width: 105.0, height: 100.0 }
);
assert_eq!(transformation.scale_x, 105.0);
assert_eq!(transformation.scale_y, 100.0);
let transformation = layout.calculate_transformation(
Size { width: 106.0, height: 100.0 }
);
assert_eq!(transformation.scale_x, 100.0);
assert_eq!(transformation.scale_y, 100.0);
}
} }

View File

@ -13,6 +13,8 @@ extern crate gtk_sys;
extern crate maplit; extern crate maplit;
extern crate serde; extern crate serde;
extern crate xkbcommon; extern crate xkbcommon;
extern crate zbus;
extern crate zvariant;
#[cfg(test)] #[cfg(test)]
#[macro_use] #[macro_use]
@ -23,6 +25,7 @@ mod logging;
mod action; mod action;
mod animation; mod animation;
pub mod data; pub mod data;
mod debug;
mod drawing; mod drawing;
mod event_loop; mod event_loop;
pub mod float_ord; pub mod float_ord;
@ -33,6 +36,7 @@ mod locale;
mod main; mod main;
mod manager; mod manager;
mod outputs; mod outputs;
mod panel;
mod popover; mod popover;
mod resources; mod resources;
mod state; mod state;

View File

@ -8,6 +8,7 @@
#include "eek/eek-types.h" #include "eek/eek-types.h"
#include "dbus.h" #include "dbus.h"
#include "panel.h"
struct receiver; struct receiver;
@ -24,7 +25,7 @@ struct rsobjects {
struct squeek_wayland *wayland; struct squeek_wayland *wayland;
}; };
void register_ui_loop_handler(struct receiver *receiver, ServerContextService *ui, DBusHandler *dbus_handler); void register_ui_loop_handler(struct receiver *receiver, struct panel_manager *panel, EekboardContextService *hint_manager, DBusHandler *dbus_handler);
struct rsobjects squeek_init(void); struct rsobjects squeek_init(void);

View File

@ -3,7 +3,8 @@
*/ */
/*! Glue for the main loop. */ /*! Glue for the main loop. */
use crate::outputs::OutputId; use crate::panel;
use crate::debug;
use crate::state; use crate::state;
use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver}; use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver};
@ -19,19 +20,21 @@ mod c {
use crate::imservice::IMService; use crate::imservice::IMService;
use crate::imservice::c::InputMethod; use crate::imservice::c::InputMethod;
use crate::outputs::Outputs; use crate::outputs::Outputs;
use crate::outputs::c::WlOutput;
use crate::state; use crate::state;
use crate::submission::Submission; use crate::submission::Submission;
use crate::util::c::Wrapped; use crate::util::c::Wrapped;
use crate::vkeyboard::c::ZwpVirtualKeyboardV1; use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
/// ServerContextService*
#[repr(transparent)]
pub struct UIManager(*const c_void);
/// DbusHandler* /// DbusHandler*
#[repr(transparent)] #[repr(transparent)]
pub struct DBusHandler(*const c_void); pub struct DBusHandler(*const c_void);
/// EekboardContextService* in the role of a hint receiver
// The clone/copy is a concession to C style of programming.
// It would be hard to get rid of it.
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct HintManager(*const c_void);
/// Holds the Rust structures that are interesting from C. /// Holds the Rust structures that are interesting from C.
#[repr(C)] #[repr(C)]
@ -75,9 +78,7 @@ mod c {
extern "C" { extern "C" {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
fn init_wayland(wayland: *mut Wayland); fn init_wayland(wayland: *mut Wayland);
fn server_context_service_update_keyboard(service: *const UIManager, output: WlOutput, height: u32); fn eekboard_context_service_set_hint_purpose(service: HintManager, hint: u32, purpose: u32);
fn server_context_service_real_hide_keyboard(service: *const UIManager);
fn server_context_service_set_hint_purpose(service: *const UIManager, hint: u32, purpose: u32);
// This should probably only get called from the gtk main loop, // This should probably only get called from the gtk main loop,
// given that dbus handler is using glib. // given that dbus handler is using glib.
fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8); fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8);
@ -94,6 +95,8 @@ mod c {
let now = Instant::now(); let now = Instant::now();
let state_manager = driver::Threaded::new(sender, state::Application::new(now)); let state_manager = driver::Threaded::new(sender, state::Application::new(now));
debug::init(state_manager.clone());
let outputs = Outputs::new(state_manager.clone()); let outputs = Outputs::new(state_manager.clone());
let mut wayland = Box::new(Wayland::new(outputs)); let mut wayland = Box::new(Wayland::new(outputs));
let wayland_raw = &mut *wayland as *mut _; let wayland_raw = &mut *wayland as *mut _;
@ -121,18 +124,20 @@ mod c {
pub extern "C" pub extern "C"
fn register_ui_loop_handler( fn register_ui_loop_handler(
receiver: Wrapped<Receiver<Commands>>, receiver: Wrapped<Receiver<Commands>>,
ui_manager: *const UIManager, panel_manager: panel::c::PanelManager,
hint_manager: HintManager,
dbus_handler: *const DBusHandler, dbus_handler: *const DBusHandler,
) { ) {
let receiver = unsafe { receiver.unwrap() }; let receiver = unsafe { receiver.unwrap() };
let receiver = Rc::try_unwrap(receiver).expect("References still present"); let receiver = Rc::try_unwrap(receiver).expect("References still present");
let receiver = receiver.into_inner(); let receiver = receiver.into_inner();
let panel_manager = Wrapped::new(panel::Manager::new(panel_manager));
let ctx = MainContext::default(); let ctx = MainContext::default();
let _acqu = ctx.acquire(); let _acqu = ctx.acquire();
receiver.attach( receiver.attach(
Some(&ctx), Some(&ctx),
move |msg| { move |msg| {
main_loop_handle_message(msg, ui_manager, dbus_handler); main_loop_handle_message(msg, panel_manager.clone(), hint_manager, dbus_handler);
Continue(true) Continue(true)
}, },
); );
@ -146,18 +151,13 @@ mod c {
/// and doesn't lend itself to testing other than integration. /// and doesn't lend itself to testing other than integration.
fn main_loop_handle_message( fn main_loop_handle_message(
msg: Commands, msg: Commands,
ui_manager: *const UIManager, panel_manager: Wrapped<panel::Manager>,
hint_manager: HintManager,
dbus_handler: *const DBusHandler, dbus_handler: *const DBusHandler,
) { ) {
match msg.panel_visibility { if let Some(visibility) = msg.panel_visibility {
Some(PanelCommand::Show { output, height }) => unsafe { panel::Manager::update(panel_manager, visibility);
server_context_service_update_keyboard(ui_manager, output.0, height); }
},
Some(PanelCommand::Hide) => unsafe {
server_context_service_real_hide_keyboard(ui_manager);
},
None => {},
};
if let Some(visible) = msg.dbus_visible_set { if let Some(visible) = msg.dbus_visible_set {
if dbus_handler != std::ptr::null() { if dbus_handler != std::ptr::null() {
@ -167,8 +167,8 @@ mod c {
if let Some(hints) = msg.layout_hint_set { if let Some(hints) = msg.layout_hint_set {
unsafe { unsafe {
server_context_service_set_hint_purpose( eekboard_context_service_set_hint_purpose(
ui_manager, hint_manager,
hints.hint.bits(), hints.hint.bits(),
hints.purpose.clone() as u32, hints.purpose.clone() as u32,
) )
@ -177,20 +177,11 @@ mod c {
} }
} }
#[derive(Clone, PartialEq, Debug)]
pub enum PanelCommand {
Show {
output: OutputId,
height: u32,
},
Hide,
}
/// The commands consumed by the main loop, /// The commands consumed by the main loop,
/// to be sent out to external components. /// to be sent out to external components.
#[derive(Clone)] #[derive(Clone)]
pub struct Commands { pub struct Commands {
pub panel_visibility: Option<PanelCommand>, pub panel_visibility: Option<panel::Command>,
pub layout_hint_set: Option<state::InputMethodDetails>, pub layout_hint_set: Option<state::InputMethodDetails>,
pub dbus_visible_set: Option<bool>, pub dbus_visible_set: Option<bool>,
} }

View File

@ -14,6 +14,7 @@ sources = [
config_h, config_h,
'dbus.c', 'dbus.c',
'imservice.c', 'imservice.c',
'panel.c',
'popover.c', 'popover.c',
'server-context-service.c', 'server-context-service.c',
'wayland.c', 'wayland.c',

View File

@ -4,9 +4,11 @@
/*! Managing Wayland outputs */ /*! Managing Wayland outputs */
use std::ops;
use std::vec::Vec; use std::vec::Vec;
use crate::event_loop; use crate::event_loop;
use ::logging; use ::logging;
use crate::util::DivCeil;
// traits // traits
use ::logging::Warn; use ::logging::Warn;
@ -126,7 +128,7 @@ pub mod c {
outputs: COutputs, outputs: COutputs,
wl_output: WlOutput, wl_output: WlOutput,
_x: i32, _y: i32, _x: i32, _y: i32,
_phys_width: i32, _phys_height: i32, phys_width: i32, phys_height: i32,
_subpixel: i32, _subpixel: i32,
_make: *const c_char, _model: *const c_char, _make: *const c_char, _model: *const c_char,
transform: i32, transform: i32,
@ -144,7 +146,19 @@ pub mod c {
.find_output_mut(wl_output) .find_output_mut(wl_output)
.map(|o| &mut o.pending); .map(|o| &mut o.pending);
match output_state { match output_state {
Some(state) => { state.transform = Some(transform) }, Some(state) => {
fn maybe_mm(value: i32) -> Option<Millimeter> {
if value == 0 { None }
else { Some(Millimeter(value)) }
}
state.geometry = Some(Geometry {
phys_size: Size {
width: maybe_mm(phys_width),
height: maybe_mm(phys_height),
},
transform,
});
},
None => log_print!( None => log_print!(
logging::Level::Warning, logging::Level::Warning,
"Got geometry on unknown output", "Got geometry on unknown output",
@ -286,24 +300,51 @@ pub mod c {
// TODO: handle unregistration // TODO: handle unregistration
} }
/// Generic size /// Generic size
#[derive(Clone)] #[derive(Clone, Copy, Debug)]
pub struct Size { pub struct Size<Unit> {
pub width: u32, pub width: Unit,
pub height: u32, pub height: Unit,
} }
pub type PixelSize = Size<u32>;
/// wl_output mode /// wl_output mode
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct Mode { pub struct Mode {
width: i32, pub width: i32,
height: i32, pub height: i32,
}
#[derive(Clone, Copy, Debug)]
pub struct Millimeter(pub i32);
impl DivCeil<i32> for Millimeter {
type Output = Millimeter;
fn div_ceil(self, other: i32) -> Self {
Self(self.0.div_ceil(other))
}
}
impl ops::Mul<i32> for Millimeter {
type Output = Self;
fn mul(self, m: i32) -> Self {
Self(self.0 * m as i32)
}
}
/// All geometry parameters
#[derive(Clone, Copy, Debug)]
pub struct Geometry {
pub transform: c::Transform,
pub phys_size: Size<Option<Millimeter>>,
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct OutputState { pub struct OutputState {
pub current_mode: Option<Mode>, pub current_mode: Option<Mode>,
pub transform: Option<c::Transform>, pub geometry: Option<Geometry>,
pub scale: i32, pub scale: i32,
} }
@ -317,33 +358,56 @@ impl OutputState {
fn uninitialized() -> OutputState { fn uninitialized() -> OutputState {
OutputState { OutputState {
current_mode: None, current_mode: None,
transform: None, geometry: None,
scale: 1, scale: 1,
} }
} }
pub fn get_pixel_size(&self) -> Option<Size> { fn transform_size<T>(
width: T,
height: T,
transform: self::c::Transform,
) -> Size<T> {
use self::c::Transform; use self::c::Transform;
match transform {
Transform::Normal
| Transform::Rotated180
| Transform::Flipped
| Transform::FlippedRotated180 => Size {
width,
height,
},
_ => Size {
width: height,
height: width,
},
}
}
/// Return resolution adjusted for current transform
pub fn get_pixel_size(&self) -> Option<PixelSize> {
match self { match self {
OutputState { OutputState {
current_mode: Some(Mode { width, height } ), current_mode: Some(Mode { width, height } ),
transform: Some(transform), geometry: Some(Geometry { transform, .. } ),
scale: _, scale: _,
} => Some( } => Some(Self::transform_size(*width as u32, *height as u32, *transform)),
match transform { OutputState {
Transform::Normal current_mode: Some(Mode { width, height } ),
| Transform::Rotated180 ..
| Transform::Flipped } => Some(PixelSize { width: *width as u32, height: *height as u32 } ),
| Transform::FlippedRotated180 => Size { _ => None,
width: *width as u32, }
height: *height as u32, }
},
_ => Size { /// Return physical dimensions adjusted for current transform
width: *height as u32, pub fn get_physical_size(&self) -> Option<Size<Option<Millimeter>>> {
height: *width as u32, match self {
}, OutputState {
} geometry: Some(Geometry { transform, phys_size } ),
), ..
} => Some(Self::transform_size(phys_size.width, phys_size.height, *transform)),
_ => None, _ => None,
} }
} }

130
src/panel.c Normal file
View File

@ -0,0 +1,130 @@
#include "eekboard/eekboard-context-service.h"
#include "wayland.h"
#include "panel.h"
// Called from rust
/// Destroys the widget
void
panel_manager_hide(struct panel_manager *self)
{
if (self->window) {
gtk_widget_destroy (GTK_WIDGET (self->window));
}
if (self->widget) {
gtk_widget_destroy (GTK_WIDGET (self->widget));
}
self->window = NULL;
self->widget = NULL;
}
static void
on_destroy (struct panel_manager *self, GtkWidget *widget)
{
g_assert (widget == GTK_WIDGET(self->window));
panel_manager_hide(self);
}
/// panel::Manager. Only needed for this callback
struct squeek_panel_manager;
/// Calls back into Rust
void squeek_panel_manager_configured(struct squeek_panel_manager *mgr, uint32_t width, uint32_t height);
static void
on_surface_configure(struct squeek_panel_manager *self, PhoshLayerSurface *surface)
{
gint width;
gint height;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (surface));
g_object_get(G_OBJECT(surface),
"configured-width", &width,
"configured-height", &height,
NULL);
squeek_panel_manager_configured(self, width, height);
}
static void
make_widget (struct panel_manager *self)
{
if (self->widget) {
g_error("Widget already present");
}
self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout);
gtk_widget_set_has_tooltip (self->widget, TRUE);
gtk_container_add (GTK_CONTAINER(self->window), self->widget);
gtk_widget_show_all(self->widget);
}
// Called from rust
/// Creates a new panel widget
void
panel_manager_request_widget (struct panel_manager *self, struct wl_output *output, uint32_t height, struct squeek_panel_manager *mgr)
{
if (self->window) {
g_error("Window already present");
}
self->window = g_object_new (
PHOSH_TYPE_LAYER_SURFACE,
"layer-shell", squeek_wayland->layer_shell,
"wl-output", output,
"height", height,
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
"kbd-interactivity", FALSE,
"exclusive-zone", height,
"namespace", "osk",
NULL
);
g_object_connect (self->window,
"swapped-signal::destroy", G_CALLBACK(on_destroy), self,
"swapped-signal::configured", G_CALLBACK(on_surface_configure), mgr,
NULL);
// The properties below are just to make hacking easier.
// The way we use layer-shell overrides some,
// and there's no space in the protocol for others.
// Those may still be useful in the future,
// or for hacks with regular windows.
gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
gtk_window_set_title (GTK_WINDOW(self->window), "Squeekboard");
gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
make_widget(self);
gtk_widget_show (GTK_WIDGET(self->window));
}
// Called from rust
/// Updates the size
void
panel_manager_resize (struct panel_manager *self, uint32_t height)
{
phosh_layer_surface_set_size(self->window, 0, height);
phosh_layer_surface_set_exclusive_zone(self->window, height);
phosh_layer_surface_wl_surface_commit(self->window);
}
struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout)
{
struct panel_manager mgr = {
.state = state,
.submission = submission,
.layout = layout,
.window = NULL,
.widget = NULL,
.current_output = NULL,
};
return mgr;
}

21
src/panel.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "eek/layersurface.h"
#include "src/layout.h"
#include "src/submission.h"
// Stores the objects that the panel and its widget will refer to
struct panel_manager {
EekboardContextService *state; // unowned
/// Needed for instantiating the widget
struct submission *submission; // unowned
struct squeek_layout_state *layout;
PhoshLayerSurface *window;
GtkWidget *widget; // nullable
// Those should be held in Rust
struct wl_output *current_output;
};
struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout);

248
src/panel.rs Normal file
View File

@ -0,0 +1,248 @@
/* Copyright (C) 2022 Purism SPC
* SPDX-License-Identifier: GPL-3.0+
*/
/*! Panel state management.
*
* This is effectively a mirror of the previous C code,
* with an explicit state machine managing the panel size.
*
* It still relies on a callback from Wayland to accept the panel size,
* which makes this code somewhat prone to mistakes.
*
* An alternative to the callback would be
* to send a message all the way to `state::State`
* every time the allocated size changes.
* That would allow for a more holistic view
* of interactions of different pieces of state.
*
* However, `state::State` already has the potential to become a ball of mud,
* tightly coupling different functionality and making it difficult to see independent units.
*
* For this reason, I'm taking a light touch approach with the panel manager,
* and moving it just a bit closer to `state::State`.
* Hopefully ths still allows us to expose assumptions that were not stated yet
* (e.g. can the output disappear between size request andallocation?).
*
* Tight coupling, e.g. a future one between presented hints and layout size,
* will have to be taken into account later.
*/
use crate::logging;
use crate::outputs::OutputId;
use crate::util::c::Wrapped;
pub mod c {
use super::*;
use glib;
use gtk::Continue;
use std::os::raw::c_void;
use crate::outputs::c::WlOutput;
/// struct panel_manager*
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct PanelManager(*const c_void);
extern "C" {
#[allow(improper_ctypes)]
pub fn panel_manager_request_widget(
service: PanelManager,
output: WlOutput,
height: u32,
// for callbacks
panel: Wrapped<Manager>,
);
pub fn panel_manager_resize(service: PanelManager, height: u32);
pub fn panel_manager_hide(service: PanelManager);
}
#[no_mangle]
pub extern "C"
fn squeek_panel_manager_configured(panel: Wrapped<Manager>, width: u32, height: u32) {
// This is why this needs to be moved into state::State:
// it's getting too coupled to glib.
glib::idle_add_local(move || {
let panel = panel.clone_ref();
panel.borrow_mut().set_configured(Size{width, height});
Continue(false)
});
}
}
/// Size in pixels that is aware of scaling
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct PixelSize {
pub pixels: u32,
pub scale_factor: u32,
}
fn div_ceil(a: u32, b: u32) -> u32 {
// Given that it's for pixels on a screen, an overflow is unlikely.
(a + b - 1) / b
}
impl PixelSize {
pub fn as_scaled_floor(&self) -> u32 {
self.pixels / self.scale_factor
}
pub fn as_scaled_ceiling(&self) -> u32 {
div_ceil(self.pixels, self.scale_factor)
}
}
#[derive(Clone, Debug)]
struct Size {
width: u32,
height: u32,
}
/// This state requests the Wayland layer shell protocol synchronization:
/// the application asks for some size,
/// and then receives a size that the compositor thought appropriate.
/// Stores raw values passed to Wayland, i.e. scaled dimensions.
#[derive(Clone, Debug)]
enum State {
Hidden,
SizeRequested {
output: OutputId,
height: u32,
//width: u32,
},
SizeAllocated {
output: OutputId,
wanted_height: u32,
allocated: Size,
},
}
#[derive(Clone, PartialEq, Debug)]
pub enum Command {
Show {
output: OutputId,
height: PixelSize,
},
Hide,
}
/// Tries to contain all the panel sizing duties.
pub struct Manager {
panel: c::PanelManager,
state: State,
}
impl Manager {
pub fn new(panel: c::PanelManager) -> Self {
Self {
panel,
state: State::Hidden,
}
}
// TODO: mabe send the allocated size back to state::State,
// to perform layout adjustments
fn set_configured(&mut self, size: Size) {
self.state = match self.state.clone() {
State::Hidden => {
// This may happen if a hide is scheduled immediately after a show.
log_print!(
logging::Level::Surprise,
"Panel has been configured, but no request is pending. Ignoring",
);
State::Hidden
},
State::SizeAllocated{output, wanted_height, ..} => {
log_print!(
logging::Level::Surprise,
"Panel received new configuration without asking",
);
State::SizeAllocated{output, wanted_height, allocated: size}
},
State::SizeRequested{output, height} => State::SizeAllocated {
output,
wanted_height: height,
allocated: size,
},
};
}
pub fn update(mgr: Wrapped<Manager>, cmd: Command) {
let copied = mgr.clone();
let mgr = mgr.clone_ref();
let mut mgr = mgr.borrow_mut();
(*mgr).state = match (cmd, mgr.state.clone()) {
(Command::Hide, State::Hidden) => State::Hidden,
(Command::Hide, State::SizeAllocated{..}) => {
unsafe { c::panel_manager_hide(mgr.panel); }
State::Hidden
},
(Command::Hide, State::SizeRequested{..}) => {
unsafe { c::panel_manager_hide(mgr.panel); }
State::Hidden
},
(Command::Show{output, height}, State::Hidden) => {
let height = height.as_scaled_ceiling();
unsafe { c::panel_manager_request_widget(mgr.panel, output.0, height, copied); }
State::SizeRequested{output, height}
},
(
Command::Show{output, height},
State::SizeRequested{output: req_output, height: req_height},
) => {
let height = height.as_scaled_ceiling();
if output == req_output && height == req_height {
State::SizeRequested{output: req_output, height: req_height}
} else if output == req_output {
// I'm not sure about that.
// This could cause a busy loop,
// when two requests are being processed at the same time:
// one message in the compositor to allocate size A,
// causing the state to update to height A'
// the other from the state wanting height B',
// causing the compositor to change size to B.
// So better cut this short here, despite artifacts.
// Out of simplicty, just ignore the new request.
// If that causes problems, the request in flight could be stored
// for the purpose of handling it better somehow.
State::SizeRequested{output: req_output, height: req_height}
} else {
// This looks weird, but should be safe.
// The stack seems to handle
// configure events on a dead surface.
unsafe {
c::panel_manager_hide(mgr.panel);
c::panel_manager_request_widget(mgr.panel, output.0, height, copied);
}
State::SizeRequested{output, height}
}
},
(
Command::Show{output, height},
State::SizeAllocated{output: alloc_output, allocated, wanted_height},
) => {
let height = height.as_scaled_ceiling();
if output == alloc_output && height == wanted_height {
State::SizeAllocated{output: alloc_output, wanted_height, allocated}
} else if output == alloc_output && height == allocated.height {
State::SizeAllocated{output: alloc_output, wanted_height: height, allocated}
} else if output == alloc_output {
// Should *all* other heights cause a resize?
// What about those between wanted and allocated?
unsafe { c::panel_manager_resize(mgr.panel, height); }
State::SizeRequested{output, height}
} else {
unsafe {
c::panel_manager_hide(mgr.panel);
c::panel_manager_request_widget(mgr.panel, output.0, height, copied);
}
State::SizeRequested{output, height}
}
},
}
}
}

View File

@ -54,6 +54,8 @@ static KEYBOARDS: &[(&'static str, &'static str)] = &[
("fr_wide", include_str!("../data/keyboards/fr_wide.yaml")), ("fr_wide", include_str!("../data/keyboards/fr_wide.yaml")),
("gr", include_str!("../data/keyboards/gr.yaml")), ("gr", include_str!("../data/keyboards/gr.yaml")),
("gr_wide", include_str!("../data/keyboards/gr_wide.yaml")),
("gr+polytonic", include_str!("../data/keyboards/gr+polytonic.yaml")),
("il", include_str!("../data/keyboards/il.yaml")), ("il", include_str!("../data/keyboards/il.yaml")),

View File

@ -20,14 +20,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "eek/eek.h"
#include "eek/eek-gtk-keyboard.h"
#include "eek/layersurface.h"
#include "eekboard/eekboard-context-service.h"
#include "submission.h"
#include "wayland.h"
#include "server-context-service.h" #include "server-context-service.h"
#include "wayland-client-protocol.h"
enum { enum {
PROP_0, PROP_0,
@ -37,148 +30,13 @@ enum {
struct _ServerContextService { struct _ServerContextService {
GObject parent; GObject parent;
EekboardContextService *state; // unowned
/// Needed for instantiating the widget
struct submission *submission; // unowned
struct squeek_layout_state *layout;
struct squeek_state_manager *state_manager; // shared reference struct squeek_state_manager *state_manager; // shared reference
PhoshLayerSurface *window;
GtkWidget *widget; // nullable
struct wl_output *current_output;
guint last_requested_height;
}; };
G_DEFINE_TYPE(ServerContextService, server_context_service, G_TYPE_OBJECT); G_DEFINE_TYPE(ServerContextService, server_context_service, G_TYPE_OBJECT);
static void static void
on_destroy (ServerContextService *self, GtkWidget *widget) /// Height is in scaled units.
{
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
g_assert (widget == GTK_WIDGET(self->window));
self->window = NULL;
self->widget = NULL;
//eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
}
static void
make_window (ServerContextService *self, struct wl_output *output, uint32_t height)
{
if (self->window) {
g_error("Window already present");
}
self->window = g_object_new (
PHOSH_TYPE_LAYER_SURFACE,
"layer-shell", squeek_wayland->layer_shell,
"wl-output", output,
"height", height,
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
"kbd-interactivity", FALSE,
"exclusive-zone", height,
"namespace", "osk",
NULL
);
g_object_connect (self->window,
"swapped-signal::destroy", G_CALLBACK(on_destroy), self,
//"swapped-signal::configured", G_CALLBACK(on_surface_configure), self,
NULL);
// The properties below are just to make hacking easier.
// The way we use layer-shell overrides some,
// and there's no space in the protocol for others.
// Those may still be useful in the future,
// or for hacks with regular windows.
gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
gtk_window_set_title (GTK_WINDOW(self->window), "Squeekboard");
gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
}
static void
destroy_window (ServerContextService *self)
{
gtk_widget_destroy (GTK_WIDGET (self->window));
self->window = NULL;
}
static void
make_widget (ServerContextService *self)
{
if (self->widget) {
gtk_widget_destroy(self->widget);
self->widget = NULL;
}
self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout);
gtk_widget_set_has_tooltip (self->widget, TRUE);
gtk_container_add (GTK_CONTAINER(self->window), self->widget);
gtk_widget_show_all(self->widget);
}
// Called from rust
/// Updates the type of hiddenness
void
server_context_service_real_hide_keyboard (ServerContextService *self)
{
//self->desired_height = 0;
self->current_output = NULL;
if (self->window) {
gtk_widget_hide (GTK_WIDGET(self->window));
}
}
// Called from rust
/// Updates the type of visibility
void
server_context_service_update_keyboard (ServerContextService *self, struct wl_output *output, uint32_t height)
{
if (output != self->current_output) {
// Recreate on a new output
server_context_service_real_hide_keyboard(self);
} else {
gint h;
PhoshLayerSurface *surface = self->window;
g_object_get(G_OBJECT(surface),
"configured-height", &h,
NULL);
if ((uint32_t)h != height) {
//TODO: make sure that redrawing happens in the correct place (it doesn't now).
phosh_layer_surface_set_size(self->window, 0, height);
phosh_layer_surface_set_exclusive_zone(self->window, height);
phosh_layer_surface_wl_surface_commit(self->window);
self->current_output = output;
return;
}
}
self->current_output = output;
if (!self->window) {
make_window (self, output, height);
}
if (!self->widget) {
make_widget (self);
}
gtk_widget_show (GTK_WIDGET(self->window));
}
static void
server_context_service_set_property (GObject *object, server_context_service_set_property (GObject *object,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
@ -209,17 +67,6 @@ server_context_service_get_property (GObject *object,
} }
} }
static void
server_context_service_dispose (GObject *object)
{
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
destroy_window (self);
self->widget = NULL;
G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
}
static void static void
server_context_service_class_init (ServerContextServiceClass *klass) server_context_service_class_init (ServerContextServiceClass *klass)
{ {
@ -228,7 +75,6 @@ server_context_service_class_init (ServerContextServiceClass *klass)
gobject_class->set_property = server_context_service_set_property; gobject_class->set_property = server_context_service_set_property;
gobject_class->get_property = server_context_service_get_property; gobject_class->get_property = server_context_service_get_property;
gobject_class->dispose = server_context_service_dispose;
/** /**
* ServerContextServie:keyboard: * ServerContextServie:keyboard:
@ -249,41 +95,29 @@ server_context_service_class_init (ServerContextServiceClass *klass)
static void static void
server_context_service_init (ServerContextService *self) {} server_context_service_init (ServerContextService *self) {}
static void
init (ServerContextService *self) { ServerContextService *
server_context_service_new (struct squeek_state_manager *state_manager)
{
ServerContextService *holder = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL);
holder->state_manager = state_manager;
const char *schema_name = "org.gnome.desktop.a11y.applications"; const char *schema_name = "org.gnome.desktop.a11y.applications";
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default(); GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default();
g_autoptr(GSettingsSchema) schema = NULL; g_autoptr(GSettingsSchema) schema = NULL;
if (!ssrc) { if (!ssrc) {
g_warning("No gsettings schemas installed."); g_warning("No gsettings schemas installed.");
return; return NULL;
} }
schema = g_settings_schema_source_lookup(ssrc, schema_name, TRUE); schema = g_settings_schema_source_lookup(ssrc, schema_name, TRUE);
if (schema) { if (schema) {
g_autoptr(GSettings) settings = g_settings_new (schema_name); g_autoptr(GSettings) settings = g_settings_new (schema_name);
g_settings_bind (settings, "screen-keyboard-enabled", g_settings_bind (settings, "screen-keyboard-enabled",
self, "enabled", G_SETTINGS_BIND_GET); holder, "enabled", G_SETTINGS_BIND_GET);
} else { } else {
g_warning("Gsettings schema %s is not installed on the system. " g_warning("Gsettings schema %s is not installed on the system. "
"Enabling by default.", schema_name); "Enabling by default.", schema_name);
} }
} return holder;
ServerContextService *
server_context_service_new (EekboardContextService *self, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager)
{
ServerContextService *ui = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL);
ui->submission = submission;
ui->state = self;
ui->layout = layout;
ui->state_manager = state_manager;
init(ui);
return ui;
}
// Used from Rust
void server_context_service_set_hint_purpose(ServerContextService *self, uint32_t hint,
uint32_t purpose) {
eekboard_context_service_set_hint_purpose(self->state, hint, purpose);
} }

View File

@ -17,9 +17,9 @@
*/ */
#ifndef SERVER_CONTEXT_SERVICE_H #ifndef SERVER_CONTEXT_SERVICE_H
#define SERVER_CONTEXT_SERVICE_H 1 #define SERVER_CONTEXT_SERVICE_H 1
#include <gtk/gtk.h>
#include "src/layout.h" #include "main.h"
#include "src/submission.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -28,8 +28,8 @@ G_BEGIN_DECLS
/** Manages the lifecycle of the window displaying layouts. */ /** Manages the lifecycle of the window displaying layouts. */
G_DECLARE_FINAL_TYPE (ServerContextService, server_context_service, SERVER, CONTEXT_SERVICE, GObject) G_DECLARE_FINAL_TYPE (ServerContextService, server_context_service, SERVER, CONTEXT_SERVICE, GObject)
ServerContextService *server_context_service_new(EekboardContextService *self, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager); ServerContextService *server_context_service_new(struct squeek_state_manager *state_manager);
enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *);
G_END_DECLS G_END_DECLS
#endif /* SERVER_CONTEXT_SERVICE_H */ #endif /* SERVER_CONTEXT_SERVICE_H */

View File

@ -31,6 +31,7 @@
#include "layout.h" #include "layout.h"
#include "main.h" #include "main.h"
#include "outputs.h" #include "outputs.h"
#include "panel.h"
#include "submission.h" #include "submission.h"
#include "server-context-service.h" #include "server-context-service.h"
#include "wayland.h" #include "wayland.h"
@ -51,8 +52,10 @@ typedef enum _SqueekboardDebugFlags {
struct squeekboard { struct squeekboard {
struct squeek_wayland wayland; // Just hooks. struct squeek_wayland wayland; // Just hooks.
DBusHandler *dbus_handler; // Controls visibility of the OSK. DBusHandler *dbus_handler; // Controls visibility of the OSK.
EekboardContextService *settings_context; // Gsettings hooks. EekboardContextService *settings_context; // Gsettings hooks for layouts.
ServerContextService *ui_context; // mess, includes the entire UI /// Gsettings hook for visibility. TODO: this does not belong in gsettings.
ServerContextService *settings_handler;
struct panel_manager panel_manager; // Controls the shape of the panel.
/// Currently wanted layout. TODO: merge into state::Application /// Currently wanted layout. TODO: merge into state::Application
struct squeek_layout_state layout_choice; struct squeek_layout_state layout_choice;
}; };
@ -435,20 +438,21 @@ main (int argc, char **argv)
} }
} }
eekboard_context_service_set_submission(instance.settings_context, rsobjects.submission); ServerContextService *setting_listener = server_context_service_new(
ServerContextService *ui_context = server_context_service_new(
instance.settings_context,
rsobjects.submission,
&instance.layout_choice,
rsobjects.state_manager); rsobjects.state_manager);
if (!ui_context) { if (!setting_listener) {
g_error("Could not initialize GUI"); g_warning ("could not connect to gsettings");
exit(1);
} }
instance.ui_context = ui_context; instance.settings_handler = setting_listener;
register_ui_loop_handler(rsobjects.receiver, instance.ui_context, instance.dbus_handler);
eekboard_context_service_set_submission(instance.settings_context, rsobjects.submission);
instance.panel_manager = panel_manager_new(instance.settings_context,
rsobjects.submission,
&instance.layout_choice);
register_ui_loop_handler(rsobjects.receiver, &instance.panel_manager, instance.settings_context, instance.dbus_handler);
session_register(); session_register();

View File

@ -6,27 +6,32 @@
* It's driven by the loop defined in the loop module. */ * It's driven by the loop defined in the loop module. */
use crate::animation; use crate::animation;
use crate::debug;
use crate::imservice::{ ContentHint, ContentPurpose }; use crate::imservice::{ ContentHint, ContentPurpose };
use crate::main::{ Commands, PanelCommand }; use crate::main::Commands;
use crate::outputs; use crate::outputs;
use crate::outputs::{OutputId, OutputState}; use crate::outputs::{Millimeter, OutputId, OutputState};
use crate::panel;
use crate::panel::PixelSize;
use crate::util::Rational;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant; use std::time::Instant;
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub enum Presence { pub enum Presence {
Present, Present,
Missing, Missing,
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct InputMethodDetails { pub struct InputMethodDetails {
pub hint: ContentHint, pub hint: ContentHint,
pub purpose: ContentPurpose, pub purpose: ContentPurpose,
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum InputMethod { pub enum InputMethod {
Active(InputMethodDetails), Active(InputMethodDetails),
InactiveSince(Instant), InactiveSince(Instant),
@ -34,12 +39,13 @@ pub enum InputMethod {
/// Incoming events. /// Incoming events.
/// This contains events that cause a change to the internal state. /// This contains events that cause a change to the internal state.
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum Event { pub enum Event {
InputMethod(InputMethod), InputMethod(InputMethod),
Visibility(visibility::Event), Visibility(visibility::Event),
PhysicalKeyboard(Presence), PhysicalKeyboard(Presence),
Output(outputs::Event), Output(outputs::Event),
Debug(debug::Event),
/// Event triggered because a moment in time passed. /// Event triggered because a moment in time passed.
/// Use to animate state transitions. /// Use to animate state transitions.
/// The value is the ideal arrival time. /// The value is the ideal arrival time.
@ -59,7 +65,7 @@ impl From<outputs::Event> for Event {
} }
pub mod visibility { pub mod visibility {
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum Event { pub enum Event {
/// User requested the panel to show /// User requested the panel to show
ForceVisible, ForceVisible,
@ -79,7 +85,7 @@ pub mod visibility {
} }
/// The outwardly visible state. /// The outwardly visible state.
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Outcome { pub struct Outcome {
pub visibility: animation::Outcome, pub visibility: animation::Outcome,
pub im: InputMethod, pub im: InputMethod,
@ -114,8 +120,8 @@ impl Outcome {
// FIXME: handle switching outputs // FIXME: handle switching outputs
let (dbus_visible_set, panel_visibility) = match new_state.visibility { let (dbus_visible_set, panel_visibility) = match new_state.visibility {
animation::Outcome::Visible{output, height} animation::Outcome::Visible{output, height}
=> (Some(true), Some(PanelCommand::Show{output, height})), => (Some(true), Some(panel::Command::Show{output, height})),
animation::Outcome::Hidden => (Some(false), Some(PanelCommand::Hide)), animation::Outcome::Hidden => (Some(false), Some(panel::Command::Hide)),
}; };
Commands { Commands {
@ -137,11 +143,12 @@ impl Outcome {
/// All state changes return the next state and the optimal time for the next check. /// All state changes return the next state and the optimal time for the next check.
/// ///
/// This state tracker can be driven by any event loop. /// This state tracker can be driven by any event loop.
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Application { pub struct Application {
pub im: InputMethod, pub im: InputMethod,
pub visibility_override: visibility::State, pub visibility_override: visibility::State,
pub physical_keyboard: Presence, pub physical_keyboard: Presence,
pub debug_mode_enabled: bool,
/// The output on which the panel should appear. /// The output on which the panel should appear.
/// This is stored as part of the state /// This is stored as part of the state
/// because it's not clear how to derive the output from the rest of the state. /// because it's not clear how to derive the output from the rest of the state.
@ -163,13 +170,29 @@ impl Application {
im: InputMethod::InactiveSince(now), im: InputMethod::InactiveSince(now),
visibility_override: visibility::State::NotForced, visibility_override: visibility::State::NotForced,
physical_keyboard: Presence::Missing, physical_keyboard: Presence::Missing,
debug_mode_enabled: false,
preferred_output: None, preferred_output: None,
outputs: Default::default(), outputs: Default::default(),
} }
} }
pub fn apply_event(self, event: Event, _now: Instant) -> Self { pub fn apply_event(self, event: Event, now: Instant) -> Self {
match event { if self.debug_mode_enabled {
println!(
"Received event:
{:#?}",
event,
);
}
let state = match event {
Event::Debug(dbg) => Self {
debug_mode_enabled: match dbg {
debug::Event::Enable => true,
debug::Event::Disable => false,
},
..self
},
Event::TimeoutReached(_) => self, Event::TimeoutReached(_) => self,
Event::Visibility(visibility) => Self { Event::Visibility(visibility) => Self {
@ -235,25 +258,88 @@ impl Application {
..self ..self
}, },
} }
};
if state.debug_mode_enabled {
println!(
"State is now:
{:#?}
Outcome:
{:#?}",
state,
state.get_outcome(now),
);
} }
state
} }
fn get_preferred_height(output: &OutputState) -> Option<u32> { fn get_preferred_height(output: &OutputState) -> Option<PixelSize> {
output.get_pixel_size() output.get_pixel_size()
.map(|px_size| { .map(|px_size| {
let height = { // Assume isotropy.
if px_size.width > px_size.height { // Pixels/mm.
px_size.width / 5 let density = output.get_physical_size()
} else { .and_then(|size| size.width)
if (px_size.width < 540) & (px_size.width > 0) { .map(|width| Rational {
px_size.width * 7 / 12 // to match 360×210 numerator: px_size.width as i32,
} else { denominator: width.0 as u32,
// Here we switch to wide layout, less height needed })
px_size.width * 7 / 22 // Whatever the Librem 5 has,
} // as a good default.
} .unwrap_or(Rational {
numerator: 720,
denominator: 65,
});
// Based on what works on the L5.
// Exceeding that probably wastes space. Reducing makes typing harder.
const IDEAL_TARGET_SIZE: Rational<Millimeter> = Rational {
numerator: Millimeter(948),
denominator: 100,
}; };
cmp::min(height, px_size.height / 2)
// TODO: calculate based on selected layout
const ROW_COUNT: u32 = 4;
let height = {
let ideal_height = IDEAL_TARGET_SIZE * ROW_COUNT as i32;
let ideal_height_px = (ideal_height * density).ceil().0 as u32;
// Reduce height to match what the layout can fill.
// For this, we need to guess if normal or wide will be picked up.
// This must match `eek_gtk_keyboard.c::get_type`.
// TODO: query layout database and choose one directly
let abstract_width
= PixelSize {
scale_factor: output.scale as u32,
pixels: px_size.width,
}
.as_scaled_ceiling();
let height_as_widths = {
if abstract_width < 540 {
// Normal
Rational {
numerator: 210,
denominator: 360,
}
} else {
// Wide
Rational {
numerator: 172,
denominator: 540,
}
}
};
cmp::min(
ideal_height_px,
(height_as_widths * px_size.width as i32).ceil() as u32,
)
};
PixelSize {
scale_factor: output.scale as u32,
pixels: cmp::min(height, px_size.height / 2),
}
}) })
} }
@ -265,10 +351,10 @@ impl Application {
Some(output) => { Some(output) => {
// Hoping that this will get optimized out on branches not using `visible`. // Hoping that this will get optimized out on branches not using `visible`.
let height = Self::get_preferred_height(self.outputs.get(&output).unwrap()) let height = Self::get_preferred_height(self.outputs.get(&output).unwrap())
.unwrap_or(0); .unwrap_or(PixelSize{pixels: 0, scale_factor: 1});
// TODO: Instead of setting size to 0 when the output is invalid, // TODO: Instead of setting size to 0 when the output is invalid,
// simply go invisible. // simply go invisible.
let visible = animation::Outcome::Visible{output, height}; let visible = animation::Outcome::Visible{ output, height };
match (self.physical_keyboard, self.visibility_override) { match (self.physical_keyboard, self.visibility_override) {
(_, visibility::State::ForcedHidden) => animation::Outcome::Hidden, (_, visibility::State::ForcedHidden) => animation::Outcome::Hidden,
@ -332,7 +418,7 @@ pub mod test {
id, id,
OutputState { OutputState {
current_mode: None, current_mode: None,
transform: None, geometry: None,
scale: 1, scale: 1,
}, },
); );
@ -514,4 +600,29 @@ pub mod test {
); );
} }
#[test]
fn size_l5() {
use crate::outputs::{Mode, Geometry, c, Size};
assert_eq!(
Application::get_preferred_height(&OutputState {
current_mode: Some(Mode {
width: 720,
height: 1440,
}),
geometry: Some(Geometry{
transform: c::Transform::Normal,
phys_size: Size {
width: Some(Millimeter(65)),
height: Some(Millimeter(130)),
},
}),
scale: 2,
}),
Some(PixelSize {
scale_factor: 2,
pixels: 420,
}),
);
}
} }

View File

@ -1,12 +1,12 @@
#ifndef __SUBMISSION_H #ifndef __SUBMISSION_H
#define __SUBMISSION_H #define __SUBMISSION_H
#include "input-method-unstable-v2-client-protocol.h" #include "inttypes.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
#include "eek/eek-types.h" #include "eek/eek-types.h"
#include "main.h"
struct squeek_layout; struct squeek_layout;
struct submission;
// Defined in Rust // Defined in Rust
uint8_t submission_hint_available(struct submission *self); uint8_t submission_hint_available(struct submission *self);

View File

@ -7,6 +7,7 @@ use ::float_ord::FloatOrd;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::hash::{ Hash, Hasher }; use std::hash::{ Hash, Hasher };
use std::iter::FromIterator; use std::iter::FromIterator;
use std::ops::Mul;
pub mod c { pub mod c {
use super::*; use super::*;
@ -157,6 +158,54 @@ pub fn find_max_double<T, I, F>(iterator: I, get: F)
.0 .0
} }
pub trait DivCeil<Rhs = Self> {
type Output;
fn div_ceil(self, rhs: Rhs) -> Self::Output;
}
/// Newer Rust introduces this natively,
/// but we don't always have newer Rust.
impl DivCeil for i32 {
type Output = Self;
fn div_ceil(self, other: i32) -> Self::Output {
let d = self / other;
let m = self % other;
if m == 0 { d } else { d + 1}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Rational<T> {
pub numerator: T,
pub denominator: u32,
}
impl<U, T: DivCeil<i32, Output=U>> Rational<T> {
pub fn ceil(self) -> U {
self.numerator.div_ceil(self.denominator as i32)
}
}
impl<T: Mul<i32, Output=T>> Mul<i32> for Rational<T> {
type Output = Self;
fn mul(self, m: i32) -> Self {
Self {
numerator: self.numerator * m,
denominator: self.denominator,
}
}
}
impl<U, T: Mul<U, Output=T>> Mul<Rational<U>> for Rational<T> {
type Output = Self;
fn mul(self, m: Rational<U>) -> Self {
Self {
numerator: self.numerator * m.numerator,
denominator: self.denominator * m.denominator,
}
}
}
/// Compares pointers but not internal values of Rc /// Compares pointers but not internal values of Rc
pub struct Pointer<T>(pub Rc<T>); pub struct Pointer<T>(pub Rc<T>);

View File

@ -76,7 +76,8 @@ foreach layout : [
'es+cat', 'es+cat',
'fi', 'fi',
'fr', 'fr_wide', 'fr', 'fr_wide',
'gr', 'gr', 'gr_wide',
'gr+polytonic',
'il', 'il',
'ir', 'ir',
'it', 'it',