Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aee981d9c0 | |||
| 3bede84a2d | |||
| e14d411150 | |||
| f91f000df1 | |||
| 18f8443a9f | |||
| 746d842dd4 | |||
| 185efb1c2a | |||
| a31f9b5e04 | |||
| 94aec87b5d | |||
| 854a9bb22e | |||
| 477a883885 | |||
| b3a63042cb | |||
| d53a683285 | |||
| 27a99e2973 | |||
| 53c64010e8 | |||
| 7f704bcd61 | |||
| 1e08adb26b | |||
| 75bbb17881 | |||
| 58c8556058 | |||
| 1c56de8698 | |||
| 0eb0a6e8fd | |||
| 9b5e0109a7 | |||
| a1b811aada | |||
| 1b424bd663 | |||
| 938ba53a38 | |||
| 1e609f4550 | |||
| e33f591a1f | |||
| 456af0f1ef | |||
| b6d25da7c2 | |||
| 288d2247da | |||
| e5eb9f0fd3 | |||
| 908aa20036 | |||
| 60f1ca1408 | |||
| 5ef687a722 | |||
| 86ed9a7a01 | |||
| 4fee2fad01 | |||
| 35ba8ad81c | |||
| 0985724b19 | |||
| 7aff7977fc | |||
| 55bb263a12 | |||
| 32b85e75db | |||
| 3935375d1b | |||
| 97dd2b1096 | |||
| de7211d1a5 | |||
| 26380ab987 | |||
| f898b75b9d | |||
| e513cb9b54 | |||
| 6fd7ab7405 | |||
| 15833323ae | |||
| 653462721b | |||
| 2889e50507 | |||
| 6b15f69e00 | |||
| 231982d7f7 | |||
| 3bea256ca5 | |||
| 4c0f23c5c1 | |||
| 27d54fb38a | |||
| 3b6999f6ef | |||
| de43d67638 | |||
| 2fca71aa53 | |||
| 7870791fef | |||
| 83f9b580ef | |||
| 54f9e61b6a | |||
| 94b7ba1ccc | |||
| e7d30d933f | |||
| 150fb3cf6a | |||
| 169f33c67a |
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2,7 +2,7 @@
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.0"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -54,7 +54,7 @@ dependencies = [
|
||||
name = "rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -142,7 +142,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
|
||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@ -3,11 +3,11 @@ name = "rs"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
maplit = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.8"
|
||||
xkbcommon = { version = "0.4", features = ["wayland"] }
|
||||
bitflags = "1.0.*"
|
||||
maplit = "1.0.*"
|
||||
serde = { version = "1.0.*", features = ["derive"] }
|
||||
serde_yaml = "0.8.*"
|
||||
xkbcommon = { version = "0.4.*", features = ["wayland"] }
|
||||
|
||||
[lib]
|
||||
name = "rs"
|
||||
|
||||
@ -42,7 +42,7 @@ Use the `cargo.sh` script for maintaining the Cargo part of the build. The scrip
|
||||
|
||||
```
|
||||
cd build_dir
|
||||
sh /source_path/cargo.sh /source_path '' test
|
||||
sh /source_path/cargo.sh '' test
|
||||
```
|
||||
|
||||
### Cargo dependencies
|
||||
@ -53,6 +53,6 @@ Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Si
|
||||
|
||||
```
|
||||
cd build_dir
|
||||
sh /source_path/cargo.sh /source_path '' update
|
||||
sh /source_path/cargo.sh '' update
|
||||
ninja test
|
||||
```
|
||||
|
||||
19
cargo.sh
Normal file → Executable file
19
cargo.sh
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# This script manages Cargo operations
|
||||
# while keeping the artifact directory within the build tree
|
||||
@ -6,18 +6,19 @@
|
||||
|
||||
set -e
|
||||
|
||||
SOURCE_DIR="$1"
|
||||
SCRIPT_PATH="$(realpath "$0")"
|
||||
SOURCE_DIR="$(dirname "$SCRIPT_PATH")"
|
||||
|
||||
export CARGO_TARGET_DIR=`pwd`
|
||||
if [ ! -z ${2} ]; then
|
||||
OUT_PATH=`realpath "${2}"`
|
||||
CARGO_TARGET_DIR="$(pwd)"
|
||||
export CARGO_TARGET_DIR
|
||||
if [ -n "${1}" ]; then
|
||||
OUT_PATH="$(realpath "$1")"
|
||||
fi
|
||||
|
||||
cd $SOURCE_DIR
|
||||
cd "$SOURCE_DIR"
|
||||
shift
|
||||
shift
|
||||
cargo $BUILD_ARG $@
|
||||
cargo "$@"
|
||||
|
||||
if [ ! -z ${OUT_PATH} ]; then
|
||||
if [ -n "${OUT_PATH}" ]; then
|
||||
cp "${CARGO_TARGET_DIR}"/debug/librs.a "${OUT_PATH}"
|
||||
fi
|
||||
|
||||
197
data/keyboards/el.yaml
Normal file
197
data/keyboards/el.yaml
Normal file
@ -0,0 +1,197 @@
|
||||
# Greek layout created by Antonis Tsolomitis
|
||||
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
|
||||
# Sep 2019
|
||||
---
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 6.33, width: 426, height: 250 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
||||
outline7:
|
||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "; ς ε ρ τ υ θ ι ο π !"
|
||||
- "α σ δ φ γ η ξ κ λ show_accented"
|
||||
- "Shift_L ζ χ ψ ω β ν μ , BackSpace"
|
||||
- "show_numbers preferences space . Return"
|
||||
upper:
|
||||
- ": EuroSign Ε Ρ Τ Υ Θ Ι Ο Π"
|
||||
- "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accented"
|
||||
- "Shift_L Ζ Χ Ψ Ω Β Ν Μ · BackSpace"
|
||||
- "show_numbers preferences space « » Return"
|
||||
accented:
|
||||
- "ά έ ή ί ό ύ ώ ϊ ϋ ΐ"
|
||||
- "ΰ Ά Έ Ή Ί Ό Ύ Ώ Ϊ show_base"
|
||||
- "Ϋ Ϗ ϐ ϑ ϕ ϖ ϗ – — BackSpace"
|
||||
- "show_numbers preferences space quoteleft quoteright Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "at numbersign dollar percent ampersand minus underscore plus parenleft parenright"
|
||||
- "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph"
|
||||
- "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright"
|
||||
- "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
buttons:
|
||||
Shift_L:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "upper"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
icon: "key-shift"
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
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: "*/="
|
||||
show_accented:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "accented"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "άΐ"
|
||||
show_base:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "αι"
|
||||
period:
|
||||
outline: altline
|
||||
label: "."
|
||||
space:
|
||||
outline: spaceline
|
||||
label: " "
|
||||
Return:
|
||||
outline: outline7
|
||||
icon: "key-enter"
|
||||
aring:
|
||||
label: "å"
|
||||
Aring:
|
||||
label: "Å"
|
||||
oslash:
|
||||
label: "ø"
|
||||
Oslash:
|
||||
label: "Ø"
|
||||
ae:
|
||||
label: "æ"
|
||||
AE:
|
||||
label: "Æ"
|
||||
asterisk:
|
||||
label: "*"
|
||||
asciitilde:
|
||||
label: "~"
|
||||
quoteleft:
|
||||
label: "`"
|
||||
bar:
|
||||
label: "|"
|
||||
U00B7:
|
||||
label: "·"
|
||||
squareroot:
|
||||
label: "√"
|
||||
Greek_pi:
|
||||
label: "π"
|
||||
division:
|
||||
label: "÷"
|
||||
multiply:
|
||||
label: "×"
|
||||
paragraph:
|
||||
label: "¶"
|
||||
Greek_tau:
|
||||
label: "τ"
|
||||
copyright:
|
||||
label: "©"
|
||||
numbersign:
|
||||
label: "#"
|
||||
U00AE:
|
||||
label: "®"
|
||||
at:
|
||||
label: "@"
|
||||
dollar:
|
||||
label: "$"
|
||||
U00A3:
|
||||
label: "£"
|
||||
percent:
|
||||
label: "%"
|
||||
EuroSign:
|
||||
label: "€"
|
||||
ampersand:
|
||||
label: "&"
|
||||
U00A5:
|
||||
label: "¥"
|
||||
minus:
|
||||
label: "-"
|
||||
asciicircum:
|
||||
label: "^"
|
||||
underscore:
|
||||
label: "_"
|
||||
degree:
|
||||
label: "°"
|
||||
plus:
|
||||
label: "+"
|
||||
equal:
|
||||
label: "="
|
||||
parenleft:
|
||||
label: "("
|
||||
parenright:
|
||||
label: ")"
|
||||
braceleft:
|
||||
label: "{"
|
||||
braceright:
|
||||
label: "}"
|
||||
comma:
|
||||
label: ","
|
||||
backslash:
|
||||
label: "\\"
|
||||
slash:
|
||||
label: "/"
|
||||
quotedbl:
|
||||
label: "\""
|
||||
quoteright:
|
||||
label: "'"
|
||||
less:
|
||||
label: "<"
|
||||
greater:
|
||||
label: ">"
|
||||
colon:
|
||||
label: ":"
|
||||
semicolon:
|
||||
label: ";"
|
||||
exclam:
|
||||
label: "!"
|
||||
question:
|
||||
label: "?"
|
||||
bracketleft:
|
||||
label: "["
|
||||
bracketright:
|
||||
label: "]"
|
||||
|
||||
96
data/keyboards/es.yaml
Normal file
96
data/keyboards/es.yaml
Normal file
@ -0,0 +1,96 @@
|
||||
---
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 1, width: 360, height: 198 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 30.67, height: 40.67 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 48, height: 40.67 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 57.33, height: 40.67 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 95.00, height: 40.67 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 39.33, height: 40.67 }
|
||||
|
||||
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"
|
||||
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"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
98
data/keyboards/it.yaml
Normal file
98
data/keyboards/it.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 1, width: 360, height: 198 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 30.67, height: 40.67 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 48, height: 40.67 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 57.33, height: 40.67 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 95.00, height: 40.67 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 39.33, height: 40.67 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l n"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers show_eschar 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_eschar preferences space ? period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters show_eschar preferences space ? period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters show_eschar preferences space ? period Return"
|
||||
eschar:
|
||||
- "á é í ó ú Á É Í Ó Ú"
|
||||
- "à è ì ò « » ù ! { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters show_symbols 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"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "default"
|
||||
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: "altline"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_eschar:
|
||||
action:
|
||||
set_view: "eschar"
|
||||
outline: "altline"
|
||||
label: "àè"
|
||||
period:
|
||||
outline: "default"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
@ -1,18 +1,17 @@
|
||||
---
|
||||
bounds: { x: 0, y: 10, width: 426, height: 229 }
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 6.33, width: 426, height: 250 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
||||
altline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
||||
outline7:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
||||
spaceline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
||||
|
||||
views:
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
---
|
||||
bounds: { x: 0, y: 10, width: 410, height: 229 }
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 6.33, width: 410, height: 250 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
|
||||
altline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
||||
outline7:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
||||
spaceline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 120.5853, height: 52 }
|
||||
|
||||
views:
|
||||
|
||||
@ -1,41 +1,42 @@
|
||||
---
|
||||
bounds: { x: 10, y: 10, width: 410, height: 229 }
|
||||
row_spacing: 11.33
|
||||
button_spacing: 4.67
|
||||
|
||||
bounds: { x: 0, y: 1, width: 360, height: 198 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
|
||||
bounds: { x: 0, y: 0, width: 30.67, height: 40.67 }
|
||||
altline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
||||
outline7:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
||||
bounds: { x: 0, y: 0, width: 48, height: 40.67 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 57.33, height: 40.67 }
|
||||
spaceline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
||||
bounds: { x: 0, y: 0, width: 137.33, height: 40.67 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 39.33, height: 40.67 }
|
||||
|
||||
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 . Return"
|
||||
- "show_numbers 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 preferences space . Return"
|
||||
- "show_numbers preferences space period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space . Return"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
|
||||
buttons:
|
||||
Shift_L:
|
||||
@ -50,9 +51,14 @@ buttons:
|
||||
icon: "edit-clear-symbolic"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
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"
|
||||
@ -60,20 +66,21 @@ buttons:
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
".":
|
||||
outline: altline
|
||||
period:
|
||||
outline: "special"
|
||||
label: "."
|
||||
space:
|
||||
outline: spaceline
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: outline7
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
|
||||
@ -1,21 +1,33 @@
|
||||
.keyboard {
|
||||
sq_view {
|
||||
background-color: rgba(0, 0, 0, 255);
|
||||
color: #ffffff;
|
||||
font-family: cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.key {
|
||||
sq_button {
|
||||
color: #deddda;
|
||||
background: #464448;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #5e5c64;
|
||||
border-radius: 2px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.key:active {
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
sq_button:active {
|
||||
background: #545256;
|
||||
border-color: #716e78;
|
||||
}
|
||||
|
||||
sq_button.altline,
|
||||
sq_button.special,
|
||||
sq_button.wide {
|
||||
background: #2b292f;
|
||||
border-color: #3e3a44
|
||||
}
|
||||
|
||||
sq_button.locked {
|
||||
background: #ffffff;
|
||||
color: #2b292f;
|
||||
}
|
||||
|
||||
#Return {
|
||||
@ -27,13 +39,3 @@
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
}
|
||||
|
||||
#Shift_L {
|
||||
background: #2b292f;
|
||||
border-color: #3e3a44
|
||||
}
|
||||
|
||||
#Shift_L:active {
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
}
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
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
|
||||
|
||||
2
debian/rules
vendored
2
debian/rules
vendored
@ -8,7 +8,7 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
# The Debian version of linked-hash-map doesn't provide any hash,
|
||||
# causing Cargo to refuse to build with a crates.io copy
|
||||
build:
|
||||
build-arch:
|
||||
rm Cargo.lock
|
||||
dh $@ --builddirectory=_build --buildsystem=meson
|
||||
|
||||
|
||||
@ -52,8 +52,6 @@ typedef struct _EekGtkKeyboardPrivate
|
||||
{
|
||||
EekRenderer *renderer;
|
||||
LevelKeyboard *keyboard;
|
||||
GtkCssProvider *css_provider;
|
||||
GtkStyleContext *scontext;
|
||||
|
||||
GdkEventSequence *sequence; // unowned reference
|
||||
} EekGtkKeyboardPrivate;
|
||||
@ -98,7 +96,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
if (!priv->renderer) {
|
||||
PangoContext *pcontext = gtk_widget_get_pango_context (self);
|
||||
|
||||
priv->renderer = eek_renderer_new (priv->keyboard, pcontext, priv->scontext);
|
||||
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
|
||||
|
||||
eek_renderer_set_allocation_size (priv->renderer,
|
||||
allocation.width,
|
||||
@ -383,22 +381,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
|
||||
|
||||
static void
|
||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
/* Create a default CSS provider and load a style sheet */
|
||||
priv->css_provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (priv->css_provider,
|
||||
"/sm/puri/squeekboard/style.css");
|
||||
|
||||
/* Apply the style to the widget */
|
||||
priv->scontext = gtk_widget_get_style_context (GTK_WIDGET(self));
|
||||
gtk_style_context_add_class (priv->scontext, "keyboard");
|
||||
gtk_style_context_add_provider (priv->scontext,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
gtk_style_context_set_state (priv->scontext, GTK_STATE_FLAG_NORMAL);
|
||||
}
|
||||
{}
|
||||
|
||||
/**
|
||||
* eek_gtk_keyboard_new:
|
||||
|
||||
@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "eek-types.h"
|
||||
|
||||
static gdouble
|
||||
length (gdouble x, gdouble y)
|
||||
{
|
||||
return sqrt (x * x + y * y);
|
||||
}
|
||||
|
||||
static gdouble
|
||||
point_line_distance (gdouble ax, gdouble ay, gdouble nx, gdouble ny)
|
||||
{
|
||||
return ax * nx + ay * ny;
|
||||
}
|
||||
|
||||
static void
|
||||
normal_form (gdouble ax, gdouble ay,
|
||||
gdouble bx, gdouble by,
|
||||
gdouble * nx, gdouble * ny, gdouble * d)
|
||||
{
|
||||
gdouble l;
|
||||
|
||||
*nx = by - ay;
|
||||
*ny = ax - bx;
|
||||
|
||||
l = length (*nx, *ny);
|
||||
|
||||
*nx /= l;
|
||||
*ny /= l;
|
||||
|
||||
*d = point_line_distance (ax, ay, *nx, *ny);
|
||||
}
|
||||
|
||||
static void
|
||||
inverse (gdouble a, gdouble b, gdouble c, gdouble d,
|
||||
gdouble * e, gdouble * f, gdouble * g, gdouble * h)
|
||||
{
|
||||
gdouble det;
|
||||
|
||||
det = a * d - b * c;
|
||||
|
||||
*e = d / det;
|
||||
*f = -b / det;
|
||||
*g = -c / det;
|
||||
*h = a / det;
|
||||
}
|
||||
|
||||
static void
|
||||
multiply (gdouble a, gdouble b, gdouble c, gdouble d,
|
||||
gdouble e, gdouble f, gdouble * x, gdouble * y)
|
||||
{
|
||||
*x = a * e + b * f;
|
||||
*y = c * e + d * f;
|
||||
}
|
||||
|
||||
static void
|
||||
intersect (gdouble n1x, gdouble n1y, gdouble d1,
|
||||
gdouble n2x, gdouble n2y, gdouble d2, gdouble * x, gdouble * y)
|
||||
{
|
||||
gdouble e, f, g, h;
|
||||
|
||||
inverse (n1x, n1y, n2x, n2y, &e, &f, &g, &h);
|
||||
multiply (e, f, g, h, d1, d2, x, y);
|
||||
}
|
||||
|
||||
|
||||
/* draw an angle from the current point to b and then to c,
|
||||
* with a rounded corner of the given radius.
|
||||
*/
|
||||
static void
|
||||
rounded_corner (cairo_t * cr,
|
||||
gdouble bx, gdouble by,
|
||||
gdouble cx, gdouble cy, gdouble radius)
|
||||
{
|
||||
gdouble ax, ay;
|
||||
gdouble n1x, n1y, d1;
|
||||
gdouble n2x, n2y, d2;
|
||||
gdouble pd1, pd2;
|
||||
gdouble ix, iy;
|
||||
gdouble dist1, dist2;
|
||||
gdouble nx, ny, d;
|
||||
gdouble a1x, a1y, c1x, c1y;
|
||||
gdouble phi1, phi2;
|
||||
|
||||
cairo_get_current_point (cr, &ax, &ay);
|
||||
#ifdef KBDRAW_DEBUG
|
||||
printf (" current point: (%f, %f), radius %f:\n", ax, ay,
|
||||
radius);
|
||||
#endif
|
||||
|
||||
/* make sure radius is not too large */
|
||||
dist1 = length (bx - ax, by - ay);
|
||||
dist2 = length (cx - bx, cy - by);
|
||||
|
||||
radius = MIN (radius, MIN (dist1, dist2));
|
||||
|
||||
/* construct normal forms of the lines */
|
||||
normal_form (ax, ay, bx, by, &n1x, &n1y, &d1);
|
||||
normal_form (bx, by, cx, cy, &n2x, &n2y, &d2);
|
||||
|
||||
/* find which side of the line a,b the point c is on */
|
||||
if (point_line_distance (cx, cy, n1x, n1y) < d1)
|
||||
pd1 = d1 - radius;
|
||||
else
|
||||
pd1 = d1 + radius;
|
||||
|
||||
/* find which side of the line b,c the point a is on */
|
||||
if (point_line_distance (ax, ay, n2x, n2y) < d2)
|
||||
pd2 = d2 - radius;
|
||||
else
|
||||
pd2 = d2 + radius;
|
||||
|
||||
/* intersect the parallels to find the center of the arc */
|
||||
intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy);
|
||||
|
||||
nx = (bx - ax) / dist1;
|
||||
ny = (by - ay) / dist1;
|
||||
d = point_line_distance (ix, iy, nx, ny);
|
||||
|
||||
/* a1 is the point on the line a-b where the arc starts */
|
||||
intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y);
|
||||
|
||||
nx = (cx - bx) / dist2;
|
||||
ny = (cy - by) / dist2;
|
||||
d = point_line_distance (ix, iy, nx, ny);
|
||||
|
||||
/* c1 is the point on the line b-c where the arc ends */
|
||||
intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y);
|
||||
|
||||
/* determine the first angle */
|
||||
if (a1x - ix == 0)
|
||||
phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
|
||||
else if (a1x - ix > 0)
|
||||
phi1 = atan ((a1y - iy) / (a1x - ix));
|
||||
else
|
||||
phi1 = M_PI + atan ((a1y - iy) / (a1x - ix));
|
||||
|
||||
/* determine the second angle */
|
||||
if (c1x - ix == 0)
|
||||
phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
|
||||
else if (c1x - ix > 0)
|
||||
phi2 = atan ((c1y - iy) / (c1x - ix));
|
||||
else
|
||||
phi2 = M_PI + atan ((c1y - iy) / (c1x - ix));
|
||||
|
||||
/* compute the difference between phi2 and phi1 mod 2pi */
|
||||
d = phi2 - phi1;
|
||||
while (d < 0)
|
||||
d += 2 * M_PI;
|
||||
while (d > 2 * M_PI)
|
||||
d -= 2 * M_PI;
|
||||
|
||||
#ifdef KBDRAW_DEBUG
|
||||
printf (" line 1 to: (%f, %f):\n", a1x, a1y);
|
||||
#endif
|
||||
if (!(isnan (a1x) || isnan (a1y)))
|
||||
cairo_line_to (cr, a1x, a1y);
|
||||
|
||||
/* pick the short arc from phi1 to phi2 */
|
||||
if (d < M_PI)
|
||||
cairo_arc (cr, ix, iy, radius, phi1, phi2);
|
||||
else
|
||||
cairo_arc_negative (cr, ix, iy, radius, phi1, phi2);
|
||||
|
||||
#ifdef KBDRAW_DEBUG
|
||||
printf (" line 2 to: (%f, %f):\n", cx, cy);
|
||||
#endif
|
||||
cairo_line_to (cr, cx, cy);
|
||||
}
|
||||
|
||||
/* renamed from rounded_polygon, use EekPoint instead of GdkPoint not
|
||||
to depend on GTK+, and exported */
|
||||
void
|
||||
_eek_rounded_polygon (cairo_t *cr,
|
||||
gdouble radius,
|
||||
EekPoint *points,
|
||||
guint num_points)
|
||||
{
|
||||
cairo_move_to (cr,
|
||||
(gdouble) (points[num_points - 1].x +
|
||||
points[0].x) / 2,
|
||||
(gdouble) (points[num_points - 1].y +
|
||||
points[0].y) / 2);
|
||||
|
||||
for (guint i = 0; i < num_points; i++) {
|
||||
guint j = (i + 1) % num_points;
|
||||
rounded_corner (cr, (gdouble) points[i].x,
|
||||
(gdouble) points[i].y,
|
||||
(gdouble) (points[i].x + points[j].x) / 2,
|
||||
(gdouble) (points[i].y + points[j].y) / 2,
|
||||
radius);
|
||||
}
|
||||
cairo_close_path (cr);
|
||||
}
|
||||
@ -29,7 +29,6 @@
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PCONTEXT,
|
||||
PROP_STYLE_CONTEXT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -38,11 +37,9 @@ typedef struct _EekRendererPrivate
|
||||
LevelKeyboard *keyboard;
|
||||
PangoContext *pcontext;
|
||||
GtkCssProvider *css_provider;
|
||||
GtkStyleContext *scontext;
|
||||
GtkStyleContext *key_context;
|
||||
GtkStyleContext *layout_context;
|
||||
GtkStyleContext *button_context; // TODO: maybe move a copy to each button
|
||||
|
||||
EekColor default_foreground_color;
|
||||
EekColor default_background_color;
|
||||
gdouble border_width;
|
||||
|
||||
gdouble allocation_width;
|
||||
@ -54,6 +51,7 @@ typedef struct _EekRendererPrivate
|
||||
|
||||
PangoFontDescription *ascii_font;
|
||||
PangoFontDescription *font;
|
||||
// TODO: Drop those or transform into general button surface caches
|
||||
GHashTable *outline_surface_cache;
|
||||
GHashTable *active_outline_surface_cache;
|
||||
GHashTable *icons;
|
||||
@ -63,15 +61,7 @@ typedef struct _EekRendererPrivate
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
|
||||
|
||||
static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0};
|
||||
static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
/* eek-keyboard-drawing.c */
|
||||
extern void _eek_rounded_polygon (cairo_t *cr,
|
||||
gdouble radius,
|
||||
EekPoint *points,
|
||||
guint num_points);
|
||||
|
||||
static void eek_renderer_real_render_button_label (EekRenderer *self,
|
||||
PangoLayout *layout,
|
||||
const struct squeek_button *button);
|
||||
@ -79,7 +69,7 @@ static void eek_renderer_real_render_button_label (EekRenderer *self,
|
||||
static void invalidate (EekRenderer *renderer);
|
||||
static void render_button (EekRenderer *self,
|
||||
cairo_t *cr, struct button_place *place,
|
||||
gboolean active);
|
||||
gboolean pressed, gboolean locked);
|
||||
|
||||
struct _CreateKeyboardSurfaceCallbackData {
|
||||
cairo_t *cr;
|
||||
@ -109,7 +99,7 @@ create_keyboard_surface_button_callback (struct squeek_button *button,
|
||||
.row = data->row,
|
||||
.button = button,
|
||||
};
|
||||
render_button (data->renderer, data->cr, &place, FALSE);
|
||||
render_button (data->renderer, data->cr, &place, FALSE, FALSE);
|
||||
|
||||
cairo_restore (data->cr);
|
||||
}
|
||||
@ -140,7 +130,7 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view)
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
EekColor foreground;
|
||||
|
||||
eek_renderer_get_foreground_color (renderer, priv->scontext, &foreground);
|
||||
eek_renderer_get_foreground_color (renderer, priv->layout_context, &foreground);
|
||||
|
||||
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
|
||||
|
||||
@ -151,11 +141,11 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view)
|
||||
};
|
||||
|
||||
/* Paint the background covering the entire widget area */
|
||||
gtk_render_background (priv->scontext,
|
||||
gtk_render_background (priv->layout_context,
|
||||
data.cr,
|
||||
0, 0,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
gtk_render_frame (priv->scontext,
|
||||
gtk_render_frame (priv->layout_context,
|
||||
data.cr,
|
||||
0, 0,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
@ -180,49 +170,25 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view)
|
||||
}
|
||||
|
||||
static void
|
||||
render_button_outline (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
const struct squeek_button *button,
|
||||
gboolean active)
|
||||
render_outline (cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
EekBounds bounds)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
EekBounds bounds = squeek_button_get_bounds(button);
|
||||
|
||||
/* 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 (priv->key_context));
|
||||
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. */
|
||||
gtk_style_context_set_path (priv->key_context, path);
|
||||
|
||||
/* Set the state to take into account whether the button is active
|
||||
(pressed) or normal. */
|
||||
gtk_style_context_set_state(priv->key_context,
|
||||
active ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
|
||||
|
||||
gtk_render_background (priv->key_context,
|
||||
cr, 0, 0, bounds.width, bounds.height);
|
||||
gtk_render_frame (priv->key_context,
|
||||
cr, 0, 0, bounds.width, bounds.height);
|
||||
|
||||
gtk_style_context_set_state(priv->key_context, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_render_background (ctx, cr, 0, 0, bounds.width, bounds.height);
|
||||
gtk_render_frame (ctx, cr, 0, 0, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
static void
|
||||
render_button (EekRenderer *self,
|
||||
static void render_button_in_context(EekRenderer *self,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
struct button_place *place,
|
||||
gboolean active)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
gboolean active) {
|
||||
cairo_surface_t *outline_surface;
|
||||
GHashTable *outline_surface_cache;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle extents = { 0, };
|
||||
EekColor foreground;
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
/* render outline */
|
||||
EekBounds bounds = squeek_button_get_bounds(place->button);
|
||||
@ -233,6 +199,7 @@ render_button (EekRenderer *self,
|
||||
outline_surface_cache = priv->outline_surface_cache;
|
||||
|
||||
outline_surface = g_hash_table_lookup (outline_surface_cache, place->button);
|
||||
|
||||
if (!outline_surface) {
|
||||
cairo_t *cr;
|
||||
|
||||
@ -250,7 +217,7 @@ render_button (EekRenderer *self,
|
||||
|
||||
cairo_save (cr);
|
||||
eek_renderer_apply_transformation_for_button (self, cr, place, 1.0, FALSE);
|
||||
render_button_outline (self, cr, place->button, active);
|
||||
render_outline (cr, ctx, bounds);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
@ -259,11 +226,10 @@ render_button (EekRenderer *self,
|
||||
(gpointer)place->button,
|
||||
outline_surface);
|
||||
}
|
||||
|
||||
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
|
||||
cairo_paint (cr);
|
||||
|
||||
eek_renderer_get_foreground_color (self, priv->key_context, &foreground);
|
||||
eek_renderer_get_foreground_color (self, ctx, &foreground);
|
||||
/* render icon (if any) */
|
||||
const char *icon_name = squeek_button_get_icon_name(place->button);
|
||||
|
||||
@ -294,7 +260,6 @@ render_button (EekRenderer *self,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* render label */
|
||||
layout = pango_cairo_create_layout (cr);
|
||||
eek_renderer_real_render_button_label (self, layout, place->button);
|
||||
@ -311,10 +276,49 @@ render_button (EekRenderer *self,
|
||||
foreground.green,
|
||||
foreground.blue,
|
||||
foreground.alpha);
|
||||
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
cairo_restore (cr);
|
||||
g_object_unref (layout);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
render_button (EekRenderer *self,
|
||||
cairo_t *cr,
|
||||
struct button_place *place,
|
||||
gboolean pressed,
|
||||
gboolean locked)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
|
||||
GtkStyleContext *ctx = priv->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(place->button);
|
||||
gtk_widget_path_iter_set_name (path, -1, name);
|
||||
|
||||
/* Update the style context with the updated widget path. */
|
||||
gtk_style_context_set_path (ctx, path);
|
||||
/* Set the state to take into account whether the button is active
|
||||
(pressed) or normal. */
|
||||
gtk_style_context_set_state(ctx,
|
||||
pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
|
||||
const char *outline_name = squeek_button_get_outline_name(place->button);
|
||||
if (locked) {
|
||||
gtk_style_context_add_class(ctx, "locked");
|
||||
}
|
||||
gtk_style_context_add_class(ctx, outline_name);
|
||||
|
||||
render_button_in_context(self, cr, ctx, place, pressed);
|
||||
|
||||
// Save and restore functions don't work if gtk_render_* was used in between
|
||||
gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_style_context_remove_class(ctx, outline_name);
|
||||
if (locked) {
|
||||
gtk_style_context_remove_class(ctx, "locked");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -445,7 +449,8 @@ eek_renderer_real_render_button (EekRenderer *self,
|
||||
struct squeek_key *key = squeek_button_get_key(place->button);
|
||||
render_button (
|
||||
self, cr, place,
|
||||
squeek_key_is_pressed(key) || squeek_key_is_locked (key)
|
||||
squeek_key_is_pressed(key),
|
||||
squeek_key_is_locked (key)
|
||||
);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
@ -496,10 +501,6 @@ eek_renderer_set_property (GObject *object,
|
||||
priv->pcontext = g_value_get_object (value);
|
||||
g_object_ref (priv->pcontext);
|
||||
break;
|
||||
case PROP_STYLE_CONTEXT:
|
||||
priv->scontext = g_value_get_object (value);
|
||||
g_object_ref (priv->scontext);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -576,15 +577,33 @@ eek_renderer_class_init (EekRendererClass *klass)
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PCONTEXT,
|
||||
pspec);
|
||||
}
|
||||
|
||||
pspec = g_param_spec_object ("style-context",
|
||||
"GTK Style Context",
|
||||
"GTK Style Context",
|
||||
GTK_TYPE_STYLE_CONTEXT,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_STYLE_CONTEXT,
|
||||
pspec);
|
||||
|
||||
static GType new_type(char *name) {
|
||||
GTypeInfo info = {0};
|
||||
info.class_size = sizeof(GtkWidgetClass);
|
||||
info.instance_size = sizeof(GtkWidget);
|
||||
|
||||
return g_type_register_static(GTK_TYPE_WIDGET, name, &info,
|
||||
G_TYPE_FLAG_ABSTRACT
|
||||
);
|
||||
}
|
||||
|
||||
static GType layout_type() {
|
||||
static GType type = 0;
|
||||
if (!type) {
|
||||
type = new_type("sq_view");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static GType button_type() {
|
||||
static GType type = 0;
|
||||
if (!type) {
|
||||
type = new_type("sq_button");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -594,8 +613,6 @@ eek_renderer_init (EekRenderer *self)
|
||||
|
||||
priv->keyboard = NULL;
|
||||
priv->pcontext = NULL;
|
||||
priv->default_foreground_color = DEFAULT_FOREGROUND_COLOR;
|
||||
priv->default_background_color = DEFAULT_BACKGROUND_COLOR;
|
||||
priv->border_width = 1.0;
|
||||
priv->allocation_width = 0.0;
|
||||
priv->allocation_height = 0.0;
|
||||
@ -627,18 +644,30 @@ eek_renderer_init (EekRenderer *self)
|
||||
gtk_css_provider_load_from_resource (priv->css_provider,
|
||||
"/sm/puri/squeekboard/style.css");
|
||||
|
||||
/* Create a style context for keys */
|
||||
priv->key_context = gtk_style_context_new ();
|
||||
gtk_style_context_add_class (priv->key_context, "key");
|
||||
gtk_style_context_add_provider (priv->key_context,
|
||||
/* Create a style context for the layout */
|
||||
GtkWidgetPath *path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type(path, layout_type());
|
||||
|
||||
priv->layout_context = gtk_style_context_new();
|
||||
gtk_style_context_set_path(priv->layout_context, path);
|
||||
gtk_widget_path_unref(path);
|
||||
gtk_style_context_add_provider (priv->layout_context,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
|
||||
g_autoptr (GtkWidgetPath) path = NULL;
|
||||
/* Create a style context for the buttons */
|
||||
path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
|
||||
gtk_style_context_set_path (priv->key_context, path);
|
||||
gtk_style_context_set_state (priv->key_context, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_widget_path_append_type(path, layout_type());
|
||||
gtk_widget_path_append_type(path, button_type());
|
||||
priv->button_context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path(priv->button_context, path);
|
||||
gtk_widget_path_unref(path);
|
||||
|
||||
gtk_style_context_set_parent(priv->button_context, priv->layout_context);
|
||||
gtk_style_context_set_state (priv->button_context, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_style_context_add_provider (priv->button_context,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -660,12 +689,10 @@ invalidate (EekRenderer *renderer)
|
||||
|
||||
EekRenderer *
|
||||
eek_renderer_new (LevelKeyboard *keyboard,
|
||||
PangoContext *pcontext,
|
||||
GtkStyleContext *scontext)
|
||||
PangoContext *pcontext)
|
||||
{
|
||||
EekRenderer *renderer = g_object_new (EEK_TYPE_RENDERER,
|
||||
"pango-context", pcontext,
|
||||
"style-context", scontext,
|
||||
NULL);
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
priv->keyboard = keyboard;
|
||||
@ -759,7 +786,7 @@ eek_renderer_get_button_bounds (EekRenderer *renderer,
|
||||
|
||||
min = points[2];
|
||||
max = points[0];
|
||||
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
|
||||
for (unsigned i = 0; i < G_N_ELEMENTS(points); i++) {
|
||||
eek_point_rotate (&points[i], angle);
|
||||
if (points[i].x < min.x)
|
||||
min.x = points[i].x;
|
||||
@ -862,30 +889,6 @@ eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
EEK_RENDERER_GET_CLASS(renderer)->render_keyboard (renderer, cr);
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_default_foreground_color (EekRenderer *renderer,
|
||||
const EekColor *color)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (color);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
|
||||
memcpy (&priv->default_foreground_color, color, sizeof(EekColor));
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_default_background_color (EekRenderer *renderer,
|
||||
const EekColor *color)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (color);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
|
||||
memcpy (&priv->default_background_color, color, sizeof(EekColor));
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_get_foreground_color (EekRenderer *renderer,
|
||||
GtkStyleContext *context,
|
||||
@ -927,7 +930,7 @@ eek_are_bounds_inside (EekBounds bounds, EekPoint point, EekPoint origin, int32_
|
||||
points[3].x = points[0].x;
|
||||
points[3].y = points[2].y;
|
||||
|
||||
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
|
||||
for (unsigned i = 0; i < G_N_ELEMENTS(points); i++) {
|
||||
eek_point_rotate (&points[i], angle);
|
||||
points[i].x += origin.x;
|
||||
points[i].y += origin.y;
|
||||
|
||||
@ -57,8 +57,7 @@ struct _EekRendererClass
|
||||
|
||||
GType eek_renderer_get_type (void) G_GNUC_CONST;
|
||||
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
|
||||
PangoContext *pcontext,
|
||||
GtkStyleContext *scontext);
|
||||
PangoContext *pcontext);
|
||||
void eek_renderer_set_allocation_size
|
||||
(EekRenderer *renderer,
|
||||
gdouble width,
|
||||
|
||||
@ -51,7 +51,6 @@ enum {
|
||||
PROP_0, // Magic: without this, keyboard is not useable in g_object_notify
|
||||
PROP_KEYBOARD,
|
||||
PROP_VISIBLE,
|
||||
PROP_FULLSCREEN,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -70,7 +69,6 @@ static guint signals[LAST_SIGNAL] = { 0, };
|
||||
struct _EekboardContextServicePrivate {
|
||||
gboolean enabled;
|
||||
gboolean visible;
|
||||
gboolean fullscreen;
|
||||
|
||||
LevelKeyboard *keyboard; // currently used keyboard
|
||||
GHashTable *keyboard_hash; // a table of available keyboards, per layout
|
||||
@ -170,9 +168,6 @@ eekboard_context_service_set_property (GObject *object,
|
||||
case PROP_VISIBLE:
|
||||
context->priv->visible = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_FULLSCREEN:
|
||||
context->priv->fullscreen = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -194,9 +189,6 @@ eekboard_context_service_get_property (GObject *object,
|
||||
case PROP_VISIBLE:
|
||||
g_value_set_boolean (value, context->priv->visible);
|
||||
break;
|
||||
case PROP_FULLSCREEN:
|
||||
g_value_set_boolean (value, context->priv->fullscreen);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -401,20 +393,6 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VISIBLE,
|
||||
pspec);
|
||||
|
||||
/**
|
||||
* EekboardContextService:fullscreen:
|
||||
*
|
||||
* Flag to indicate if keyboard is rendered in fullscreen mode.
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("fullscreen",
|
||||
"Fullscreen",
|
||||
"Fullscreen",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FULLSCREEN,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -524,19 +502,6 @@ eekboard_context_service_get_keyboard (EekboardContextService *context)
|
||||
return context->priv->keyboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_service_get_fullscreen:
|
||||
* @context: an #EekboardContextService
|
||||
*
|
||||
* Check if keyboard is rendered in fullscreen mode in @context.
|
||||
* Returns: %TRUE or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
eekboard_context_service_get_fullscreen (EekboardContextService *context)
|
||||
{
|
||||
return context->priv->fullscreen;
|
||||
}
|
||||
|
||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
|
||||
const LevelKeyboard *keyboard)
|
||||
{
|
||||
|
||||
@ -98,8 +98,6 @@ void eekboard_context_service_hide_keyboard
|
||||
(EekboardContextService *context);
|
||||
void eekboard_context_service_destroy (EekboardContextService *context);
|
||||
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
|
||||
gboolean eekboard_context_service_get_fullscreen
|
||||
(EekboardContextService *context);
|
||||
|
||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
|
||||
const LevelKeyboard *keyboard);
|
||||
|
||||
@ -1,654 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eekboard-context
|
||||
* @short_description: client interface of eekboard input context service
|
||||
*
|
||||
* The #EekboardContext class provides a client access to remote input
|
||||
* context.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eekboard/eekboard-context.h"
|
||||
//#include "eekboard/eekboard-marshalers.h"
|
||||
|
||||
#define I_(string) g_intern_static_string (string)
|
||||
|
||||
enum {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_VISIBLE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
typedef struct _EekboardContextPrivate
|
||||
{
|
||||
gboolean visible;
|
||||
gboolean enabled;
|
||||
gboolean fullscreen;
|
||||
gint group;
|
||||
} EekboardContextPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContext, eekboard_context, G_TYPE_DBUS_PROXY)
|
||||
|
||||
static void
|
||||
eekboard_context_real_g_signal (GDBusProxy *self,
|
||||
const gchar *sender_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters)
|
||||
{
|
||||
EekboardContext *context = EEKBOARD_CONTEXT (self);
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (g_strcmp0 (signal_name, "Enabled") == 0) {
|
||||
g_signal_emit (context, signals[ENABLED], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (signal_name, "Disabled") == 0) {
|
||||
g_signal_emit (context, signals[DISABLED], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (signal_name, "Destroyed") == 0) {
|
||||
g_signal_emit (context, signals[DESTROYED], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (signal_name, "VisibilityChanged") == 0) {
|
||||
gboolean visible = FALSE;
|
||||
|
||||
g_variant_get (parameters, "(b)", &visible);
|
||||
if (visible != priv->visible) {
|
||||
priv->visible = visible;
|
||||
g_object_notify (G_OBJECT(context), "visible");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (signal_name, "GroupChanged") == 0) {
|
||||
gint group = 0;
|
||||
|
||||
g_variant_get (parameters, "(i)", &group);
|
||||
if (group != priv->group) {
|
||||
priv->group = group;
|
||||
/* g_object_notify (G_OBJECT(context), "group"); */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_real_enabled (EekboardContext *self)
|
||||
{
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (self);
|
||||
|
||||
priv->enabled = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_real_disabled (EekboardContext *self)
|
||||
{
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (self);
|
||||
|
||||
priv->enabled = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_real_destroyed (EekboardContext *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekboardContext *context = EEKBOARD_CONTEXT(object);
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_VISIBLE:
|
||||
g_value_set_boolean (value, priv->visible);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_class_init (EekboardContextClass *klass)
|
||||
{
|
||||
GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
klass->enabled = eekboard_context_real_enabled;
|
||||
klass->disabled = eekboard_context_real_disabled;
|
||||
klass->destroyed = eekboard_context_real_destroyed;
|
||||
|
||||
proxy_class->g_signal = eekboard_context_real_g_signal;
|
||||
|
||||
gobject_class->get_property = eekboard_context_get_property;
|
||||
|
||||
/**
|
||||
* EekboardContext:visible:
|
||||
*
|
||||
* Flag to indicate if keyboard is visible or not.
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("visible",
|
||||
"visible",
|
||||
"Flag that indicates if keyboard is visible",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VISIBLE,
|
||||
pspec);
|
||||
|
||||
/**
|
||||
* EekboardContext::enabled:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* Emitted when @context is enabled.
|
||||
*/
|
||||
signals[ENABLED] =
|
||||
g_signal_new (I_("enabled"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextClass, enabled),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EekboardContext::disabled:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* The ::disabled signal is emitted each time @context is disabled.
|
||||
*/
|
||||
signals[DISABLED] =
|
||||
g_signal_new (I_("disabled"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextClass, disabled),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/**
|
||||
* EekboardContext::destroyed:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* The ::destroyed signal is emitted each time the name of remote
|
||||
* end is vanished.
|
||||
*/
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextClass, destroyed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_init (EekboardContext *self)
|
||||
{
|
||||
/* void */
|
||||
}
|
||||
|
||||
static void
|
||||
context_name_vanished_callback (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardContext *context = user_data;
|
||||
g_signal_emit (context, signals[DESTROYED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_new:
|
||||
* @connection: a #GDBusConnection
|
||||
* @object_path: object path
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Create a D-Bus proxy of an input context maintained by
|
||||
* eekboard-server. This function is seldom called from applications
|
||||
* since eekboard_server_create_context() calls it implicitly.
|
||||
*/
|
||||
EekboardContext *
|
||||
eekboard_context_new (GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GInitable *initable;
|
||||
GError *error;
|
||||
|
||||
g_return_val_if_fail (object_path != NULL, NULL);
|
||||
g_return_val_if_fail (G_IS_DBUS_CONNECTION(connection), NULL);
|
||||
|
||||
error = NULL;
|
||||
initable =
|
||||
g_initable_new (EEKBOARD_TYPE_CONTEXT,
|
||||
cancellable,
|
||||
&error,
|
||||
"g-name", "org.fedorahosted.Eekboard",
|
||||
"g-connection", connection,
|
||||
"g-interface-name", "org.fedorahosted.Eekboard.Context",
|
||||
"g-object-path", object_path,
|
||||
NULL);
|
||||
if (initable != NULL) {
|
||||
EekboardContext *context = EEKBOARD_CONTEXT (initable);
|
||||
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(context));
|
||||
|
||||
if (name_owner == NULL) {
|
||||
g_object_unref (context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the vanished callback is called when the server is disconnected */
|
||||
g_bus_watch_name_on_connection (connection,
|
||||
name_owner,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
NULL,
|
||||
context_name_vanished_callback,
|
||||
context,
|
||||
NULL);
|
||||
g_free (name_owner);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
g_warning ("can't create context client: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
context_async_ready_callback (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
|
||||
result = g_dbus_proxy_call_finish (G_DBUS_PROXY(source_object),
|
||||
res,
|
||||
&error);
|
||||
if (result)
|
||||
g_variant_unref (result);
|
||||
else {
|
||||
g_warning ("error in D-Bus proxy call: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_add_keyboard:
|
||||
* @context: an #EekboardContext
|
||||
* @keyboard: a string representing keyboard
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Register @keyboard in @context.
|
||||
*/
|
||||
guint
|
||||
eekboard_context_add_keyboard (EekboardContext *context,
|
||||
const gchar *keyboard,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GVariant *result;
|
||||
GError *error;
|
||||
|
||||
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), 0);
|
||||
|
||||
error = NULL;
|
||||
result = g_dbus_proxy_call_sync (G_DBUS_PROXY(context),
|
||||
"AddKeyboard",
|
||||
g_variant_new ("(s)", keyboard),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
&error);
|
||||
|
||||
if (result) {
|
||||
guint keyboard_id;
|
||||
|
||||
g_variant_get (result, "(u)", &keyboard_id);
|
||||
g_variant_unref (result);
|
||||
|
||||
return keyboard_id;
|
||||
}
|
||||
|
||||
g_warning ("error in AddKeyboard call: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_remove_keyboard:
|
||||
* @context: an #EekboardContext
|
||||
* @keyboard_id: keyboard ID
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Unregister the keyboard with @keyboard_id in @context.
|
||||
*/
|
||||
void
|
||||
eekboard_context_remove_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"RemoveKeyboard",
|
||||
g_variant_new ("(u)", keyboard_id),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_set_keyboard:
|
||||
* @context: an #EekboardContext
|
||||
* @keyboard_id: keyboard ID
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Select a keyboard with ID @keyboard_id in @context.
|
||||
*/
|
||||
void
|
||||
eekboard_context_set_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetKeyboard",
|
||||
g_variant_new ("(u)", keyboard_id),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_set_group:
|
||||
* @context: an #EekboardContext
|
||||
* @group: group number
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Set the keyboard group of @context.
|
||||
*/
|
||||
void
|
||||
eekboard_context_set_group (EekboardContext *context,
|
||||
gint group,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->group != group) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetGroup",
|
||||
g_variant_new ("(i)", group),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_get_group:
|
||||
* @context: an #EekboardContext
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Get the keyboard group of @context.
|
||||
*/
|
||||
gint
|
||||
eekboard_context_get_group (EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), 0);
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
return priv->group;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_show_keyboard:
|
||||
* @context: an #EekboardContext
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Request eekboard-server to show a keyboard set by
|
||||
* eekboard_context_set_keyboard().
|
||||
*/
|
||||
void
|
||||
eekboard_context_show_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->enabled) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"ShowKeyboard",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_hide_keyboard:
|
||||
* @context: an #EekboardContext
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Request eekboard-server to hide a keyboard.
|
||||
*/
|
||||
void
|
||||
eekboard_context_hide_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->enabled) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"HideKeyboard",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_press_keycode:
|
||||
* @context: an #EekboardContext
|
||||
* @keycode: keycode number
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Tell eekboard-server that a key identified by @keycode is pressed.
|
||||
*/
|
||||
void
|
||||
eekboard_context_press_keycode (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->enabled) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"PressKeycode",
|
||||
g_variant_new ("(u)", keycode),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_release_keycode:
|
||||
* @context: an #EekboardContext
|
||||
* @keycode: keycode number
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Tell eekboard-server that a key identified by @keycode is released.
|
||||
*/
|
||||
void
|
||||
eekboard_context_release_keycode (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->enabled) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"ReleaseKeycode",
|
||||
g_variant_new ("(u)", keycode),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_is_visible:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* Check if keyboard is visible.
|
||||
*/
|
||||
gboolean
|
||||
eekboard_context_is_visible (EekboardContext *context)
|
||||
{
|
||||
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), FALSE);
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
return priv->enabled && priv->visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_set_enabled:
|
||||
* @context: an #EekboardContext
|
||||
* @enabled: flag to indicate if @context is enabled
|
||||
*
|
||||
* Set @context enabled or disabled. This function is seldom called
|
||||
* since the flag is set via D-Bus signal #EekboardContext::enabled
|
||||
* and #EekboardContext::disabled.
|
||||
*/
|
||||
void
|
||||
eekboard_context_set_enabled (EekboardContext *context,
|
||||
gboolean enabled)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
priv->enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_is_enabled:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* Check if @context is enabled.
|
||||
*/
|
||||
gboolean
|
||||
eekboard_context_is_enabled (EekboardContext *context)
|
||||
{
|
||||
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), FALSE);
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
return priv->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_set_fullscreen:
|
||||
* @context: an #EekboardContext
|
||||
* @fullscreen: a flag to indicate fullscreen mode
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Set the fullscreen mode of @context.
|
||||
*/
|
||||
void
|
||||
eekboard_context_set_fullscreen (EekboardContext *context,
|
||||
gboolean fullscreen,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
|
||||
|
||||
if (priv->fullscreen != fullscreen) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetFullscreen",
|
||||
g_variant_new ("(b)", fullscreen),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if !defined(__EEKBOARD_CLIENT_H_INSIDE__) && !defined(EEKBOARD_COMPILATION)
|
||||
#error "Only <eekboard/eekboard-client.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef EEKBOARD_CONTEXT_H
|
||||
#define EEKBOARD_CONTEXT_H 1
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "eek/eek.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EEKBOARD_TYPE_CONTEXT (eekboard_context_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE (EekboardContext, eekboard_context, EEKBOARD, CONTEXT, GDBusProxy)
|
||||
|
||||
/**
|
||||
* EekboardContextClass:
|
||||
* @enabled: class handler for #EekboardContext::enabled signal
|
||||
* @disabled: class handler for #EekboardContext::disabled signal
|
||||
* @key_pressed: class handler for #EekboardContext::key-pressed signal
|
||||
* @destroyed: class handler for #EekboardContext::destroyed signal
|
||||
*/
|
||||
struct _EekboardContextClass {
|
||||
/*< private >*/
|
||||
GDBusProxyClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
/* signals */
|
||||
void (*enabled) (EekboardContext *self);
|
||||
void (*disabled) (EekboardContext *self);
|
||||
void (*destroyed) (EekboardContext *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eekboard_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekboardContext *eekboard_context_new (GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
GCancellable *cancellable);
|
||||
guint eekboard_context_add_keyboard (EekboardContext *context,
|
||||
const gchar *keyboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_remove_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_show_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_hide_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_group (EekboardContext *context,
|
||||
gint group,
|
||||
GCancellable *cancellable);
|
||||
gint eekboard_context_get_group (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_press_keycode (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_release_keycode (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
gboolean eekboard_context_is_visible
|
||||
(EekboardContext *context);
|
||||
void eekboard_context_set_enabled (EekboardContext *context,
|
||||
gboolean enabled);
|
||||
gboolean eekboard_context_is_enabled (EekboardContext *context);
|
||||
void eekboard_context_set_fullscreen (EekboardContext *context,
|
||||
gboolean fullscreen,
|
||||
GCancellable *cancellable);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_CONTEXT_H */
|
||||
@ -3,13 +3,13 @@ extern crate xkbcommon;
|
||||
|
||||
use std::env;
|
||||
|
||||
use rs::data::{ load_layout_from_resource, LoadError };
|
||||
use rs::data::{ Layout, LoadError };
|
||||
|
||||
use xkbcommon::xkb;
|
||||
|
||||
|
||||
fn check_layout(name: &str) {
|
||||
let layout = load_layout_from_resource(name)
|
||||
let layout = Layout::from_resource(name)
|
||||
.and_then(|layout| layout.build().map_err(LoadError::BadKeyMap))
|
||||
.expect("layout broken");
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
project(
|
||||
'squeekboard',
|
||||
'c', 'rust',
|
||||
version: '1.2.0',
|
||||
version: '1.2.1',
|
||||
license: 'GPLv3',
|
||||
meson_version: '>=0.51.0',
|
||||
default_options: [
|
||||
|
||||
194
src/data.rs
194
src/data.rs
@ -67,15 +67,7 @@ impl fmt::Display for LoadError {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_layout_from_resource(
|
||||
name: &str
|
||||
) -> Result<Layout, LoadError> {
|
||||
let data = resources::get_keyboard(name)
|
||||
.ok_or(LoadError::MissingResource)?;
|
||||
serde_yaml::from_str(data)
|
||||
.map_err(|e| LoadError::BadResource(e))
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum DataSource {
|
||||
File(PathBuf),
|
||||
Resource(String),
|
||||
@ -93,63 +85,90 @@ impl fmt::Display for DataSource {
|
||||
/// Tries to load the layout from the first place where it's present.
|
||||
/// If the layout exists, but is broken, fallback is activated.
|
||||
fn load_layout(
|
||||
name: &str
|
||||
) -> (Result<::layout::Layout, LoadError>, DataSource) {
|
||||
let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| xdg::data_path("squeekboard/keyboards"))
|
||||
.map(|path| path.join(name).with_extension("yaml"));
|
||||
|
||||
let (layout, source) = match path {
|
||||
Some(path) => {(
|
||||
Layout::from_yaml_stream(path.clone())
|
||||
.map_err(|e| LoadError::BadData(e)),
|
||||
DataSource::File(path)
|
||||
)},
|
||||
None => {(
|
||||
load_layout_from_resource(name),
|
||||
DataSource::Resource(name.into())
|
||||
)},
|
||||
};
|
||||
|
||||
let layout = layout.and_then(
|
||||
|layout| layout.build().map_err(LoadError::BadKeyMap)
|
||||
name: &str,
|
||||
keyboards_path: Option<PathBuf>,
|
||||
) -> (
|
||||
Result<::layout::Layout, LoadError>, // last attempted
|
||||
DataSource, // last attempt source
|
||||
Option<(LoadError, DataSource)>, // first attempt source
|
||||
) {
|
||||
let path = keyboards_path.map(|path|
|
||||
path.join(name).with_extension("yaml")
|
||||
);
|
||||
|
||||
(layout, source)
|
||||
let layout = match path {
|
||||
Some(path) => Some((
|
||||
Layout::from_file(path.clone())
|
||||
.map_err(LoadError::BadData)
|
||||
.and_then(|layout|
|
||||
layout.build().map_err(LoadError::BadKeyMap)
|
||||
),
|
||||
DataSource::File(path),
|
||||
)),
|
||||
None => None, // No env var, not an error
|
||||
};
|
||||
|
||||
let (failed_attempt, layout) = match layout {
|
||||
Some((Ok(layout), path)) => (None, Some((layout, path))),
|
||||
Some((Err(e), path)) => (Some((e, path)), None),
|
||||
None => (None, None),
|
||||
};
|
||||
|
||||
let (layout, source) = match layout {
|
||||
Some((layout, path)) => (Ok(layout), path),
|
||||
None => (
|
||||
Layout::from_resource(name)
|
||||
.and_then(|layout|
|
||||
layout.build().map_err(LoadError::BadKeyMap)
|
||||
),
|
||||
DataSource::Resource(name.into()),
|
||||
),
|
||||
};
|
||||
|
||||
(layout, source, failed_attempt)
|
||||
}
|
||||
|
||||
fn log_attempt_info(attempt: Option<(LoadError, DataSource)>) {
|
||||
match attempt {
|
||||
Some((
|
||||
LoadError::BadData(Error::Missing(_e)),
|
||||
DataSource::File(_file)
|
||||
)) => {
|
||||
// Missing file, not to worry. TODO: print in debug logging level
|
||||
}
|
||||
Some((e, source)) => {
|
||||
eprintln!(
|
||||
"Failed to load layout from {}: {}, trying builtin",
|
||||
source, e
|
||||
);
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn load_layout_with_fallback(
|
||||
name: &str
|
||||
) -> ::layout::Layout {
|
||||
let (layout, source) = load_layout(name);
|
||||
let (layout, source) = match (layout, source) {
|
||||
let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| xdg::data_path("squeekboard/keyboards"));
|
||||
|
||||
let (layout, source, attempt) = load_layout(name, path.clone());
|
||||
|
||||
log_attempt_info(attempt);
|
||||
|
||||
let (layout, source, attempt) = match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
eprintln!(
|
||||
"Failed to load layout from {}: {}, using fallback",
|
||||
source, e
|
||||
);
|
||||
load_layout(FALLBACK_LAYOUT_NAME)
|
||||
load_layout(FALLBACK_LAYOUT_NAME, path)
|
||||
},
|
||||
res => res,
|
||||
(res, source) => (res, source, None),
|
||||
};
|
||||
|
||||
let (layout, source) = match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
eprintln!(
|
||||
"Failed to load fallback layout from {}: {}, using hardcoded",
|
||||
source, e
|
||||
);
|
||||
(
|
||||
load_layout_from_resource(FALLBACK_LAYOUT_NAME)
|
||||
.and_then(
|
||||
|layout| layout.build().map_err(LoadError::BadKeyMap)
|
||||
),
|
||||
DataSource::Resource(FALLBACK_LAYOUT_NAME.into()),
|
||||
)
|
||||
},
|
||||
res => res,
|
||||
};
|
||||
log_attempt_info(attempt);
|
||||
|
||||
match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
@ -170,6 +189,8 @@ fn load_layout_with_fallback(
|
||||
#[derive(Debug, Deserialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Layout {
|
||||
row_spacing: f64,
|
||||
button_spacing: f64,
|
||||
bounds: Bounds,
|
||||
views: HashMap<String, Vec<ButtonIds>>,
|
||||
#[serde(default)]
|
||||
@ -218,14 +239,18 @@ enum Action {
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Outline {
|
||||
corner_radius: f64,
|
||||
bounds: Bounds,
|
||||
}
|
||||
|
||||
/// Errors encountered loading the layout into yaml
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Yaml(serde_yaml::Error),
|
||||
Io(io::Error),
|
||||
/// The file was missing.
|
||||
/// It's distinct from Io in order to make it matchable
|
||||
/// without calling io::Error::kind()
|
||||
Missing(io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@ -233,21 +258,38 @@ impl fmt::Display for Error {
|
||||
match self {
|
||||
Error::Yaml(e) => write!(f, "YAML: {}", e),
|
||||
Error::Io(e) => write!(f, "IO: {}", e),
|
||||
Error::Missing(e) => write!(f, "Missing: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Self {
|
||||
let kind = e.kind();
|
||||
match kind {
|
||||
io::ErrorKind::NotFound => Error::Missing(e),
|
||||
_ => Error::Io(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
fn from_yaml_stream(path: PathBuf) -> Result<Layout, Error> {
|
||||
pub fn from_resource(name: &str) -> Result<Layout, LoadError> {
|
||||
let data = resources::get_keyboard(name)
|
||||
.ok_or(LoadError::MissingResource)?;
|
||||
serde_yaml::from_str(data)
|
||||
.map_err(LoadError::BadResource)
|
||||
}
|
||||
|
||||
fn from_file(path: PathBuf) -> Result<Layout, Error> {
|
||||
let infile = BufReader::new(
|
||||
fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&path)
|
||||
.map_err(Error::Io)?
|
||||
.open(&path)?
|
||||
);
|
||||
serde_yaml::from_reader(infile)
|
||||
.map_err(Error::Yaml)
|
||||
serde_yaml::from_reader(infile).map_err(Error::Yaml)
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<::layout::Layout, FormattingError> {
|
||||
let button_names = self.views.values()
|
||||
.flat_map(|rows| {
|
||||
@ -303,6 +345,10 @@ impl Layout {
|
||||
width: self.bounds.width,
|
||||
height: self.bounds.height,
|
||||
},
|
||||
spacing: ::layout::Spacing {
|
||||
row: self.row_spacing,
|
||||
button: self.button_spacing,
|
||||
},
|
||||
rows: view.iter().map(|row| {
|
||||
Box::new(::layout::Row {
|
||||
angle: 0,
|
||||
@ -469,13 +515,13 @@ fn create_button(
|
||||
.unwrap_or_else(|| {
|
||||
eprintln!("No default outline defied Using 1x1!");
|
||||
Outline {
|
||||
corner_radius: 0f64,
|
||||
bounds: Bounds { x: 0f64, y: 0f64, width: 1f64, height: 1f64 },
|
||||
}
|
||||
});
|
||||
|
||||
::layout::Button {
|
||||
name: cname,
|
||||
outline_name: CString::new(outline_name).expect("Bad outline"),
|
||||
// TODO: do layout before creating buttons
|
||||
bounds: ::layout::c::Bounds {
|
||||
x: outline.bounds.x,
|
||||
@ -483,7 +529,6 @@ fn create_button(
|
||||
width: outline.bounds.width,
|
||||
height: outline.bounds.height,
|
||||
},
|
||||
corner_radius: outline.corner_radius,
|
||||
label: label,
|
||||
state: state,
|
||||
}
|
||||
@ -498,10 +543,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_parse_path() {
|
||||
assert_eq!(
|
||||
Layout::from_yaml_stream(
|
||||
PathBuf::from("tests/layout.yaml")
|
||||
).unwrap(),
|
||||
Layout::from_file(PathBuf::from("tests/layout.yaml")).unwrap(),
|
||||
Layout {
|
||||
row_spacing: 0f64,
|
||||
button_spacing: 0f64,
|
||||
bounds: Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 },
|
||||
views: hashmap!(
|
||||
"base".into() => vec!("test".into()),
|
||||
@ -517,7 +562,6 @@ mod tests {
|
||||
},
|
||||
outlines: hashmap!{
|
||||
"default".into() => Outline {
|
||||
corner_radius: 1f64,
|
||||
bounds: Bounds {
|
||||
x: 0f64, y: 0f64, width: 0f64, height: 0f64
|
||||
},
|
||||
@ -530,7 +574,7 @@ mod tests {
|
||||
/// Check if the default protection works
|
||||
#[test]
|
||||
fn test_empty_views() {
|
||||
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout2.yaml"));
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout2.yaml"));
|
||||
match out {
|
||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||
Err(e) => {
|
||||
@ -548,7 +592,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_extra_field() {
|
||||
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout3.yaml"));
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout3.yaml"));
|
||||
match out {
|
||||
Ok(_) => assert!(false, "Data mistakenly accepted"),
|
||||
Err(e) => {
|
||||
@ -567,7 +611,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_layout_punctuation() {
|
||||
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout_key1.yaml"))
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key1.yaml"))
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
@ -582,7 +626,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_layout_unicode() {
|
||||
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout_key2.yaml"))
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key2.yaml"))
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
@ -597,12 +641,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parsing_fallback() {
|
||||
assert!(load_layout_from_resource(FALLBACK_LAYOUT_NAME)
|
||||
assert!(Layout::from_resource(FALLBACK_LAYOUT_NAME)
|
||||
.and_then(|layout| layout.build().map_err(LoadError::BadKeyMap))
|
||||
.is_ok()
|
||||
);
|
||||
}
|
||||
|
||||
/// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
|
||||
#[test]
|
||||
fn fallbacks_order() {
|
||||
let (layout, source, _failure) = load_layout(
|
||||
"nb",
|
||||
Some(PathBuf::from("tests"))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
source,
|
||||
load_layout("nb", None).1
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_keysym() {
|
||||
let keysym = xkb::keysym_from_name(
|
||||
|
||||
@ -3,7 +3,6 @@ use std::ffi::CString;
|
||||
use std::num::Wrapping;
|
||||
use std::string::String;
|
||||
|
||||
use super::bitflags;
|
||||
use ::util::c::into_cstring;
|
||||
|
||||
// Traits
|
||||
|
||||
@ -32,6 +32,7 @@ EekBounds squeek_button_get_bounds(const struct squeek_button*);
|
||||
const char *squeek_button_get_label(const struct squeek_button*);
|
||||
const char *squeek_button_get_icon_name(const struct squeek_button*);
|
||||
const char *squeek_button_get_name(const struct squeek_button*);
|
||||
const char *squeek_button_get_outline_name(const struct squeek_button*);
|
||||
|
||||
struct squeek_key *squeek_button_get_key(const struct squeek_button*);
|
||||
uint32_t *squeek_button_has_key(const struct squeek_button* button,
|
||||
|
||||
@ -40,11 +40,6 @@ pub mod c {
|
||||
#[repr(transparent)]
|
||||
pub struct UserData(*const c_void);
|
||||
|
||||
/// The index in the relevant outline table
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OutlineRef(u32);
|
||||
|
||||
/// Defined in eek-types.h
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
@ -195,6 +190,13 @@ pub mod c {
|
||||
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_has_key(
|
||||
@ -328,8 +330,8 @@ pub mod c {
|
||||
.map(|button| button.bounds.clone())
|
||||
.collect()
|
||||
}).collect();
|
||||
|
||||
view.place_buttons_with_sizes(sizes);
|
||||
let spacing = view.spacing.clone();
|
||||
view.place_buttons_with_sizes(sizes, spacing);
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,6 +442,10 @@ pub mod c {
|
||||
x: 0f64, y: 0f64,
|
||||
width: 0f64, height: 0f64
|
||||
},
|
||||
spacing: Spacing {
|
||||
button: 0f64,
|
||||
row: 0f64,
|
||||
},
|
||||
rows: vec!(row),
|
||||
};
|
||||
|
||||
@ -459,6 +465,10 @@ pub mod c {
|
||||
x: 0f64, y: 0f64,
|
||||
width: 0f64, height: 0f64
|
||||
},
|
||||
spacing: Spacing {
|
||||
button: 0f64,
|
||||
row: 0f64,
|
||||
},
|
||||
rows: Vec::new(),
|
||||
};
|
||||
assert_eq!(
|
||||
@ -498,10 +508,10 @@ pub mod c {
|
||||
) -> Box<Button> {
|
||||
Box::new(Button {
|
||||
name: CString::new(name.clone()).unwrap(),
|
||||
corner_radius: 0f64,
|
||||
bounds: c::Bounds {
|
||||
x: 0f64, y: 0f64, width: 0f64, height: 0f64
|
||||
},
|
||||
outline_name: CString::new("test").unwrap(),
|
||||
label: Label::Text(CString::new(name).unwrap()),
|
||||
state: state,
|
||||
})
|
||||
@ -561,18 +571,15 @@ pub struct Button {
|
||||
pub name: CString,
|
||||
/// Label to display to the user
|
||||
pub label: Label,
|
||||
pub corner_radius: f64,
|
||||
/// TODO: position the buttons before they get initial bounds
|
||||
/// Position relative to some origin (i.e. parent/row)
|
||||
pub bounds: c::Bounds,
|
||||
/// The name of the visual class applied
|
||||
pub outline_name: CString,
|
||||
/// current state, shared with other buttons
|
||||
pub state: Rc<RefCell<KeyState>>,
|
||||
}
|
||||
|
||||
// FIXME: derive from the style/margin/padding
|
||||
const BUTTON_SPACING: f64 = 4.0;
|
||||
const ROW_SPACING: f64 = 7.0;
|
||||
|
||||
/// The graphical representation of a row of buttons
|
||||
pub struct Row {
|
||||
pub buttons: Vec<Box<Button>>,
|
||||
@ -599,7 +606,7 @@ impl Row {
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_button_positions(outlines: Vec<c::Bounds>)
|
||||
fn calculate_button_positions(outlines: Vec<c::Bounds>, button_spacing: f64)
|
||||
-> Vec<c::Bounds>
|
||||
{
|
||||
let mut x_offset = 0f64;
|
||||
@ -609,7 +616,7 @@ impl Row {
|
||||
x: x_offset,
|
||||
..outline.clone()
|
||||
};
|
||||
x_offset += outline.width + BUTTON_SPACING;
|
||||
x_offset += outline.width + button_spacing;
|
||||
position
|
||||
}).collect()
|
||||
}
|
||||
@ -648,9 +655,16 @@ impl Row {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Spacing {
|
||||
pub row: f64,
|
||||
pub button: f64,
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
/// Position relative to keyboard origin
|
||||
pub bounds: c::Bounds,
|
||||
pub spacing: Spacing,
|
||||
pub rows: Vec<Box<Row>>,
|
||||
}
|
||||
|
||||
@ -662,7 +676,9 @@ impl View {
|
||||
/// and derive a scaling factor that lets contents fit into view)
|
||||
/// (or TODO: blow up view bounds to match contents
|
||||
/// and then scale the entire thing)
|
||||
fn calculate_row_positions(&self, sizes: Vec<Size>) -> Vec<c::Bounds> {
|
||||
fn calculate_row_positions(&self, sizes: Vec<Size>, row_spacing: f64)
|
||||
-> Vec<c::Bounds>
|
||||
{
|
||||
let mut y_offset = self.bounds.y;
|
||||
sizes.into_iter().map(|size| {
|
||||
let position = c::Bounds {
|
||||
@ -671,7 +687,7 @@ impl View {
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
};
|
||||
y_offset += size.height + ROW_SPACING;
|
||||
y_offset += size.height + row_spacing;
|
||||
position
|
||||
}).collect()
|
||||
}
|
||||
@ -680,19 +696,23 @@ impl View {
|
||||
/// The view itself will not be affected by the sizes
|
||||
fn place_buttons_with_sizes(
|
||||
&mut self,
|
||||
button_outlines: Vec<Vec<c::Bounds>>
|
||||
button_outlines: Vec<Vec<c::Bounds>>,
|
||||
spacing: Spacing,
|
||||
) {
|
||||
// Determine all positions
|
||||
let button_positions: Vec<_>
|
||||
= button_outlines.into_iter()
|
||||
.map(Row::calculate_button_positions)
|
||||
.map(|outlines| {
|
||||
Row::calculate_button_positions(outlines, spacing.button)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let row_sizes = button_positions.iter()
|
||||
.map(Row::calculate_row_size)
|
||||
.collect();
|
||||
|
||||
let row_positions = self.calculate_row_positions(row_sizes);
|
||||
let row_positions
|
||||
= self.calculate_row_positions(row_sizes, spacing.row);
|
||||
|
||||
// Apply all positions
|
||||
for ((mut row, row_position), button_positions)
|
||||
|
||||
@ -19,7 +19,6 @@ sources = [
|
||||
'../eek/eek-element.c',
|
||||
'../eek/eek-gtk-keyboard.c',
|
||||
'../eek/eek-keyboard.c',
|
||||
'../eek/eek-keyboard-drawing.c',
|
||||
'../eek/eek-layout.c',
|
||||
'../eek/eek-renderer.c',
|
||||
'../eek/eek-types.c',
|
||||
@ -29,7 +28,6 @@ sources = [
|
||||
enums,
|
||||
'../eekboard/key-emitter.c',
|
||||
'../eekboard/eekboard-context-service.c',
|
||||
'../eekboard/eekboard-context.c',
|
||||
'../eekboard/eekboard-service.c',
|
||||
# '../eekboard/eekboard-xklutil.c',
|
||||
squeekboard_resources,
|
||||
@ -60,13 +58,29 @@ rslibs = custom_target(
|
||||
output: ['librs.a'],
|
||||
install: false,
|
||||
console: true,
|
||||
command: [cargo_script, '@CURRENT_SOURCE_DIR@', '@OUTPUT@', 'build']
|
||||
command: [cargo_script, '@OUTPUT@', 'build']
|
||||
)
|
||||
|
||||
build_rstests = custom_target(
|
||||
'build_rstests',
|
||||
build_by_default: false,
|
||||
# HACK: this target needs to build before all the tests,
|
||||
# but it doesn't produce anything stable.
|
||||
# Declaring build_by_default with some random but irrelevant output
|
||||
# ensures that it's always built as it should
|
||||
build_always_stale: true,
|
||||
output: ['src'],
|
||||
install: false,
|
||||
console: true,
|
||||
command: [cargo_script, '', 'build', '--tests'],
|
||||
depends: rslibs, # no point building tests if the code itself fails
|
||||
)
|
||||
|
||||
test(
|
||||
'rstest',
|
||||
cargo_script,
|
||||
args: [meson.source_root(), '', 'test']
|
||||
args: ['', 'test'],
|
||||
depends: build_rstests,
|
||||
)
|
||||
|
||||
libsqueekboard = static_library('libsqueekboard',
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
|
||||
const KEYBOARDS: &[(*const str, *const str)] = &[
|
||||
("us", include_str!("../data/keyboards/us.yaml")),
|
||||
("el", include_str!("../data/keyboards/el.yaml")),
|
||||
("es", include_str!("../data/keyboards/es.yaml")),
|
||||
("it", include_str!("../data/keyboards/it.yaml")),
|
||||
("nb", include_str!("../data/keyboards/nb.yaml")),
|
||||
("number", include_str!("../data/keyboards/number.yaml")),
|
||||
];
|
||||
|
||||
@ -40,6 +40,7 @@ struct _ServerContextService {
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *widget;
|
||||
guint hiding;
|
||||
|
||||
gdouble size_constraint_landscape[2];
|
||||
gdouble size_constraint_portrait[2];
|
||||
@ -51,17 +52,6 @@ struct _ServerContextServiceClass {
|
||||
|
||||
G_DEFINE_TYPE (ServerContextService, server_context_service, EEKBOARD_TYPE_CONTEXT_SERVICE);
|
||||
|
||||
static void set_geometry (ServerContextService *context);
|
||||
|
||||
static void
|
||||
on_monitors_changed (GdkScreen *screen,
|
||||
ServerContextService *context)
|
||||
|
||||
{
|
||||
if (context->window)
|
||||
set_geometry (context);
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroy (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
@ -107,15 +97,6 @@ on_notify_keyboard (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify_fullscreen (GObject *object,
|
||||
GParamSpec *spec,
|
||||
ServerContextService *context)
|
||||
{
|
||||
if (context->window)
|
||||
set_geometry (context);
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify_map (GObject *object,
|
||||
ServerContextService *context)
|
||||
@ -131,49 +112,6 @@ on_notify_unmap (GObject *object,
|
||||
g_object_set (context, "visible", FALSE, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_geometry (ServerContextService *context)
|
||||
{
|
||||
GdkScreen *screen = gdk_screen_get_default ();
|
||||
GdkWindow *root = gdk_screen_get_root_window (screen);
|
||||
GdkDisplay *display = gdk_display_get_default ();
|
||||
GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, root);
|
||||
LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
|
||||
|
||||
GdkRectangle rect;
|
||||
|
||||
gdk_monitor_get_geometry (monitor, &rect);
|
||||
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(keyboard));
|
||||
|
||||
if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
|
||||
gint width = rect.width;
|
||||
gint height = rect.height;
|
||||
|
||||
if (width > height) {
|
||||
width *= context->size_constraint_landscape[0];
|
||||
height *= context->size_constraint_landscape[1];
|
||||
} else {
|
||||
width *= context->size_constraint_portrait[0];
|
||||
height *= context->size_constraint_portrait[1];
|
||||
}
|
||||
|
||||
if (width * bounds.height > height * bounds.width)
|
||||
width = (height / bounds.height) * bounds.width;
|
||||
else
|
||||
height = (width / bounds.width) * bounds.height;
|
||||
|
||||
gtk_window_resize (GTK_WINDOW(context->widget), width, height);
|
||||
|
||||
gtk_window_move (GTK_WINDOW(context->window),
|
||||
(rect.width - width) / 2,
|
||||
rect.height - height);
|
||||
|
||||
gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
|
||||
gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#define KEYBOARD_HEIGHT 210
|
||||
static void
|
||||
make_window (ServerContextService *context)
|
||||
@ -237,7 +175,6 @@ make_widget (ServerContextService *context)
|
||||
gtk_widget_set_has_tooltip (context->widget, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER(context->window), context->widget);
|
||||
gtk_widget_show (context->widget);
|
||||
set_geometry (context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -245,6 +182,11 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
|
||||
{
|
||||
ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
|
||||
|
||||
if (context->hiding) {
|
||||
g_source_remove (context->hiding);
|
||||
context->hiding = 0;
|
||||
}
|
||||
|
||||
if (!context->window)
|
||||
make_window (context);
|
||||
if (!context->widget)
|
||||
@ -255,12 +197,22 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
|
||||
gtk_widget_show (context->window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_hide (ServerContextService *context)
|
||||
{
|
||||
gtk_widget_hide (context->window);
|
||||
context->hiding = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
server_context_service_real_hide_keyboard (EekboardContextService *_context)
|
||||
{
|
||||
ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
|
||||
|
||||
gtk_widget_hide (context->window);
|
||||
if (!context->hiding)
|
||||
context->hiding = g_timeout_add (200, (GSourceFunc) on_hide, context);
|
||||
|
||||
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
|
||||
hide_keyboard (_context);
|
||||
@ -349,21 +301,10 @@ server_context_service_class_init (ServerContextServiceClass *klass)
|
||||
static void
|
||||
server_context_service_init (ServerContextService *context)
|
||||
{
|
||||
GdkScreen *screen = gdk_screen_get_default ();
|
||||
|
||||
g_signal_connect (screen,
|
||||
"monitors-changed",
|
||||
G_CALLBACK(on_monitors_changed),
|
||||
context);
|
||||
g_signal_connect (context,
|
||||
"notify::keyboard",
|
||||
G_CALLBACK(on_notify_keyboard),
|
||||
context);
|
||||
|
||||
g_signal_connect (context,
|
||||
"notify::fullscreen",
|
||||
G_CALLBACK(on_notify_fullscreen),
|
||||
context);
|
||||
}
|
||||
|
||||
EekboardContextService *
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SERVER_CONTEXT_H
|
||||
#define SERVER_CONTEXT_H 1
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SERVER_CONTEXT_PATH "/org/fedorahosted/Eekboard/Context_%d"
|
||||
#define SERVER_CONTEXT_INTERFACE "org.fedorahosted.Eekboard.Context"
|
||||
|
||||
#define SERVER_TYPE_CONTEXT (server_context_get_type())
|
||||
#define SERVER_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SERVER_TYPE_CONTEXT, ServerContext))
|
||||
#define SERVER_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SERVER_TYPE_CONTEXT, ServerContextClass))
|
||||
#define SERVER_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SERVER_TYPE_CONTEXT))
|
||||
#define SERVER_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SERVER_TYPE_CONTEXT))
|
||||
#define SERVER_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SERVER_TYPE_CONTEXT, ServerContextClass))
|
||||
|
||||
typedef struct _ServerContext ServerContext;
|
||||
|
||||
ServerContext *server_context_new (const gchar *object_path,
|
||||
GDBusConnection *connection);
|
||||
void server_context_set_enabled (ServerContext *context,
|
||||
gboolean enabled);
|
||||
void server_context_set_client_connection
|
||||
(ServerContext *context,
|
||||
const gchar *client_connection);
|
||||
const gchar *server_context_get_client_connection
|
||||
(ServerContext *context);
|
||||
void server_context_set_client_name
|
||||
(ServerContext *context,
|
||||
const gchar *client_name);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* SERVER_CONTEXT_H */
|
||||
@ -1,4 +1,7 @@
|
||||
---
|
||||
row_spacing: 0
|
||||
button_spacing: 0
|
||||
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
@ -9,7 +12,6 @@ views:
|
||||
- "test"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
---
|
||||
# missing views
|
||||
row_spacing: 0
|
||||
button_spacing: 0
|
||||
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
@ -7,6 +10,5 @@ bounds:
|
||||
height: 0
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
---
|
||||
# extra field
|
||||
row_spacing: 0
|
||||
button_spacing: 0
|
||||
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
@ -10,7 +13,6 @@ views:
|
||||
- "test"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
bad_field: false
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
---
|
||||
# punctuation
|
||||
row_spacing: 0
|
||||
button_spacing: 0
|
||||
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
@ -10,7 +13,6 @@ views:
|
||||
- "."
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
---
|
||||
# punctuation
|
||||
row_spacing: 0
|
||||
button_spacing: 0
|
||||
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
@ -10,7 +13,6 @@ views:
|
||||
- "å"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
@ -47,11 +47,11 @@ endforeach
|
||||
# The layout test is in the examples directory
|
||||
# due to the way Cargo builds executables
|
||||
# and the need to call it manually
|
||||
foreach layout : ['us', 'nb', 'number']
|
||||
foreach layout : ['us', 'el', 'es', 'it', 'nb', 'number']
|
||||
test(
|
||||
'test_layout_' + layout,
|
||||
cargo_script,
|
||||
args: [meson.source_root(), '', 'run', '--example', 'test_layout', layout]
|
||||
args: ['', 'run', '--example', 'test_layout', layout]
|
||||
)
|
||||
endforeach
|
||||
|
||||
|
||||
Reference in New Issue
Block a user