Compare commits
	
		
			15 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2e44b448af | |||
| 8afcd87fc8 | |||
| be458fb10e | |||
| b8e74b3721 | |||
| d753f2dc2c | |||
| f91c58ae4d | |||
| 0c258711cf | |||
| 622cd03918 | |||
| 7589a2d1d1 | |||
| 7cb431b58d | |||
| 1dd4b38c88 | |||
| 1d3e8c9a4b | |||
| 1c6448a9f7 | |||
| 3d2f9f3d9e | |||
| a20ab70984 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,6 +1,5 @@
 | 
			
		||||
.zanata-cache/
 | 
			
		||||
_build
 | 
			
		||||
po/squeekboard.pot
 | 
			
		||||
po/*.mo
 | 
			
		||||
TAGS
 | 
			
		||||
tags
 | 
			
		||||
vgdump
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										126
									
								
								.gitlab-ci.yml
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								.gitlab-ci.yml
									
									
									
									
									
								
							@ -1,14 +1,22 @@
 | 
			
		||||
image: pureos/byzantium
 | 
			
		||||
image: debian:bullseye
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
  - build
 | 
			
		||||
  - test
 | 
			
		||||
 | 
			
		||||
.tags: &tags
 | 
			
		||||
  tags:
 | 
			
		||||
    - librem5
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
  - apt-get -y update
 | 
			
		||||
  - apt-get -y install ca-certificates
 | 
			
		||||
  - apt-get -y install wget ca-certificates gnupg
 | 
			
		||||
  - echo "deb [trusted=yes] http://ci.puri.sm/ bullseyeci main" > /etc/apt/sources.list.d/ci.list
 | 
			
		||||
  - wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
 | 
			
		||||
  - apt-get -y update
 | 
			
		||||
 | 
			
		||||
build_docs:
 | 
			
		||||
  <<: *tags
 | 
			
		||||
  stage: build
 | 
			
		||||
  artifacts:
 | 
			
		||||
    paths:
 | 
			
		||||
@ -17,11 +25,10 @@ build_docs:
 | 
			
		||||
      - apt-get -y install python3-pip python3-sphinx
 | 
			
		||||
      - pip3 install recommonmark
 | 
			
		||||
      - ./doc/build.sh _build
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
 | 
			
		||||
build_meson:
 | 
			
		||||
  tags:
 | 
			
		||||
    - librem5
 | 
			
		||||
  stage: build
 | 
			
		||||
  artifacts:
 | 
			
		||||
    paths:
 | 
			
		||||
@ -31,114 +38,115 @@ build_meson:
 | 
			
		||||
    - apt-get -y build-dep .
 | 
			
		||||
    - meson . _build/ -Ddepdatadir=/usr/share --werror
 | 
			
		||||
    - ninja -C _build install
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
 | 
			
		||||
build_deb:
 | 
			
		||||
    tags:
 | 
			
		||||
        - librem5
 | 
			
		||||
    stage: build
 | 
			
		||||
    artifacts:
 | 
			
		||||
      paths:
 | 
			
		||||
      - '*.deb'
 | 
			
		||||
        - "*.deb"
 | 
			
		||||
    script:
 | 
			
		||||
        - rm -f ../*.deb
 | 
			
		||||
        - apt-get -y build-dep .
 | 
			
		||||
        - apt-get -y install devscripts
 | 
			
		||||
    - REV=$(git log -1 --format=%h)
 | 
			
		||||
    - VER=$(dpkg-parsechangelog -SVersion)
 | 
			
		||||
    - DEBFULLNAME="Librem5 CI"
 | 
			
		||||
    - EMAIL="librem5-builds@lists.community.puri.sm"
 | 
			
		||||
    - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG"
 | 
			
		||||
        - debuild -i -us -uc -b
 | 
			
		||||
        - cp ../*.deb .
 | 
			
		||||
 | 
			
		||||
build_deb:amber:
 | 
			
		||||
    image: pureos/amber
 | 
			
		||||
    tags:
 | 
			
		||||
        - librem5
 | 
			
		||||
    stage: build
 | 
			
		||||
    artifacts:
 | 
			
		||||
      paths:
 | 
			
		||||
        - "*.deb"
 | 
			
		||||
    script:
 | 
			
		||||
        - echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
 | 
			
		||||
        - apt-get -y update
 | 
			
		||||
        - rm -f ../*.deb
 | 
			
		||||
        - apt-get -y build-dep .
 | 
			
		||||
        - apt-get -y install devscripts
 | 
			
		||||
        - debuild -i -us -uc -b
 | 
			
		||||
        - cp ../*.deb .
 | 
			
		||||
 | 
			
		||||
build_deb:buster:
 | 
			
		||||
    image: "debian:buster"
 | 
			
		||||
    tags:
 | 
			
		||||
        - librem5
 | 
			
		||||
    stage: build
 | 
			
		||||
    artifacts:
 | 
			
		||||
      paths:
 | 
			
		||||
        - "*.deb"
 | 
			
		||||
    script:
 | 
			
		||||
        - echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
 | 
			
		||||
        - apt-get -y update
 | 
			
		||||
        - rm -f ../*.deb
 | 
			
		||||
        - apt-get -y build-dep .
 | 
			
		||||
        - apt-get -y install devscripts
 | 
			
		||||
        - debuild -i -us -uc -b
 | 
			
		||||
        - cp ../*.deb .
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
build_deb:arm64:
 | 
			
		||||
  image: pureos/byzantium
 | 
			
		||||
    tags:
 | 
			
		||||
    - aarch64
 | 
			
		||||
        - librem5:arm64
 | 
			
		||||
    stage: build
 | 
			
		||||
    artifacts:
 | 
			
		||||
      paths:
 | 
			
		||||
      - '*.deb'
 | 
			
		||||
        - "*.deb"
 | 
			
		||||
    script:
 | 
			
		||||
        - rm -f ../*.deb
 | 
			
		||||
        - apt-get -y build-dep .
 | 
			
		||||
        - apt-get -y install devscripts
 | 
			
		||||
    - REV=$(git log -1 --format=%h)
 | 
			
		||||
    - VER=$(dpkg-parsechangelog -SVersion)
 | 
			
		||||
    - DEBFULLNAME="Librem5 CI"
 | 
			
		||||
    - EMAIL="librem5-builds@lists.community.puri.sm"
 | 
			
		||||
    - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG"
 | 
			
		||||
        - debuild -i -us -uc -b
 | 
			
		||||
        - cp ../*.deb .
 | 
			
		||||
 | 
			
		||||
build_deb:future:
 | 
			
		||||
  image: debian:sid
 | 
			
		||||
  allow_failure: true
 | 
			
		||||
build_deb:arm64_buster:
 | 
			
		||||
    image: "debian:buster"
 | 
			
		||||
    tags:
 | 
			
		||||
    - aarch64
 | 
			
		||||
        - librem5:arm64
 | 
			
		||||
    stage: build
 | 
			
		||||
    artifacts:
 | 
			
		||||
      paths:
 | 
			
		||||
      - '*.deb'
 | 
			
		||||
        - "*.deb"
 | 
			
		||||
    script:
 | 
			
		||||
        - echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
 | 
			
		||||
        - apt-get -y update
 | 
			
		||||
        - rm -f ../*.deb
 | 
			
		||||
    - mv debian/control-newer debian/control
 | 
			
		||||
        - apt-get -y build-dep .
 | 
			
		||||
        - apt-get -y install devscripts
 | 
			
		||||
    - REV=$(git log -1 --format=%h)
 | 
			
		||||
    - VER=$(dpkg-parsechangelog -SVersion)
 | 
			
		||||
    - DEBFULLNAME="Librem5 CI"
 | 
			
		||||
    - EMAIL="librem5-builds@lists.community.puri.sm"
 | 
			
		||||
    - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG"
 | 
			
		||||
        - debuild -i -us -uc -b
 | 
			
		||||
        - cp ../*.deb .
 | 
			
		||||
 | 
			
		||||
test_lintian:
 | 
			
		||||
    <<: *tags
 | 
			
		||||
    stage: test
 | 
			
		||||
  needs:
 | 
			
		||||
    - job: build_deb
 | 
			
		||||
      artifacts: true
 | 
			
		||||
    dependencies:
 | 
			
		||||
        - build_deb
 | 
			
		||||
    script:
 | 
			
		||||
        - apt-get -y install lintian
 | 
			
		||||
        - lintian *.deb
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
  tags:
 | 
			
		||||
    - librem5
 | 
			
		||||
  stage: test
 | 
			
		||||
  needs:
 | 
			
		||||
    - job: build_meson
 | 
			
		||||
      artifacts: true
 | 
			
		||||
    - build_meson
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get -y build-dep .
 | 
			
		||||
    - apt-get -y install clang-tidy
 | 
			
		||||
    - ninja -C _build test
 | 
			
		||||
    - tools/style-check_build _build
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
 | 
			
		||||
test_style:
 | 
			
		||||
  stage: test
 | 
			
		||||
  needs: []
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get -y build-dep .
 | 
			
		||||
    - tools/style-check_source
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
    - cd _build
 | 
			
		||||
    - clang-tidy --checks=-clang-diagnostic-missing-braces,readability-braces-around-statements, --warnings-as-errors=readability-braces-around-statements -extra-arg=-Wno-unknown-warning-option ../src/*.c ../eek/*.c ../eekboard/*.c
 | 
			
		||||
 | 
			
		||||
check_release:
 | 
			
		||||
  <<: *tags
 | 
			
		||||
  stage: test
 | 
			
		||||
  needs: []
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
      - master
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get -y install git python3
 | 
			
		||||
    - (head -n 1 ./debian/changelog && git tag) | ./debian/check_release.py
 | 
			
		||||
  except:
 | 
			
		||||
    variables:
 | 
			
		||||
      - $PKG_ONLY == "1"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								Cargo.deps
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Cargo.deps
									
									
									
									
									
								
							@ -1,13 +1,11 @@
 | 
			
		||||
# Dependencies which change based on build flags
 | 
			
		||||
bitflags = "1.2.*"
 | 
			
		||||
clap = { version = "2.33.*", default-features = false }
 | 
			
		||||
regex = { version = "1.3.*", default-features = false, features = ["std", "unicode-case"] }
 | 
			
		||||
 | 
			
		||||
[dependencies.cairo-rs]
 | 
			
		||||
version = "0.7.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.cairo-sys-rs]
 | 
			
		||||
version = "0.9"
 | 
			
		||||
 | 
			
		||||
[dependencies.gdk]
 | 
			
		||||
version = "0.11.*"
 | 
			
		||||
 | 
			
		||||
@ -19,14 +17,6 @@ features = ["v2_44"]
 | 
			
		||||
version = "0.8.*"
 | 
			
		||||
features = ["v2_44"]
 | 
			
		||||
 | 
			
		||||
[dependencies.glib-sys]
 | 
			
		||||
version = "*"
 | 
			
		||||
features = ["v2_44"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk]
 | 
			
		||||
version = "0.7.*"
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk-sys]
 | 
			
		||||
version = "0.9"
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
							
								
								
									
										22
									
								
								Cargo.deps.legacy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Cargo.deps.legacy
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
# Dependencies which change based on build flags
 | 
			
		||||
bitflags = "1.0.*"
 | 
			
		||||
clap = { version = "2.32.*", default-features = false }
 | 
			
		||||
regex = { version = "1.1.*", default-features = false, features = ['use_std'] }
 | 
			
		||||
 | 
			
		||||
[dependencies.cairo-rs]
 | 
			
		||||
version = "0.5.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.gdk]
 | 
			
		||||
version = "0.9.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.gio]
 | 
			
		||||
version = "0.5.*"
 | 
			
		||||
features = ["v2_44"]
 | 
			
		||||
 | 
			
		||||
[dependencies.glib]
 | 
			
		||||
version = "0.6.*"
 | 
			
		||||
features = ["v2_44"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk]
 | 
			
		||||
version = "0.5.*"
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
# Dependencies which change based on build flags
 | 
			
		||||
# For the newer-than-Byzantium config
 | 
			
		||||
bitflags = "1.3.*"
 | 
			
		||||
clap = { version = "2.33.*", default-features = false }
 | 
			
		||||
 | 
			
		||||
[dependencies.cairo-rs]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.cairo-sys-rs]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.gdk]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
 | 
			
		||||
[dependencies.gio]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
features = ["v2_58"]
 | 
			
		||||
 | 
			
		||||
[dependencies.glib]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
features = ["v2_58"]
 | 
			
		||||
 | 
			
		||||
[dependencies.glib-sys]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
features = ["v2_58"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk-sys]
 | 
			
		||||
version = "0.14.*"
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
# 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" }
 | 
			
		||||
							
								
								
									
										100
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										100
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -1,7 +1,5 @@
 | 
			
		||||
# This file is automatically @generated by Cargo.
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 3
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "atk"
 | 
			
		||||
version = "0.7.0"
 | 
			
		||||
@ -28,12 +26,6 @@ dependencies = [
 | 
			
		||||
 "pkg-config",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "autocfg"
 | 
			
		||||
version = "1.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bitflags"
 | 
			
		||||
version = "1.2.1"
 | 
			
		||||
@ -67,21 +59,27 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "cc"
 | 
			
		||||
version = "1.0.73"
 | 
			
		||||
version = "1.0.67"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
 | 
			
		||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "clap"
 | 
			
		||||
version = "2.33.4"
 | 
			
		||||
version = "2.33.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "826bf7bc84f9435630275cb8e802a4a0ec792b615969934bd16d42ffed10f207"
 | 
			
		||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "textwrap",
 | 
			
		||||
 "unicode-width",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "dtoa"
 | 
			
		||||
version = "0.4.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "fragile"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
@ -259,22 +257,6 @@ dependencies = [
 | 
			
		||||
 "pkg-config",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "hashbrown"
 | 
			
		||||
version = "0.11.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "indexmap"
 | 
			
		||||
version = "1.8.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
 "hashbrown",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "lazy_static"
 | 
			
		||||
version = "1.4.0"
 | 
			
		||||
@ -283,9 +265,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "libc"
 | 
			
		||||
version = "0.2.119"
 | 
			
		||||
version = "0.2.94"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
 | 
			
		||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "linked-hash-map"
 | 
			
		||||
@ -338,28 +320,43 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pkg-config"
 | 
			
		||||
version = "0.3.24"
 | 
			
		||||
version = "0.3.19"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
 | 
			
		||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "proc-macro2"
 | 
			
		||||
version = "1.0.36"
 | 
			
		||||
version = "1.0.26"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
 | 
			
		||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "unicode-xid",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quote"
 | 
			
		||||
version = "1.0.15"
 | 
			
		||||
version = "1.0.9"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
 | 
			
		||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "regex"
 | 
			
		||||
version = "1.3.9"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "regex-syntax",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "regex-syntax"
 | 
			
		||||
version = "0.6.25"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rs"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
@ -375,31 +372,26 @@ dependencies = [
 | 
			
		||||
 "gtk",
 | 
			
		||||
 "gtk-sys",
 | 
			
		||||
 "maplit",
 | 
			
		||||
 "regex",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "serde_yaml",
 | 
			
		||||
 "xkbcommon",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ryu"
 | 
			
		||||
version = "1.0.9"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde"
 | 
			
		||||
version = "1.0.136"
 | 
			
		||||
version = "1.0.126"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
 | 
			
		||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "serde_derive",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde_derive"
 | 
			
		||||
version = "1.0.136"
 | 
			
		||||
version = "1.0.126"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 | 
			
		||||
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
@ -408,21 +400,21 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde_yaml"
 | 
			
		||||
version = "0.8.23"
 | 
			
		||||
version = "0.8.17"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
 | 
			
		||||
checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "indexmap",
 | 
			
		||||
 "ryu",
 | 
			
		||||
 "dtoa",
 | 
			
		||||
 "linked-hash-map",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "yaml-rust",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "1.0.86"
 | 
			
		||||
version = "1.0.72"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
 | 
			
		||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
@ -440,9 +432,9 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-width"
 | 
			
		||||
version = "0.1.9"
 | 
			
		||||
version = "0.1.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
 | 
			
		||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-xid"
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,22 @@ name = "test_layout"
 | 
			
		||||
path = "@path@/examples/test_layout.rs"
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
glib_v0_14 = []
 | 
			
		||||
gio_v0_5 = []
 | 
			
		||||
gtk_v0_5 = []
 | 
			
		||||
rustc_less_1_36 = []
 | 
			
		||||
 | 
			
		||||
# Dependencies which don't change based on build flags
 | 
			
		||||
[dependencies.cairo-sys-rs]
 | 
			
		||||
version = ""
 | 
			
		||||
 | 
			
		||||
[dependencies.glib-sys]
 | 
			
		||||
version = ""
 | 
			
		||||
features = ["v2_44"]
 | 
			
		||||
 | 
			
		||||
[dependencies.gtk-sys]
 | 
			
		||||
version = ""
 | 
			
		||||
features = ["v3_22"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
maplit = "1.0.*"
 | 
			
		||||
serde = { version = "1.0.*", features = ["derive"] }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
*squeekboard* - a Wayland on-screen keyboard
 | 
			
		||||
*squeekboard* - a Wayland virtual keyboard
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
*Squeekboard* is a keyboard-shaped input method supporting Wayland, built primarily for the *Librem 5* phone.
 | 
			
		||||
*Squeekboard* is a virtual keyboard supporting Wayland, built primarily for the *Librem 5* phone.
 | 
			
		||||
 | 
			
		||||
It squeaks because some Rust got inside.
 | 
			
		||||
 | 
			
		||||
@ -11,24 +11,20 @@ Features
 | 
			
		||||
### Present
 | 
			
		||||
 | 
			
		||||
- GTK3
 | 
			
		||||
- Custom keyboard layouts defined in yaml
 | 
			
		||||
- Input purpose dependent keyboard layouts
 | 
			
		||||
- Custom yaml-defined keyboards
 | 
			
		||||
- DBus interface to show and hide
 | 
			
		||||
- Use Wayland input method protocol to submit text
 | 
			
		||||
- Use Wayland input method protocol to show and hide
 | 
			
		||||
- Use Wayland virtual keyboard protocol
 | 
			
		||||
 | 
			
		||||
### Temporarily dropped
 | 
			
		||||
 | 
			
		||||
- A settings interface
 | 
			
		||||
 | 
			
		||||
### TODO
 | 
			
		||||
 | 
			
		||||
- Text prediction/correction
 | 
			
		||||
- Use preedit
 | 
			
		||||
- Submit actions like "next field" using a future Wayland protocol
 | 
			
		||||
- Use Wayland input method protocol
 | 
			
		||||
- Pick up DBus interface files from /usr/share
 | 
			
		||||
 | 
			
		||||
Creating layouts
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
If you want to work on layouts, check out the [guide](doc/tutorial.md).
 | 
			
		||||
 | 
			
		||||
Building
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
@ -39,7 +35,7 @@ See `.gitlab-ci.yml` or run `apt-get build-dep .`
 | 
			
		||||
### Build from git repo
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ git clone https://gitlab.gnome.org/World/Phosh/squeekboard.git
 | 
			
		||||
$ git clone https://source.puri.sm/Librem5/squeekboard.git
 | 
			
		||||
$ cd squeekboard
 | 
			
		||||
$ mkdir _build
 | 
			
		||||
$ meson _build/
 | 
			
		||||
@ -58,31 +54,18 @@ $ cd ../build/
 | 
			
		||||
$ src/squeekboard
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Squeekboard's panel will appear whenever a compatible application requests an input method. Click a text field in any GTK application, like `python3 ./tools/entry.py`.
 | 
			
		||||
 | 
			
		||||
Squeekboard honors the gnome "screen-keyboard-enabled" setting. Either enable this through gnome-settings under accessibility or run:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Alternatively, force panel visibility manually with:
 | 
			
		||||
To make the keyboard show you can use either an application that does so automatically, like a text editor or `python3 ./tests/entry.py`, or you can manually trigger it with:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### What the compositor has to support
 | 
			
		||||
 | 
			
		||||
A compatible compositor has to support the protocols:
 | 
			
		||||
 | 
			
		||||
- layer-shell
 | 
			
		||||
- virtual-keyboard-v1
 | 
			
		||||
 | 
			
		||||
It's strongly recommended to support:
 | 
			
		||||
 | 
			
		||||
- input-method-v2
 | 
			
		||||
 | 
			
		||||
Developing
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
/* Theme independent styles */
 | 
			
		||||
 | 
			
		||||
