Compare commits

..

1 Commits

Author SHA1 Message Date
914c5d4940 text input: Reset hints when text input gone
This ensures that when the keyboard is force brought up next time, the user is not stuck with an overlay they can't switch.

As a downside, there's a blink of default hint before the keyboard hides.
2020-12-15 12:50:47 +00:00
49 changed files with 364 additions and 1737 deletions

44
Cargo.lock generated
View File

@ -59,9 +59,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.66"
version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
[[package]]
name = "clap"
@ -76,9 +76,9 @@ dependencies = [
[[package]]
name = "dtoa"
version = "0.4.7"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]]
name = "fragile"
@ -265,15 +265,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.82"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "linked-hash-map"
version = "0.5.4"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]]
name = "maplit"
@ -335,9 +335,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.8"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
@ -353,9 +353,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.22"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]]
name = "rs"
@ -380,18 +380,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.118"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.118"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
dependencies = [
"proc-macro2",
"quote",
@ -400,9 +400,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
version = "0.8.15"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "971be8f6e4d4a47163b405a3df70d14359186f9ab0f3a3ec37df144ca1ce089f"
checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
dependencies = [
"dtoa",
"linked-hash-map",
@ -412,9 +412,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.58"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [
"proc-macro2",
"quote",
@ -476,9 +476,9 @@ dependencies = [
[[package]]
name = "yaml-rust"
version = "0.4.5"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
dependencies = [
"linked-hash-map",
]

View File

@ -1,87 +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 ? 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 show_eschars preferences space ¿ period Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # € % & - _ + ( )"
- "show_symbols , \" ' colon ; ! = BackSpace"
- "show_letters show_eschars preferences space ? period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ $ ¥ ^ ° * { }"
- "show_numbers \\ / < > = [ ] BackSpace"
- "show_letters show_eschars preferences space ? period Return"
eschars:
- "á é í ó ú Á É Í Ó Ú"
- "à è ì ò ù À È Ì Ò Ù"
- "show_numbers ü ç ï Ü Ç Ï ¡ BackSpace"
- "show_letters show_eschars preferences space « » Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
preferences:
action: "show_prefs"
outline: "default"
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: "àÀ"
period:
outline: "default"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "altline"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -1,71 +0,0 @@
---
outlines:
default: { width: 40, height: 60 }
altline: { width: 56, height: 60 }
wide: { width: 62, height: 60 }
spaceline: { width: 142, height: 60 }
special: { width: 44, height: 60 }
views:
base:
- "' - ק ר א ט ו ן ם פ"
- "ש ד ג כ ע י ח ל ך ף"
- ס ב ה נ מ צ ת ץ BackSpace"
- "show_numbers comma preferences space period Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # ₪ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € $ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
buttons:
BackSpace:
outline: "default"
icon: "edit-clear-symbolic"
action: erase
comma:
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: ":"

View File

@ -1,78 +0,0 @@
---
outlines:
default: { width: 35.33, height: 52 }
altline: { width: 52.67, height: 52 }
wide: { width: 62, height: 52 }
spaceline: { width: 142, height: 52 }
special: { width: 44, height: 52 }
views:
base:
- "ض ص ق ف غ ع ه خ ح ج"
- "ش س ی ب ل ا ت ن م ک"
- "Shift_L ظ ط ز ر ذ د و BackSpace"
- "show_numbers preferences space period Return"
upper:
- "پ { } [ ] ّ َ ِ ُ چ"
- "ؤ‌ ئ ي‌ إ أ آ ة‌ » « گ"
- "Shift_L ك ٓ ژ ء > < ؟ BackSpace"
- "show_numbers preferences space period Return"
numbers:
- "۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰"
- "@ # ﷼ % & - _ + ( )"
- "show_symbols , \" ' colon ؛ ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
preferences:
action: show_prefs
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_numbers_from_symbols:
action:
set_view: "numbers"
outline: "altline"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ABC"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
period:
outline: "special"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -1,78 +0,0 @@
---
outlines:
default: { width: 54, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 108, height: 42 }
spaceline: { width: 216, height: 42 }
special: { width: 54, height: 42 }
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"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_numbers_from_symbols:
action:
set_view: "numbers"
outline: "altline"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ABC"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
".":
outline: "special"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -22,7 +22,7 @@ views:
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # € % & - _ + ( )"
- "show_symbols , \" ' : ; ! = BackSpace"
- "show_symbols , \" ' colon ; ! = BackSpace"
- "show_letters show_eschars preferences space ? . Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
@ -86,4 +86,7 @@ buttons:
outline: "altline"
icon: "key-enter"
keysym: "Return"
colon:
label: ":"
"\"":
keysym: "quotedbl"

View File

@ -22,7 +22,7 @@ views:
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # € % & - _ + ( )"
- "show_symbols , \" ' : ; ! ? BackSpace"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters show_eschars preferences space ? . Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
@ -84,4 +84,7 @@ buttons:
outline: "altline"
icon: "key-enter"
keysym: "Return"
colon:
label: ":"
"\"":
keysym: "quotedbl"

View File

@ -52,8 +52,6 @@ buttons:
locking:
lock_view: "upper_accents"
unlock_view: "accents"
looks_locked_from:
- "upper"
outline: "altline"
icon: "key-shift"
BackSpace:
@ -96,8 +94,6 @@ buttons:
locking:
lock_view: "upper_accents"
unlock_view: "upper"
looks_locked_from:
- "accents"
outline: "altline"
label: "ĄĘ"
period:

View File

@ -1,84 +0,0 @@
---
outlines:
default: { width: 75, height: 56 }
altline: { width: 75, height: 56 }
wide: { width: 135, height: 56 }
spaceline: { width: 450, height: 56 }
spacelinesymbol: { width: 300, height: 56 }
special: { width: 90, height: 56 }
views:
base:
- "ๅ / _ ภ ถ ุ ึ ค ต จ ข ช"
- "ๆ ไ ำ พ ะ ั ี ร น ย บ ล"
- "ฟ ห ก ด เ ้ ่ า ส ว ง ฃ"
- "Shift_L ผ ป แ อ ิ ื ท ม ใ ฝ BackSpace"
- "show_numbers preferences space period Return"
upper:
- "+ ๑ ๒ ๓ ๔ ู ฿ ๕ ๖ ๗ ๘ ๙"
- " \" ฎ ฑ ธ ํ ๊ ณ ฯ ญ ฐ ,"
- "ฤ ฆ ฏ โ ฌ ็ ๋ ษ ศ ซ . ฅ"
- "Shift_L ( ) ฉ ฮ ฺ ์ ? ฒ ฬ ฦ BackSpace"
- "show_numbers preferences space period Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # $ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences spacesymbol period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences spacesymbol 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: " "
spacesymbol:
outline: "spacelinesymbol"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -1,78 +0,0 @@
---
outlines:
default: { width: 54, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 108, height: 42 }
spaceline: { width: 216, height: 42 }
special: { width: 54, height: 42 }
views:
base:
- "q w f p g j l u y"
- "a r s t d h n e i o"
- "Shift_L z x c v b k m BackSpace"
- "show_numbers preferences space . Return"
upper:
- "Q W F P G J L U Y"
- "A R S T D H N E I O"
- "Shift_L Z X C V B K M BackSpace"
- "show_numbers preferences space . 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: "*/="
".":
outline: "special"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -1,89 +0,0 @@
---
outlines:
default: { width: 35.33, height: 52 }
altline: { width: 52.67, height: 52 }
wide: { width: 62, height: 52 }
spaceline: { width: 142, height: 52 }
special: { width: 44, height: 52 }
views:
base:
- "Shift_L p y f g c r l BackSpace"
- "a o e u i d h t n s"
- ", q j k x b m w v z"
- "show_numbers preferences space period Return"
upper:
- "Shift_L P Y F G C R L BackSpace"
- "A O E U I D H T N S"
- ", Q J K X B M W V Z"
- "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: "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: ":"
# The US QWERTY layout has fewer letters on the third row, and so has
# the shift & backspace keys placed there. In contrast, the US DVORAK
# layout has fewer letters on the first row, which makes it a good
# choice for the shift & backspace keys. That leads to what may be,
# for many people, an unexpected layout in numbers mode: the numerals
# are on the third row (not the first) so that the backspace key
# remains in a consistent location regardless of mode, without
# sacrificing key width. (Once could argue that in numbers mode, the
# numerals should be closer to the enter key.) As with any keyboard
# layout, familiarity comes with repeated use.

View File

@ -1,89 +0,0 @@
---
outlines:
default: { width: 54, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 108, height: 42 }
spaceline: { width: 216, height: 42 }
special: { width: 54, height: 42 }
views:
base:
- "Shift_L p y f g c r l BackSpace"
- "a o e u i d h t n s"
- ", q j k x b m w v z"
- "show_numbers preferences space period Return"
upper:
- "Shift_L P Y F G C R L BackSpace"
- "A O E U I D H T N S"
- ", Q J K X B M W V Z"
- "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: "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: ":"
# The US QWERTY layout has fewer letters on the third row, and so has
# the shift & backspace keys placed there. In contrast, the US DVORAK
# layout has fewer letters on the first row, which makes it a good
# choice for the shift & backspace keys. That leads to what may be,
# for many people, an unexpected layout in numbers mode: the numerals
# are on the third row (not the first) so that the backspace key
# remains in a consistent location regardless of mode, without
# sacrificing key width. (Once could argue that in numbers mode, the
# numerals should be closer to the enter key.) As with any keyboard
# layout, familiarity comes with repeated use.

View File

@ -1,2 +0,0 @@
emoji ایموجی
terminal ترمینال

View File

@ -1,19 +0,0 @@
be בלגית
br פורטוגזית (ברזיל)
cz צ'כית
de גרמנית
dk דנית
es ספרדית
emoji אימוג'י
fi פינית
fr צרפתית
gr יוונית
il עברית
it איטלקית
no נורווגית
pl פולנית
ru רוסית
se שוודית
terminal טרמינל
ua אוקראינית
us אנגלית (ארה"ב)

View File

@ -31,14 +31,9 @@ sq_button.wide {
border-color: #3e3a44;
}
sq_button.latched {
background: #ffffff;
color: #2b292f;
}
sq_button.locked {
background: #ffffff;
color: #1c71d8;
color: #2b292f;
}
sq_button.action {

View File

@ -34,14 +34,9 @@ sq_button.wide {
border-color: @borders; /* #3e3a44; */
}
sq_button.latched {
background: @theme_fg_color; /*#ffffff;*/
color: @theme_bg_color; /*#2b292f;*/
}
sq_button.locked {
background: @theme_fg_color; /*#ffffff;*/
color: mix(@theme_selected_bg_color, @theme_bg_color, 0.4); /*#2b292f;*/
color: @theme_bg_color; /*#2b292f;*/
}
sq_button.action {

60
debian/changelog vendored
View File

@ -1,63 +1,3 @@
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
[ 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 ]

View File

@ -5,7 +5,6 @@ Feed it the first changelog line, and then all available tags.
"""
import re, sys
version = re.findall("\\((.*)\\)", input())[0]
tag = 'v' + re.findall("([0-9]+\\.[0-9]+\\.[0-9]+).*", version)[0]
tag = "v" + re.findall("\\((.*)\\)", input())[0]
if tag not in map(str.strip, sys.stdin.readlines()):
raise Exception("Changelog's current version doesn't have a tag. Push the tag!")

2
debian/compat vendored
View File

@ -1 +1 @@
12
10

1
debian/control vendored
View File

@ -41,7 +41,6 @@ Depends:
${misc:Depends},
Breaks:
librem5-base (<< 24),
phosh (<= 0.10),
Description: On-screen keyboard for Wayland
Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone.

View File

@ -1,2 +1,2 @@
tools/squeekboard-restyled usr/bin
usr/bin/squeekboard /usr/bin
usr/share/applications/sm.puri.Squeekboard.desktop

View File

@ -1,16 +0,0 @@
[Unit]
Description=Squeekboard - a Wayland virtual keyboard
PartOf=graphical-session.target
# Don't stop restarting the program
StartLimitIntervalSec=0
[Service]
Environment="GTK_THEME=Adwaita:dark"
ExecStart=/usr/bin/squeekboard
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=graphical-session.target

View File

@ -45,8 +45,6 @@
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer; // owned, nullable
struct render_geometry render_geometry; // mutable
EekboardContextService *eekboard_context; // unowned reference
struct submission *submission; // unowned reference
@ -74,23 +72,12 @@ eek_gtk_keyboard_real_realize (GtkWidget *self)
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->realize (self);
}
static void set_allocation_size(EekGtkKeyboard *gtk_keyboard,
struct squeek_layout *layout, gdouble width, gdouble height)
{
// This is where size-dependent surfaces would be released
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (gtk_keyboard);
priv->render_geometry = eek_render_geometry_from_allocation_size(
layout, width, height);
}
static gboolean
eek_gtk_keyboard_real_draw (GtkWidget *self,
cairo_t *cr)
{
EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self);
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (keyboard);
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
gtk_widget_get_allocation (self, &allocation);
@ -105,14 +92,15 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
priv->keyboard,
pcontext);
set_allocation_size (keyboard, priv->keyboard->layout,
allocation.width, allocation.height);
eek_renderer_set_allocation_size (priv->renderer,
priv->keyboard->layout,
allocation.width,
allocation.height);
eek_renderer_set_scale_factor (priv->renderer,
gtk_widget_get_scale_factor (self));
}
eek_renderer_render_keyboard (priv->renderer, priv->render_geometry,
priv->submission, cr, priv->keyboard);
eek_renderer_render_keyboard (priv->renderer, priv->submission, cr, priv->keyboard);
return FALSE;
}
@ -129,9 +117,8 @@ static void
eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
GtkAllocation *allocation)
{
EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self);
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (keyboard);
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
// check if the change would switch types
enum squeek_arrangement_kind new_type = get_type(
(uint32_t)(allocation->width - allocation->x),
@ -143,8 +130,10 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
}
if (priv->renderer) {
set_allocation_size (keyboard, priv->keyboard->layout,
allocation->width, allocation->height);
eek_renderer_set_allocation_size (priv->renderer,
priv->keyboard->layout,
allocation->width,
allocation->height);
}
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
@ -173,7 +162,7 @@ static void depress(EekGtkKeyboard *self,
}
squeek_layout_depress(priv->keyboard->layout,
priv->submission,
x, y, priv->render_geometry.widget_to_layout, time, self);
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
}
static void drag(EekGtkKeyboard *self,
@ -185,7 +174,7 @@ static void drag(EekGtkKeyboard *self,
}
squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
priv->submission,
x, y, priv->render_geometry.widget_to_layout, time,
x, y, eek_renderer_get_transformation(priv->renderer), time,
priv->eekboard_context, self);
}
@ -196,7 +185,8 @@ static void release(EekGtkKeyboard *self, guint32 time)
return;
}
squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
priv->submission, priv->render_geometry.widget_to_layout, time,
priv->submission,
eek_renderer_get_transformation(priv->renderer), time,
priv->eekboard_context, self);
}
@ -406,24 +396,6 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice,
priv->submission = submission;
priv->layout = layout;
priv->renderer = NULL;
// This should really be done on initialization.
// Before the widget is allocated,
// we don't really know what geometry it takes.
// When it's off the screen, we also kinda don't.
struct render_geometry initial_geometry = {
// Set to 100 just to make sure if there's any attempt to use it,
// it actually gives plausible results instead of blowing up,
// e.g. on zero division.
.allocation_width = 100,
.allocation_height = 100,
.widget_to_layout = {
.origin_x = 0,
.origin_y = 0,
.scale = 1,
},
};
priv->render_geometry = initial_geometry;
g_signal_connect (eekservice,
"notify::keyboard",
G_CALLBACK(on_notify_keyboard),

View File

@ -28,7 +28,6 @@
#include <glib.h>
#include <gtk/gtk.h>
#include "eek/eek-renderer.h"
#include "eek/eek-types.h"
struct submission;

View File

@ -18,6 +18,8 @@
* 02110-1301 USA
*/
#include "config.h"
#include <math.h>
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@ -31,6 +33,10 @@
static void render_button_label (cairo_t *cr, GtkStyleContext *ctx,
const gchar *label, EekBounds bounds);
void eek_render_button (EekRenderer *self,
cairo_t *cr, const struct squeek_button *button,
gboolean pressed, gboolean locked);
static void
render_outline (cairo_t *cr,
GtkStyleContext *ctx,
@ -54,21 +60,21 @@ render_outline (cairo_t *cr,
position.x, position.y, position.width, position.height);
}
/// Rust interface
void eek_render_button_in_context(uint32_t scale_factor,
static void render_button_in_context(gint scale_factor,
cairo_t *cr,
GtkStyleContext *ctx,
EekBounds bounds,
const char *icon_name,
const gchar *label) {
const struct squeek_button *button) {
/* blank background */
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
cairo_paint (cr);
EekBounds bounds = squeek_button_get_bounds(button);
render_outline (cr, ctx, bounds);
cairo_paint (cr);
/* render icon (if any) */
const char *icon_name = squeek_button_get_icon_name(button);
if (icon_name) {
cairo_surface_t *icon_surface =
eek_renderer_get_icon_surface (icon_name, 16, scale_factor);
@ -98,27 +104,25 @@ void eek_render_button_in_context(uint32_t scale_factor,
}
}
const gchar *label = squeek_button_get_label(button);
if (label) {
render_button_label (cr, ctx, label, bounds);
render_button_label (cr, ctx, label, squeek_button_get_bounds(button));
}
}
/// Prepare context for drawing the button.
/// The context MUST be released using the corresponing "put" procedure
/// before drawing the next button.
/// Interface for Rust.
GtkStyleContext *
eek_get_style_context_for_button (EekRenderer *self,
const char *name,
const char *outline_name,
const char *locked_class,
uint64_t pressed)
void
eek_render_button (EekRenderer *self,
cairo_t *cr,
const struct squeek_button *button,
gboolean pressed,
gboolean locked)
{
GtkStyleContext *ctx = self->button_context;
/* Set the name of the button on the widget path, using the name obtained
from the button's symbol. */
g_autoptr (GtkWidgetPath) path = NULL;
path = gtk_widget_path_copy (gtk_style_context_get_path (ctx));
const char *name = squeek_button_get_name(button);
gtk_widget_path_iter_set_name (path, -1, name);
/* Update the style context with the updated widget path. */
@ -127,22 +131,19 @@ eek_get_style_context_for_button (EekRenderer *self,
(pressed) or normal. */
gtk_style_context_set_state(ctx,
pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
if (locked_class) {
gtk_style_context_add_class(ctx, locked_class);
const char *outline_name = squeek_button_get_outline_name(button);
if (locked) {
gtk_style_context_add_class(ctx, "locked");
}
gtk_style_context_add_class(ctx, outline_name);
return ctx;
}
/// Interface for Rust.
void eek_put_style_context_for_button(GtkStyleContext *ctx,
const char *outline_name,
const char *locked_class) {
render_button_in_context(self->scale_factor, cr, ctx, button);
// Save and restore functions don't work if gtk_render_* was used in between
gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
gtk_style_context_remove_class(ctx, outline_name);
if (locked_class) {
gtk_style_context_remove_class(ctx, locked_class);
if (locked) {
gtk_style_context_remove_class(ctx, "locked");
}
}
@ -193,23 +194,22 @@ render_button_label (cairo_t *cr,
// FIXME: Pass just the active modifiers instead of entire submission
void
eek_renderer_render_keyboard (EekRenderer *self,
struct render_geometry geometry,
struct submission *submission,
cairo_t *cr,
LevelKeyboard *keyboard)
{
g_return_if_fail (geometry.allocation_width > 0.0);
g_return_if_fail (geometry.allocation_height > 0.0);
g_return_if_fail (self->allocation_width > 0.0);
g_return_if_fail (self->allocation_height > 0.0);
/* Paint the background covering the entire widget area */
gtk_render_background (self->view_context,
cr,
0, 0,
geometry.allocation_width, geometry.allocation_height);
self->allocation_width, self->allocation_height);
cairo_save(cr);
cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y);
cairo_scale (cr, geometry.widget_to_layout.scale, geometry.widget_to_layout.scale);
cairo_translate (cr, self->widget_to_layout.origin_x, self->widget_to_layout.origin_y);
cairo_scale (cr, self->widget_to_layout.scale, self->widget_to_layout.scale);
squeek_draw_layout_base_view(keyboard->layout, self, cr);
squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission);
@ -261,6 +261,8 @@ static void
renderer_init (EekRenderer *self)
{
self->pcontext = NULL;
self->allocation_width = 0.0;
self->allocation_height = 0.0;
self->scale_factor = 1;
self->css_provider = squeek_load_style();
@ -307,18 +309,22 @@ eek_renderer_new (LevelKeyboard *keyboard,
return renderer;
}
struct render_geometry
eek_render_geometry_from_allocation_size (struct squeek_layout *layout,
void
eek_renderer_set_allocation_size (EekRenderer *renderer,
struct squeek_layout *layout,
gdouble width,
gdouble height)
{
struct render_geometry ret = {
.allocation_width = width,
.allocation_height = height,
.widget_to_layout = squeek_layout_calculate_transformation(
layout, width, height),
};
return ret;
g_return_if_fail (width > 0.0 && height > 0.0);
renderer->allocation_width = width;
renderer->allocation_height = height;
renderer->widget_to_layout = squeek_layout_calculate_transformation(
layout,
renderer->allocation_width, renderer->allocation_height);
// This is where size-dependent surfaces would be released
}
void
@ -327,11 +333,6 @@ eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale)
renderer->scale_factor = scale;
}
/// Rust interface.
uint32_t eek_renderer_get_scale_factor(EekRenderer *renderer) {
return renderer->scale_factor;
}
cairo_surface_t *
eek_renderer_get_icon_surface (const gchar *icon_name,
gint size,
@ -355,3 +356,8 @@ eek_renderer_get_icon_surface (const gchar *icon_name,
}
return surface;
}
struct transformation
eek_renderer_get_transformation (EekRenderer *renderer) {
return renderer->widget_to_layout;
}

View File

@ -41,23 +41,22 @@ typedef struct EekRenderer
gchar *extra_style; // owned
// Mutable state
gint scale_factor; /* the outputs scale factor */
} EekRenderer;
/// Mutable part of the renderer state.
/// TODO: Possibly should include scale factor.
struct render_geometry {
/// Background extents
gdouble allocation_width;
gdouble allocation_height;
gint scale_factor; /* the outputs scale factor */
/// Coords transformation
struct transformation widget_to_layout;
};
} EekRenderer;
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer, struct squeek_layout *layout,
gdouble width,
gdouble height);
void eek_renderer_set_scale_factor (EekRenderer *renderer,
gint scale);
@ -65,14 +64,13 @@ cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name,
gint size,
gint scale);
void eek_renderer_render_keyboard (EekRenderer *renderer, struct render_geometry geometry, struct submission *submission,
void eek_renderer_render_keyboard (EekRenderer *renderer, struct submission *submission,
cairo_t *cr, LevelKeyboard *keyboard);
void
eek_renderer_free (EekRenderer *self);
struct render_geometry
eek_render_geometry_from_allocation_size (struct squeek_layout *layout,
gdouble width, gdouble height);
struct transformation
eek_renderer_get_transformation (EekRenderer *renderer);
G_END_DECLS
#endif /* EEK_RENDERER_H */

View File

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

View File

@ -1,7 +1,7 @@
project(
'squeekboard',
'c', 'rust',
version: '1.12.0',
version: '1.10.0',
license: 'GPLv3',
meson_version: '>=0.51.0',
default_options: [

View File

@ -294,8 +294,8 @@
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 on that object.
When the compositor receives a commit request with a serial different than
equal to the number of commit requests already issued on that object.
When the compositor receives a done event 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.

View File

@ -10,14 +10,13 @@ pub struct KeySym(pub String);
type View = String;
/// Use to send modified keypresses
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Modifier {
/// Control and Alt are the only modifiers
/// which doesn't interfere with levels,
/// so it's simple to implement as levels are deprecated in squeekboard.
Control,
Alt,
Mod4,
}
/// Action to perform on the keypress and, in reverse, on keyrelease
@ -30,11 +29,6 @@ pub enum Action {
lock: View,
/// When unlocked by pressing it or emitting a key
unlock: View,
/// Whether key has a latched state
/// that pops when another key is pressed.
latches: bool,
/// Should take on *locked* appearance whenever latch comes back to those views.
looks_locked_from: Vec<View>,
},
/// Hold this modifier for as long as the button is pressed
ApplyModifier(Modifier),
@ -54,24 +48,14 @@ pub enum Action {
impl Action {
pub fn is_locked(&self, view_name: &str) -> bool {
match self {
Action::LockView { lock, unlock: _, latches: _, looks_locked_from: _ } => lock == view_name,
_ => false,
}
}
pub fn has_locked_appearance_from(&self, locked_view_name: &str) -> bool {
match self {
Action::LockView { lock: _, unlock: _, latches: _, looks_locked_from } => {
looks_locked_from.iter()
.find(|view| locked_view_name == view.as_str())
.is_some()
},
Action::LockView { lock, unlock: _ } => lock == view_name,
_ => false,
}
}
pub fn is_active(&self, view_name: &str) -> bool {
match self {
Action::SetView(view) => view == view_name,
Action::LockView { lock, unlock: _, latches: _, looks_locked_from: _ } => lock == view_name,
Action::LockView { lock, unlock: _ } => lock == view_name,
_ => false,
}
}

View File

@ -289,13 +289,7 @@ struct ButtonMeta {
#[serde(deny_unknown_fields)]
enum Action {
#[serde(rename="locking")]
Locking {
lock_view: String,
unlock_view: String,
pops: Option<bool>,
#[serde(default)]
looks_locked_from: Vec<String>,
},
Locking { lock_view: String, unlock_view: String },
#[serde(rename="set_view")]
SetView(String),
#[serde(rename="show_prefs")]
@ -606,9 +600,7 @@ fn create_action<H: logging::Handler>(
)
),
SubmitData::Action(Action::Locking {
lock_view, unlock_view,
pops,
looks_locked_from,
lock_view, unlock_view
}) => ::action::Action::LockView {
lock: filter_view_name(
name,
@ -622,8 +614,6 @@ fn create_action<H: logging::Handler>(
&view_names,
warning_handler,
),
latches: pops.unwrap_or(true),
looks_locked_from,
},
SubmitData::Action(
Action::ShowPrefs
@ -668,9 +658,6 @@ fn create_action<H: logging::Handler>(
Modifier::Alt => action::Action::ApplyModifier(
action::Modifier::Alt,
),
Modifier::Mod4 => action::Action::ApplyModifier(
action::Modifier::Mod4,
),
unsupported_modifier => {
warning_handler.handle(
logging::Level::Bug,

View File

@ -59,7 +59,7 @@ handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
if (service->context) {
if (arg_visible) {
server_context_service_force_show_keyboard (service->context);
server_context_service_show_keyboard (service->context);
} else {
server_context_service_hide_keyboard (service->context);
}

View File

@ -3,24 +3,20 @@
use cairo;
use std::cell::RefCell;
use ::action::{ Action, Modifier };
use ::action::Action;
use ::keyboard;
use ::layout::{ Button, Label, LatchedState, Layout };
use ::layout::c::{ Bounds, EekGtkKeyboard, Point };
use ::layout::{ Button, Layout };
use ::layout::c::{ EekGtkKeyboard, Point };
use ::submission::Submission;
use glib::translate::FromGlibPtrNone;
use gtk::WidgetExt;
use std::collections::HashSet;
use std::ffi::CStr;
use std::ptr;
mod c {
use super::*;
use cairo_sys;
use std::os::raw::{ c_char, c_void };
use std::os::raw::c_void;
// This is constructed only in C, no need for warnings
#[allow(dead_code)]
@ -28,44 +24,18 @@ mod c {
#[derive(Clone, Copy)]
pub struct EekRenderer(*const c_void);
// This is constructed only in C, no need for warnings
/// Just don't clone this for no reason.
#[allow(dead_code)]
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct GtkStyleContext(*const c_void);
#[no_mangle]
extern "C" {
// Button and View inside CButtonPlace are safe to pass to C
// as long as they don't outlive the call
// and nothing dereferences them
#[allow(improper_ctypes)]
pub fn eek_renderer_get_scale_factor(
pub fn eek_render_button(
renderer: EekRenderer,
) -> u32;
#[allow(improper_ctypes)]
pub fn eek_render_button_in_context(
scale_factor: u32,
cr: *mut cairo_sys::cairo_t,
ctx: GtkStyleContext,
bounds: Bounds,
icon_name: *const c_char,
label: *const c_char,
);
#[allow(improper_ctypes)]
pub fn eek_get_style_context_for_button(
renderer: EekRenderer,
name: *const c_char,
outline_name: *const c_char,
locked_class: *const c_char,
button: *const Button,
pressed: u64,
) -> GtkStyleContext;
#[allow(improper_ctypes)]
pub fn eek_put_style_context_for_button(
ctx: GtkStyleContext,
outline_name: *const c_char,
locked_class: *const c_char,
locked: u64,
);
}
@ -85,16 +55,13 @@ mod c {
layout.foreach_visible_button(|offset, button| {
let state = RefCell::borrow(&button.state).clone();
let locked = LockedStyle::from_action(
&state.action,
&active_modifiers,
layout.get_view_latched(),
&layout.current_view,
);
if state.pressed == keyboard::PressType::Pressed
|| locked != LockedStyle::Free
{
let active_mod = match &state.action {
Action::ApplyModifier(m) => active_modifiers.contains(m),
_ => false,
};
let locked = state.action.is_active(&layout.current_view)
| active_mod;
if state.pressed == keyboard::PressType::Pressed || locked {
render_button_at_position(
renderer, &cr,
offset,
@ -120,55 +87,20 @@ mod c {
renderer, &cr,
offset,
button.as_ref(),
keyboard::PressType::Released,
LockedStyle::Free,
keyboard::PressType::Released, false,
);
})
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
enum LockedStyle {
Free,
Latched,
Locked,
}
impl LockedStyle {
fn from_action(
action: &Action,
mods: &HashSet<Modifier>,
latched_view: &LatchedState,
current_view: &str,
) -> LockedStyle {
let active_mod = match action {
Action::ApplyModifier(m) => mods.contains(m),
_ => false,
};
let active_view = action.is_active(current_view);
let latched_button = match latched_view {
LatchedState::Not => false,
LatchedState::FromView(view) => !action.has_locked_appearance_from(view),
};
match (active_mod, active_view, latched_button) {
// Modifiers don't latch.
(true, _, _) => LockedStyle::Locked,
(false, true, false) => LockedStyle::Locked,
(false, true, true) => LockedStyle::Latched,
_ => LockedStyle::Free,
}
}
}
/// Renders a button at a position (button's own bounds ignored)
fn render_button_at_position(
pub fn render_button_at_position(
renderer: c::EekRenderer,
cr: &cairo::Context,
position: Point,
button: &Button,
pressed: keyboard::PressType,
locked: LockedStyle,
locked: bool,
) {
cr.save();
cr.translate(position.x, position.y);
@ -177,110 +109,19 @@ fn render_button_at_position(
button.size.width, button.size.height
);
cr.clip();
let scale_factor = unsafe {
c::eek_renderer_get_scale_factor(renderer)
};
let bounds = button.get_bounds();
let (label_c, icon_name_c) = match &button.label {
Label::Text(text) => (text.as_ptr(), ptr::null()),
Label::IconName(name) => {
let l = unsafe {
// CStr doesn't allocate anything, so it only points to
// the 'static str, avoiding a memory leak
CStr::from_bytes_with_nul_unchecked(b"icon\0")
};
(l.as_ptr(), name.as_ptr())
},
};
with_button_context(
renderer,
button,
pressed,
locked,
|ctx| unsafe {
// TODO: split into separate procedures:
// draw outline, draw label, draw icon.
c::eek_render_button_in_context(
scale_factor,
cairo::Context::to_raw_none(&cr),
*ctx,
bounds,
icon_name_c,
label_c,
)
}
);
cr.restore();
}
fn with_button_context<R, F: FnOnce(&c::GtkStyleContext) -> R>(
renderer: c::EekRenderer,
button: &Button,
pressed: keyboard::PressType,
locked: LockedStyle,
operation: F,
) -> R {
let outline_name_c = button.outline_name.as_ptr();
let locked_class_c = match locked {
LockedStyle::Free => ptr::null(),
LockedStyle::Locked => unsafe {
CStr::from_bytes_with_nul_unchecked(b"locked\0").as_ptr()
},
LockedStyle::Latched => unsafe {
CStr::from_bytes_with_nul_unchecked(b"latched\0").as_ptr()
},
};
let ctx = unsafe {
c::eek_get_style_context_for_button(
renderer,
button.name.as_ptr(),
outline_name_c,
locked_class_c,
pressed as u64,
)
};
let r = operation(&ctx);
unsafe {
c::eek_put_style_context_for_button(
ctx,
outline_name_c,
locked_class_c,
c::eek_render_button(
renderer,
cairo::Context::to_raw_none(&cr),
button as *const Button,
pressed as u64,
locked as u64,
)
};
r
cr.restore();
}
pub fn queue_redraw(keyboard: EekGtkKeyboard) {
let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) };
widget.queue_draw();
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_exit_only() {
assert_eq!(
LockedStyle::from_action(
&Action::LockView {
lock: "ab".into(),
unlock: "a".into(),
latches: true,
looks_locked_from: vec!["b".into()],
},
&HashSet::new(),
&LatchedState::FromView("b".into()),
"ab",
),
LockedStyle::Locked,
);
}
}

View File

@ -32,9 +32,9 @@ pub mod c {
#[repr(transparent)]
pub struct InputMethod(*const c_void);
#[no_mangle]
extern "C" {
fn imservice_destroy_im(im: *mut c::InputMethod);
#[allow(improper_ctypes)] // IMService will never be dereferenced in C
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);
@ -149,18 +149,21 @@ pub mod c {
..IMProtocolState::default()
};
imservice.serial += Wrapping(1u32);
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,
);
}
let (hint, purpose) = if imservice.current.active {(
imservice.current.content_hint,
imservice.current.content_purpose.clone(),
)} else {(
ContentHint::NONE,
ContentPurpose::Normal,
)};
unsafe {
eekboard_context_service_set_hint_purpose(
imservice.state_manager,
hint.bits(),
purpose as u32,
);
}
}
}
@ -406,6 +409,7 @@ impl IMService {
unsafe {
c::eek_input_method_commit(self.im, self.serial.0)
}
self.serial += Wrapping(1u32);
Ok(())
},
false => Err(SubmitError::NotActive),

View File

@ -26,6 +26,13 @@ struct squeek_layout_state {
struct squeek_layout;
EekBounds squeek_button_get_bounds(const struct squeek_button*);
const char *squeek_button_get_label(const struct squeek_button*);
const char *squeek_button_get_icon_name(const struct squeek_button*);
const char *squeek_button_get_name(const struct squeek_button*);
const char *squeek_button_get_outline_name(const struct squeek_button*);
void squeek_button_print(const struct squeek_button* button);
struct transformation squeek_layout_calculate_transformation(
const struct squeek_layout *layout,

View File

@ -41,7 +41,9 @@ pub mod c {
use super::*;
use gtk_sys;
use std::os::raw::c_void;
use std::ffi::CStr;
use std::os::raw::{ c_char, c_void };
use std::ptr;
use std::ops::{ Add, Sub };
@ -50,6 +52,7 @@ pub mod c {
#[derive(Copy, Clone)]
pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
#[no_mangle]
extern "C" {
#[allow(improper_ctypes)]
pub fn eek_gtk_keyboard_emit_feedback(
@ -159,6 +162,64 @@ pub mod c {
pub struct LevelKeyboard(*const c_void);
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
#[no_mangle]
pub extern "C"
fn squeek_button_get_bounds(button: *const ::layout::Button) -> Bounds {
let button = unsafe { &*button };
Bounds {
x: 0.0, y: 0.0,
width: button.size.width, height: button.size.height
}
}
#[no_mangle]
pub extern "C"
fn squeek_button_get_label(
button: *const ::layout::Button
) -> *const c_char {
let button = unsafe { &*button };
match &button.label {
Label::Text(text) => text.as_ptr(),
// returning static strings to C is a bit cumbersome
Label::IconName(_) => unsafe {
// CStr doesn't allocate anything, so it only points to
// the 'static str, avoiding a memory leak
CStr::from_bytes_with_nul_unchecked(b"icon\0")
}.as_ptr(),
}
}
#[no_mangle]
pub extern "C"
fn squeek_button_get_icon_name(button: *const Button) -> *const c_char {
let button = unsafe { &*button };
match &button.label {
Label::Text(_) => ptr::null(),
Label::IconName(name) => name.as_ptr(),
}
}
#[no_mangle]
pub extern "C"
fn squeek_button_get_name(button: *const Button) -> *const c_char {
let button = unsafe { &*button };
button.name.as_ptr()
}
#[no_mangle]
pub extern "C"
fn squeek_button_get_outline_name(button: *const Button) -> *const c_char {
let button = unsafe { &*button };
button.outline_name.as_ptr()
}
#[no_mangle]
pub extern "C"
fn squeek_button_print(button: *const ::layout::Button) {
let button = unsafe { &*button };
println!("{:?}", button);
}
/// Positions the layout contents within the available space.
/// The origin of the transformation is the point inside the margins.
@ -424,15 +485,6 @@ pub struct Button {
pub state: Rc<RefCell<KeyState>>,
}
impl Button {
pub fn get_bounds(&self) -> c::Bounds {
c::Bounds {
x: 0.0, y: 0.0,
width: self.size.width, height: self.size.height,
}
}
}
/// The graphical representation of a row of buttons
#[derive(Clone, Debug)]
pub struct Row {
@ -500,7 +552,6 @@ pub struct Spacing {
pub button: f64,
}
#[derive(Clone)]
pub struct View {
/// Rows together with their offsets from the top left
rows: Vec<(c::Point, Row)>,
@ -614,19 +665,6 @@ pub struct Margins {
pub right: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub enum LatchedState {
/// Holds view to return to.
FromView(String),
Not,
}
impl LatchedState {
pub fn is_latched(&self) -> bool {
self != &LatchedState::Not
}
}
// TODO: split into sth like
// Arrangement (views) + details (keymap) + State (keys)
/// State of the UI, contains the backend as well
@ -634,12 +672,6 @@ pub struct Layout {
pub margins: Margins,
pub kind: ArrangementKind,
pub current_view: String,
// If current view is latched,
// clicking any button that emits an action (erase, submit, set modifier)
// will cause lock buttons to unlatch.
view_latched: LatchedState,
// Views own the actual buttons which have state
// Maybe they should own UI only,
// and keys should be owned by a dedicated non-UI-State?
@ -686,7 +718,6 @@ impl Layout {
Layout {
kind,
current_view: "base".to_owned(),
view_latched: LatchedState::Not,
views: data.views,
keymaps: data.keymaps,
pressed_keys: HashSet::new(),
@ -712,12 +743,6 @@ impl Layout {
}
}
// Layout is passed around mutably,
// so better keep the field away from direct access.
pub fn get_view_latched(&self) -> &LatchedState {
&self.view_latched
}
/// Calculates size without margins
fn calculate_inner_size(&self) -> Size {
View::calculate_super_size(
@ -793,117 +818,8 @@ impl Layout {
}
out
}
fn apply_view_transition(
&mut self,
action: &Action,
) {
let (transition, new_latched) = Layout::process_action_for_view(
action,
&self.current_view,
&self.view_latched,
);
match transition {
ViewTransition::UnlatchAll => self.unstick_locks(),
ViewTransition::ChangeTo(view) => try_set_view(self, view.into()),
ViewTransition::NoChange => {},
};
self.view_latched = new_latched;
}
/// Unlatch all latched keys,
/// so that the new view is the one before first press.
fn unstick_locks(&mut self) {
if let LatchedState::FromView(name) = self.view_latched.clone() {
match self.set_view(name.clone()) {
Ok(_) => { self.view_latched = LatchedState::Not; }
Err(e) => log_print!(
logging::Level::Bug,
"Bad view {}, can't unlatch ({:?})",
name,
e,
),
}
}
}
/// Last bool is new latch state.
/// It doesn't make sense when the result carries UnlatchAll,
/// but let's not be picky.
///
/// Although the state is not defined at the keys
/// (it's in the relationship between view and action),
/// keys go through the following stages when clicked repeatedly:
/// unlocked+unlatched -> locked+latched -> locked+unlatched
/// -> unlocked+unlatched
fn process_action_for_view<'a>(
action: &'a Action,
current_view: &str,
latched: &LatchedState,
) -> (ViewTransition<'a>, LatchedState) {
match action {
Action::Submit { text: _, keys: _ }
| Action::Erase
| Action::ApplyModifier(_)
=> {
let t = match latched {
LatchedState::FromView(_) => ViewTransition::UnlatchAll,
LatchedState::Not => ViewTransition::NoChange,
};
(t, LatchedState::Not)
},
Action::SetView(view) => (
ViewTransition::ChangeTo(view),
LatchedState::Not,
),
Action::LockView { lock, unlock, latches, looks_locked_from: _ } => {
use self::ViewTransition as VT;
let locked = action.is_locked(current_view);
match (locked, latched, latches) {
// Was unlocked, now make locked but latched.
(false, LatchedState::Not, true) => (
VT::ChangeTo(lock),
LatchedState::FromView(current_view.into()),
),
// Layout is latched for reason other than this button.
(false, LatchedState::FromView(view), true) => (
VT::ChangeTo(lock),
LatchedState::FromView(view.clone()),
),
// Was latched, now only locked.
(true, LatchedState::FromView(_), true)
=> (VT::NoChange, LatchedState::Not),
// Was unlocked, can't latch so now make fully locked.
(false, _, false)
=> (VT::ChangeTo(lock), LatchedState::Not),
// Was locked, now make unlocked.
(true, _, _)
=> (VT::ChangeTo(unlock), LatchedState::Not),
}
},
_ => (ViewTransition::NoChange, latched.clone()),
}
}
}
#[derive(Debug, PartialEq)]
enum ViewTransition<'a> {
ChangeTo(&'a str),
UnlatchAll,
NoChange,
}
fn try_set_view(layout: &mut Layout, view_name: &str) {
layout.set_view(view_name.into())
.or_print(
logging::Problem::Bug,
&format!("Bad view {}, ignoring", view_name),
);
}
mod procedures {
use super::*;
@ -982,6 +898,67 @@ pub struct UIBackend {
mod seat {
use super::*;
fn try_set_view(layout: &mut Layout, view_name: String) {
layout.set_view(view_name.clone())
.or_print(
logging::Problem::Bug,
&format!("Bad view {}, ignoring", view_name),
);
}
/// A vessel holding an obligation to switch view.
/// Use with #[must_use]
struct ViewChange<'a> {
layout: &'a mut Layout,
view_name: Option<String>,
}
impl<'a> ViewChange<'a> {
fn choose_view(self, view_name: String) -> ViewChange<'a> {
ViewChange {
view_name: Some(view_name),
..self
}
}
fn apply(self) {
if let Some(name) = self.view_name {
try_set_view(self.layout, name);
}
}
}
/// Find all impermanent view changes and undo them in an arbitrary order.
/// Return an obligation to actually switch the view.
/// The final view is the "unlock" view
/// from one of the currently stuck keys.
// As long as only one stuck button is used, this should be fine.
// This is guaranteed because pressing a lock button unlocks all others.
// TODO: Make some broader guarantee about the resulting view,
// e.g. by maintaining a stack of stuck keys.
#[must_use]
fn unstick_locks(layout: &mut Layout) -> ViewChange {
let mut new_view = None;
for key in layout.get_locked_keys().clone() {
let key: &Rc<RefCell<KeyState>> = key.borrow();
let key = RefCell::borrow(key);
match &key.action {
Action::LockView { lock: _, unlock: view } => {
new_view = Some(view.clone());
},
a => log_print!(
logging::Level::Bug,
"Non-locking action {:?} was found inside locked keys",
a,
),
};
}
ViewChange {
layout,
view_name: new_view,
}
}
pub fn handle_press_key(
layout: &mut Layout,
submission: &mut Submission,
@ -1041,22 +1018,37 @@ mod seat {
};
let action = key.action.clone();
layout.apply_view_transition(&action);
// update
let key = key.into_released();
// process non-view switching
// process changes
match action {
Action::Submit { text: _, keys: _ }
| Action::Erase
=> {
unstick_locks(layout).apply();
submission.handle_release(KeyState::get_id(rckey), time);
},
Action::SetView(view) => {
try_set_view(layout, view)
},
Action::LockView { lock, unlock } => {
let gets_locked = !key.action.is_locked(&layout.current_view);
unstick_locks(layout)
// It doesn't matter what the resulting view should be,
// it's getting changed anyway.
.choose_view(
match gets_locked {
true => lock.clone(),
false => unlock.clone(),
}
)
.apply()
},
Action::ApplyModifier(modifier) => {
// FIXME: key id is unneeded with stateless locks
let key_id = KeyState::get_id(rckey);
let gets_locked = !submission.is_modifier_active(modifier);
let gets_locked = !submission.is_modifier_active(modifier.clone());
match gets_locked {
true => submission.handle_add_modifier(
key_id,
@ -1091,8 +1083,6 @@ mod seat {
}
}
},
// Other keys are handled in view switcher before.
_ => {}
};
let pointer = ::util::Pointer(rckey.clone());
@ -1110,20 +1100,14 @@ mod test {
use std::ffi::CString;
use ::keyboard::PressType;
pub fn make_state_with_action(action: Action)
-> Rc<RefCell<::keyboard::KeyState>>
{
pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
Rc::new(RefCell::new(::keyboard::KeyState {
pressed: PressType::Released,
keycodes: Vec::new(),
action,
action: Action::SetView("default".into()),
}))
}
pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
make_state_with_action(Action::SetView("default".into()))
}
pub fn make_button_with_state(
name: String,
state: Rc<RefCell<::keyboard::KeyState>>,
@ -1137,242 +1121,6 @@ mod test {
})
}
#[test]
fn latch_lock_unlock() {
let action = Action::LockView {
lock: "lock".into(),
unlock: "unlock".into(),
latches: true,
looks_locked_from: vec![],
};
assert_eq!(
Layout::process_action_for_view(&action, "unlock", &LatchedState::Not),
(ViewTransition::ChangeTo("lock"), LatchedState::FromView("unlock".into())),
);
assert_eq!(
Layout::process_action_for_view(&action, "lock", &LatchedState::FromView("unlock".into())),
(ViewTransition::NoChange, LatchedState::Not),
);
assert_eq!(
Layout::process_action_for_view(&action, "lock", &LatchedState::Not),
(ViewTransition::ChangeTo("unlock"), LatchedState::Not),
);
assert_eq!(
Layout::process_action_for_view(&Action::Erase, "lock", &LatchedState::FromView("base".into())),
(ViewTransition::UnlatchAll, LatchedState::Not),
);
}
#[test]
fn latch_pop_layout() {
let switch = Action::LockView {
lock: "locked".into(),
unlock: "base".into(),
latches: true,
looks_locked_from: vec![],
};
let submit = Action::Erase;
let view = View::new(vec![(
0.0,
Row::new(vec![
(
0.0,
make_button_with_state(
"switch".into(),
make_state_with_action(switch.clone())
),
),
(
1.0,
make_button_with_state(
"submit".into(),
make_state_with_action(submit.clone())
),
),
]),
)]);
let mut layout = Layout {
current_view: "base".into(),
view_latched: LatchedState::Not,
keymaps: Vec::new(),
kind: ArrangementKind::Base,
pressed_keys: HashSet::new(),
margins: Margins {
top: 0.0,
left: 0.0,
right: 0.0,
bottom: 0.0,
},
views: hashmap! {
// Both can use the same structure.
// Switching doesn't depend on the view shape
// as long as the switching button is present.
"base".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
"locked".into() => (c::Point { x: 0.0, y: 0.0 }, view),
},
};
// Basic cycle
layout.apply_view_transition(&switch);
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&switch);
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&submit);
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&switch);
assert_eq!(&layout.current_view, "base");
layout.apply_view_transition(&switch);
// Unlatch
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&submit);
assert_eq!(&layout.current_view, "base");
}
#[test]
fn reverse_unlatch_layout() {
let switch = Action::LockView {
lock: "locked".into(),
unlock: "base".into(),
latches: true,
looks_locked_from: vec![],
};
let unswitch = Action::LockView {
lock: "locked".into(),
unlock: "unlocked".into(),
latches: false,
looks_locked_from: vec![],
};
let submit = Action::Erase;
let view = View::new(vec![(
0.0,
Row::new(vec![
(
0.0,
make_button_with_state(
"switch".into(),
make_state_with_action(switch.clone())
),
),
(
1.0,
make_button_with_state(
"submit".into(),
make_state_with_action(submit.clone())
),
),
]),
)]);
let mut layout = Layout {
current_view: "base".into(),
view_latched: LatchedState::Not,
keymaps: Vec::new(),
kind: ArrangementKind::Base,
pressed_keys: HashSet::new(),
margins: Margins {
top: 0.0,
left: 0.0,
right: 0.0,
bottom: 0.0,
},
views: hashmap! {
// Both can use the same structure.
// Switching doesn't depend on the view shape
// as long as the switching button is present.
"base".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
"locked".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
"unlocked".into() => (c::Point { x: 0.0, y: 0.0 }, view),
},
};
layout.apply_view_transition(&switch);
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&unswitch);
assert_eq!(&layout.current_view, "unlocked");
}
#[test]
fn latch_twopop_layout() {
let switch = Action::LockView {
lock: "locked".into(),
unlock: "base".into(),
latches: true,
looks_locked_from: vec![],
};
let switch_again = Action::LockView {
lock: "ĄĘ".into(),
unlock: "locked".into(),
latches: true,
looks_locked_from: vec![],
};
let submit = Action::Erase;
let view = View::new(vec![(
0.0,
Row::new(vec![
(
0.0,
make_button_with_state(
"switch".into(),
make_state_with_action(switch.clone())
),
),
(
1.0,
make_button_with_state(
"submit".into(),
make_state_with_action(submit.clone())
),
),
]),
)]);
let mut layout = Layout {
current_view: "base".into(),
view_latched: LatchedState::Not,
keymaps: Vec::new(),
kind: ArrangementKind::Base,
pressed_keys: HashSet::new(),
margins: Margins {
top: 0.0,
left: 0.0,
right: 0.0,
bottom: 0.0,
},
views: hashmap! {
// All can use the same structure.
// Switching doesn't depend on the view shape
// as long as the switching button is present.
"base".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
"locked".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
"ĄĘ".into() => (c::Point { x: 0.0, y: 0.0 }, view),
},
};
// Latch twice, then Ąto-unlatch across 2 levels
layout.apply_view_transition(&switch);
println!("{:?}", layout.view_latched);
assert_eq!(&layout.current_view, "locked");
layout.apply_view_transition(&switch_again);
println!("{:?}", layout.view_latched);
assert_eq!(&layout.current_view, "ĄĘ");
layout.apply_view_transition(&submit);
println!("{:?}", layout.view_latched);
assert_eq!(&layout.current_view, "base");
}
#[test]
fn check_centering() {
// A B
@ -1445,7 +1193,6 @@ mod test {
]);
let layout = Layout {
current_view: String::new(),
view_latched: LatchedState::Not,
keymaps: Vec::new(),
kind: ArrangementKind::Base,
pressed_keys: HashSet::new(),

View File

@ -24,6 +24,7 @@ mod c {
#[repr(C)]
pub struct GnomeXkbInfo(*const c_void);
#[no_mangle]
extern "C" {
// from libc
pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;

View File

@ -9,6 +9,7 @@ pub mod c {
#[derive(Clone, Copy)]
pub struct Manager(*const c_void);
#[no_mangle]
extern "C" {
pub fn eekboard_context_service_set_overlay(
manager: Manager,

9
src/popover.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef POPOVER_H__
#define POPOVER_H__
#include <gtk/gtk.h>
#include "eek/eek-keyboard.h"
void squeek_popover_show(GtkWidget*, struct button_place);
#endif

View File

@ -29,6 +29,7 @@ use ::logging::Warn;
mod c {
use std::os::raw::c_char;
#[no_mangle]
extern "C" {
pub fn popover_open_settings_panel(panel: *const c_char);
}
@ -436,8 +437,7 @@ pub fn show(
let settings_action = gio::SimpleAction::new("settings", None);
settings_action.connect_activate(move |_, _| {
let s = CString::new("region").unwrap();
unsafe { c::popover_open_settings_panel(s.as_ptr()) };
unsafe { c::popover_open_settings_panel(CString::new("region").unwrap().as_ptr()) };
});
let action_group = gio::SimpleActionGroup::new();

View File

@ -10,78 +10,41 @@ use std::iter::FromIterator;
// TODO: keep a list of what is a language layout,
// and what a convenience layout. "_wide" is not a layout,
// neither is "number"
/// List of builtin layouts
const KEYBOARDS: &[(*const str, *const str)] = &[
// layouts: us must be left as first, as it is the,
// fallback layout.
// fallback layout. The others should be alphabetical.
("us", include_str!("../data/keyboards/us.yaml")),
("us+colemak", include_str!("../data/keyboards/us+colemak.yaml")),
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
// Language layouts: keep alphabetical.
("br", include_str!("../data/keyboards/br.yaml")),
("de", include_str!("../data/keyboards/de.yaml")),
("be", include_str!("../data/keyboards/be.yaml")),
("be_wide", include_str!("../data/keyboards/be_wide.yaml")),
("bg", include_str!("../data/keyboards/bg.yaml")),
("br", include_str!("../data/keyboards/br.yaml")),
("de", include_str!("../data/keyboards/de.yaml")),
("de_wide", include_str!("../data/keyboards/de_wide.yaml")),
("cz", include_str!("../data/keyboards/cz.yaml")),
("cz_wide", include_str!("../data/keyboards/cz_wide.yaml")),
("cz+qwerty", include_str!("../data/keyboards/cz+qwerty.yaml")),
("cz+qwerty_wide", include_str!("../data/keyboards/cz+qwerty_wide.yaml")),
("dk", include_str!("../data/keyboards/dk.yaml")),
("epo", include_str!("../data/keyboards/epo.yaml")),
("es", include_str!("../data/keyboards/es.yaml")),
("es+cat", include_str!("../data/keyboards/es+cat.yaml")),
("fi", include_str!("../data/keyboards/fi.yaml")),
("fr", include_str!("../data/keyboards/fr.yaml")),
("fr_wide", include_str!("../data/keyboards/fr_wide.yaml")),
("gr", include_str!("../data/keyboards/gr.yaml")),
("il", include_str!("../data/keyboards/il.yaml")),
("ir", include_str!("../data/keyboards/ir.yaml")),
("ir_wide", include_str!("../data/keyboards/ir_wide.yaml")),
("it", include_str!("../data/keyboards/it.yaml")),
("it+fur", include_str!("../data/keyboards/it+fur.yaml")),
("gr", include_str!("../data/keyboards/gr.yaml")),
("it", include_str!("../data/keyboards/it.yaml")),
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
("jp+kana_wide", include_str!("../data/keyboards/jp+kana_wide.yaml")),
("no", include_str!("../data/keyboards/no.yaml")),
("number", include_str!("../data/keyboards/number.yaml")),
("pl", include_str!("../data/keyboards/pl.yaml")),
("pl_wide", include_str!("../data/keyboards/pl_wide.yaml")),
("ru", include_str!("../data/keyboards/ru.yaml")),
("se", include_str!("../data/keyboards/se.yaml")),
("th", include_str!("../data/keyboards/th.yaml")),
("th_wide", include_str!("../data/keyboards/th_wide.yaml")),
("ua", include_str!("../data/keyboards/ua.yaml")),
("us+colemak", include_str!("../data/keyboards/us+colemak.yaml")),
("us+colemak_wide", include_str!("../data/keyboards/us+colemak_wide.yaml")),
("us+dvorak", include_str!("../data/keyboards/us+dvorak.yaml")),
("us+dvorak_wide", include_str!("../data/keyboards/us+dvorak_wide.yaml")),
// Others
("number", include_str!("../data/keyboards/number.yaml")),
("bg", include_str!("../data/keyboards/bg.yaml")),
// layout+overlay
("terminal", include_str!("../data/keyboards/terminal.yaml")),
("terminal_wide", include_str!("../data/keyboards/terminal_wide.yaml")),
@ -122,7 +85,6 @@ const LAYOUT_NAMES: &[(*const str, *const str)] = &[
("en-US", include_str!("../data/langs/en-US.txt")),
("es-ES", include_str!("../data/langs/es-ES.txt")),
("fur-IT", include_str!("../data/langs/fur-IT.txt")),
("he-IL", include_str!("../data/langs/he-IL.txt")),
("ja-JP", include_str!("../data/langs/ja-JP.txt")),
("pl-PL", include_str!("../data/langs/pl-PL.txt")),
("ru-RU", include_str!("../data/langs/ru-RU.txt")),

View File

@ -239,13 +239,6 @@ server_context_service_real_show_keyboard (ServerContextService *self)
gtk_widget_show (GTK_WIDGET(self->window));
}
static gboolean
show_keyboard_source_func(ServerContextService *context)
{
server_context_service_real_show_keyboard(context);
return G_SOURCE_REMOVE;
}
static void
server_context_service_real_hide_keyboard (ServerContextService *self)
{
@ -253,13 +246,6 @@ server_context_service_real_hide_keyboard (ServerContextService *self)
self->visible = FALSE;
}
static gboolean
hide_keyboard_source_func(ServerContextService *context)
{
server_context_service_real_hide_keyboard(context);
return G_SOURCE_REMOVE;
}
static gboolean
on_hide (ServerContextService *self)
{
@ -269,7 +255,7 @@ on_hide (ServerContextService *self)
return G_SOURCE_REMOVE;
}
static void
void
server_context_service_show_keyboard (ServerContextService *self)
{
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
@ -280,30 +266,17 @@ server_context_service_show_keyboard (ServerContextService *self)
}
if (!self->visible) {
g_idle_add((GSourceFunc)show_keyboard_source_func, self);
server_context_service_real_show_keyboard (self);
}
}
void
server_context_service_force_show_keyboard (ServerContextService *self)
{
if (!submission_hint_available(self->submission)) {
eekboard_context_service_set_hint_purpose(
self->state,
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL
);
}
server_context_service_show_keyboard(self);
}
void
server_context_service_hide_keyboard (ServerContextService *self)
{
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
if (self->visible) {
g_idle_add((GSourceFunc)hide_keyboard_source_func, self);
server_context_service_real_hide_keyboard (self);
}
}

View File

@ -31,7 +31,7 @@ G_DECLARE_FINAL_TYPE (ServerContextService, server_context_service, SERVER, CONT
ServerContextService *server_context_service_new(EekboardContextService *self, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman, struct vis_manager *visman);
enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *);
void server_context_service_force_show_keyboard (ServerContextService *self);
void server_context_service_show_keyboard (ServerContextService *self);
void server_context_service_hide_keyboard (ServerContextService *self);
G_END_DECLS
#endif /* SERVER_CONTEXT_SERVICE_H */

View File

@ -50,16 +50,9 @@ struct squeekboard {
};
GMainLoop *loop;
static gboolean opt_system = FALSE;
static gchar *opt_address = NULL;
static void
quit (void)
{
g_main_loop_quit (loop);
}
// D-Bus
static void
@ -138,67 +131,6 @@ static const struct wl_registry_listener registry_listener = {
#define SESSION_NAME "sm.puri.OSK0"
GDBusProxy *_proxy = NULL;
GDBusProxy *_client_proxy = NULL;
gchar *_client_path = NULL;
static void
send_quit_response (GDBusProxy *proxy)
{
g_debug ("Calling EndSessionResponse");
g_dbus_proxy_call (proxy, "EndSessionResponse",
g_variant_new ("(bs)", TRUE, ""), G_DBUS_CALL_FLAGS_NONE,
G_MAXINT, NULL, NULL, NULL);
}
static void
unregister_client (void)
{
g_autoptr (GError) error = NULL;
g_return_if_fail (G_IS_DBUS_PROXY (_proxy));
g_return_if_fail (_client_path != NULL);
g_debug ("Unregistering client");
g_dbus_proxy_call_sync (_proxy,
"UnregisterClient",
g_variant_new ("(o)", _client_path),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
&error);
if (error) {
g_warning ("Failed to unregister client: %s", error->message);
}
g_clear_object (&_client_proxy);
g_clear_pointer (&_client_path, g_free);
}
static void client_proxy_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
if (g_str_equal (signal_name, "QueryEndSession")) {
g_debug ("Received QueryEndSession");
send_quit_response (proxy);
} else if (g_str_equal (signal_name, "CancelEndSession")) {
g_debug ("Received CancelEndSession");
} else if (g_str_equal (signal_name, "EndSession")) {
g_debug ("Received EndSession");
send_quit_response (proxy);
unregister_client ();
quit ();
} else if (g_str_equal (signal_name, "Stop")) {
g_debug ("Received Stop");
unregister_client ();
quit ();
}
}
static void
session_register(void) {
@ -219,8 +151,7 @@ session_register(void) {
return;
}
g_autoptr (GVariant) res = NULL;
res = g_dbus_proxy_call_sync(_proxy, "RegisterClient",
g_dbus_proxy_call_sync(_proxy, "RegisterClient",
g_variant_new("(ss)", SESSION_NAME, autostart_id),
G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &error);
if (error) {
@ -229,22 +160,6 @@ session_register(void) {
g_clear_error(&error);
return;
}
g_variant_get (res, "(o)", &_client_path);
g_debug ("Registered client at '%s'", _client_path);
_client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
0, NULL, "org.gnome.SessionManager", _client_path,
"org.gnome.SessionManager.ClientPrivate", NULL, &error);
if (error) {
g_warning ("Failed to get client proxy: %s", error->message);
g_clear_error (&error);
g_free (_client_path);
_client_path = NULL;
return;
}
g_signal_connect (_client_proxy, "g-signal", G_CALLBACK (client_proxy_signal), NULL);
}
int
@ -392,7 +307,8 @@ main (int argc, char **argv)
session_register();
loop = g_main_loop_new (NULL, FALSE);
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
if (connection) {

View File

@ -17,7 +17,6 @@ struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager,
// Defined in Rust
struct submission* submission_new(struct zwp_input_method_v2 *im, struct zwp_virtual_keyboard_v1 *vk, EekboardContextService *state, struct vis_manager *vis_manager);
uint8_t submission_hint_available(struct submission *self);
void submission_set_ui(struct submission *self, ServerContextService *ui_context);
void submission_use_layout(struct submission *self, struct squeek_layout *layout, uint32_t time);
#endif

View File

@ -93,18 +93,6 @@ pub mod c {
let layout = unsafe { &*layout };
submission.use_layout(layout, Timestamp(time));
}
#[no_mangle]
pub extern "C"
fn submission_hint_available(submission: *mut Submission) -> u8 {
if submission.is_null() {
panic!("Null submission pointer");
}
let submission: &mut Submission = unsafe { &mut *submission };
let active = submission.imservice.as_ref()
.map(|imservice| imservice.is_active());
(Some(true) == active) as u8
}
}
#[derive(Clone, Copy)]
@ -270,7 +258,6 @@ impl Submission {
.map(|(_id, m)| match m {
Modifier::Control => Modifiers::CONTROL,
Modifier::Alt => Modifiers::MOD1,
Modifier::Mod4 => Modifiers::MOD4,
})
.fold(Modifiers::empty(), |m, n| m | n);
self.virtual_keyboard.set_modifiers_state(raw_modifiers);

View File

@ -19,6 +19,7 @@ pub mod c {
#[repr(transparent)]
pub struct UIManager(*const c_void);
#[no_mangle]
extern "C" {
pub fn server_context_service_update_visible(imservice: *const UIManager, active: u32);
pub fn server_context_service_release_visibility(imservice: *const UIManager);

View File

@ -37,6 +37,7 @@ pub mod c {
}
}
#[no_mangle]
extern "C" {
// From libc, to let KeyMap get deallocated.
fn close(fd: u32);

View File

@ -46,49 +46,34 @@ endforeach
# The layout test is in the examples directory
# due to the way Cargo builds executables
# and the need to call it manually.
# This is the list of tested builtin layouts.
# Please keep each block alphabetical!
# Please keep shapes (with _) on the same line,
# variants (with +) on separate lines.
# and the need to call it manually
foreach layout : [
# This is the fallback layout,
# so stays first to make sure it never goes missing.
'us', 'us_wide',
# Block: Languages
'us', 'us+colemak', 'us_wide',
'br',
'be', 'be_wide',
'bg',
'br',
'cz', 'cz_wide',
'cz+qwerty', 'cz+qwerty_wide',
'de', 'de_wide',
'dk',
'epo',
'es',
'es+cat',
'fi',
'fr', 'fr_wide',
'gr',
'il',
'ir',
'it',
'it+fur',
'gr',
'it',
'jp+kana','jp+kana_wide',
'no',
'number',
'pl', 'pl_wide',
'ru',
'se',
'th', 'th_wide',
'ua',
'us+colemak', 'us+colemak_wide',
'us+dvorak', 'us+dvorak_wide',
# Block: Not languages.
'emoji',
'number',
'th',
'terminal', 'terminal_wide',
'emoji',
]
extra = []
if layout == 'emoji'