Compare commits
132 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e080d4351e | |||
| dcd4dbf931 | |||
| ea0926147f | |||
| ce223e04e6 | |||
| ddd1c1b16b | |||
| 0f1f6531da | |||
| c917a1f818 | |||
| afe8fd64f4 | |||
| bd3b27eceb | |||
| 35ad61890e | |||
| 1b1fbed7de | |||
| 264d30d884 | |||
| 38d8290b59 | |||
| 254b65681a | |||
| fbb3824a3d | |||
| 24126ad4f3 | |||
| 869a0af67f | |||
| 5281d96460 | |||
| 8f7f6c05c0 | |||
| 01fe433612 | |||
| 63e55ff5c4 | |||
| 8d4d50cfca | |||
| dde659dbd3 | |||
| 788a39f144 | |||
| 43e2b7b803 | |||
| 3fb0a3a959 | |||
| bdef7b3516 | |||
| 57d36e476b | |||
| 0b5aa1ba7c | |||
| 55410a005c | |||
| 1290fd4a1e | |||
| c99efc430c | |||
| ce6c9cbea3 | |||
| 4cdfc30c29 | |||
| 3b6c19401c | |||
| 29231f7e31 | |||
| 76b8a61d0a | |||
| d62abc2f12 | |||
| 8f61a26fb4 | |||
| 8fd63cea80 | |||
| 162b828c4c | |||
| ac58b675ef | |||
| a048722a94 | |||
| a74be1b299 | |||
| 89b56ddccf | |||
| 8ab3a2b8d3 | |||
| f56c5e3879 | |||
| 8eda2cd04d | |||
| cfd2bff1aa | |||
| 02501aee9e | |||
| 70056b68a7 | |||
| b36c48daa3 | |||
| 9e078be603 | |||
| ac68d5d0a8 | |||
| b45edcd4fe | |||
| dc2bc46167 | |||
| 9cd439767e | |||
| 212e55d7cf | |||
| 31fdde4da9 | |||
| 10bad4ebe3 | |||
| da5a83f367 | |||
| ef38fd3e64 | |||
| 46d3312c86 | |||
| cb8d2b01af | |||
| 3f3e33c853 | |||
| aa3dc96986 | |||
| 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 |
@ -22,6 +22,7 @@ build_meson:
|
||||
artifacts:
|
||||
paths:
|
||||
- _build
|
||||
expire_in: 3h
|
||||
script:
|
||||
- meson . _build/ -Ddepdatadir=/usr/share
|
||||
- ninja -C _build install
|
||||
@ -49,7 +50,7 @@ test_lintian:
|
||||
test:
|
||||
<<: *tags
|
||||
stage: test
|
||||
dependencies:
|
||||
needs:
|
||||
- build_meson
|
||||
script:
|
||||
- ninja -C _build test
|
||||
|
||||
37
AUTHORS
37
AUTHORS
@ -1,36 +1,5 @@
|
||||
eekboard is written by Daiki Ueno <ueno@unixuser.org>. The following
|
||||
files contain code derived from other free software packages:
|
||||
squeekboard is written by Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> on behlf of Purism, SPC.
|
||||
eekboard was written by Daiki Ueno <ueno@unixuser.org>
|
||||
|
||||
eek/eek-keyboard-drawing.h
|
||||
eek/eek-keyboard-drawing.c
|
||||
For more details, see the debian/copyright file.
|
||||
|
||||
These files contain code derived from the libgnomekbd library.
|
||||
Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||
|
||||
eek/eek-theme.h
|
||||
eek/eek-theme.c
|
||||
eek/eek-theme-context.h
|
||||
eek/eek-theme-context.c
|
||||
eek/eek-theme-node.h
|
||||
eek/eek-theme-node.c
|
||||
|
||||
These files contain code derived from gnome-shell.
|
||||
|
||||
Copyright 2008-2010 Red Hat, Inc.
|
||||
Copyright 2009 Steve Frécinaux
|
||||
Copyright 2009, 2010 Florian Müllner
|
||||
Copyright 2010 Adel Gadllah
|
||||
Copyright 2010 Giovanni Campagna
|
||||
Copyright 2003-2004 Dodji Seketeli
|
||||
|
||||
data/icons/8x8/Makefile.am
|
||||
data/icons/16x16/Makefile.am
|
||||
data/icons/22x22/Makefile.am
|
||||
data/icons/24x24/Makefile.am
|
||||
data/icons/32x32/Makefile.am
|
||||
data/icons/48x48/Makefile.am
|
||||
data/icons/scalable/Makefile.am
|
||||
|
||||
These files contain code derived from im-chooser.
|
||||
|
||||
Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
|
||||
|
||||
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
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Eekboard
|
||||
Exec=eekboard -f
|
||||
Type=Application
|
||||
#AutostartCondition=GSettings org.gnome.desktop.a11y.applications screen-keyboard-enabled
|
||||
X-GNOME-AutoRestart=true
|
||||
@ -1,3 +0,0 @@
|
||||
[D-BUS Service]
|
||||
Name=org.fedorahosted.Eekboard
|
||||
Exec=@bindir@/eekboard-server
|
||||
@ -1,9 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Eekboard
|
||||
GenericName=Eekboard Virtual Keyboard
|
||||
Comment=Virtual Keyboard
|
||||
Exec=eekboard
|
||||
Icon=eekboard
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=GTK;Utility;
|
||||
95
data/keyboards/de.yaml
Normal file
95
data/keyboards/de.yaml
Normal file
@ -0,0 +1,95 @@
|
||||
# German layout by Mark Müller
|
||||
# Version 2019101900
|
||||
---
|
||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t z u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L y x c v b n m BackSpace"
|
||||
- "show_numbers show_dechars preferences space , period Return"
|
||||
upper:
|
||||
- "Q W E R T Z U I O P"
|
||||
- "A S D F G H J K L"
|
||||
- "Shift_L Y X C V B N M BackSpace"
|
||||
- "show_numbers show_dechars preferences space ! ? Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # € % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon = < > BackSpace"
|
||||
- "show_letters show_dechars preferences space , period Return"
|
||||
symbols:
|
||||
- "~ ` ´ | · √ µ ÷ × ¶"
|
||||
- "© ® £ $ ¥ ^ ° * { }"
|
||||
- "show_numbers \\ / § π τ [ ] BackSpace"
|
||||
- "show_letters show_dechars preferences space , period Return"
|
||||
dechars:
|
||||
- "ä è é ö ü Ä È É Ö Ü"
|
||||
- "à â ê î ô À Â È Î Ô"
|
||||
- "show_numbers « » ç Ç æ œ ß BackSpace"
|
||||
- "show_letters show_dechars 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: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: "abc"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
show_dechars:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "dechars"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "äÄ"
|
||||
|
||||
period:
|
||||
outline: "default"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
196
data/keyboards/el.yaml
Normal file
196
data/keyboards/el.yaml
Normal file
@ -0,0 +1,196 @@
|
||||
# Greek layout created by Antonis Tsolomitis
|
||||
# University of the Aegean, Department of Mathematics, atsol@aegean.gr
|
||||
# Sep 2019
|
||||
---
|
||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 32, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
outline7:
|
||||
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "; ς ε ρ τ υ θ ι ο π !"
|
||||
- "α σ δ φ γ η ξ κ λ show_accented"
|
||||
- "Shift_L ζ χ ψ ω β ν μ , BackSpace"
|
||||
- "show_numbers preferences space period 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: "wide"
|
||||
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: "]"
|
||||
|
||||
93
data/keyboards/es.yaml
Normal file
93
data/keyboards/es.yaml
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
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"
|
||||
97
data/keyboards/it.yaml
Normal file
97
data/keyboards/it.yaml
Normal file
@ -0,0 +1,97 @@
|
||||
# Italian layout created by Antonio Pandolfo
|
||||
# 03 october 2019
|
||||
---
|
||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 35.33, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 99.67, height: 52 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
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_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_eschars:
|
||||
action:
|
||||
set_view: "eschars"
|
||||
outline: "altline"
|
||||
label: "àè"
|
||||
period:
|
||||
outline: "default"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: "altline"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
529
data/keyboards/ja+kana.yaml
Normal file
529
data/keyboards/ja+kana.yaml
Normal file
@ -0,0 +1,529 @@
|
||||
# Japanese Kana layout by Mark Müller
|
||||
# Version 2019101900
|
||||
---
|
||||
bounds: { x: 0, y: 1, width: 360, height: 210 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
default-wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
|
||||
views:
|
||||
base: # hiragana
|
||||
- "preferences _a ka sa BackSpace"
|
||||
- "Left ta na ha Right"
|
||||
- "カタカナ ma ya ra space"
|
||||
- "switch2roman symbols wa punct Return"
|
||||
_a:
|
||||
- "preferences dummykey _a dummykey BackSpace"
|
||||
- "あ い う え お"
|
||||
- "ぁ ぃ ぅ ぇ ぉ" # 2 code points each
|
||||
- "dummykey dummykey ゔ dummykey dummykey"
|
||||
ka:
|
||||
- "preferences dummykey ka dummykey BackSpace"
|
||||
- "か き く け こ"
|
||||
- "が ぎ ぐ げ ご"
|
||||
- "ゕ dummykey dummykey ゖ dummykey"
|
||||
sa:
|
||||
- "preferences dummykey sa dummykey BackSpace"
|
||||
- "さ し す せ そ"
|
||||
- "ざ じ ず ぜ ぞ"
|
||||
ta:
|
||||
- "preferences dummykey ta dummykey BackSpace"
|
||||
- "た ち つ て と"
|
||||
- "だ ぢ づ で ど"
|
||||
- "dummykey dummykey っ dummykey dummykey"
|
||||
na:
|
||||
- "preferences dummykey na dummykey BackSpace"
|
||||
- "な に ぬ ね の"
|
||||
ha:
|
||||
- "preferences dummykey ha dummykey BackSpace"
|
||||
- "は ひ ふ へ ほ"
|
||||
- "ば び ぶ べ ぼ"
|
||||
- "ぱ ぴ ぷ ぺ ぽ"
|
||||
ma:
|
||||
- "preferences dummykey ma dummykey BackSpace"
|
||||
- "ま み む め も"
|
||||
ya:
|
||||
- "preferences dummykey ya dummykey BackSpace"
|
||||
- "や dummykey ゆ dummykey よ"
|
||||
- "ゃ dummykey ゅ dummykey ょ"
|
||||
ra:
|
||||
- "preferences dummykey ra dummykey BackSpace"
|
||||
- "ら り る れ ろ"
|
||||
wa:
|
||||
- "preferences dummykey wa dummykey BackSpace"
|
||||
- "わ ゐ dummykey ゑ を"
|
||||
- "ゎ dummykey ん dummykey dummykey"
|
||||
symbols:
|
||||
- "preferences dummykey symbols dummykey BackSpace"
|
||||
- "「 」 ( ) §"
|
||||
- "【 】 < > ="
|
||||
- "+ * & % $ "
|
||||
punct:
|
||||
- "preferences dummykey punct dummykey BackSpace"
|
||||
- "。 、 ? ! ー"
|
||||
|
||||
- ": ; ・ 〜 …"
|
||||
- "♪ ” ’ ゙ ゚"
|
||||
|
||||
#a あア かカ さサ たタ なナ はハ まマ やヤ らラ わワ
|
||||
#i いイ きキ しシ ちチ にニ ひヒ みミ ※ りリ ゐヰ
|
||||
#u うウ くク すス つツ ぬヌ ふフ むム ゆユ るル ※
|
||||
#e えエ けケ せセ てテ ねネ へヘ めメ ※ れレ ゑヱ
|
||||
#o おオ こコ そソ とト のノ ほホ もモ よヨ ろロ をヲ
|
||||
|
||||
# g z d b p n
|
||||
#a が ガ ざ ザ だ ダ ば バ ぱ パ ん ン
|
||||
#i ぎ ギ じ ジ ぢ ヂ び ビ ぴ ピ
|
||||
#u ぐ グ ず ズ づ ヅ ぶ ブ ぷ プ
|
||||
#e げ ゲ ぜ ゼ で デ べ ベ ぺ ペ
|
||||
#o ご ゴ ぞ ゾ ど ド ぼ ボ ぽ ポ
|
||||
|
||||
カタカナ: # katakana
|
||||
- "preferences _A KA SA BackSpace"
|
||||
- "Left TA NA HA Right"
|
||||
- "ひらがな MA YA RA space"
|
||||
- "switch2roman SYMBOLS WA PUNCT Return"
|
||||
_A:
|
||||
- "preferences DUMMYKEY _A DUMMYKEY BackSpace"
|
||||
- "ア イ ウ エ オ"
|
||||
- "ァ ィ ゥ ェ ォ"
|
||||
- "DUMMYKEY DUMMYKEY ヴ DUMMYKEY DUMMYKEY"
|
||||
KA:
|
||||
- "preferences DUMMYKEY KA DUMMYKEY BackSpace"
|
||||
- "カ キ ク ケ コ"
|
||||
- "ガ ギ グ ゲ ゴ"
|
||||
- "ヵ DUMMYKEY ㇰ ヶ DUMMYKEY"
|
||||
SA:
|
||||
- "preferences DUMMYKEY SA DUMMYKEY BackSpace"
|
||||
- "サ シ ス セ ソ"
|
||||
- "ザ ジ ズ ゼ ゾ"
|
||||
- "DUMMYKEY ㇱ ㇲ DUMMYKEY DUMMYKEY"
|
||||
TA:
|
||||
- "preferences DUMMYKEY TA DUMMYKEY BackSpace"
|
||||
- "タ チ ツ テ ト"
|
||||
- "ダ ヂ ヅ デ ド"
|
||||
- "DUMMYKEY DUMMYKEY ッ DUMMYKEY ㇳ"
|
||||
NA:
|
||||
- "preferences DUMMYKEY NA DUMMYKEY BackSpace"
|
||||
- "ナ ニ ヌ ネ ノ"
|
||||
- "DUMMYKEY DUMMYKEY ㇴ DUMMYKEY DUMMYKEY"
|
||||
HA:
|
||||
- "preferences DUMMYKEY HA DUMMYKEY BackSpace"
|
||||
- "ハ ヒ フ ヘ ホ"
|
||||
- "バ ビ ブ ベ ボ"
|
||||
- "パ ピ プ ペ ポ"
|
||||
MA:
|
||||
- "preferences DUMMYKEY MA DUMMYKEY BackSpace"
|
||||
- "マ ミ ム メ モ"
|
||||
- "DUMMYKEY DUMMYKEY ㇺ DUMMYKEY DUMMYKEY"
|
||||
YA:
|
||||
- "preferences DUMMYKEY YA DUMMYKEY BackSpace"
|
||||
- "ヤ DUMMYKEY ユ DUMMYKEY ヨ"
|
||||
- "ャ DUMMYKEY ュ DUMMYKEY ョ"
|
||||
RA:
|
||||
- "preferences DUMMYKEY RA DUMMYKEY BackSpace"
|
||||
- "ラ リ ル レ ロ"
|
||||
- "ㇻ ㇼ ㇽ ㇾ ㇿ"
|
||||
WA:
|
||||
- "preferences DUMMYKEY WA DUMMYKEY BackSpace"
|
||||
- "ワ ヰ DUMMYKEY ヱ ヲ"
|
||||
- "ヮ ヸ ン ヹ ヺ"
|
||||
# numbers view
|
||||
numbers:
|
||||
- "preferences 1 2 3 BackSpace"
|
||||
- "Left 4 5 6 Right"
|
||||
- "roman 7 8 9 space"
|
||||
- "switch2kana * 0 # Return"
|
||||
# Roman alphabet view
|
||||
roman:
|
||||
- "preferences RSYM1 ABC DEF BackSpace"
|
||||
- "Left GHI JKL MNO Right"
|
||||
- "ひらがな PQRS TUV WXYZ space"
|
||||
- "switch2num RSYM2 RSYM3 RSYM4 Return"
|
||||
RSYM1:
|
||||
- "preferences dummykey RSYM1 dummykey BackSpace"
|
||||
- "@ # $ § :"
|
||||
- "| € ¥ £ 1"
|
||||
ABC:
|
||||
- "preferences dummykey ABC dummykey BackSpace"
|
||||
- "A B C Ä ç"
|
||||
- "a b c ä 2"
|
||||
DEF:
|
||||
- "preferences dummykey DEF dummykey BackSpace"
|
||||
- "D E F dummykey"
|
||||
- "d e f 3"
|
||||
GHI:
|
||||
- "preferences dummykey GHI dummykey BackSpace"
|
||||
- "G H I dummykey"
|
||||
- "g h i 4"
|
||||
JKL:
|
||||
- "preferences dummykey JKL dummykey BackSpace"
|
||||
- "J K L dummykey"
|
||||
- "j k l 5"
|
||||
MNO:
|
||||
- "preferences dummykey MNO dummykey BackSpace"
|
||||
- "M N O Ö dummykey"
|
||||
- "m n o ö 6"
|
||||
PQRS:
|
||||
- "preferences dummykey PQRS dummykey BackSpace"
|
||||
- "P Q R S ß"
|
||||
- "p q r s 7"
|
||||
TUV:
|
||||
- "preferences dummykey TUV dummykey BackSpace"
|
||||
- "T U V Ü dummykey"
|
||||
- "t u v ü 8"
|
||||
WXYZ:
|
||||
- "preferences dummykey WXYZ dummykey BackSpace"
|
||||
- "W X Y Z dummykey"
|
||||
- "w x y z 9"
|
||||
RSYM2:
|
||||
- "preferences dummykey RSYM2 dummykey BackSpace"
|
||||
- "( ) ' \" ~"
|
||||
- "[ ] { } _"
|
||||
RSYM3:
|
||||
- "preferences dummykey RSYM3 dummykey BackSpace"
|
||||
- "+ - * / ="
|
||||
- "< > ^ ° 0"
|
||||
RSYM4:
|
||||
- "preferences dummykey RSYM4 dummykey BackSpace"
|
||||
- ", . ? ! ;"
|
||||
- "\\ ´ ` · ¶"
|
||||
|
||||
buttons:
|
||||
# following 4 buttons are keysyms from libxkbcommon
|
||||
BackSpace:
|
||||
outline: "wide"
|
||||
icon: "edit-clear-symbolic"
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
Left:
|
||||
outline: "wide"
|
||||
label: "←"
|
||||
Right:
|
||||
outline: "wide"
|
||||
label: "→"
|
||||
# special button "preferences" is handled in the code
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
# space button (unicode)
|
||||
space:
|
||||
outline: "default-wide"
|
||||
label: "␣"
|
||||
keysym: "U3000"
|
||||
# switch to number view
|
||||
numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
# switch to latin characters
|
||||
roman:
|
||||
action:
|
||||
set_view: "roman"
|
||||
outline: "wide"
|
||||
label: "ᴀʙᴄ"
|
||||
# toggle button with 3 different states
|
||||
switch2roman: # switch from kana to latin characters view
|
||||
action:
|
||||
set_view: "roman"
|
||||
outline: "wide"
|
||||
label: "あᴀ₁"
|
||||
switch2num: # switch from latin characters to numbers view
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "ぁA₁"
|
||||
switch2kana: # switch from numbers to hiragana view
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ぁᴀ1"
|
||||
# Buttons for katakana and symbols
|
||||
ひらがな:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "あさ"
|
||||
_a:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "_a"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "あ"
|
||||
ka:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ka"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "か"
|
||||
sa:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "sa"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "さ"
|
||||
ta:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ta"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "た"
|
||||
na:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "na"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "な"
|
||||
ha:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ha"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "は"
|
||||
ma:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ma"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "ま"
|
||||
ya:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ya"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "や"
|
||||
ra:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ra"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "ら"
|
||||
wa:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "wa"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "わ"
|
||||
dummykey:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "altline"
|
||||
label: ""
|
||||
# buttons available on different views like symbols and punct should go
|
||||
# back to their corresponding view
|
||||
symbols:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "symbols"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "()"
|
||||
punct:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "punct"
|
||||
unlock_view: "base"
|
||||
outline: "altline"
|
||||
label: "。"
|
||||
# Buttons for katakana and symbols
|
||||
カタカナ:
|
||||
action:
|
||||
set_view: "カタカナ"
|
||||
outline: "wide"
|
||||
label: "アサ"
|
||||
_A:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "_A"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ア"
|
||||
KA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "KA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "カ"
|
||||
SA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "SA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "サ"
|
||||
TA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "TA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "タ"
|
||||
NA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "NA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ナ"
|
||||
HA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "HA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ハ"
|
||||
MA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "MA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "マ"
|
||||
YA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "YA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ヤ"
|
||||
RA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "RA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ラ"
|
||||
WA:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "WA"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "ワ"
|
||||
DUMMYKEY:
|
||||
action:
|
||||
set_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: ""
|
||||
SYMBOLS:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "symbols"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "()"
|
||||
PUNCT:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "punct"
|
||||
unlock_view: "カタカナ"
|
||||
outline: "altline"
|
||||
label: "。"
|
||||
# Buttons for Latin charachters
|
||||
RSYM1:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "RSYM1"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "@#"
|
||||
ABC:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "ABC"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴀʙᴄ"
|
||||
DEF:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "DEF"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴅᴇꜰ"
|
||||
GHI:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "GHI"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ɢʜɪ"
|
||||
JKL:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "JKL"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴊᴋʟ"
|
||||
MNO:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "MNO"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴍɴᴏ"
|
||||
PQRS:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "PQRS"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴘǫʀs"
|
||||
TUV:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "TUV"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴛᴜᴠ"
|
||||
WXYZ:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "WXYZ"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "ᴡxʏᴢ"
|
||||
RSYM2:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "RSYM2"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "()"
|
||||
RSYM3:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "RSYM3"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: "+-"
|
||||
RSYM4:
|
||||
action:
|
||||
locking:
|
||||
lock_view: "RSYM4"
|
||||
unlock_view: "roman"
|
||||
outline: "altline"
|
||||
label: ",.?"
|
||||
@ -1,18 +1,16 @@
|
||||
---
|
||||
bounds: { x: 0, y: 10, width: 426, height: 229 }
|
||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
||||
|
||||
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 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, 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:
|
||||
@ -74,7 +72,7 @@ buttons:
|
||||
outline: spaceline
|
||||
label: " "
|
||||
Return:
|
||||
outline: outline7
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
aring:
|
||||
label: "å"
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
---
|
||||
bounds: { x: 0, y: 10, width: 410, height: 229 }
|
||||
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
|
||||
|
||||
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,39 @@
|
||||
---
|
||||
bounds: { x: 10, y: 10, width: 410, height: 229 }
|
||||
bounds: { x: 0, y: 1, width: 360, height: 208 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
|
||||
bounds: { x: 0, y: 0, width: 35.33, 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 }
|
||||
bounds: { x: 0, y: 0, width: 52.67, height: 52 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 62, height: 52 }
|
||||
spaceline:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
|
||||
bounds: { x: 0, y: 0, width: 142, height: 52 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 44, height: 52 }
|
||||
|
||||
views:
|
||||
base:
|
||||
- "q w e r t y u i o p"
|
||||
- "a s d f g h j k l"
|
||||
- "Shift_L z x c v b n m BackSpace"
|
||||
- "show_numbers preferences space . 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 +48,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 +63,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: ":"
|
||||
|
||||
85
data/keyboards/us_wide.yaml
Normal file
85
data/keyboards/us_wide.yaml
Normal file
@ -0,0 +1,85 @@
|
||||
---
|
||||
bounds: { x: 0, y: 1, width: 540, height: 168 }
|
||||
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 54, height: 42 }
|
||||
altline:
|
||||
bounds: { x: 0, y: 0, width: 81, height: 42 }
|
||||
wide:
|
||||
bounds: { x: 0, y: 0, width: 108, height: 42 }
|
||||
spaceline:
|
||||
bounds: { x: 0, y: 0, width: 216, height: 42 }
|
||||
special:
|
||||
bounds: { x: 0, y: 0, width: 54, height: 42 }
|
||||
|
||||
views:
|
||||
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 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 period Return"
|
||||
numbers:
|
||||
- "1 2 3 4 5 6 7 8 9 0"
|
||||
- "@ # $ % & - _ + ( )"
|
||||
- "show_symbols , \" ' colon ; ! ? BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
symbols:
|
||||
- "~ ` | · √ π τ ÷ × ¶"
|
||||
- "© ® £ € ¥ ^ ° * { }"
|
||||
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
|
||||
- "show_letters preferences space period Return"
|
||||
|
||||
buttons:
|
||||
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: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "wide"
|
||||
label: "123"
|
||||
show_numbers_from_symbols:
|
||||
action:
|
||||
set_view: "numbers"
|
||||
outline: "altline"
|
||||
label: "123"
|
||||
show_letters:
|
||||
action:
|
||||
set_view: "base"
|
||||
outline: "wide"
|
||||
label: "ABC"
|
||||
show_symbols:
|
||||
action:
|
||||
set_view: "symbols"
|
||||
outline: "altline"
|
||||
label: "*/="
|
||||
period:
|
||||
outline: "special"
|
||||
label: "."
|
||||
space:
|
||||
outline: "spaceline"
|
||||
label: " "
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
colon:
|
||||
label: ":"
|
||||
"\"":
|
||||
keysym: "quotedbl"
|
||||
@ -1,39 +1,46 @@
|
||||
.keyboard {
|
||||
sq_view {
|
||||
background-color: rgba(0, 0, 0, 255);
|
||||
color: #ffffff;
|
||||
font-family: cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.key {
|
||||
sq_view sq_button {
|
||||
color: #deddda;
|
||||
background: #464448;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #5e5c64;
|
||||
border-radius: 2px;
|
||||
border-radius: 3px;
|
||||
margin: 4px 2px 4px 2px;
|
||||
}
|
||||
|
||||
.key:active {
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
sq_view.wide sq_button {
|
||||
margin: 1px 1px 1px 1px;
|
||||
}
|
||||
|
||||
sq_button:active {
|
||||
background: #747077;
|
||||
border-color: #96949d;
|
||||
}
|
||||
|
||||
sq_button.altline,
|
||||
sq_button.special,
|
||||
sq_button.wide {
|
||||
background: #2b292f;
|
||||
border-color: #3e3a44;
|
||||
}
|
||||
|
||||
sq_button.locked {
|
||||
background: #ffffff;
|
||||
color: #2b292f;
|
||||
}
|
||||
|
||||
#Return {
|
||||
background: #1c71d8;
|
||||
border-color: #1a5fb4
|
||||
border-color: #1a5fb4;
|
||||
}
|
||||
|
||||
#Return:active {
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
}
|
||||
|
||||
#Shift_L {
|
||||
background: #2b292f;
|
||||
border-color: #3e3a44
|
||||
}
|
||||
|
||||
#Shift_L:active {
|
||||
background: #1c71d8;
|
||||
border-color: #3584e4;
|
||||
}
|
||||
|
||||
12
debian/changelog
vendored
12
debian/changelog
vendored
@ -1,3 +1,15 @@
|
||||
squeekboard (1.2.2) amber-phone; urgency=medium
|
||||
|
||||
* Landscape mode
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 30 Oct 2019 12:38:39 +0000
|
||||
|
||||
squeekboard (1.2.1) amber-phone; urgency=medium
|
||||
|
||||
* Use different distribution
|
||||
|
||||
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Tue, 08 Oct 2019 10:56:10 +0000
|
||||
|
||||
squeekboard (1.2.0) unstable; urgency=medium
|
||||
|
||||
* Use Cargo-based dependencies
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
||||
[
|
||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||
]>
|
||||
<book id="index">
|
||||
<bookinfo>
|
||||
<title>libeek Reference Manual</title>
|
||||
<releaseinfo>
|
||||
for libeek 0.90.0.
|
||||
</releaseinfo>
|
||||
<copyright>
|
||||
<year>2010-2011</year>
|
||||
<holder>Daiki Ueno</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>2010-2011</year>
|
||||
<holder>Red Hat, Inc.</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
Version 1.3 or any later version published by the Free Software
|
||||
Foundation; with no Invariant Sections, no Front-Cover Texts and
|
||||
no Back-Cover Texts. A copy of the license is included in the
|
||||
section entitled "GNU Free Documentation License".
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<xi:include href="xml/eek-overview.xml"/>
|
||||
<part id="apireference">
|
||||
<title>API Manual</title>
|
||||
<chapter>
|
||||
<title>Base Classes, Interfaces, and Utilities</title>
|
||||
<xi:include href="xml/eek.xml"/>
|
||||
<xi:include href="xml/eek-serializable.xml"/>
|
||||
<xi:include href="xml/eek-element.xml"/>
|
||||
<xi:include href="xml/eek-container.xml"/>
|
||||
<xi:include href="xml/eek-keyboard.xml"/>
|
||||
<xi:include href="xml/eek-section.xml"/>
|
||||
<xi:include href="xml/eek-key.xml"/>
|
||||
<xi:include href="xml/eek-symbol.xml"/>
|
||||
<xi:include href="xml/eek-keysym.xml"/>
|
||||
<xi:include href="xml/eek-text.xml"/>
|
||||
<xi:include href="xml/eek-layout.xml"/>
|
||||
<xi:include href="xml/eek-types.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>GTK Adapter</title>
|
||||
<xi:include href="xml/eek-gtk-keyboard.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>Clutter Adapter</title>
|
||||
<xi:include href="xml/eek-clutter-keyboard.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>Libxklavier Layout Engine</title>
|
||||
<xi:include href="xml/eek-xkl-layout.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>XKB Layout Engine</title>
|
||||
<xi:include href="xml/eek-xkb-layout.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>XML Layout Engine</title>
|
||||
<xi:include href="xml/eek-xml-layout.xml"/>
|
||||
<xi:include href="xml/eek-xml.xml"/>
|
||||
</chapter>
|
||||
<chapter id="object-tree">
|
||||
<title>Object Hierarchy</title>
|
||||
<xi:include href="xml/tree_index.sgml"/>
|
||||
</chapter>
|
||||
<index id="api-index-full">
|
||||
<title>API Index</title>
|
||||
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
||||
</index>
|
||||
</part>
|
||||
</book>
|
||||
@ -1,70 +0,0 @@
|
||||
<part id="eek-overview">
|
||||
<title>Usage Overview</title>
|
||||
<partintro>
|
||||
|
||||
<para>libeek is a library to create keyboard-like user interface.
|
||||
Since it is designed as simple as possible, it provides only two
|
||||
kind of objects. One is <emphasis>keyboard element</emphasis>
|
||||
(objects derived from #EekElement) and another is
|
||||
<emphasis>keyboard layout engine</emphasis> (objects which
|
||||
implements the #EekLayout interface).</para>
|
||||
|
||||
<para>A keyboard element represents either a keyboard
|
||||
(#EekKeyboard), a section (#EekSection), or a key (#EekKey). Each
|
||||
element implements the Builder design pattern so that it can map
|
||||
itself to different UI widgets (#ClutterActor, #GtkDrawingArea,
|
||||
aso).</para>
|
||||
|
||||
<para>A layout engine arranges keyboard elements using information
|
||||
from external configuration mechanisms (libxklavier, XKB,
|
||||
matchbox-keyboard layouts in XML, aso)</para>
|
||||
|
||||
<para>Here is a sample code which demonstrates (1) keyboard
|
||||
elements are arranged with the system keyboard layout using
|
||||
libxklavier and (2) keyboard elements are mapped into
|
||||
#ClutterActor:</para>
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
EekLayout *layout;
|
||||
EekKeyboard *keyboard;
|
||||
ClutterActor *actor;
|
||||
|
||||
/* Create a layout engine based on libxklavier configuration. */
|
||||
layout = eek_xkl_layout_new ();
|
||||
|
||||
/* Create a keyboard from the given layout. */
|
||||
keyboard = eek_keyboard_new (layout, initial_width, initial_height);
|
||||
|
||||
/* Create a ClutterActor. */
|
||||
actor = eek_clutter_keyboard_new (eekboard->keyboard);
|
||||
|
||||
/* Add the actor to a stage. */
|
||||
clutter_group_add (CLUTTER_GROUP(stage), actor);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>libeek currently supports GTK+ and Clutter as UI toolkits.
|
||||
To create a keyboard-like #GtkWidget instead of #ClutterActor,
|
||||
replace eek_clutter_keyboard_new() with eek_gtk_keyboard_new().
|
||||
Similarly, if you want to use XKB configuration directly (without
|
||||
libxklavier), you will only need to replace eek_xkl_layout_new ()
|
||||
with eek_xkb_layout_new().</para>
|
||||
|
||||
<para>In the above example, a keyboard is represented as a tree of
|
||||
#EekElement -- #EekKeyboard contains one or more #EekSection's and
|
||||
#EekSection contains one or more #EekKey's. Each element may emit
|
||||
events when user pushes the corresponding UI widget.</para>
|
||||
<para>
|
||||
Here is another sample code which demonstrates logical events on
|
||||
#EekElement:
|
||||
</para>
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* Find a key element in the logical keyboard. */
|
||||
EekKey *key = eek_keyboard_find_key_by_keycode (keyboard, 0x38);
|
||||
g_signal_connect (key, "pressed", on_a_pressed);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
<para>When user pushed a widget which looks like "a" key (i.e. keycode 0x38), on_a_pressed will be called.</para>
|
||||
</partintro>
|
||||
</part>
|
||||
@ -1,544 +0,0 @@
|
||||
<SECTION>
|
||||
<FILE>eek</FILE>
|
||||
eek_init
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-clutter</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-clutter-key</FILE>
|
||||
<TITLE>EekClutterKey</TITLE>
|
||||
EekClutterKey
|
||||
EekClutterKeyClass
|
||||
eek_clutter_key_new
|
||||
<SUBSECTION Standard>
|
||||
EEK_CLUTTER_KEY
|
||||
EEK_CLUTTER_KEY_CLASS
|
||||
EEK_CLUTTER_KEY_GET_CLASS
|
||||
EEK_IS_CLUTTER_KEY
|
||||
EEK_IS_CLUTTER_KEY_CLASS
|
||||
EEK_TYPE_CLUTTER_KEY
|
||||
EekClutterKeyPrivate
|
||||
eek_clutter_key_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-clutter-keyboard</FILE>
|
||||
<TITLE>EekClutterKeyboard</TITLE>
|
||||
EekClutterKeyboard
|
||||
EekClutterKeyboardClass
|
||||
eek_clutter_keyboard_new
|
||||
eek_clutter_keyboard_set_theme
|
||||
<SUBSECTION Standard>
|
||||
EEK_CLUTTER_KEYBOARD
|
||||
EEK_CLUTTER_KEYBOARD_CLASS
|
||||
EEK_CLUTTER_KEYBOARD_GET_CLASS
|
||||
EEK_IS_CLUTTER_KEYBOARD
|
||||
EEK_IS_CLUTTER_KEYBOARD_CLASS
|
||||
EEK_TYPE_CLUTTER_KEYBOARD
|
||||
EekClutterKeyboardPrivate
|
||||
eek_clutter_keyboard_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-clutter-renderer</FILE>
|
||||
<TITLE>EekClutterRenderer</TITLE>
|
||||
EekClutterRenderer
|
||||
EekClutterRendererClass
|
||||
eek_clutter_renderer_new
|
||||
eek_clutter_renderer_render_key
|
||||
<SUBSECTION Standard>
|
||||
EEK_CLUTTER_RENDERER
|
||||
EEK_CLUTTER_RENDERER_CLASS
|
||||
EEK_CLUTTER_RENDERER_GET_CLASS
|
||||
EEK_IS_CLUTTER_RENDERER
|
||||
EEK_IS_CLUTTER_RENDERER_CLASS
|
||||
EEK_TYPE_CLUTTER_RENDERER
|
||||
EekClutterRendererPrivate
|
||||
eek_clutter_renderer_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-clutter-section</FILE>
|
||||
<TITLE>EekClutterSection</TITLE>
|
||||
EekClutterSection
|
||||
EekClutterSectionClass
|
||||
eek_clutter_section_new
|
||||
<SUBSECTION Standard>
|
||||
EEK_CLUTTER_SECTION
|
||||
EEK_CLUTTER_SECTION_CLASS
|
||||
EEK_CLUTTER_SECTION_GET_CLASS
|
||||
EEK_IS_CLUTTER_SECTION
|
||||
EEK_IS_CLUTTER_SECTION_CLASS
|
||||
EEK_TYPE_CLUTTER_SECTION
|
||||
EekClutterSectionPrivate
|
||||
eek_clutter_section_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-container</FILE>
|
||||
<TITLE>EekContainer</TITLE>
|
||||
EekCallback
|
||||
EekCompareFunc
|
||||
EekContainer
|
||||
EekContainerClass
|
||||
eek_container_add_child
|
||||
eek_container_find
|
||||
eek_container_foreach_child
|
||||
<SUBSECTION Standard>
|
||||
EEK_CONTAINER
|
||||
EEK_CONTAINER_CLASS
|
||||
EEK_CONTAINER_GET_CLASS
|
||||
EEK_IS_CONTAINER
|
||||
EEK_IS_CONTAINER_CLASS
|
||||
EEK_TYPE_CONTAINER
|
||||
EekContainerPrivate
|
||||
eek_container_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-element</FILE>
|
||||
<TITLE>EekElement</TITLE>
|
||||
EekElement
|
||||
EekElementClass
|
||||
eek_element_get_absolute_position
|
||||
eek_element_get_bounds
|
||||
eek_element_get_group
|
||||
eek_element_get_level
|
||||
eek_element_get_name
|
||||
eek_element_get_parent
|
||||
eek_element_get_symbol_index
|
||||
eek_element_set_bounds
|
||||
eek_element_set_group
|
||||
eek_element_set_level
|
||||
eek_element_set_name
|
||||
eek_element_set_parent
|
||||
eek_element_set_position
|
||||
eek_element_set_size
|
||||
eek_element_set_symbol_index
|
||||
<SUBSECTION Standard>
|
||||
EEK_ELEMENT
|
||||
EEK_ELEMENT_CLASS
|
||||
EEK_ELEMENT_GET_CLASS
|
||||
EEK_IS_ELEMENT
|
||||
EEK_IS_ELEMENT_CLASS
|
||||
EEK_TYPE_ELEMENT
|
||||
EekElementPrivate
|
||||
eek_element_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-gtk</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-gtk-keyboard</FILE>
|
||||
<TITLE>EekGtkKeyboard</TITLE>
|
||||
EekGtkKeyboard
|
||||
EekGtkKeyboardClass
|
||||
eek_gtk_keyboard_new
|
||||
eek_gtk_keyboard_set_theme
|
||||
<SUBSECTION Standard>
|
||||
EEK_GTK_KEYBOARD
|
||||
EEK_GTK_KEYBOARD_CLASS
|
||||
EEK_GTK_KEYBOARD_GET_CLASS
|
||||
EEK_IS_GTK_KEYBOARD
|
||||
EEK_IS_GTK_KEYBOARD_CLASS
|
||||
EEK_TYPE_GTK_KEYBOARD
|
||||
EekGtkKeyboardPrivate
|
||||
eek_gtk_keyboard_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-key</FILE>
|
||||
<TITLE>EekKey</TITLE>
|
||||
EekKey
|
||||
EekKeyClass
|
||||
eek_key_get_index
|
||||
eek_key_get_keycode
|
||||
eek_key_get_oref
|
||||
eek_key_get_symbol
|
||||
eek_key_get_symbol_at_index
|
||||
eek_key_get_symbol_matrix
|
||||
eek_key_get_symbol_with_fallback
|
||||
eek_key_is_locked
|
||||
eek_key_is_pressed
|
||||
eek_key_set_index
|
||||
eek_key_set_keycode
|
||||
eek_key_set_oref
|
||||
eek_key_set_symbol_matrix
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_KEY
|
||||
EEK_IS_KEY_CLASS
|
||||
EEK_KEY
|
||||
EEK_KEY_CLASS
|
||||
EEK_KEY_GET_CLASS
|
||||
EEK_TYPE_KEY
|
||||
EekKeyPrivate
|
||||
eek_key_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-keyboard</FILE>
|
||||
<TITLE>EekKeyboard</TITLE>
|
||||
EekKeyboard
|
||||
EekKeyboardClass
|
||||
EekModifierKey
|
||||
eek_keyboard_add_outline
|
||||
eek_keyboard_create_section
|
||||
eek_keyboard_find_key_by_keycode
|
||||
eek_keyboard_get_alt_gr_mask
|
||||
eek_keyboard_get_group
|
||||
eek_keyboard_get_layout
|
||||
eek_keyboard_get_level
|
||||
eek_keyboard_get_locked_keys
|
||||
eek_keyboard_get_modifier_behavior
|
||||
eek_keyboard_get_modifiers
|
||||
eek_keyboard_get_num_lock_mask
|
||||
eek_keyboard_get_outline
|
||||
eek_keyboard_get_pressed_keys
|
||||
eek_keyboard_get_size
|
||||
eek_keyboard_get_symbol_index
|
||||
eek_keyboard_new
|
||||
eek_keyboard_set_alt_gr_mask
|
||||
eek_keyboard_set_group
|
||||
eek_keyboard_set_level
|
||||
eek_keyboard_set_modifier_behavior
|
||||
eek_keyboard_set_modifiers
|
||||
eek_keyboard_set_num_lock_mask
|
||||
eek_keyboard_set_size
|
||||
eek_keyboard_set_symbol_index
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_KEYBOARD
|
||||
EEK_IS_KEYBOARD_CLASS
|
||||
EEK_KEYBOARD
|
||||
EEK_KEYBOARD_CLASS
|
||||
EEK_KEYBOARD_GET_CLASS
|
||||
EEK_TYPE_KEYBOARD
|
||||
EekKeyboardPrivate
|
||||
eek_keyboard_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-keysym</FILE>
|
||||
<TITLE>EekKeysym</TITLE>
|
||||
EekKeysym
|
||||
EekKeysymClass
|
||||
eek_keysym_get_xkeysym
|
||||
eek_keysym_new
|
||||
eek_keysym_new_from_name
|
||||
eek_keysym_new_with_modifier
|
||||
<SUBSECTION Standard>
|
||||
EEK_INVALID_KEYSYM
|
||||
EEK_IS_KEYSYM
|
||||
EEK_IS_KEYSYM_CLASS
|
||||
EEK_KEYSYM
|
||||
EEK_KEYSYM_CLASS
|
||||
EEK_KEYSYM_GET_CLASS
|
||||
EEK_TYPE_KEYSYM
|
||||
EekKeysymPrivate
|
||||
eek_keysym_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-layout</FILE>
|
||||
<TITLE>EekLayout</TITLE>
|
||||
EekLayout
|
||||
EekLayoutClass
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_LAYOUT
|
||||
EEK_IS_LAYOUT_CLASS
|
||||
EEK_LAYOUT
|
||||
EEK_LAYOUT_CLASS
|
||||
EEK_LAYOUT_GET_CLASS
|
||||
EEK_TYPE_LAYOUT
|
||||
eek_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-marshalers</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-section</FILE>
|
||||
<TITLE>EekSection</TITLE>
|
||||
EekSection
|
||||
EekSectionClass
|
||||
eek_section_add_row
|
||||
eek_section_create_key
|
||||
eek_section_find_key_by_keycode
|
||||
eek_section_get_angle
|
||||
eek_section_get_n_rows
|
||||
eek_section_get_row
|
||||
eek_section_set_angle
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_SECTION
|
||||
EEK_IS_SECTION_CLASS
|
||||
EEK_SECTION
|
||||
EEK_SECTION_CLASS
|
||||
EEK_SECTION_GET_CLASS
|
||||
EEK_TYPE_SECTION
|
||||
EekSectionPrivate
|
||||
eek_section_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-serializable</FILE>
|
||||
<TITLE>EekSerializable</TITLE>
|
||||
EekSerializableIface
|
||||
eek_serializable_deserialize
|
||||
eek_serializable_serialize
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_SERIALIZABLE
|
||||
EEK_SERIALIZABLE
|
||||
EEK_SERIALIZABLE_GET_IFACE
|
||||
EEK_TYPE_SERIALIZABLE
|
||||
eek_serializable_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-special-keysym-entries</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-symbol</FILE>
|
||||
<TITLE>EekSymbol</TITLE>
|
||||
EekSymbol
|
||||
EekSymbolCategory
|
||||
EekSymbolClass
|
||||
eek_symbol_category_from_name
|
||||
eek_symbol_category_get_name
|
||||
eek_symbol_get_category
|
||||
eek_symbol_get_icon_name
|
||||
eek_symbol_get_label
|
||||
eek_symbol_get_modifier_mask
|
||||
eek_symbol_get_name
|
||||
eek_symbol_is_modifier
|
||||
eek_symbol_new
|
||||
eek_symbol_set_category
|
||||
eek_symbol_set_icon_name
|
||||
eek_symbol_set_label
|
||||
eek_symbol_set_modifier_mask
|
||||
eek_symbol_set_name
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_SYMBOL
|
||||
EEK_IS_SYMBOL_CLASS
|
||||
EEK_SYMBOL
|
||||
EEK_SYMBOL_CLASS
|
||||
EEK_SYMBOL_GET_CLASS
|
||||
EEK_TYPE_SYMBOL
|
||||
EekSymbolPrivate
|
||||
eek_symbol_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-symbol-matrix</FILE>
|
||||
EekSymbolMatrix
|
||||
eek_symbol_matrix_copy
|
||||
eek_symbol_matrix_free
|
||||
eek_symbol_matrix_get_symbol
|
||||
eek_symbol_matrix_new
|
||||
eek_symbol_matrix_set_symbol
|
||||
<SUBSECTION Standard>
|
||||
EEK_TYPE_SYMBOL_MATRIX
|
||||
eek_symbol_matrix_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-text</FILE>
|
||||
<TITLE>EekText</TITLE>
|
||||
EekText
|
||||
EekTextClass
|
||||
eek_text_get_text
|
||||
eek_text_new
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_TEXT
|
||||
EEK_IS_TEXT_CLASS
|
||||
EEK_TEXT
|
||||
EEK_TEXT_CLASS
|
||||
EEK_TEXT_GET_CLASS
|
||||
EEK_TYPE_TEXT
|
||||
EekTextPrivate
|
||||
eek_text_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-theme-context</FILE>
|
||||
EekThemeContextClass
|
||||
eek_theme_context_get_font
|
||||
eek_theme_context_get_resolution
|
||||
eek_theme_context_get_root_node
|
||||
eek_theme_context_get_theme
|
||||
eek_theme_context_new
|
||||
eek_theme_context_set_default_resolution
|
||||
eek_theme_context_set_font
|
||||
eek_theme_context_set_resolution
|
||||
eek_theme_context_set_theme
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_THEME_CONTEXT
|
||||
EEK_IS_THEME_CONTEXT_CLASS
|
||||
EEK_THEME_CONTEXT
|
||||
EEK_THEME_CONTEXT_CLASS
|
||||
EEK_THEME_CONTEXT_GET_CLASS
|
||||
EEK_TYPE_THEME_CONTEXT
|
||||
eek_theme_context_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-theme-private</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-types</FILE>
|
||||
EEK_INVALID_KEYCODE
|
||||
EekBounds
|
||||
EekColor
|
||||
EekContainer
|
||||
EekElement
|
||||
EekGradientType
|
||||
EekKey
|
||||
EekKeyboard
|
||||
EekKeysym
|
||||
EekModifierBehavior
|
||||
EekModifierType
|
||||
EekOrientation
|
||||
EekOutline
|
||||
EekPoint
|
||||
EekSection
|
||||
EekSymbol
|
||||
EekSymbolMatrix
|
||||
EekText
|
||||
EekTheme
|
||||
EekThemeContext
|
||||
EekThemeNode
|
||||
I_
|
||||
eek_bounds_copy
|
||||
eek_bounds_free
|
||||
eek_bounds_long_side
|
||||
eek_color_copy
|
||||
eek_color_free
|
||||
eek_color_new
|
||||
eek_outline_copy
|
||||
eek_outline_free
|
||||
eek_point_copy
|
||||
eek_point_free
|
||||
eek_point_rotate
|
||||
<SUBSECTION Standard>
|
||||
EEK_TYPE_BOUNDS
|
||||
EEK_TYPE_COLOR
|
||||
EEK_TYPE_OUTLINE
|
||||
EEK_TYPE_POINT
|
||||
eek_bounds_get_type
|
||||
eek_color_get_type
|
||||
eek_outline_get_type
|
||||
eek_point_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-unicode-keysym-entries</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xkb</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xkb-layout</FILE>
|
||||
<TITLE>EekXkbLayout</TITLE>
|
||||
EekXkbLayout
|
||||
EekXkbLayoutClass
|
||||
eek_xkb_layout_get_geometry
|
||||
eek_xkb_layout_get_keycodes
|
||||
eek_xkb_layout_get_symbols
|
||||
eek_xkb_layout_new
|
||||
eek_xkb_layout_set_geometry
|
||||
eek_xkb_layout_set_keycodes
|
||||
eek_xkb_layout_set_names
|
||||
eek_xkb_layout_set_names_full
|
||||
eek_xkb_layout_set_names_full_valist
|
||||
eek_xkb_layout_set_symbols
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_XKB_LAYOUT
|
||||
EEK_IS_XKB_LAYOUT_CLASS
|
||||
EEK_TYPE_XKB_LAYOUT
|
||||
EEK_XKB_LAYOUT
|
||||
EEK_XKB_LAYOUT_CLASS
|
||||
EEK_XKB_LAYOUT_GET_CLASS
|
||||
EekXkbLayoutPrivate
|
||||
eek_xkb_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xkeysym-keysym-entries</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xkl</FILE>
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xkl-layout</FILE>
|
||||
<TITLE>EekXklLayout</TITLE>
|
||||
EekXklLayout
|
||||
EekXklLayoutClass
|
||||
eek_xkl_layout_disable_option
|
||||
eek_xkl_layout_enable_option
|
||||
eek_xkl_layout_get_layouts
|
||||
eek_xkl_layout_get_model
|
||||
eek_xkl_layout_get_option
|
||||
eek_xkl_layout_get_options
|
||||
eek_xkl_layout_get_variants
|
||||
eek_xkl_layout_new
|
||||
eek_xkl_layout_set_config
|
||||
eek_xkl_layout_set_config_full
|
||||
eek_xkl_layout_set_layouts
|
||||
eek_xkl_layout_set_model
|
||||
eek_xkl_layout_set_options
|
||||
eek_xkl_layout_set_variants
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_XKL_LAYOUT
|
||||
EEK_IS_XKL_LAYOUT_CLASS
|
||||
EEK_TYPE_XKL_LAYOUT
|
||||
EEK_XKL_LAYOUT
|
||||
EEK_XKL_LAYOUT_CLASS
|
||||
EEK_XKL_LAYOUT_GET_CLASS
|
||||
EekXklLayoutPrivate
|
||||
eek_xkl_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xml</FILE>
|
||||
EEK_XML_SCHEMA_VERSION
|
||||
eek_keyboard_output
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eek-xml-layout</FILE>
|
||||
<TITLE>EekXmlLayout</TITLE>
|
||||
EekXmlLayout
|
||||
EekXmlLayoutClass
|
||||
eek_xml_layout_get_source
|
||||
eek_xml_layout_new
|
||||
eek_xml_layout_set_source
|
||||
<SUBSECTION Standard>
|
||||
EEK_IS_XML_LAYOUT
|
||||
EEK_IS_XML_LAYOUT_CLASS
|
||||
EEK_TYPE_XML_LAYOUT
|
||||
EEK_XML_LAYOUT
|
||||
EEK_XML_LAYOUT_CLASS
|
||||
EEK_XML_LAYOUT_GET_CLASS
|
||||
EekXmlLayoutPrivate
|
||||
eek_xml_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
||||
[
|
||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||
]>
|
||||
<book id="index">
|
||||
<bookinfo>
|
||||
<title>eekboard Reference Manual</title>
|
||||
<releaseinfo>
|
||||
for eekboard 0.90.0.
|
||||
</releaseinfo>
|
||||
<copyright>
|
||||
<year>2011</year>
|
||||
<holder>Daiki Ueno</holder>
|
||||
</copyright>
|
||||
|
||||
<copyright>
|
||||
<year>2011</year>
|
||||
<holder>Red Hat, Inc.</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
Version 1.3 or any later version published by the Free Software
|
||||
Foundation; with no Invariant Sections, no Front-Cover Texts and
|
||||
no Back-Cover Texts. A copy of the license is included in the
|
||||
section entitled "GNU Free Documentation License".
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<part id="apireference">
|
||||
<title>API Manual</title>
|
||||
<chapter>
|
||||
<title>Client interface to eekboard-server</title>
|
||||
<xi:include href="xml/eekboard-client.xml"/>
|
||||
<xi:include href="xml/eekboard-context.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>Server interface to implement custom eekboard-server</title>
|
||||
<xi:include href="xml/eekboard-service.xml"/>
|
||||
<xi:include href="xml/eekboard-context-service.xml"/>
|
||||
</chapter>
|
||||
<chapter id="object-tree">
|
||||
<title>Object Hierarchy</title>
|
||||
<xi:include href="xml/tree_index.sgml"/>
|
||||
</chapter>
|
||||
<index id="api-index-full">
|
||||
<title>API Index</title>
|
||||
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
||||
</index>
|
||||
</part>
|
||||
</book>
|
||||
@ -1,104 +0,0 @@
|
||||
<SECTION>
|
||||
<FILE>eekboard-client</FILE>
|
||||
<TITLE>EekboardClient</TITLE>
|
||||
EekboardClient
|
||||
EekboardClientClass
|
||||
eekboard_client_new
|
||||
eekboard_client_create_context
|
||||
eekboard_client_push_context
|
||||
eekboard_client_pop_context
|
||||
eekboard_client_destroy_context
|
||||
EekboardClientPrivate
|
||||
<SUBSECTION Standard>
|
||||
EEKBOARD_CLIENT
|
||||
EEKBOARD_IS_CLIENT
|
||||
EEKBOARD_TYPE_CLIENT
|
||||
eekboard_client_get_type
|
||||
EEKBOARD_CLIENT_CLASS
|
||||
EEKBOARD_IS_CLIENT_CLASS
|
||||
EEKBOARD_CLIENT_GET_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eekboard-service</FILE>
|
||||
<TITLE>EekboardService</TITLE>
|
||||
EEKBOARD_SERVICE_PATH
|
||||
EEKBOARD_SERVICE_INTERFACE
|
||||
EekboardService
|
||||
EekboardServiceClass
|
||||
eekboard_service_new
|
||||
EekboardServicePrivate
|
||||
<SUBSECTION Standard>
|
||||
EEKBOARD_SERVICE
|
||||
EEKBOARD_IS_SERVICE
|
||||
EEKBOARD_TYPE_SERVICE
|
||||
eekboard_service_get_type
|
||||
EEKBOARD_SERVICE_CLASS
|
||||
EEKBOARD_IS_SERVICE_CLASS
|
||||
EEKBOARD_SERVICE_GET_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eekboard-context</FILE>
|
||||
<TITLE>EekboardContext</TITLE>
|
||||
EekboardContext
|
||||
EekboardContextClass
|
||||
eekboard_context_new
|
||||
eekboard_context_add_keyboard
|
||||
eekboard_context_remove_keyboard
|
||||
eekboard_context_set_keyboard
|
||||
eekboard_context_show_keyboard
|
||||
eekboard_context_hide_keyboard
|
||||
eekboard_context_set_group
|
||||
eekboard_context_get_group
|
||||
eekboard_context_press_keycode
|
||||
eekboard_context_release_keycode
|
||||
eekboard_context_is_keyboard_visible
|
||||
eekboard_context_set_enabled
|
||||
eekboard_context_is_enabled
|
||||
eekboard_context_set_fullscreen
|
||||
EekboardContextPrivate
|
||||
<SUBSECTION Standard>
|
||||
EEKBOARD_CONTEXT
|
||||
EEKBOARD_IS_CONTEXT
|
||||
EEKBOARD_TYPE_CONTEXT
|
||||
eekboard_context_get_type
|
||||
EEKBOARD_CONTEXT_CLASS
|
||||
EEKBOARD_IS_CONTEXT_CLASS
|
||||
EEKBOARD_CONTEXT_GET_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eekboard-context-service</FILE>
|
||||
<TITLE>EekboardContextService</TITLE>
|
||||
EEKBOARD_CONTEXT_SERVICE_PATH
|
||||
EEKBOARD_CONTEXT_SERVICE_INTERFACE
|
||||
EekboardContextService
|
||||
EekboardContextServiceClass
|
||||
eekboard_context_service_enable
|
||||
eekboard_context_service_disable
|
||||
eekboard_context_service_get_keyboard
|
||||
eekboard_context_service_get_fullscreen
|
||||
eekboard_context_service_get_client_name
|
||||
EekboardContextServicePrivate
|
||||
<SUBSECTION Standard>
|
||||
EEKBOARD_CONTEXT_SERVICE
|
||||
EEKBOARD_IS_CONTEXT_SERVICE
|
||||
EEKBOARD_TYPE_CONTEXT_SERVICE
|
||||
eekboard_context_service_get_type
|
||||
EEKBOARD_CONTEXT_SERVICE_CLASS
|
||||
EEKBOARD_IS_CONTEXT_SERVICE_CLASS
|
||||
EEKBOARD_CONTEXT_SERVICE_GET_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>eekboard-xklutil</FILE>
|
||||
eekboard_xkl_config_rec_from_string
|
||||
eekboard_xkl_config_rec_to_string
|
||||
eekboard_xkl_list_models
|
||||
eekboard_xkl_list_layouts
|
||||
eekboard_xkl_list_option_groups
|
||||
eekboard_xkl_list_layout_variants
|
||||
eekboard_xkl_list_options
|
||||
</SECTION>
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
eekboard_client_get_type
|
||||
eekboard_context_get_type
|
||||
eekboard_context_service_get_type
|
||||
eekboard_service_get_type
|
||||
@ -37,6 +37,9 @@
|
||||
|
||||
#include "eek-gtk-keyboard.h"
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LAST
|
||||
@ -52,22 +55,13 @@ typedef struct _EekGtkKeyboardPrivate
|
||||
{
|
||||
EekRenderer *renderer;
|
||||
LevelKeyboard *keyboard;
|
||||
GtkCssProvider *css_provider;
|
||||
GtkStyleContext *scontext;
|
||||
|
||||
GdkEventSequence *sequence; // unowned reference
|
||||
} EekGtkKeyboardPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
|
||||
|
||||
static void on_button_pressed (struct squeek_button *button, struct squeek_view *view,
|
||||
EekGtkKeyboard *self);
|
||||
static void on_button_released (const struct squeek_button *button,
|
||||
struct squeek_view *view,
|
||||
EekGtkKeyboard *self);
|
||||
static void render_pressed_button (GtkWidget *widget, struct button_place *place);
|
||||
static void render_locked_button (GtkWidget *widget,
|
||||
struct button_place *place);
|
||||
static void render_released_button (GtkWidget *widget,
|
||||
const struct squeek_button *button);
|
||||
|
||||
@ -98,7 +92,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,
|
||||
@ -107,30 +101,10 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
gtk_widget_get_scale_factor (self));
|
||||
}
|
||||
|
||||
// render the keyboard without any key activity (TODO: from a cached buffer)
|
||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||
|
||||
struct squeek_view *view = squeek_layout_get_current_view(priv->keyboard->layout);
|
||||
|
||||
/* redraw pressed key */
|
||||
const GList *list = priv->keyboard->pressed_keys;
|
||||
for (const GList *head = list; head; head = g_list_next (head)) {
|
||||
struct button_place place = squeek_view_find_key(
|
||||
view, head->data
|
||||
);
|
||||
if (place.button)
|
||||
render_pressed_button (self, &place);
|
||||
}
|
||||
|
||||
/* redraw locked key */
|
||||
list = priv->keyboard->locked_keys;
|
||||
for (const GList *head = list; head; head = g_list_next (head)) {
|
||||
struct button_place place = squeek_view_find_key(
|
||||
view, ((EekModifierKey *)head->data)->key
|
||||
);
|
||||
if (place.button)
|
||||
render_locked_button (self, &place);
|
||||
}
|
||||
|
||||
// render only a few remaining changes
|
||||
squeek_layout_draw_all_changed(priv->keyboard->layout, EEK_GTK_KEYBOARD(self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -154,84 +128,24 @@ static void depress(EekGtkKeyboard *self,
|
||||
gdouble x, gdouble y, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
struct squeek_view *view = level_keyboard_current(priv->keyboard);
|
||||
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
|
||||
|
||||
if (button) {
|
||||
eek_keyboard_press_key(
|
||||
priv->keyboard,
|
||||
squeek_button_get_key(button),
|
||||
time
|
||||
);
|
||||
on_button_pressed(button, view, self);
|
||||
}
|
||||
squeek_layout_depress(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
|
||||
}
|
||||
|
||||
static void drag(EekGtkKeyboard *self,
|
||||
gdouble x, gdouble y, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
struct squeek_view *view = level_keyboard_current(priv->keyboard);
|
||||
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
|
||||
GList *list, *head;
|
||||
|
||||
list = g_list_copy(priv->keyboard->pressed_keys);
|
||||
|
||||
if (button) {
|
||||
gboolean found = FALSE;
|
||||
|
||||
for (head = list; head; head = g_list_next (head)) {
|
||||
struct squeek_key *key = head->data;
|
||||
if (squeek_button_has_key(button, key)) {
|
||||
found = TRUE;
|
||||
} else {
|
||||
eek_keyboard_release_key(priv->keyboard, key, time);
|
||||
// The released handler proceeds to ignore this info...
|
||||
// let's do this for consistency nevertheless
|
||||
struct button_place place = squeek_view_find_key(view, key);
|
||||
on_button_released(place.button, view, self);
|
||||
}
|
||||
}
|
||||
g_list_free (list);
|
||||
|
||||
if (!found) {
|
||||
eek_keyboard_press_key(
|
||||
priv->keyboard,
|
||||
squeek_button_get_key(button),
|
||||
time
|
||||
);
|
||||
|
||||
on_button_pressed(button, view, self);
|
||||
}
|
||||
} else {
|
||||
for (head = list; head; head = g_list_next (head)) {
|
||||
struct squeek_key *key = head->data;
|
||||
eek_keyboard_release_key(priv->keyboard, key, time);
|
||||
// The released handler proceeds to ignore this info...
|
||||
// let's do this for consistency nevertheless
|
||||
struct button_place place = squeek_view_find_key(view, key);
|
||||
on_button_released(place.button, view, self);
|
||||
}
|
||||
g_list_free (list);
|
||||
}
|
||||
squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
|
||||
}
|
||||
|
||||
static void release(EekGtkKeyboard *self, guint32 time)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
struct squeek_view *view = level_keyboard_current(priv->keyboard);
|
||||
|
||||
GList *list = g_list_copy(priv->keyboard->pressed_keys);
|
||||
for (GList *head = list; head; head = g_list_next (head)) {
|
||||
struct squeek_key *key = head->data;
|
||||
eek_keyboard_release_key(priv->keyboard, key, time);
|
||||
// The released handler proceeds to ignore this info...
|
||||
// let's do this for consistency nevertheless
|
||||
struct button_place place = squeek_view_find_key(view, key);
|
||||
on_button_released(place.button, view, self);
|
||||
}
|
||||
g_list_free (list);
|
||||
squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, time, self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -306,16 +220,10 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
|
||||
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
|
||||
|
||||
if (priv->keyboard) {
|
||||
GList *head;
|
||||
|
||||
for (head = priv->keyboard->pressed_keys; head; head = g_list_next (head)) {
|
||||
/* Unlike other places where we call this, we don't call
|
||||
on_button_released afterwards since we don't want to queue a
|
||||
redraw. */
|
||||
eek_keyboard_release_key(priv->keyboard, head->data,
|
||||
squeek_layout_release_all_only(
|
||||
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
gdk_event_get_time(NULL));
|
||||
}
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self);
|
||||
}
|
||||
@ -346,13 +254,9 @@ eek_gtk_keyboard_dispose (GObject *object)
|
||||
}
|
||||
|
||||
if (priv->keyboard) {
|
||||
GList *head;
|
||||
|
||||
for (head = priv->keyboard->pressed_keys; head; head = g_list_next (head)) {
|
||||
eek_keyboard_release_key(priv->keyboard, head->data,
|
||||
squeek_layout_release_all_only(
|
||||
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
|
||||
gdk_event_get_time(NULL));
|
||||
}
|
||||
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
|
||||
@ -383,22 +287,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:
|
||||
@ -437,18 +326,17 @@ render_pressed_button (GtkWidget *widget,
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
render_locked_button (GtkWidget *widget, struct button_place *place)
|
||||
void
|
||||
eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place)
|
||||
{
|
||||
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
|
||||
GdkWindow *window = gtk_widget_get_window (widget);
|
||||
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET(self));
|
||||
cairo_region_t *region = gdk_window_get_clip_region (window);
|
||||
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
|
||||
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
|
||||
|
||||
eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
|
||||
eek_renderer_render_button (priv->renderer, cr, &place, 1.0, TRUE);
|
||||
|
||||
gdk_window_end_draw_frame (window, context);
|
||||
|
||||
@ -476,9 +364,8 @@ render_released_button (GtkWidget *widget,
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_pressed (struct squeek_button *button,
|
||||
struct squeek_view *view,
|
||||
void
|
||||
eek_gtk_on_button_pressed (struct button_place place,
|
||||
EekGtkKeyboard *self)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||
@ -487,10 +374,6 @@ on_button_pressed (struct squeek_button *button,
|
||||
if (!priv->renderer)
|
||||
return;
|
||||
|
||||
struct button_place place = {
|
||||
.button = button,
|
||||
.row = squeek_view_get_row(view, button),
|
||||
};
|
||||
if (!place.row) {
|
||||
return;
|
||||
}
|
||||
@ -506,8 +389,8 @@ on_button_pressed (struct squeek_button *button,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_released (const struct squeek_button *button,
|
||||
void
|
||||
eek_gtk_on_button_released (const struct squeek_button *button,
|
||||
struct squeek_view *view,
|
||||
EekGtkKeyboard *self)
|
||||
{
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type())
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
#ifndef EEK_GTK_H
|
||||
#define EEK_GTK_H 1
|
||||
|
||||
#include "eek.h"
|
||||
#include "eek-gtk-keyboard.h"
|
||||
|
||||
#endif /* EEK_GTK_H */
|
||||
@ -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);
|
||||
}
|
||||
@ -31,101 +31,13 @@
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include "eek-enumtypes.h"
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
#include "eekboard/key-emitter.h"
|
||||
#include "keymap.h"
|
||||
#include "src/keyboard.h"
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
|
||||
EekModifierKey *
|
||||
eek_modifier_key_copy (EekModifierKey *modkey)
|
||||
{
|
||||
return g_slice_dup (EekModifierKey, modkey);
|
||||
}
|
||||
|
||||
void
|
||||
eek_modifier_key_free (EekModifierKey *modkey)
|
||||
{
|
||||
g_slice_free (EekModifierKey, modkey);
|
||||
}
|
||||
|
||||
void
|
||||
eek_keyboard_set_key_locked (LevelKeyboard *keyboard,
|
||||
struct squeek_key *key)
|
||||
{
|
||||
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
|
||||
modifier_key->modifiers = 0;
|
||||
modifier_key->key = key;
|
||||
keyboard->locked_keys =
|
||||
g_list_prepend (keyboard->locked_keys, modifier_key);
|
||||
}
|
||||
|
||||
/// Unlock all locked keys.
|
||||
/// All locked keys will unlock at the next keypress (should be called "stuck")
|
||||
/// Returns the number of handled keys
|
||||
/// TODO: may need to check key type in order to chain locks
|
||||
/// before pressing an "emitting" key
|
||||
static int unlock_keys(LevelKeyboard *keyboard) {
|
||||
int handled = 0;
|
||||
for (GList *head = keyboard->locked_keys; head; ) {
|
||||
EekModifierKey *modifier_key = head->data;
|
||||
GList *next = g_list_next (head);
|
||||
keyboard->locked_keys =
|
||||
g_list_remove_link (keyboard->locked_keys, head);
|
||||
//squeek_key_set_locked(squeek_button_get_key(modifier_key->button), false);
|
||||
|
||||
squeek_layout_set_state_from_press(keyboard->layout, keyboard, modifier_key->key);
|
||||
g_list_free1 (head);
|
||||
head = next;
|
||||
handled++;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
static void
|
||||
set_level_from_press (LevelKeyboard *keyboard, struct squeek_key *key)
|
||||
{
|
||||
// If the currently locked key was already handled in the unlock phase,
|
||||
// then skip
|
||||
if (unlock_keys(keyboard) == 0) {
|
||||
squeek_layout_set_state_from_press(keyboard->layout, keyboard, key);
|
||||
}
|
||||
}
|
||||
|
||||
void eek_keyboard_press_key(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp) {
|
||||
squeek_key_set_pressed(key, TRUE);
|
||||
keyboard->pressed_keys = g_list_prepend (keyboard->pressed_keys, key);
|
||||
|
||||
// Only take action about setting level *after* the key has taken effect, i.e. on release
|
||||
//set_level_from_press (keyboard, key);
|
||||
|
||||
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
|
||||
|
||||
guint keycode = squeek_key_get_keycode (key);
|
||||
|
||||
emit_key_activated(keyboard->manager, keyboard, keycode, TRUE, timestamp);
|
||||
}
|
||||
|
||||
void eek_keyboard_release_key(LevelKeyboard *keyboard,
|
||||
struct squeek_key *key,
|
||||
guint32 timestamp) {
|
||||
for (GList *head = keyboard->pressed_keys; head; head = g_list_next (head)) {
|
||||
if (squeek_key_equal(head->data, key)) {
|
||||
keyboard->pressed_keys = g_list_remove_link (keyboard->pressed_keys, head);
|
||||
g_list_free1 (head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_level_from_press (keyboard, key);
|
||||
|
||||
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
|
||||
|
||||
guint keycode = squeek_key_get_keycode (key);
|
||||
|
||||
emit_key_activated(keyboard->manager, keyboard, keycode, FALSE, timestamp);
|
||||
}
|
||||
|
||||
void level_keyboard_deinit(LevelKeyboard *self) {
|
||||
squeek_layout_free(self->layout);
|
||||
}
|
||||
|
||||
@ -33,43 +33,19 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _EekModifierKey {
|
||||
/*< public >*/
|
||||
EekModifierType modifiers;
|
||||
struct squeek_key *key;
|
||||
};
|
||||
typedef struct _EekModifierKey EekModifierKey;
|
||||
|
||||
/// Keyboard state holder
|
||||
struct _LevelKeyboard {
|
||||
struct squeek_layout *layout;
|
||||
struct squeek_layout *layout; // owned
|
||||
struct xkb_keymap *keymap;
|
||||
int keymap_fd; // keymap formatted as XKB string
|
||||
size_t keymap_len; // length of the data inside keymap_fd
|
||||
|
||||
GList *pressed_keys; // struct squeek_key*
|
||||
GList *locked_keys; // struct EekModifierKey*
|
||||
|
||||
guint id; // as a key to layout choices
|
||||
|
||||
EekboardContextService *manager; // unowned reference
|
||||
};
|
||||
typedef struct _LevelKeyboard LevelKeyboard;
|
||||
|
||||
/// Represents the path to the button within a view
|
||||
struct button_place {
|
||||
const struct squeek_row *row;
|
||||
const struct squeek_button *button;
|
||||
};
|
||||
|
||||
EekModifierKey *eek_modifier_key_copy
|
||||
(EekModifierKey *modkey);
|
||||
void eek_modifier_key_free
|
||||
(EekModifierKey *modkey);
|
||||
|
||||
void eek_keyboard_press_key(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp);
|
||||
void eek_keyboard_release_key(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp);
|
||||
|
||||
gchar * eek_keyboard_get_keymap
|
||||
(LevelKeyboard *keyboard);
|
||||
|
||||
|
||||
@ -24,12 +24,12 @@
|
||||
#include <string.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-renderer.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PCONTEXT,
|
||||
PROP_STYLE_CONTEXT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -38,11 +38,9 @@ typedef struct _EekRendererPrivate
|
||||
LevelKeyboard *keyboard;
|
||||
PangoContext *pcontext;
|
||||
GtkCssProvider *css_provider;
|
||||
GtkStyleContext *scontext;
|
||||
GtkStyleContext *key_context;
|
||||
GtkStyleContext *view_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 +52,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,23 +62,15 @@ 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);
|
||||
|
||||
static void invalidate (EekRenderer *renderer);
|
||||
static void render_button (EekRenderer *self,
|
||||
cairo_t *cr, struct button_place *place,
|
||||
gboolean active);
|
||||
cairo_t *cr, EekBounds view_bounds, struct button_place *place,
|
||||
gboolean pressed, gboolean locked);
|
||||
|
||||
struct _CreateKeyboardSurfaceCallbackData {
|
||||
cairo_t *cr;
|
||||
@ -109,7 +100,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, squeek_view_get_bounds(data->view), &place, FALSE, FALSE);
|
||||
|
||||
cairo_restore (data->cr);
|
||||
}
|
||||
@ -140,7 +131,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 (priv->view_context, &foreground);
|
||||
|
||||
EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
|
||||
|
||||
@ -151,11 +142,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->view_context,
|
||||
data.cr,
|
||||
0, 0,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
gtk_render_frame (priv->scontext,
|
||||
gtk_render_frame (priv->view_context,
|
||||
data.cr,
|
||||
0, 0,
|
||||
priv->allocation_width, priv->allocation_height);
|
||||
@ -180,46 +171,37 @@ 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);
|
||||
GtkBorder margin, border;
|
||||
gtk_style_context_get_margin(ctx, GTK_STATE_FLAG_NORMAL, &margin);
|
||||
gtk_style_context_get_border(ctx, GTK_STATE_FLAG_NORMAL, &border);
|
||||
|
||||
/* 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);
|
||||
gdouble x = margin.left + border.left;
|
||||
gdouble y = margin.top + border.top;
|
||||
EekBounds position = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = bounds.width - x - (margin.right + border.right),
|
||||
.height = bounds.height - y - (margin.bottom + border.bottom),
|
||||
};
|
||||
gtk_render_background (ctx, cr,
|
||||
position.x, position.y, position.width, position.height);
|
||||
gtk_render_frame (ctx, cr,
|
||||
position.x, position.y, position.width, position.height);
|
||||
}
|
||||
|
||||
static void
|
||||
render_button (EekRenderer *self,
|
||||
static void render_button_in_context(EekRenderer *self,
|
||||
gdouble scale,
|
||||
gint scale_factor,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *ctx,
|
||||
EekBounds view_bounds,
|
||||
struct button_place *place,
|
||||
gboolean active)
|
||||
{
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
cairo_surface_t *outline_surface;
|
||||
GHashTable *outline_surface_cache;
|
||||
gboolean active) {
|
||||
cairo_surface_t *outline_surface = NULL;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle extents = { 0, };
|
||||
EekColor foreground;
|
||||
@ -227,13 +209,7 @@ render_button (EekRenderer *self,
|
||||
/* render outline */
|
||||
EekBounds bounds = squeek_button_get_bounds(place->button);
|
||||
|
||||
if (active)
|
||||
outline_surface_cache = priv->active_outline_surface_cache;
|
||||
else
|
||||
outline_surface_cache = priv->outline_surface_cache;
|
||||
|
||||
outline_surface = g_hash_table_lookup (outline_surface_cache, place->button);
|
||||
if (!outline_surface) {
|
||||
{
|
||||
cairo_t *cr;
|
||||
|
||||
// Outline will be drawn on the outside of the button, so the
|
||||
@ -249,37 +225,31 @@ render_button (EekRenderer *self,
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_save (cr);
|
||||
eek_renderer_apply_transformation_for_button (self, cr, place, 1.0, FALSE);
|
||||
render_button_outline (self, cr, place->button, active);
|
||||
eek_renderer_apply_transformation_for_button (cr, view_bounds, place, 1.0, FALSE);
|
||||
render_outline (cr, ctx, bounds);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
g_hash_table_insert (outline_surface_cache,
|
||||
(gpointer)place->button,
|
||||
outline_surface);
|
||||
}
|
||||
|
||||
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
|
||||
cairo_surface_destroy(outline_surface);
|
||||
cairo_paint (cr);
|
||||
|
||||
eek_renderer_get_foreground_color (self, priv->key_context, &foreground);
|
||||
eek_renderer_get_foreground_color (ctx, &foreground);
|
||||
/* render icon (if any) */
|
||||
const char *icon_name = squeek_button_get_icon_name(place->button);
|
||||
|
||||
if (icon_name) {
|
||||
gint scale = priv->scale_factor;
|
||||
cairo_surface_t *icon_surface =
|
||||
eek_renderer_get_icon_surface (self, icon_name, 16 / priv->scale,
|
||||
scale);
|
||||
eek_renderer_get_icon_surface (icon_name, 16, scale_factor);
|
||||
if (icon_surface) {
|
||||
gint width = cairo_image_surface_get_width (icon_surface);
|
||||
gint height = cairo_image_surface_get_height (icon_surface);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr,
|
||||
(bounds.width - (double)width / scale) / 2,
|
||||
(bounds.height - (double)height / scale) / 2);
|
||||
(bounds.width - (double)width / scale_factor) / 2,
|
||||
(bounds.height - (double)height / scale_factor) / 2);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_clip (cr);
|
||||
/* Draw the shape of the icon using the foreground color */
|
||||
@ -288,13 +258,12 @@ render_button (EekRenderer *self,
|
||||
foreground.blue,
|
||||
foreground.alpha);
|
||||
cairo_mask_surface (cr, icon_surface, 0.0, 0.0);
|
||||
cairo_surface_destroy(icon_surface);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* render label */
|
||||
layout = pango_cairo_create_layout (cr);
|
||||
eek_renderer_real_render_button_label (self, layout, place->button);
|
||||
@ -311,12 +280,51 @@ 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,
|
||||
EekBounds view_bounds,
|
||||
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, priv->scale, priv->scale_factor, cr, ctx, view_bounds, 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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_renderer_apply_transformation_for_key:
|
||||
* @self: The renderer used to render the key
|
||||
@ -333,8 +341,8 @@ render_button (EekRenderer *self,
|
||||
* normal keys for popups.
|
||||
*/
|
||||
void
|
||||
eek_renderer_apply_transformation_for_button (EekRenderer *self,
|
||||
cairo_t *cr,
|
||||
eek_renderer_apply_transformation_for_button (cairo_t *cr,
|
||||
EekBounds view_bounds,
|
||||
struct button_place *place,
|
||||
gdouble scale,
|
||||
gboolean rotate)
|
||||
@ -342,8 +350,8 @@ eek_renderer_apply_transformation_for_button (EekRenderer *self,
|
||||
EekBounds bounds, rotated_bounds;
|
||||
gdouble s;
|
||||
|
||||
eek_renderer_get_button_bounds (self, place, &bounds, FALSE);
|
||||
eek_renderer_get_button_bounds (self, place, &rotated_bounds, TRUE);
|
||||
eek_renderer_get_button_bounds (view_bounds, place, &bounds, FALSE);
|
||||
eek_renderer_get_button_bounds (view_bounds, place, &rotated_bounds, TRUE);
|
||||
|
||||
gint angle = squeek_row_get_angle (place->row);
|
||||
|
||||
@ -372,7 +380,6 @@ eek_renderer_real_render_button_label (EekRenderer *self,
|
||||
}
|
||||
|
||||
PangoFontDescription *font;
|
||||
PangoLayoutLine *line;
|
||||
gdouble scale;
|
||||
|
||||
|
||||
@ -404,9 +411,10 @@ eek_renderer_real_render_button_label (EekRenderer *self,
|
||||
pango_font_description_free (font);
|
||||
|
||||
pango_layout_set_text (layout, label, -1);
|
||||
line = pango_layout_get_line (layout, 0);
|
||||
if (line->resolved_dir == PANGO_DIRECTION_RTL)
|
||||
PangoLayoutLine *line = pango_layout_get_line_readonly(layout, 0);
|
||||
if (line->resolved_dir == PANGO_DIRECTION_RTL) {
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
|
||||
}
|
||||
pango_layout_set_width (layout,
|
||||
PANGO_SCALE * bounds.width * scale);
|
||||
}
|
||||
@ -432,7 +440,8 @@ eek_renderer_real_render_button (EekRenderer *self,
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
|
||||
EekBounds bounds;
|
||||
|
||||
eek_renderer_get_button_bounds (self, place, &bounds, rotate);
|
||||
EekBounds view_bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
|
||||
eek_renderer_get_button_bounds (view_bounds, place, &bounds, rotate);
|
||||
|
||||
cairo_save (cr);
|
||||
/* Because this function is called separately from the keyboard rendering
|
||||
@ -441,11 +450,12 @@ eek_renderer_real_render_button (EekRenderer *self,
|
||||
cairo_scale (cr, priv->scale, priv->scale);
|
||||
cairo_translate (cr, bounds.x, bounds.y);
|
||||
|
||||
eek_renderer_apply_transformation_for_button (self, cr, place, scale, rotate);
|
||||
eek_renderer_apply_transformation_for_button (cr, view_bounds, place, scale, rotate);
|
||||
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)
|
||||
self, cr, view_bounds, place,
|
||||
squeek_key_is_pressed(key) != 0,
|
||||
squeek_key_is_locked (key) != 0
|
||||
);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
@ -496,10 +506,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 +582,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 view_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 +618,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;
|
||||
@ -626,19 +648,6 @@ eek_renderer_init (EekRenderer *self)
|
||||
priv->css_provider = gtk_css_provider_new ();
|
||||
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,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
|
||||
g_autoptr (GtkWidgetPath) path = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -660,15 +669,44 @@ 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;
|
||||
|
||||
/* Create a style context for the layout */
|
||||
GtkWidgetPath *path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type(path, view_type());
|
||||
|
||||
priv->view_context = gtk_style_context_new();
|
||||
gtk_style_context_set_path(priv->view_context, path);
|
||||
gtk_widget_path_unref(path);
|
||||
if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
gtk_style_context_add_class(priv->view_context, "wide");
|
||||
}
|
||||
gtk_style_context_add_provider (priv->view_context,
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
printf("view: %s\n", gtk_style_context_to_string(priv->view_context, GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE));
|
||||
|
||||
/* Create a style context for the buttons */
|
||||
path = gtk_widget_path_new();
|
||||
gtk_widget_path_append_type(path, view_type());
|
||||
if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) {
|
||||
gtk_widget_path_iter_add_class(path, -1, "wide");
|
||||
}
|
||||
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->view_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);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
@ -720,7 +758,7 @@ eek_renderer_get_size (EekRenderer *renderer,
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_get_button_bounds (EekRenderer *renderer,
|
||||
eek_renderer_get_button_bounds (EekBounds view_bounds,
|
||||
struct button_place *place,
|
||||
EekBounds *bounds,
|
||||
gboolean rotate)
|
||||
@ -728,15 +766,11 @@ eek_renderer_get_button_bounds (EekRenderer *renderer,
|
||||
gint angle = 0;
|
||||
EekPoint points[4], min, max;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (place);
|
||||
g_return_if_fail (bounds != NULL);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
|
||||
EekBounds button_bounds = squeek_button_get_bounds(place->button);
|
||||
EekBounds row_bounds = squeek_row_get_bounds (place->row);
|
||||
EekBounds view_bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
|
||||
|
||||
if (!rotate) {
|
||||
button_bounds.x += view_bounds.x + row_bounds.x;
|
||||
@ -759,7 +793,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;
|
||||
@ -806,28 +840,19 @@ eek_renderer_create_pango_layout (EekRenderer *renderer)
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
eek_renderer_get_icon_surface (EekRenderer *renderer,
|
||||
const gchar *icon_name,
|
||||
eek_renderer_get_icon_surface (const gchar *icon_name,
|
||||
gint size,
|
||||
gint scale)
|
||||
{
|
||||
GError *error = NULL;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
|
||||
surface = g_hash_table_lookup (priv->icons, icon_name);
|
||||
if (!surface) {
|
||||
surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
|
||||
cairo_surface_t *surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
|
||||
icon_name,
|
||||
size,
|
||||
scale,
|
||||
NULL,
|
||||
0,
|
||||
&error);
|
||||
g_hash_table_insert (priv->icons, g_strdup(icon_name), surface);
|
||||
|
||||
if (surface == NULL) {
|
||||
g_warning ("can't get icon surface for %s: %s",
|
||||
icon_name,
|
||||
@ -835,7 +860,6 @@ eek_renderer_get_icon_surface (EekRenderer *renderer,
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@ -863,35 +887,9 @@ eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
}
|
||||
|
||||
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,
|
||||
eek_renderer_get_foreground_color (GtkStyleContext *context,
|
||||
EekColor *color)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (color);
|
||||
|
||||
GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;
|
||||
@ -927,7 +925,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;
|
||||
@ -951,29 +949,16 @@ eek_are_bounds_inside (EekBounds bounds, EekPoint point, EekPoint origin, int32_
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_renderer_find_key_by_position:
|
||||
* @renderer: The renderer normally used to render the key
|
||||
* @x: The horizontal widget coordinate of the position to test for a key
|
||||
* @y: The vertical widget coordinate of the position to test for a key
|
||||
*
|
||||
* Return value: the key located at the position x, y in widget coordinates, or
|
||||
* NULL if no key can be found at that location
|
||||
**/
|
||||
struct squeek_button *
|
||||
eek_renderer_find_button_by_position (EekRenderer *renderer,
|
||||
struct squeek_view *view,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
|
||||
struct transformation
|
||||
eek_renderer_get_transformation (EekRenderer *renderer) {
|
||||
struct transformation failed = {0};
|
||||
g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed);
|
||||
|
||||
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||
|
||||
/* Transform from widget coordinates to keyboard coordinates */
|
||||
EekPoint point = {
|
||||
.x = (x - priv->origin_x)/priv->scale,
|
||||
.y = (y - priv->origin_y)/priv->scale,
|
||||
struct transformation ret = {
|
||||
.origin_x = priv->origin_x,
|
||||
.origin_y = priv->origin_y,
|
||||
.scale = priv->scale,
|
||||
};
|
||||
return squeek_view_find_button_by_position(view, point);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-types.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -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,
|
||||
@ -66,7 +65,7 @@ void eek_renderer_set_allocation_size
|
||||
void eek_renderer_get_size (EekRenderer *renderer,
|
||||
gdouble *width,
|
||||
gdouble *height);
|
||||
void eek_renderer_get_button_bounds (EekRenderer *renderer,
|
||||
void eek_renderer_get_button_bounds (EekBounds view_bounds,
|
||||
struct button_place *button,
|
||||
EekBounds *bounds,
|
||||
gboolean rotate);
|
||||
@ -83,8 +82,7 @@ void eek_renderer_render_button (EekRenderer *renderer,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
|
||||
const gchar *icon_name,
|
||||
cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name,
|
||||
gint size,
|
||||
gint scale);
|
||||
|
||||
@ -98,19 +96,19 @@ void eek_renderer_set_default_background_color
|
||||
(EekRenderer *renderer,
|
||||
const EekColor *color);
|
||||
void eek_renderer_get_foreground_color
|
||||
(EekRenderer *renderer,
|
||||
GtkStyleContext *context,
|
||||
(GtkStyleContext *context,
|
||||
EekColor *color);
|
||||
void eek_renderer_set_border_width (EekRenderer *renderer,
|
||||
gdouble border_width);
|
||||
struct squeek_button *eek_renderer_find_button_by_position(EekRenderer *renderer, struct squeek_view *view,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void eek_renderer_apply_transformation_for_button
|
||||
(EekRenderer *renderer,
|
||||
cairo_t *cr, struct button_place *place,
|
||||
(cairo_t *cr,
|
||||
EekBounds view_bounds,
|
||||
struct button_place *place,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
struct transformation
|
||||
eek_renderer_get_transformation (EekRenderer *renderer);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_RENDERER_H */
|
||||
|
||||
113
eek/eek-symbol.c
113
eek/eek-symbol.c
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:eek-symbol
|
||||
* @short_description: Base class of a symbol
|
||||
*
|
||||
* The #EekSymbolClass class represents a symbol assigned to a key.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "eek-symbol.h"
|
||||
#include "eek-enumtypes.h"
|
||||
|
||||
EekSymbol *
|
||||
eek_symbol_new (const gchar *name)
|
||||
{
|
||||
EekSymbol *self = g_new0(EekSymbol, 1);
|
||||
self->name = g_strdup (name);
|
||||
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_set_label:
|
||||
* @symbol: an #EekSymbol
|
||||
* @label: label text of @symbol
|
||||
*
|
||||
* Set the label text of @symbol to @label.
|
||||
*/
|
||||
void
|
||||
eek_symbol_set_label (EekSymbol *symbol,
|
||||
const gchar *label)
|
||||
{
|
||||
g_free (symbol->label);
|
||||
symbol->label = g_strdup (label);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_set_modifier_mask:
|
||||
* @symbol: an #EekSymbol
|
||||
* @mask: an #EekModifierType
|
||||
*
|
||||
* Set modifier mask that @symbol can trigger.
|
||||
*/
|
||||
void
|
||||
eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
||||
EekModifierType mask)
|
||||
{
|
||||
symbol->modifier_mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_get_modifier_mask:
|
||||
* @symbol: an #EekSymbol
|
||||
*
|
||||
* Get modifier mask that @symbol can trigger.
|
||||
*/
|
||||
EekModifierType
|
||||
eek_symbol_get_modifier_mask (EekSymbol *symbol)
|
||||
{
|
||||
return 0;
|
||||
return symbol->modifier_mask;
|
||||
}
|
||||
|
||||
void
|
||||
eek_symbol_set_icon_name (EekSymbol *symbol,
|
||||
const gchar *icon_name)
|
||||
{
|
||||
g_free (symbol->icon_name);
|
||||
symbol->icon_name = g_strdup (icon_name);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
eek_symbol_get_icon_name (EekSymbol *symbol)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
eek_symbol_set_tooltip (EekSymbol *symbol,
|
||||
const gchar *tooltip)
|
||||
{
|
||||
g_free (symbol->tooltip);
|
||||
symbol->tooltip = g_strdup (tooltip);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
eek_symbol_get_tooltip (EekSymbol *symbol)
|
||||
{
|
||||
return NULL;
|
||||
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
|
||||
return NULL;
|
||||
return symbol->tooltip;
|
||||
}
|
||||
@ -73,28 +73,6 @@ eek_bounds_free (EekBounds *bounds)
|
||||
g_slice_free (EekBounds, bounds);
|
||||
}
|
||||
|
||||
/* EekOutline */
|
||||
G_DEFINE_BOXED_TYPE(EekOutline, eek_outline,
|
||||
eek_outline_copy, eek_outline_free);
|
||||
|
||||
EekOutline *
|
||||
eek_outline_copy (const EekOutline *outline)
|
||||
{
|
||||
EekOutline *_outline = g_slice_dup (EekOutline, outline);
|
||||
_outline->corner_radius = outline->corner_radius;
|
||||
_outline->num_points = outline->num_points;
|
||||
_outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
|
||||
memcpy (_outline->points, outline->points, sizeof (EekPoint) * outline->num_points);
|
||||
return _outline;
|
||||
}
|
||||
|
||||
void
|
||||
eek_outline_free (EekOutline *outline)
|
||||
{
|
||||
g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points);
|
||||
g_slice_free (EekOutline, outline);
|
||||
}
|
||||
|
||||
/* EekColor */
|
||||
G_DEFINE_BOXED_TYPE(EekColor, eek_color, eek_color_copy, eek_color_free);
|
||||
|
||||
@ -126,9 +104,3 @@ eek_color_new (gdouble red,
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
GQuark
|
||||
eek_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("eek-error-quark");
|
||||
}
|
||||
|
||||
148
eek/eek-types.h
148
eek/eek-types.h
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
* Copyright (C) 2019 Purism, SPC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
@ -33,116 +34,9 @@ G_BEGIN_DECLS
|
||||
|
||||
#define EEK_TYPE_POINT (eek_point_get_type ())
|
||||
#define EEK_TYPE_BOUNDS (eek_bounds_get_type ())
|
||||
#define EEK_TYPE_OUTLINE (eek_outline_get_type ())
|
||||
#define EEK_TYPE_COLOR (eek_color_get_type ())
|
||||
|
||||
|
||||
/**
|
||||
* EekOrientation:
|
||||
* @EEK_ORIENTATION_VERTICAL: the elements will be arranged vertically
|
||||
* @EEK_ORIENTATION_HORIZONTAL: the elements will be arranged horizontally
|
||||
* @EEK_ORIENTATION_INVALID: used for error reporting
|
||||
*
|
||||
* Orientation of rows in sections. Elements in a row will be
|
||||
* arranged with the specified orientation.
|
||||
*/
|
||||
typedef enum {
|
||||
EEK_ORIENTATION_VERTICAL,
|
||||
EEK_ORIENTATION_HORIZONTAL,
|
||||
EEK_ORIENTATION_INVALID = -1
|
||||
} EekOrientation;
|
||||
|
||||
/**
|
||||
* EekModifierBehavior:
|
||||
* @EEK_MODIFIER_BEHAVIOR_NONE: do nothing when a modifier key is pressed
|
||||
* @EEK_MODIFIER_BEHAVIOR_LOCK: toggle the modifier status each time a
|
||||
* modifier key are pressed
|
||||
* @EEK_MODIFIER_BEHAVIOR_LATCH: enable the modifier when a modifier
|
||||
* key is pressed and keep it enabled until any key is pressed.
|
||||
*
|
||||
* Modifier handling mode.
|
||||
*/
|
||||
typedef enum {
|
||||
EEK_MODIFIER_BEHAVIOR_NONE,
|
||||
EEK_MODIFIER_BEHAVIOR_LOCK,
|
||||
EEK_MODIFIER_BEHAVIOR_LATCH
|
||||
} EekModifierBehavior;
|
||||
|
||||
/**
|
||||
* EekModifierType:
|
||||
* @EEK_SHIFT_MASK: the Shift key.
|
||||
* @EEK_LOCK_MASK: a Lock key (depending on the modifier mapping of the
|
||||
* X server this may either be CapsLock or ShiftLock).
|
||||
* @EEK_CONTROL_MASK: the Control key.
|
||||
* @EEK_MOD1_MASK: the fourth modifier key (it depends on the modifier
|
||||
* mapping of the X server which key is interpreted as this modifier, but
|
||||
* normally it is the Alt key).
|
||||
* @EEK_MOD2_MASK: the fifth modifier key (it depends on the modifier
|
||||
* mapping of the X server which key is interpreted as this modifier).
|
||||
* @EEK_MOD3_MASK: the sixth modifier key (it depends on the modifier
|
||||
* mapping of the X server which key is interpreted as this modifier).
|
||||
* @EEK_MOD4_MASK: the seventh modifier key (it depends on the modifier
|
||||
* mapping of the X server which key is interpreted as this modifier).
|
||||
* @EEK_MOD5_MASK: the eighth modifier key (it depends on the modifier
|
||||
* mapping of the X server which key is interpreted as this modifier).
|
||||
* @EEK_BUTTON1_MASK: the first mouse button.
|
||||
* @EEK_BUTTON2_MASK: the second mouse button.
|
||||
* @EEK_BUTTON3_MASK: the third mouse button.
|
||||
* @EEK_BUTTON4_MASK: the fourth mouse button.
|
||||
* @EEK_BUTTON5_MASK: the fifth mouse button.
|
||||
* @EEK_SUPER_MASK: the Super modifier. Since 2.10
|
||||
* @EEK_HYPER_MASK: the Hyper modifier. Since 2.10
|
||||
* @EEK_META_MASK: the Meta modifier. Since 2.10
|
||||
* @EEK_RELEASE_MASK: not used in EEK itself. GTK+ uses it to differentiate
|
||||
* between (keyval, modifiers) pairs from key press and release events.
|
||||
* @EEK_MODIFIER_MASK: a mask covering all modifier types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
EEK_SHIFT_MASK = 1 << 0,
|
||||
EEK_LOCK_MASK = 1 << 1,
|
||||
EEK_CONTROL_MASK = 1 << 2,
|
||||
EEK_MOD1_MASK = 1 << 3,
|
||||
EEK_MOD2_MASK = 1 << 4,
|
||||
EEK_MOD3_MASK = 1 << 5,
|
||||
EEK_MOD4_MASK = 1 << 6,
|
||||
EEK_MOD5_MASK = 1 << 7,
|
||||
EEK_BUTTON1_MASK = 1 << 8,
|
||||
EEK_BUTTON2_MASK = 1 << 9,
|
||||
EEK_BUTTON3_MASK = 1 << 10,
|
||||
EEK_BUTTON4_MASK = 1 << 11,
|
||||
EEK_BUTTON5_MASK = 1 << 12,
|
||||
|
||||
/* The next few modifiers are used by XKB, so we skip to the end.
|
||||
* Bits 15 - 25 are currently unused. Bit 29 is used internally.
|
||||
*/
|
||||
|
||||
EEK_SUPER_MASK = 1 << 26,
|
||||
EEK_HYPER_MASK = 1 << 27,
|
||||
EEK_META_MASK = 1 << 28,
|
||||
|
||||
EEK_RELEASE_MASK = 1 << 30,
|
||||
|
||||
EEK_MODIFIER_MASK = 0x5c001fff
|
||||
} EekModifierType;
|
||||
|
||||
/**
|
||||
* EEK_INVALID_KEYCODE:
|
||||
*
|
||||
* Pseudo keycode used for error reporting.
|
||||
*/
|
||||
#define EEK_INVALID_KEYCODE (0)
|
||||
|
||||
typedef struct _EekElement EekElement;
|
||||
typedef struct _EekSymbol EekSymbol;
|
||||
typedef struct _EekText EekText;
|
||||
typedef struct _EekTheme EekTheme;
|
||||
typedef struct _EekThemeContext EekThemeContext;
|
||||
typedef struct _EekThemeNode EekThemeNode;
|
||||
|
||||
typedef struct _EekSymbolMatrix EekSymbolMatrix;
|
||||
typedef struct _EekBounds EekBounds;
|
||||
typedef struct _EekOutline EekOutline;
|
||||
typedef struct _EekColor EekColor;
|
||||
|
||||
typedef struct _EekboardContextService EekboardContextService;
|
||||
@ -191,26 +85,6 @@ GType eek_bounds_get_type (void) G_GNUC_CONST;
|
||||
EekBounds *eek_bounds_copy (const EekBounds *bounds);
|
||||
void eek_bounds_free (EekBounds *bounds);
|
||||
|
||||
/**
|
||||
* EekOutline:
|
||||
* @corner_radius: radius of corners of rounded polygon
|
||||
* @points: an array of points represents a polygon
|
||||
* @num_points: the length of @points
|
||||
*
|
||||
* 2D rounded polygon used to draw key shape
|
||||
*/
|
||||
struct _EekOutline
|
||||
{
|
||||
/*< public >*/
|
||||
gdouble corner_radius;
|
||||
EekPoint *points;
|
||||
guint num_points;
|
||||
};
|
||||
|
||||
GType eek_outline_get_type (void) G_GNUC_CONST;
|
||||
EekOutline *eek_outline_copy (const EekOutline *outline);
|
||||
void eek_outline_free (EekOutline *outline);
|
||||
|
||||
/**
|
||||
* EekColor:
|
||||
* @red: red component of color, between 0.0 and 1.0
|
||||
@ -238,20 +112,10 @@ EekColor *eek_color_new (gdouble red,
|
||||
EekColor *eek_color_copy (const EekColor *color);
|
||||
void eek_color_free (EekColor *color);
|
||||
|
||||
typedef enum {
|
||||
EEK_GRADIENT_NONE,
|
||||
EEK_GRADIENT_VERTICAL,
|
||||
EEK_GRADIENT_HORIZONTAL,
|
||||
EEK_GRADIENT_RADIAL
|
||||
} EekGradientType;
|
||||
|
||||
GQuark eek_error_quark (void);
|
||||
|
||||
#define EEK_ERROR eek_error_quark ()
|
||||
typedef enum {
|
||||
EEK_ERROR_LAYOUT_ERROR,
|
||||
EEK_ERROR_FAILED
|
||||
} EekErrorEnum;
|
||||
|
||||
struct transformation {
|
||||
gdouble origin_x;
|
||||
gdouble origin_y;
|
||||
gdouble scale;
|
||||
};
|
||||
G_END_DECLS
|
||||
#endif /* EEK_TYPES_H */
|
||||
|
||||
@ -31,9 +31,10 @@
|
||||
|
||||
LevelKeyboard *
|
||||
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
|
||||
EekboardContextService *manager)
|
||||
EekboardContextService *manager,
|
||||
enum squeek_arrangement_kind t)
|
||||
{
|
||||
struct squeek_layout *layout = squeek_load_layout(keyboard_type);
|
||||
struct squeek_layout *layout = squeek_load_layout(keyboard_type, t);
|
||||
squeek_layout_place_contents(layout);
|
||||
return level_keyboard_new(manager, layout);
|
||||
}
|
||||
|
||||
@ -24,10 +24,13 @@
|
||||
#define EEK_XML_LAYOUT_H 1
|
||||
|
||||
#include "eek-types.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
LevelKeyboard *
|
||||
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
|
||||
EekboardContextService *manager);
|
||||
EekboardContextService *manager,
|
||||
enum squeek_arrangement_kind t);
|
||||
G_END_DECLS
|
||||
#endif /* EEK_XML_LAYOUT_H */
|
||||
|
||||
@ -3,15 +3,12 @@
|
||||
* SPDX-License-Identifier: GPL-3.0+
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
WARNING: this file is taken directly from phosh, with no modificaions apart from this message. Please update phosh instead of changing this file. Please copy the file back here afterwards, with the same notice.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define G_LOG_DOMAIN "phosh-layer-surface"
|
||||
|
||||
#include "config.h"
|
||||
@ -27,8 +24,14 @@ enum {
|
||||
PHOSH_LAYER_SURFACE_PROP_LAYER,
|
||||
PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY,
|
||||
PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE,
|
||||
PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP,
|
||||
PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM,
|
||||
PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT,
|
||||
PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT,
|
||||
PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH,
|
||||
PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT,
|
||||
PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH,
|
||||
PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT,
|
||||
PHOSH_LAYER_SURFACE_PROP_NAMESPACE,
|
||||
PHOSH_LAYER_SURFACE_PROP_LAST_PROP
|
||||
};
|
||||
@ -50,7 +53,10 @@ typedef struct {
|
||||
guint layer;
|
||||
gboolean kbd_interactivity;
|
||||
gint exclusive_zone;
|
||||
gint margin_top, margin_bottom;
|
||||
gint margin_left, margin_right;
|
||||
gint width, height;
|
||||
gint configured_width, configured_height;
|
||||
gchar *namespace;
|
||||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct wl_output *wl_output;
|
||||
@ -65,10 +71,24 @@ static void layer_surface_configure(void *data,
|
||||
uint32_t height)
|
||||
{
|
||||
PhoshLayerSurface *self = data;
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
gtk_window_resize (GTK_WINDOW (self), width, height);
|
||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||
|
||||
if (priv->configured_height != height) {
|
||||
priv->configured_height = height;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT]);
|
||||
}
|
||||
|
||||
if (priv->configured_width != width) {
|
||||
priv->configured_width = width;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH]);
|
||||
}
|
||||
|
||||
g_debug("Configured %p", self);
|
||||
g_signal_emit (self, signals[CONFIGURED], 0);
|
||||
}
|
||||
|
||||
@ -98,6 +118,7 @@ phosh_layer_surface_set_property (GObject *object,
|
||||
{
|
||||
PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
|
||||
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
|
||||
gint width, height;
|
||||
|
||||
switch (property_id) {
|
||||
case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL:
|
||||
@ -113,16 +134,46 @@ phosh_layer_surface_set_property (GObject *object,
|
||||
priv->layer = g_value_get_uint (value);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY:
|
||||
priv->kbd_interactivity = g_value_get_boolean (value);
|
||||
phosh_layer_surface_set_kbd_interactivity (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
|
||||
priv->exclusive_zone = g_value_get_int (value);
|
||||
phosh_layer_surface_set_exclusive_zone (self, g_value_get_int (value));
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
|
||||
phosh_layer_surface_set_margins (self,
|
||||
g_value_get_int (value),
|
||||
priv->margin_right,
|
||||
priv->margin_bottom,
|
||||
priv->margin_left);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
|
||||
phosh_layer_surface_set_margins (self,
|
||||
priv->margin_top,
|
||||
priv->margin_right,
|
||||
g_value_get_int (value),
|
||||
priv->margin_left);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
|
||||
phosh_layer_surface_set_margins (self,
|
||||
priv->margin_top,
|
||||
priv->margin_right,
|
||||
priv->margin_bottom,
|
||||
g_value_get_int (value));
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
|
||||
phosh_layer_surface_set_margins (self,
|
||||
priv->margin_top,
|
||||
g_value_get_int (value),
|
||||
priv->margin_bottom,
|
||||
priv->margin_left);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
|
||||
priv->width = g_value_get_uint (value);
|
||||
width = g_value_get_uint (value);
|
||||
phosh_layer_surface_set_size(self, width, priv->height);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
|
||||
priv->height = g_value_get_uint (value);
|
||||
height = g_value_get_uint (value);
|
||||
phosh_layer_surface_set_size(self, priv->width, height);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
|
||||
g_free (priv->namespace);
|
||||
@ -161,7 +212,19 @@ phosh_layer_surface_get_property (GObject *object,
|
||||
g_value_set_boolean (value, priv->kbd_interactivity);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
|
||||
g_value_set_boolean (value, priv->exclusive_zone);
|
||||
g_value_set_int (value, priv->exclusive_zone);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
|
||||
g_value_set_int (value, priv->margin_top);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
|
||||
g_value_set_int (value, priv->margin_bottom);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
|
||||
g_value_set_int (value, priv->margin_left);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
|
||||
g_value_set_int (value, priv->margin_right);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
|
||||
g_value_set_uint (value, priv->width);
|
||||
@ -169,6 +232,12 @@ phosh_layer_surface_get_property (GObject *object,
|
||||
case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
|
||||
g_value_set_uint (value, priv->height);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH:
|
||||
g_value_set_uint (value, priv->configured_width);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT:
|
||||
g_value_set_uint (value, priv->configured_height);
|
||||
break;
|
||||
case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
|
||||
g_value_set_string (value, priv->namespace);
|
||||
break;
|
||||
@ -221,6 +290,11 @@ on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, priv->exclusive_zone);
|
||||
zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
|
||||
zwlr_layer_surface_v1_set_anchor(priv->layer_surface, priv->anchor);
|
||||
zwlr_layer_surface_v1_set_margin(priv->layer_surface,
|
||||
priv->margin_top,
|
||||
priv->margin_right,
|
||||
priv->margin_bottom,
|
||||
priv->margin_left);
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(priv->layer_surface, priv->kbd_interactivity);
|
||||
zwlr_layer_surface_v1_add_listener(priv->layer_surface,
|
||||
&layer_surface_listener,
|
||||
@ -262,6 +336,8 @@ phosh_layer_surface_constructed (GObject *object)
|
||||
g_signal_connect (self, "unmap",
|
||||
G_CALLBACK (on_phosh_layer_surface_unmapped),
|
||||
NULL);
|
||||
|
||||
G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
|
||||
@ -332,7 +408,7 @@ phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
|
||||
"Keyboard interactivity",
|
||||
"Whether the surface interacts with the keyboard",
|
||||
FALSE,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE] =
|
||||
g_param_spec_int (
|
||||
@ -342,7 +418,47 @@ phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
|
||||
-1,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT] =
|
||||
g_param_spec_int (
|
||||
"margin-left",
|
||||
"Left margin",
|
||||
"Distance away from the left anchor point",
|
||||
G_MININT,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT] =
|
||||
g_param_spec_int (
|
||||
"margin-right",
|
||||
"Right margin",
|
||||
"Distance away from the right anchor point",
|
||||
G_MININT,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP] =
|
||||
g_param_spec_int (
|
||||
"margin-top",
|
||||
"Top margin",
|
||||
"Distance away from the top anchor point",
|
||||
G_MININT,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM] =
|
||||
g_param_spec_int (
|
||||
"margin-bottom",
|
||||
"Bottom margin",
|
||||
"Distance away from the bottom anchor point",
|
||||
G_MININT,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH] =
|
||||
g_param_spec_uint (
|
||||
@ -352,7 +468,7 @@ phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
|
||||
0,
|
||||
G_MAXUINT,
|
||||
0,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT] =
|
||||
g_param_spec_uint (
|
||||
@ -362,7 +478,28 @@ phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
|
||||
0,
|
||||
G_MAXUINT,
|
||||
0,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH] =
|
||||
g_param_spec_uint (
|
||||
"configured-width",
|
||||
"Configured width",
|
||||
"The width of the layer surface set by the compositor",
|
||||
0,
|
||||
G_MAXUINT,
|
||||
0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT] =
|
||||
g_param_spec_uint (
|
||||
"configured-height",
|
||||
"Configured height",
|
||||
"The height of the layer surface set by the compositor",
|
||||
0,
|
||||
G_MAXUINT,
|
||||
0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
props[PHOSH_LAYER_SURFACE_PROP_NAMESPACE] =
|
||||
g_param_spec_string (
|
||||
@ -438,3 +575,148 @@ phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
return priv->wl_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* phosh_layer_surface_set_size:
|
||||
*
|
||||
* Set the size of a layer surface. A value of '-1' indicates 'use old value'
|
||||
*/
|
||||
void
|
||||
phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height)
|
||||
{
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
gint old_width, old_height;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->height == height && priv->width == width)
|
||||
return;
|
||||
|
||||
old_width = priv->width;
|
||||
old_height = priv->height;
|
||||
|
||||
if (width != -1)
|
||||
priv->width = width;
|
||||
|
||||
if (height != -1)
|
||||
priv->height = height;
|
||||
|
||||
if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
|
||||
zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
|
||||
}
|
||||
|
||||
if (priv->height != old_height)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT]);
|
||||
|
||||
if (priv->width != old_width)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]);
|
||||
}
|
||||
|
||||
/**
|
||||
* phosh_layer_surface_set_margins:
|
||||
*
|
||||
* Set anchor margins of a layer surface.
|
||||
*/
|
||||
void
|
||||
phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, gint bottom, gint left)
|
||||
{
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
gint old_top, old_bottom, old_left, old_right;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
old_top = priv->margin_top;
|
||||
old_left = priv->margin_left;
|
||||
old_right = priv->margin_right;
|
||||
old_bottom = priv->margin_bottom;
|
||||
|
||||
if (old_top == top && old_left == left && old_right == right && old_bottom == bottom)
|
||||
return;
|
||||
|
||||
priv->margin_top = top;
|
||||
priv->margin_left = left;
|
||||
priv->margin_right = right;
|
||||
priv->margin_bottom = bottom;
|
||||
|
||||
if (priv->layer_surface)
|
||||
zwlr_layer_surface_v1_set_margin(priv->layer_surface, top, right, bottom, left);
|
||||
|
||||
if (old_top != top)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP]);
|
||||
if (old_bottom != bottom)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM]);
|
||||
if (old_left != left)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT]);
|
||||
if (old_right != right)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* phosh_layer_surface_set_exclusive_zone:
|
||||
*
|
||||
* Set exclusive zone of a layer surface.
|
||||
*/
|
||||
void
|
||||
phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone)
|
||||
{
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
gint old_zone;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
old_zone = priv->exclusive_zone;
|
||||
|
||||
if (old_zone == zone)
|
||||
return;
|
||||
|
||||
priv->exclusive_zone = zone;
|
||||
|
||||
if (priv->layer_surface)
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, zone);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* phosh_layer_surface_set_keyboard_interactivity:
|
||||
*
|
||||
* Set keyboard ineractivity a layer surface.
|
||||
*/
|
||||
void
|
||||
phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean interactivity)
|
||||
{
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->kbd_interactivity == interactivity)
|
||||
return;
|
||||
|
||||
priv->kbd_interactivity = interactivity;
|
||||
|
||||
if (priv->layer_surface)
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* phosh_layer_surface_wl_surface_commit:
|
||||
*
|
||||
* Forces a commit of layer surface's state.
|
||||
*/
|
||||
void
|
||||
phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self)
|
||||
{
|
||||
PhoshLayerSurfacePrivate *priv;
|
||||
|
||||
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
|
||||
priv = phosh_layer_surface_get_instance_private (self);
|
||||
|
||||
if (priv->wl_surface)
|
||||
wl_surface_commit (priv->wl_surface);
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ WARNING: this file is taken directly from phosh, with no modificaions apart from
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@ -39,3 +38,16 @@ GtkWidget *phosh_layer_surface_new (gpointer layer_shell,
|
||||
gpointer wl_output);
|
||||
struct zwlr_layer_surface_v1 *phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self);
|
||||
struct wl_surface *phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self);
|
||||
void phosh_layer_surface_set_size(PhoshLayerSurface *self,
|
||||
gint width,
|
||||
gint height);
|
||||
void phosh_layer_surface_set_margins(PhoshLayerSurface *self,
|
||||
gint top,
|
||||
gint right,
|
||||
gint bottom,
|
||||
gint left);
|
||||
void phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self,
|
||||
gint zone);
|
||||
void phosh_layer_surface_set_kbd_interactivity(PhoshLayerSurface *self,
|
||||
gboolean interactivity);
|
||||
void phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self);
|
||||
|
||||
@ -41,17 +41,14 @@
|
||||
#include "wayland.h"
|
||||
|
||||
#include "eek/eek-xml-layout.h"
|
||||
#include "src/server-context-service.h"
|
||||
|
||||
#include "eekboard/eekboard-context-service.h"
|
||||
|
||||
#define CSW 640
|
||||
#define CSH 480
|
||||
|
||||
enum {
|
||||
PROP_0, // Magic: without this, keyboard is not useable in g_object_notify
|
||||
PROP_KEYBOARD,
|
||||
PROP_VISIBLE,
|
||||
PROP_FULLSCREEN,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -70,15 +67,10 @@ 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
|
||||
|
||||
// TODO: make use of repeating buttons
|
||||
guint repeat_timeout_id;
|
||||
gboolean repeat_triggered;
|
||||
|
||||
GSettings *settings;
|
||||
uint32_t hint;
|
||||
uint32_t purpose;
|
||||
@ -88,9 +80,10 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_
|
||||
|
||||
static LevelKeyboard *
|
||||
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
|
||||
const gchar *keyboard_type)
|
||||
const gchar *keyboard_type,
|
||||
enum squeek_arrangement_kind t)
|
||||
{
|
||||
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self);
|
||||
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self, t);
|
||||
if (!keyboard) {
|
||||
g_error("Failed to create a keyboard");
|
||||
}
|
||||
@ -170,9 +163,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 +184,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;
|
||||
@ -239,8 +226,8 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
|
||||
g_variant_unref(inputs);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_update_layout(EekboardContextService *context)
|
||||
void
|
||||
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t)
|
||||
{
|
||||
g_autofree gchar *keyboard_type = NULL;
|
||||
g_autofree gchar *keyboard_layout = NULL;
|
||||
@ -270,7 +257,7 @@ settings_update_layout(EekboardContextService *context)
|
||||
GUINT_TO_POINTER(keyboard_id));
|
||||
// create a keyboard
|
||||
if (!keyboard) {
|
||||
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
|
||||
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout, t);
|
||||
|
||||
g_hash_table_insert (context->priv->keyboard_hash,
|
||||
GUINT_TO_POINTER(keyboard_id),
|
||||
@ -280,11 +267,14 @@ settings_update_layout(EekboardContextService *context)
|
||||
}
|
||||
// set as current
|
||||
context->priv->keyboard = keyboard;
|
||||
// TODO: this used to save the group, why?
|
||||
//group = eek_element_get_group (EEK_ELEMENT(context->priv->keyboard));
|
||||
|
||||
g_object_notify (G_OBJECT(context), "keyboard");
|
||||
}
|
||||
|
||||
static void update_layout_and_type(EekboardContextService *context) {
|
||||
eekboard_context_service_update_layout(context, server_context_service_get_layout_type(context));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
settings_handle_layout_changed(GSettings *s,
|
||||
gpointer keys, gint n_keys,
|
||||
@ -293,7 +283,7 @@ settings_handle_layout_changed(GSettings *s,
|
||||
(void)keys;
|
||||
(void)n_keys;
|
||||
EekboardContextService *context = user_data;
|
||||
settings_update_layout(context);
|
||||
update_layout_and_type(context);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -307,7 +297,7 @@ eekboard_context_service_constructed (GObject *object)
|
||||
if (!context->virtual_keyboard) {
|
||||
g_error("Programmer error: Failed to receive a virtual keyboard instance");
|
||||
}
|
||||
settings_update_layout(context);
|
||||
update_layout_and_type(context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -401,20 +391,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 +500,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)
|
||||
{
|
||||
@ -553,6 +516,6 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
||||
if (priv->hint != hint || priv->purpose != purpose) {
|
||||
priv->hint = hint;
|
||||
priv->purpose = purpose;
|
||||
settings_update_layout(context);
|
||||
update_layout_and_type(context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -107,6 +105,7 @@ void eekboard_context_service_set_keymap(EekboardContextService *context,
|
||||
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
|
||||
uint32_t hint,
|
||||
uint32_t purpose);
|
||||
|
||||
void
|
||||
eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t);
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_CONTEXT_SERVICE_H */
|
||||
|
||||
@ -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 */
|
||||
@ -131,7 +131,6 @@ emit_key_activated (EekboardContextService *manager,
|
||||
*/
|
||||
SeatEmitter emitter = {0};
|
||||
emitter.virtual_keyboard = manager->virtual_keyboard;
|
||||
emitter.keymap = keyboard->keymap;
|
||||
update_modifier_info (&emitter);
|
||||
send_fake_key (&emitter, keyboard, keycode, pressed, timestamp);
|
||||
}
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
||||
# Copyright (C) 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/>.
|
||||
|
||||
import eekboard
|
||||
import glib
|
||||
|
||||
class SimpleClient(object):
|
||||
def __init__(self):
|
||||
client = eekboard.Client()
|
||||
self.__context = client.create_context('simple-client')
|
||||
client.push_context(self.__context)
|
||||
keyboard_id = self.__context.add_keyboard('us')
|
||||
self.__context.set_keyboard(keyboard_id)
|
||||
|
||||
def __key_pressed_cb(self, c, keyname, symbol, modifiers):
|
||||
print (keyname, symbol, modifiers)
|
||||
|
||||
def __notify_visible_cb(self, c, p, mainloop):
|
||||
if not c.props.visible:
|
||||
mainloop.quit()
|
||||
|
||||
def run(self):
|
||||
mainloop = glib.MainLoop()
|
||||
self.__context.connect('key-pressed', self.__key_pressed_cb)
|
||||
self.__context.connect('notify::visible', self.__notify_visible_cb,
|
||||
mainloop)
|
||||
self.__context.show_keyboard();
|
||||
mainloop.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
client = SimpleClient()
|
||||
client.run()
|
||||
@ -3,25 +3,48 @@ 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");
|
||||
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
layout.keymap_str
|
||||
|
||||
let keymap_str = layout.keymap_str
|
||||
.clone()
|
||||
.into_string().expect("Failed to decode keymap string"),
|
||||
.into_string().expect("Failed to decode keymap string");
|
||||
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
keymap_str.clone(),
|
||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||
).expect("Failed to create keymap");
|
||||
|
||||
let state = xkb::State::new(&keymap);
|
||||
|
||||
// "Press" each button with keysyms
|
||||
for view in layout.views.values() {
|
||||
for row in &view.rows {
|
||||
for button in &row.buttons {
|
||||
let keystate = button.state.borrow();
|
||||
for keycode in &keystate.keycodes {
|
||||
match state.key_get_one_sym(*keycode) {
|
||||
xkb::KEY_NoSymbol => {
|
||||
eprintln!("{}", keymap_str);
|
||||
panic!("Keysym {} on key {:?} can't be resolved", keycode, button.name);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> () {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
project(
|
||||
'squeekboard',
|
||||
'c', 'rust',
|
||||
version: '1.2.0',
|
||||
version: '1.2.2',
|
||||
license: 'GPLv3',
|
||||
meson_version: '>=0.51.0',
|
||||
default_options: [
|
||||
@ -18,6 +18,7 @@ add_project_arguments(
|
||||
'-Werror=maybe-uninitialized',
|
||||
'-Werror=missing-field-initializers',
|
||||
'-Werror=incompatible-pointer-types',
|
||||
'-Werror=int-conversion',
|
||||
],
|
||||
language: 'c'
|
||||
)
|
||||
|
||||
@ -37,10 +37,3 @@ pub enum Action {
|
||||
keys: Vec<KeySym>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Contains a static description of a particular key's actions
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Symbol {
|
||||
/// The action that this key performs
|
||||
pub action: Action,
|
||||
}
|
||||
448
src/data.rs
448
src/data.rs
@ -14,11 +14,13 @@ use std::vec::Vec;
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use ::keyboard::{
|
||||
KeyState,
|
||||
KeyState, PressType,
|
||||
generate_keymap, generate_keycodes, FormattingError
|
||||
};
|
||||
use ::layout::ArrangementKind;
|
||||
use ::resources;
|
||||
use ::util::c::as_str;
|
||||
use ::util::hash_map_map;
|
||||
use ::xdg;
|
||||
|
||||
// traits, derives
|
||||
@ -35,12 +37,21 @@ pub mod c {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_load_layout(name: *const c_char) -> *mut ::layout::Layout {
|
||||
fn squeek_load_layout(
|
||||
name: *const c_char,
|
||||
type_: u32,
|
||||
) -> *mut ::layout::Layout {
|
||||
let type_ = match type_ {
|
||||
0 => ArrangementKind::Base,
|
||||
1 => ArrangementKind::Wide,
|
||||
_ => panic!("Bad enum value"),
|
||||
};
|
||||
let name = as_str(&name)
|
||||
.expect("Bad layout name")
|
||||
.expect("Empty layout name");
|
||||
|
||||
let layout = load_layout_with_fallback(name);
|
||||
let (kind, layout) = load_layout_data_with_fallback(&name, type_);
|
||||
let layout = ::layout::Layout::new(layout, kind);
|
||||
Box::into_raw(Box::new(layout))
|
||||
}
|
||||
}
|
||||
@ -67,15 +78,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, Clone, PartialEq)]
|
||||
enum DataSource {
|
||||
File(PathBuf),
|
||||
Resource(String),
|
||||
@ -90,80 +93,113 @@ 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) {
|
||||
/// Lists possible sources, with 0 as the most preferred one
|
||||
/// Trying order: native lang of the right kind, native base,
|
||||
/// fallback lang of the right kind, fallback base
|
||||
fn list_layout_sources(
|
||||
name: &str,
|
||||
kind: ArrangementKind,
|
||||
keyboards_path: Option<PathBuf>,
|
||||
) -> Vec<(ArrangementKind, DataSource)> {
|
||||
let mut ret = Vec::new();
|
||||
{
|
||||
fn name_with_arrangement(name: String, kind: &ArrangementKind)
|
||||
-> String
|
||||
{
|
||||
match kind {
|
||||
ArrangementKind::Base => name,
|
||||
ArrangementKind::Wide => name + "_wide",
|
||||
}
|
||||
}
|
||||
|
||||
let mut add_by_name = |name: &str, kind: &ArrangementKind| {
|
||||
if let Some(path) = keyboards_path.clone() {
|
||||
ret.push((
|
||||
kind.clone(),
|
||||
DataSource::File(
|
||||
path.join(name.to_owned()).with_extension("yaml")
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
ret.push((
|
||||
kind.clone(),
|
||||
DataSource::Resource(name.into())
|
||||
));
|
||||
};
|
||||
|
||||
match &kind {
|
||||
ArrangementKind::Base => {},
|
||||
kind => add_by_name(
|
||||
&name_with_arrangement(name.into(), &kind),
|
||||
&kind,
|
||||
),
|
||||
};
|
||||
|
||||
add_by_name(name, &ArrangementKind::Base);
|
||||
|
||||
match &kind {
|
||||
ArrangementKind::Base => {},
|
||||
kind => add_by_name(
|
||||
&name_with_arrangement(FALLBACK_LAYOUT_NAME.into(), &kind),
|
||||
&kind,
|
||||
),
|
||||
};
|
||||
|
||||
add_by_name(FALLBACK_LAYOUT_NAME, &ArrangementKind::Base);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
fn load_layout_data(source: DataSource)
|
||||
-> Result<::layout::LayoutData, LoadError>
|
||||
{
|
||||
match source {
|
||||
DataSource::File(path) => {
|
||||
Layout::from_file(path.clone())
|
||||
.map_err(LoadError::BadData)
|
||||
.and_then(|layout|
|
||||
layout.build().map_err(LoadError::BadKeyMap)
|
||||
)
|
||||
},
|
||||
DataSource::Resource(name) => {
|
||||
Layout::from_resource(&name)
|
||||
.and_then(|layout|
|
||||
layout.build().map_err(LoadError::BadKeyMap)
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn load_layout_data_with_fallback(
|
||||
name: &str,
|
||||
kind: ArrangementKind,
|
||||
) -> (ArrangementKind, ::layout::LayoutData) {
|
||||
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"));
|
||||
.or_else(|| xdg::data_path("squeekboard/keyboards"));
|
||||
|
||||
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)
|
||||
);
|
||||
|
||||
(layout, source)
|
||||
}
|
||||
|
||||
fn load_layout_with_fallback(
|
||||
name: &str
|
||||
) -> ::layout::Layout {
|
||||
let (layout, source) = load_layout(name);
|
||||
let (layout, source) = match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
eprintln!(
|
||||
"Failed to load layout from {}: {}, using fallback",
|
||||
source, e
|
||||
);
|
||||
load_layout(FALLBACK_LAYOUT_NAME)
|
||||
},
|
||||
res => res,
|
||||
};
|
||||
|
||||
let (layout, source) = match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
eprintln!(
|
||||
"Failed to load fallback layout from {}: {}, using hardcoded",
|
||||
source, e
|
||||
);
|
||||
for (kind, source) in list_layout_sources(name, kind, path) {
|
||||
let layout = load_layout_data(source.clone());
|
||||
match layout {
|
||||
Err(e) => match (e, source) {
|
||||
(
|
||||
load_layout_from_resource(FALLBACK_LAYOUT_NAME)
|
||||
.and_then(
|
||||
|layout| layout.build().map_err(LoadError::BadKeyMap)
|
||||
LoadError::BadData(Error::Missing(e)),
|
||||
DataSource::File(file)
|
||||
) => eprintln!( // TODO: print in debug logging level
|
||||
"Tried file {:?}, but it's missing: {}",
|
||||
file, e
|
||||
),
|
||||
DataSource::Resource(FALLBACK_LAYOUT_NAME.into()),
|
||||
)
|
||||
},
|
||||
res => res,
|
||||
};
|
||||
|
||||
match (layout, source) {
|
||||
(Err(e), source) => {
|
||||
panic!(
|
||||
format!("Failed to load hardcoded layout from {}: {:?}",
|
||||
(e, source) => eprintln!(
|
||||
"Failed to load layout from {}: {}, skipping",
|
||||
source, e
|
||||
)
|
||||
);
|
||||
),
|
||||
},
|
||||
(Ok(layout), source) => {
|
||||
eprintln!("Loaded layout from {}", source);
|
||||
layout
|
||||
Ok(layout) => return (kind, layout),
|
||||
}
|
||||
}
|
||||
|
||||
panic!("No useful layout found!");
|
||||
}
|
||||
|
||||
/// The root element describing an entire keyboard
|
||||
@ -218,14 +254,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,22 +273,41 @@ 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> {
|
||||
|
||||
pub fn build(self)
|
||||
-> Result<::layout::LayoutData, FormattingError>
|
||||
{
|
||||
let button_names = self.views.values()
|
||||
.flat_map(|rows| {
|
||||
rows.iter()
|
||||
@ -258,41 +317,73 @@ impl Layout {
|
||||
let button_names: HashSet<&str>
|
||||
= HashSet::from_iter(button_names);
|
||||
|
||||
let keycodes = generate_keycodes(
|
||||
button_names.iter()
|
||||
.map(|name| *name)
|
||||
.filter(|name| {
|
||||
match self.buttons.get(*name) {
|
||||
// buttons with defined action can't emit keysyms
|
||||
// and so don't need keycodes
|
||||
Some(ButtonMeta { action: Some(_), .. }) => false,
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
let button_states = button_names.iter().map(|name| {(
|
||||
String::from(*name),
|
||||
Rc::new(RefCell::new(KeyState {
|
||||
pressed: false,
|
||||
locked: false,
|
||||
keycode: keycodes.get(*name).map(|k| *k),
|
||||
symbol: create_symbol(
|
||||
let button_actions: Vec<(&str, ::action::Action)>
|
||||
= button_names.iter().map(|name| {(
|
||||
*name,
|
||||
create_action(
|
||||
&self.buttons,
|
||||
name,
|
||||
self.views.keys().collect()
|
||||
),
|
||||
}))
|
||||
)});
|
||||
)
|
||||
)}).collect();
|
||||
|
||||
let button_states =
|
||||
HashMap::<String, Rc<RefCell<KeyState>>>::from_iter(
|
||||
let keymap: HashMap<String, u32> = generate_keycodes(
|
||||
button_actions.iter()
|
||||
.filter_map(|(_name, action)| {
|
||||
match action {
|
||||
::action::Action::Submit {
|
||||
text: _, keys,
|
||||
} => Some(keys),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.map(|named_keysym| named_keysym.0.as_str())
|
||||
);
|
||||
|
||||
let button_states = button_actions.into_iter().map(|(name, action)| {
|
||||
let keycodes = match &action {
|
||||
::action::Action::Submit { text: _, keys } => {
|
||||
keys.iter().map(|named_keycode| {
|
||||
*keymap.get(named_keycode.0.as_str())
|
||||
.expect(
|
||||
format!(
|
||||
"keycode {} in key {} missing from keymap",
|
||||
named_keycode.0,
|
||||
name
|
||||
).as_str()
|
||||
)
|
||||
}).collect()
|
||||
},
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(
|
||||
name.into(),
|
||||
KeyState {
|
||||
pressed: PressType::Released,
|
||||
locked: false,
|
||||
keycodes,
|
||||
action,
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
let button_states
|
||||
= HashMap::<String, KeyState>::from_iter(
|
||||
button_states
|
||||
);
|
||||
|
||||
// TODO: generate from symbols
|
||||
let keymap_str = generate_keymap(&button_states)?;
|
||||
|
||||
let button_states_cache = hash_map_map(
|
||||
button_states,
|
||||
|name, state| {(
|
||||
name,
|
||||
Rc::new(RefCell::new(state))
|
||||
)}
|
||||
);
|
||||
|
||||
let views = HashMap::from_iter(
|
||||
self.views.iter().map(|(name, view)| {(
|
||||
name.clone(),
|
||||
@ -312,7 +403,7 @@ impl Layout {
|
||||
&self.buttons,
|
||||
&self.outlines,
|
||||
name,
|
||||
button_states.get(name.into())
|
||||
button_states_cache.get(name.into())
|
||||
.expect("Button state not created")
|
||||
.clone()
|
||||
))
|
||||
@ -323,8 +414,7 @@ impl Layout {
|
||||
)})
|
||||
);
|
||||
|
||||
Ok(::layout::Layout {
|
||||
current_view: "base".into(),
|
||||
Ok(::layout::LayoutData {
|
||||
views: views,
|
||||
keymap_str: {
|
||||
CString::new(keymap_str)
|
||||
@ -334,11 +424,11 @@ impl Layout {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_symbol(
|
||||
fn create_action(
|
||||
button_info: &HashMap<String, ButtonMeta>,
|
||||
name: &str,
|
||||
view_names: Vec<&String>,
|
||||
) -> ::symbol::Symbol {
|
||||
) -> ::action::Action {
|
||||
let default_meta = ButtonMeta::default();
|
||||
let symbol_meta = button_info.get(name)
|
||||
.unwrap_or(&default_meta);
|
||||
@ -364,43 +454,54 @@ fn create_symbol(
|
||||
xkb::keysym_from_name(name, xkb::KEYSYM_NO_FLAGS) != xkb::KEY_NoSymbol
|
||||
}
|
||||
|
||||
let keysym = match &symbol_meta.action {
|
||||
Some(_) => None,
|
||||
None => Some(match &symbol_meta.keysym {
|
||||
Some(keysym) => match keysym_valid(keysym.as_str()) {
|
||||
let keysyms = match &symbol_meta.action {
|
||||
// Non-submit action
|
||||
Some(_) => Vec::new(),
|
||||
// Submit action
|
||||
None => match &symbol_meta.keysym {
|
||||
// Keysym given explicitly
|
||||
Some(keysym) => vec!(match keysym_valid(keysym.as_str()) {
|
||||
true => keysym.clone(),
|
||||
false => {
|
||||
eprintln!("Keysym name invalid: {}", keysym);
|
||||
"space".into() // placeholder
|
||||
},
|
||||
},
|
||||
}),
|
||||
// Keysyms left open to derive
|
||||
// TODO: when button name is meant diretly as xkb keysym name,
|
||||
// mark it so, e.g. with a "#"
|
||||
None => match keysym_valid(name) {
|
||||
true => String::from(name),
|
||||
false => match name.chars().count() {
|
||||
1 => format!("U{:04X}", name.chars().next().unwrap() as u32),
|
||||
// If the name is longer than 1 char,
|
||||
// then it's not a single Unicode char,
|
||||
// but was trying to be an identifier
|
||||
_ => {
|
||||
eprintln!(
|
||||
"Could not derive a valid keysym for key {}",
|
||||
name
|
||||
);
|
||||
"space".into() // placeholder
|
||||
// Button name is actually a valid xkb name
|
||||
true => vec!(String::from(name)),
|
||||
// Button name is not a valid xkb name,
|
||||
// so assume it's a literal string to be submitted
|
||||
false => {
|
||||
if name.chars().count() == 0 {
|
||||
// A name read from yaml with no valid Unicode.
|
||||
// Highly improbable, but let's be safe.
|
||||
eprintln!("Key {} doesn't have any characters", name);
|
||||
vec!("space".into()) // placeholder
|
||||
} else {
|
||||
name.chars().map(|codepoint| {
|
||||
let codepoint_string = codepoint.to_string();
|
||||
match keysym_valid(codepoint_string.as_str()) {
|
||||
true => codepoint_string,
|
||||
false => format!("U{:04X}", codepoint as u32),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
match &symbol_meta.action {
|
||||
Some(Action::SetView(view_name)) => ::symbol::Symbol {
|
||||
action: ::symbol::Action::SetLevel(
|
||||
Some(Action::SetView(view_name)) => ::action::Action::SetLevel(
|
||||
filter_view_name(name, view_name.clone(), &view_names)
|
||||
),
|
||||
},
|
||||
Some(Action::Locking { lock_view, unlock_view }) => ::symbol::Symbol {
|
||||
action: ::symbol::Action::LockLevel {
|
||||
Some(Action::Locking {
|
||||
lock_view, unlock_view
|
||||
}) => ::action::Action::LockLevel {
|
||||
lock: filter_view_name(name, lock_view.clone(), &view_names),
|
||||
unlock: filter_view_name(
|
||||
name,
|
||||
@ -408,20 +509,13 @@ fn create_symbol(
|
||||
&view_names
|
||||
),
|
||||
},
|
||||
},
|
||||
Some(Action::ShowPrefs) => ::symbol::Symbol {
|
||||
action: ::symbol::Action::Submit {
|
||||
Some(Action::ShowPrefs) => ::action::Action::Submit {
|
||||
text: None,
|
||||
keys: Vec::new(),
|
||||
},
|
||||
},
|
||||
None => ::symbol::Symbol {
|
||||
action: ::symbol::Action::Submit {
|
||||
None => ::action::Action::Submit {
|
||||
text: None,
|
||||
keys: vec!(
|
||||
::symbol::KeySym(keysym.unwrap()),
|
||||
),
|
||||
},
|
||||
keys: keysyms.into_iter().map(::action::KeySym).collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -469,13 +563,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 +577,6 @@ fn create_button(
|
||||
width: outline.bounds.width,
|
||||
height: outline.bounds.height,
|
||||
},
|
||||
corner_radius: outline.corner_radius,
|
||||
label: label,
|
||||
state: state,
|
||||
}
|
||||
@ -498,9 +591,7 @@ 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 {
|
||||
bounds: Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 },
|
||||
views: hashmap!(
|
||||
@ -517,7 +608,6 @@ mod tests {
|
||||
},
|
||||
outlines: hashmap!{
|
||||
"default".into() => Outline {
|
||||
corner_radius: 1f64,
|
||||
bounds: Bounds {
|
||||
x: 0f64, y: 0f64, width: 0f64, height: 0f64
|
||||
},
|
||||
@ -530,7 +620,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 +638,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 +657,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 +672,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();
|
||||
@ -595,14 +685,48 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// Test multiple codepoints
|
||||
#[test]
|
||||
fn test_layout_unicode_multi() {
|
||||
let out = Layout::from_file(PathBuf::from("tests/layout_key3.yaml"))
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
out.views["base"]
|
||||
.rows[0]
|
||||
.buttons[0]
|
||||
.state.borrow()
|
||||
.keycodes.len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[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 sources = list_layout_sources("nb", ArrangementKind::Base, None);
|
||||
|
||||
assert_eq!(
|
||||
sources,
|
||||
vec!(
|
||||
(ArrangementKind::Base, DataSource::Resource("nb".into())),
|
||||
(
|
||||
ArrangementKind::Base,
|
||||
DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_keysym() {
|
||||
let keysym = xkb::keysym_from_name(
|
||||
@ -616,7 +740,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_key_unicode() {
|
||||
assert_eq!(
|
||||
create_symbol(
|
||||
create_action(
|
||||
&hashmap!{
|
||||
".".into() => ButtonMeta {
|
||||
icon: None,
|
||||
@ -629,11 +753,9 @@ mod tests {
|
||||
".",
|
||||
Vec::new()
|
||||
),
|
||||
::symbol::Symbol {
|
||||
action: ::symbol::Action::Submit {
|
||||
::action::Action::Submit {
|
||||
text: None,
|
||||
keys: vec!(::symbol::KeySym("U002E".into())),
|
||||
},
|
||||
keys: vec!(::action::KeySym("U002E".into())),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,26 +1,12 @@
|
||||
#ifndef __KEYBOARD_H
|
||||
#define __KEYBOARD_H
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "inttypes.h"
|
||||
#include "stdbool.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
|
||||
struct squeek_key;
|
||||
|
||||
struct squeek_key *squeek_key_new(uint32_t keycode);
|
||||
void squeek_key_free(struct squeek_key *key);
|
||||
void squeek_key_add_symbol(struct squeek_key* key,
|
||||
const char *element_name,
|
||||
const char *text, uint32_t keyval,
|
||||
const char *label, const char *icon,
|
||||
const char *tooltip);
|
||||
uint32_t squeek_key_is_pressed(struct squeek_key *key);
|
||||
void squeek_key_set_pressed(struct squeek_key *key, uint32_t pressed);
|
||||
uint32_t squeek_key_is_locked(struct squeek_key *key);
|
||||
void squeek_key_set_locked(struct squeek_key *key, uint32_t pressed);
|
||||
uint32_t squeek_key_get_keycode(struct squeek_key *key);
|
||||
void squeek_key_set_keycode(struct squeek_key *key, uint32_t keycode);
|
||||
uint32_t squeek_key_equal(struct squeek_key* key, struct squeek_key* key1);
|
||||
|
||||
struct squeek_symbol *squeek_key_get_symbol(struct squeek_key* key);
|
||||
const char* squeek_key_to_keymap_entry(const char *key_name, struct squeek_key *key);
|
||||
#endif
|
||||
|
||||
189
src/keyboard.rs
189
src/keyboard.rs
@ -1,147 +1,54 @@
|
||||
/*! State of the emulated keyboard and keys */
|
||||
/*! State of the emulated keyboard and keys.
|
||||
* Regards the keyboard as if it was composed of switches. */
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use ::symbol::{ Symbol, Action };
|
||||
use ::action::Action;
|
||||
|
||||
use std::io::Write;
|
||||
use std::iter::{ FromIterator, IntoIterator };
|
||||
use ::util::CloneOwned;
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use super::*;
|
||||
use ::util::c;
|
||||
use ::util::c::as_cstr;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
pub type CKeyState = c::Wrapped<KeyState>;
|
||||
|
||||
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_free(key: CKeyState) {
|
||||
unsafe { key.unwrap() }; // reference dropped
|
||||
}
|
||||
|
||||
/// Compares pointers to the data
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_equal(key: CKeyState, key2: CKeyState) -> u32 {
|
||||
return Rc::ptr_eq(&key.clone_ref(), &key2.clone_ref()) as u32
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_is_pressed(key: CKeyState) -> u32 {
|
||||
//let key = unsafe { Rc::from_raw(key.0) };
|
||||
return key.to_owned().pressed as u32;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_set_pressed(key: CKeyState, pressed: u32) {
|
||||
let key = key.clone_ref();
|
||||
let mut key = key.borrow_mut();
|
||||
key.pressed = pressed != 0;
|
||||
return key.clone_owned().pressed as u32;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_is_locked(key: CKeyState) -> u32 {
|
||||
return key.to_owned().locked as u32;
|
||||
return key.clone_owned().locked as u32;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_set_locked(key: CKeyState, locked: u32) {
|
||||
let key = key.clone_ref();
|
||||
let mut key = key.borrow_mut();
|
||||
key.locked = locked != 0;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_get_keycode(key: CKeyState) -> u32 {
|
||||
return key.to_owned().keycode.unwrap_or(0u32);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_to_keymap_entry(
|
||||
key_name: *const c_char,
|
||||
key: CKeyState,
|
||||
) -> *const c_char {
|
||||
let key_name = as_cstr(&key_name)
|
||||
.expect("Missing key name")
|
||||
.to_str()
|
||||
.expect("Bad key name");
|
||||
|
||||
let symbol_name = match key.to_owned().symbol.action {
|
||||
Action::Submit { text: Some(text), .. } => {
|
||||
Some(
|
||||
text.clone()
|
||||
.into_string().expect("Bad symbol")
|
||||
)
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let inner = match symbol_name {
|
||||
Some(name) => format!("[ {} ]", name),
|
||||
_ => format!("[ ]"),
|
||||
};
|
||||
|
||||
CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner))
|
||||
.expect("Couldn't convert string")
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_get_action_name(
|
||||
key_name: *const c_char,
|
||||
key: CKeyState,
|
||||
) -> *const c_char {
|
||||
let key_name = as_cstr(&key_name)
|
||||
.expect("Missing key name")
|
||||
.to_str()
|
||||
.expect("Bad key name");
|
||||
|
||||
let symbol_name = match key.to_owned().symbol.action {
|
||||
Action::Submit { text: Some(text), .. } => {
|
||||
Some(
|
||||
text.clone()
|
||||
.into_string().expect("Bad symbol text")
|
||||
)
|
||||
},
|
||||
_ => None
|
||||
};
|
||||
|
||||
let inner = match symbol_name {
|
||||
Some(name) => format!("[ {} ]", name),
|
||||
_ => format!("[ ]"),
|
||||
};
|
||||
|
||||
CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner))
|
||||
.expect("Couldn't convert string")
|
||||
.into_raw()
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PressType {
|
||||
Released = 0,
|
||||
Pressed = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyState {
|
||||
pub pressed: bool,
|
||||
pub pressed: PressType,
|
||||
pub locked: bool,
|
||||
pub keycode: Option<u32>,
|
||||
pub symbol: Symbol,
|
||||
/// A cache of raw keycodes derived from Action::Sumbit given a keymap
|
||||
pub keycodes: Vec<u32>,
|
||||
/// Static description of what the key does when pressed or released
|
||||
pub action: Action,
|
||||
}
|
||||
|
||||
/// Generates a mapping where each key gets a keycode, starting from 8
|
||||
@ -178,7 +85,7 @@ impl From<io::Error> for FormattingError {
|
||||
|
||||
/// Generates a de-facto single level keymap. TODO: actually drop second level
|
||||
pub fn generate_keymap(
|
||||
keystates: &HashMap::<String, Rc<RefCell<KeyState>>>
|
||||
keystates: &HashMap::<String, KeyState>
|
||||
) -> Result<String, FormattingError> {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
writeln!(
|
||||
@ -191,24 +98,17 @@ pub fn generate_keymap(
|
||||
)?;
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
let state = state.borrow();
|
||||
if let ::symbol::Action::Submit { text: _, keys } = &state.symbol.action {
|
||||
match keys.len() {
|
||||
0 => eprintln!("Key {} has no keysyms", name),
|
||||
a => {
|
||||
// TODO: don't ignore any keysyms
|
||||
if a > 1 {
|
||||
eprintln!("Key {} multiple keysyms", name);
|
||||
}
|
||||
if let Action::Submit { text: _, keys } = &state.action {
|
||||
if let 0 = keys.len() { eprintln!("Key {} has no keysyms", name); };
|
||||
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
<{}> = {};",
|
||||
keys[0].0,
|
||||
state.keycode.unwrap()
|
||||
named_keysym.0,
|
||||
keycode,
|
||||
)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,8 +124,8 @@ pub fn generate_keymap(
|
||||
)?;
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
if let ::symbol::Action::Submit { text: _, keys } = &state.borrow().symbol.action {
|
||||
if let Some(keysym) = keys.iter().next() {
|
||||
if let Action::Submit { text: _, keys } = &state.action {
|
||||
for keysym in keys.iter() {
|
||||
write!(
|
||||
buf,
|
||||
"
|
||||
@ -255,5 +155,44 @@ pub fn generate_keymap(
|
||||
}};"
|
||||
)?;
|
||||
|
||||
//println!("{}", String::from_utf8(buf.clone()).unwrap());
|
||||
String::from_utf8(buf).map_err(FormattingError::Utf)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use ::action::KeySym;
|
||||
|
||||
#[test]
|
||||
fn test_keymap_multi() {
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
|
||||
let keymap_str = generate_keymap(&hashmap!{
|
||||
"ac".into() => KeyState {
|
||||
action: Action::Submit {
|
||||
text: None,
|
||||
keys: vec!(KeySym("a".into()), KeySym("c".into())),
|
||||
},
|
||||
keycodes: vec!(9, 10),
|
||||
locked: false,
|
||||
pressed: PressType::Released,
|
||||
},
|
||||
}).unwrap();
|
||||
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
keymap_str.clone(),
|
||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||
).expect("Failed to create keymap");
|
||||
|
||||
let state = xkb::State::new(&keymap);
|
||||
|
||||
assert_eq!(state.key_get_one_sym(9), xkb::KEY_a);
|
||||
assert_eq!(state.key_get_one_sym(10), xkb::KEY_c);
|
||||
}
|
||||
}
|
||||
|
||||
46
src/layout.h
46
src/layout.h
@ -4,34 +4,41 @@
|
||||
#include <inttypes.h>
|
||||
#include <glib.h>
|
||||
#include "eek/eek-element.h"
|
||||
#include "eek/eek-gtk-keyboard.h"
|
||||
#include "eek/eek-types.h"
|
||||
#include "src/keyboard.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
|
||||
enum squeek_arrangement_kind {
|
||||
ARRANGEMENT_KIND_BASE = 0,
|
||||
ARRANGEMENT_KIND_WIDE = 1,
|
||||
};
|
||||
|
||||
struct squeek_button;
|
||||
struct squeek_row;
|
||||
struct squeek_view;
|
||||
struct squeek_layout;
|
||||
|
||||
/// Represents the path to the button within a view
|
||||
struct button_place {
|
||||
const struct squeek_row *row;
|
||||
const struct squeek_button *button;
|
||||
};
|
||||
|
||||
int32_t squeek_row_get_angle(const struct squeek_row*);
|
||||
|
||||
EekBounds squeek_row_get_bounds(const struct squeek_row*);
|
||||
|
||||
uint32_t squeek_row_contains(struct squeek_row*, struct squeek_button *button);
|
||||
|
||||
struct button_place squeek_view_find_key(struct squeek_view*, struct squeek_key *state);
|
||||
|
||||
|
||||
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
|
||||
void squeek_row_foreach(struct squeek_row*,
|
||||
ButtonCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void squeek_row_free(struct squeek_row*);
|
||||
|
||||
uint32_t squeek_button_get_oref(const struct squeek_button*);
|
||||
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,
|
||||
@ -46,19 +53,24 @@ void squeek_view_foreach(struct squeek_view*,
|
||||
RowCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
struct squeek_row *squeek_view_get_row(struct squeek_view *view,
|
||||
struct squeek_button *button);
|
||||
|
||||
struct squeek_button *squeek_view_find_button_by_position(struct squeek_view *view, EekPoint point);
|
||||
|
||||
|
||||
void
|
||||
squeek_layout_place_contents(struct squeek_layout*);
|
||||
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
|
||||
void squeek_layout_set_state_from_press(struct squeek_layout* layout, LevelKeyboard *keyboard, struct squeek_key* key);
|
||||
|
||||
|
||||
struct squeek_layout *squeek_load_layout(const char *type);
|
||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
|
||||
const char *squeek_layout_get_keymap(const struct squeek_layout*);
|
||||
enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *);
|
||||
void squeek_layout_free(struct squeek_layout*);
|
||||
|
||||
void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp);
|
||||
void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
|
||||
double x_widget, double y_widget,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard,
|
||||
double x_widget, double y_widget,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekGtkKeyboard *ui_keyboard);
|
||||
#endif
|
||||
|
||||
810
src/layout.rs
810
src/layout.rs
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,19 @@
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use] // only for tests
|
||||
extern crate maplit;
|
||||
extern crate serde;
|
||||
extern crate xkbcommon;
|
||||
|
||||
mod action;
|
||||
pub mod data;
|
||||
pub mod float_ord;
|
||||
pub mod imservice;
|
||||
mod keyboard;
|
||||
mod layout;
|
||||
mod outputs;
|
||||
mod resources;
|
||||
mod symbol;
|
||||
mod submission;
|
||||
mod util;
|
||||
mod xdg;
|
||||
|
||||
@ -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',
|
||||
|
||||
13
src/outputs.h
Normal file
13
src/outputs.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __OUTPUTS_H
|
||||
#define __OUTPUTS_H
|
||||
|
||||
#include "wayland-client-protocol.h"
|
||||
|
||||
struct squeek_outputs;
|
||||
|
||||
struct squeek_outputs *squeek_outputs_new();
|
||||
void squeek_outputs_free(struct squeek_outputs*);
|
||||
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output);
|
||||
struct wl_output *squeek_outputs_get_current(struct squeek_outputs*);
|
||||
int32_t squeek_outputs_get_perceptual_width(struct squeek_outputs*, struct wl_output *output);
|
||||
#endif
|
||||
322
src/outputs.rs
Normal file
322
src/outputs.rs
Normal file
@ -0,0 +1,322 @@
|
||||
/*! Managing Wayland outputs */
|
||||
|
||||
use std::vec::Vec;
|
||||
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use super::*;
|
||||
|
||||
use std::os::raw::{ c_char, c_void };
|
||||
|
||||
use ::util::c::COpaquePtr;
|
||||
|
||||
// Defined in C
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct WlOutput(*const c_void);
|
||||
|
||||
#[repr(C)]
|
||||
struct WlOutputListener<T: COpaquePtr> {
|
||||
geometry: extern fn(
|
||||
T, // data
|
||||
WlOutput,
|
||||
i32, // x
|
||||
i32, // y
|
||||
i32, // physical_width
|
||||
i32, // physical_height
|
||||
i32, // subpixel
|
||||
*const c_char, // make
|
||||
*const c_char, // model
|
||||
i32, // transform
|
||||
),
|
||||
mode: extern fn(
|
||||
T, // data
|
||||
WlOutput,
|
||||
u32, // flags
|
||||
i32, // width
|
||||
i32, // height
|
||||
i32, // refresh
|
||||
),
|
||||
done: extern fn(
|
||||
T, // data
|
||||
WlOutput,
|
||||
),
|
||||
scale: extern fn(
|
||||
T, // data
|
||||
WlOutput,
|
||||
i32, // factor
|
||||
),
|
||||
}
|
||||
|
||||
bitflags!{
|
||||
/// Map to `wl_output.mode` values
|
||||
pub struct Mode: u32 {
|
||||
const NONE = 0x0;
|
||||
const CURRENT = 0x1;
|
||||
const PREFERRED = 0x2;
|
||||
}
|
||||
}
|
||||
|
||||
/// Map to `wl_output.transform` values
|
||||
#[derive(Clone)]
|
||||
pub enum Transform {
|
||||
Normal = 0,
|
||||
Rotated90 = 1,
|
||||
Rotated180 = 2,
|
||||
Rotated270 = 3,
|
||||
Flipped = 4,
|
||||
FlippedRotated90 = 5,
|
||||
FlippedRotated180 = 6,
|
||||
FlippedRotated270 = 7,
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
fn from_u32(v: u32) -> Option<Transform> {
|
||||
use self::Transform::*;
|
||||
match v {
|
||||
0 => Some(Normal),
|
||||
1 => Some(Rotated90),
|
||||
2 => Some(Rotated180),
|
||||
3 => Some(Rotated270),
|
||||
4 => Some(Flipped),
|
||||
5 => Some(FlippedRotated90),
|
||||
6 => Some(FlippedRotated180),
|
||||
7 => Some(FlippedRotated270),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// Rustc wrongly assumes
|
||||
// that COutputs allows C direct access to the underlying RefCell
|
||||
#[allow(improper_ctypes)]
|
||||
fn squeek_output_add_listener(
|
||||
wl_output: WlOutput,
|
||||
listener: *const WlOutputListener<COutputs>,
|
||||
data: COutputs,
|
||||
) -> i32;
|
||||
}
|
||||
|
||||
type COutputs = ::util::c::Wrapped<Outputs>;
|
||||
|
||||
// Defined in Rust
|
||||
|
||||
extern fn outputs_handle_geometry(
|
||||
outputs: COutputs,
|
||||
wl_output: WlOutput,
|
||||
_x: i32, _y: i32,
|
||||
_phys_width: i32, _phys_height: i32,
|
||||
_subpixel: i32,
|
||||
_make: *const c_char, _model: *const c_char,
|
||||
transform: i32,
|
||||
) {
|
||||
let transform = Transform::from_u32(transform as u32).unwrap_or_else(
|
||||
|| {
|
||||
eprintln!(
|
||||
"Warning: received invalid wl_output.transform value"
|
||||
);
|
||||
Transform::Normal
|
||||
}
|
||||
);
|
||||
|
||||
let outputs = outputs.clone_ref();
|
||||
let mut collection = outputs.borrow_mut();
|
||||
let output_state: Option<&mut OutputState>
|
||||
= find_output_mut(&mut collection, wl_output)
|
||||
.map(|o| &mut o.pending);
|
||||
match output_state {
|
||||
Some(state) => { state.transform = Some(transform) },
|
||||
None => eprintln!("Wayland error: Got mode on unknown output"),
|
||||
};
|
||||
}
|
||||
|
||||
extern fn outputs_handle_mode(
|
||||
outputs: COutputs,
|
||||
wl_output: WlOutput,
|
||||
flags: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
_refresh: i32,
|
||||
) {
|
||||
let flags = Mode::from_bits(flags).unwrap_or_else(|| {
|
||||
eprintln!("Warning: received invalid wl_output.mode flags");
|
||||
Mode::NONE
|
||||
});
|
||||
let outputs = outputs.clone_ref();
|
||||
let mut collection = outputs.borrow_mut();
|
||||
let output_state: Option<&mut OutputState>
|
||||
= find_output_mut(&mut collection, wl_output)
|
||||
.map(|o| &mut o.pending);
|
||||
match output_state {
|
||||
Some(state) => {
|
||||
if flags.contains(Mode::CURRENT) {
|
||||
state.current_mode = Some(super::Mode { width, height});
|
||||
}
|
||||
},
|
||||
None => eprintln!("Wayland error: Got mode on unknown output"),
|
||||
};
|
||||
}
|
||||
|
||||
extern fn outputs_handle_done(
|
||||
outputs: COutputs,
|
||||
wl_output: WlOutput,
|
||||
) {
|
||||
let outputs = outputs.clone_ref();
|
||||
let mut collection = outputs.borrow_mut();
|
||||
let output = find_output_mut(&mut collection, wl_output);
|
||||
match output {
|
||||
Some(output) => { output.current = output.pending.clone(); }
|
||||
None => eprintln!("Wayland error: Got done on unknown output"),
|
||||
};
|
||||
}
|
||||
|
||||
extern fn outputs_handle_scale(
|
||||
outputs: COutputs,
|
||||
wl_output: WlOutput,
|
||||
factor: i32,
|
||||
) {
|
||||
let outputs = outputs.clone_ref();
|
||||
let mut collection = outputs.borrow_mut();
|
||||
let output_state: Option<&mut OutputState>
|
||||
= find_output_mut(&mut collection, wl_output)
|
||||
.map(|o| &mut o.pending);
|
||||
match output_state {
|
||||
Some(state) => { state.scale = factor; }
|
||||
None => eprintln!("Wayland error: Got done on unknown output"),
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_outputs_new() -> COutputs {
|
||||
COutputs::new(Outputs { outputs: Vec::new() })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_outputs_free(outputs: COutputs) {
|
||||
unsafe { outputs.unwrap() }; // gets dropped
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_outputs_register(raw_collection: COutputs, output: WlOutput) {
|
||||
let collection = raw_collection.clone_ref();
|
||||
let mut collection = collection.borrow_mut();
|
||||
collection.outputs.push(Output {
|
||||
output: output.clone(),
|
||||
pending: OutputState::uninitialized(),
|
||||
current: OutputState::uninitialized(),
|
||||
});
|
||||
|
||||
unsafe { squeek_output_add_listener(
|
||||
output,
|
||||
&WlOutputListener {
|
||||
geometry: outputs_handle_geometry,
|
||||
mode: outputs_handle_mode,
|
||||
done: outputs_handle_done,
|
||||
scale: outputs_handle_scale,
|
||||
} as *const WlOutputListener<COutputs>,
|
||||
raw_collection,
|
||||
)};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_outputs_get_current(raw_collection: COutputs) -> WlOutput {
|
||||
let collection = raw_collection.clone_ref();
|
||||
let collection = collection.borrow();
|
||||
collection.outputs[0].output.clone()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_outputs_get_perceptual_width(
|
||||
raw_collection: COutputs,
|
||||
wl_output: WlOutput,
|
||||
) -> i32 {
|
||||
let collection = raw_collection.clone_ref();
|
||||
let collection = collection.borrow();
|
||||
|
||||
let output_state = find_output(&collection, wl_output)
|
||||
.map(|o| &o.current);
|
||||
match output_state {
|
||||
Some(OutputState {
|
||||
current_mode: Some(super::Mode { width, height } ),
|
||||
transform: Some(transform),
|
||||
scale,
|
||||
}) => {
|
||||
match transform {
|
||||
Transform::Normal
|
||||
| Transform::Rotated180
|
||||
| Transform::Flipped
|
||||
| Transform::FlippedRotated180 => width / scale,
|
||||
_ => height / scale,
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
eprintln!("Not enough info registered on output");
|
||||
0
|
||||
},
|
||||
}
|
||||
}
|
||||
// TODO: handle unregistration
|
||||
|
||||
fn find_output(
|
||||
collection: &Outputs,
|
||||
wl_output: WlOutput,
|
||||
) -> Option<&Output> {
|
||||
collection.outputs
|
||||
.iter()
|
||||
.find_map(|o|
|
||||
if o.output == wl_output { Some(o) } else { None }
|
||||
)
|
||||
}
|
||||
|
||||
fn find_output_mut(
|
||||
collection: &mut Outputs,
|
||||
wl_output: WlOutput,
|
||||
) -> Option<&mut Output> {
|
||||
collection.outputs
|
||||
.iter_mut()
|
||||
.find_map(|o|
|
||||
if o.output == wl_output { Some(o) } else { None }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Mode {
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OutputState {
|
||||
current_mode: Option<Mode>,
|
||||
transform: Option<c::Transform>,
|
||||
scale: i32,
|
||||
}
|
||||
|
||||
impl OutputState {
|
||||
fn uninitialized() -> OutputState {
|
||||
OutputState {
|
||||
current_mode: None,
|
||||
transform: None,
|
||||
scale: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Output {
|
||||
output: c::WlOutput,
|
||||
pending: OutputState,
|
||||
current: OutputState,
|
||||
}
|
||||
|
||||
pub struct Outputs {
|
||||
outputs: Vec<Output>,
|
||||
}
|
||||
@ -2,9 +2,14 @@
|
||||
* This could be done using GResource, but that would need additional work.
|
||||
*/
|
||||
|
||||
|
||||
const KEYBOARDS: &[(*const str, *const str)] = &[
|
||||
("us", include_str!("../data/keyboards/us.yaml")),
|
||||
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
|
||||
("de", include_str!("../data/keyboards/de.yaml")),
|
||||
("el", include_str!("../data/keyboards/el.yaml")),
|
||||
("es", include_str!("../data/keyboards/es.yaml")),
|
||||
("it", include_str!("../data/keyboards/it.yaml")),
|
||||
("ja+kana", include_str!("../data/keyboards/ja+kana.yaml")),
|
||||
("nb", include_str!("../data/keyboards/nb.yaml")),
|
||||
("number", include_str!("../data/keyboards/number.yaml")),
|
||||
];
|
||||
|
||||
@ -20,7 +20,8 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "eek/eek-gtk.h"
|
||||
#include "eek/eek.h"
|
||||
#include "eek/eek-gtk-keyboard.h"
|
||||
#include "eek/layersurface.h"
|
||||
#include "wayland.h"
|
||||
|
||||
@ -38,8 +39,11 @@ typedef struct _ServerContextServiceClass ServerContextServiceClass;
|
||||
struct _ServerContextService {
|
||||
EekboardContextService parent;
|
||||
|
||||
GtkWidget *window;
|
||||
PhoshLayerSurface *window;
|
||||
GtkWidget *widget;
|
||||
guint hiding;
|
||||
guint last_requested_height;
|
||||
enum squeek_arrangement_kind last_type;
|
||||
|
||||
gdouble size_constraint_landscape[2];
|
||||
gdouble size_constraint_portrait[2];
|
||||
@ -51,23 +55,12 @@ 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)
|
||||
{
|
||||
ServerContextService *context = user_data;
|
||||
|
||||
g_assert (widget == context->window);
|
||||
g_assert (widget == GTK_WIDGET(context->window));
|
||||
|
||||
context->window = NULL;
|
||||
context->widget = NULL;
|
||||
@ -107,15 +100,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)
|
||||
@ -128,70 +112,84 @@ static void
|
||||
on_notify_unmap (GObject *object,
|
||||
ServerContextService *context)
|
||||
{
|
||||
(void)object;
|
||||
g_object_set (context, "visible", FALSE, NULL);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
calculate_height(int32_t width)
|
||||
{
|
||||
uint32_t height = 180;
|
||||
if (width < 360 && width > 0) {
|
||||
height = ((unsigned)width * 7 / 12); // to match 360×210
|
||||
} else if (width < 540) {
|
||||
height = 180 + (540 - (unsigned)width) * 30 / 180; // smooth transition
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) {
|
||||
(void)height;
|
||||
if (width < 540) {
|
||||
return ARRANGEMENT_KIND_BASE;
|
||||
}
|
||||
return ARRANGEMENT_KIND_WIDE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_geometry (ServerContextService *context)
|
||||
on_surface_configure(PhoshLayerSurface *surface, 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];
|
||||
gint width;
|
||||
gint height;
|
||||
g_object_get(G_OBJECT(surface),
|
||||
"configured-width", &width,
|
||||
"configured-height", &height,
|
||||
NULL);
|
||||
// check if the change would switch types
|
||||
enum squeek_arrangement_kind new_type = get_type((uint32_t)width, (uint32_t)height);
|
||||
if (context->last_type != new_type) {
|
||||
context->last_type = new_type;
|
||||
eekboard_context_service_update_layout(EEKBOARD_CONTEXT_SERVICE(context), context->last_type);
|
||||
}
|
||||
|
||||
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);
|
||||
guint desired_height = calculate_height(width);
|
||||
guint configured_height = (guint)height;
|
||||
// if height was already requested once but a different one was given
|
||||
// (for the same set of surrounding properties),
|
||||
// then it's probably not reasonable to ask for it again,
|
||||
// as it's likely to create pointless loops
|
||||
// of request->reject->request_again->...
|
||||
if (desired_height != configured_height
|
||||
&& context->last_requested_height != desired_height) {
|
||||
context->last_requested_height = desired_height;
|
||||
phosh_layer_surface_set_size(surface, 0,
|
||||
(gint)desired_height);
|
||||
phosh_layer_surface_set_exclusive_zone(surface, (gint)desired_height);
|
||||
phosh_layer_surface_wl_surface_commit (surface);
|
||||
}
|
||||
}
|
||||
|
||||
#define KEYBOARD_HEIGHT 210
|
||||
static void
|
||||
make_window (ServerContextService *context)
|
||||
{
|
||||
if (context->window)
|
||||
g_error("Window already present");
|
||||
|
||||
struct wl_output *output = squeek_outputs_get_current(squeek_wayland->outputs);
|
||||
int32_t width = squeek_outputs_get_perceptual_width(squeek_wayland->outputs, output);
|
||||
uint32_t height = calculate_height(width);
|
||||
|
||||
context->window = g_object_new (
|
||||
PHOSH_TYPE_LAYER_SURFACE,
|
||||
"layer-shell", squeek_wayland->layer_shell,
|
||||
"wl-output", g_ptr_array_index(squeek_wayland->outputs, 0), // TODO: select output as needed,
|
||||
"height", KEYBOARD_HEIGHT,
|
||||
"wl-output", output,
|
||||
"height", height,
|
||||
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
|
||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
|
||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
|
||||
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
|
||||
"kbd-interactivity", FALSE,
|
||||
"exclusive-zone", KEYBOARD_HEIGHT,
|
||||
"exclusive-zone", height,
|
||||
"namespace", "osk",
|
||||
NULL
|
||||
);
|
||||
@ -200,6 +198,7 @@ make_window (ServerContextService *context)
|
||||
"signal::destroy", G_CALLBACK(on_destroy), context,
|
||||
"signal::map", G_CALLBACK(on_notify_map), context,
|
||||
"signal::unmap", G_CALLBACK(on_notify_unmap), context,
|
||||
"signal::configured", G_CALLBACK(on_surface_configure), context,
|
||||
NULL);
|
||||
|
||||
// The properties below are just to make hacking easier.
|
||||
@ -207,7 +206,7 @@ make_window (ServerContextService *context)
|
||||
// and there's no space in the protocol for others.
|
||||
// Those may still be useful in the future,
|
||||
// or for hacks with regular windows.
|
||||
gtk_widget_set_can_focus (context->window, FALSE);
|
||||
gtk_widget_set_can_focus (GTK_WIDGET(context->window), FALSE);
|
||||
g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL);
|
||||
gtk_window_set_title (GTK_WINDOW(context->window),
|
||||
_("Squeekboard"));
|
||||
@ -237,7 +236,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 +243,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)
|
||||
@ -252,7 +255,16 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
|
||||
|
||||
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
|
||||
show_keyboard (_context);
|
||||
gtk_widget_show (context->window);
|
||||
gtk_widget_show (GTK_WIDGET(context->window));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_hide (ServerContextService *context)
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET(context->window));
|
||||
context->hiding = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -260,7 +272,8 @@ 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 +362,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 *
|
||||
@ -371,3 +373,8 @@ server_context_service_new ()
|
||||
{
|
||||
return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL));
|
||||
}
|
||||
|
||||
enum squeek_arrangement_kind server_context_service_get_layout_type(EekboardContextService *service)
|
||||
{
|
||||
return SERVER_CONTEXT_SERVICE(service)->last_type;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#define SERVER_CONTEXT_SERVICE_H 1
|
||||
|
||||
#include "eekboard/eekboard-service.h"
|
||||
#include "src/layout.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -33,6 +34,7 @@ G_BEGIN_DECLS
|
||||
typedef struct _ServerContextService ServerContextService;
|
||||
|
||||
EekboardContextService *server_context_service_new ();
|
||||
enum squeek_arrangement_kind server_context_service_get_layout_type(EekboardContextService*);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* SERVER_CONTEXT_SERVICE_H */
|
||||
|
||||
@ -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 */
|
||||
@ -28,6 +28,7 @@
|
||||
#include "eekboard/eekboard-service.h"
|
||||
#include "eek/eek.h"
|
||||
#include "imservice.h"
|
||||
#include "outputs.h"
|
||||
#include "server-context-service.h"
|
||||
#include "wayland.h"
|
||||
|
||||
@ -116,7 +117,7 @@ registry_handle_global (void *data,
|
||||
} else if (!strcmp (interface, "wl_output")) {
|
||||
struct wl_output *output = wl_registry_bind (registry, name,
|
||||
&wl_output_interface, 2);
|
||||
g_ptr_array_add (instance->wayland.outputs, output);
|
||||
squeek_outputs_register(instance->wayland.outputs, output);
|
||||
} else if (!strcmp(interface, "wl_seat")) {
|
||||
instance->wayland.seat = wl_registry_bind(registry, name,
|
||||
&wl_seat_interface, 1);
|
||||
|
||||
68
src/submission.rs
Normal file
68
src/submission.rs
Normal file
@ -0,0 +1,68 @@
|
||||
/*! Managing the events belonging to virtual-keyboard interface. */
|
||||
|
||||
use ::keyboard::{ KeyState, PressType };
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ZwpVirtualKeyboardV1(*const c_void);
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" {
|
||||
/// Checks if point falls within bounds,
|
||||
/// which are relative to origin and rotated by angle (I think)
|
||||
pub fn eek_virtual_keyboard_v1_key(
|
||||
virtual_keyboard: ZwpVirtualKeyboardV1,
|
||||
timestamp: u32,
|
||||
keycode: u32,
|
||||
press: u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Timestamp(pub u32);
|
||||
|
||||
/// Layout-independent backend. TODO: Have one instance per program or seat
|
||||
pub struct VirtualKeyboard(pub c::ZwpVirtualKeyboardV1);
|
||||
|
||||
impl VirtualKeyboard {
|
||||
// TODO: split out keyboard state management
|
||||
pub fn switch(
|
||||
&self,
|
||||
key: &mut KeyState,
|
||||
action: PressType,
|
||||
timestamp: Timestamp,
|
||||
) {
|
||||
key.pressed = action.clone();
|
||||
|
||||
let keycodes_count = key.keycodes.len();
|
||||
for keycode in key.keycodes.iter() {
|
||||
let keycode = keycode - 8;
|
||||
match (&key.pressed, keycodes_count) {
|
||||
// Pressing a key made out of a single keycode is simple:
|
||||
// press on press, release on release.
|
||||
(_, 1) => unsafe {
|
||||
c::eek_virtual_keyboard_v1_key(
|
||||
self.0, timestamp.0, keycode, action.clone() as u32
|
||||
);
|
||||
},
|
||||
// A key made of multiple keycodes
|
||||
// has to submit them one after the other
|
||||
(PressType::Pressed, _) => unsafe {
|
||||
c::eek_virtual_keyboard_v1_key(
|
||||
self.0, timestamp.0, keycode, PressType::Pressed as u32
|
||||
);
|
||||
c::eek_virtual_keyboard_v1_key(
|
||||
self.0, timestamp.0, keycode, PressType::Released as u32
|
||||
);
|
||||
},
|
||||
// Design choice here: submit multiple all at press time
|
||||
// and do nothing at release time
|
||||
(PressType::Released, _) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
111
src/util.rs
111
src/util.rs
@ -1,4 +1,14 @@
|
||||
/*! Assorted helpers */
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::hash::{ Hash, Hasher };
|
||||
use std::iter::FromIterator;
|
||||
|
||||
pub mod c {
|
||||
use super::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::{ CStr, CString };
|
||||
use std::os::raw::c_char;
|
||||
@ -53,12 +63,16 @@ pub mod c {
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker trait for values that can be transferred to/received from C.
|
||||
/// They must be either *const or *mut or repr(transparent).
|
||||
pub trait COpaquePtr {}
|
||||
|
||||
/// Wraps structures to pass them safely to/from C
|
||||
/// Since C doesn't respect borrowing rules,
|
||||
/// RefCell will enforce them dynamically (only 1 writer/many readers)
|
||||
/// Rc is implied and will ensure timely dropping
|
||||
#[repr(transparent)]
|
||||
pub struct Wrapped<T: Clone>(*const RefCell<T>);
|
||||
pub struct Wrapped<T>(*const RefCell<T>);
|
||||
|
||||
// It would be nice to implement `Borrow`
|
||||
// directly on the raw pointer to avoid one conversion call,
|
||||
@ -68,7 +82,10 @@ pub mod c {
|
||||
// Unfortunately, that needs a `Ref` struct with self-referential fields,
|
||||
// which is a bit too complex for now.
|
||||
|
||||
impl<T: Clone> Wrapped<T> {
|
||||
impl<T> Wrapped<T> {
|
||||
pub fn new(value: T) -> Wrapped<T> {
|
||||
Wrapped::wrap(Rc::new(RefCell::new(value)))
|
||||
}
|
||||
pub fn wrap(state: Rc<RefCell<T>>) -> Wrapped<T> {
|
||||
Wrapped(Rc::into_raw(state))
|
||||
}
|
||||
@ -86,18 +103,92 @@ pub mod c {
|
||||
Rc::into_raw(used_rc); // prevent dropping the original reference
|
||||
rc
|
||||
}
|
||||
|
||||
/// Create a copy of the underlying data
|
||||
pub fn to_owned(&self) -> T {
|
||||
let rc = self.clone_ref();
|
||||
let r = rc.borrow();
|
||||
r.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Clone for Wrapped<T> {
|
||||
impl<T> Clone for Wrapped<T> {
|
||||
fn clone(&self) -> Wrapped<T> {
|
||||
Wrapped::wrap(self.clone_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// ToOwned won't work here
|
||||
/// because it's really difficult to implement Borrow on Wrapped<T>
|
||||
/// with the Rc<RefCell<>> chain on the way to the data
|
||||
impl<T: Clone> CloneOwned for Wrapped<T> {
|
||||
type Owned = T;
|
||||
|
||||
fn clone_owned(&self) -> T {
|
||||
let rc = self.clone_ref();
|
||||
let r = RefCell::borrow(&rc);
|
||||
r.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> COpaquePtr for Wrapped<T> {}
|
||||
}
|
||||
|
||||
pub trait CloneOwned {
|
||||
type Owned;
|
||||
fn clone_owned(&self) -> Self::Owned;
|
||||
}
|
||||
|
||||
pub fn hash_map_map<K, V, F, K1, V1>(map: HashMap<K, V>, mut f: F)
|
||||
-> HashMap<K1, V1>
|
||||
where F: FnMut(K, V) -> (K1, V1),
|
||||
K1: std::cmp::Eq + std::hash::Hash
|
||||
{
|
||||
HashMap::from_iter(
|
||||
map.into_iter().map(|(key, value)| f(key, value))
|
||||
)
|
||||
}
|
||||
|
||||
/// Compares pointers but not internal values of Rc
|
||||
pub struct Pointer<T>(pub Rc<T>);
|
||||
|
||||
impl<T> Pointer<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Pointer(Rc::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Hash for Pointer<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(&*self.0 as *const T).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for Pointer<T> {
|
||||
fn eq(&self, other: &Pointer<T>) -> bool {
|
||||
Rc::ptr_eq(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Pointer<T> {}
|
||||
|
||||
impl<T> Clone for Pointer<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Pointer(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<Rc<T>> for Pointer<T> {
|
||||
fn borrow(&self) -> &Rc<T> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn check_set() {
|
||||
let mut s = HashSet::new();
|
||||
let first = Rc::new(1u32);
|
||||
s.insert(Pointer(first.clone()));
|
||||
assert_eq!(s.insert(Pointer(Rc::new(2u32))), true);
|
||||
assert_eq!(s.remove(&Pointer(first)), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,17 @@
|
||||
#include "wayland.h"
|
||||
|
||||
struct squeek_wayland *squeek_wayland = NULL;
|
||||
|
||||
// The following functions only exist
|
||||
// to create linkable symbols out of inline functions,
|
||||
// because those are not directly callable from Rust
|
||||
|
||||
void
|
||||
eek_virtual_keyboard_v1_key(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, uint32_t time, uint32_t key, uint32_t state) {
|
||||
zwp_virtual_keyboard_v1_key(zwp_virtual_keyboard_v1, time, key, state);
|
||||
}
|
||||
|
||||
int squeek_output_add_listener(struct wl_output *wl_output,
|
||||
const struct wl_output_listener *listener, void *data) {
|
||||
return wl_output_add_listener(wl_output, listener, data);
|
||||
}
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
#ifndef WAYLAND_H
|
||||
#define WAYLAND_H
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
#include "input-method-unstable-v2-client-protocol.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "outputs.h"
|
||||
|
||||
struct squeek_wayland {
|
||||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct zwp_virtual_keyboard_manager_v1 *virtual_keyboard_manager;
|
||||
struct zwp_input_method_manager_v2 *input_method_manager;
|
||||
GPtrArray *outputs; // *wl_output
|
||||
struct squeek_outputs *outputs;
|
||||
struct wl_seat *seat;
|
||||
};
|
||||
|
||||
@ -21,7 +22,7 @@ extern struct squeek_wayland *squeek_wayland;
|
||||
|
||||
|
||||
static inline void squeek_wayland_init(struct squeek_wayland *wayland) {
|
||||
wayland->outputs = g_ptr_array_new();
|
||||
wayland->outputs = squeek_outputs_new();
|
||||
}
|
||||
|
||||
static inline void squeek_wayland_set_global(struct squeek_wayland *wayland) {
|
||||
@ -29,7 +30,7 @@ static inline void squeek_wayland_set_global(struct squeek_wayland *wayland) {
|
||||
}
|
||||
|
||||
static inline void squeek_wayland_deinit(struct squeek_wayland *wayland) {
|
||||
g_ptr_array_free(wayland->outputs, TRUE);
|
||||
squeek_outputs_free(wayland->outputs);
|
||||
}
|
||||
|
||||
#endif // WAYLAND_H
|
||||
|
||||
@ -9,7 +9,6 @@ views:
|
||||
- "test"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
@ -7,6 +7,5 @@ bounds:
|
||||
height: 0
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ views:
|
||||
- "test"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
bad_field: false
|
||||
|
||||
@ -10,7 +10,6 @@ views:
|
||||
- "."
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
@ -10,7 +10,6 @@ views:
|
||||
- "å"
|
||||
outlines:
|
||||
default:
|
||||
corner_radius: 1
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
buttons:
|
||||
|
||||
14
tests/layout_key3.yaml
Normal file
14
tests/layout_key3.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
# punctuation
|
||||
bounds:
|
||||
x: 0
|
||||
y: 0
|
||||
width: 0
|
||||
height: 0
|
||||
views:
|
||||
base:
|
||||
- "か゚" # 2 codepoints
|
||||
outlines:
|
||||
default:
|
||||
bounds: { x: 0, y: 0, width: 0, height: 0 }
|
||||
|
||||
@ -47,11 +47,20 @@ 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', 'us_wide',
|
||||
'de',
|
||||
'el',
|
||||
'es',
|
||||
'it',
|
||||
'ja+kana',
|
||||
'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