sq_view {
 | 
			
		||||
    font-family: cantarell, sans-serif;
 | 
			
		||||
    font-size: 1.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button {
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    margin: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_view.wide sq_button {
 | 
			
		||||
    margin: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.latched,
 | 
			
		||||
sq_button.locked {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.action {
 | 
			
		||||
    font-size: 0.75em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.small {
 | 
			
		||||
    font-size: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_view.pin sq_button {
 | 
			
		||||
    border-radius: 0px;
 | 
			
		||||
    margin: 1px 1px 1px 1px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,84 +0,0 @@
 | 
			
		||||
# Armenian layout created by Norayr Chilingarian
 | 
			
		||||
# Yerevan
 | 
			
		||||
# Oct 2021
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 35.33, height: 52 }
 | 
			
		||||
    altline: { width: 52.67, height: 52 }
 | 
			
		||||
    wide: { width: 32, height: 32 }
 | 
			
		||||
    spaceline: { width: 142, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "՝ է թ փ ձ ջ ւ և ռ չ ճ ֊ ժ"
 | 
			
		||||
        - "ք ո ե ր տ ը ւ ի օ պ խ ծ շ"
 | 
			
		||||
        - "ա ս դ ֆ գ հ յ կ լ ․"
 | 
			
		||||
        - "Shift_L զ ղ ց վ բ ն մ ՛ BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        period Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "՝ Է Թ Փ Ձ Ջ Ւ և Ռ Չ Ճ — Ժ"
 | 
			
		||||
        - "Ք Ո Ե Ր Տ Ը Ւ Ի Օ Պ Խ Ծ Շ"
 | 
			
		||||
        - "Ա Ս Դ Ֆ Գ Հ Յ Կ Լ ։"
 | 
			
		||||
        - "Shift_L Զ Ղ Ց Վ Բ Ն Մ ՞ BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        period Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "ﬓ  ﬔ  ﬕ  ﬖ  ﬗ   ՟ և"
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "show_letters preferences         space        period Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "show_numbers_from_symbols   \\ % < > = [ ]  BackSpace"
 | 
			
		||||
        - "* # $ / & - _ + ( )"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° @ { }"
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "show_letters preferences         space        period Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "ԱԲԳ"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    period:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "."
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
@ -1,84 +0,0 @@
 | 
			
		||||
# Armenian layout created by Norayr Chilingarian
 | 
			
		||||
# Yerevan
 | 
			
		||||
# Oct 2021
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 35.33, height: 52 }
 | 
			
		||||
    altline: { width: 52.67, height: 52 }
 | 
			
		||||
    wide: { width: 32, height: 32 }
 | 
			
		||||
    spaceline: { width: 142, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "՝ ֆ ձ ֊ , ։ ՞ ․ ՛ ) օ է ղ"
 | 
			
		||||
        - "ճ փ բ ս մ ո ւ կ ը թ ծ ց »"
 | 
			
		||||
        - "ջ վ գ ե ա ն ի տ հ պ ր"
 | 
			
		||||
        - "Shift_L ժ դ չ յ զ լ ք խ շ ռ BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        period Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "՜ Ֆ Ձ — $ … ՟ և ՚ ( Օ Է Ղ"
 | 
			
		||||
        - "Ճ Փ Բ Ս Մ Ո Ւ Կ Ը Թ Ծ Ց «"
 | 
			
		||||
        - "Ջ Վ Գ Ե Ա Ն Ի Տ Հ Պ Պ Ր"
 | 
			
		||||
        - "Shift_L Ժ Դ Չ Յ Զ Լ Ք Խ Շ Ռ BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        period Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "ﬓ  ﬔ  ﬕ  ﬖ  ﬗ   ՟ և"
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "show_letters preferences         space        period Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "show_numbers_from_symbols   \\ % < > = [ ]  BackSpace"
 | 
			
		||||
        - "* # $ / & - _ + ( )"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° @ { }"
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "show_letters preferences         space        period Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "ԱԲԳ"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    period:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "."
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
@ -1,70 +0,0 @@
 | 
			
		||||
# Maintained by: Khaled Eldoheiri <khalid@kdehairy.com>
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 32.66, height: 52 }
 | 
			
		||||
    altline: { width: 48.99, height: 52 }
 | 
			
		||||
    wide: { width: 62, height: 52 }
 | 
			
		||||
    spaceline: { width: 195.96, height: 52 }
 | 
			
		||||
    special: { width: 35.66, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "ذ ض ص ث ق ف غ ع خ ح ج"
 | 
			
		||||
        - "ش س ي ب ل ا ت ن م ك ط"
 | 
			
		||||
        - "Shift_L ء ؤ ر ة و ز ظ د BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        . Return"
 | 
			
		||||
    extra:
 | 
			
		||||
        - "ذ ض ص ث ق لإ إ ع خ ح ج"
 | 
			
		||||
        - "ش س ى ب لأ أ ت ن م ك ط"
 | 
			
		||||
        - "Shift_L ئ لآ لا ه آ ز ظ د BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        . Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   ، \" ' : ؛ ! ؟  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        . Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "extra"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "ض"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
@ -1,70 +0,0 @@
 | 
			
		||||
# Maintained by: Khaled Eldoheiri <khalid@kdehairy.com>
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 49, height: 42 }
 | 
			
		||||
    altline: { width: 73.5, height: 42 }
 | 
			
		||||
    wide: { width: 108, height: 42 }
 | 
			
		||||
    spaceline: { width: 324, height: 42 }
 | 
			
		||||
    special: { width: 49, height: 42 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "ذ ض ص ث ق ف غ ع خ ح ج"
 | 
			
		||||
        - "ش س ي ب ل ا ت ن م ك ط"
 | 
			
		||||
        - "Shift_L ء ؤ ر ة و ز ظ د BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        . Return"
 | 
			
		||||
    extra:
 | 
			
		||||
        - "ذ ض ص ث ق لإ إ ع خ ح ج"
 | 
			
		||||
        - "ش س ى ب لأ أ ت ن م ك ط"
 | 
			
		||||
        - "Shift_L ئ لآ لا ه آ ز ظ د BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        . Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   ، \" ' : ؛ ! ؟  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        . Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "extra"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "ض"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
@ -1,78 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 32.72, height: 52 }
 | 
			
		||||
    altline: { width: 47, height: 52 }
 | 
			
		||||
    wide: { width: 49.09, height: 52 }
 | 
			
		||||
    spaceline: { width: 185, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "я в е р т ъ у и о п ю"
 | 
			
		||||
        - "а с д ф г х й к л ш щ"
 | 
			
		||||
        - "Shift_L з ь ц ж б н м ч BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space   .    Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Я В Е Р Т Ъ У И О П Ю"
 | 
			
		||||
        - "А С Д Ф Г Х Й К Л Ш Щ"
 | 
			
		||||
        - "Shift_L З Ь Ц Ж Б Н М Ч BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space   ,    Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ $ ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers_from_symbols   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        Return"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -8,19 +8,19 @@ outlines:
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "у е и ш щ к с д з ц б"
 | 
			
		||||
        - "ь я а о ж г т н в м ч"
 | 
			
		||||
        - "Shift_L ю й ъ ф х п р л BackSpace"
 | 
			
		||||
        - "я в е р т ъ у и о п ю"
 | 
			
		||||
        - "а с д ф г х й к л ш щ"
 | 
			
		||||
        - "Shift_L з ь ц ж б н м ч BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space   .    Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "У Е И Ш Щ К С Д З Ц Б"
 | 
			
		||||
        - "Ь Я А О Ж Г Т Н В М Ч"
 | 
			
		||||
        - "Shift_L Ю Й Ъ Ф Х П Р Л BackSpace"
 | 
			
		||||
        - "Я В Е Р Т Ъ У И О П Ю"
 | 
			
		||||
        - "А С Д Ф Г Х Й К Л Ш Щ"
 | 
			
		||||
        - "Shift_L З Ь Ц Ж Б Н М Ч BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space   ,    Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols , \" ' colon ; ! ? ѝ BackSpace"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
 | 
			
		||||
@ -1,73 +0,0 @@
 | 
			
		||||
# Maintained by Patrick Jörg <patrickjoerg@gmx.ch>. No Copyright, enjoy!
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default:   { width: 35.33, height: 52 }
 | 
			
		||||
    altline:   { width: 48,    height: 52 }
 | 
			
		||||
    wide:      { width: 59,    height: 52 }
 | 
			
		||||
    spaceline: { width: 70,    height: 52 }
 | 
			
		||||
    special:   { width: 28,    height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t z u i o p ü"
 | 
			
		||||
        - "a s d f g h j k l ö ä"
 | 
			
		||||
        - "Shift_L   y x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers ? !  preferences    '   space        , . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Z U I O P Ü"
 | 
			
		||||
        - "A S D F G H J K L Ö Ä"
 | 
			
		||||
        - "Shift_L   Y X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers - _  preferences    \"  space        , . Return"
 | 
			
		||||
    numbers:      
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ * + - = ( ) ~ < >"
 | 
			
		||||
        - "show_symbols  # & / \\ √ ; : BackSpace"
 | 
			
		||||
        - "show_letters ? !  preferences    _   space        , . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "€ $ £ ¥ % | § µ [ ]"
 | 
			
		||||
        - "© ® § ` ^ { } · ¡ ¿"
 | 
			
		||||
        - "show_numbers  « » ÷ × “ ” „ BackSpace"
 | 
			
		||||
        - "show_letters  preferences    -   space        , . Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,91 +0,0 @@
 | 
			
		||||
# Maintained by: Jordi Bossy <jordi@bossy.space>. No Copyright, enjoy!
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default:   { width: 35.33, height: 52 }
 | 
			
		||||
    altline:   { width: 48,    height: 52 }
 | 
			
		||||
    wide:      { width: 59,    height: 52 }
 | 
			
		||||
    spaceline: { width: 70,    height: 52 }
 | 
			
		||||
    special:   { width: 28,    height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t z u i o p"
 | 
			
		||||
        - "a s d f g h j k l ?"
 | 
			
		||||
        - "Shift_L   y x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    '   space        , . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Z U I O P"
 | 
			
		||||
        - "A S D F G H J K L !"
 | 
			
		||||
        - "Shift_L   Y X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    \"  space        , . Return"
 | 
			
		||||
    numbers:      
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ * + - = ( ) ~ < >"
 | 
			
		||||
        - "show_symbols  # & / \\ √ ; : BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    _   space        , . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "€ $ £ ¥ % | § µ [ ]"
 | 
			
		||||
        - "© ® § ` ^ { } · ¡ ¿"
 | 
			
		||||
        - "show_numbers  « » ÷ × “ ” „ BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    -   space        , . Return"
 | 
			
		||||
    eschars:
 | 
			
		||||
        - "à â ç é è ê î ô ù û"
 | 
			
		||||
        - "À Â Ç É È Ê Î Ô Ù Û"
 | 
			
		||||
        - "show_numbers  æ œ ä ë ï ö ü  BackSpace"
 | 
			
		||||
        - "show_letters_from_accents preferences  ñ Ñ   space        ° ß Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    show_eschars:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "âÂ"
 | 
			
		||||
    show_letters_from_accents:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "âÂ"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,93 +0,0 @@
 | 
			
		||||
# Maintained by: Jordy Bossy <jordi@bossy.space>
 | 
			
		||||
# and Patrick Jörg <patrickjoerg@gmx.ch>. No Copyright, enjoy!
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default:   { width: 35.33, height: 52 }
 | 
			
		||||
    altline:   { width: 48,    height: 52 }
 | 
			
		||||
    wide:      { width: 59,    height: 52 }
 | 
			
		||||
    spaceline: { width: 70,    height: 52 }
 | 
			
		||||
    special:   { width: 28,    height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t z u i o p ü"
 | 
			
		||||
        - "a s d f g h j k l ö ä"
 | 
			
		||||
        - "Shift_L   y x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    '   space        , . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Z U I O P Ü"
 | 
			
		||||
        - "A S D F G H J K L Ö Ä"
 | 
			
		||||
        - "Shift_L   Y X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    \"  space        , . Return"
 | 
			
		||||
    numbers:      
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ * + - = ( ) ~ < > ? !"
 | 
			
		||||
        - "show_symbols  # & / \\ √ ; : BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    _   space        , . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "€ $ £ ¥ % | § µ [ ]"
 | 
			
		||||
        - "© ® § ` ^ { } · ¡ ¿"
 | 
			
		||||
        - "show_numbers  « » ÷ × “ ” „ BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    -   space        , . Return"
 | 
			
		||||
    eschars:
 | 
			
		||||
        - "à â ç é è ê î ô ù û"
 | 
			
		||||
        - "À Â Ç É È Ê Î Ô Ù Û"
 | 
			
		||||
        - "show_numbers  æ œ ä ë ï ö ü  BackSpace"
 | 
			
		||||
        - "show_letters_from_accents preferences  ñ Ñ   space        ° ß Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    show_eschars:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "âÂ"
 | 
			
		||||
    show_letters_from_accents:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "âÂ"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,93 +0,0 @@
 | 
			
		||||
# Maintained by: Jordy Bossy <jordy@bossy.space>
 | 
			
		||||
# and Patrick Jörg <patrickjoerg@gmx.ch>. No Copyright, enjoy!
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 48, height: 42 }
 | 
			
		||||
    altline: { width: 81, height: 42 }
 | 
			
		||||
    wide: { width: 108, height: 42 }
 | 
			
		||||
    spaceline: { width: 216, height: 42 }
 | 
			
		||||
    special: { width: 48, height: 42 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t z u i o p ü"
 | 
			
		||||
        - "a s d f g h j k l ö ä"
 | 
			
		||||
        - "Shift_L   y x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    '   space        , . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Z U I O P Ü"
 | 
			
		||||
        - "A S D F G H J K L Ö Ä"
 | 
			
		||||
        - "Shift_L   Y X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences    \"  space        , . Return"
 | 
			
		||||
    numbers:      
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ * + - = ( ) ~ < > ? !"
 | 
			
		||||
        - "show_symbols  # & / \\ √ ; : BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    _   space        , . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "€ $ £ ¥ % | § µ [ ]"
 | 
			
		||||
        - "© ® § ` ^ { } · ¡ ¿"
 | 
			
		||||
        - "show_numbers  « » ÷ × “ ” „ BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences    -   space        , . Return"
 | 
			
		||||
    eschars:
 | 
			
		||||
        - "à â ç é è ê î ô ù û"
 | 
			
		||||
        - "À Â Ç É È Ê Î Ô Ù Û"
 | 
			
		||||
        - "show_numbers  æ œ ä ë ï ö ü  BackSpace"
 | 
			
		||||
        - "show_letters_from_accents preferences  ñ Ñ   space        ° ß Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    show_eschars:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "äÄ"
 | 
			
		||||
    show_letters_from_accents:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "âÂ"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        label: " "
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,81 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 35.33, height: 52 }
 | 
			
		||||
    altline: { width: 52.67, height: 52 }
 | 
			
		||||
    wide: { width: 62, height: 52 }
 | 
			
		||||
    spaceline: { width: 106.67, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t y u i o p"
 | 
			
		||||
        - "a s d f g h j k l"
 | 
			
		||||
        - "Shift_L   z x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        at period Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Y U I O P"
 | 
			
		||||
        - "A S D F G H J K L"
 | 
			
		||||
        - "Shift_L   Z X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        at period Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # $ % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        at period Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers_from_symbols   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        at period Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    at:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "@"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: show_prefs
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "ABC"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    period:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "."
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
margins: { top: 4, side: 0, bottom: 4 }
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 120, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "1 2 3"
 | 
			
		||||
        - "4 5 6"
 | 
			
		||||
        - "7 8 9"
 | 
			
		||||
        - "BackSpace 0 Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    Return:
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
 | 
			
		||||
@ -1,89 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 35.33, height: 52 }
 | 
			
		||||
    altline: { width: 52.67, height: 52 }
 | 
			
		||||
    wide: { width: 62, height: 52 }
 | 
			
		||||
    spaceline: { width: 99.67, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t y u i o p"
 | 
			
		||||
        - "a s d f g h j k l"
 | 
			
		||||
        - "Shift_L   z x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences         space        . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Y U I O P"
 | 
			
		||||
        - "A S D F G H J K L"
 | 
			
		||||
        - "Shift_L   Z X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences         space        , Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ $ ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers_from_symbols   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        , Return"
 | 
			
		||||
    eschars:
 | 
			
		||||
        - "ă â î ș ț á é í ó ü"
 | 
			
		||||
        - "Ă Â Î Ș Ț Á É Í Ó Ü"
 | 
			
		||||
        - "show_numbers_from_symbols „ ” « » ― { } BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        . Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    show_eschars:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "ăĂ"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,89 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 54, height: 42 }
 | 
			
		||||
    altline: { width: 81, height: 42 }
 | 
			
		||||
    wide: { width: 108, height: 42 }
 | 
			
		||||
    spaceline: { width: 153, height: 42 }
 | 
			
		||||
    special: { width: 54, height: 42 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t y u i o p"
 | 
			
		||||
        - "a s d f g h j k l"
 | 
			
		||||
        - "Shift_L   z x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences         space        . Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Y U I O P"
 | 
			
		||||
        - "A S D F G H J K L"
 | 
			
		||||
        - "Shift_L   Z X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers show_eschars preferences         space        , Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # € % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        . Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ $ ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers_from_symbols   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        , Return"
 | 
			
		||||
    eschars:
 | 
			
		||||
        - "ă â î ș ț á é í ó ü"
 | 
			
		||||
        - "Ă Â Î Ș Ț Á É Í Ó Ü"
 | 
			
		||||
        - "show_numbers_from_symbols „ ” « » ― { } BackSpace"
 | 
			
		||||
        - "show_letters show_eschars preferences         space        . Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: "erase"
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: "show_prefs"
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "abc"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    show_eschars:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "eschars"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "ăĂ"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
    "\"":
 | 
			
		||||
        keysym: "quotedbl"
 | 
			
		||||
@ -1,81 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
outlines:
 | 
			
		||||
    default: { width: 35.33, height: 52 }
 | 
			
		||||
    altline: { width: 52.67, height: 52 }
 | 
			
		||||
    wide: { width: 62, height: 52 }
 | 
			
		||||
    spaceline: { width: 106.67, height: 52 }
 | 
			
		||||
    special: { width: 44, height: 52 }
 | 
			
		||||
 | 
			
		||||
views:
 | 
			
		||||
    base:
 | 
			
		||||
        - "q w e r t y u i o p"
 | 
			
		||||
        - "a s d f g h j k l"
 | 
			
		||||
        - "Shift_L   z x c v b n m  BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        slash period Return"
 | 
			
		||||
    upper:
 | 
			
		||||
        - "Q W E R T Y U I O P"
 | 
			
		||||
        - "A S D F G H J K L"
 | 
			
		||||
        - "Shift_L   Z X C V B N M  BackSpace"
 | 
			
		||||
        - "show_numbers preferences         space        slash period Return"
 | 
			
		||||
    numbers:
 | 
			
		||||
        - "1 2 3 4 5 6 7 8 9 0"
 | 
			
		||||
        - "@ # $ % & - _ + ( )"
 | 
			
		||||
        - "show_symbols   , \" ' colon ; ! ?  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        slash period Return"
 | 
			
		||||
    symbols:
 | 
			
		||||
        - "~ ` | · √ π τ ÷ × ¶"
 | 
			
		||||
        - "© ® £ € ¥ ^ ° * { }"
 | 
			
		||||
        - "show_numbers_from_symbols   \\ / < > = [ ]  BackSpace"
 | 
			
		||||
        - "show_letters preferences         space        slash period Return"
 | 
			
		||||
 | 
			
		||||
buttons:
 | 
			
		||||
    Shift_L:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
                lock_view: "upper"
 | 
			
		||||
                unlock_view: "base"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "key-shift"
 | 
			
		||||
    BackSpace:
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        icon: "edit-clear-symbolic"
 | 
			
		||||
        action: erase
 | 
			
		||||
    preferences:
 | 
			
		||||
        action: show_prefs
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        icon: "keyboard-mode-symbolic"
 | 
			
		||||
    show_numbers:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_numbers_from_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "numbers"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "123"
 | 
			
		||||
    show_letters:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "base"
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        label: "ABC"
 | 
			
		||||
    show_symbols:
 | 
			
		||||
        action:
 | 
			
		||||
            set_view: "symbols"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "*/="
 | 
			
		||||
    period:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "."
 | 
			
		||||
    slash:
 | 
			
		||||
        outline: "special"
 | 
			
		||||
        text: "/"
 | 
			
		||||
    space:
 | 
			
		||||
        outline: "spaceline"
 | 
			
		||||
        text: " "
 | 
			
		||||
    Return:
 | 
			
		||||
        outline: "wide"
 | 
			
		||||
        icon: "key-enter"
 | 
			
		||||
        keysym: "Return"
 | 
			
		||||
    colon:
 | 
			
		||||
        text: ":"
 | 
			
		||||
							
								
								
									
										13
									
								
								data/langs/bg-BG.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								data/langs/bg-BG.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
bg Български
 | 
			
		||||
de Немски
 | 
			
		||||
es Испански
 | 
			
		||||
emoji Емоджи
 | 
			
		||||
fi Френски
 | 
			
		||||
gr Гръцки
 | 
			
		||||
it Италянски
 | 
			
		||||
no Норевежки
 | 
			
		||||
pl Полски
 | 
			
		||||
ru Руски
 | 
			
		||||
se Шведски
 | 
			
		||||
terminal Терминал
 | 
			
		||||
us Английски (САЩ)
 | 
			
		||||
							
								
								
									
										21
									
								
								data/langs/cs-CZ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								data/langs/cs-CZ.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
be Belgická
 | 
			
		||||
cz Česká
 | 
			
		||||
cz+qwerty Česká (QWERTY)
 | 
			
		||||
de Německá
 | 
			
		||||
dk Dánská
 | 
			
		||||
emoji Emoji
 | 
			
		||||
es Španělská
 | 
			
		||||
fi Finská
 | 
			
		||||
fr Francouzská
 | 
			
		||||
gr Řecká
 | 
			
		||||
it Italská
 | 
			
		||||
jp Japonská
 | 
			
		||||
jp+kana Japonská (Kana)
 | 
			
		||||
no Norská
 | 
			
		||||
pl Polská
 | 
			
		||||
ru Ruská
 | 
			
		||||
se Švédská
 | 
			
		||||
terminal Terminál
 | 
			
		||||
th Thajská
 | 
			
		||||
ua Ukrajinská
 | 
			
		||||
us Anglická (USA)
 | 
			
		||||
							
								
								
									
										0
									
								
								data/langs/de-DE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								data/langs/de-DE.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								data/langs/en-US.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								data/langs/en-US.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
emoji Emoji
 | 
			
		||||
terminal Terminal
 | 
			
		||||
							
								
								
									
										7
									
								
								data/langs/es-ES.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								data/langs/es-ES.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
us Inglés (EE.UU.)
 | 
			
		||||
de Alemán
 | 
			
		||||
el Griego
 | 
			
		||||
es Español
 | 
			
		||||
it Italiano
 | 
			
		||||
jp+kana Japonés (Kana)
 | 
			
		||||
no Noruego
 | 
			
		||||
							
								
								
									
										2
									
								
								data/langs/fa-IR.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								data/langs/fa-IR.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
emoji ایموجی
 | 
			
		||||
terminal ترمینال
 | 
			
		||||
							
								
								
									
										18
									
								
								data/langs/fur-IT.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								data/langs/fur-IT.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
be Belgjic
 | 
			
		||||
br Brasilian
 | 
			
		||||
de Todesc
 | 
			
		||||
dk Danês
 | 
			
		||||
es Spagnûl
 | 
			
		||||
fi Finlandês
 | 
			
		||||
fr Francês
 | 
			
		||||
it+fur Furlan
 | 
			
		||||
gr Grêc
 | 
			
		||||
it Talian
 | 
			
		||||
jp+kana Gjaponês (Kana)
 | 
			
		||||
no Norvegjês
 | 
			
		||||
pl Polac
 | 
			
		||||
ru Rus
 | 
			
		||||
se Svedês
 | 
			
		||||
terminal Terminâl
 | 
			
		||||
ua Ucrain
 | 
			
		||||
us American (USA)
 | 
			
		||||
							
								
								
									
										19
									
								
								data/langs/he-IL.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								data/langs/he-IL.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
be בלגית
 | 
			
		||||
br פורטוגזית (ברזיל)
 | 
			
		||||
cz צ'כית
 | 
			
		||||
de גרמנית
 | 
			
		||||
dk דנית
 | 
			
		||||
es ספרדית
 | 
			
		||||
emoji אימוג'י
 | 
			
		||||
fi פינית
 | 
			
		||||
fr צרפתית
 | 
			
		||||
gr יוונית
 | 
			
		||||
il עברית
 | 
			
		||||
it איטלקית
 | 
			
		||||
no נורווגית
 | 
			
		||||
pl פולנית
 | 
			
		||||
ru רוסית
 | 
			
		||||
se שוודית
 | 
			
		||||
terminal טרמינל
 | 
			
		||||
ua אוקראינית
 | 
			
		||||
us אנגלית (ארה"ב)
 | 
			
		||||
							
								
								
									
										0
									
								
								data/langs/ja-JP.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								data/langs/ja-JP.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								data/langs/pl-PL.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								data/langs/pl-PL.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
emoji emoji
 | 
			
		||||
terminal terminal
 | 
			
		||||
							
								
								
									
										11
									
								
								data/langs/ru-RU.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								data/langs/ru-RU.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
de Немецкий
 | 
			
		||||
es Испанский
 | 
			
		||||
fi Финский
 | 
			
		||||
gr Греческий
 | 
			
		||||
it Итальянский
 | 
			
		||||
no Норвежский
 | 
			
		||||
pl Польский
 | 
			
		||||
ru Русский
 | 
			
		||||
se Шведский
 | 
			
		||||
terminal Терминал
 | 
			
		||||
us Английский (США)
 | 
			
		||||
@ -12,7 +12,7 @@ desktopconf.set('bindir', bindir)
 | 
			
		||||
 | 
			
		||||
desktop_file = 'sm.puri.Squeekboard.desktop'
 | 
			
		||||
 | 
			
		||||
i18n.merge_file(
 | 
			
		||||
i18n.merge_file('desktop',
 | 
			
		||||
    input: configure_file(
 | 
			
		||||
      input: desktop_file + '.in.in',
 | 
			
		||||
      output: desktop_file + '.in',
 | 
			
		||||
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<interface>
 | 
			
		||||
  <menu id="app-menu">
 | 
			
		||||
    <item>
 | 
			
		||||
      <!-- translators: This is a emmoji keyboard layout -->
 | 
			
		||||
      <attribute name="label" translatable="yes">Emoji</attribute>
 | 
			
		||||
      <attribute name="action">layout</attribute>
 | 
			
		||||
      <attribute name="target">emoji</attribute>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
      <!-- translators: This is a terminal keyboard layout -->
 | 
			
		||||
      <attribute name="label" translatable="yes">Terminal</attribute>
 | 
			
		||||
      <attribute name="action">layout</attribute>
 | 
			
		||||
      <attribute name="target">terminal</attribute>
 | 
			
		||||
    </item>
 | 
			
		||||
    <section>
 | 
			
		||||
      <item>
 | 
			
		||||
        <attribute name="label" translatable="yes">Keyboard Settings</attribute>
 | 
			
		||||
        <attribute name="action">settings</attribute>
 | 
			
		||||
      </item>
 | 
			
		||||
    </section>
 | 
			
		||||
  </menu>
 | 
			
		||||
</interface>
 | 
			
		||||
							
								
								
									
										19
									
								
								data/popup.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								data/popup.ui
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- Generated with glade 3.22.1 -->
 | 
			
		||||
<interface>
 | 
			
		||||
  <requires lib="gtk+" version="3.16"/>
 | 
			
		||||
  <object class="GtkPopoverMenu" id="main_menu">
 | 
			
		||||
    <property name="can_focus">False</property>
 | 
			
		||||
    <child>
 | 
			
		||||
      <object class="GtkBox" id="box">
 | 
			
		||||
        <property name="visible">True</property>
 | 
			
		||||
        <property name="can_focus">False</property>
 | 
			
		||||
        <property name="orientation">vertical</property>
 | 
			
		||||
      </object>
 | 
			
		||||
      <packing>
 | 
			
		||||
        <property name="submenu">main</property>
 | 
			
		||||
        <property name="position">1</property>
 | 
			
		||||
      </packing>
 | 
			
		||||
    </child>
 | 
			
		||||
  </object>
 | 
			
		||||
</interface>
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Name=Squeekboard
 | 
			
		||||
GenericName=On Screen Keyboard
 | 
			
		||||
Comment=An on screen virtual keyboard
 | 
			
		||||
GenericName=Squeekboard Virtual Keyboard
 | 
			
		||||
Comment=Virtual Keyboard
 | 
			
		||||
Exec=@bindir@/squeekboard
 | 
			
		||||
Terminal=false
 | 
			
		||||
Type=Application
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,9 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<gresources>
 | 
			
		||||
  <gresource prefix="/sm/puri/squeekboard">
 | 
			
		||||
   <file compressed="true">common.css</file>
 | 
			
		||||
   <file compressed="true">style.css</file>
 | 
			
		||||
   <file compressed="true">style-Adwaita:dark.css</file>
 | 
			
		||||
   <file compressed="true" preprocess="xml-stripblanks">popover.ui</file>
 | 
			
		||||
   <file compressed="true" preprocess="xml-stripblanks">popup.ui</file>
 | 
			
		||||
   <file>icons/key-enter.svg</file>
 | 
			
		||||
   <file>icons/key-shift.svg</file>
 | 
			
		||||
   <file>icons/keyboard-mode-symbolic.svg</file>
 | 
			
		||||
 | 
			
		||||
@ -1,22 +1,34 @@
 | 
			
		||||
/* Adwaita-dark style keyboard */
 | 
			
		||||
sq_view {
 | 
			
		||||
    background-color: rgba(0, 0, 0, 255);
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
    font-family: cantarell, sans-serif;
 | 
			
		||||
    font-size: 25px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_view sq_button {
 | 
			
		||||
    color: #deddda;
 | 
			
		||||
    background: #464448;
 | 
			
		||||
    border-style: solid;
 | 
			
		||||
    border-width: 1px;
 | 
			
		||||
    border-color: #5e5c64;
 | 
			
		||||
    border-radius: 3px;
 | 
			
		||||
    margin: 4px 2px 4px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_view.wide sq_button {
 | 
			
		||||
    margin: 1px 1px 1px 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button:active {
 | 
			
		||||
    background: #747077;
 | 
			
		||||
    border-color: #96949d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.altline,
 | 
			
		||||
sq_button.special,
 | 
			
		||||
sq_button.wide {
 | 
			
		||||
    background: #2b292f;
 | 
			
		||||
    border-color: #3e3a44;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.latched {
 | 
			
		||||
@ -29,12 +41,20 @@ sq_button.locked {
 | 
			
		||||
    color: #1c71d8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.action {
 | 
			
		||||
    font-size: 0.75em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.small {
 | 
			
		||||
    font-size: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Return {
 | 
			
		||||
    background: #1c71d8;
 | 
			
		||||
    border-color: #1a5fb4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Return:active {
 | 
			
		||||
    background: #1c71d8;
 | 
			
		||||
    border-color: #3584e4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@import url("resource:///sm/puri/squeekboard/common.css");
 | 
			
		||||
 | 
			
		||||
@ -1,47 +1,63 @@
 | 
			
		||||
/* Keyboard style */
 | 
			
		||||
sq_view {
 | 
			
		||||
    background-color: mix(@theme_base_color, @theme_fg_color, 0.1);
 | 
			
		||||
    box-shadow:inset 0 1px 0 0 mix(@borders, @theme_base_color, 0.8);
 | 
			
		||||
    background-color: @theme_base_color; /*rgba(0, 0, 0, 255);*/
 | 
			
		||||
    color: @theme_text_color; /*#ffffff;*/
 | 
			
		||||
    font-family: cantarell, sans-serif;
 | 
			
		||||
    font-size: 25px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button {
 | 
			
		||||
    color: @theme_fg_color;
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.07); 
 | 
			
		||||
    box-shadow: 0 1px 0 0 rgba(0,0,0,0.2); 
 | 
			
		||||
sq_view sq_button {
 | 
			
		||||
    color: @theme_fg_color; /*#deddda;*/
 | 
			
		||||
    background: mix(@theme_bg_color, @theme_base_color, -0.5); /* #464448; */
 | 
			
		||||
    border-style: solid;
 | 
			
		||||
    border-width: 1px;
 | 
			
		||||
    border-color: @borders; /* #5e5c64;*/
 | 
			
		||||
    border-radius: 3px;
 | 
			
		||||
    margin: 4px 2px 4px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button:active {
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.11);
 | 
			
		||||
sq_view.wide sq_button {
 | 
			
		||||
    margin: 1px 1px 1px 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button:active,
 | 
			
		||||
sq_button.altline:active,
 | 
			
		||||
sq_button.special:active,
 | 
			
		||||
sq_button.wide:active {
 | 
			
		||||
    background: mix(@theme_bg_color, @theme_selected_bg_color, 0.4);/* #747077; */
 | 
			
		||||
    border-color: mix(@borders, @theme_selected_fg_color, 0.5);/* #96949d; */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.altline,
 | 
			
		||||
sq_button.special {
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.15); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.altline:active,
 | 
			
		||||
sq_button.special:active {
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.2);
 | 
			
		||||
sq_button.special,
 | 
			
		||||
sq_button.wide {
 | 
			
		||||
    background: mix(@theme_bg_color, @theme_base_color, 0.5); /*#2b292f;*/
 | 
			
		||||
    border-color: @borders; /* #3e3a44; */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.latched {
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.2); 
 | 
			
		||||
    color: alpha(@theme_fg_color, 0.8);
 | 
			
		||||
    background: @theme_fg_color; /*#ffffff;*/
 | 
			
		||||
    color: @theme_bg_color; /*#2b292f;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.locked {
 | 
			
		||||
    background: alpha(@theme_fg_color, 0.5);
 | 
			
		||||
    color: @theme_base_color;
 | 
			
		||||
    background: @theme_fg_color; /*#ffffff;*/
 | 
			
		||||
    color: mix(@theme_selected_bg_color, @theme_bg_color, 0.4); /*#2b292f;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.action {
 | 
			
		||||
    font-size: 0.75em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sq_button.small {
 | 
			
		||||
    font-size: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Return {
 | 
			
		||||
    background: @theme_selected_bg_color;
 | 
			
		||||
    color: @theme_selected_fg_color;
 | 
			
		||||
    background: @theme_selected_bg_color; /* #1c71d8; */
 | 
			
		||||
    border-color: @borders; /*#1a5fb4;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Return:active {
 | 
			
		||||
    background: mix(@theme_selected_bg_color, black, 0.2);
 | 
			
		||||
    color: mix(@theme_selected_fg_color, black, 0.2);
 | 
			
		||||
    background: mix(@theme_selected_bg_color, @theme_bg_color, 0.4); /*#1c71d8;*/
 | 
			
		||||
    border-color: @borders; /*#3584e4;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@import url("resource:///sm/puri/squeekboard/common.css");
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/cargo/config
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/cargo/config
									
									
									
									
										vendored
									
									
								
							@ -9,3 +9,4 @@ replace-with = 'vendored-sources'
 | 
			
		||||
 | 
			
		||||
[source.vendored-sources]
 | 
			
		||||
directory = '/usr/share/cargo/registry'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										846
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										846
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@ -1,830 +1,94 @@
 | 
			
		||||
squeekboard (1.17.1-1) experimental; urgency=medium
 | 
			
		||||
squeekboard (1.14.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * build: Replace missing crates.io dependency with Purism-hosted one
 | 
			
		||||
  * ci: Allow failure on sid
 | 
			
		||||
  * panel: Use scaling to set height
 | 
			
		||||
  * debian: New upstream release
 | 
			
		||||
 | 
			
		||||
  [ William Wold ]
 | 
			
		||||
  * Do not reset pending state on zwp_input_method_v2.done
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 22 May 2021 14:19:27 +0000
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * state: fix "wide mode" detection in portrait orientation
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 05 Apr 2022 13:32:53 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.17.0-1) experimental; urgency=medium
 | 
			
		||||
squeekboard (1.13.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * docs: Detail the release process better
 | 
			
		||||
  * cleanup: Remove unused header lines
 | 
			
		||||
  * docstrings: Clarify the purpose of Receiver
 | 
			
		||||
  * wayland: Move initialization to the Rust side
 | 
			
		||||
  * ffi: Remove unnecessary pointers to InputMethod
 | 
			
		||||
  * outputs: Clean up for more Rust usage
 | 
			
		||||
  * outputs: Notify the state manager about changes
 | 
			
		||||
  * outputs: Handle removal
 | 
			
		||||
  * Save outputs state
 | 
			
		||||
  * Store preferred output
 | 
			
		||||
  * deps: Vendor assert_matches
 | 
			
		||||
  * Carry output information on visible command all the way to C
 | 
			
		||||
  * Don't reach for globals to choose output
 | 
			
		||||
  * visibility: Forward panel height information to window creation
 | 
			
		||||
  * outputs: Remove ui manager
 | 
			
		||||
  * output: Use new source of panel height information
 | 
			
		||||
  * panel: Apply a hard limit of 1/2 height
 | 
			
		||||
  * cargo: Update lockfile
 | 
			
		||||
  * debian: New upstream release
 | 
			
		||||
 | 
			
		||||
  [ Cosmin Humeniuc ]
 | 
			
		||||
  * Add Romanian layout
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 12 Apr 2021 10:50:32 +0000a
 | 
			
		||||
 | 
			
		||||
  [ Sam Hewitt ]
 | 
			
		||||
  * data: Update stylesheet with upstream design
 | 
			
		||||
 | 
			
		||||
  [ Tor ]
 | 
			
		||||
  * Make compatible with latest cargo deps
 | 
			
		||||
 | 
			
		||||
  [ Luís Fernando Stürmer da Rosa ]
 | 
			
		||||
  * Update Brazilian Portuguese translation
 | 
			
		||||
 | 
			
		||||
  [ Fran Dieguez ]
 | 
			
		||||
  * Add Galician translation
 | 
			
		||||
 | 
			
		||||
  [ William Wold ]
 | 
			
		||||
  * Check if dbus handler is null before using
 | 
			
		||||
 | 
			
		||||
  [ Yosef Or Boczko ]
 | 
			
		||||
  * Add Hebrew translation
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 25 Jan 2022 11:24:04 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.16.0-1) experimental; urgency=medium
 | 
			
		||||
squeekboard (1.12.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * build: Remove regex crate
 | 
			
		||||
  * ci: Use bookworm image
 | 
			
		||||
  * build: Pin transitive dependencies
 | 
			
		||||
  * cargo: Update Cargo.lock with pinned dependencies
 | 
			
		||||
  * CI: Use byzantium as the base
 | 
			
		||||
  * cargo: Bump dependencies
 | 
			
		||||
  * debian: New Byzantium release
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * po: Fix ui file name
 | 
			
		||||
  * entry: Mark as executable
 | 
			
		||||
  * entry: Only activate purpose timer when focused
 | 
			
		||||
  * entry: Add another input hint
 | 
			
		||||
  * Add entry test using GTK4
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Thu, 28 Jan 2021 14:36:20 +0000
 | 
			
		||||
 | 
			
		||||
  [ Rafael Fontenelle ]
 | 
			
		||||
  * Add Brazilian Portuguese translation
 | 
			
		||||
 | 
			
		||||
  [ Yuri Chornoivan ]
 | 
			
		||||
  * Add Ukrainian translation
 | 
			
		||||
 | 
			
		||||
  [ Luna Jernberg ]
 | 
			
		||||
  * Add Swedish Translation
 | 
			
		||||
  * Update sv.po
 | 
			
		||||
  * Update LINGUAS
 | 
			
		||||
 | 
			
		||||
  [ Fabio Tomat ]
 | 
			
		||||
  * Add Friulian translation
 | 
			
		||||
 | 
			
		||||
  [ Daniel Șerbănescu ]
 | 
			
		||||
  * Add Romanian translation
 | 
			
		||||
 | 
			
		||||
  [ Matej Urbančič ]
 | 
			
		||||
  * Add Slovenian translation
 | 
			
		||||
 | 
			
		||||
  [ Nathan Follens ]
 | 
			
		||||
  * Add Dutch translation
 | 
			
		||||
 | 
			
		||||
  [ Jiri Grönroos ]
 | 
			
		||||
  * Add Finnish translation
 | 
			
		||||
 | 
			
		||||
  [ Danial Behzadi ]
 | 
			
		||||
  * Add Persian translation
 | 
			
		||||
 | 
			
		||||
  [ Jordi Mas i Hernandez ]
 | 
			
		||||
  * Add Catalan translation
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 25 Jan 2022 11:24:04 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.15.0-1) experimental; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Khaled Eldoheiri ]
 | 
			
		||||
  * Introduce Arabic keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * Docs: Release procedure
 | 
			
		||||
  * build: Fix "any" dependency versioning
 | 
			
		||||
  * readme: Mention the layout guide
 | 
			
		||||
  * dbus: Hint that maybe squeekboard is running
 | 
			
		||||
  * readme: Change self-reference to repo to gnome
 | 
			
		||||
  * docs: Move env vars section to debugging
 | 
			
		||||
  * readme: Clarify basic running steps
 | 
			
		||||
  * readme: Put emphasis on being an input method
 | 
			
		||||
  * readme: Update features
 | 
			
		||||
  * ci: Use cached artifacts in the test
 | 
			
		||||
  * ci: Move release test to the start
 | 
			
		||||
  * ci: Start lintian test right after deb build
 | 
			
		||||
  * ci: Add git revision and CI pipeline number to .deb artifacts
 | 
			
		||||
  * ci: Use bookworm image
 | 
			
		||||
  * ci: Reformat yaml file
 | 
			
		||||
  * ci: Include pre-build style check
 | 
			
		||||
  * popover: Fix reentrancy problem
 | 
			
		||||
  * submission: Wrap the structure in a safe wrapper
 | 
			
		||||
  * util: Add ArcWrapped
 | 
			
		||||
  * animation: Prototype a way of handling state and applying it separately
 | 
			
		||||
  * state: Connect the animation state machine to the rest
 | 
			
		||||
  * event_loop: Separate and use for physical keyboard presence
 | 
			
		||||
  * Revert "util: Add ArcWrapped"
 | 
			
		||||
  * Revert "ci: Use bookworm image"
 | 
			
		||||
  * ci: Fix formatting
 | 
			
		||||
  * ci: Make indentation close to original again
 | 
			
		||||
  * cargo: version bump
 | 
			
		||||
 | 
			
		||||
  [ Jordi ]
 | 
			
		||||
  * Introduce Swiss French keyboard layout
 | 
			
		||||
  * improve accents layout behavior and code cleaning
 | 
			
		||||
 | 
			
		||||
  [ Plamen Stoev ]
 | 
			
		||||
  * Rename bg to bg+phonetic
 | 
			
		||||
  * Add 'bg' layout
 | 
			
		||||
  * Translate more layout names in Bulgarian
 | 
			
		||||
 | 
			
		||||
  [ William Wold ]
 | 
			
		||||
  * Show error when Layer Shell is not supported
 | 
			
		||||
  * Update entry.py file path in readme
 | 
			
		||||
  * Update zwp_text_input_v3 (comment changes only)
 | 
			
		||||
  * Update zwp_input_method_v2
 | 
			
		||||
 | 
			
		||||
  [ Patrick Jörg ]
 | 
			
		||||
  * Introduce Swiss German keyboard layout
 | 
			
		||||
  * Introducing ch+de layout and modified ch.yaml fallback
 | 
			
		||||
  * Added ch_wide
 | 
			
		||||
 | 
			
		||||
  [ ZenWalker ]
 | 
			
		||||
  * layersurface: avoid duplicate assignment
 | 
			
		||||
 | 
			
		||||
  [ T. Zack Crawford ]
 | 
			
		||||
  * Update tutorial.md to clarify steps in creating a custom layout
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * gitlab-ci: Adjust CI tags
 | 
			
		||||
  * gitlab-ci: Drop build for outdated distributions
 | 
			
		||||
  * data: Fix build with meson 0.60.0
 | 
			
		||||
  * main: Remove trailing whitespace
 | 
			
		||||
  * main: Honor --help and -h
 | 
			
		||||
  * eek-renderer: Add log domain
 | 
			
		||||
  * eek-renderer: Fix indentation
 | 
			
		||||
  * eek-renderer: Honor theme changes (Closes: #296)
 | 
			
		||||
  * main: Drop broken support G_BUS_TYPE_SYSTEM
 | 
			
		||||
  * main: Avoid two error variables in the same function
 | 
			
		||||
  * main: Use dark theme when run in a Phosh session (Closes: #242)
 | 
			
		||||
  * gtk-keyboard: Don't set variable to NULL twice in a row
 | 
			
		||||
  * renderer: Use `g_debug ()`
 | 
			
		||||
  * main: Add debug flag to always show squeekboard on start
 | 
			
		||||
  * renderer: Disconnect theme change signal handler
 | 
			
		||||
  * main: Add debug flag to show GTK inspector
 | 
			
		||||
  * README: Document SQUEEKBOARD_DEBUG environment variable
 | 
			
		||||
  * Move style-check to separate script
 | 
			
		||||
  * Honor input-purpose PIN
 | 
			
		||||
  * entry: Use a scrolled window
 | 
			
		||||
  * entry: Set a margin on the grids
 | 
			
		||||
  * entry: Add a random text entry field
 | 
			
		||||
  * imservice: Invoke eekboard_context_service_set_hint_purpose unconditionally
 | 
			
		||||
    (Closes: #311)
 | 
			
		||||
  * langs: Don't use empty translation file (Closes: #313)
 | 
			
		||||
  * Initialize gettext
 | 
			
		||||
  * Reuse the unused popover ui file for i18n (Closes: #315)
 | 
			
		||||
  * po: Add German translation
 | 
			
		||||
  * gresources: Drop popup.ui
 | 
			
		||||
  * Revert "gresources: Drop popup.ui"
 | 
			
		||||
  * gitlab-ci: Add PKG_ONLY
 | 
			
		||||
  * layout: Drop trailing whitespace
 | 
			
		||||
  * Use special pin keyboard
 | 
			
		||||
  * layout: Keep content purpose around
 | 
			
		||||
  * renderer: Set style class based on input purpose
 | 
			
		||||
  * pin: Use less margin
 | 
			
		||||
  * debian: Install translations
 | 
			
		||||
  * debian: Switch to dh 13
 | 
			
		||||
  * debian: Install desktop file
 | 
			
		||||
  * eekboard-context-service: Don't translate property names
 | 
			
		||||
  * server-context-servide: Don't translate application name
 | 
			
		||||
  * data: Make generic name truly generic
 | 
			
		||||
  * po: Add desktop file to translatable files
 | 
			
		||||
  * Add URL and EMail keyboard variants for us (Closes: #65)
 | 
			
		||||
  * gitignore: Drop zanata dir
 | 
			
		||||
  * gitignore: Ignore generated po files
 | 
			
		||||
  * popover: Move Emoji and Terminal to ui file
 | 
			
		||||
  * popover: Add translator notes
 | 
			
		||||
  * popover: Make the ui file match the code file name
 | 
			
		||||
  * Remove emoji and terminal from translations
 | 
			
		||||
  * popover: Don't complain about missing translations
 | 
			
		||||
  * Drop custom translation handling
 | 
			
		||||
  * Drop locale_config
 | 
			
		||||
  * Remove custom translations
 | 
			
		||||
 | 
			
		||||
  [ PhilProg ]
 | 
			
		||||
  * Add documentation about compositors
 | 
			
		||||
 | 
			
		||||
  [ Norayr Chilingarian ]
 | 
			
		||||
  * armenian typewriter and phonetic keyboards.
 | 
			
		||||
  * armenian layout also added to meson.build etc.
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * resources: add wide FR terminal keyboard
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * renderer: Take context scale into account when drawing icons (Closes: #139)
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sun, 19 Dec 2021 14:11:06 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.14.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * data: Split into loading and parsing
 | 
			
		||||
  * layout: Remove unused code
 | 
			
		||||
  * build: Fix unnecessary shell quotes
 | 
			
		||||
  * popover: Allow spanning outside panel area
 | 
			
		||||
  * cargo: Update dependencies before release
 | 
			
		||||
 | 
			
		||||
  [ undef ]
 | 
			
		||||
  * Fix typos jp keyboard comments
 | 
			
		||||
 | 
			
		||||
  [ anteater ]
 | 
			
		||||
  * use the correct GtkStyleProviderPriority to indicate that the styles are provided by the application
 | 
			
		||||
  * remove some unnecessary unsafe code
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 15 May 2021 12:45:20 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.13.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * layout: Latch keys when clicked twice
 | 
			
		||||
  * layout: Add stateless view switching
 | 
			
		||||
  * layout: Plug in stateless view switching
 | 
			
		||||
  * layout: Remove the little abomination of view change promise
 | 
			
		||||
  * view: Ąto-unlatching when multiple latching buttons pressed
 | 
			
		||||
  * renderer: Bring button drawing closer to Rust
 | 
			
		||||
  * ffi: Eliminate squeek_button and squeek_row
 | 
			
		||||
  * imservice: Increment serials on receiving done, not sending commit
 | 
			
		||||
  * input-method: Fix commit/done mixup in protocol text
 | 
			
		||||
  * CI: fix xheck_tag to be compatible with Amber
 | 
			
		||||
  * italian: Fix colon
 | 
			
		||||
  * popover: Fix prematurely deallocated CString
 | 
			
		||||
  * Rust: Remove unnecessary no_mangle statements to silence warnings
 | 
			
		||||
  * renderer: Reduce reliance on knowing the transform
 | 
			
		||||
  * renderer: Split mutable geometry and place it directly in GtkKeyboard
 | 
			
		||||
  * Revert "moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations."
 | 
			
		||||
  * layout: Make it possible to opt out of latching per-key
 | 
			
		||||
  * renderer: Mark latched buttons differently than locked
 | 
			
		||||
  * appearance: Colour latched/locked according to design
 | 
			
		||||
  * docs: Describe view switching
 | 
			
		||||
  * language-terminal: Place keyboards in a sub-path
 | 
			
		||||
  * layout selection: Fix emoji and number
 | 
			
		||||
  * rust: Fix compiler warnings
 | 
			
		||||
  * layout: Take into account text purpose again
 | 
			
		||||
  * layouts: Make selection testable
 | 
			
		||||
  * layouts: Stop assuming that layout name always changes on switch
 | 
			
		||||
  * Cargo: Version bump
 | 
			
		||||
 | 
			
		||||
  [ J.D. Laub ]
 | 
			
		||||
  * Add US Dvorak layout (and Colemak wide)
 | 
			
		||||
  *     Add US Dvorak layout (and Colemak wide)
 | 
			
		||||
 | 
			
		||||
  [ Jordi Masip ]
 | 
			
		||||
  * Catalan keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Myth ]
 | 
			
		||||
  * Added hebrew keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ David96 ]
 | 
			
		||||
  * Add Mod4 (Windows) key
 | 
			
		||||
 | 
			
		||||
  [ Panawat Wong-klaew ]
 | 
			
		||||
  * Add wide Thai keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * server-main: Add quit()
 | 
			
		||||
  * server-main: Properly register to gnome-session (Closes: #274)
 | 
			
		||||
 | 
			
		||||
  [ Kozova1 ]
 | 
			
		||||
  * Added Hebrew translations for most layouts.
 | 
			
		||||
  * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations.
 | 
			
		||||
  * Fixed Hebrew layout.
 | 
			
		||||
  * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations.
 | 
			
		||||
 | 
			
		||||
  [ M33 ]
 | 
			
		||||
  * Revert "Update tests/meson.build"
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 12 Apr 2021 10:40:32 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.12.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * docs: Correct Cargo update instructions
 | 
			
		||||
  * visibility: Centralize keyboard panel visibility policy and handling
 | 
			
		||||
  * build: Fix release
 | 
			
		||||
  * tests: Prefer the env var for finding test layouts
 | 
			
		||||
  * tests: Explicitly pass source directory to tests
 | 
			
		||||
  * debian: Build reproducibly
 | 
			
		||||
  * tests: Allow legacy mode to have much longer tests.
 | 
			
		||||
  * build: Enable unused warnings in C
 | 
			
		||||
  * build: Enable wformat to remove warnings about missing wformat
 | 
			
		||||
  * build: Fail on any C warnings when strict
 | 
			
		||||
  * data: Made data flow in fallback clearer
 | 
			
		||||
  * data: Flattened layout fallback function
 | 
			
		||||
  * layouts: Use base as fallback for alternative layouts
 | 
			
		||||
  * layouts: Simplify the main flow of source list
 | 
			
		||||
  * tests: Add some description to the list of tested layouts
 | 
			
		||||
  * layout_names: Unmess the list of builtin layouts
 | 
			
		||||
  * dbus: Reset hints if text input missing
 | 
			
		||||
  * visibility: Stop calling GTK functions from the visibility manager
 | 
			
		||||
 | 
			
		||||
  [ Wannaphong Phatthiyaphaibun ]
 | 
			
		||||
  * Add thai keyboard
 | 
			
		||||
  * Update resources.rs
 | 
			
		||||
  * Update meson.build
 | 
			
		||||
  * escape " on thai keyboard
 | 
			
		||||
 | 
			
		||||
  [ clonex10100 ]
 | 
			
		||||
  * Added US Colemak Keyboard Layout
 | 
			
		||||
squeekboard (1.12.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Henry-Nicolas Tourneur ]
 | 
			
		||||
  * d/rules: fix an FTBFS on mips64el with GOT > 64kb
 | 
			
		||||
  * d/rules: export RUSTFLAGS only on architecture that needs it
 | 
			
		||||
  * d/rules: export RUSTFLAGS only on architecture that needs it
 | 
			
		||||
 | 
			
		||||
  [ Jiří Stránský ]
 | 
			
		||||
  * Add Czech keyboard layouts
 | 
			
		||||
 | 
			
		||||
  [ Stefan Grotz ]
 | 
			
		||||
  * Esperanto keyboard
 | 
			
		||||
 | 
			
		||||
  [ Vladimir ]
 | 
			
		||||
  * Bulgarian language keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Vladimir Stoilov ]
 | 
			
		||||
  * bulgarian add translation and to needed lists
 | 
			
		||||
  * Fix bulgarian layout size
 | 
			
		||||
 | 
			
		||||
  [ Andreas Rönnquist ]
 | 
			
		||||
  * no: Use wide button switching between numbers, symbols and base
 | 
			
		||||
 | 
			
		||||
  [ jranaraki ]
 | 
			
		||||
  * Farsi/Persian keyboard layout
 | 
			
		||||
  * Farsi/Persian keyboard layout
 | 
			
		||||
  * Added requirements to resources.rs and meson.build
 | 
			
		||||
  * Updated the layout to provide more convenient and faster typing experience
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sun, 10 Jan 2021 09:43:42 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.11.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * keyboard: Fix semicolon in German layout
 | 
			
		||||
  * keyboard: Move semicolon in German layout to numbers view replacing redundant comma key
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * imservice: Set up UI according to current needs when it shows up
 | 
			
		||||
  * UI: Keep visibility factors in a central place
 | 
			
		||||
  * cargo: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 21 Nov 2020 11:08:06 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.11.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * UI: Delay hiding only when leaving a text field
 | 
			
		||||
  * ui: Cancel hiding delay when activity requested again
 | 
			
		||||
  * Update dependencies
 | 
			
		||||
 | 
			
		||||
  [ Fabio Tomat ]
 | 
			
		||||
  * Update fur-IT.txt fix typo for Spanish
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 14 Nov 2020 06:46:28 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.10.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * virtual_keyboard: Fix desynced modifiers state
 | 
			
		||||
  * rust: Fix deprecation warnings
 | 
			
		||||
  * docs: Tutorial syntax cleanups
 | 
			
		||||
  * docs: Reorganize tutorial
 | 
			
		||||
  * build: Error on repeating declarations
 | 
			
		||||
  * keymap: Generate from symbol map, not layout
 | 
			
		||||
  * data: Restore testability of action->keysym conversion
 | 
			
		||||
  * syntax: Let older rustc understand symbolmap's lifetime
 | 
			
		||||
  * debian: Insert a "breaks" for librem5-base < 24
 | 
			
		||||
  * keymap: Keep keymap fd management in one place
 | 
			
		||||
  * vkeyboard: Use a generic slice instead of a vector
 | 
			
		||||
  * tests: Check for missing return in builtin layouts except emoji
 | 
			
		||||
  * keymap: Concentrate special handling of BackSpace, which is implicit in Erase action
 | 
			
		||||
  * keymaps: Use multiple key maps, each within the limit of what Xorg can accept.
 | 
			
		||||
  * build: Avoid MaybeUninit on older Debian
 | 
			
		||||
  * tests: Fix bad field access
 | 
			
		||||
  * cargo: Update dependencies
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * eekboard-context-service: Return early if schema is unavailable
 | 
			
		||||
  * treewide: Use new style function definitions
 | 
			
		||||
  * build: Enable '-Wold-style-definition' '-Wstrict-prototypes'
 | 
			
		||||
  * build: Enable '-Wunused-function'
 | 
			
		||||
  * eekboard-context-service: Drop EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE
 | 
			
		||||
  * keyboard: Fix warning
 | 
			
		||||
  * layout: Fix warning
 | 
			
		||||
  * gitlab-ci: Enable --Werror
 | 
			
		||||
  * eek-keyboard: Don't ignore return value
 | 
			
		||||
  * build: Enable -Winit-self
 | 
			
		||||
  * build: Enable -Wformat-security
 | 
			
		||||
  * build: Enable -Wmaybe-uninitialized
 | 
			
		||||
  * treewide: Drop redundant declarations
 | 
			
		||||
  * build: Enable -Wredundant-declarations
 | 
			
		||||
  * ServerContextService: Drop GObject boilerplate
 | 
			
		||||
  * build: Enable '-Wformat-nonliteral'
 | 
			
		||||
  * eekboad-context-service: Drop signal class handler
 | 
			
		||||
  * eekboard-context-service: Drop docstrings for inexistent functions
 | 
			
		||||
  * eekboard-context-service: Drop the GObject boilerplate
 | 
			
		||||
  * eekboard-context-service: Drop private struct
 | 
			
		||||
  * server-context-service: Consistenty name self argument 'self'
 | 
			
		||||
  * server-context-service: swap signal arguments
 | 
			
		||||
  * server-context-service: Don't show keyboard when disabled (Closes: #222)
 | 
			
		||||
 | 
			
		||||
  [ Nazarii Kretovych ]
 | 
			
		||||
  * Add Ukrainian keyboard layout.
 | 
			
		||||
 | 
			
		||||
  [ Benjamin Schaaf ]
 | 
			
		||||
  * Fix spelling mistakes in doc/hacking.md
 | 
			
		||||
  * Expand the development documentation in the readme
 | 
			
		||||
  * Expand key press detection to the edges of the view's bounding box
 | 
			
		||||
  * Sort layouts by type before sorting by name
 | 
			
		||||
  * Fix leak in level_keyboard_new
 | 
			
		||||
  * Fix leak endlessly adding a resource path to the default theme
 | 
			
		||||
  * Add settings option to popover
 | 
			
		||||
 | 
			
		||||
  [ Al ]
 | 
			
		||||
  * proposal for belgian layout (copy of fr)
 | 
			
		||||
  * alphabetical order for src/resources.rs tests/meson.build
 | 
			
		||||
  * debian: Build reproducibly
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * eek-gtk-keyboard: use virtual resolution to check arrangement kind
 | 
			
		||||
  * server-context-service: optimize height calculation
 | 
			
		||||
  * keyboards: add wide French layout
 | 
			
		||||
  * keyboards: add wide Belgian layout
 | 
			
		||||
  * keyboards: add wide terminal layout
 | 
			
		||||
  * New upstream version 1.12.0
 | 
			
		||||
 | 
			
		||||
  [ Fabio Tomat ]
 | 
			
		||||
  * Revert "Add friulian keyboard"
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 26 Jan 2021 18:19:42 +0100
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 19 Oct 2020 14:07:01 +0000
 | 
			
		||||
squeekboard (1.11.1-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.3) amber-phone; urgency=medium
 | 
			
		||||
  * New upstream version 1.11.1
 | 
			
		||||
 | 
			
		||||
  [ Björn Tantau ]
 | 
			
		||||
  * Show more useful keys at the same time.
 | 
			
		||||
  * Add Ctrl and Alt modifier keys.
 | 
			
		||||
  * Add missing Ê key.
 | 
			
		||||
  * Make f-keys slightly wider.
 | 
			
		||||
  * Add Menu key.
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 24 Nov 2020 11:52:41 +0100
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * d/rules: Only remove Cargo.lock if it exists
 | 
			
		||||
  * eek: Drop libcanberra usage
 | 
			
		||||
  * debian: Build-depend on libfeedback
 | 
			
		||||
  * eek-gtk-keyboard: Trigger event feedback on button press (Closes: #166)
 | 
			
		||||
squeekboard (1.11.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * build: Add missing gio-unix dependency
 | 
			
		||||
  * build: Make compatible with Debian Bullseye
 | 
			
		||||
  * debian: Add amber to legacy distro list
 | 
			
		||||
  * ci: Add amber job
 | 
			
		||||
  * debian: Require lsb-release
 | 
			
		||||
  * size: Hardcode size to work around screen rotation
 | 
			
		||||
  * ci: Re-add x64 Buster build
 | 
			
		||||
  * italian: Fix space and period
 | 
			
		||||
  * New upstream release 1.11.0
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * Revert "Merge branch 'btantau-master-patch-76686' into 'master'"
 | 
			
		||||
  * Terminal layout: another approach
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Mon, 16 Nov 2020 11:17:23 +0100
 | 
			
		||||
 | 
			
		||||
  [ Luís Fernando Stürmer da Rosa ]
 | 
			
		||||
  * Brazilian Portuguese Keyboard Layout.
 | 
			
		||||
squeekboard (1.10.0-2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
 -- Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>  Wed, 05 Aug 2020 16:16:08 +0200
 | 
			
		||||
  * Team upload.
 | 
			
		||||
  * d/rules: set RUSTFLAGS to avoid an FTBFS on mips64el (Closes: #974036)
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.2) amber-phone; urgency=medium
 | 
			
		||||
 -- Henry-Nicolas Tourneur <debian@nilux.be>  Tue, 10 Nov 2020 18:40:50 +0000
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * keyboard: Remove unused code
 | 
			
		||||
  * gsettings: Don't crash when unavailable
 | 
			
		||||
  * dbus: Don't crash if can't make a connection
 | 
			
		||||
  * gsettings: Don't crash on switching when unavailable
 | 
			
		||||
  * layout: Split out choice to a struct on its own
 | 
			
		||||
  * renderer: Simplify by dropping gobjectness
 | 
			
		||||
  * levelkeyboard: Rearrange to make future conversion easier
 | 
			
		||||
  * layout: Minor generalizations
 | 
			
		||||
  * Remove unused code
 | 
			
		||||
  * sizing: Create a standalone UI shape manager
 | 
			
		||||
  * sizing: Ignore scaling factor for layout selection
 | 
			
		||||
  * CI: Fix typo
 | 
			
		||||
  * Update rust deps for release
 | 
			
		||||
squeekboard (1.10.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Andreas Rönnquist ]
 | 
			
		||||
  * Swedish keyboard, wide button switching between numbers, symbols and base
 | 
			
		||||
  * More fixes of button sizes
 | 
			
		||||
  * Folder is doc, not docs
 | 
			
		||||
  * New upstream release 1.10.0
 | 
			
		||||
  * d/control: build-depend on libfeedbackd-dev and set team maintainership
 | 
			
		||||
  * d/control: fix dependency name
 | 
			
		||||
  * d/copyright: add missing entries
 | 
			
		||||
  * d/copyright: add entries for new keyboard files and remove duplicate
 | 
			
		||||
    `src/meson.build` appeared in 2 different paragraphs, remove the
 | 
			
		||||
    duplicate entry.
 | 
			
		||||
  * d/gbp.conf: fix debian version number
 | 
			
		||||
 | 
			
		||||
  [ uzanto ]
 | 
			
		||||
  * Add new file
 | 
			
		||||
  * Replace duplicated show_symbols by show_eschars and removed "Delete" button that it's doing nothing
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Fri, 23 Oct 2020 13:18:43 +0200
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * keyboards: fr: fix keyboard layout
 | 
			
		||||
  * keyboards: fr: make sure the layout fits the screen
 | 
			
		||||
  * resources: include French keyboard layout
 | 
			
		||||
  * keyboards: fr: improve consistency with other layouts
 | 
			
		||||
  * keyboards: fr: improve diacritics layout
 | 
			
		||||
  * tests: add french layout
 | 
			
		||||
squeekboard (1.9.3-1) experimental; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vlad ]
 | 
			
		||||
  * Fresh Russian layout
 | 
			
		||||
  * Upload to experimental
 | 
			
		||||
  * Update upstream source from tag 'v1.9.3'
 | 
			
		||||
    Update to upstream version '1.9.3'
 | 
			
		||||
    with Debian dir 7a3f8b82779759ba288b75755ba54500250b0ff4
 | 
			
		||||
  * d/control: Use librust-xkbcommon-dev
 | 
			
		||||
    This one avoids the empty feature package.
 | 
			
		||||
  * Ship sm.puri.OSK0.desktop.
 | 
			
		||||
    This is needed to fulfill phosh's session dependencies
 | 
			
		||||
  * Conflict with phosh-osk-stub.
 | 
			
		||||
    They're not useful at the same time and we'll drop phosh-osk-stub from
 | 
			
		||||
    Debian once squeekboard is in.
 | 
			
		||||
  * Drop pathes no longer required due to upstream changes
 | 
			
		||||
    - 0001-Cargo.toml-update-to-Debian-dependencies-versions.patch
 | 
			
		||||
    - 0002-popover.rs-fix-build-with-gtk-rs-0.7.0.patch
 | 
			
		||||
  * d/gbp.conf: Don't use patch numbers.
 | 
			
		||||
    Ordering is defined via the series file and patch numbers just
 | 
			
		||||
    cause manual work.
 | 
			
		||||
 | 
			
		||||
  [ Jordi Masip ]
 | 
			
		||||
  * Removed unused dependency 'libcroco'
 | 
			
		||||
 -- Guido Günther <agx@sigxcpu.org>  Sat, 26 Sep 2020 13:01:18 +0200
 | 
			
		||||
 | 
			
		||||
  [ Florian Klink ]
 | 
			
		||||
  * sm.puri.Squeekboard.desktop: make path to Exec= absolute
 | 
			
		||||
squeekboard (1.9.2-1) UNRELEASED; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Ole Guldberg ]
 | 
			
		||||
  * Danish keyboard layout
 | 
			
		||||
  * Danish keyboard layout
 | 
			
		||||
  * add test for danish layout
 | 
			
		||||
  * Initial Debian release (Closes: #956960)
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 01 Jun 2020 09:39:12 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * layout: Improve press handling
 | 
			
		||||
  * settings: Handle empty settings
 | 
			
		||||
  * Variant: Use proper pointer conversion between C and Rust
 | 
			
		||||
  * meta: Add doap file
 | 
			
		||||
  * modifiers: Support Control and Alt
 | 
			
		||||
  * CI: Test that any bump to changelog has a corresponding tag
 | 
			
		||||
  * docs: Add the guiding principle
 | 
			
		||||
  * hacking: Move into docs/
 | 
			
		||||
 | 
			
		||||
  [ &t ]
 | 
			
		||||
  * Fix minor comment typos
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * cargo: Bump package versions before release
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sun, 08 Mar 2020 10:04:29 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * imservice: Add commit_string method
 | 
			
		||||
  * submission: Handle submitting strings
 | 
			
		||||
  * input_method: Use for erasing
 | 
			
		||||
  * logging: Use in merged functions
 | 
			
		||||
  * translations: Remove redundant ones
 | 
			
		||||
  * translations: Translate builtin layouts
 | 
			
		||||
  * greek: Rename to gr which is used by gnome settings
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layouts: Add Polish layouts
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * locks: Draw based on current view
 | 
			
		||||
  * locking: Lock keys statelessly
 | 
			
		||||
  * layouts: Better accented uppercase in PL
 | 
			
		||||
  * emoji: Add more choices
 | 
			
		||||
  * row: Eliminate angle
 | 
			
		||||
  * layout: Center views relative to each other and the layout bounds
 | 
			
		||||
  * drawing: Generalized foreach_visible_button
 | 
			
		||||
  * variant: Fix double-free
 | 
			
		||||
  * variant: Fix leak
 | 
			
		||||
  * keyboard_layout: Fix leak
 | 
			
		||||
  * layout: Improve scoping of locked variable
 | 
			
		||||
  * terminal: Make */ easier to reach
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layouts: terminal: Use altline outline for dot key
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * text input: Disable erasing
 | 
			
		||||
  * cargo: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 19 Feb 2020 14:32:39 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.8.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * action: Rename Level to View
 | 
			
		||||
  * keyboard: Introduce a KeyCode type wrapping u32
 | 
			
		||||
  * layout: Centralize handling key releases
 | 
			
		||||
  * layout: Make handling presses uniform
 | 
			
		||||
  * UI: Drop indirection for show/hide functions
 | 
			
		||||
  * managers: Move visible flag to UI manager
 | 
			
		||||
  * dbus_service: Remove unused function
 | 
			
		||||
  * dbus: Remove unneeded gobjectness
 | 
			
		||||
  * dbus: Rename handler from eekboard_service
 | 
			
		||||
  * context: Moved keymap setting together with its generation
 | 
			
		||||
  * key-emitter: Remove unused
 | 
			
		||||
  * eekboard_context_service: Drop unused enable property
 | 
			
		||||
  * services: Split out layout management from EekboardContextService
 | 
			
		||||
  * submission: Move away from virtual-keyboard
 | 
			
		||||
  * submission: Create a new wrapper over imservice
 | 
			
		||||
  * imservice: Limited scope of unsafe
 | 
			
		||||
  * EekGtkKeyboard: Use a direct reference to EekboardContext
 | 
			
		||||
  * submission: Take over virtual_keyboard handling
 | 
			
		||||
  * keyboard: Cleanups of unused code
 | 
			
		||||
  * levelkeyboard: Drop unused manager references
 | 
			
		||||
  * keyboard: Gather up keymap handling, drop layout
 | 
			
		||||
  * submission: Remove wildcard reexport
 | 
			
		||||
  * imservice: Rename commit_state to done to match protocol
 | 
			
		||||
  * ci: Clean up `..` before it's searched for artifacts
 | 
			
		||||
  * dbus: Log error on dbus exit
 | 
			
		||||
  * logging: Try to improve common operations
 | 
			
		||||
  * imservice: Return something more resembling an Error on failure
 | 
			
		||||
  * logging: Unified to remove random eprint calls
 | 
			
		||||
  * press_key: Use proper logging
 | 
			
		||||
  * number: Fix keysym for Return
 | 
			
		||||
  * build: Strip clap of optional features
 | 
			
		||||
  * layouts: Fix segfault on switching to wide
 | 
			
		||||
  * font: Use font from style context
 | 
			
		||||
  * font: Only pass relevant data to label renderer
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layout: terminal: Swap positions of preferences and actions button
 | 
			
		||||
  * layout: terminal: Show actions button on all views
 | 
			
		||||
  * layout: terminal: Replace actions button with period on symbols view
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * setup: Connect ui to the state manager
 | 
			
		||||
  * debian: Add missing commas
 | 
			
		||||
 | 
			
		||||
  [ David Boddie ]
 | 
			
		||||
  * Tidy build file and docs
 | 
			
		||||
  * Use pip to install recommonmark
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Fri, 31 Jan 2020 09:59:12 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.8.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * translations: Use gnome-desktop's xkb info database for layout names
 | 
			
		||||
  * translations: Make the code cleaner
 | 
			
		||||
  * overlay: Add terminal
 | 
			
		||||
  * eek-layout: Remove unused
 | 
			
		||||
  * pre-release: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 14 Jan 2020 13:55:00 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.7.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * New terminal layout appearing on terminal input hint
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 08 Jan 2020 11:53:07 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.7.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * New terminal layout appearing on terminal input hint
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 08 Jan 2020 11:53:07 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.6.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * tools: Move entry.py
 | 
			
		||||
  * build: Move building of squeekboard-test-layout to tools
 | 
			
		||||
  * packaging: Install entty.py as squeekboard-entry
 | 
			
		||||
  * Remove unused build dependencies
 | 
			
		||||
  * Remove unused header generator
 | 
			
		||||
  * logging: Move all facilities to one file
 | 
			
		||||
  * logging: Described the design
 | 
			
		||||
  * logging: Add described log levels
 | 
			
		||||
  * popover: Install emoji layout
 | 
			
		||||
  * popover: Show overlays as selected
 | 
			
		||||
  * Fix old Rust woes
 | 
			
		||||
  * emoji: Add a passable layout
 | 
			
		||||
  * Fix g_ and stdlib allocation/free mismatches
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Thu, 02 Jan 2020 12:02:50 +0000
 | 
			
		||||
 
 | 
			
		||||
squeekboard (1.5.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * keycodes: Sort to eliminate runtime indeterminism
 | 
			
		||||
  * switcher: Switch layout on menu item click
 | 
			
		||||
  * Drop squeek_key
 | 
			
		||||
  * renderer: Remove some unneeded vars
 | 
			
		||||
  * renderer: Simplified outline rendering
 | 
			
		||||
  * renderer: Drop row from button rendering
 | 
			
		||||
  * renderer: Drop unused params
 | 
			
		||||
  * renderer: Simplify surface rendering
 | 
			
		||||
  * rendering: Simplify Cairo context usage, remove unneeded calls.
 | 
			
		||||
  * rendering: Remove unneeded redraw after button release
 | 
			
		||||
  * renderer: Remove unused locked key render function
 | 
			
		||||
  * renderer: Simply cut off when painting outside bounds
 | 
			
		||||
  * renderer: Render whole keyboard the same way as pressed buttons
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * layout: add German wide layout
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * renderer: Remove unused functions
 | 
			
		||||
  * cleanup: Remove references to squeek_view
 | 
			
		||||
  * cleanup: Unbox View and Row
 | 
			
		||||
  * cleanup: Remove unused single frame draw
 | 
			
		||||
  * positioning: Calculate sizes instead of storing, move position out of widgets
 | 
			
		||||
  * positioning: Clean up unused code
 | 
			
		||||
  * Fix old Rust woes
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * layout: add Japanese Kana wide layout
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * Entry test: Add Terminal input purpose
 | 
			
		||||
  * readme: Add note about Cargo dependencies
 | 
			
		||||
  * Create a library/UI module separation
 | 
			
		||||
  * hacking: Add DCO and licensing requirement
 | 
			
		||||
  * Fix internal .md link
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * squeekboard-test-layout: add argument parsing and some more output
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * Use clap in the lockfile
 | 
			
		||||
  * parsing: Remove bounds which weren't used anyway
 | 
			
		||||
  * layout: Respect margins
 | 
			
		||||
  * CI: Build arm64 .deb
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 23 Dec 2019 11:58:57 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.4.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * "text" property in layouts
 | 
			
		||||
  * Adjusts to user's color scheme
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 02 Dec 2019 19:37:01 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.2) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Make sure all key presses get accepted by the compositor
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 26 Nov 2019 15:36:27 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Update and fix layouts and languages
 | 
			
		||||
  * Make tests less likely to fail
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 20 Nov 2019 22:10:48 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Language selection popup
 | 
			
		||||
  * Swedish and Finnish layouts
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 16 Nov 2019 15:38:14 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.2) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Landscape mode
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 30 Oct 2019 12:38:39 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use different distribution
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 08 Oct 2019 10:56:10 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use Cargo-based dependencies
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 24 Sep 2019 10:42:15 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.1.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use new keyboard layout format
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 02 Sep 2019 10:12:02 +0000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
squeekboard (1.0.10) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use a shared DBus definition
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 02 Jul 2019 20:12:02 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.0.9) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Initial release.
 | 
			
		||||
 | 
			
		||||
 -- David Boddie <david.boddie@puri.sm>  Tue, 25 Jun 2019 19:33:00 +0200
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 09 Jun 2020 23:29:19 +0200
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
10
 | 
			
		||||
							
								
								
									
										6
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@ -4,7 +4,7 @@ Priority: optional
 | 
			
		||||
Maintainer: Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>
 | 
			
		||||
Build-Depends:
 | 
			
		||||
 cargo,
 | 
			
		||||
 debhelper-compat (= 13),
 | 
			
		||||
 debhelper (>= 10),
 | 
			
		||||
 meson (>=0.51.0),
 | 
			
		||||
 ninja-build,
 | 
			
		||||
 pkg-config,
 | 
			
		||||
@ -20,17 +20,19 @@ Build-Depends:
 | 
			
		||||
 librust-gtk+v3-22-dev (>= 0.5),
 | 
			
		||||
 librust-gtk-sys-dev,
 | 
			
		||||
 librust-maplit-1-dev (>= 1.0),
 | 
			
		||||
 librust-regex-1-dev (>= 1.1),
 | 
			
		||||
 librust-serde-derive-1-dev (>= 1.0),
 | 
			
		||||
 librust-serde-yaml-0.8-dev (>= 0.8),
 | 
			
		||||
 librust-xkbcommon-0.4+wayland-dev (>= 0.4),
 | 
			
		||||
 libwayland-dev (>= 1.16),
 | 
			
		||||
 lsb-release,
 | 
			
		||||
 python3,
 | 
			
		||||
 python3-ruamel.yaml,
 | 
			
		||||
 rustc,
 | 
			
		||||
 wayland-protocols (>= 1.14),
 | 
			
		||||
Standards-Version: 4.1.3
 | 
			
		||||
Homepage: https://source.puri.sm/Librem5/squeekboard
 | 
			
		||||
Vcs-Browser: https://source.puri.sm/pureos/squeekboard
 | 
			
		||||
Vcs-Git: https://source.puri.sm/pureos/squeekboard.git
 | 
			
		||||
 | 
			
		||||
Package: squeekboard
 | 
			
		||||
Architecture: linux-any
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										58
									
								
								debian/control-newer
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								debian/control-newer
									
									
									
									
										vendored
									
									
								
							@ -1,58 +0,0 @@
 | 
			
		||||
Source: squeekboard
 | 
			
		||||
Section: x11
 | 
			
		||||
Priority: optional
 | 
			
		||||
Maintainer: Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>
 | 
			
		||||
Build-Depends:
 | 
			
		||||
 cargo,
 | 
			
		||||
 debhelper-compat (= 13),
 | 
			
		||||
 meson (>=0.51.0),
 | 
			
		||||
 ninja-build,
 | 
			
		||||
 pkg-config,
 | 
			
		||||
 libglib2.0-dev,
 | 
			
		||||
 libgnome-desktop-3-dev,
 | 
			
		||||
 libgtk-3-dev,
 | 
			
		||||
 libfeedback-dev,
 | 
			
		||||
 librust-bitflags-dev (>= 1.0),
 | 
			
		||||
 librust-clap-dev (>= 2.32),
 | 
			
		||||
 librust-gio+v2-58-dev,
 | 
			
		||||
 librust-glib+v2-58-dev,
 | 
			
		||||
 librust-glib-sys-dev,
 | 
			
		||||
 librust-gtk+v3-22-dev (>= 0.5),
 | 
			
		||||
 librust-gtk-sys-dev,
 | 
			
		||||
 librust-maplit-1-dev (>= 1.0),
 | 
			
		||||
 librust-serde-derive-1-dev (>= 1.0),
 | 
			
		||||
 librust-serde-yaml-0.8-dev (>= 0.8),
 | 
			
		||||
 librust-xkbcommon-0.4+wayland-dev (>= 0.4),
 | 
			
		||||
 libwayland-dev (>= 1.16),
 | 
			
		||||
 lsb-release,
 | 
			
		||||
 python3,
 | 
			
		||||
 python3-ruamel.yaml,
 | 
			
		||||
 rustc,
 | 
			
		||||
 wayland-protocols (>= 1.14),
 | 
			
		||||
Standards-Version: 4.1.3
 | 
			
		||||
Homepage: https://source.puri.sm/Librem5/squeekboard
 | 
			
		||||
 | 
			
		||||
Package: squeekboard
 | 
			
		||||
Architecture: linux-any
 | 
			
		||||
Depends:
 | 
			
		||||
# for the Adwaita-dark theme
 | 
			
		||||
 gnome-themes-extra-data,
 | 
			
		||||
 ${shlibs:Depends},
 | 
			
		||||
 ${misc:Depends},
 | 
			
		||||
Breaks:
 | 
			
		||||
 librem5-base (<< 24),
 | 
			
		||||
Description: On-screen keyboard for Wayland
 | 
			
		||||
 Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.
 | 
			
		||||
 | 
			
		||||
Package: squeekboard-devel
 | 
			
		||||
Architecture: linux-any
 | 
			
		||||
Depends:
 | 
			
		||||
 python3,
 | 
			
		||||
 python3-gi,
 | 
			
		||||
 ${shlibs:Depends},
 | 
			
		||||
 ${misc:Depends},
 | 
			
		||||
Description: Resources for making Squeekboard layouts
 | 
			
		||||
 Tools for creating and testing Squeekboard layouts:
 | 
			
		||||
 .
 | 
			
		||||
  * squeekboard-entry
 | 
			
		||||
  * squeekboard-test-layout
 | 
			
		||||
							
								
								
									
										7
									
								
								debian/gbp.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								debian/gbp.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
[DEFAULT]
 | 
			
		||||
debian-branch = pureos/byzantium
 | 
			
		||||
debian-tag = pureos/%(version)s
 | 
			
		||||
debian-tag-msg = %(pkg)s %(version)s
 | 
			
		||||
 | 
			
		||||
[tag]
 | 
			
		||||
sign-tags = true
 | 
			
		||||
							
								
								
									
										29
									
								
								debian/librem5-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								debian/librem5-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
include:
 | 
			
		||||
 - 'https://source.puri.sm/Librem5/librem5-ci/raw/master/librem5-pipeline-definitions.yml'
 | 
			
		||||
 - 'https://source.puri.sm/Librem5/librem5-ci/raw/master/librem5-pipeline-byzantium-jobs.yml'
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
 - package
 | 
			
		||||
 - test-package
 | 
			
		||||
 | 
			
		||||
.tags: &tags
 | 
			
		||||
  tags:
 | 
			
		||||
    - librem5
 | 
			
		||||
 | 
			
		||||
check_release:
 | 
			
		||||
  <<: *tags
 | 
			
		||||
  stage: test-package
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
      - pureos/byzantium
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get -y install git python3
 | 
			
		||||
    - (head -n 1 ./debian/changelog && git tag) | ./debian/check_release.py
 | 
			
		||||
 | 
			
		||||
# check-tarball relies on the contents of other branches,
 | 
			
		||||
# which are irrelevant for MRs. It's similar to checking tags in this way.
 | 
			
		||||
check-tarball:
 | 
			
		||||
  extends: .l5-check-tarball
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
        - pureos/byzantium
 | 
			
		||||
							
								
								
									
										8
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@ -25,10 +25,10 @@ export RUSTFLAGS = --remap-path-prefix=$(CURDIR)=/remap-pwd $(xgot)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
distrel := $(shell lsb_release --codename --short)
 | 
			
		||||
ifneq (,$(filter $(distrel),sid))
 | 
			
		||||
	newer = true
 | 
			
		||||
ifneq (,$(filter $(distrel),buster amber))
 | 
			
		||||
	legacy = true
 | 
			
		||||
else
 | 
			
		||||
	newer = false
 | 
			
		||||
	legacy = false
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
%:
 | 
			
		||||
@ -38,6 +38,6 @@ endif
 | 
			
		||||
# causing Cargo to refuse to build with a crates.io copy
 | 
			
		||||
override_dh_auto_configure:
 | 
			
		||||
	[ ! -f Cargo.lock ] || rm Cargo.lock
 | 
			
		||||
	dh_auto_configure -- -Dnewer=$(newer) -Donline=false
 | 
			
		||||
	dh_auto_configure -- -Dlegacy=$(legacy)
 | 
			
		||||
 | 
			
		||||
override_dh_autoreconf:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
								
							@ -1 +1 @@
 | 
			
		||||
3.0 (native)
 | 
			
		||||
3.0 (quilt)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/squeekboard.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/squeekboard.install
									
									
									
									
										vendored
									
									
								
							@ -1,4 +1,2 @@
 | 
			
		||||
tools/squeekboard-restyled usr/bin
 | 
			
		||||
usr/bin/squeekboard /usr/bin
 | 
			
		||||
usr/share/applications/
 | 
			
		||||
usr/share/locale/
 | 
			
		||||
 | 
			
		||||
@ -90,15 +90,6 @@ Layouts can be selected using the GNOME Settings application.
 | 
			
		||||
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'de')]"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Environment Variables
 | 
			
		||||
 | 
			
		||||
Besides the environment variables supported by GTK and [GLib](https://docs.gtk.org/glib/running.html) applications
 | 
			
		||||
squeekboard honors the `SQUEEKBOARD_DEBUG` environment variable which can
 | 
			
		||||
contain a comma separated list of:
 | 
			
		||||
 | 
			
		||||
- `force-show` : Show squeekboard on startup independent of any gsettings or compositor requests
 | 
			
		||||
- `gtk-inspector`: Spawn [gtk-inspector](https://wiki.gnome.org/Projects/GTK/Inspector)
 | 
			
		||||
 | 
			
		||||
Coding
 | 
			
		||||
------
 | 
			
		||||
 | 
			
		||||
@ -120,16 +111,6 @@ User interface modules should:
 | 
			
		||||
 | 
			
		||||
### Style
 | 
			
		||||
 | 
			
		||||
Note that some portions, like the .gitlab-ci.yml file have accummulated enough style/whitespace conflicts that an enforced style checker is now applied.
 | 
			
		||||
 | 
			
		||||
To fix your contributions before submitting a change, use:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
./tools/style-check_source --apply
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
* * *
 | 
			
		||||
 | 
			
		||||
Code submitted should roughly match the style of surrounding code. Things that will *not* be accepted are ones that often lead to errors:
 | 
			
		||||
 | 
			
		||||
- skipping brackets `{}` after every `if()`, `else`, and similar ([SCI CERT C: EXP19-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP19-C.+Use+braces+for+the+body+of+an+if%2C+for%2C+or+while+statement))
 | 
			
		||||
@ -194,74 +175,14 @@ All Cargo dependencies must be selected in the version available in PureOS, and
 | 
			
		||||
 | 
			
		||||
Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
 | 
			
		||||
 | 
			
		||||
Releases
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
Squeekboard should get a new release every time something interesting comes in. Preferably when there are no known bugs too. People will rely on theose releases, after all.
 | 
			
		||||
 | 
			
		||||
### 1. Update `Cargo.toml`.
 | 
			
		||||
 | 
			
		||||
While the file is not actually used, it's a good idea to save the config in case some rare bug appears in dependencies.
 | 
			
		||||
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It must correspond to the default dependency configuration: without flags to use older or newer versions of dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
cd squeekboard-build
 | 
			
		||||
.../squeekboard-source/cargo.sh update
 | 
			
		||||
cd build_dir
 | 
			
		||||
ninja ./Cargo.toml
 | 
			
		||||
sh /source_path/cargo.sh update
 | 
			
		||||
ninja test
 | 
			
		||||
cp ./Cargo.lock .../squeekboard-source
 | 
			
		||||
cp ./Cargo.lock /source_path/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then commit the updated `Cargo.lock`.
 | 
			
		||||
 | 
			
		||||
### 2. Choose the version number
 | 
			
		||||
 | 
			
		||||
Squeekboard tries to use semantic versioning. It's 3 numbers separated by dots: "a.b.c". Releases which only fix bugs and nothing else are "a.b.c+1". Releases which add user-visible features in addition to bug fixes are "a.b+1.0". Releases which, in addition to the previous, change *the user contract* in incompatible ways are "a+1.0.0". "The user contract" means plugin APIs that are deemed stable, or the way language switching works, etc. In other words, incompatible changes to developers, or big changes to users bump "a" to the next natural number.
 | 
			
		||||
 | 
			
		||||
### 3. Update the number in `meson.build`
 | 
			
		||||
 | 
			
		||||
It's in the `project(version: xxx)` statement.
 | 
			
		||||
 | 
			
		||||
### 4. Update packaging
 | 
			
		||||
 | 
			
		||||
Packaging is in the `debian/` directory, and creates builds that can be quickly tested.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
cd squeekboard-source
 | 
			
		||||
gbp dch --multimaint-merge  --ignore-branch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Inspect `debian/changelog`, and make sure the first line contains the correct version number and suite. For example:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
squeekboard (1.13.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Commit the updated `debian/changelog`. The commit message should contain the release version and a description of changes.
 | 
			
		||||
 | 
			
		||||
> Release 1.13.0 "Externality"
 | 
			
		||||
>
 | 
			
		||||
> Changes:
 | 
			
		||||
>
 | 
			
		||||
> - A system for latching and locking views
 | 
			
		||||
> ...
 | 
			
		||||
 | 
			
		||||
### 5. Create a signed tag for downstreams
 | 
			
		||||
 | 
			
		||||
The tag should be the version number with "v" in front of it. The tag message should be "squeekboard" and the tag name. Push it to the upstream repository:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git tag -s -u my_address@example.com v1.13.0 -m "squeekboard v1.13.0"
 | 
			
		||||
git push v1.13.0
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 5. Create a signed tag for packaging
 | 
			
		||||
 | 
			
		||||
Similar to the above, but format it for the PureOS downstream.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git tag -s -u my_address@example.com 'pureos/1.13.0pureos0_amber0' -m 'squeekboard 1.13.0pureos0_amber0'
 | 
			
		||||
git push 'pureos/1.13.0pureos0_amber0'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 6. Rejoice
 | 
			
		||||
 | 
			
		||||
You released a new version of Squeekboard, and made it available on PureOS. Congratulations.
 | 
			
		||||
Since version 1.9.3, `Cargo.lock` is not actually used by the build system, due to `Cargo.toml` being generated at every build.
 | 
			
		||||
 | 
			
		||||
@ -21,8 +21,7 @@ Creating a layout is easy. You don't need to recompile things, just edit and tes
 | 
			
		||||
### Creating the keyboard layout
 | 
			
		||||
 | 
			
		||||
* To be written: For the time being, take a look at [Using non-latin language on Librem 5](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5)
 | 
			
		||||
* Select and enable the input source you would like to change from the Region & Language section of the device settings. Perhaps use "A user-defined custom layout" listed under Other.
 | 
			
		||||
* Find the correct name of the .yaml file associated with that input source. This can be found with the command 
 | 
			
		||||
* The correct name of the .yaml file can be found with the command 
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
gsettings get org.gnome.desktop.input-sources sources
 | 
			
		||||
@ -30,14 +29,12 @@ gsettings get org.gnome.desktop.input-sources sources
 | 
			
		||||
 | 
			
		||||
The output should be something like this: `[('xkb', 'us'), ('xkb', 'de')]`
 | 
			
		||||
So for example “de.yaml” would be the correct name for the German keyboard layout.
 | 
			
		||||
If the name of your layout is not translated correctly in the list, you can fix it by adding it and recompiling Squeekboard.
 | 
			
		||||
 | 
			
		||||
There is also associated files for that layout in landscape, terminal, number, emoji mode. They can be found at something analogous to `us_wide.yaml`, `terminal/us.yaml`, `number/us.yaml`, `emoji/us.yaml`, respectively.
 | 
			
		||||
If the name of your layout is not translated correctly in the list, you can fix it by adding it and recompiling Squeekboard.
 | 
			
		||||
 | 
			
		||||
### Testing the layout
 | 
			
		||||
 | 
			
		||||
Copy your yaml file to `~/.local/share/squeekboard/keyboards/` for testing purposes. From there it should get picked up by squeekboard automatically.
 | 
			
		||||
The yaml file will overwrite the default settings for that layout. If you want to go back to default, simply remove the file.
 | 
			
		||||
 | 
			
		||||
You can also use the `test_layout` tool from the -devel package to check it for errors:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -316,6 +316,7 @@ eek_gtk_keyboard_dispose (GObject *object)
 | 
			
		||||
    if (priv->renderer) {
 | 
			
		||||
        eek_renderer_free(priv->renderer);
 | 
			
		||||
        priv->renderer = NULL;
 | 
			
		||||
        priv->renderer = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (priv->keyboard) {
 | 
			
		||||
 | 
			
		||||
@ -18,8 +18,6 @@
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define G_LOG_DOMAIN "squeekboard-eek-renderer"
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
@ -56,13 +54,6 @@ render_outline (cairo_t     *cr,
 | 
			
		||||
        position.x, position.y, position.width, position.height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float get_scale(cairo_t *cr) {
 | 
			
		||||
    double width = 1;
 | 
			
		||||
    double height = 1;
 | 
			
		||||
    cairo_user_to_device_distance (cr, &width, &height);
 | 
			
		||||
    return width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Rust interface
 | 
			
		||||
void eek_render_button_in_context(uint32_t scale_factor,
 | 
			
		||||
                                     cairo_t     *cr,
 | 
			
		||||
@ -79,17 +70,16 @@ void eek_render_button_in_context(uint32_t scale_factor,
 | 
			
		||||
 | 
			
		||||
    /* render icon (if any) */
 | 
			
		||||
    if (icon_name) {
 | 
			
		||||
        int context_scale = ceil (get_scale (cr));
 | 
			
		||||
        cairo_surface_t *icon_surface =
 | 
			
		||||
            eek_renderer_get_icon_surface (icon_name, 16, scale_factor * context_scale);
 | 
			
		||||
            eek_renderer_get_icon_surface (icon_name, 16, scale_factor);
 | 
			
		||||
        if (icon_surface) {
 | 
			
		||||
            double width = cairo_image_surface_get_width (icon_surface);
 | 
			
		||||
            double height = cairo_image_surface_get_height (icon_surface);
 | 
			
		||||
            gint width = cairo_image_surface_get_width (icon_surface);
 | 
			
		||||
            gint height = cairo_image_surface_get_height (icon_surface);
 | 
			
		||||
 | 
			
		||||
            cairo_save (cr);
 | 
			
		||||
            cairo_translate (cr,
 | 
			
		||||
                             (bounds.width - width / (scale_factor * context_scale)) / 2,
 | 
			
		||||
                             (bounds.height - height / (scale_factor * context_scale)) / 2);
 | 
			
		||||
                             (bounds.width - (double)width / scale_factor) / 2,
 | 
			
		||||
                             (bounds.height - (double)height / scale_factor) / 2);
 | 
			
		||||
            cairo_rectangle (cr, 0, 0, width, height);
 | 
			
		||||
            cairo_clip (cr);
 | 
			
		||||
            /* Draw the shape of the icon using the foreground color */
 | 
			
		||||
@ -236,8 +226,6 @@ eek_renderer_free (EekRenderer        *self)
 | 
			
		||||
    g_object_unref(self->css_provider);
 | 
			
		||||
    g_object_unref(self->view_context);
 | 
			
		||||
    g_object_unref(self->button_context);
 | 
			
		||||
    g_clear_signal_handler (&self->theme_name_id, gtk_settings_get_default());
 | 
			
		||||
 | 
			
		||||
    // this is where renderer-specific surfaces would be released
 | 
			
		||||
 | 
			
		||||
    free(self);
 | 
			
		||||
@ -269,49 +257,12 @@ static GType button_type(void) {
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_gtk_theme_name_changed (GtkSettings *settings, gpointer foo, EekRenderer *self)
 | 
			
		||||
{
 | 
			
		||||
  g_autofree char *name = NULL;
 | 
			
		||||
 | 
			
		||||
  g_object_get (settings, "gtk-theme-name", &name, NULL);
 | 
			
		||||
  g_debug ("GTK theme: %s", name);
 | 
			
		||||
 | 
			
		||||
  gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
 | 
			
		||||
                                                GTK_STYLE_PROVIDER (self->css_provider));
 | 
			
		||||
  gtk_style_context_remove_provider (self->button_context,
 | 
			
		||||
                                     GTK_STYLE_PROVIDER(self->css_provider));
 | 
			
		||||
  gtk_style_context_remove_provider (self->view_context,
 | 
			
		||||
                                     GTK_STYLE_PROVIDER(self->css_provider));
 | 
			
		||||
 | 
			
		||||
  g_set_object (&self->css_provider, squeek_load_style());
 | 
			
		||||
 | 
			
		||||
  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
 | 
			
		||||
                                             GTK_STYLE_PROVIDER (self->css_provider),
 | 
			
		||||
                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 | 
			
		||||
  gtk_style_context_add_provider (self->button_context,
 | 
			
		||||
                                  GTK_STYLE_PROVIDER(self->css_provider),
 | 
			
		||||
                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 | 
			
		||||
  gtk_style_context_add_provider (self->view_context,
 | 
			
		||||
                                  GTK_STYLE_PROVIDER(self->css_provider),
 | 
			
		||||
                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
renderer_init (EekRenderer *self)
 | 
			
		||||
{
 | 
			
		||||
    self->pcontext = NULL;
 | 
			
		||||
    self->scale_factor = 1;
 | 
			
		||||
 | 
			
		||||
    GtkSettings *gtk_settings;
 | 
			
		||||
 | 
			
		||||
    gtk_settings = gtk_settings_get_default ();
 | 
			
		||||
 | 
			
		||||
    self->theme_name_id = g_signal_connect (gtk_settings, "notify::gtk-theme-name",
 | 
			
		||||
                                            G_CALLBACK (on_gtk_theme_name_changed), self);
 | 
			
		||||
 | 
			
		||||
    self->css_provider = squeek_load_style();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -323,7 +274,6 @@ eek_renderer_new (LevelKeyboard  *keyboard,
 | 
			
		||||
    renderer_init(renderer);
 | 
			
		||||
    renderer->pcontext = pcontext;
 | 
			
		||||
    g_object_ref (renderer->pcontext);
 | 
			
		||||
    const char *purpose_class = "normal";
 | 
			
		||||
 | 
			
		||||
    /* Create a style context for the layout */
 | 
			
		||||
    GtkWidgetPath *path = gtk_widget_path_new();
 | 
			
		||||
@ -345,55 +295,6 @@ eek_renderer_new (LevelKeyboard  *keyboard,
 | 
			
		||||
    if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
 | 
			
		||||
        gtk_widget_path_iter_add_class(path, -1, "wide");
 | 
			
		||||
    }
 | 
			
		||||
    /* Add style classes based on purpose */
 | 
			
		||||
    switch (squeek_layout_get_purpose (keyboard->layout)) {
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL:
 | 
			
		||||
        purpose_class = "normal";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA:
 | 
			
		||||
        purpose_class = "alpha";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS:
 | 
			
		||||
        purpose_class = "digits";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
 | 
			
		||||
        purpose_class = "number";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
 | 
			
		||||
        purpose_class = "phone";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL:
 | 
			
		||||
        purpose_class = "url";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL:
 | 
			
		||||
        purpose_class = "email";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME:
 | 
			
		||||
        purpose_class = "name";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD:
 | 
			
		||||
        purpose_class = "password";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN:
 | 
			
		||||
        purpose_class = "pin";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE:
 | 
			
		||||
        purpose_class = "date";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME:
 | 
			
		||||
        purpose_class = "time";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME:
 | 
			
		||||
        purpose_class = "datetime";
 | 
			
		||||
        break;
 | 
			
		||||
    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
 | 
			
		||||
        purpose_class = "terminal";
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_warning ("Unknown input purpose %d", squeek_layout_get_purpose(keyboard->layout));
 | 
			
		||||
    }
 | 
			
		||||
    gtk_widget_path_iter_add_class(path, -1, purpose_class);
 | 
			
		||||
 | 
			
		||||
    gtk_widget_path_append_type(path, button_type());
 | 
			
		||||
    renderer->button_context = gtk_style_context_new ();
 | 
			
		||||
    gtk_style_context_set_path(renderer->button_context, path);
 | 
			
		||||
 | 
			
		||||
@ -39,8 +39,6 @@ typedef struct EekRenderer
 | 
			
		||||
    GtkStyleContext *button_context; // TODO: maybe move a copy to each button
 | 
			
		||||
    /// Style class for rendering the view and button CSS.
 | 
			
		||||
    gchar *extra_style; // owned
 | 
			
		||||
    // Theme name change signal handler id
 | 
			
		||||
    gulong theme_name_id;
 | 
			
		||||
 | 
			
		||||
    // Mutable state
 | 
			
		||||
    gint scale_factor; /* the outputs scale factor */
 | 
			
		||||
 | 
			
		||||
@ -312,6 +312,7 @@ on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
 | 
			
		||||
  PhoshLayerSurfacePrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
 | 
			
		||||
  priv = phosh_layer_surface_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  priv = phosh_layer_surface_get_instance_private (self);
 | 
			
		||||
  if (priv->layer_surface) {
 | 
			
		||||
 | 
			
		||||
@ -217,7 +217,7 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
 | 
			
		||||
     * Emitted when @context is destroyed.
 | 
			
		||||
     */
 | 
			
		||||
    signals[DESTROYED] =
 | 
			
		||||
        g_signal_new ("destroyed",
 | 
			
		||||
        g_signal_new (I_("destroyed"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      0,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								meson.build
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
project(
 | 
			
		||||
    'squeekboard',
 | 
			
		||||
    'c', 'rust',
 | 
			
		||||
    version: '1.17.1',
 | 
			
		||||
    version: '1.14.0',
 | 
			
		||||
    license: 'GPLv3',
 | 
			
		||||
    meson_version: '>=0.51.0',
 | 
			
		||||
    default_options: [
 | 
			
		||||
@ -36,6 +36,8 @@ add_project_arguments(
 | 
			
		||||
 | 
			
		||||
i18n = import('i18n')
 | 
			
		||||
 | 
			
		||||
conf_data = configuration_data()
 | 
			
		||||
 | 
			
		||||
if get_option('buildtype').startswith('debug')
 | 
			
		||||
    add_project_arguments('-DDEBUG=1', language : 'c')
 | 
			
		||||
endif
 | 
			
		||||
@ -61,7 +63,6 @@ endif
 | 
			
		||||
prefix = get_option('prefix')
 | 
			
		||||
bindir = join_paths(prefix, get_option('bindir'))
 | 
			
		||||
datadir = join_paths(prefix, get_option('datadir'))
 | 
			
		||||
localedir = join_paths(prefix, get_option('localedir'))
 | 
			
		||||
desktopdir = join_paths(datadir, 'applications')
 | 
			
		||||
pkgdatadir = join_paths(datadir, meson.project_name())
 | 
			
		||||
if get_option('depdatadir') == ''
 | 
			
		||||
@ -71,10 +72,6 @@ else
 | 
			
		||||
endif
 | 
			
		||||
dbusdir = join_paths(depdatadir, 'dbus-1/interfaces')
 | 
			
		||||
 | 
			
		||||
conf_data = configuration_data()
 | 
			
		||||
conf_data.set_quoted('GETTEXT_PACKAGE', 'squeekboard')
 | 
			
		||||
conf_data.set_quoted('LOCALEDIR', localedir)
 | 
			
		||||
 | 
			
		||||
summary = [
 | 
			
		||||
        '',
 | 
			
		||||
        '------------------',
 | 
			
		||||
@ -96,23 +93,19 @@ cargo_toml_base = configure_file(
 | 
			
		||||
    configuration: path_data,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
cargo_patch = []
 | 
			
		||||
 | 
			
		||||
if get_option('newer') == true
 | 
			
		||||
    cargo_build_flags += ['--features', 'glib_v0_14']
 | 
			
		||||
    cargo_deps = files('Cargo.deps.newer')
 | 
			
		||||
else
 | 
			
		||||
    cargo_deps = files('Cargo.deps')
 | 
			
		||||
    if get_option('online') == true
 | 
			
		||||
        cargo_patch = [files('Cargo.deps.online')]
 | 
			
		||||
    endif
 | 
			
		||||
cargo_deps = files('Cargo.deps')
 | 
			
		||||
 | 
			
		||||
if get_option('legacy') == true
 | 
			
		||||
    cargo_build_flags += ['--features', 'gtk_v0_5,gio_v0_5,rustc_less_1_36']
 | 
			
		||||
    cargo_deps = files('Cargo.deps.legacy')
 | 
			
		||||
endif
 | 
			
		||||
    
 | 
			
		||||
cat = find_program('cat')
 | 
			
		||||
cargo_toml = custom_target(
 | 
			
		||||
    'Cargo.toml',
 | 
			
		||||
    output: 'Cargo.toml',
 | 
			
		||||
    command: [cat, cargo_toml_base, cargo_deps] + cargo_patch,
 | 
			
		||||
    command: [cat, cargo_toml_base, cargo_deps],
 | 
			
		||||
    capture: true,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -121,7 +114,6 @@ cargo_script = find_program('cargo.sh')
 | 
			
		||||
cargo_build = find_program('cargo_build.py')
 | 
			
		||||
 | 
			
		||||
subdir('data')
 | 
			
		||||
subdir('po')
 | 
			
		||||
subdir('protocols')
 | 
			
		||||
subdir('src')
 | 
			
		||||
subdir('tools')
 | 
			
		||||
 | 
			
		||||
@ -7,13 +7,9 @@ option('tests',
 | 
			
		||||
       type: 'boolean', value: true,
 | 
			
		||||
       description: 'Whether to compile unit tests')
 | 
			
		||||
 | 
			
		||||
option('newer',
 | 
			
		||||
option('legacy',
 | 
			
		||||
       type: 'boolean', value: false,
 | 
			
		||||
       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.')
 | 
			
		||||
       description: 'Build with Deban Buster versions of dependencies')
 | 
			
		||||
 | 
			
		||||
option('strict',
 | 
			
		||||
       type: 'boolean', value: true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								po/LINGUAS
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								po/LINGUAS
									
									
									
									
									
								
							@ -1,13 +0,0 @@
 | 
			
		||||
ca
 | 
			
		||||
de
 | 
			
		||||
fa
 | 
			
		||||
fi
 | 
			
		||||
fur
 | 
			
		||||
gl
 | 
			
		||||
he
 | 
			
		||||
nl
 | 
			
		||||
pt_BR
 | 
			
		||||
ro
 | 
			
		||||
sl
 | 
			
		||||
uk
 | 
			
		||||
sv
 | 
			
		||||
@ -1,2 +0,0 @@
 | 
			
		||||
data/popover.ui
 | 
			
		||||
data/sm.puri.Squeekboard.desktop.in.in
 | 
			
		||||
							
								
								
									
										45
									
								
								po/ca.po
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								po/ca.po
									
									
									
									
									
								
							@ -1,45 +0,0 @@
 | 
			
		||||
# Catalan translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# maite <maite.guix@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-01-11 14:31+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2022-01-20 10:53+0100\n"
 | 
			
		||||
"Last-Translator: maite guix <maite.guix@me.com>\n"
 | 
			
		||||
"Language-Team: Catalan <gnome@llistes.softcatala.org>\n"
 | 
			
		||||
"Language: ca\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 "Configuració del teclat"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:3
 | 
			
		||||
msgid "Squeekboard"
 | 
			
		||||
msgstr "Teclat virtual"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:4
 | 
			
		||||
msgid "On Screen Keyboard"
 | 
			
		||||
msgstr "Teclat en pantalla"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Un teclat virtual en pantalla"
 | 
			
		||||
							
								
								
									
										22
									
								
								po/de.po
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								po/de.po
									
									
									
									
									
								
							@ -1,22 +0,0 @@
 | 
			
		||||
# German translations for squeekboard package.
 | 
			
		||||
# Copyright (C) 2021 THE squeekboard'S COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Automatically generated, 2021.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: squeekboard\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2021-12-03 18:41+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-03 18:41+0100\n"
 | 
			
		||||
"Last-Translator: Automatically generated\n"
 | 
			
		||||
"Language-Team: none\n"
 | 
			
		||||
"Language: de\n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=ASCII\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 | 
			
		||||
 | 
			
		||||
#: data/popup.ui:15
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Tastatureinstellungen"
 | 
			
		||||
							
								
								
									
										45
									
								
								po/fa.po
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								po/fa.po
									
									
									
									
									
								
							@ -1,45 +0,0 @@
 | 
			
		||||
# Persian translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Danial Behzadi <dani.behzi@ubuntu.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: 2021-12-26 15:15+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2022-01-11 18:01+0330\n"
 | 
			
		||||
"Language-Team: Persian <fa@li.org>\n"
 | 
			
		||||
"Language: fa\n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"Last-Translator: Danial Behzadi <dani.behzi@ubuntu.com>\n"
 | 
			
		||||
"X-Generator: Poedit 3.0\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/fi.po
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								po/fi.po
									
									
									
									
									
								
							@ -1,46 +0,0 @@
 | 
			
		||||
# Finnish translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Jiri Grönroos <jiri.gronroos@iki.fi>, 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-25 13:55+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-26 17:15+0200\n"
 | 
			
		||||
"Last-Translator: Jiri Grönroos <jiri.gronroos+l10n@iki.fi>\n"
 | 
			
		||||
"Language-Team: Finnish <lokalisointi-lista@googlegroups.com>\n"
 | 
			
		||||
"Language: fi\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 "Pääte"
 | 
			
		||||
 | 
			
		||||
#: data/popover.ui:18
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Näppäimistön asetukset"
 | 
			
		||||
 | 
			
		||||
#: 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 "Näyttönäppäimistö"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Virtuaalinen näyttönäppäimistö"
 | 
			
		||||
							
								
								
									
										45
									
								
								po/fur.po
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								po/fur.po
									
									
									
									
									
								
							@ -1,45 +0,0 @@
 | 
			
		||||
# Friulian translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Fabio Tomat <f.t.public@gmail.com>, 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 13:33+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-22 15:06+0100\n"
 | 
			
		||||
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
 | 
			
		||||
"Language-Team: Friulian <fur@li.org>\n"
 | 
			
		||||
"Language: fur\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 "Terminâl"
 | 
			
		||||
 | 
			
		||||
#: data/popover.ui:18
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Impostazions tastiere"
 | 
			
		||||
 | 
			
		||||
#: 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 "Tastiere a visôr"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Une tastiere virtuâl a visôr"
 | 
			
		||||
							
								
								
									
										52
									
								
								po/gl.po
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								po/gl.po
									
									
									
									
									
								
							@ -1,52 +0,0 @@
 | 
			
		||||
# Galician 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.
 | 
			
		||||
# Fran Diéguez <frandieguez@gnome.org>, 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-02 17:41+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2022-02-04 16:18+0100\n"
 | 
			
		||||
"Last-Translator: Fran Diéguez <frandieguez@gnome.org>\n"
 | 
			
		||||
"Language-Team: Galician <proxecto@trasno.gal>\n"
 | 
			
		||||
"Language: gl\n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"X-DL-Team: gl\n"
 | 
			
		||||
"X-DL-Module: squeekboard\n"
 | 
			
		||||
"X-DL-Branch: master\n"
 | 
			
		||||
"X-DL-Domain: po\n"
 | 
			
		||||
"X-DL-State: Translating\n"
 | 
			
		||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
 | 
			
		||||
"X-Generator: Gtranslator 41.0\n"
 | 
			
		||||
 | 
			
		||||
#. translators: This is a emmoji keyboard layout
 | 
			
		||||
#: data/popover.ui:6
 | 
			
		||||
msgid "Emoji"
 | 
			
		||||
msgstr "Emoticono"
 | 
			
		||||
 | 
			
		||||
#. translators: This is a terminal keyboard layout
 | 
			
		||||
#: data/popover.ui:12
 | 
			
		||||
msgid "Terminal"
 | 
			
		||||
msgstr "Terminal"
 | 
			
		||||
 | 
			
		||||
#: data/popover.ui:18
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Preferencias 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 pantalla"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Un teclado en pantalla virtual"
 | 
			
		||||
							
								
								
									
										46
									
								
								po/he.po
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								po/he.po
									
									
									
									
									
								
							@ -1,46 +0,0 @@
 | 
			
		||||
# Hebrew translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Yosef Or Boczko <yoseforb@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-02-04 15:22+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2022-02-14 18:05+0200\n"
 | 
			
		||||
"Last-Translator: Yosef Or Boczko <yoseforb@gmail.com>\n"
 | 
			
		||||
"Language-Team: Hebrew <>\n"
 | 
			
		||||
"Language: he\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 40.0\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 "מקלדת מדומה על המסך"
 | 
			
		||||
@ -1,2 +0,0 @@
 | 
			
		||||
i18n = import('i18n')
 | 
			
		||||
i18n.gettext('squeekboard', preset : 'glib')
 | 
			
		||||
							
								
								
									
										48
									
								
								po/nl.po
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								po/nl.po
									
									
									
									
									
								
							@ -1,48 +0,0 @@
 | 
			
		||||
# Dutch translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Jan Jasper de Kroon <jajadekroon@gmail.com>, 2021.
 | 
			
		||||
# Nathan Follens <nfollens@gnome.org>, 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-23 15:18+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-25 14:04+0100\n"
 | 
			
		||||
"Last-Translator: Nathan Follens <nfollens@gnome.org>\n"
 | 
			
		||||
"Language-Team: Dutch <gnome-nl-list@gnome.org>\n"
 | 
			
		||||
"Language: nl\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 "Toetsenbordinstellingen"
 | 
			
		||||
 | 
			
		||||
# Dit is de naam van de applicatie
 | 
			
		||||
#: 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 "Schermtoetsenbord"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Een virtueel schermtoetsenbord"
 | 
			
		||||
							
								
								
									
										47
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								po/pt_BR.po
									
									
									
									
									
								
							@ -1,47 +0,0 @@
 | 
			
		||||
# Brazilian Portuguese translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Rafael Fontenelle <rafaelff@gnome.org>, 2021.
 | 
			
		||||
# Luís Fernando Stürmer da Rosa <luisfsr@dismail.de>, 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 12:39+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2022-01-30 12:34-0300\n"
 | 
			
		||||
"Last-Translator: Luís Fernando Stürmer da Rosa <luisfsr@dismail.de>\n"
 | 
			
		||||
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
 | 
			
		||||
"Language: pt_BR\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\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 "Configuraçõ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 virtual"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Um teclado virtual"
 | 
			
		||||
							
								
								
									
										47
									
								
								po/ro.po
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								po/ro.po
									
									
									
									
									
								
							@ -1,47 +0,0 @@
 | 
			
		||||
# Romanian translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# libre <eposta1@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 14:45+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-22 20:05+0100\n"
 | 
			
		||||
"Last-Translator: libre <eposta1@pm.me>\n"
 | 
			
		||||
"Language-Team: Romanian <gnomero-list@lists.sourceforge.net>\n"
 | 
			
		||||
"Language: ro\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==0 || (n%100 > 0 && n%100 < "
 | 
			
		||||
"20)) ? 1 : 2);;\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 "Terminal"
 | 
			
		||||
 | 
			
		||||
#: data/popover.ui:18
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Opțiuni tastatură"
 | 
			
		||||
 | 
			
		||||
#: 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 "Tastatură pe ecran"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "O tastatură virtuală pe ecran"
 | 
			
		||||
							
								
								
									
										49
									
								
								po/sl.po
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								po/sl.po
									
									
									
									
									
								
							@ -1,49 +0,0 @@
 | 
			
		||||
# Slovenian translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
#
 | 
			
		||||
# Matej Urbančič <mateju@src.gnome.org>, 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-23 16:17+0100\n"
 | 
			
		||||
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
 | 
			
		||||
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
 | 
			
		||||
"Language: sl_SI\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%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
 | 
			
		||||
"%100==4 ? 3 : 0);\n"
 | 
			
		||||
"X-Poedit-SourceCharset: utf-8\n"
 | 
			
		||||
"X-Generator: Poedit 3.0.1\n"
 | 
			
		||||
 | 
			
		||||
#. translators: This is a emmoji keyboard layout
 | 
			
		||||
#: data/popover.ui:6
 | 
			
		||||
msgid "Emoji"
 | 
			
		||||
msgstr "Izrazne ikone"
 | 
			
		||||
 | 
			
		||||
#. translators: This is a terminal keyboard layout
 | 
			
		||||
#: data/popover.ui:12
 | 
			
		||||
msgid "Terminal"
 | 
			
		||||
msgstr "Terminal"
 | 
			
		||||
 | 
			
		||||
#: data/popover.ui:18
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Nastavitve tipkovnice"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:3
 | 
			
		||||
msgid "Squeekboard"
 | 
			
		||||
msgstr "Cvilkovnica"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:4
 | 
			
		||||
msgid "On Screen Keyboard"
 | 
			
		||||
msgstr "Zaslonska tipkovnica"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Navidezna zaslonska tipkovnica"
 | 
			
		||||
							
								
								
									
										48
									
								
								po/sv.po
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								po/sv.po
									
									
									
									
									
								
							@ -1,48 +0,0 @@
 | 
			
		||||
# Swedish translations for squeekboard package.
 | 
			
		||||
# Copyright (C) 2021 THE squeekboard'S COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
# Automatically generated, 2021.
 | 
			
		||||
#
 | 
			
		||||
# Luna Jernberg <droidbittin@gmail.com>, 2021.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: \n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
 | 
			
		||||
"issues\n"
 | 
			
		||||
"POT-Creation-Date: 2021-12-22 12:47+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-22 14:15+0100\n"
 | 
			
		||||
"Language-Team: \n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"X-Generator: Poedit 3.0\n"
 | 
			
		||||
"Last-Translator: \n"
 | 
			
		||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 | 
			
		||||
"Language: sv\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 "Tangentbordsinställningar"
 | 
			
		||||
 | 
			
		||||
#: 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 "Skärmtangentbord"
 | 
			
		||||
 | 
			
		||||
#: data/sm.puri.Squeekboard.desktop.in.in:5
 | 
			
		||||
msgid "An on screen virtual keyboard"
 | 
			
		||||
msgstr "Ett virtuellt skärmtangentbord"
 | 
			
		||||
							
								
								
									
										51
									
								
								po/uk.po
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								po/uk.po
									
									
									
									
									
								
							@ -1,51 +0,0 @@
 | 
			
		||||
# Ukrainian translation for squeekboard.
 | 
			
		||||
# Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER
 | 
			
		||||
# This file is distributed under the same license as the squeekboard package.
 | 
			
		||||
#
 | 
			
		||||
# Yuri Chornoivan <yurchor@ukr.net>, 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 10:36+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2021-12-22 14:46+0200\n"
 | 
			
		||||
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
 | 
			
		||||
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
 | 
			
		||||
"Language: uk\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"
 | 
			
		||||
"X-Generator: Lokalize 20.12.0\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 ""
 | 
			
		||||
"Екранна віртуальна клавіатура"
 | 
			
		||||
@ -2,9 +2,6 @@
 | 
			
		||||
<protocol name="input_method_unstable_v2">
 | 
			
		||||
 | 
			
		||||
  <copyright>
 | 
			
		||||
    Copyright © 2008-2011 Kristian Høgsberg
 | 
			
		||||
    Copyright © 2010-2011 Intel Corporation
 | 
			
		||||
    Copyright © 2012-2013 Collabora, Ltd.
 | 
			
		||||
    Copyright © 2012, 2013 Intel Corporation
 | 
			
		||||
    Copyright © 2015, 2016 Jan Arne Petersen
 | 
			
		||||
    Copyright © 2017, 2018 Red Hat, Inc.
 | 
			
		||||
@ -75,19 +72,18 @@
 | 
			
		||||
        Notification that a text input focused on this seat requested the input
 | 
			
		||||
        method to be activated.
 | 
			
		||||
 | 
			
		||||
        This event serves the purpose of providing the compositor with an
 | 
			
		||||
        active input method.
 | 
			
		||||
        This request must be issued every time a text input requests an input
 | 
			
		||||
        method.
 | 
			
		||||
 | 
			
		||||
        This event resets all state associated with previous enable, disable,
 | 
			
		||||
        surrounding_text, text_change_cause, and content_type events, as well
 | 
			
		||||
        as the state associated with set_preedit_string, commit_string, and
 | 
			
		||||
        delete_surrounding_text requests. In addition, it marks the
 | 
			
		||||
        zwp_input_method_v2 object as active, and makes any existing
 | 
			
		||||
        zwp_input_popup_surface_v2 objects visible.
 | 
			
		||||
        This request resets all state associated with previous enable, disable,
 | 
			
		||||
        set_surrounding_text, set_text_change_cause, set_content_type, and
 | 
			
		||||
        set_cursor_rectangle requests, as well as the state associated with
 | 
			
		||||
        preedit_string, commit_string, and delete_surrounding_text events. In
 | 
			
		||||
        addition, it marks the input method object as active.
 | 
			
		||||
 | 
			
		||||
        The surrounding_text, and content_type events must follow before the
 | 
			
		||||
        next done event if the text input supports the respective
 | 
			
		||||
        functionality.
 | 
			
		||||
        The set_surrounding_text, set_content_type and set_cursor_rectangle
 | 
			
		||||
        requests must follow before the next done event if the text input
 | 
			
		||||
        supports the respective functionality.
 | 
			
		||||
 | 
			
		||||
        State set with this event is double-buffered. It will get applied on
 | 
			
		||||
        the next zwp_input_method_v2.done event, and stay valid until changed.
 | 
			
		||||
@ -96,12 +92,13 @@
 | 
			
		||||
 | 
			
		||||
    <event name="deactivate">
 | 
			
		||||
      <description summary="deactivate event">
 | 
			
		||||
        Notification that no focused text input currently needs an active 
 | 
			
		||||
        input method on this seat.
 | 
			
		||||
        Notification that this seat's current text input requested the input
 | 
			
		||||
        method to be deactivated.
 | 
			
		||||
 | 
			
		||||
        This event marks the zwp_input_method_v2 object as inactive. The
 | 
			
		||||
        compositor must make all existing zwp_input_popup_surface_v2 objects
 | 
			
		||||
        invisible until the next activate event.
 | 
			
		||||
        This event mrks the zwp_input_method_v2 object as inactive.
 | 
			
		||||
 | 
			
		||||
        When the seat has the keyboard capability the text-input focus follows
 | 
			
		||||
        the keyboard focus.
 | 
			
		||||
 | 
			
		||||
        State set with this event is double-buffered. It will get applied on
 | 
			
		||||
        the next zwp_input_method_v2.done event, and stay valid until changed.
 | 
			
		||||
@ -110,7 +107,7 @@
 | 
			
		||||
 | 
			
		||||
    <event name="surrounding_text">
 | 
			
		||||
      <description summary="surrounding text event">
 | 
			
		||||
        Updates the surrounding plain text around the cursor, excluding the
 | 
			
		||||
        Sets the surrounding plain text around the cursor, excluding the
 | 
			
		||||
        preedit text.
 | 
			
		||||
 | 
			
		||||
        If any preedit text is present, it is replaced with the cursor for the
 | 
			
		||||
@ -128,7 +125,7 @@
 | 
			
		||||
        buffer. If there is no selected text, anchor must be the same as
 | 
			
		||||
        cursor.
 | 
			
		||||
 | 
			
		||||
        If this event does not arrive before the first done event, the input
 | 
			
		||||
        If this request does not arrive before the first done event, the input
 | 
			
		||||
        method may assume that the text input does not support this
 | 
			
		||||
        functionality and ignore following surrounding_text events.
 | 
			
		||||
 | 
			
		||||
@ -169,7 +166,7 @@
 | 
			
		||||
    <event name="content_type">
 | 
			
		||||
      <description summary="content purpose and hint">
 | 
			
		||||
        Indicates the content type and hint for the current
 | 
			
		||||
        zwp_input_method_v2 instance.
 | 
			
		||||
        input_method_context instance.
 | 
			
		||||
 | 
			
		||||
        Values set with this event are double-buffered. They will get applied
 | 
			
		||||
        on the next zwp_input_method_v2.done event.
 | 
			
		||||
@ -216,14 +213,14 @@
 | 
			
		||||
        4000 bytes.
 | 
			
		||||
 | 
			
		||||
        Values set with this event are double-buffered. They must be applied
 | 
			
		||||
        and reset to initial on the next zwp_text_input_v3.commit request.
 | 
			
		||||
        and reset to initial on the next zwp_text_input_v3.done event.
 | 
			
		||||
 | 
			
		||||
        The initial value of text is an empty string.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="text" type="string"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="set_preedit_string">
 | 
			
		||||
    <request name="preedit_string">
 | 
			
		||||
      <description summary="pre-edit string">
 | 
			
		||||
        Send the pre-edit string text to the application text input.
 | 
			
		||||
 | 
			
		||||
@ -278,7 +275,7 @@
 | 
			
		||||
 | 
			
		||||
    <request name="commit">
 | 
			
		||||
      <description summary="apply state">
 | 
			
		||||
        Apply state changes from commit_string, set_preedit_string and
 | 
			
		||||
        Apply state changes from commit_string, preedit_string and
 | 
			
		||||
        delete_surrounding_text requests.
 | 
			
		||||
 | 
			
		||||
        The state relating to these events is double-buffered, and each one
 | 
			
		||||
@ -297,10 +294,11 @@
 | 
			
		||||
 | 
			
		||||
        The serial number reflects the last state of the zwp_input_method_v2
 | 
			
		||||
        object known to the client. The value of the serial argument must be
 | 
			
		||||
        equal to the number of done events already issued by that object. When
 | 
			
		||||
        the compositor receives a commit request with a serial different than
 | 
			
		||||
        the number of past done events, it must proceed as normal, except it
 | 
			
		||||
        should not change the current state of the zwp_input_method_v2 object.
 | 
			
		||||
        equal to the number of done events already issued on that object.
 | 
			
		||||
        When the compositor receives a commit request with a serial different than
 | 
			
		||||
        the number of past commit requests, it must proceed as normal, except
 | 
			
		||||
        it should not change the current state of the zwp_input_method_v2
 | 
			
		||||
        object.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="serial" type="uint"/>
 | 
			
		||||
    </request>
 | 
			
		||||
@ -309,10 +307,6 @@
 | 
			
		||||
      <description summary="create popup surface">
 | 
			
		||||
        Creates a new zwp_input_popup_surface_v2 object wrapping a given
 | 
			
		||||
        surface.
 | 
			
		||||
 | 
			
		||||
        The surface gets assigned the "input_popup" role. If the surface
 | 
			
		||||
        already has an assigned role, the compositor must issue a protocol
 | 
			
		||||
        error.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="id" type="new_id" interface="zwp_input_popup_surface_v2"/>
 | 
			
		||||
      <arg name="surface" type="object" interface="wl_surface"/>
 | 
			
		||||
@ -333,8 +327,7 @@
 | 
			
		||||
 | 
			
		||||
        Releasing the resulting wl_keyboard object releases the grab.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="keyboard" type="new_id"
 | 
			
		||||
        interface="zwp_input_method_keyboard_grab_v2"/>
 | 
			
		||||
      <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
 | 
			
		||||
    </request>
 | 
			
		||||
    
 | 
			
		||||
    <event name="unavailable">
 | 
			
		||||
@ -354,25 +347,15 @@
 | 
			
		||||
      </description>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <request name="destroy" type="destructor">
 | 
			
		||||
      <description summary="destroy the text input">
 | 
			
		||||
        Destroys the zwp_text_input_v2 object and any associated child
 | 
			
		||||
        objects, i.e. zwp_input_popup_surface_v2 and
 | 
			
		||||
        zwp_input_method_keyboard_grab_v2.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
    <request name="destroy" type="destructor"/>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="zwp_input_popup_surface_v2" version="1">
 | 
			
		||||
    <description summary="popup surface">
 | 
			
		||||
      This interface marks a surface as a popup for interacting with an input
 | 
			
		||||
      method.
 | 
			
		||||
      This surface is a popup for interacting with an input method.
 | 
			
		||||
 | 
			
		||||
      The compositor should place it near the active text input area. It must
 | 
			
		||||
      be visible if and only if the input method is in the active state.
 | 
			
		||||
 | 
			
		||||
      The client must not destroy the underlying wl_surface while the
 | 
			
		||||
      zwp_input_popup_surface_v2 object exists.
 | 
			
		||||
    </description>
 | 
			
		||||
 | 
			
		||||
    <event name="text_input_rectangle">
 | 
			
		||||
@ -392,75 +375,6 @@
 | 
			
		||||
    <request name="destroy" type="destructor"/>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="zwp_input_method_keyboard_grab_v2" version="1">
 | 
			
		||||
    <!-- Closely follows wl_keyboard version 6 -->
 | 
			
		||||
    <description summary="keyboard grab">
 | 
			
		||||
      The zwp_input_method_keyboard_grab_v2 interface represents an exclusive
 | 
			
		||||
      grab of the wl_keyboard interface associated with the seat.
 | 
			
		||||
    </description>
 | 
			
		||||
 | 
			
		||||
    <event name="keymap">
 | 
			
		||||
      <description summary="keyboard mapping">
 | 
			
		||||
        This event provides a file descriptor to the client which can be
 | 
			
		||||
        memory-mapped to provide a keyboard mapping description.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="format" type="uint" enum="wl_keyboard.keymap_format"
 | 
			
		||||
        summary="keymap format"/>
 | 
			
		||||
      <arg name="fd" type="fd" summary="keymap file descriptor"/>
 | 
			
		||||
      <arg name="size" type="uint" summary="keymap size, in bytes"/>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <event name="key">
 | 
			
		||||
      <description summary="key event">
 | 
			
		||||
        A key was pressed or released.
 | 
			
		||||
        The time argument is a timestamp with millisecond granularity, with an
 | 
			
		||||
        undefined base.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="serial" type="uint" summary="serial number of the key event"/>
 | 
			
		||||
      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
 | 
			
		||||
      <arg name="key" type="uint" summary="key that produced the event"/>
 | 
			
		||||
      <arg name="state" type="uint" enum="wl_keyboard.key_state"
 | 
			
		||||
        summary="physical state of the key"/>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <event name="modifiers">
 | 
			
		||||
      <description summary="modifier and group state">
 | 
			
		||||
        Notifies clients that the modifier and/or group state has changed, and
 | 
			
		||||
        it should update its local state.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
 | 
			
		||||
      <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
 | 
			
		||||
      <arg name="mods_latched" type="uint" summary="latched modifiers"/>
 | 
			
		||||
      <arg name="mods_locked" type="uint" summary="locked modifiers"/>
 | 
			
		||||
      <arg name="group" type="uint" summary="keyboard layout"/>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <request name="release" type="destructor">
 | 
			
		||||
      <description summary="release the grab object"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <event name="repeat_info">
 | 
			
		||||
      <description summary="repeat rate and delay">
 | 
			
		||||
        Informs the client about the keyboard's repeat rate and delay.
 | 
			
		||||
 | 
			
		||||
        This event is sent as soon as the zwp_input_method_keyboard_grab_v2
 | 
			
		||||
        object has been created, and is guaranteed to be received by the
 | 
			
		||||
        client before any key press event.
 | 
			
		||||
 | 
			
		||||
        Negative values for either rate or delay are illegal. A rate of zero
 | 
			
		||||
        will disable any repeating (regardless of the value of delay).
 | 
			
		||||
 | 
			
		||||
        This event can be sent later on as well with a new value if necessary,
 | 
			
		||||
        so clients should continue listening for the event past the creation
 | 
			
		||||
        of zwp_input_method_keyboard_grab_v2.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="rate" type="int"
 | 
			
		||||
	   summary="the rate of repeating keys in characters per second"/>
 | 
			
		||||
      <arg name="delay" type="int"
 | 
			
		||||
	   summary="delay in milliseconds since key down until repeating starts"/>
 | 
			
		||||
    </event>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="zwp_input_method_manager_v2" version="1">
 | 
			
		||||
    <description summary="input method manager">
 | 
			
		||||
      The input method manager allows the client to become the input method on
 | 
			
		||||
 | 
			
		||||
@ -94,12 +94,6 @@
 | 
			
		||||
        zwp_text_input_v3.disable when there is no longer any input focus on
 | 
			
		||||
        the current surface.
 | 
			
		||||
 | 
			
		||||
        Clients must not enable more than one text input on the single seat
 | 
			
		||||
        and should disable the current text input before enabling the new one.
 | 
			
		||||
        At most one instance of text input may be in enabled state per instance,
 | 
			
		||||
        Requests to enable the another text input when some text input is active
 | 
			
		||||
        must be ignored by compositor.
 | 
			
		||||
 | 
			
		||||
        This request resets all state associated with previous enable, disable,
 | 
			
		||||
        set_surrounding_text, set_text_change_cause, set_content_type, and
 | 
			
		||||
        set_cursor_rectangle requests, as well as the state associated with
 | 
			
		||||
@ -313,9 +307,6 @@
 | 
			
		||||
      <description summary="enter event">
 | 
			
		||||
        Notification that this seat's text-input focus is on a certain surface.
 | 
			
		||||
 | 
			
		||||
        If client has created multiple text input objects, compositor must send
 | 
			
		||||
        this event to all of them.
 | 
			
		||||
 | 
			
		||||
        When the seat has the keyboard capability the text-input focus follows
 | 
			
		||||
        the keyboard focus. This event sets the current surface for the
 | 
			
		||||
        text-input object.
 | 
			
		||||
@ -330,9 +321,7 @@
 | 
			
		||||
        set.
 | 
			
		||||
 | 
			
		||||
        The leave notification clears the current surface. It is sent before
 | 
			
		||||
        the enter notification for the new focus. After leave event, compositor
 | 
			
		||||
        must ignore requests from any text input instances until next enter
 | 
			
		||||
        event.
 | 
			
		||||
        the enter notification for the new focus.
 | 
			
		||||
 | 
			
		||||
        When the seat has the keyboard capability the text-input focus follows
 | 
			
		||||
        the keyboard focus.
 | 
			
		||||
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
/* Copyright (C) 2020 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! Animation details */
 | 
			
		||||
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
 | 
			
		||||
use crate::main::PixelSize;
 | 
			
		||||
use crate::outputs::OutputId;
 | 
			
		||||
 | 
			
		||||
/// The keyboard should hide after this has elapsed to prevent flickering.
 | 
			
		||||
pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200);
 | 
			
		||||
 | 
			
		||||
/// The outwardly visible state of visibility
 | 
			
		||||
#[derive(PartialEq, Debug, Clone)]
 | 
			
		||||
pub enum Outcome {
 | 
			
		||||
    Visible {
 | 
			
		||||
        output: OutputId,
 | 
			
		||||
        height: PixelSize,
 | 
			
		||||
    },
 | 
			
		||||
    Hidden,
 | 
			
		||||
}
 | 
			
		||||
@ -1,358 +0,0 @@
 | 
			
		||||
/* Taken from https://github.com/murarth/assert_matches
 | 
			
		||||
 *
 | 
			
		||||
 * git commit: 26b8b40a12823c068a829ba475d0eccc13dfc221
 | 
			
		||||
 * 
 | 
			
		||||
 * assert_matches is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
 | 
			
		||||
 *
 | 
			
		||||
Copyright (c) 2016 Murarth
 | 
			
		||||
	
 | 
			
		||||
Permission is hereby granted, free of charge, to any
 | 
			
		||||
person obtaining a copy of this software and associated
 | 
			
		||||
documentation files (the "Software"), to deal in the
 | 
			
		||||
Software without restriction, including without
 | 
			
		||||
limitation the rights to use, copy, modify, merge,
 | 
			
		||||
publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
the Software, and to permit persons to whom the Software
 | 
			
		||||
is furnished to do so, subject to the following
 | 
			
		||||
conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice
 | 
			
		||||
shall be included in all copies or substantial portions
 | 
			
		||||
of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
 | 
			
		||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 | 
			
		||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 | 
			
		||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 | 
			
		||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | 
			
		||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
			
		||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 | 
			
		||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
			
		||||
DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//! Provides a macro, `assert_matches!`, which tests whether a value
 | 
			
		||||
//! matches a given pattern, causing a panic if the match fails.
 | 
			
		||||
//!
 | 
			
		||||
//! See the macro [`assert_matches!`] documentation for more information.
 | 
			
		||||
//!
 | 
			
		||||
//! Also provides a debug-only counterpart, [`debug_assert_matches!`].
 | 
			
		||||
//!
 | 
			
		||||
//! See the macro [`debug_assert_matches!`] documentation for more information
 | 
			
		||||
//! about this macro.
 | 
			
		||||
//!
 | 
			
		||||
//! [`assert_matches!`]: macro.assert_matches.html
 | 
			
		||||
//! [`debug_assert_matches!`]: macro.debug_assert_matches.html
 | 
			
		||||
 | 
			
		||||
#![deny(missing_docs)]
 | 
			
		||||
#![cfg_attr(not(test), no_std)]
 | 
			
		||||
 | 
			
		||||
/// Asserts that an expression matches a given pattern.
 | 
			
		||||
///
 | 
			
		||||
/// A guard expression may be supplied to add further restrictions to the
 | 
			
		||||
/// expected value of the expression.
 | 
			
		||||
///
 | 
			
		||||
/// A `match` arm may be supplied to perform additional assertions or to yield
 | 
			
		||||
/// a value from the macro invocation.
 | 
			
		||||
///
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```
 | 
			
		||||
/// #[macro_use] extern crate assert_matches;
 | 
			
		||||
///
 | 
			
		||||
/// #[derive(Debug)]
 | 
			
		||||
/// enum Foo {
 | 
			
		||||
///     A(i32),
 | 
			
		||||
///     B(&'static str),
 | 
			
		||||
/// }
 | 
			
		||||
///
 | 
			
		||||
/// # fn main() {
 | 
			
		||||
/// let a = Foo::A(1);
 | 
			
		||||
///
 | 
			
		||||
/// // Assert that `a` matches the pattern `Foo::A(_)`.
 | 
			
		||||
/// assert_matches!(a, Foo::A(_));
 | 
			
		||||
///
 | 
			
		||||
/// // Assert that `a` matches the pattern and
 | 
			
		||||
/// // that the contained value meets the condition `i > 0`.
 | 
			
		||||
/// assert_matches!(a, Foo::A(i) if i > 0);
 | 
			
		||||
///
 | 
			
		||||
/// let b = Foo::B("foobar");
 | 
			
		||||
/// 
 | 
			
		||||
/// // Assert that `b` matches the pattern `Foo::B(_)`.
 | 
			
		||||
/// assert_matches!(b, Foo::B(s) => {
 | 
			
		||||
///     // Perform additional assertions on the variable binding `s`.
 | 
			
		||||
///     assert!(s.starts_with("foo"));
 | 
			
		||||
///     assert!(s.ends_with("bar"));
 | 
			
		||||
/// });
 | 
			
		||||
///
 | 
			
		||||
/// // Assert that `b` matches the pattern and yield the string `s`.
 | 
			
		||||
/// let s = assert_matches!(b, Foo::B(s) => s);
 | 
			
		||||
///
 | 
			
		||||
/// // Perform an assertion on the value `s`.
 | 
			
		||||
/// assert_eq!(s, "foobar");
 | 
			
		||||
/// # }
 | 
			
		||||
/// ```
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! assert_matches {
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ => (),
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`",
 | 
			
		||||
                e, stringify!($($pat)|+))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ if $cond:expr ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ if $cond => (),
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`",
 | 
			
		||||
                e, stringify!($($pat)|+ if $cond))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ => $arm:expr ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ => $arm,
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`",
 | 
			
		||||
                e, stringify!($($pat)|+))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ if $cond:expr => $arm:expr ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ if $cond => $arm,
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`",
 | 
			
		||||
                e, stringify!($($pat)|+ if $cond))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ , $($arg:tt)* ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ => (),
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}",
 | 
			
		||||
                e, stringify!($($pat)|+), format_args!($($arg)*))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ if $cond:expr , $($arg:tt)* ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ if $cond => (),
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}",
 | 
			
		||||
                e, stringify!($($pat)|+ if $cond), format_args!($($arg)*))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ => $arm:expr , $($arg:tt)* ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ => $arm,
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}",
 | 
			
		||||
                e, stringify!($($pat)|+), format_args!($($arg)*))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    ( $e:expr , $($pat:pat)|+ if $cond:expr => $arm:expr , $($arg:tt)* ) => {
 | 
			
		||||
        match $e {
 | 
			
		||||
            $($pat)|+ if $cond => $arm,
 | 
			
		||||
            ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}",
 | 
			
		||||
                e, stringify!($($pat)|+ if $cond), format_args!($($arg)*))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Asserts that an expression matches a given pattern.
 | 
			
		||||
///
 | 
			
		||||
/// Unlike [`assert_matches!`], `debug_assert_matches!` statements are only enabled
 | 
			
		||||
/// in non-optimized builds by default. An optimized build will omit all
 | 
			
		||||
/// `debug_assert_matches!` statements unless `-C debug-assertions` is passed
 | 
			
		||||
/// to the compiler.
 | 
			
		||||
///
 | 
			
		||||
/// See the macro [`assert_matches!`] documentation for more information.
 | 
			
		||||
///
 | 
			
		||||
/// [`assert_matches!`]: macro.assert_matches.html
 | 
			
		||||
#[macro_export(local_inner_macros)]
 | 
			
		||||
macro_rules! debug_assert_matches {
 | 
			
		||||
    ( $($tt:tt)* ) => { {
 | 
			
		||||
        if _assert_matches_cfg!(debug_assertions) {
 | 
			
		||||
            assert_matches!($($tt)*);
 | 
			
		||||
        }
 | 
			
		||||
    } }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[doc(hidden)]
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! _assert_matches_cfg {
 | 
			
		||||
    ( $($tt:tt)* ) => { cfg!($($tt)*) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use std::panic::{catch_unwind, UnwindSafe};
 | 
			
		||||
 | 
			
		||||
    #[derive(Debug)]
 | 
			
		||||
    enum Foo {
 | 
			
		||||
        A(i32),
 | 
			
		||||
        B(&'static str),
 | 
			
		||||
        C(&'static str),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_assert_succeed() {
 | 
			
		||||
        let a = Foo::A(123);
 | 
			
		||||
 | 
			
		||||
        assert_matches!(a, Foo::A(_));
 | 
			
		||||
        assert_matches!(a, Foo::A(123));
 | 
			
		||||
        assert_matches!(a, Foo::A(i) if i == 123);
 | 
			
		||||
        assert_matches!(a, Foo::A(42) | Foo::A(123));
 | 
			
		||||
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(_));
 | 
			
		||||
        assert_matches!(b, Foo::B("foo"));
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "foo");
 | 
			
		||||
        assert_matches!(b, Foo::B(s) => assert_eq!(s, "foo"));
 | 
			
		||||
        assert_matches!(b, Foo::B(s) => { assert_eq!(s, "foo"); assert!(true) });
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "foo" => assert_eq!(s, "foo"));
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(true) });
 | 
			
		||||
 | 
			
		||||
        let c = Foo::C("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(c, Foo::B(_) | Foo::C(_));
 | 
			
		||||
        assert_matches!(c, Foo::B("foo") | Foo::C("foo"));
 | 
			
		||||
        assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo");
 | 
			
		||||
        assert_matches!(c, Foo::B(s) | Foo::C(s) => assert_eq!(s, "foo"));
 | 
			
		||||
        assert_matches!(c, Foo::B(s) | Foo::C(s) => { assert_eq!(s, "foo"); assert!(true) });
 | 
			
		||||
        assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo" => assert_eq!(s, "foo"));
 | 
			
		||||
        assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(true) });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_0() {
 | 
			
		||||
        let a = Foo::A(123);
 | 
			
		||||
 | 
			
		||||
        assert_matches!(a, Foo::B(_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_1() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B("bar"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_2() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "bar");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_3() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(s) => assert_eq!(s, "bar"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_4() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "bar" => assert_eq!(s, "foo"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_5() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "foo" => assert_eq!(s, "bar"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn test_assert_panic_6() {
 | 
			
		||||
        let b = Foo::B("foo");
 | 
			
		||||
 | 
			
		||||
        assert_matches!(b, Foo::B(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(false) });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_assert_no_move() {
 | 
			
		||||
        let b = &mut Foo::A(0);
 | 
			
		||||
        assert_matches!(*b, Foo::A(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn assert_with_message() {
 | 
			
		||||
        let a = Foo::A(0);
 | 
			
		||||
 | 
			
		||||
        assert_matches!(a, Foo::A(_), "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0, "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0 => assert_eq!(n, 0), "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0 => { assert_eq!(n, 0); assert!(n < 1) }, "o noes");
 | 
			
		||||
        assert_matches!(a, Foo::A(_), "o noes {:?}", a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0, "o noes {:?}", a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes {:?}", a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes {:?}", a);
 | 
			
		||||
        assert_matches!(a, Foo::A(_), "o noes {value:?}", value=a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0, "o noes {value:?}", value=a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes {value:?}", value=a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes {value:?}", value=a);
 | 
			
		||||
        assert_matches!(a, Foo::A(n) if n == 0 => assert_eq!(n, 0), "o noes {value:?}", value=a);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn panic_message<F>(f: F) -> String
 | 
			
		||||
            where F: FnOnce() + UnwindSafe {
 | 
			
		||||
        let err = catch_unwind(f)
 | 
			
		||||
            .expect_err("function did not panic");
 | 
			
		||||
 | 
			
		||||
        *err.downcast::<String>()
 | 
			
		||||
            .expect("function panicked with non-String value")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_panic_message() {
 | 
			
		||||
        let a = Foo::A(1);
 | 
			
		||||
 | 
			
		||||
        // expr, pat
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(_));
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat if cond
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(s) if s == "foo");
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat => arm
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(_) => {});
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat if cond => arm
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(s) if s == "foo" => {});
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat, args
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(_), "msg");
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`: msg"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat if cond, args
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(s) if s == "foo", "msg");
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`: msg"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat => arm, args
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(_) => {}, "msg");
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`: msg"#);
 | 
			
		||||
 | 
			
		||||
        // expr, pat if cond => arm, args
 | 
			
		||||
        assert_eq!(panic_message(|| {
 | 
			
		||||
            assert_matches!(a, Foo::B(s) if s == "foo" => {}, "msg");
 | 
			
		||||
        }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`: msg"#);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -2,9 +2,3 @@
 | 
			
		||||
 * Autogenerated by the Meson build system.
 | 
			
		||||
 * Do not edit, your changes will be lost.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#mesondefine GETTEXT_PACKAGE
 | 
			
		||||
 | 
			
		||||
#mesondefine LOCALEDIR
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@ pub mod c {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let (kind, layout) = load_layout_data_with_fallback(&name, type_, variant, overlay_str);
 | 
			
		||||
        let layout = ::layout::Layout::new(layout, kind, variant);
 | 
			
		||||
        let layout = ::layout::Layout::new(layout, kind);
 | 
			
		||||
        Box::into_raw(Box::new(layout))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -166,13 +166,10 @@ fn get_directory_string(
 | 
			
		||||
 | 
			
		||||
    let layout_purpose = match overlay {
 | 
			
		||||
        None => match content_purpose {
 | 
			
		||||
            ContentPurpose::Email => Special("email"),
 | 
			
		||||
            ContentPurpose::Digits => Special("number"),
 | 
			
		||||
            ContentPurpose::Number => Special("number"),
 | 
			
		||||
            ContentPurpose::Digits => Special("number"),
 | 
			
		||||
            ContentPurpose::Phone => Special("number"),
 | 
			
		||||
            ContentPurpose::Pin => Special("pin"),
 | 
			
		||||
            ContentPurpose::Terminal => Special("terminal"),
 | 
			
		||||
            ContentPurpose::Url => Special("url"),
 | 
			
		||||
            _ => Default,
 | 
			
		||||
        },
 | 
			
		||||
        Some(overlay) => Special(overlay),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								src/dbus.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/dbus.c
									
									
									
									
									
								
							@ -19,9 +19,7 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "dbus.h"
 | 
			
		||||
#include "main.h"
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
 | 
			
		||||
@ -46,6 +44,11 @@ dbus_handler_destroy(DBusHandler *service)
 | 
			
		||||
        service->introspection_data = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (service->context) {
 | 
			
		||||
        g_signal_handlers_disconnect_by_data (service->context, service);
 | 
			
		||||
        service->context = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(service);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -54,25 +57,38 @@ handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
 | 
			
		||||
                   gboolean arg_visible, gpointer user_data) {
 | 
			
		||||
    DBusHandler *service = user_data;
 | 
			
		||||
 | 
			
		||||
    if (service->context) {
 | 
			
		||||
        if (arg_visible) {
 | 
			
		||||
        squeek_state_send_force_visible (service->state_manager);
 | 
			
		||||
            server_context_service_force_show_keyboard (service->context);
 | 
			
		||||
        } else {
 | 
			
		||||
        squeek_state_send_force_hidden(service->state_manager);
 | 
			
		||||
            server_context_service_hide_keyboard (service->context);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sm_puri_osk0_complete_set_visible(object, invocation);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void on_visible(DBusHandler *service,
 | 
			
		||||
                       GParamSpec *pspec,
 | 
			
		||||
                       ServerContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    (void)pspec;
 | 
			
		||||
    gboolean visible;
 | 
			
		||||
 | 
			
		||||
    g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (context));
 | 
			
		||||
 | 
			
		||||
    g_object_get (context, "visible", &visible, NULL);
 | 
			
		||||
 | 
			
		||||
    sm_puri_osk0_set_visible(service->dbus_interface, visible);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DBusHandler *
 | 
			
		||||
dbus_handler_new (GDBusConnection *connection,
 | 
			
		||||
                      const gchar     *object_path,
 | 
			
		||||
                  struct squeek_state_manager *state_manager)
 | 
			
		||||
                      const gchar     *object_path)
 | 
			
		||||
{
 | 
			
		||||
    DBusHandler *self = calloc(1, sizeof(DBusHandler));
 | 
			
		||||
    self->object_path = g_strdup(object_path);
 | 
			
		||||
    self->connection = connection;
 | 
			
		||||
    self->state_manager = state_manager;
 | 
			
		||||
 | 
			
		||||
    self->dbus_interface = sm_puri_osk0_skeleton_new();
 | 
			
		||||
    g_signal_connect(self->dbus_interface, "handle-set-visible",
 | 
			
		||||
@ -93,9 +109,16 @@ dbus_handler_new (GDBusConnection *connection,
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exported to Rust
 | 
			
		||||
void dbus_handler_set_visible(DBusHandler *service,
 | 
			
		||||
                       uint8_t visible)
 | 
			
		||||
void
 | 
			
		||||
dbus_handler_set_ui_context(DBusHandler *service,
 | 
			
		||||
                             ServerContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    sm_puri_osk0_set_visible(service->dbus_interface, visible);
 | 
			
		||||
    g_return_if_fail (!service->context);
 | 
			
		||||
 | 
			
		||||
    service->context = context;
 | 
			
		||||
 | 
			
		||||
    g_signal_connect_swapped (service->context,
 | 
			
		||||
                              "notify::visible",
 | 
			
		||||
                              G_CALLBACK(on_visible),
 | 
			
		||||
                              service);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								src/dbus.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/dbus.h
									
									
									
									
									
								
							@ -19,20 +19,15 @@
 | 
			
		||||
#ifndef DBUS_H_
 | 
			
		||||
#define DBUS_H_ 1
 | 
			
		||||
 | 
			
		||||
#include "sm.puri.OSK0.h"
 | 
			
		||||
#include "server-context-service.h"
 | 
			
		||||
 | 
			
		||||
// From main.h
 | 
			
		||||
struct squeek_state_manager;
 | 
			
		||||
#include "sm.puri.OSK0.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define DBUS_SERVICE_PATH "/sm/puri/OSK0"
 | 
			
		||||
#define DBUS_SERVICE_INTERFACE "sm.puri.OSK0"
 | 
			
		||||
 | 
			
		||||
/// Two jobs: accept events, forwarding them to the visibility manager,
 | 
			
		||||
/// and get updated from inside to show internal state.
 | 
			
		||||
/// Updates are handled in the same loop as the UI.
 | 
			
		||||
/// See main.rs
 | 
			
		||||
typedef struct _DBusHandler
 | 
			
		||||
{
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
@ -41,14 +36,13 @@ typedef struct _DBusHandler
 | 
			
		||||
    guint registration_id;
 | 
			
		||||
    char *object_path;
 | 
			
		||||
 | 
			
		||||
    /// Forward incoming events there
 | 
			
		||||
    struct squeek_state_manager *state_manager; // shared reference
 | 
			
		||||
    ServerContextService *context; // unowned reference
 | 
			
		||||
} DBusHandler;
 | 
			
		||||
 | 
			
		||||
DBusHandler * dbus_handler_new      (GDBusConnection *connection,
 | 
			
		||||
                                             const gchar     *object_path,
 | 
			
		||||
                                     struct squeek_state_manager *state_manager);
 | 
			
		||||
 | 
			
		||||
                                             const gchar     *object_path);
 | 
			
		||||
void              dbus_handler_set_ui_context(DBusHandler *service,
 | 
			
		||||
                                               ServerContextService *context);
 | 
			
		||||
void dbus_handler_destroy(DBusHandler*);
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* DBUS_H_ */
 | 
			
		||||
 | 
			
		||||
@ -7,10 +7,10 @@ use ::action::{ Action, Modifier };
 | 
			
		||||
use ::keyboard;
 | 
			
		||||
use ::layout::{ Button, Label, LatchedState, Layout };
 | 
			
		||||
use ::layout::c::{ Bounds, EekGtkKeyboard, Point };
 | 
			
		||||
use ::submission::c::Submission as CSubmission;
 | 
			
		||||
use ::submission::Submission;
 | 
			
		||||
 | 
			
		||||
use glib::translate::FromGlibPtrNone;
 | 
			
		||||
use gtk::prelude::WidgetExt;
 | 
			
		||||
use gtk::WidgetExt;
 | 
			
		||||
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
use std::ffi::CStr;
 | 
			
		||||
@ -76,11 +76,10 @@ mod c {
 | 
			
		||||
        layout: *mut Layout,
 | 
			
		||||
        renderer: EekRenderer,
 | 
			
		||||
        cr: *mut cairo_sys::cairo_t,
 | 
			
		||||
        submission: CSubmission,
 | 
			
		||||
        submission: *const Submission,
 | 
			
		||||
    ) {
 | 
			
		||||
        let layout = unsafe { &mut *layout };
 | 
			
		||||
        let submission = submission.clone_ref();
 | 
			
		||||
        let submission = submission.borrow();
 | 
			
		||||
        let submission = unsafe { &*submission };
 | 
			
		||||
        let cr = unsafe { cairo::Context::from_raw_none(cr) };
 | 
			
		||||
        let active_modifiers = submission.get_active_modifiers();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,143 +0,0 @@
 | 
			
		||||
/* Copyright (C) 2021 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
/*! This drives the loop from the `loop` module.
 | 
			
		||||
 * 
 | 
			
		||||
 * The tracker loop needs to be driven somehow,
 | 
			
		||||
 * and connected to the external world,
 | 
			
		||||
 * both on the side of receiving and sending events.
 | 
			
		||||
 * 
 | 
			
		||||
 * That's going to be implementation-dependent,
 | 
			
		||||
 * connecting to some external mechanisms
 | 
			
		||||
 * for time, messages, and threading/callbacks.
 | 
			
		||||
 * 
 | 
			
		||||
 * This is the "imperative shell" part of the software,
 | 
			
		||||
 * and no longer unit-testable.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use crate::event_loop;
 | 
			
		||||
use crate::logging;
 | 
			
		||||
use crate::main::Commands;
 | 
			
		||||
use crate::state::{ Application, Event };
 | 
			
		||||
use glib;
 | 
			
		||||
use std::sync::mpsc;
 | 
			
		||||
use std::thread;
 | 
			
		||||
use std::time::Instant;
 | 
			
		||||
 | 
			
		||||
// Traits
 | 
			
		||||
use crate::logging::Warn;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Type of the sender that waits for external events
 | 
			
		||||
type Sender = mpsc::Sender<Event>;
 | 
			
		||||
/// Type of the sender that waits for internal state changes
 | 
			
		||||
type UISender = glib::Sender<Commands>;
 | 
			
		||||
 | 
			
		||||
/// This loop driver spawns a new thread which updates the state in a loop,
 | 
			
		||||
/// in response to incoming events.
 | 
			
		||||
/// It sends outcomes to the glib main loop using a channel.
 | 
			
		||||
/// The outcomes are applied by the UI end of the channel in the `main` module.
 | 
			
		||||
// This could still be reasonably tested,
 | 
			
		||||
// by creating a glib::Sender and checking what messages it receives.
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct Threaded {
 | 
			
		||||
    thread: Sender,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Threaded {
 | 
			
		||||
    pub fn new(ui: UISender, initial_state: Application) -> Self {
 | 
			
		||||
        let (sender, receiver) = mpsc::channel();
 | 
			
		||||
        let saved_sender = sender.clone();
 | 
			
		||||
        thread::spawn(move || {
 | 
			
		||||
            let mut state = event_loop::State::new(initial_state, Instant::now());
 | 
			
		||||
            loop {
 | 
			
		||||
                match receiver.recv() {
 | 
			
		||||
                    Ok(event) => {
 | 
			
		||||
                        state = Self::handle_loop_event(&sender, state, event, &ui);
 | 
			
		||||
                    },
 | 
			
		||||
                    Err(e) => {
 | 
			
		||||
                        logging::print(logging::Level::Bug, &format!("Senders hung up, aborting: {}", e));
 | 
			
		||||
                        return;
 | 
			
		||||
                    },
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            thread: saved_sender,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    pub fn send(&self, event: Event) -> Result<(), mpsc::SendError<Event>> {
 | 
			
		||||
        self.thread.send(event)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn handle_loop_event(loop_sender: &Sender, state: event_loop::State, event: Event, ui: &UISender)
 | 
			
		||||
        -> event_loop::State
 | 
			
		||||
    {
 | 
			
		||||
        let now = Instant::now();
 | 
			
		||||
 | 
			
		||||
        let (new_state, commands) = event_loop::handle_event(state.clone(), event, now);
 | 
			
		||||
 | 
			
		||||
        ui.send(commands)
 | 
			
		||||
            .or_warn(&mut logging::Print, logging::Problem::Bug, "Can't send to UI");
 | 
			
		||||
 | 
			
		||||
        if new_state.scheduled_wakeup != state.scheduled_wakeup {
 | 
			
		||||
            if let Some(when) = new_state.scheduled_wakeup {
 | 
			
		||||
                Self::schedule_timeout_wake(loop_sender, when);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        new_state
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn schedule_timeout_wake(loop_sender: &Sender, when: Instant) {
 | 
			
		||||
        let sender = loop_sender.clone();
 | 
			
		||||
        thread::spawn(move || {
 | 
			
		||||
            let now = Instant::now();
 | 
			
		||||
            thread::sleep(when - now);
 | 
			
		||||
            sender.send(Event::TimeoutReached(when))
 | 
			
		||||
                .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't wake visibility manager");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// For calling in only
 | 
			
		||||
mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    use crate::state::Presence;
 | 
			
		||||
    use crate::state::visibility;
 | 
			
		||||
    use crate::util::c::Wrapped;
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_state_send_force_visible(mgr: Wrapped<Threaded>) {
 | 
			
		||||
        let sender = mgr.clone_ref();
 | 
			
		||||
        let sender = sender.borrow();
 | 
			
		||||
        sender.send(Event::Visibility(visibility::Event::ForceVisible))
 | 
			
		||||
            .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_state_send_force_hidden(sender: Wrapped<Threaded>) {
 | 
			
		||||
        let sender = sender.clone_ref();
 | 
			
		||||
        let sender = sender.borrow();
 | 
			
		||||
        sender.send(Event::Visibility(visibility::Event::ForceHidden))
 | 
			
		||||
            .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_state_send_keyboard_present(sender: Wrapped<Threaded>, present: u32) {
 | 
			
		||||
        let sender = sender.clone_ref();
 | 
			
		||||
        let sender = sender.borrow();
 | 
			
		||||
        let state =
 | 
			
		||||
            if present == 0 { Presence::Missing }
 | 
			
		||||
            else { Presence::Present };
 | 
			
		||||
        sender.send(Event::PhysicalKeyboard(state))
 | 
			
		||||
            .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,188 +0,0 @@
 | 
			
		||||
/* Copyright (C) 2021 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! The loop abstraction for driving state changes.
 | 
			
		||||
 * It binds to the state tracker in `state::Application`,
 | 
			
		||||
 * and actually gets driven by a driver in the `driver` module.
 | 
			
		||||
 *
 | 
			
		||||
 * * * *
 | 
			
		||||
 * 
 | 
			
		||||
 * If we performed updates in a tight loop,
 | 
			
		||||
 * the state tracker would have been all we need.
 | 
			
		||||
 *
 | 
			
		||||
 * ``
 | 
			
		||||
 * loop {
 | 
			
		||||
 *  event = current_event()
 | 
			
		||||
 *  outcome = update_state(event)
 | 
			
		||||
 *  io.apply(outcome)
 | 
			
		||||
 * }
 | 
			
		||||
 * ``
 | 
			
		||||
 * 
 | 
			
		||||
 * This is enough to process all events,
 | 
			
		||||
 * and keep the window always in sync with the current state.
 | 
			
		||||
 * 
 | 
			
		||||
 * However, we're trying to be conservative,
 | 
			
		||||
 * and not waste time performing updates that don't change state,
 | 
			
		||||
 * so we have to react to events that end up influencing the state.
 | 
			
		||||
 * 
 | 
			
		||||
 * One complication from that is that animation steps
 | 
			
		||||
 * are not a response to events coming from the owner of the loop,
 | 
			
		||||
 * but are needed by the loop itself.
 | 
			
		||||
 *
 | 
			
		||||
 * This is where the rest of bugs hide:
 | 
			
		||||
 * too few scheduled wakeups mean missed updates and wrong visible state.
 | 
			
		||||
 * Too many wakeups can slow down the process, or make animation jittery.
 | 
			
		||||
 * The loop iteration is kept as a pure function to stay testable.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
pub mod driver;
 | 
			
		||||
 | 
			
		||||
// This module is tightly coupled to the shape of data passed around in this project.
 | 
			
		||||
// That's not a problem as long as there's only one loop.
 | 
			
		||||
// They can still be abstracted into Traits,
 | 
			
		||||
// and the loop parametrized over them.
 | 
			
		||||
use crate::main::Commands;
 | 
			
		||||
use crate::state;
 | 
			
		||||
use crate::state::Event;
 | 
			
		||||
use std::cmp;
 | 
			
		||||
use std::time::{ Duration, Instant };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// This keeps the state of the tracker loop between iterations
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
struct State {
 | 
			
		||||
    state: state::Application,
 | 
			
		||||
    scheduled_wakeup: Option<Instant>,
 | 
			
		||||
    last_update: Instant,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl State {
 | 
			
		||||
    fn new(initial_state: state::Application, now: Instant) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            state: initial_state,
 | 
			
		||||
            scheduled_wakeup: None,
 | 
			
		||||
            last_update: now,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A single iteration of the loop, updating its persistent state.
 | 
			
		||||
/// - updates tracker state,
 | 
			
		||||
/// - determines outcome,
 | 
			
		||||
/// - determines next scheduled animation wakeup,
 | 
			
		||||
/// and because this is a pure function, it's easily testable.
 | 
			
		||||
/// It returns the new state, and the message to send onwards.
 | 
			
		||||
fn handle_event(
 | 
			
		||||
    mut loop_state: State,
 | 
			
		||||
    event: Event,
 | 
			
		||||
    now: Instant,
 | 
			
		||||
) -> (State, Commands) {
 | 
			
		||||
    // Calculate changes to send to the consumer,
 | 
			
		||||
    // based on publicly visible state.
 | 
			
		||||
    // The internal state may change more often than the publicly visible one,
 | 
			
		||||
    // so the resulting changes may be no-ops.
 | 
			
		||||
    let old_state = loop_state.state.clone();
 | 
			
		||||
    let last_update = loop_state.last_update;
 | 
			
		||||
    loop_state.state = loop_state.state.apply_event(event.clone(), now);
 | 
			
		||||
    loop_state.last_update = now;
 | 
			
		||||
 | 
			
		||||
    let new_outcome = loop_state.state.get_outcome(now);
 | 
			
		||||
 | 
			
		||||
    let commands = old_state.get_outcome(last_update)
 | 
			
		||||
        .get_commands_to_reach(&new_outcome);
 | 
			
		||||
    
 | 
			
		||||
    // Timeout events are special: they affect the scheduled timeout.
 | 
			
		||||
    loop_state.scheduled_wakeup = match event {
 | 
			
		||||
        Event::TimeoutReached(when) => {
 | 
			
		||||
            if when > now {
 | 
			
		||||
                // Special handling for scheduled events coming in early.
 | 
			
		||||
                // Wait at least 10 ms to avoid Zeno's paradox.
 | 
			
		||||
                // This is probably not needed though,
 | 
			
		||||
                // if the `now` contains the desired time of the event.
 | 
			
		||||
                // But then what about time "reversing"?
 | 
			
		||||
                Some(cmp::max(
 | 
			
		||||
                    when,
 | 
			
		||||
                    now + Duration::from_millis(10),
 | 
			
		||||
                ))
 | 
			
		||||
            } else {
 | 
			
		||||
                // There's only one timeout in flight, and it's this one.
 | 
			
		||||
                // It's about to complete, and then the tracker can be cleared.
 | 
			
		||||
                // I'm not sure if this is strictly necessary.
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        _ => loop_state.scheduled_wakeup.clone(),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Reschedule timeout if the new state calls for it.
 | 
			
		||||
    let scheduled = &loop_state.scheduled_wakeup;
 | 
			
		||||
    let desired = loop_state.state.get_next_wake(now);
 | 
			
		||||
 | 
			
		||||
    loop_state.scheduled_wakeup = match (scheduled, desired) {
 | 
			
		||||
        (&Some(scheduled), Some(next)) => {
 | 
			
		||||
            if scheduled > next {
 | 
			
		||||
                // State wants a wake to happen before the one which is already scheduled.
 | 
			
		||||
                // The previous state is removed in order to only ever keep one in flight.
 | 
			
		||||
                // That hopefully avoids pileups,
 | 
			
		||||
                // e.g. because the system is busy
 | 
			
		||||
                // and the user keeps doing something that queues more events.
 | 
			
		||||
                Some(next)
 | 
			
		||||
            } else {
 | 
			
		||||
                // Not changing the case when the wanted wake is *after* scheduled,
 | 
			
		||||
                // because wakes are not expensive as long as they don't pile up,
 | 
			
		||||
                // and I can't see a pileup potential when it doesn't retrigger itself.
 | 
			
		||||
                // Skipping an expected event is much more dangerous.
 | 
			
		||||
                Some(scheduled)
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        (None, Some(next)) => Some(next),
 | 
			
		||||
        // No need to change the unneeded wake - see above.
 | 
			
		||||
        // (Some(_), None) => ...
 | 
			
		||||
        (other, _) => other.clone(),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    (loop_state, commands)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use crate::animation;
 | 
			
		||||
    use crate::imservice::{ ContentHint, ContentPurpose };
 | 
			
		||||
    use crate::main::PanelCommand;
 | 
			
		||||
    use crate::state::{ Application, InputMethod, InputMethodDetails, Presence, visibility };
 | 
			
		||||
    use crate::state::test::application_with_fake_output;
 | 
			
		||||
 | 
			
		||||
    fn imdetails_new() -> InputMethodDetails {
 | 
			
		||||
        InputMethodDetails {
 | 
			
		||||
            purpose: ContentPurpose::Normal,
 | 
			
		||||
            hint: ContentHint::NONE,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn schedule_hide() {
 | 
			
		||||
        let start = Instant::now(); // doesn't matter when. It would be better to have a reproducible value though
 | 
			
		||||
        let mut now = start;
 | 
			
		||||
 | 
			
		||||
        let state = Application {
 | 
			
		||||
            im: InputMethod::Active(imdetails_new()),
 | 
			
		||||
            physical_keyboard: Presence::Missing,
 | 
			
		||||
            visibility_override: visibility::State::NotForced,
 | 
			
		||||
            ..application_with_fake_output(start)
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let l = State::new(state, now);
 | 
			
		||||
        let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now);
 | 
			
		||||
        assert_matches!(commands.panel_visibility, Some(PanelCommand::Show{..}));
 | 
			
		||||
        assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT));
 | 
			
		||||
        
 | 
			
		||||
        now += animation::HIDING_TIMEOUT;
 | 
			
		||||
        
 | 
			
		||||
        let (l, commands) = handle_event(l, Event::TimeoutReached(now), now);
 | 
			
		||||
        assert_eq!(commands.panel_visibility, Some(PanelCommand::Hide));
 | 
			
		||||
        assert_eq!(l.scheduled_wakeup, None);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -23,6 +23,22 @@ static const struct zwp_input_method_v2_listener input_method_listener = {
 | 
			
		||||
    .unavailable = imservice_handle_unavailable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
 | 
			
		||||
                                  struct zwp_virtual_keyboard_manager_v1 *vkmanager,
 | 
			
		||||
                                  struct vis_manager *vis_manager,
 | 
			
		||||
                                  struct wl_seat *seat,
 | 
			
		||||
                                  EekboardContextService *state) {
 | 
			
		||||
    struct zwp_input_method_v2 *im = NULL;
 | 
			
		||||
    if (immanager) {
 | 
			
		||||
        im = zwp_input_method_manager_v2_get_input_method(immanager, seat);
 | 
			
		||||
    }
 | 
			
		||||
    struct zwp_virtual_keyboard_v1 *vk = NULL;
 | 
			
		||||
    if (vkmanager) {
 | 
			
		||||
        vk = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkmanager, seat);
 | 
			
		||||
    }
 | 
			
		||||
    return submission_new(im, vk, state, vis_manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Un-inlined
 | 
			
		||||
struct zwp_input_method_v2 *imservice_manager_get_input_method(struct zwp_input_method_manager_v2 *manager,
 | 
			
		||||
                                   struct wl_seat *seat) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								src/imservice.rs
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/imservice.rs
									
									
									
									
									
								
							@ -8,11 +8,7 @@ use std::ffi::CString;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::num::Wrapping;
 | 
			
		||||
use std::string::String;
 | 
			
		||||
use std::time::Instant;
 | 
			
		||||
 | 
			
		||||
use crate::event_loop::driver;
 | 
			
		||||
use crate::state;
 | 
			
		||||
use crate::state::Event;
 | 
			
		||||
use ::logging;
 | 
			
		||||
use ::util::c::into_cstring;
 | 
			
		||||
 | 
			
		||||
@ -26,32 +22,25 @@ pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    use std::os::raw::{c_char, c_void};
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
 | 
			
		||||
    pub use ::ui_manager::c::UIManager;
 | 
			
		||||
    pub use ::submission::c::StateManager;
 | 
			
		||||
 | 
			
		||||
    // The following defined in C
 | 
			
		||||
        
 | 
			
		||||
    /// struct zwp_input_method_v2*
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    #[derive(PartialEq, Clone, Copy)]
 | 
			
		||||
    pub struct InputMethod(*const c_void);
 | 
			
		||||
 | 
			
		||||
    impl InputMethod {
 | 
			
		||||
        pub fn is_null(&self) -> bool {
 | 
			
		||||
            self.0.is_null()
 | 
			
		||||
        }
 | 
			
		||||
        pub fn null() -> Self {
 | 
			
		||||
            Self(ptr::null())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extern "C" {
 | 
			
		||||
        fn imservice_destroy_im(im: InputMethod);
 | 
			
		||||
        fn imservice_destroy_im(im: *mut c::InputMethod);
 | 
			
		||||
 | 
			
		||||
        #[allow(improper_ctypes)] // IMService will never be dereferenced in C
 | 
			
		||||
        pub fn imservice_connect_listeners(im: InputMethod, imservice: *const IMService);
 | 
			
		||||
        pub fn eek_input_method_commit_string(im: InputMethod, text: *const c_char);
 | 
			
		||||
        pub fn eek_input_method_delete_surrounding_text(im: InputMethod, before: u32, after: u32);
 | 
			
		||||
        pub fn eek_input_method_commit(im: InputMethod, serial: u32);
 | 
			
		||||
        pub fn imservice_connect_listeners(im: *mut InputMethod, imservice: *const IMService);
 | 
			
		||||
        pub fn eek_input_method_commit_string(im: *mut InputMethod, text: *const c_char);
 | 
			
		||||
        pub fn eek_input_method_delete_surrounding_text(im: *mut InputMethod, before: u32, after: u32);
 | 
			
		||||
        pub fn eek_input_method_commit(im: *mut InputMethod, serial: u32);
 | 
			
		||||
        fn eekboard_context_service_set_hint_purpose(state: *const StateManager, hint: u32, purpose: u32);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
			
		||||
@ -60,7 +49,7 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_input_method_activate(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod)
 | 
			
		||||
        im: *const InputMethod)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
        imservice.preedit_string = String::new();
 | 
			
		||||
@ -73,7 +62,7 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_input_method_deactivate(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod)
 | 
			
		||||
        im: *const InputMethod)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
        imservice.pending = IMProtocolState {
 | 
			
		||||
@ -85,7 +74,7 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_surrounding_text(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod,
 | 
			
		||||
        im: *const InputMethod,
 | 
			
		||||
        text: *const c_char, cursor: u32, _anchor: u32)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
@ -101,7 +90,7 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_content_type(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod,
 | 
			
		||||
        im: *const InputMethod,
 | 
			
		||||
        hint: u32, purpose: u32)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
@ -129,7 +118,7 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_text_change_cause(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod,
 | 
			
		||||
        im: *const InputMethod,
 | 
			
		||||
        cause: u32)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
@ -149,20 +138,38 @@ pub mod c {
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_done(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod)
 | 
			
		||||
        im: *const InputMethod)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
        let active_changed = imservice.current.active ^ imservice.pending.active;
 | 
			
		||||
 | 
			
		||||
        imservice.current = imservice.pending.clone();
 | 
			
		||||
        imservice.pending = IMProtocolState {
 | 
			
		||||
            active: imservice.current.active,
 | 
			
		||||
            ..IMProtocolState::default()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        imservice.serial += Wrapping(1u32);
 | 
			
		||||
        imservice.send_event();
 | 
			
		||||
 | 
			
		||||
        if active_changed {
 | 
			
		||||
            (imservice.active_callback)(imservice.current.active);
 | 
			
		||||
            if imservice.current.active {
 | 
			
		||||
                unsafe {
 | 
			
		||||
                    eekboard_context_service_set_hint_purpose(
 | 
			
		||||
                        imservice.state_manager,
 | 
			
		||||
                        imservice.current.content_hint.bits(),
 | 
			
		||||
                        imservice.current.content_purpose.clone() as u32,
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // TODO: this is really untested
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn imservice_handle_unavailable(imservice: *mut IMService,
 | 
			
		||||
        im: InputMethod)
 | 
			
		||||
        im: *mut InputMethod)
 | 
			
		||||
    {
 | 
			
		||||
        let imservice = check_imservice(imservice, im).unwrap();
 | 
			
		||||
        unsafe { imservice_destroy_im(im); }
 | 
			
		||||
@ -171,7 +178,7 @@ pub mod c {
 | 
			
		||||
        // the keyboard is already decommissioned
 | 
			
		||||
        imservice.current.active = false;
 | 
			
		||||
 | 
			
		||||
        imservice.send_event();
 | 
			
		||||
        (imservice.active_callback)(imservice.current.active);
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
    // FIXME: destroy and deallocate
 | 
			
		||||
@ -187,7 +194,7 @@ pub mod c {
 | 
			
		||||
    /// Care must be take
 | 
			
		||||
    /// not to exceed the lifetime of the pointer with the reference,
 | 
			
		||||
    /// especially not to store it.
 | 
			
		||||
    fn check_imservice(imservice: *mut IMService, im: InputMethod)
 | 
			
		||||
    fn check_imservice(imservice: *mut IMService, im: *const InputMethod)
 | 
			
		||||
        -> Result<&'static mut IMService, &'static str>
 | 
			
		||||
    {
 | 
			
		||||
        if imservice.is_null() {
 | 
			
		||||
@ -226,7 +233,7 @@ bitflags!{
 | 
			
		||||
/// use rs::imservice::ContentPurpose;
 | 
			
		||||
/// assert_eq!(ContentPurpose::Alpha as u32, 1);
 | 
			
		||||
/// ```
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum ContentPurpose {
 | 
			
		||||
    Normal = 0,
 | 
			
		||||
    Alpha = 1,
 | 
			
		||||
@ -321,8 +328,10 @@ impl Default for IMProtocolState {
 | 
			
		||||
 | 
			
		||||
pub struct IMService {
 | 
			
		||||
    /// Owned reference (still created and destroyed in C)
 | 
			
		||||
    pub im: c::InputMethod,
 | 
			
		||||
    sender: driver::Threaded,
 | 
			
		||||
    pub im: *mut c::InputMethod,
 | 
			
		||||
    /// Unowned reference. Be careful, it's shared with C at large
 | 
			
		||||
    state_manager: *const c::StateManager,
 | 
			
		||||
    active_callback: Box<dyn Fn(bool)>,
 | 
			
		||||
 | 
			
		||||
    pending: IMProtocolState,
 | 
			
		||||
    current: IMProtocolState, // turn current into an idiomatic representation?
 | 
			
		||||
@ -337,14 +346,16 @@ pub enum SubmitError {
 | 
			
		||||
 | 
			
		||||
impl IMService {
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        im: c::InputMethod,
 | 
			
		||||
        sender: driver::Threaded,
 | 
			
		||||
        im: *mut c::InputMethod,
 | 
			
		||||
        state_manager: *const c::StateManager,
 | 
			
		||||
        active_callback: Box<dyn Fn(bool)>,
 | 
			
		||||
    ) -> Box<IMService> {
 | 
			
		||||
        // IMService will be referenced to by C,
 | 
			
		||||
        // so it needs to stay in the same place in memory via Box
 | 
			
		||||
        let imservice = Box::new(IMService {
 | 
			
		||||
            im,
 | 
			
		||||
            sender,
 | 
			
		||||
            active_callback,
 | 
			
		||||
            state_manager,
 | 
			
		||||
            pending: IMProtocolState::default(),
 | 
			
		||||
            current: IMProtocolState::default(),
 | 
			
		||||
            preedit_string: String::new(),
 | 
			
		||||
@ -404,21 +415,4 @@ impl IMService {
 | 
			
		||||
    pub fn is_active(&self) -> bool {
 | 
			
		||||
        self.current.active
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn send_event(&self) {
 | 
			
		||||
        let state = &self.current;
 | 
			
		||||
        let timestamp = Instant::now();
 | 
			
		||||
        let message = if state.active {
 | 
			
		||||
            state::InputMethod::Active(
 | 
			
		||||
                state::InputMethodDetails {
 | 
			
		||||
                    hint: state.content_hint,
 | 
			
		||||
                    purpose: state.content_purpose,
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            state::InputMethod::InactiveSince(timestamp)
 | 
			
		||||
        };
 | 
			
		||||
        self.sender.send(Event::InputMethod(message))
 | 
			
		||||
            .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,6 @@ struct transformation squeek_layout_calculate_transformation(
 | 
			
		||||
 | 
			
		||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type, uint32_t variant_type, const char *overlay_name);
 | 
			
		||||
enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *);
 | 
			
		||||
uint32_t squeek_layout_get_purpose(const struct squeek_layout *);
 | 
			
		||||
void squeek_layout_free(struct squeek_layout*);
 | 
			
		||||
 | 
			
		||||
void squeek_layout_release(struct squeek_layout *layout,
 | 
			
		||||
 | 
			
		||||
@ -32,8 +32,6 @@ use ::manager;
 | 
			
		||||
use ::submission::{ Submission, SubmitData, Timestamp };
 | 
			
		||||
use ::util::find_max_double;
 | 
			
		||||
 | 
			
		||||
use ::imservice::ContentPurpose;
 | 
			
		||||
 | 
			
		||||
// Traits
 | 
			
		||||
use std::borrow::Borrow;
 | 
			
		||||
use ::logging::Warn;
 | 
			
		||||
@ -44,7 +42,6 @@ pub mod c {
 | 
			
		||||
 | 
			
		||||
    use gtk_sys;
 | 
			
		||||
    use std::os::raw::c_void;
 | 
			
		||||
    use crate::submission::c::Submission as CSubmission;
 | 
			
		||||
 | 
			
		||||
    use std::ops::{ Add, Sub };
 | 
			
		||||
 | 
			
		||||
@ -186,13 +183,6 @@ pub mod c {
 | 
			
		||||
        layout.kind.clone() as u32
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_layout_get_purpose(layout: *const Layout) -> u32 {
 | 
			
		||||
        let layout = unsafe { &*layout };
 | 
			
		||||
        layout.purpose.clone() as u32
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_layout_free(layout: *mut Layout) {
 | 
			
		||||
@ -208,7 +198,7 @@ pub mod c {
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_layout_release(
 | 
			
		||||
            layout: *mut Layout,
 | 
			
		||||
            submission: CSubmission,
 | 
			
		||||
            submission: *mut Submission,
 | 
			
		||||
            widget_to_layout: Transformation,
 | 
			
		||||
            time: u32,
 | 
			
		||||
            manager: manager::c::Manager,
 | 
			
		||||
@ -216,8 +206,7 @@ pub mod c {
 | 
			
		||||
        ) {
 | 
			
		||||
            let time = Timestamp(time);
 | 
			
		||||
            let layout = unsafe { &mut *layout };
 | 
			
		||||
            let submission = submission.clone_ref();
 | 
			
		||||
            let mut submission = submission.borrow_mut();
 | 
			
		||||
            let submission = unsafe { &mut *submission };
 | 
			
		||||
            let ui_backend = UIBackend {
 | 
			
		||||
                widget_to_layout,
 | 
			
		||||
                keyboard: ui_keyboard,
 | 
			
		||||
@ -229,7 +218,7 @@ pub mod c {
 | 
			
		||||
                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
			
		||||
                seat::handle_release_key(
 | 
			
		||||
                    layout,
 | 
			
		||||
                    &mut submission,
 | 
			
		||||
                    submission,
 | 
			
		||||
                    Some(&ui_backend),
 | 
			
		||||
                    time,
 | 
			
		||||
                    Some(manager),
 | 
			
		||||
@ -244,19 +233,18 @@ pub mod c {
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_layout_release_all_only(
 | 
			
		||||
            layout: *mut Layout,
 | 
			
		||||
            submission: CSubmission,
 | 
			
		||||
            submission: *mut Submission,
 | 
			
		||||
            time: u32,
 | 
			
		||||
        ) {
 | 
			
		||||
            let layout = unsafe { &mut *layout };
 | 
			
		||||
            let submission = submission.clone_ref();
 | 
			
		||||
            let mut submission = submission.borrow_mut();
 | 
			
		||||
            let submission = unsafe { &mut *submission };
 | 
			
		||||
            // The list must be copied,
 | 
			
		||||
            // because it will be mutated in the loop
 | 
			
		||||
            for key in layout.pressed_keys.clone() {
 | 
			
		||||
                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
			
		||||
                seat::handle_release_key(
 | 
			
		||||
                    layout,
 | 
			
		||||
                    &mut submission,
 | 
			
		||||
                    submission,
 | 
			
		||||
                    None, // don't update UI
 | 
			
		||||
                    Timestamp(time),
 | 
			
		||||
                    None, // don't switch layouts
 | 
			
		||||
@ -269,15 +257,14 @@ pub mod c {
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_layout_depress(
 | 
			
		||||
            layout: *mut Layout,
 | 
			
		||||
            submission: CSubmission,
 | 
			
		||||
            submission: *mut Submission,
 | 
			
		||||
            x_widget: f64, y_widget: f64,
 | 
			
		||||
            widget_to_layout: Transformation,
 | 
			
		||||
            time: u32,
 | 
			
		||||
            ui_keyboard: EekGtkKeyboard,
 | 
			
		||||
        ) {
 | 
			
		||||
            let layout = unsafe { &mut *layout };
 | 
			
		||||
            let submission = submission.clone_ref();
 | 
			
		||||
            let mut submission = submission.borrow_mut();
 | 
			
		||||
            let submission = unsafe { &mut *submission };
 | 
			
		||||
            let point = widget_to_layout.forward(
 | 
			
		||||
                Point { x: x_widget, y: y_widget }
 | 
			
		||||
            );
 | 
			
		||||
@ -288,7 +275,7 @@ pub mod c {
 | 
			
		||||
            if let Some(state) = state {
 | 
			
		||||
                seat::handle_press_key(
 | 
			
		||||
                    layout,
 | 
			
		||||
                    &mut submission,
 | 
			
		||||
                    submission,
 | 
			
		||||
                    Timestamp(time),
 | 
			
		||||
                    &state,
 | 
			
		||||
                );
 | 
			
		||||
@ -307,7 +294,7 @@ pub mod c {
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_layout_drag(
 | 
			
		||||
            layout: *mut Layout,
 | 
			
		||||
            submission: CSubmission,
 | 
			
		||||
            submission: *mut Submission,
 | 
			
		||||
            x_widget: f64, y_widget: f64,
 | 
			
		||||
            widget_to_layout: Transformation,
 | 
			
		||||
            time: u32,
 | 
			
		||||
@ -316,8 +303,7 @@ pub mod c {
 | 
			
		||||
        ) {
 | 
			
		||||
            let time = Timestamp(time);
 | 
			
		||||
            let layout = unsafe { &mut *layout };
 | 
			
		||||
            let submission = submission.clone_ref();
 | 
			
		||||
            let mut submission = submission.borrow_mut();
 | 
			
		||||
            let submission = unsafe { &mut *submission };
 | 
			
		||||
            let ui_backend = UIBackend {
 | 
			
		||||
                widget_to_layout,
 | 
			
		||||
                keyboard: ui_keyboard,
 | 
			
		||||
@ -345,7 +331,7 @@ pub mod c {
 | 
			
		||||
                    } else {
 | 
			
		||||
                        seat::handle_release_key(
 | 
			
		||||
                            layout,
 | 
			
		||||
                            &mut submission,
 | 
			
		||||
                            submission,
 | 
			
		||||
                            Some(&ui_backend),
 | 
			
		||||
                            time,
 | 
			
		||||
                            Some(manager),
 | 
			
		||||
@ -356,7 +342,7 @@ pub mod c {
 | 
			
		||||
                if !found {
 | 
			
		||||
                    seat::handle_press_key(
 | 
			
		||||
                        layout,
 | 
			
		||||
                        &mut submission,
 | 
			
		||||
                        submission,
 | 
			
		||||
                        time,
 | 
			
		||||
                        &state,
 | 
			
		||||
                    );
 | 
			
		||||
@ -370,7 +356,7 @@ pub mod c {
 | 
			
		||||
                    let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
 | 
			
		||||
                    seat::handle_release_key(
 | 
			
		||||
                        layout,
 | 
			
		||||
                        &mut submission,
 | 
			
		||||
                        submission,
 | 
			
		||||
                        Some(&ui_backend),
 | 
			
		||||
                        time,
 | 
			
		||||
                        Some(manager),
 | 
			
		||||
@ -641,7 +627,6 @@ pub enum LatchedState {
 | 
			
		||||
pub struct Layout {
 | 
			
		||||
    pub margins: Margins,
 | 
			
		||||
    pub kind: ArrangementKind,
 | 
			
		||||
    pub purpose: ContentPurpose,
 | 
			
		||||
    pub current_view: String,
 | 
			
		||||
 | 
			
		||||
    // If current view is latched,
 | 
			
		||||
@ -691,7 +676,7 @@ impl fmt::Display for NoSuchView {
 | 
			
		||||
// The usage of &mut on Rc<RefCell<KeyState>> doesn't mean anything special.
 | 
			
		||||
// Cloning could also be used.
 | 
			
		||||
impl Layout {
 | 
			
		||||
    pub fn new(data: LayoutData, kind: ArrangementKind, purpose: ContentPurpose) -> Layout {
 | 
			
		||||
    pub fn new(data: LayoutData, kind: ArrangementKind) -> Layout {
 | 
			
		||||
        Layout {
 | 
			
		||||
            kind,
 | 
			
		||||
            current_view: "base".to_owned(),
 | 
			
		||||
@ -700,7 +685,6 @@ impl Layout {
 | 
			
		||||
            keymaps: data.keymaps,
 | 
			
		||||
            pressed_keys: HashSet::new(),
 | 
			
		||||
            margins: data.margins,
 | 
			
		||||
            purpose,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1210,7 +1194,6 @@ mod test {
 | 
			
		||||
                "base".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
 | 
			
		||||
                "locked".into() => (c::Point { x: 0.0, y: 0.0 }, view),
 | 
			
		||||
            },
 | 
			
		||||
            purpose: ContentPurpose::Normal,
 | 
			
		||||
        };        
 | 
			
		||||
 | 
			
		||||
        // Basic cycle
 | 
			
		||||
@ -1287,7 +1270,6 @@ mod test {
 | 
			
		||||
                "locked".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
 | 
			
		||||
                "unlocked".into() => (c::Point { x: 0.0, y: 0.0 }, view),
 | 
			
		||||
            },
 | 
			
		||||
            purpose: ContentPurpose::Normal,
 | 
			
		||||
        };        
 | 
			
		||||
 | 
			
		||||
        layout.apply_view_transition(&switch);
 | 
			
		||||
@ -1354,7 +1336,6 @@ mod test {
 | 
			
		||||
                "locked".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
 | 
			
		||||
                "ĄĘ".into() => (c::Point { x: 0.0, y: 0.0 }, view),
 | 
			
		||||
            },
 | 
			
		||||
            purpose: ContentPurpose::Normal,
 | 
			
		||||
        };        
 | 
			
		||||
 | 
			
		||||
        // Latch twice, then Ąto-unlatch across 2 levels
 | 
			
		||||
@ -1455,7 +1436,6 @@ mod test {
 | 
			
		||||
            views: hashmap! {
 | 
			
		||||
                String::new() => (c::Point { x: 0.0, y: 0.0 }, view),
 | 
			
		||||
            },
 | 
			
		||||
            purpose: ContentPurpose::Normal,
 | 
			
		||||
        };
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            layout.calculate_inner_size(),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -11,34 +11,30 @@ extern crate gtk_sys;
 | 
			
		||||
#[allow(unused_imports)]
 | 
			
		||||
#[macro_use] // only for tests
 | 
			
		||||
extern crate maplit;
 | 
			
		||||
extern crate regex;
 | 
			
		||||
extern crate serde;
 | 
			
		||||
extern crate xkbcommon;
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
#[macro_use]
 | 
			
		||||
mod assert_matches;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
mod logging;
 | 
			
		||||
 | 
			
		||||
mod action;
 | 
			
		||||
mod animation;
 | 
			
		||||
pub mod data;
 | 
			
		||||
mod drawing;
 | 
			
		||||
mod event_loop;
 | 
			
		||||
pub mod float_ord;
 | 
			
		||||
pub mod imservice;
 | 
			
		||||
mod keyboard;
 | 
			
		||||
mod layout;
 | 
			
		||||
mod locale;
 | 
			
		||||
mod main;
 | 
			
		||||
mod locale_config;
 | 
			
		||||
mod manager;
 | 
			
		||||
mod outputs;
 | 
			
		||||
mod popover;
 | 
			
		||||
mod resources;
 | 
			
		||||
mod state;
 | 
			
		||||
mod style;
 | 
			
		||||
mod submission;
 | 
			
		||||
pub mod tests;
 | 
			
		||||
pub mod util;
 | 
			
		||||
mod ui_manager;
 | 
			
		||||
mod vkeyboard;
 | 
			
		||||
mod xdg;
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,15 @@ impl Drop for XkbInfo {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, PartialEq)]
 | 
			
		||||
pub struct Translation<'a>(pub &'a str);
 | 
			
		||||
 | 
			
		||||
impl<'a> Translation<'a> {
 | 
			
		||||
    pub fn to_owned(&'a self) -> OwnedTranslation {
 | 
			
		||||
        OwnedTranslation(self.0.to_owned())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, PartialEq)]
 | 
			
		||||
pub struct OwnedTranslation(pub String);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										535
									
								
								src/locale_config.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										535
									
								
								src/locale_config.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,535 @@
 | 
			
		||||
/*! Locale detection and management.
 | 
			
		||||
 * Based on https://github.com/rust-locale/locale_config
 | 
			
		||||
 * 
 | 
			
		||||
 * Ready for deletion/replacement once Debian starts packaging this,
 | 
			
		||||
 * although this version doesn't need lazy_static.
 | 
			
		||||
 * 
 | 
			
		||||
 * Copyright (c) 2016–2019 Jan Hudec <bulb@ucw.cz>
 | 
			
		||||
   Copyright (c) 2016 A.J. Gardner <aaron.j.gardner@gmail.com>
 | 
			
		||||
   Copyright (c) 2019, Bastien Orivel <eijebong@bananium.fr>
 | 
			
		||||
   Copyright (c) 2019, Igor Gnatenko <i.gnatenko.brain@gmail.com>
 | 
			
		||||
   Copyright (c) 2019, Sophie Tauchert <999eagle@999eagle.moe>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use regex::Regex;
 | 
			
		||||
use std::borrow::Cow;
 | 
			
		||||
use std::env;
 | 
			
		||||
 | 
			
		||||
/// Errors that may be returned by `locale_config`.
 | 
			
		||||
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
 | 
			
		||||
pub enum Error {
 | 
			
		||||
    /// Provided definition was not well formed.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This is returned when provided configuration string does not match even the rather loose
 | 
			
		||||
    /// definition for language range from [RFC4647] or the composition format used by `Locale`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// [RFC4647]: https://www.rfc-editor.org/rfc/rfc4647.txt
 | 
			
		||||
    NotWellFormed,
 | 
			
		||||
    /// Placeholder for adding more errors in future. **Do not match!**.
 | 
			
		||||
    __NonExhaustive,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ::std::fmt::Display for Error {
 | 
			
		||||
    fn fmt(&self, out: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
 | 
			
		||||
        out.write_str(match self {
 | 
			
		||||
            &Error::NotWellFormed => "Language tag is not well-formed.",
 | 
			
		||||
            // this is exception: here we do want exhaustive match so we don't publish version with
 | 
			
		||||
            // missing descriptions by mistake.
 | 
			
		||||
            &Error::__NonExhaustive => panic!("Placeholder error must not be instantiated!"),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Convenience Result alias.
 | 
			
		||||
type Result<T> = ::std::result::Result<T, Error>;
 | 
			
		||||
 | 
			
		||||
/// Iterator over `LanguageRange`s for specific category in a `Locale`
 | 
			
		||||
///
 | 
			
		||||
/// Returns `LanguageRange`s in the `Locale` that are applicable to provided category. The tags
 | 
			
		||||
/// are returned in order of preference, which means the category-specific ones first and then
 | 
			
		||||
/// the generic ones.
 | 
			
		||||
///
 | 
			
		||||
/// The iterator is guaranteed to return at least one value.
 | 
			
		||||
pub struct TagsFor<'a, 'c> {
 | 
			
		||||
    src: &'a str,
 | 
			
		||||
    tags: std::str::Split<'a, &'static str>,
 | 
			
		||||
    category: Option<&'c str>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a, 'c> Iterator for TagsFor<'a, 'c> {
 | 
			
		||||
    type Item = LanguageRange<'a>;
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        if let Some(cat) = self.category {
 | 
			
		||||
            while let Some(s) = self.tags.next() {
 | 
			
		||||
                if s.starts_with(cat) && s[cat.len()..].starts_with("=") {
 | 
			
		||||
                    return Some(
 | 
			
		||||
                        LanguageRange { language: Cow::Borrowed(&s[cat.len()+1..]) });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            self.category = None;
 | 
			
		||||
            self.tags = self.src.split(",");
 | 
			
		||||
        }
 | 
			
		||||
        while let Some(s) = self.tags.next() {
 | 
			
		||||
            if s.find('=').is_none() {
 | 
			
		||||
                return Some(
 | 
			
		||||
                    LanguageRange{ language: Cow::Borrowed(s) });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return None;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Language and culture identifier.
 | 
			
		||||
///
 | 
			
		||||
/// This object holds a [RFC4647] extended language range.
 | 
			
		||||
///
 | 
			
		||||
/// The internal data may be owned or shared from object with lifetime `'a`. The lifetime can be
 | 
			
		||||
/// extended using the `into_static()` method, which internally clones the data as needed.
 | 
			
		||||
///
 | 
			
		||||
/// # Syntax
 | 
			
		||||
///
 | 
			
		||||
/// The range is composed of `-`-separated alphanumeric subtags, possibly replaced by `*`s. It
 | 
			
		||||
/// might be empty.
 | 
			
		||||
///
 | 
			
		||||
/// In agreement with [RFC4647], this object only requires that the tag matches:
 | 
			
		||||
///
 | 
			
		||||
/// ```ebnf
 | 
			
		||||
/// language_tag = (alpha{1,8} | "*")
 | 
			
		||||
///                ("-" (alphanum{1,8} | "*"))*
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
/// The exact interpretation is up to the downstream localization provider, but it expected that
 | 
			
		||||
/// it will be matched against a normalized [RFC5646] language tag, which has the structure:
 | 
			
		||||
///
 | 
			
		||||
/// ```ebnf
 | 
			
		||||
/// language_tag    = language
 | 
			
		||||
///                   ("-" script)?
 | 
			
		||||
///                   ("-" region)?
 | 
			
		||||
///                   ("-" variant)*
 | 
			
		||||
///                   ("-" extension)*
 | 
			
		||||
///                   ("-" private)?
 | 
			
		||||
///
 | 
			
		||||
/// language        = alpha{2,3} ("-" alpha{3}){0,3}
 | 
			
		||||
///
 | 
			
		||||
/// script          = aplha{4}
 | 
			
		||||
///
 | 
			
		||||
/// region          = alpha{2}
 | 
			
		||||
///                 | digit{3}
 | 
			
		||||
///
 | 
			
		||||
/// variant         = alphanum{5,8}
 | 
			
		||||
///                 | digit alphanum{3}
 | 
			
		||||
///
 | 
			
		||||
/// extension       = [0-9a-wyz] ("-" alphanum{2,8})+
 | 
			
		||||
///
 | 
			
		||||
/// private         = "x" ("-" alphanum{1,8})+
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
///  * `language` is an [ISO639] 2-letter or, where not defined, 3-letter code. A code for
 | 
			
		||||
///     macro-language might be followed by code of specific dialect.
 | 
			
		||||
///  * `script` is an [ISO15924] 4-letter code.
 | 
			
		||||
///  * `region` is either an [ISO3166] 2-letter code or, for areas other than countries, [UN M.49]
 | 
			
		||||
///    3-digit numeric code.
 | 
			
		||||
///  * `variant` is a string indicating variant of the language.
 | 
			
		||||
///  * `extension` and `private` define additional options. The private part has same structure as
 | 
			
		||||
///    the Unicode [`-u-` extension][u_ext]. Available options are documented for the facets that
 | 
			
		||||
///    use them.
 | 
			
		||||
///
 | 
			
		||||
/// The values obtained by inspecting the system are normalized according to those rules.
 | 
			
		||||
///
 | 
			
		||||
/// The content will be case-normalized as recommended in [RFC5646] §2.1.1, namely:
 | 
			
		||||
///
 | 
			
		||||
///  * `language` is written in lowercase,
 | 
			
		||||
///  * `script` is written with first capital,
 | 
			
		||||
///  * `country` is written in uppercase and
 | 
			
		||||
///  * all other subtags are written in lowercase.
 | 
			
		||||
///
 | 
			
		||||
/// When detecting system configuration, additional options that may be generated under the
 | 
			
		||||
/// [`-u-` extension][u_ext] currently are:
 | 
			
		||||
///
 | 
			
		||||
/// * `cf` — Currency format (`account` for parenthesized negative values, `standard` for minus
 | 
			
		||||
///   sign).
 | 
			
		||||
/// * `fw` — First day of week (`mon` to `sun`).
 | 
			
		||||
/// * `hc` — Hour cycle (`h12` for 1–12, `h23` for 0–23).
 | 
			
		||||
/// * `ms` — Measurement system (`metric` or `ussystem`).
 | 
			
		||||
/// * `nu` — Numbering system—only decimal systems are currently used.
 | 
			
		||||
/// * `va` — Variant when locale is specified in Unix format and the tag after `@` does not
 | 
			
		||||
///   correspond to any variant defined in [Language subtag registry].
 | 
			
		||||
///
 | 
			
		||||
/// And under the `-x-` extension, following options are defined:
 | 
			
		||||
///
 | 
			
		||||
/// * `df` — Date format:
 | 
			
		||||
///
 | 
			
		||||
///     * `iso`: Short date should be in ISO format of `yyyy-MM-dd`.
 | 
			
		||||
///
 | 
			
		||||
///     For example `-df-iso`.
 | 
			
		||||
///
 | 
			
		||||
/// * `dm` — Decimal separator for monetary:
 | 
			
		||||
///
 | 
			
		||||
///     Followed by one or more Unicode codepoints in hexadecimal. For example `-dm-002d` means to
 | 
			
		||||
///     use comma.
 | 
			
		||||
///
 | 
			
		||||
/// * `ds` — Decimal separator for numbers:
 | 
			
		||||
///
 | 
			
		||||
///     Followed by one or more Unicode codepoints in hexadecimal. For example `-ds-002d` means to
 | 
			
		||||
///     use comma.
 | 
			
		||||
///
 | 
			
		||||
/// * `gm` — Group (thousand) separator for monetary:
 | 
			
		||||
///
 | 
			
		||||
///     Followed by one or more Unicode codepoints in hexadecimal. For example `-dm-00a0` means to
 | 
			
		||||
///     use non-breaking space.
 | 
			
		||||
///
 | 
			
		||||
/// * `gs` — Group (thousand) separator for numbers:
 | 
			
		||||
///
 | 
			
		||||
///     Followed by one or more Unicode codepoints in hexadecimal. For example `-ds-00a0` means to
 | 
			
		||||
///     use non-breaking space.
 | 
			
		||||
///
 | 
			
		||||
/// * `ls` — List separator:
 | 
			
		||||
///
 | 
			
		||||
///     Followed by one or more Unicode codepoints in hexadecimal. For example, `-ds-003b` means to
 | 
			
		||||
///     use a semicolon.
 | 
			
		||||
///
 | 
			
		||||
/// [RFC5646]: https://www.rfc-editor.org/rfc/rfc5646.txt
 | 
			
		||||
/// [RFC4647]: https://www.rfc-editor.org/rfc/rfc4647.txt
 | 
			
		||||
/// [ISO639]: https://en.wikipedia.org/wiki/ISO_639
 | 
			
		||||
/// [ISO15924]: https://en.wikipedia.org/wiki/ISO_15924
 | 
			
		||||
/// [ISO3166]: https://en.wikipedia.org/wiki/ISO_3166
 | 
			
		||||
/// [UN M.49]: https://en.wikipedia.org/wiki/UN_M.49
 | 
			
		||||
/// [u_ext]: http://www.unicode.org/reports/tr35/#u_Extension
 | 
			
		||||
/// [Language subtag registry]: https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
 | 
			
		||||
#[derive(Clone,Debug,Eq,Hash,PartialEq)]
 | 
			
		||||
pub struct LanguageRange<'a> {
 | 
			
		||||
    language: Cow<'a, str>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> LanguageRange<'a> {
 | 
			
		||||
    /// Return LanguageRange for the invariant locale.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Invariant language is identified simply by empty string.
 | 
			
		||||
    pub fn invariant() -> LanguageRange<'static> {
 | 
			
		||||
        LanguageRange { language: Cow::Borrowed("") }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create language tag from Unix/Linux/GNU locale tag.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Unix locale tags have the form
 | 
			
		||||
    ///
 | 
			
		||||
    /// > *language* [ `_` *region* ] [ `.` *encoding* ] [ `@` *variant* ]
 | 
			
		||||
    ///
 | 
			
		||||
    /// The *language* and *region* have the same format as RFC5646. *Encoding* is not relevant
 | 
			
		||||
    /// here, since Rust always uses Utf-8. That leaves *variant*, which is unfortunately rather
 | 
			
		||||
    /// free-form. So this function will translate known variants to corresponding RFC5646 subtags
 | 
			
		||||
    /// and represent anything else with Unicode POSIX variant (`-u-va-`) extension.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Note: This function is public here for benefit of applications that may come across this
 | 
			
		||||
    /// kind of tags from other sources than system configuration.
 | 
			
		||||
    pub fn from_unix(s: &str) -> Result<LanguageRange<'static>> {
 | 
			
		||||
        let unix_tag_regex = Regex::new(r"(?ix) ^
 | 
			
		||||
            (?P<language> [[:alpha:]]{2,3} )
 | 
			
		||||
            (?: _  (?P<region> [[:alpha:]]{2} | [[:digit:]]{3} ))?
 | 
			
		||||
            (?: \. (?P<encoding> [0-9a-zA-Z-]{1,20} ))?
 | 
			
		||||
            (?: @  (?P<variant> [[:alnum:]]{1,20} ))?
 | 
			
		||||
        $ ").unwrap();
 | 
			
		||||
        
 | 
			
		||||
        let unix_invariant_regex = Regex::new(r"(?ix) ^
 | 
			
		||||
            (?: c | posix )
 | 
			
		||||
            (?: \. (?: [0-9a-zA-Z-]{1,20} ))?
 | 
			
		||||
        $ ").unwrap();
 | 
			
		||||
        
 | 
			
		||||
        if let Some(caps) = unix_tag_regex.captures(s) {
 | 
			
		||||
            let src_variant = caps.name("variant").map(|m| m.as_str()).unwrap_or("").to_ascii_lowercase();
 | 
			
		||||
            let mut res = caps.name("language").map(|m| m.as_str()).unwrap().to_ascii_lowercase();
 | 
			
		||||
            let region = caps.name("region").map(|m| m.as_str()).unwrap_or("");
 | 
			
		||||
            let mut script = "";
 | 
			
		||||
            let mut variant = "";
 | 
			
		||||
            let mut uvariant = "";
 | 
			
		||||
            match src_variant.as_ref() {
 | 
			
		||||
            // Variants seen in the wild in GNU LibC (via http://lh.2xlibre.net/) or in Debian
 | 
			
		||||
            // GNU/Linux Stretch system. Treatment of things not found in RFC5646 subtag registry
 | 
			
		||||
            // (http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry)
 | 
			
		||||
            // or CLDR according to notes at https://wiki.openoffice.org/wiki/LocaleMapping.
 | 
			
		||||
            // Dialects:
 | 
			
		||||
                // aa_ER@saaho - NOTE: Can't be found under that name in RFC5646 subtag registry,
 | 
			
		||||
                // but there is language Saho with code ssy, which is likely that thing.
 | 
			
		||||
                "saaho" if res == "aa" => res = String::from("ssy"),
 | 
			
		||||
            // Scripts:
 | 
			
		||||
                // @arabic
 | 
			
		||||
                "arabic" => script = "Arab",
 | 
			
		||||
                // @cyrillic
 | 
			
		||||
                "cyrl" => script = "Cyrl",
 | 
			
		||||
                "cyrillic" => script = "Cyrl",
 | 
			
		||||
                // @devanagari
 | 
			
		||||
                "devanagari" => script = "Deva",
 | 
			
		||||
                // @hebrew
 | 
			
		||||
                "hebrew" => script = "Hebr",
 | 
			
		||||
                // tt@iqtelif
 | 
			
		||||
                // Neither RFC5646 subtag registry nor CLDR knows anything about this, but as best
 | 
			
		||||
                // as I can tell it is Tatar name for Latin (default is Cyrillic).
 | 
			
		||||
                "iqtelif" => script = "Latn",
 | 
			
		||||
                // @Latn
 | 
			
		||||
                "latn" => script = "Latn",
 | 
			
		||||
                // @latin
 | 
			
		||||
                "latin" => script = "Latn",
 | 
			
		||||
                // en@shaw
 | 
			
		||||
                "shaw" => script = "Shaw",
 | 
			
		||||
            // Variants:
 | 
			
		||||
                // sr@ijekavianlatin
 | 
			
		||||
                "ijekavianlatin" => {
 | 
			
		||||
                    script = "Latn";
 | 
			
		||||
                    variant = "ijekavsk";
 | 
			
		||||
                },
 | 
			
		||||
                // sr@ije
 | 
			
		||||
                "ije" => variant = "ijekavsk",
 | 
			
		||||
                // sr@ijekavian
 | 
			
		||||
                "ijekavian" => variant = "ijekavsk",
 | 
			
		||||
                // ca@valencia
 | 
			
		||||
                "valencia" => variant = "valencia",
 | 
			
		||||
            // Currencies:
 | 
			
		||||
                // @euro - NOTE: We follow suite of Java and Openoffice and ignore it, because it
 | 
			
		||||
                // is default for all locales where it sometimes appears now, and because we use
 | 
			
		||||
                // explicit currency in monetary formatting anyway.
 | 
			
		||||
                "euro" => {},
 | 
			
		||||
            // Collation:
 | 
			
		||||
                // gez@abegede - NOTE: This is collation, but CLDR does not have any code for it,
 | 
			
		||||
                // so we for the moment leave it fall through as -u-va- instead of -u-co-.
 | 
			
		||||
            // Anything else:
 | 
			
		||||
                // en@boldquot, en@quot, en@piglatin - just randomish stuff
 | 
			
		||||
                // @cjknarrow - beware, it's gonna end up as -u-va-cjknarro due to lenght limit
 | 
			
		||||
                s if s.len() <= 8 => uvariant = &*s,
 | 
			
		||||
                s => uvariant = &s[0..8], // the subtags are limited to 8 chars, but some are longer
 | 
			
		||||
            };
 | 
			
		||||
            if script != "" {
 | 
			
		||||
                res.push('-');
 | 
			
		||||
                res.push_str(script);
 | 
			
		||||
            }
 | 
			
		||||
            if region != "" {
 | 
			
		||||
                res.push('-');
 | 
			
		||||
                res.push_str(&*region.to_ascii_uppercase());
 | 
			
		||||
            }
 | 
			
		||||
            if variant != "" {
 | 
			
		||||
                res.push('-');
 | 
			
		||||
                res.push_str(variant);
 | 
			
		||||
            }
 | 
			
		||||
            if uvariant != "" {
 | 
			
		||||
                res.push_str("-u-va-");
 | 
			
		||||
                res.push_str(uvariant);
 | 
			
		||||
            }
 | 
			
		||||
            return Ok(LanguageRange {
 | 
			
		||||
                language: Cow::Owned(res)
 | 
			
		||||
            });
 | 
			
		||||
        } else if unix_invariant_regex.is_match(s) {
 | 
			
		||||
            return Ok(LanguageRange::invariant())
 | 
			
		||||
        } else {
 | 
			
		||||
            return Err(Error::NotWellFormed);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> AsRef<str> for LanguageRange<'a> {
 | 
			
		||||
    fn as_ref(&self) -> &str {
 | 
			
		||||
        self.language.as_ref()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Locale configuration.
 | 
			
		||||
///
 | 
			
		||||
/// Users may accept several languages in some order of preference and may want to use rules from
 | 
			
		||||
/// different culture for some particular aspect of the program behaviour, and operating systems
 | 
			
		||||
/// allow them to specify this (to various extent).
 | 
			
		||||
///
 | 
			
		||||
/// The `Locale` objects represent the user configuration. They contain:
 | 
			
		||||
///
 | 
			
		||||
///  - The primary `LanguageRange`.
 | 
			
		||||
///  - Optional category-specific overrides.
 | 
			
		||||
///  - Optional fallbacks in case data (usually translations) for the primary language are not
 | 
			
		||||
///    available.
 | 
			
		||||
///
 | 
			
		||||
/// The set of categories is open-ended. The `locale` crate uses five well-known categories
 | 
			
		||||
/// `messages`, `numeric`, `time`, `collate` and `monetary`, but some systems define additional
 | 
			
		||||
/// ones (GNU Linux has additionally `paper`, `name`, `address`, `telephone` and `measurement`) and
 | 
			
		||||
/// these are provided in the user default `Locale` and other libraries can use them.
 | 
			
		||||
///
 | 
			
		||||
/// `Locale` is represented by a `,`-separated sequence of tags in `LanguageRange` syntax, where
 | 
			
		||||
/// all except the first one may be preceded by category name and `=` sign.
 | 
			
		||||
///
 | 
			
		||||
/// The first tag indicates the default locale, the tags prefixed by category names indicate
 | 
			
		||||
/// _overrides_ for those categories and the remaining tags indicate fallbacks.
 | 
			
		||||
///
 | 
			
		||||
/// Note that a syntactically valid value of HTTP `Accept-Language` header is a valid `Locale`. Not
 | 
			
		||||
/// the other way around though due to the presence of category selectors.
 | 
			
		||||
// TODO: Interning
 | 
			
		||||
#[derive(Clone,Debug,Eq,Hash,PartialEq)]
 | 
			
		||||
pub struct Locale {
 | 
			
		||||
    // TODO: Intern the string for performance reasons
 | 
			
		||||
    // XXX: Store pre-split to LanguageTags?
 | 
			
		||||
    inner: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Locale {
 | 
			
		||||
    /// Construct invariant locale.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Invariant locale is represented simply with empty string.
 | 
			
		||||
    pub fn invariant() -> Locale {
 | 
			
		||||
        Locale::from(LanguageRange::invariant())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Append fallback language tag.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Adds fallback to the end of the list.
 | 
			
		||||
    pub fn add(&mut self, tag: &LanguageRange) {
 | 
			
		||||
        for i in self.inner.split(',') {
 | 
			
		||||
            if i == tag.as_ref() {
 | 
			
		||||
                return; // don't add duplicates
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self.inner.push_str(",");
 | 
			
		||||
        self.inner.push_str(tag.as_ref());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Append category override.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Appending new override for a category that already has one will not replace the existing
 | 
			
		||||
    /// override. This might change in future.
 | 
			
		||||
    pub fn add_category(&mut self, category: &str, tag: &LanguageRange) {
 | 
			
		||||
        if self.inner.split(',').next().unwrap() == tag.as_ref() {
 | 
			
		||||
            return; // don't add useless override equal to the primary tag
 | 
			
		||||
        }
 | 
			
		||||
        for i in self.inner.split(',') {
 | 
			
		||||
            if i.starts_with(category) &&
 | 
			
		||||
                    i[category.len()..].starts_with("=") &&
 | 
			
		||||
                    &i[category.len() + 1..] == tag.as_ref() {
 | 
			
		||||
                return; // don't add duplicates
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self.inner.push_str(",");
 | 
			
		||||
        self.inner.push_str(category);
 | 
			
		||||
        self.inner.push_str("=");
 | 
			
		||||
        self.inner.push_str(tag.as_ref());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Iterate over `LanguageRange`s in this `Locale` applicable to given category.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Returns `LanguageRange`s in the `Locale` that are applicable to provided category. The tags
 | 
			
		||||
    /// are returned in order of preference, which means the category-specific ones first and then
 | 
			
		||||
    /// the generic ones.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The iterator is guaranteed to return at least one value.
 | 
			
		||||
    pub fn tags_for<'a, 'c>(&'a self, category: &'c str) -> TagsFor<'a, 'c> {
 | 
			
		||||
        let mut tags = self.inner.split(",");
 | 
			
		||||
        while let Some(s) = tags.clone().next() {
 | 
			
		||||
            if s.starts_with(category) && s[category.len()..].starts_with("=") {
 | 
			
		||||
                return TagsFor {
 | 
			
		||||
                    src: self.inner.as_ref(),
 | 
			
		||||
                    tags: tags,
 | 
			
		||||
                    category: Some(category),
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            tags.next();
 | 
			
		||||
        }
 | 
			
		||||
        return TagsFor {
 | 
			
		||||
            src: self.inner.as_ref(),
 | 
			
		||||
            tags: self.inner.split(","),
 | 
			
		||||
            category: None,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Locale is specified by a string tag. This is the way to access it.
 | 
			
		||||
// FIXME: Do we want to provide the full string representation? We would have it as single string
 | 
			
		||||
// then.
 | 
			
		||||
impl AsRef<str> for Locale {
 | 
			
		||||
    fn as_ref(&self) -> &str {
 | 
			
		||||
        self.inner.as_ref()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> From<LanguageRange<'a>> for Locale {
 | 
			
		||||
    fn from(t: LanguageRange<'a>) -> Locale {
 | 
			
		||||
        Locale {
 | 
			
		||||
            inner: t.language.into_owned(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn tag(s: &str) -> Result<LanguageRange> {
 | 
			
		||||
    LanguageRange::from_unix(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Read /etc/locale.alias
 | 
			
		||||
fn tag_inv(s: &str) -> LanguageRange {
 | 
			
		||||
    tag(s).unwrap_or(LanguageRange::invariant())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn system_locale() -> Option<Locale> {
 | 
			
		||||
    // LC_ALL overrides everything
 | 
			
		||||
    if let Ok(all) = env::var("LC_ALL") {
 | 
			
		||||
        if let Ok(t) = tag(all.as_ref()) {
 | 
			
		||||
            return Some(Locale::from(t));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // LANG is default
 | 
			
		||||
    let mut loc =
 | 
			
		||||
        if let Ok(lang) = env::var("LANG") {
 | 
			
		||||
            Locale::from(tag_inv(lang.as_ref()))
 | 
			
		||||
        } else {
 | 
			
		||||
            Locale::invariant()
 | 
			
		||||
        };
 | 
			
		||||
    // category overrides
 | 
			
		||||
    for &(cat, var) in [
 | 
			
		||||
        ("ctype",       "LC_CTYPE"),
 | 
			
		||||
        ("numeric",     "LC_NUMERIC"),
 | 
			
		||||
        ("time",        "LC_TIME"),
 | 
			
		||||
        ("collate",     "LC_COLLATE"),
 | 
			
		||||
        ("monetary",    "LC_MONETARY"),
 | 
			
		||||
        ("messages",    "LC_MESSAGES"),
 | 
			
		||||
        ("paper",       "LC_PAPER"),
 | 
			
		||||
        ("name",        "LC_NAME"),
 | 
			
		||||
        ("address",     "LC_ADDRESS"),
 | 
			
		||||
        ("telephone",   "LC_TELEPHONE"),
 | 
			
		||||
        ("measurement", "LC_MEASUREMENT"),
 | 
			
		||||
    ].iter() {
 | 
			
		||||
        if let Ok(val) = env::var(var) {
 | 
			
		||||
            if let Ok(tag) = tag(val.as_ref())
 | 
			
		||||
            {
 | 
			
		||||
                loc.add_category(cat, &tag);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // LANGUAGE defines fallbacks
 | 
			
		||||
    if let Ok(langs) = env::var("LANGUAGE") {
 | 
			
		||||
        for i in langs.split(':') {
 | 
			
		||||
            if i != "" {
 | 
			
		||||
                if let Ok(tag) = tag(i) {
 | 
			
		||||
                    loc.add(&tag);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if loc.as_ref() != "" {
 | 
			
		||||
        return Some(loc);
 | 
			
		||||
    } else {
 | 
			
		||||
        return None;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use super::LanguageRange;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn unix_tags() {
 | 
			
		||||
        assert_eq!("cs-CZ", LanguageRange::from_unix("cs_CZ.UTF-8").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("sr-RS-ijekavsk", LanguageRange::from_unix("sr_RS@ijekavian").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("sr-Latn-ijekavsk", LanguageRange::from_unix("sr.UTF-8@ijekavianlatin").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("en-Arab", LanguageRange::from_unix("en@arabic").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("en-Arab", LanguageRange::from_unix("en.UTF-8@arabic").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("de-DE", LanguageRange::from_unix("DE_de.UTF-8@euro").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("ssy-ER", LanguageRange::from_unix("aa_ER@saaho").unwrap().as_ref());
 | 
			
		||||
        assert!(LanguageRange::from_unix("foo_BAR").is_err());
 | 
			
		||||
        assert!(LanguageRange::from_unix("en@arabic.UTF-8").is_err());
 | 
			
		||||
        assert_eq!("", LanguageRange::from_unix("C").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("", LanguageRange::from_unix("C.UTF-8").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("", LanguageRange::from_unix("C.ISO-8859-1").unwrap().as_ref());
 | 
			
		||||
        assert_eq!("", LanguageRange::from_unix("POSIX").unwrap().as_ref());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/main.h
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/main.h
									
									
									
									
									
								
							@ -1,34 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
/// This all wraps https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.channel
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#include "input-method-unstable-v2-client-protocol.h"
 | 
			
		||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
			
		||||
 | 
			
		||||
#include "eek/eek-types.h"
 | 
			
		||||
#include "dbus.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct receiver;
 | 
			
		||||
 | 
			
		||||
/// Wrapped<event_loop::driver::Threaded>
 | 
			
		||||
struct squeek_state_manager;
 | 
			
		||||
 | 
			
		||||
struct submission;
 | 
			
		||||
 | 
			
		||||
struct rsobjects {
 | 
			
		||||
    struct receiver *receiver;
 | 
			
		||||
    struct squeek_state_manager *state_manager;
 | 
			
		||||
    struct submission *submission;
 | 
			
		||||
    struct squeek_wayland *wayland;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void register_ui_loop_handler(struct receiver *receiver, ServerContextService *ui, DBusHandler *dbus_handler);
 | 
			
		||||
 | 
			
		||||
struct rsobjects squeek_init(void);
 | 
			
		||||
 | 
			
		||||
void squeek_state_send_force_visible(struct squeek_state_manager *state);
 | 
			
		||||
void squeek_state_send_force_hidden(struct squeek_state_manager *state);
 | 
			
		||||
 | 
			
		||||
void squeek_state_send_keyboard_present(struct squeek_state_manager *state, uint32_t keyboard_present);
 | 
			
		||||
							
								
								
									
										218
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								src/main.rs
									
									
									
									
									
								
							@ -1,218 +0,0 @@
 | 
			
		||||
/* Copyright (C) 2020,2022 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! Glue for the main loop. */
 | 
			
		||||
use crate::outputs::OutputId;
 | 
			
		||||
use crate::state;
 | 
			
		||||
use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use std::os::raw::c_void;
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
    use std::rc::Rc;
 | 
			
		||||
    use std::time::Instant;
 | 
			
		||||
 | 
			
		||||
    use crate::event_loop::driver;
 | 
			
		||||
    use crate::imservice::IMService;
 | 
			
		||||
    use crate::imservice::c::InputMethod;
 | 
			
		||||
    use crate::outputs::Outputs;
 | 
			
		||||
    use crate::outputs::c::WlOutput;
 | 
			
		||||
    use crate::state;
 | 
			
		||||
    use crate::submission::Submission;
 | 
			
		||||
    use crate::util::c::Wrapped;
 | 
			
		||||
    use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
 | 
			
		||||
    
 | 
			
		||||
    /// ServerContextService*
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    pub struct UIManager(*const c_void);
 | 
			
		||||
    
 | 
			
		||||
    /// DbusHandler*
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    pub struct DBusHandler(*const c_void);
 | 
			
		||||
    
 | 
			
		||||
    /// Holds the Rust structures that are interesting from C.
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    pub struct RsObjects {
 | 
			
		||||
        /// The handle to which Commands should be sent
 | 
			
		||||
        /// for processing in the main loop.
 | 
			
		||||
        receiver: Wrapped<Receiver<Commands>>,
 | 
			
		||||
        state_manager: Wrapped<driver::Threaded>,
 | 
			
		||||
        submission: Wrapped<Submission>,
 | 
			
		||||
        /// Not wrapped, because C needs to access this.
 | 
			
		||||
        wayland: *mut Wayland,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Corresponds to wayland.h::squeek_wayland.
 | 
			
		||||
    /// Fields unused by Rust are marked as generic data types.
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    pub struct Wayland {
 | 
			
		||||
        layer_shell: *const c_void,
 | 
			
		||||
        virtual_keyboard_manager: *const c_void,
 | 
			
		||||
        input_method_manager: *const c_void,
 | 
			
		||||
        outputs: Wrapped<Outputs>,
 | 
			
		||||
        seat: *const c_void,
 | 
			
		||||
        input_method: InputMethod,
 | 
			
		||||
        virtual_keyboard: ZwpVirtualKeyboardV1,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl Wayland {
 | 
			
		||||
        fn new(outputs_manager: Outputs) -> Self {
 | 
			
		||||
            Wayland {
 | 
			
		||||
                layer_shell: ptr::null(),
 | 
			
		||||
                virtual_keyboard_manager: ptr::null(),
 | 
			
		||||
                input_method_manager: ptr::null(),
 | 
			
		||||
                outputs: Wrapped::new(outputs_manager),
 | 
			
		||||
                seat: ptr::null(),
 | 
			
		||||
                input_method: InputMethod::null(),
 | 
			
		||||
                virtual_keyboard: ZwpVirtualKeyboardV1::null(),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    extern "C" {
 | 
			
		||||
        #[allow(improper_ctypes)]
 | 
			
		||||
        fn init_wayland(wayland: *mut Wayland);
 | 
			
		||||
        fn server_context_service_update_keyboard(service: *const UIManager, output: WlOutput, scaled_height: 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,
 | 
			
		||||
        // given that dbus handler is using glib.
 | 
			
		||||
        fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates what's possible in Rust to eliminate as many FFI calls as possible,
 | 
			
		||||
    /// because types aren't getting checked across their boundaries,
 | 
			
		||||
    /// and that leads to suffering.
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_init() -> RsObjects {
 | 
			
		||||
        // Set up channels
 | 
			
		||||
        let (sender, receiver) = MainContext::channel(PRIORITY_DEFAULT);
 | 
			
		||||
        let now = Instant::now();
 | 
			
		||||
        let state_manager = driver::Threaded::new(sender, state::Application::new(now));
 | 
			
		||||
 | 
			
		||||
        let outputs = Outputs::new(state_manager.clone());
 | 
			
		||||
        let mut wayland = Box::new(Wayland::new(outputs));
 | 
			
		||||
        let wayland_raw = &mut *wayland as *mut _;
 | 
			
		||||
        unsafe { init_wayland(wayland_raw); }
 | 
			
		||||
 | 
			
		||||
        let vk = wayland.virtual_keyboard;
 | 
			
		||||
 | 
			
		||||
        let imservice = if wayland.input_method.is_null() {
 | 
			
		||||
            None
 | 
			
		||||
        } else {
 | 
			
		||||
            Some(IMService::new(wayland.input_method, state_manager.clone()))
 | 
			
		||||
        };
 | 
			
		||||
        let submission = Submission::new(vk, imservice);
 | 
			
		||||
        
 | 
			
		||||
        RsObjects {
 | 
			
		||||
            submission: Wrapped::new(submission),
 | 
			
		||||
            state_manager: Wrapped::new(state_manager),
 | 
			
		||||
            receiver: Wrapped::new(receiver),
 | 
			
		||||
            wayland: Box::into_raw(wayland),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Places the UI loop callback in the glib main loop.
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn register_ui_loop_handler(
 | 
			
		||||
        receiver: Wrapped<Receiver<Commands>>,
 | 
			
		||||
        ui_manager: *const UIManager,
 | 
			
		||||
        dbus_handler: *const DBusHandler,
 | 
			
		||||
    ) {
 | 
			
		||||
        let receiver = unsafe { receiver.unwrap() };
 | 
			
		||||
        let receiver = Rc::try_unwrap(receiver).expect("References still present");
 | 
			
		||||
        let receiver = receiver.into_inner();
 | 
			
		||||
        let ctx = MainContext::default();
 | 
			
		||||
        let _acqu = ctx.acquire();
 | 
			
		||||
        receiver.attach(
 | 
			
		||||
            Some(&ctx),
 | 
			
		||||
            move |msg| {
 | 
			
		||||
                main_loop_handle_message(msg, ui_manager, dbus_handler);
 | 
			
		||||
                Continue(true)
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
        #[cfg(not(feature = "glib_v0_14"))]
 | 
			
		||||
        ctx.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// A single iteration of the UI loop.
 | 
			
		||||
    /// Applies state outcomes to external portions of the program.
 | 
			
		||||
    /// This is the outest layer of the imperative shell,
 | 
			
		||||
    /// and doesn't lend itself to testing other than integration.
 | 
			
		||||
    fn main_loop_handle_message(
 | 
			
		||||
        msg: Commands,
 | 
			
		||||
        ui_manager: *const UIManager,
 | 
			
		||||
        dbus_handler: *const DBusHandler,
 | 
			
		||||
    ) {
 | 
			
		||||
        match msg.panel_visibility {
 | 
			
		||||
            Some(PanelCommand::Show { output, height }) => unsafe {
 | 
			
		||||
                server_context_service_update_keyboard(ui_manager, output.0, height.as_scaled_ceiling());
 | 
			
		||||
            },
 | 
			
		||||
            Some(PanelCommand::Hide) => unsafe {
 | 
			
		||||
                server_context_service_real_hide_keyboard(ui_manager);
 | 
			
		||||
            },
 | 
			
		||||
            None => {},
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if let Some(visible) = msg.dbus_visible_set {
 | 
			
		||||
            if dbus_handler != std::ptr::null() {
 | 
			
		||||
                unsafe { dbus_handler_set_visible(dbus_handler, visible as u8) };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let Some(hints) = msg.layout_hint_set {
 | 
			
		||||
            unsafe {
 | 
			
		||||
                server_context_service_set_hint_purpose(
 | 
			
		||||
                    ui_manager,
 | 
			
		||||
                    hints.hint.bits(),
 | 
			
		||||
                    hints.purpose.clone() as u32,
 | 
			
		||||
                )
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// 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, PartialEq, Debug)]
 | 
			
		||||
pub enum PanelCommand {
 | 
			
		||||
    Show {
 | 
			
		||||
        output: OutputId,
 | 
			
		||||
        height: PixelSize,
 | 
			
		||||
    },
 | 
			
		||||
    Hide,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The commands consumed by the main loop,
 | 
			
		||||
/// to be sent out to external components.
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct Commands {
 | 
			
		||||
    pub panel_visibility: Option<PanelCommand>,
 | 
			
		||||
    pub layout_hint_set: Option<state::InputMethodDetails>,
 | 
			
		||||
    pub dbus_visible_set: Option<bool>,
 | 
			
		||||
}
 | 
			
		||||
@ -11,8 +11,7 @@ struct squeek_output_handle {
 | 
			
		||||
 | 
			
		||||
struct squeek_outputs *squeek_outputs_new(void);
 | 
			
		||||
void squeek_outputs_free(struct squeek_outputs*);
 | 
			
		||||
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output, uint32_t id);
 | 
			
		||||
struct wl_output *squeek_outputs_try_unregister(struct squeek_outputs*, uint32_t id);
 | 
			
		||||
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output);
 | 
			
		||||
struct squeek_output_handle squeek_outputs_get_current(struct squeek_outputs*);
 | 
			
		||||
int32_t squeek_outputs_get_perceptual_width(struct squeek_outputs*, struct wl_output *output);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										211
									
								
								src/outputs.rs
									
									
									
									
									
								
							
							
						
						
									
										211
									
								
								src/outputs.rs
									
									
									
									
									
								
							@ -1,11 +1,6 @@
 | 
			
		||||
/* Copyright (C) 2019-2022 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! Managing Wayland outputs */
 | 
			
		||||
 | 
			
		||||
use std::vec::Vec;
 | 
			
		||||
use crate::event_loop;
 | 
			
		||||
use ::logging;
 | 
			
		||||
 | 
			
		||||
// traits
 | 
			
		||||
@ -16,22 +11,15 @@ pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    
 | 
			
		||||
    use std::os::raw::{ c_char, c_void };
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
 | 
			
		||||
    use ::util::c::{COpaquePtr, Wrapped};
 | 
			
		||||
    use ::util::c::COpaquePtr;
 | 
			
		||||
 | 
			
		||||
    // Defined in C
 | 
			
		||||
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    #[derive(Clone, PartialEq, Copy, Debug, Eq, Hash)]
 | 
			
		||||
    #[derive(Clone, PartialEq, Copy)]
 | 
			
		||||
    pub struct WlOutput(*const c_void);
 | 
			
		||||
 | 
			
		||||
    impl WlOutput {
 | 
			
		||||
        fn null() -> Self {
 | 
			
		||||
            Self(ptr::null())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    struct WlOutputListener<T: COpaquePtr> {
 | 
			
		||||
        geometry: extern fn(
 | 
			
		||||
@ -75,7 +63,7 @@ pub mod c {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Map to `wl_output.transform` values
 | 
			
		||||
    #[derive(Clone, Copy, Debug)]
 | 
			
		||||
    #[derive(Clone)]
 | 
			
		||||
    pub enum Transform {
 | 
			
		||||
        Normal = 0,
 | 
			
		||||
        Rotated90 = 1,
 | 
			
		||||
@ -115,13 +103,28 @@ pub mod c {
 | 
			
		||||
        ) -> i32;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Wrapping Outputs is required for calling its methods from C
 | 
			
		||||
    type COutputs = Wrapped<Outputs>;
 | 
			
		||||
    type COutputs = ::util::c::Wrapped<Outputs>;
 | 
			
		||||
 | 
			
		||||
    /// A stable reference to an output.
 | 
			
		||||
    #[derive(Clone)]
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    pub struct OutputHandle {
 | 
			
		||||
        wl_output: WlOutput,
 | 
			
		||||
        outputs: COutputs,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl OutputHandle {
 | 
			
		||||
        // Cannot return an Output reference
 | 
			
		||||
        // because COutputs is too deeply wrapped
 | 
			
		||||
        pub fn get_state(&self) -> Option<OutputState> {
 | 
			
		||||
            let outputs = self.outputs.clone_ref();
 | 
			
		||||
            let outputs = outputs.borrow();
 | 
			
		||||
            find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Defined in Rust
 | 
			
		||||
 | 
			
		||||
    // Callbacks from the output listener follow
 | 
			
		||||
 | 
			
		||||
    extern fn outputs_handle_geometry(
 | 
			
		||||
        outputs: COutputs,
 | 
			
		||||
        wl_output: WlOutput,
 | 
			
		||||
@ -140,8 +143,7 @@ pub mod c {
 | 
			
		||||
        let outputs = outputs.clone_ref();
 | 
			
		||||
        let mut collection = outputs.borrow_mut();
 | 
			
		||||
        let output_state: Option<&mut OutputState>
 | 
			
		||||
            = collection
 | 
			
		||||
                .find_output_mut(wl_output)
 | 
			
		||||
            = find_output_mut(&mut collection, wl_output)
 | 
			
		||||
                .map(|o| &mut o.pending);
 | 
			
		||||
        match output_state {
 | 
			
		||||
            Some(state) => { state.transform = Some(transform) },
 | 
			
		||||
@ -169,8 +171,7 @@ pub mod c {
 | 
			
		||||
        let outputs = outputs.clone_ref();
 | 
			
		||||
        let mut collection = outputs.borrow_mut();
 | 
			
		||||
        let output_state: Option<&mut OutputState>
 | 
			
		||||
            = collection
 | 
			
		||||
                .find_output_mut(wl_output)
 | 
			
		||||
            = find_output_mut(&mut collection, wl_output)
 | 
			
		||||
                .map(|o| &mut o.pending);
 | 
			
		||||
        match output_state {
 | 
			
		||||
            Some(state) => {
 | 
			
		||||
@ -191,27 +192,14 @@ pub mod c {
 | 
			
		||||
    ) {
 | 
			
		||||
        let outputs = outputs.clone_ref();
 | 
			
		||||
        let mut collection = outputs.borrow_mut();
 | 
			
		||||
        let output = collection
 | 
			
		||||
            .find_output_mut(wl_output);
 | 
			
		||||
        let event = match output {
 | 
			
		||||
            Some(output) => {
 | 
			
		||||
                output.current = output.pending.clone();
 | 
			
		||||
                Some(Event {
 | 
			
		||||
                    output: OutputId(wl_output),
 | 
			
		||||
                    change: ChangeType::Altered(output.current),
 | 
			
		||||
                })
 | 
			
		||||
            },
 | 
			
		||||
            None => {
 | 
			
		||||
                log_print!(
 | 
			
		||||
        let output = find_output_mut(&mut collection, wl_output);
 | 
			
		||||
        match output {
 | 
			
		||||
            Some(output) => { output.current = output.pending.clone(); }
 | 
			
		||||
            None => log_print!(
 | 
			
		||||
                logging::Level::Warning,
 | 
			
		||||
                "Got done on unknown output",
 | 
			
		||||
                );
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
            ),
 | 
			
		||||
        };
 | 
			
		||||
        if let Some(event) = event {
 | 
			
		||||
            collection.send_event(event);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extern fn outputs_handle_scale(
 | 
			
		||||
@ -222,8 +210,7 @@ pub mod c {
 | 
			
		||||
        let outputs = outputs.clone_ref();
 | 
			
		||||
        let mut collection = outputs.borrow_mut();
 | 
			
		||||
        let output_state: Option<&mut OutputState>
 | 
			
		||||
            = collection
 | 
			
		||||
                .find_output_mut(wl_output)
 | 
			
		||||
            = find_output_mut(&mut collection, wl_output)
 | 
			
		||||
                .map(|o| &mut o.pending);
 | 
			
		||||
        match output_state {
 | 
			
		||||
            Some(state) => { state.scale = factor; }
 | 
			
		||||
@ -234,7 +221,11 @@ pub mod c {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // End callbacks
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_outputs_new() -> COutputs {
 | 
			
		||||
        COutputs::new(Outputs { outputs: Vec::new() })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
@ -244,17 +235,14 @@ pub mod c {
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_outputs_register(raw_collection: COutputs, output: WlOutput, id: u32) {
 | 
			
		||||
    fn squeek_outputs_register(raw_collection: COutputs, output: WlOutput) {
 | 
			
		||||
        let collection = raw_collection.clone_ref();
 | 
			
		||||
        let mut collection = collection.borrow_mut();
 | 
			
		||||
        collection.outputs.push((
 | 
			
		||||
            Output {
 | 
			
		||||
        collection.outputs.push(Output {
 | 
			
		||||
            output: output.clone(),
 | 
			
		||||
            pending: OutputState::uninitialized(),
 | 
			
		||||
            current: OutputState::uninitialized(),
 | 
			
		||||
            },
 | 
			
		||||
            id,
 | 
			
		||||
        ));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        unsafe { squeek_output_add_listener(
 | 
			
		||||
            output,
 | 
			
		||||
@ -268,22 +256,40 @@ pub mod c {
 | 
			
		||||
        )};
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// This will try to unregister the output, if the id matches a registered one.
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_outputs_try_unregister(raw_collection: COutputs, id: u32) -> WlOutput {
 | 
			
		||||
    fn squeek_outputs_get_current(raw_collection: COutputs) -> OutputHandle {
 | 
			
		||||
        let collection = raw_collection.clone_ref();
 | 
			
		||||
        let mut collection = collection.borrow_mut();
 | 
			
		||||
        collection.remove_output_by_global(id)
 | 
			
		||||
            .map_err(|e| log_print!(
 | 
			
		||||
                logging::Level::Debug,
 | 
			
		||||
                "Tried to remove global {:x} but it is not registered as an output: {:?}",
 | 
			
		||||
                id, e,
 | 
			
		||||
            ))
 | 
			
		||||
            .unwrap_or(WlOutput::null())
 | 
			
		||||
        let collection = collection.borrow();
 | 
			
		||||
        OutputHandle {
 | 
			
		||||
            wl_output: collection.outputs[0].output.clone(),
 | 
			
		||||
            outputs: raw_collection.clone(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: handle unregistration
 | 
			
		||||
    
 | 
			
		||||
    fn find_output(
 | 
			
		||||
        collection: &Outputs,
 | 
			
		||||
        wl_output: WlOutput,
 | 
			
		||||
    ) -> Option<&Output> {
 | 
			
		||||
        collection.outputs
 | 
			
		||||
            .iter()
 | 
			
		||||
            .find_map(|o|
 | 
			
		||||
                if o.output == wl_output { Some(o) } else { None }
 | 
			
		||||
            )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn find_output_mut(
 | 
			
		||||
        collection: &mut Outputs,
 | 
			
		||||
        wl_output: WlOutput,
 | 
			
		||||
    ) -> Option<&mut Output> {
 | 
			
		||||
        collection.outputs
 | 
			
		||||
            .iter_mut()
 | 
			
		||||
            .find_map(|o|
 | 
			
		||||
                if o.output == wl_output { Some(o) } else { None }
 | 
			
		||||
            )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Generic size
 | 
			
		||||
@ -294,16 +300,16 @@ pub struct Size {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// wl_output mode
 | 
			
		||||
#[derive(Clone, Copy, Debug)]
 | 
			
		||||
pub struct Mode {
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
struct Mode {
 | 
			
		||||
    width: i32,
 | 
			
		||||
    height: i32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Copy, Debug)]
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct OutputState {
 | 
			
		||||
    pub current_mode: Option<Mode>,
 | 
			
		||||
    pub transform: Option<c::Transform>,
 | 
			
		||||
    current_mode: Option<Mode>,
 | 
			
		||||
    transform: Option<c::Transform>,
 | 
			
		||||
    pub scale: i32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -349,83 +355,12 @@ impl OutputState {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Not guaranteed to exist,
 | 
			
		||||
/// but can be used to look up state.
 | 
			
		||||
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash)]
 | 
			
		||||
pub struct OutputId(pub c::WlOutput);
 | 
			
		||||
 | 
			
		||||
// WlOutput is a pointer,
 | 
			
		||||
// but in the public interface,
 | 
			
		||||
// we're only using it as a lookup key.
 | 
			
		||||
unsafe impl Send for OutputId {}
 | 
			
		||||
 | 
			
		||||
struct Output {
 | 
			
		||||
pub struct Output {
 | 
			
		||||
    output: c::WlOutput,
 | 
			
		||||
    pending: OutputState,
 | 
			
		||||
    current: OutputState,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct NotFound;
 | 
			
		||||
 | 
			
		||||
/// Wayland global ID type
 | 
			
		||||
type GlobalId = u32;
 | 
			
		||||
 | 
			
		||||
/// The outputs manager
 | 
			
		||||
pub struct Outputs {
 | 
			
		||||
    outputs: Vec<(Output, GlobalId)>,
 | 
			
		||||
    sender: event_loop::driver::Threaded,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Outputs {
 | 
			
		||||
    pub fn new(sender: event_loop::driver::Threaded) -> Outputs {
 | 
			
		||||
        Outputs {
 | 
			
		||||
            outputs: Vec::new(),
 | 
			
		||||
            sender,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn send_event(&self, event: Event) {
 | 
			
		||||
        self.sender.send(event.into()).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_output_by_global(&mut self, id: GlobalId)
 | 
			
		||||
        -> Result<c::WlOutput, NotFound>
 | 
			
		||||
    {
 | 
			
		||||
        let index = self.outputs.iter()
 | 
			
		||||
            .position(|(_o, global_id)| *global_id == id);
 | 
			
		||||
        if let Some(index) = index {
 | 
			
		||||
            let (output, _id) = self.outputs.remove(index);
 | 
			
		||||
            self.send_event(Event {
 | 
			
		||||
                change: ChangeType::Removed,
 | 
			
		||||
                output: OutputId(output.output),
 | 
			
		||||
            });
 | 
			
		||||
            Ok(output.output)
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(NotFound)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn find_output_mut(&mut self, wl_output: c::WlOutput)
 | 
			
		||||
        -> Option<&mut Output>
 | 
			
		||||
    {
 | 
			
		||||
        self.outputs
 | 
			
		||||
            .iter_mut()
 | 
			
		||||
            .find_map(|(o, _global)|
 | 
			
		||||
                if o.output == wl_output { Some(o) } else { None }
 | 
			
		||||
            )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Copy, Debug)]
 | 
			
		||||
pub enum ChangeType {
 | 
			
		||||
    /// Added or changed
 | 
			
		||||
    Altered(OutputState),
 | 
			
		||||
    Removed,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Copy, Debug)]
 | 
			
		||||
pub struct Event {
 | 
			
		||||
    pub output: OutputId,
 | 
			
		||||
    pub change: ChangeType,
 | 
			
		||||
    outputs: Vec<Output>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user