Compare commits

..

1 Commits

Author SHA1 Message Date
901ca9ec76 Remove explicit keycodes in XML, auto-generate them instead
This makes it easier to keep the geometry and symbols files in sync.
2019-07-14 00:16:32 +02:00
165 changed files with 19991 additions and 7030 deletions

9
.gitignore vendored
View File

@ -1,9 +0,0 @@
.zanata-cache/
_build
TAGS
tags
vgdump
*.swp
*~
\#*#
.\#*

View File

@ -2,55 +2,16 @@ image: debian:buster
stages:
- build
- test
.tags: &tags
tags:
- librem5
before_script:
- apt-get -y update
- apt-get -y install wget ca-certificates gnupg
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
- apt-get -y update
- apt-get -y build-dep .
build_meson:
<<: *tags
stage: build
artifacts:
paths:
- _build
expire_in: 3h
tags:
- librem5
script:
- meson . _build/ -Ddepdatadir=/usr/share
- ninja -C _build install
build_deb:
<<: *tags
stage: build
artifacts:
paths:
- "*.deb"
script:
- apt-get -y install devscripts
- debuild -i -us -uc -b
- cp ../*.deb .
test_lintian:
<<: *tags
stage: test
dependencies:
- build_deb
script:
- apt-get -y install lintian
- lintian *.deb
test:
<<: *tags
stage: test
needs:
- build_meson
script:
- ninja -C _build test

37
AUTHORS
View File

@ -1,5 +1,36 @@
squeekboard is written by Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> on behlf of Purism, SPC.
eekboard was written by Daiki Ueno <ueno@unixuser.org>
eekboard is written by Daiki Ueno <ueno@unixuser.org>. The following
files contain code derived from other free software packages:
For more details, see the debian/copyright file.
eek/eek-keyboard-drawing.h
eek/eek-keyboard-drawing.c
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.

162
Cargo.lock generated
View File

@ -1,162 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dtoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linked-hash-map"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rs"
version = "0.1.0"
dependencies = [
"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)",
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_yaml"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "xkbcommon"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"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"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"

View File

@ -1,15 +0,0 @@
[package]
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"] }
[lib]
name = "rs"
path = "src/lib.rs"
crate-type = ["staticlib", "rlib"]

View File

@ -1,58 +0,0 @@
Hacking
=======
This document describes the standards for modifying and maintaining the *squeekboard* project.
Testing
-------
Most common testing is done in CI. Occasionally, and for each release, do perform manual tests to make sure that
- the application draws correctly
- it shows when relevant
- it changes layouts
- it changes levels
Testing with an application:
```
python3 tests/entry.py
```
Testing visibility:
```
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false
```
Testing layouts:
```
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'ua')]"
$ gsettings set org.gnome.desktop.input-sources current 1
```
Maintenance
-----------
Squeekboard uses Rust & Cargo for some of its dependencies.
Use the `cargo.sh` script for maintaining the Cargo part of the build. The script takes the usual Cargo commands, after the first 2 positionsl arguments: source directory, and output artifact. So, `cargo test` becomes:
```
cd build_dir
sh /source_path/cargo.sh '' test
```
### Cargo dependencies
Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates.
`Cargo.lock` is used for remembering the revisions of all Rust dependencies. It should be updated often, preferably with each bugfix revision, and in a commit on its own:
```
cd build_dir
sh /source_path/cargo.sh '' update
ninja test
```

View File

@ -3,18 +3,14 @@
*Squeekboard* is a virtual keyboard supporting Wayland, built primarily for the *Librem 5* phone.
It squeaks because some Rust got inside.
Features
--------
### Present
- GTK3
- Custom yaml-defined keyboards
- Custom xml-defined keyboards
- DBus interface to show and hide
- Use Wayland input method protocol to show and hide
- Use Wayland virtual keyboard protocol
### Temporarily dropped
@ -22,6 +18,8 @@ Features
### TODO
- Use Wayland virtual keyboard protocol
- Use Wayland text input protocol
- Use Wayland input method protocol
- Pick up DBus interface files from /usr/share
@ -35,25 +33,36 @@ See `.gitlab-ci.yml`.
### Build from git repo
```
$ git clone https://source.puri.sm/Librem5/squeekboard.git
$ cd squeekboard
$ git clone https://source.puri.sm/Librem5/eekboard.git
$ cd eekboard
$ mkdir ../build
$ meson ../build/
$ cd ../build
$ ninja test
$ ninja install
```
For development, alter the `meson` call:
```
$ meson ../build/ --prefix=../install
```
and don't skip `ninja install` before running. The last step is necessary in order to find the keyboard definition files.
Running
-------
```
$ phoc # if no compatible Wayland compositor is running yet
$ rootston
$ cd ../build/
$ src/squeekboard
```
Developing
----------
### Testing
See `HACKING.md`
```
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
$ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'ua')]"
$ gsettings set org.gnome.desktop.input-sources current 1
```

1
TODO Normal file
View File

@ -0,0 +1 @@
See https://github.com/ueno/eekboard/wiki/TODO

20
autogen.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="eekboard"
(test -f $srcdir/configure.ac \
&& test -f $srcdir/README.md ) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4"
REQUIRED_AUTOMAKE_VERSION=1.10
REQUIRED_AUTOCONF_VERSION=2.60
. gnome-autogen.sh

View File

@ -0,0 +1 @@
Eek cheader_filename="eek/eek.h"

View File

@ -0,0 +1 @@
EekGtk cheader_filename="eek/eek-gtk.h"

View File

@ -0,0 +1 @@
EekXkl cheader_filename="eek/eek-xkl.h"

View File

@ -0,0 +1 @@
gio-2.0

View File

@ -0,0 +1 @@
eek-0.90

View File

@ -0,0 +1,2 @@
eek-0.90
x11

View File

@ -1,24 +0,0 @@
#!/bin/sh
# This script manages Cargo operations
# while keeping the artifact directory within the build tree
# instead of the source tree
set -e
SCRIPT_PATH="$(realpath "$0")"
SOURCE_DIR="$(dirname "$SCRIPT_PATH")"
CARGO_TARGET_DIR="$(pwd)"
export CARGO_TARGET_DIR
if [ -n "${1}" ]; then
OUT_PATH="$(realpath "$1")"
fi
cd "$SOURCE_DIR"
shift
cargo "$@"
if [ -n "${OUT_PATH}" ]; then
cp "${CARGO_TARGET_DIR}"/debug/librs.a "${OUT_PATH}"
fi

View File

@ -0,0 +1,6 @@
[Desktop Entry]
Name=Eekboard
Exec=eekboard -f
Type=Application
#AutostartCondition=GSettings org.gnome.desktop.a11y.applications screen-keyboard-enabled
X-GNOME-AutoRestart=true

View File

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.fedorahosted.Eekboard
Exec=@bindir@/eekboard-server

9
data/eekboard.desktop.in Normal file
View File

@ -0,0 +1,9 @@
[Desktop Entry]
Name=Eekboard
GenericName=Eekboard Virtual Keyboard
Comment=Virtual Keyboard
Exec=eekboard
Icon=eekboard
Terminal=false
Type=Application
Categories=GTK;Utility;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"
version="1.1" viewBox="0 0 24 24">
<path d="M 24,1 L 24,10 C 24,15 20,17 17,17 L 7,17 L 10,20 L 10,23

Before

Width:  |  Height:  |  Size: 388 B

After

Width:  |  Height:  |  Size: 388 B

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"
version="1.1" viewBox="0 0 24 24">
<path d="M 12,2 L 22,14 L 16,14 L 16,22 L 8,22 L 8,14 L 2,14 Z"

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 279 B

View File

@ -1,95 +0,0 @@
# 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"

View File

@ -1,196 +0,0 @@
# 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: "]"

View File

@ -1,93 +0,0 @@
---
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"

View File

@ -0,0 +1,119 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="ABC123" oref="altline" />
<key name="I150" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="150.5853" y="0.000000"/>
<point x="150.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

@ -1,97 +0,0 @@
# 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"

View File

@ -1,529 +0,0 @@
# 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: ",.?"

View File

@ -0,0 +1,88 @@
<?xml version="1.0"?>
<keyboards version="0.90">
<keyboard id="ar" name="ar"
geometry="compact" symbols="ar"
longname="Arabic" language="ar"/>
<keyboard id="be" name="be"
geometry="compact" symbols="be"
longname="Belarusian" language="be"/>
<keyboard id="fa" name="fa"
geometry="compact" symbols="fa"
longname="Farsi (ISIRI 2901-1994)" language="fa"/>
<keyboard id="he" name="he"
geometry="compact" symbols="he"
longname="Hebrew" language="he"/>
<keyboard id="ja" name="ja"
geometry="compact" symbols="ja-kana"
longname="Japanese (Kana)" language="ja"/>
<keyboard id="kk" name="kk"
geometry="compact" symbols="kk"
longname="Kazakh" language="kk"/>
<keyboard id="ks" name="ks"
geometry="compact" symbols="ks"
longname="Kashmiri" language="ks"/>
<keyboard id="my" name="my"
geometry="compact" symbols="my"
longname="Myanmar" language="my"/>
<keyboard id="ru" name="ru"
geometry="compact" symbols="us"
longname="Russian" language="ru"/>
<keyboard id="th" name="th"
geometry="compact" symbols="th"
longname="Thai" language="th"/>
<keyboard id="ua" name="ua"
geometry="compact" symbols="ua"
longname="Ukrainian" language="ua"/>
<keyboard id="ug" name="ug"
geometry="compact" symbols="ug"
longname="Uyghur" language="ug"/>
<keyboard id="us" name="us"
geometry="compact" symbols="us"
longname="US" language="en"/>
<keyboard id="zh-bopomofo" name="zh-bopomofo"
geometry="compact" symbols="zh-bopomofo"
longname="Chinese (Bopomofo)" language="zh"/>
<!-- Indic Inscript keyboards converted from m17n-lib -->
<keyboard id="as-inscript" name="as-inscript"
geometry="compact" symbols="as-inscript"
longname="Assamese (Inscript)" language="as"/>
<keyboard id="bn-inscript" name="bn-inscript"
geometry="compact" symbols="bn-inscript"
longname="Bengali (Inscript)" language="bn"/>
<keyboard id="gu-inscript" name="gu-inscript"
geometry="compact" symbols="gu-inscript"
longname="Gujarati (Inscript)" language="gu"/>
<keyboard id="hi-inscript" name="hi-inscript"
geometry="compact" symbols="hi-inscript"
longname="Hindi (Inscript)" language="hi"/>
<keyboard id="kn-inscript" name="kn-inscript"
geometry="compact" symbols="kn-inscript"
longname="Kannada (Inscript)" language="kn"/>
<keyboard id="ks-inscript" name="ks-inscript"
geometry="compact" symbols="ks-inscript"
longname="Kashmiri Devanagari (Inscript)" language="ks"/>
<keyboard id="mai-inscript" name="mai-inscript"
geometry="compact" symbols="mai-inscript"
longname="Maithili (Inscript)" language="mai"/>
<keyboard id="ml-inscript" name="ml-inscript"
geometry="compact" symbols="ml-inscript"
longname="Malayalam (Inscript)" language="ml-inscript"/>
<keyboard id="mr-inscript" name="mr-inscript"
geometry="compact" symbols="mr-inscript"
longname="Marathi (Inscript)" language="mr"/>
<keyboard id="or-inscript" name="or-inscript"
geometry="compact" symbols="or-inscript"
longname="Oriya (Inscript)" language="or"/>
<keyboard id="pa-inscript" name="pa-inscript"
geometry="compact" symbols="pa-inscript"
longname="Punjabi (Inscript)" language="pa"/>
<keyboard id="sd-inscript" name="sd-inscript"
geometry="compact" symbols="sd-inscript"
longname="Sindhi (Inscript)" language="sd"/>
<keyboard id="ta-inscript" name="ta-inscript"
geometry="compact" symbols="ta-inscript"
longname="Tamil (Inscript)" language="ta"/>
<keyboard id="te-inscript" name="te-inscript"
geometry="compact" symbols="te-inscript"
longname="Telugu (Inscript)" language="te"/>
</keyboards>

View File

@ -1,177 +0,0 @@
---
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:
- "q w e r t y u i o p aring"
- "a s d f g h j k l oslash ae"
- "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 Aring"
- "A S D F G H J K L Oslash AE"
- "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"
- "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: "ABC"
show_symbols:
action:
set_view: "symbols"
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: "]"

View File

@ -1,43 +0,0 @@
---
bounds: { x: 0, y: 0.33, width: 360, height: 210 }
outlines:
default:
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
altline:
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
outline7:
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
bounds: { x: 0, y: 0, width: 120.5853, height: 52 }
views:
base:
- "1 2 3 parenleft parenright"
- "4 5 6 numbersign asterisk"
- "7 8 9 plus minus"
- "BackSpace 0 space Return"
buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
space:
outline: spaceline
label: " "
Return:
outline: outline7
icon: "key-enter"
asterisk:
label: "*"
numbersign:
label: "#"
minus:
label: "-"
plus:
label: "+"
parenleft:
label: "("
parenright:
label: ")"

View File

@ -0,0 +1,180 @@
<?xml version="1.0"?>
<symbols version="0.90">
<key name="AD01">
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
<keysym keyval="49">1</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key name="AD02">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
<keysym keyval="50">2</keysym>
<keysym keyval="96">quoteleft</keysym>
</key>
<key name="AD03">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
<keysym keyval="51">3</keysym>
<keysym keyval="124">bar</keysym>
</key>
<key name="AD04">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
<keysym keyval="52">4</keysym>
<keysym keyval="183">middledot</keysym>
</key>
<key name="AD05">
<keysym keyval="116">t</keysym>
<keysym keyval="84">T</keysym>
<keysym keyval="53">5</keysym>
</key>
<key name="AD06">
<keysym keyval="121">y</keysym>
<keysym keyval="89">Y</keysym>
<keysym keyval="54">6</keysym>
</key>
<key name="AD07">
<keysym keyval="117">u</keysym>
<keysym keyval="85">U</keysym>
<keysym keyval="55">7</keysym>
</key>
<key name="AD08">
<keysym keyval="105">i</keysym>
<keysym keyval="73">I</keysym>
<keysym keyval="56">8</keysym>
</key>
<key name="AD09">
<keysym keyval="111">o</keysym>
<keysym keyval="79">O</keysym>
<keysym keyval="57">9</keysym>
</key>
<key name="AD10">
<keysym keyval="112">p</keysym>
<keysym keyval="80">P</keysym>
<keysym keyval="48">0</keysym>
</key>
<key name="AC01">
<keysym keyval="97">a</keysym>
<keysym keyval="65">A</keysym>
<keysym keyval="64">at</keysym>
<keysym keyval="169">copyright</keysym>
</key>
<key name="AC02">
<keysym keyval="115">s</keysym>
<keysym keyval="83">S</keysym>
<keysym keyval="35">numbersign</keysym>
<keysym keyval="174">registeredtrademark</keysym>
</key>
<key name="AC03">
<keysym keyval="100">d</keysym>
<keysym keyval="68">D</keysym>
<keysym keyval="36">dollar</keysym>
<keysym keyval="163">poundsign</keysym>
</key>
<key name="AC04">
<keysym keyval="102">f</keysym>
<keysym keyval="70">F</keysym>
<keysym keyval="37">percent</keysym>
<text></text>
</key>
<key name="AC05">
<keysym keyval="103">g</keysym>
<keysym keyval="71">G</keysym>
<keysym keyval="38">ampersand</keysym>
<keysym keyval="165">yensign</keysym>
</key>
<key name="AC06">
<keysym keyval="104">h</keysym>
<keysym keyval="72">H</keysym>
<keysym keyval="45">minus</keysym>
<keysym keyval="94">asciicircum</keysym>
</key>
<key name="AC07">
<keysym keyval="106">j</keysym>
<keysym keyval="74">J</keysym>
<keysym keyval="43">plus</keysym>
<keysym keyval="176">degreesign</keysym>
</key>
<key name="AC08">
<keysym keyval="107">k</keysym>
<keysym keyval="75">K</keysym>
<keysym keyval="40">parenleft</keysym>
<keysym keyval="123">braceleft</keysym>
</key>
<key name="AC09">
<keysym keyval="108">l</keysym>
<keysym keyval="76">L</keysym>
<keysym keyval="41">parenright</keysym>
<keysym keyval="125">braceright</keysym>
</key>
<key name="RTRN">
<keysym keyval="65293" icon="key-enter">Return</keysym>
</key>
<key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" label="=/+">Shift_L</keysym>
<keysym keyval="65505" label="123">Shift_L</keysym>
</key>
<key name="AB01">
<keysym keyval="122">z</keysym>
<keysym keyval="90">Z</keysym>
<keysym keyval="44">comma</keysym>
<keysym keyval="92">backslash</keysym>
</key>
<key name="AB02">
<keysym keyval="120">x</keysym>
<keysym keyval="88">X</keysym>
<keysym keyval="34">quotedbl</keysym>
<keysym keyval="47">slash</keysym>
</key>
<key name="AB03">
<keysym keyval="99">c</keysym>
<keysym keyval="67">C</keysym>
<keysym keyval="39">quoteright</keysym>
<keysym keyval="60">less</keysym>
</key>
<key name="AB04">
<keysym keyval="118">v</keysym>
<keysym keyval="86">V</keysym>
<keysym keyval="58">colon</keysym>
<keysym keyval="62">greater</keysym>
</key>
<key name="AB05">
<keysym keyval="98">b</keysym>
<keysym keyval="66">B</keysym>
<keysym keyval="59">semicolon</keysym>
<keysym keyval="61">equal</keysym>
</key>
<key name="AB06">
<keysym keyval="110">n</keysym>
<keysym keyval="78">N</keysym>
<keysym keyval="33">exclam</keysym>
<keysym keyval="91">bracketleft</keysym>
</key>
<key name="AB07">
<keysym keyval="109">m</keysym>
<keysym keyval="77">M</keysym>
<keysym keyval="63">question</keysym>
<keysym keyval="93">bracketright</keysym>
</key>
<key name="AB08">
<keysym keyval="46">period</keysym>
</key>
<key name="ABC123">
<symbol label="123">show-numbers</symbol>
<symbol label="123">show-numbers</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="ABC">show-letters</symbol>
</key>
<key name="I150">
<symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key name="SPCE">
<keysym keyval="32">space</keysym>
</key>
<key name="BKSP">
<keysym keyval="65288" icon="edit-clear-symbolic">backspace</keysym>
</key>
</symbols>

View File

@ -1,85 +0,0 @@
---
bounds: { x: 0, y: 1, width: 360, height: 208 }
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: 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 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"

View File

@ -1,85 +0,0 @@
---
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"

View File

@ -6,5 +6,4 @@ Exec=squeekboard
Icon=squeekboard
Terminal=false
Type=Application
NoDisplay=true
Categories=GTK;Utility;

View File

@ -2,6 +2,8 @@
<gresources>
<gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/compact.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ar.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/as-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/be.xml</file>
@ -28,6 +30,7 @@
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/th.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ua.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ug.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/us.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.xml</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>

View File

@ -1,46 +1,18 @@
sq_view {
.keyboard {
background-color: rgba(0, 0, 0, 255);
color: #ffffff;
font-family: cantarell, sans-serif;
}
sq_view sq_button {
.key {
color: #deddda;
background: #464448;
border-style: solid;
border-width: 1px;
border-width: 0.5px;
border-color: #5e5c64;
border-radius: 3px;
margin: 4px 2px 4px 2px;
border-radius: 2px;
}
sq_view.wide sq_button {
margin: 1px 1px 1px 1px;
}
sq_button:active {
background: #747077;
border-color: #96949d;
}
sq_button.altline,
sq_button.special,
sq_button.wide {
background: #2b292f;
border-color: #3e3a44;
}
sq_button.locked {
background: #ffffff;
color: #2b292f;
}
#Return {
background: #1c71d8;
border-color: #1a5fb4;
}
#Return:active {
.key:active {
background: #1c71d8;
border-color: #3584e4;
}

12
debian/cargo/config vendored
View File

@ -1,12 +0,0 @@
# When modifying this file, consider instead
# to take advantage of the method that Cargo packagers use
# to set up all the necessary stuff automatically:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=907629#30
[source.crates-io]
registry = 'https://github.com/rust-lang/crates.io-index'
replace-with = 'vendored-sources'
[source.vendored-sources]
directory = '/usr/share/cargo/registry'

25
debian/changelog vendored
View File

@ -1,28 +1,3 @@
squeekboard (1.2.2) amber-phone; urgency=medium
* Landscape mode
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 30 Oct 2019 12:38:39 +0000
squeekboard (1.2.1) amber-phone; urgency=medium
* Use different distribution
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Tue, 08 Oct 2019 10:56:10 +0000
squeekboard (1.2.0) unstable; urgency=medium
* Use Cargo-based dependencies
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Tue, 24 Sep 2019 10:42:15 +0000
squeekboard (1.1.0) unstable; urgency=medium
* Use new keyboard layout format
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Mon, 02 Sep 2019 10:12:02 +0000
squeekboard (1.0.10) unstable; urgency=medium
* Use a shared DBus definition

14
debian/control vendored
View File

@ -3,25 +3,15 @@ Section: x11
Priority: optional
Maintainer: Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>
Build-Depends:
cargo,
debhelper (>= 10),
meson (>=0.51.0),
ninja-build,
meson (>=0.43.0),
pkg-config,
libglib2.0-dev,
libgtk-3-dev,
libcroco3-dev,
librust-bitflags-1-dev (>= 1.0),
librust-maplit-1-dev (>= 1.0),
librust-serde-derive-1-dev (>= 1.0),
librust-serde-yaml-0.8-dev (>= 0.8),
librust-xkbcommon-0.4+wayland-dev (>= 0.4),
libwayland-dev (>= 1.16),
rustc,
wayland-protocols (>= 1.14),
# for running the tests
xvfb,
xauth,
wayland-protocols (>= 1.14)
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard

4
debian/copyright vendored
View File

@ -1,6 +1,6 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: squeekboard
Source: https://source.puri.sm/Librem5/squeekboard
Upstream-Name: evscript
Source: https://source.puri.sm/david.boddie/evscript
Files: *
Copyright: 2010-2011 Daiki Ueno <ueno@unixuser.org>

7
debian/rules vendored
View File

@ -1,15 +1,8 @@
#!/usr/bin/make -f
export CARGO_HOME = $(CURDIR)/debian/cargo
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@ --builddirectory=_build --buildsystem=meson
# The Debian version of linked-hash-map doesn't provide any hash,
# causing Cargo to refuse to build with a crates.io copy
build-arch:
rm Cargo.lock
dh $@ --builddirectory=_build --buildsystem=meson
override_dh_autoreconf:

View File

@ -1,2 +0,0 @@
# yaml-rust 0.4.3 shares some roots with libyaml, including the string which lintian checks, creating a false positive
squeekboard binary: embedded-library usr/bin/squeekboard: libyaml

View File

@ -0,0 +1,83 @@
<?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>

View File

@ -0,0 +1,70 @@
<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>

View File

@ -0,0 +1,544 @@
<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>

View File

@ -0,0 +1,56 @@
<?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>

View File

@ -0,0 +1,104 @@
<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>

View File

@ -0,0 +1,4 @@
eekboard_client_get_type
eekboard_context_get_type
eekboard_context_service_get_type
eekboard_service_get_type

0
eek/config.h Normal file
View File

234
eek/eek-container.c Normal file
View File

@ -0,0 +1,234 @@
/*
* 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
*/
/**
* SECTION:eek-container
* @short_description: Base class of a keyboard container
*
* The #EekContainerClass class represents a keyboard container, which
* shall be used to implement #EekKeyboard and #EekSection.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-container.h"
enum {
CHILD_ADDED,
CHILD_REMOVED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekContainerPrivate
{
GList *head;
GList *last;
} EekContainerPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekContainer, eek_container, EEK_TYPE_ELEMENT)
static void
eek_container_real_add_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
g_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref (child);
if (!priv->head) {
priv->head = priv->last = g_list_prepend (priv->head, child);
} else {
priv->last->next = g_list_prepend (priv->last->next, child);
priv->last = priv->last->next;
}
eek_element_set_parent (child, EEK_ELEMENT(self));
g_signal_emit (self, signals[CHILD_ADDED], 0, child);
}
static void
eek_container_real_remove_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
g_return_if_fail (EEK_IS_ELEMENT(child));
head = g_list_find (priv->head, child);
g_return_if_fail (head);
g_object_unref (child);
if (head == priv->last)
priv->last = g_list_previous (priv->last);
priv->head = g_list_remove_link (priv->head, head);
eek_element_set_parent (child, NULL);
g_signal_emit (self, signals[CHILD_REMOVED], 0, child);
}
static void
eek_container_real_foreach_child (EekContainer *self,
EekCallback callback,
gpointer user_data)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = g_list_next (head))
(*callback) (EEK_ELEMENT(head->data), user_data);
}
static EekElement *
eek_container_real_find (EekContainer *self,
EekCompareFunc func,
gpointer user_data)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
head = g_list_find_custom (priv->head, user_data, (GCompareFunc)func);
if (head)
return head->data;
return NULL;
}
static void
eek_container_dispose (GObject *object)
{
EekContainer *self = EEK_CONTAINER (object);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = priv->head) {
g_object_unref (head->data);
priv->head = g_list_next (head);
g_list_free1 (head);
}
G_OBJECT_CLASS(eek_container_parent_class)->dispose (object);
}
static void
eek_container_class_init (EekContainerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->add_child = eek_container_real_add_child;
klass->remove_child = eek_container_real_remove_child;
klass->foreach_child = eek_container_real_foreach_child;
klass->find = eek_container_real_find;
/* signals */
klass->child_added = NULL;
klass->child_removed = NULL;
gobject_class->dispose = eek_container_dispose;
/**
* EekContainer::child-added:
* @container: an #EekContainer
* @element: an #EekElement
*
* The ::child-added signal is emitted each time an element is
* added to @container.
*/
signals[CHILD_ADDED] =
g_signal_new (I_("child-added"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
EEK_TYPE_ELEMENT);
/**
* EekContainer::child-removed:
* @container: an #EekContainer
* @element: an #EekElement
*
* The ::child-removed signal is emitted each time an element is
* removed from @container.
*/
signals[CHILD_REMOVED] =
g_signal_new (I_("child-removed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
EEK_TYPE_ELEMENT);
}
static void
eek_container_init (EekContainer *self)
{
/* void */
}
/**
* eek_container_foreach_child:
* @container: an #EekContainer
* @callback: (scope call): an #EekCallback
* @user_data: additional data passed to @callback
*
* Enumerate children of @container and run @callback with each child.
*/
void
eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
EEK_CONTAINER_GET_CLASS(container)->foreach_child (container,
callback,
user_data);
}
/**
* eek_container_find:
* @container: an #EekContainer
* @func: function to be used to compare two children
* @user_data: additional data passed to @func
*
* Find a child which matches the criteria supplied as @func, in @container.
* Returns: an #EekElement or NULL on failure
*/
EekElement *
eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data)
{
g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
return EEK_CONTAINER_GET_CLASS(container)->find (container,
func,
user_data);
}
void
eek_container_add_child (EekContainer *container, EekElement *element)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
g_return_if_fail (EEK_IS_ELEMENT(element));
return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
}

94
eek/eek-container.h Normal file
View File

@ -0,0 +1,94 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_CONTAINER_H
#define EEK_CONTAINER_H 1
#include "eek-element.h"
G_BEGIN_DECLS
#define EEK_TYPE_CONTAINER (eek_container_get_type())
G_DECLARE_DERIVABLE_TYPE (EekContainer, eek_container, EEK, CONTAINER, EekElement)
/**
* EekCallback:
* @element: an #EekElement
* @user_data: user-supplied data
*
* The type of the callback function used for iterating over the
* children of a container, see eek_container_foreach_child().
*/
typedef void (*EekCallback) (EekElement *element, gpointer user_data);
typedef gint (*EekCompareFunc) (EekElement *element, gpointer user_data);
/**
* EekContainerClass:
* @foreach_child: virtual function for iterating over the container's children
* @find: virtual function for looking up a child
* @child_added: class handler for #EekContainer::child-added
* @child_removed: class handler for #EekContainer::child-added
*/
struct _EekContainerClass
{
/*< private >*/
EekElementClass parent_class;
void (* add_child) (EekContainer *self,
EekElement *element);
void (* remove_child) (EekContainer *self,
EekElement *element);
/*< public >*/
void (* foreach_child) (EekContainer *self,
EekCallback callback,
gpointer user_data);
EekElement *(* find) (EekContainer *self,
EekCompareFunc func,
gpointer data);
/* signals */
void (* child_added) (EekContainer *self,
EekElement *element);
void (* child_removed) (EekContainer *self,
EekElement *element);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_container_get_type (void) G_GNUC_CONST;
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
void eek_container_add_child (EekContainer *container,
EekElement *element);
G_END_DECLS
#endif /* EEK_CONTAINER_H */

View File

@ -26,28 +26,58 @@
* shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-element.h"
#include "eek-container.h"
#include "eek-marshalers.h"
enum {
PROP_0,
PROP_NAME,
PROP_BOUNDS,
PROP_GROUP,
PROP_LEVEL,
PROP_LAST
};
enum {
SYMBOL_INDEX_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekElementPrivate
{
gchar *name;
EekBounds bounds;
EekElement *parent;
gint group;
gint level;
} EekElementPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT)
static void
eek_element_real_symbol_index_changed (EekElement *self,
gint group,
gint level)
{
// g_debug ("symbol-index-changed");
}
static void
eek_element_finalize (GObject *object)
{
EekElement *self = EEK_ELEMENT (object);
EekElementPrivate *priv = eek_element_get_instance_private (self);
g_free (priv->name);
G_OBJECT_CLASS (eek_element_parent_class)->finalize (object);
}
@ -60,9 +90,18 @@ eek_element_set_property (GObject *object,
EekElement *element = EEK_ELEMENT(object);
switch (prop_id) {
case PROP_NAME:
eek_element_set_name (element,
g_value_dup_string (value));
break;
case PROP_BOUNDS:
eek_element_set_bounds (element, g_value_get_boxed (value));
break;
case PROP_GROUP:
eek_element_set_group (element, g_value_get_int (value));
break;
case PROP_LEVEL:
eek_element_set_level (element, g_value_get_int (value));
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -79,10 +118,19 @@ eek_element_get_property (GObject *object,
EekBounds bounds;
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_element_get_name (element));
break;
case PROP_BOUNDS:
eek_element_get_bounds (element, &bounds);
g_value_set_boxed (value, &bounds);
break;
case PROP_GROUP:
g_value_set_int (value, eek_element_get_group (element));
break;
case PROP_LEVEL:
g_value_set_int (value, eek_element_get_level (element));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -96,10 +144,26 @@ eek_element_class_init (EekElementClass *klass)
GParamSpec *pspec;
/* signals */
klass->symbol_index_changed = eek_element_real_symbol_index_changed;
gobject_class->set_property = eek_element_set_property;
gobject_class->get_property = eek_element_get_property;
gobject_class->finalize = eek_element_finalize;
/**
* EekElement:name:
*
* The name of #EekElement.
*/
pspec = g_param_spec_string ("name",
"Name",
"Name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_NAME,
pspec);
/**
* EekElement:bounds:
*
@ -113,12 +177,149 @@ eek_element_class_init (EekElementClass *klass)
g_object_class_install_property (gobject_class,
PROP_BOUNDS,
pspec);
/**
* EekElement:group:
*
* The group value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("group",
"Group",
"Group value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_GROUP,
pspec);
/**
* EekElement:level:
*
* The level value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("level",
"Level",
"Level value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LEVEL,
pspec);
/**
* EekElement::symbol-index-changed:
* @element: an #EekElement
* @group: row index of the symbol matrix of keys on @element
* @level: column index of the symbol matrix of keys on @element
*
* The ::symbol-index-changed signal is emitted each time the
* global configuration of group/level index changes.
*/
signals[SYMBOL_INDEX_CHANGED] =
g_signal_new (I_("symbol-index-changed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekElementClass, symbol_index_changed),
NULL,
NULL,
_eek_marshal_VOID__INT_INT,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_INT);
}
static void
eek_element_init (EekElement *self)
{
(void)self;
EekElementPrivate *priv = eek_element_get_instance_private (self);
priv->group = -1;
priv->level = -1;
}
/**
* eek_element_set_parent:
* @element: an #EekElement
* @parent: (allow-none): an #EekElement or %NULL
*
* Set the parent of @element to @parent.
*/
void
eek_element_set_parent (EekElement *element,
EekElement *parent)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (parent == NULL || EEK_IS_ELEMENT(parent));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->parent == parent)
return;
if (priv->parent != NULL) {
/* release self-reference acquired when setting parent */
g_object_unref (element);
}
if (parent != NULL) {
g_object_ref (element);
}
priv->parent = parent;
}
/**
* eek_element_get_parent:
* @element: an #EekElement
*
* Get the parent of @element.
* Returns: an #EekElement if the parent is set
*/
EekElement *
eek_element_get_parent (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->parent;
}
/**
* eek_element_set_name:
* @element: an #EekElement
* @name: name of @element
*
* Set the name of @element to @name.
*/
void
eek_element_set_name (EekElement *element,
const gchar *name)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
* eek_element_get_name:
* @element: an #EekElement
*
* Get the name of @element.
* Returns: the name of @element or NULL when the name is not set
*/
const gchar *
eek_element_get_name (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->name;
}
/**
@ -161,3 +362,211 @@ eek_element_get_bounds (EekElement *element,
memcpy (bounds, &priv->bounds, sizeof(EekBounds));
}
/**
* eek_element_get_absolute_position:
* @element: an #EekElement
* @x: pointer where the X coordinate of @element will be stored
* @y: pointer where the Y coordinate of @element will be stored
*
* Compute the absolute position of @element.
*/
void
eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y)
{
EekBounds bounds;
gdouble ax = 0.0, ay = 0.0;
do {
eek_element_get_bounds (element, &bounds);
ax += bounds.x;
ay += bounds.y;
} while ((element = eek_element_get_parent (element)) != NULL);
*x = ax;
*y = ay;
}
/**
* eek_element_set_position:
* @element: an #EekElement
* @x: X coordinate of top left corner
* @y: Y coordinate of top left corner
*
* Set the relative position of @element.
*/
void
eek_element_set_position (EekElement *element,
gdouble x,
gdouble y)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.x = x;
bounds.y = y;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_size:
* @element: an #EekElement
* @width: width of @element
* @height: height of @element
*
* Set the size of @element.
*/
void
eek_element_set_size (EekElement *element,
gdouble width,
gdouble height)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.width = width;
bounds.height = height;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_symbol_index:
* @element: an #EekElement
* @group: row index of the symbol matrix
* @level: column index of the symbol matrix
*
* Set the default index of the symbol matrices of @element. The
* setting affects the child, if child does not have the index set, as
* well as this element. To unset, pass -1 as group/level.
*/
void
eek_element_set_symbol_index (EekElement *element,
gint group,
gint level)
{
gboolean emit_signal;
g_return_if_fail (EEK_IS_ELEMENT(element));
emit_signal = group != eek_element_get_group (element) ||
level != eek_element_get_level (element);
eek_element_set_group (element, group);
eek_element_set_level (element, level);
if (emit_signal)
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0, group, level);
}
/**
* eek_element_get_symbol_index:
* @element: an #EekElement
* @group: a pointer where the group value of the symbol index will be stored
* @level: a pointer where the level value of the symbol index will be stored
*
* Get the default index of the symbol matrices of @element.
* If the index is not set, -1 will be returned.
*/
void
eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (group != NULL || level != NULL);
if (group != NULL)
*group = eek_element_get_group (element);
if (level != NULL)
*level = eek_element_get_level (element);
}
/**
* eek_element_set_group:
* @element: an #EekElement
* @group: group index of @element
*
* Set the group value of the default symbol index of @element. To
* unset, pass -1 as @group.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_group (EekElement *element,
gint group)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->group != group) {
priv->group = group;
g_object_notify (G_OBJECT(element), "group");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
group, priv->level);
}
}
/**
* eek_element_set_level:
* @element: an #EekElement
* @level: level index of @element
*
* Set the level value of the default symbol index of @element. To
* unset, pass -1 as @level.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_level (EekElement *element,
gint level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->level != level) {
priv->level = level;
g_object_notify (G_OBJECT(element), "level");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
priv->group, level);
}
}
/**
* eek_element_get_group:
* @element: an #EekElement
*
* Return the group value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_group (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->group;
}
/**
* eek_element_get_level:
* @element: an #EekElement
*
* Return the level value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_level (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->level;
}

View File

@ -36,10 +36,18 @@ struct _EekElementClass
{
/*< private >*/
GObjectClass parent_class;
/* signals */
void (* symbol_index_changed) (EekElement *self,
gint group,
gint level);
};
GType eek_element_get_type (void) G_GNUC_CONST;
void eek_element_set_parent (EekElement *element,
EekElement *parent);
EekElement *eek_element_get_parent (EekElement *element);
void eek_element_set_name (EekElement *element,
const gchar *name);
@ -51,5 +59,29 @@ void eek_element_set_bounds (EekElement *element,
void eek_element_get_bounds (EekElement *element,
EekBounds *bounds);
void eek_element_set_position (EekElement *element,
gdouble x,
gdouble y);
void eek_element_set_size (EekElement *element,
gdouble width,
gdouble height);
void eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y);
void eek_element_set_symbol_index (EekElement *element,
gint group,
gint level);
void eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level);
void eek_element_set_group (EekElement *element,
gint group);
void eek_element_set_level (EekElement *element,
gint level);
gint eek_element_get_group (EekElement *element);
gint eek_element_get_level (EekElement *element);
G_END_DECLS
#endif /* EEK_ELEMENT_H */

View File

@ -23,7 +23,9 @@
* @short_description: a #GtkWidget displaying #EekKeyboard
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
@ -32,16 +34,16 @@
#include <math.h>
#include <string.h>
#include "eek-renderer.h"
#include "eek-keyboard.h"
#include "eek-gtk-keyboard.h"
#include "eekboard/eekboard-context-service.h"
#include "src/layout.h"
#include "eek-gtk-renderer.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
enum {
PROP_0,
PROP_KEYBOARD,
PROP_LAST
};
@ -54,16 +56,37 @@ enum {
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
LevelKeyboard *keyboard;
EekKeyboard *keyboard;
gulong key_locked_handler;
gulong key_unlocked_handler;
gulong symbol_index_changed_handler;
EekTheme *theme;
GdkEventSequence *sequence; // unowned reference
} EekGtkKeyboardPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
static void render_pressed_button (GtkWidget *widget, struct button_place *place);
static void render_released_button (GtkWidget *widget,
const struct squeek_button *button);
static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self);
static void on_key_released (EekKey *key,
EekGtkKeyboard *self);
static void on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
static void render_pressed_key (GtkWidget *widget,
EekKey *key);
static void render_locked_key (GtkWidget *widget,
EekKey *key);
static void render_released_key (GtkWidget *widget,
EekKey *key);
static void
eek_gtk_keyboard_real_realize (GtkWidget *self)
@ -74,8 +97,7 @@ eek_gtk_keyboard_real_realize (GtkWidget *self)
GDK_KEY_RELEASE_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_TOUCH_MASK);
GDK_BUTTON_MOTION_MASK);
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->realize (self);
}
@ -87,24 +109,39 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
GList *list, *head;
gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) {
PangoContext *pcontext = gtk_widget_get_pango_context (self);
PangoContext *pcontext;
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
pcontext = gtk_widget_get_pango_context (self);
priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
if (priv->theme)
eek_renderer_set_theme (priv->renderer, priv->theme);
eek_renderer_set_allocation_size (priv->renderer,
allocation.width,
allocation.height);
eek_renderer_set_scale_factor (priv->renderer,
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);
// render only a few remaining changes
squeek_layout_draw_all_changed(priv->keyboard->layout, EEK_GTK_KEYBOARD(self));
/* redraw pressed key */
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data);
}
g_list_free (list);
/* redraw locked key */
list = eek_keyboard_get_locked_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key);
}
g_list_free (list);
return FALSE;
}
@ -125,27 +162,52 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
}
static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time)
{
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_depress(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
if (key) {
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
}
}
static void drag(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time)
{
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
x, y, eek_renderer_get_transformation(priv->renderer), time, self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
if (key) {
GList *list, *head;
gboolean found = FALSE;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
if (head->data == key)
found = TRUE;
else {
eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
on_key_released(key, self);
}
}
g_list_free (list);
if (!found) {
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
}
}
}
static void release(EekGtkKeyboard *self, guint32 time)
{
static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, time, self);
GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (GList *head = list; head; head = g_list_next (head)) {
EekKey *key = EEK_KEY(head->data);
eek_keyboard_release_key(priv->keyboard, key, time);
on_key_released(key, self);
}
g_list_free (list);
}
static gboolean
@ -188,27 +250,27 @@ handle_touch_event (GtkWidget *widget,
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* For each new touch, release the previous one and record the new event
sequence. */
if (event->type == GDK_TOUCH_BEGIN) {
release(self, event->time);
if (priv->sequence) {
// Ignore second and following touch points
return FALSE;
}
priv->sequence = event->sequence;
depress(self, event->x, event->y, event->time);
return TRUE;
}
/* Only allow the latest touch point to be dragged. */
if (event->type == GDK_TOUCH_UPDATE && event->sequence == priv->sequence) {
if (priv->sequence != event->sequence) {
return FALSE;
}
if (event->type == GDK_TOUCH_UPDATE) {
drag(self, event->x, event->y, event->time);
}
else if (event->type == GDK_TOUCH_END || event->type == GDK_TOUCH_CANCEL) {
if (event->type == GDK_TOUCH_END || event->type == GDK_TOUCH_CANCEL) {
// TODO: can the event have different coords than the previous update event?
/* Only respond to the release of the latest touch point. Previous
touches have already been released. */
if (event->sequence == priv->sequence) {
release(self, event->time);
priv->sequence = NULL;
}
release(self, event->time);
priv->sequence = NULL;
}
return TRUE;
}
@ -220,21 +282,80 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->keyboard) {
squeek_layout_release_all_only(
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
gdk_event_get_time(NULL));
GList *list, *head;
/* Make a copy of HEAD before sending "released" signal on
elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released");
g_signal_emit_by_name (head->data, "released");
}
g_list_free (list);
}
GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self);
}
static gboolean
eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
gint x,
gint y,
gboolean keyboard_tooltip,
GtkTooltip *tooltip)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key;
key = eek_renderer_find_key_by_position (priv->renderer,
(gdouble)x,
(gdouble)y);
if (key) {
EekSymbol *symbol = eek_key_get_symbol (key);
const gchar *text = eek_symbol_get_tooltip (symbol);
if (text) {
gtk_tooltip_set_text (tooltip, text);
return TRUE;
}
}
return FALSE;
}
static void
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
priv->keyboard = g_object_ref (keyboard);
priv->key_locked_handler =
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
priv->key_unlocked_handler =
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
priv->symbol_index_changed_handler =
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
eek_gtk_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboard *keyboard;
switch (prop_id) {
case PROP_KEYBOARD:
keyboard = g_value_get_object (value);
eek_gtk_keyboard_set_keyboard (EEK_GTK_KEYBOARD(object), keyboard);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -250,16 +371,40 @@ eek_gtk_keyboard_dispose (GObject *object)
if (priv->renderer) {
g_object_unref (priv->renderer);
priv->renderer = NULL;
priv->renderer = NULL;
}
if (priv->keyboard) {
squeek_layout_release_all_only(
priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard,
gdk_event_get_time(NULL));
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_locked_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_locked_handler);
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_unlocked_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_unlocked_handler);
if (g_signal_handler_is_connected (priv->keyboard,
priv->symbol_index_changed_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->symbol_index_changed_handler);
GList *list, *head;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
g_signal_emit_by_name (head->data, "released", priv->keyboard);
}
g_list_free (list);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
if (priv->theme) {
g_object_unref (priv->theme);
priv->theme = NULL;
}
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
}
@ -268,6 +413,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
widget_class->realize = eek_gtk_keyboard_real_realize;
widget_class->unmap = eek_gtk_keyboard_real_unmap;
@ -279,15 +425,28 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
eek_gtk_keyboard_real_button_release_event;
widget_class->motion_notify_event =
eek_gtk_keyboard_real_motion_notify_event;
widget_class->query_tooltip =
eek_gtk_keyboard_real_query_tooltip;
widget_class->touch_event = handle_touch_event;
gobject_class->set_property = eek_gtk_keyboard_set_property;
gobject_class->dispose = eek_gtk_keyboard_dispose;
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
pspec);
}
static void
eek_gtk_keyboard_init (EekGtkKeyboard *self)
{}
{
/* void */
}
/**
* eek_gtk_keyboard_new:
@ -297,76 +456,180 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
* Returns: a #GtkWidget
*/
GtkWidget *
eek_gtk_keyboard_new (LevelKeyboard *keyboard)
eek_gtk_keyboard_new (EekKeyboard *keyboard)
{
EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
priv->keyboard = keyboard;
return GTK_WIDGET(ret);
return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
}
static void
render_pressed_button (GtkWidget *widget,
struct button_place *place)
magnify_bounds (GtkWidget *self,
EekBounds *bounds,
EekBounds *large_bounds,
gdouble scale)
{
GtkAllocation allocation;
gdouble x, y;
g_assert (scale >= 1.0);
gtk_widget_get_allocation (self, &allocation);
large_bounds->width = bounds->width * scale;
large_bounds->height = bounds->height * scale;
x = bounds->x - (large_bounds->width - bounds->width) / 2;
y = bounds->y - large_bounds->height;
large_bounds->x = CLAMP(x, 0, allocation.width - large_bounds->width);
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
}
/*
* Alleviate the asymmetry between drawing a pressed key and a released key,
* and consistently draw to the exact same area.
*
* By saving the dirty rectangle we can limit drawing of the backbuffer to
* the screen as well, eg gdk_window_invalidate_rect() instead of
* gtk_widget_queue_draw() which redraws the entire widget.
*
* b1 is mandatory, b2 is optional
*/
static GdkRectangle
clip_bounds_to_dirty_rectangle (cairo_t *cr, EekBounds *b1, EekBounds *b2)
{
if (b2)
cairo_rectangle (cr, b2->x, b2->y, b2->width, b2->height);
cairo_rectangle (cr, b1->x, b1->y, b1->width, b1->height);
cairo_clip (cr);
/*
* save the clipped region to a bounding box so we can limit
* the drawing of the backbuffer to the screen to the same area
*/
cairo_rectangle_t bbox;
cairo_clip_extents (cr, &bbox.x, &bbox.y, &bbox.width, &bbox.height);
/* convert double to int, making sure r strictly covers bbox to avoid
* artefacts. floor() is unnecessary, ceil() is not */
GdkRectangle r = {
floor (bbox.x),
floor (bbox.y),
ceil (bbox.width),
ceil (bbox.height)
};
return r;
}
static void
render_pressed_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
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_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
/*
* clip to limit drawing to backbuffer and save clip region to dirty_rect
* to limit redrawing of the backbuffer to the same area
*/
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, &large_bounds);
cairo_save (cr);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
/*
cairo_save (cr);
cairo_translate (cr, large_bounds.x, large_bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_restore (cr);
*/
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
/* force immediate drawing of the backbuffer to the screen */
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
}
void
eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
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);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
// TODO: does it really redraw the entire keyboard?
static void
render_released_button (GtkWidget *widget,
const struct squeek_button *button)
render_locked_key (GtkWidget *widget,
EekKey *key)
{
(void)button;
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds;
GdkWindow *window = gtk_widget_get_window (widget);
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_get_key_bounds (priv->renderer, key, &bounds, TRUE);
/*
* clip to limit drawing to backbuffer and save clip region to dirty_rect
* to limit redrawing of the backbuffer to the same area
*/
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, NULL);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
/* force immediate drawing of the backbuffer to the screen */
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
}
static void
render_released_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
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_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
/*
* clip to limit drawing to backbuffer and save clip region to dirty_rect
* to limit redrawing of the backbuffer to the same area
*/
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle(cr, &bounds, &large_bounds);
eek_renderer_render_keyboard (priv->renderer, cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
/* force immediate drawing of the backbuffer to the screen */
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
}
void
eek_gtk_on_button_pressed (struct button_place place,
EekGtkKeyboard *self)
static void
on_key_pressed (EekKey *key,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -374,11 +637,7 @@ eek_gtk_on_button_pressed (struct button_place place,
if (!priv->renderer)
return;
if (!place.row) {
return;
}
render_pressed_button (GTK_WIDGET(self), &place);
gtk_widget_queue_draw (GTK_WIDGET(self));
render_pressed_key (GTK_WIDGET(self), key);
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -389,20 +648,17 @@ eek_gtk_on_button_pressed (struct button_place place,
#endif
}
void
eek_gtk_on_button_released (const struct squeek_button *button,
struct squeek_view *view,
EekGtkKeyboard *self)
static void
on_key_released (EekKey *key,
EekGtkKeyboard *self)
{
(void)view;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_button (GTK_WIDGET(self), button);
gtk_widget_queue_draw (GTK_WIDGET(self));
render_released_key (GTK_WIDGET(self), key);
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -412,3 +668,55 @@ eek_gtk_on_button_released (const struct squeek_button *button,
NULL);
#endif
}
static void
on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_locked_key (widget, key);
}
static void
on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_key (widget, key);
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
GtkWidget *widget = user_data;
gtk_widget_queue_draw (widget);
}
void
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
g_return_if_fail (EEK_IS_THEME(theme));
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard);
priv->theme = g_object_ref (theme);
}

View File

@ -28,7 +28,7 @@
#include <glib.h>
#include <gtk/gtk.h>
typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs
#include "eek-keyboard.h"
G_BEGIN_DECLS
#define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type())
@ -45,7 +45,9 @@ struct _EekGtkKeyboardClass
};
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard);
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */

118
eek/eek-gtk-renderer.c Normal file
View File

@ -0,0 +1,118 @@
/*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "eek-gtk-renderer.h"
#include "eek-key.h"
G_DEFINE_TYPE (EekGtkRenderer, eek_gtk_renderer, EEK_TYPE_RENDERER);
static cairo_surface_t *
pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
{
cairo_surface_t *dummy_surface;
cairo_pattern_t *pattern;
cairo_surface_t *surface;
cairo_t *cr;
dummy_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cr = cairo_create (dummy_surface);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
pattern = cairo_get_source (cr);
cairo_pattern_get_surface (pattern, &surface);
cairo_surface_reference (surface);
cairo_destroy (cr);
cairo_surface_destroy (dummy_surface);
return surface;
}
static cairo_surface_t *
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
const gchar *icon_name,
gint size)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
cairo_surface_t *surface;
gchar *path = g_strconcat("/sm/puri/squeekboard/icons/", icon_name, ".svg", NULL);
pixbuf = gdk_pixbuf_new_from_resource_at_scale (path, size, size,
TRUE, &error);
if (pixbuf != NULL)
goto found;
else {
/* g_warning ("can't get icon pixbuf for %s: %s", path, error->message);*/
g_error_free (error);
error = NULL;
}
g_free(path);
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
icon_name,
size,
0,
&error);
if (pixbuf == NULL) {
g_warning ("can't get icon pixbuf for %s: %s",
icon_name,
error->message);
g_error_free (error);
return NULL;
}
found:
surface = pixbuf_to_cairo_surface (pixbuf);
g_object_unref (pixbuf);
return surface;
}
static void
eek_gtk_renderer_class_init (EekGtkRendererClass *klass)
{
EekRendererClass *renderer_class = EEK_RENDERER_CLASS (klass);
renderer_class->get_icon_surface = eek_gtk_renderer_real_get_icon_surface;
}
static void
eek_gtk_renderer_init (EekGtkRenderer *self)
{
}
EekRenderer *
eek_gtk_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
GtkWidget *widget)
{
return g_object_new (EEK_TYPE_GTK_RENDERER,
"keyboard", keyboard,
"pango-context", pcontext,
NULL);
}

61
eek/eek-gtk-renderer.h Normal file
View File

@ -0,0 +1,61 @@
/*
* 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_RENDERER_H
#define EEK_GTK_RENDERER_H 1
#include <gtk/gtk.h>
#include "eek-renderer.h"
G_BEGIN_DECLS
#define EEK_TYPE_GTK_RENDERER (eek_gtk_renderer_get_type())
#define EEK_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRenderer))
#define EEK_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
#define EEK_IS_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_GTK_RENDERER))
#define EEK_IS_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_GTK_RENDERER))
#define EEK_GTK_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
typedef struct _EekGtkRenderer EekGtkRenderer;
typedef struct _EekGtkRendererClass EekGtkRendererClass;
typedef struct _EekGtkRendererPrivate EekGtkRendererPrivate;
struct _EekGtkRenderer {
EekRenderer parent;
EekGtkRendererPrivate *priv;
};
struct _EekGtkRendererClass
{
EekRendererClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_gtk_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_gtk_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
GtkWidget *widget);
G_END_DECLS
#endif /* EEK_GTK_RENDERER_H */

26
eek/eek-gtk.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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 */

613
eek/eek-key.c Normal file
View File

@ -0,0 +1,613 @@
/*
* 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
*/
/**
* SECTION:eek-key
* @short_description: Base class of a key
*
* The #EekKeyClass class represents a key.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-key.h"
#include "eek-section.h"
#include "eek-keyboard.h"
#include "eek-symbol.h"
enum {
PROP_0,
PROP_KEYCODE,
PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OREF,
PROP_LAST
};
enum {
LOCKED,
UNLOCKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekKeyPrivate
{
guint keycode;
EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
gulong oref; // UI outline reference
gboolean is_pressed;
gboolean is_locked;
} EekKeyPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekKey, eek_key, EEK_TYPE_ELEMENT)
static void
eek_key_real_locked (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = TRUE;
#if DEBUG
g_debug ("locked %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_real_unlocked (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = FALSE;
#if DEBUG
g_debug ("unlocked %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_finalize (GObject *object)
{
EekKey *self = EEK_KEY (object);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
eek_symbol_matrix_free (priv->symbol_matrix);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
static void
eek_key_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekSymbolMatrix *matrix;
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
break;
case PROP_SYMBOL_MATRIX:
matrix = g_value_get_boxed (value);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), g_value_get_int (value), row);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break;
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_key_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
break;
case PROP_SYMBOL_MATRIX:
g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object)));
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, column);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row);
break;
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_key_class_init (EekKeyClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_key_set_property;
gobject_class->get_property = eek_key_get_property;
gobject_class->finalize = eek_key_finalize;
/* signals */
klass->locked = eek_key_real_locked;
klass->unlocked = eek_key_real_unlocked;
/**
* EekKey:keycode:
*
* The keycode of #EekKey.
*/
pspec = g_param_spec_uint ("keycode",
"Keycode",
"Keycode of the key",
0, G_MAXUINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_KEYCODE, pspec);
/**
* EekKey:symbol-matrix:
*
* The symbol matrix of #EekKey.
*/
pspec = g_param_spec_boxed ("symbol-matrix",
"Symbol matrix",
"Symbol matrix of the key",
EEK_TYPE_SYMBOL_MATRIX,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
/**
* EekKey:column:
*
* The column index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("column",
"Column",
"Column index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_COLUMN, pspec);
/**
* EekKey:row:
*
* The row index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("row",
"Row",
"Row index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/**
* EekKey:oref:
*
* The outline id of #EekKey.
*/
pspec = g_param_spec_ulong ("oref",
"Oref",
"Outline id of the key",
0, G_MAXULONG, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OREF, pspec);
/**
* EekKey::locked:
* @key: an #EekKey
*
* The ::locked signal is emitted each time @key is shifted to
* the locked state. The class handler runs before signal
* handlers to allow signal handlers to read the status of @key
* with eek_key_is_locked().
*/
signals[LOCKED] =
g_signal_new (I_("locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekKeyClass, locked),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* EekKey::unlocked:
* @key: an #EekKey
*
* The ::unlocked signal is emitted each time @key is shifted to
* the unlocked state.
*/
signals[UNLOCKED] =
g_signal_new (I_("unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyClass, unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eek_key_init (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
}
/**
* eek_key_set_keycode:
* @key: an #EekKey
* @keycode: keycode
*
* Set the keycode of @key to @keycode. Since typically the keycode
* value is used to find a key in a keyboard by calling
* eek_keyboard_find_key_by_keycode, it is not necessarily the same as
* the X keycode but it should be unique in the keyboard @key belongs
* to.
*/
void
eek_key_set_keycode (EekKey *key,
guint keycode)
{
g_return_if_fail (EEK_IS_KEY (key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->keycode = keycode;
}
/**
* eek_key_get_keycode:
* @key: an #EekKey
*
* Get keycode of @key.
* Returns: keycode or %EEK_INVALID_KEYCODE on failure
*/
guint
eek_key_get_keycode (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), EEK_INVALID_KEYCODE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->keycode;
}
/**
* eek_key_set_symbol_matrix:
* @key: an #EekKey
* @matrix: an #EekSymbolMatrix
*
* Set the symbol matrix of @key to @matrix.
*/
void
eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
eek_symbol_matrix_free (priv->symbol_matrix);
priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
}
/**
* eek_key_get_symbol_matrix:
* @key: an #EekKey
*
* Get the symbol matrix of @key.
* Returns: (transfer none): #EekSymbolMatrix or %NULL
*/
EekSymbolMatrix *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->symbol_matrix;
}
/**
* eek_key_get_symbol:
* @key: an #EekKey
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol (EekKey *key)
{
return eek_key_get_symbol_with_fallback (key, 0, 0);
}
/**
* eek_key_get_symbol_with_fallback:
* @key: an #EekKey
* @fallback_group: fallback group index
* @fallback_level: fallback level index
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol_with_fallback (EekKey *key,
gint fallback_group,
gint fallback_level)
{
gint group, level;
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
eek_element_get_symbol_index (EEK_ELEMENT(key), &group, &level);
if (group < 0 || level < 0) {
EekElement *section;
section = eek_element_get_parent (EEK_ELEMENT(key));
g_return_val_if_fail (EEK_IS_SECTION (section), NULL);
if (group < 0)
group = eek_element_get_group (section);
if (level < 0)
level = eek_element_get_level (section);
if (group < 0 || level < 0) {
EekElement *keyboard;
keyboard = eek_element_get_parent (section);
g_return_val_if_fail (EEK_IS_KEYBOARD (keyboard), NULL);
if (group < 0)
group = eek_element_get_group (keyboard);
if (level < 0)
level = eek_element_get_level (keyboard);
}
}
return eek_key_get_symbol_at_index (key,
group,
level,
fallback_group,
fallback_level);
}
/**
* eek_key_get_symbol_at_index:
* @key: an #EekKey
* @group: group index of the symbol matrix
* @level: level index of the symbol matrix
* @fallback_group: fallback group index
* @fallback_level: fallback level index
*
* Get the symbol at (@group, @level) in the symbol matrix of @key.
* Return value: (transfer none): an #EekSymbol at (@group, @level), or %NULL
*/
EekSymbol *
eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level)
{
EekKeyPrivate *priv = eek_key_get_instance_private (key);
gint num_symbols;
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
if (group < 0)
group = fallback_group;
if (level < 0)
level = fallback_level;
if (!priv->symbol_matrix)
return NULL;
num_symbols = priv->symbol_matrix->num_groups *
priv->symbol_matrix->num_levels;
if (num_symbols == 0)
return NULL;
if (group >= priv->symbol_matrix->num_groups) {
if (fallback_group < 0)
return NULL;
group = fallback_group;
}
if (level >= priv->symbol_matrix->num_levels) {
if (fallback_level < 0)
return NULL;
level = fallback_level;
}
return priv->symbol_matrix->data[group * priv->symbol_matrix->num_levels +
level];
}
/**
* eek_key_set_index:
* @key: an #EekKey
* @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection
*
* Set the location of @key in #EekSection with @column and @row.
*/
void
eek_key_set_index (EekKey *key,
gint column,
gint row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (0 <= column);
g_return_if_fail (0 <= row);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->column != column) {
priv->column = column;
g_object_notify (G_OBJECT(key), "column");
}
if (priv->row != row) {
priv->row = row;
g_object_notify (G_OBJECT(key), "row");
}
}
/**
* eek_key_get_index:
* @key: an #EekKey
* @column: (allow-none): pointer where the column index of @key in #EekSection will be stored
* @row: (allow-none): pointer where the row index of @key in #EekSection will be stored
*
* Get the location of @key in #EekSection.
*/
void
eek_key_get_index (EekKey *key,
gint *column,
gint *row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (column != NULL || row != NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (column != NULL)
*column = priv->column;
if (row != NULL)
*row = priv->row;
}
/**
* eek_key_set_oref:
* @key: an #EekKey
* @oref: outline id of @key
*
* Set the outline id of @key to @oref.
*/
void
eek_key_set_oref (EekKey *key,
guint oref)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->oref != oref) {
priv->oref = oref;
g_object_notify (G_OBJECT(key), "oref");
}
}
/**
* eek_key_get_oref:
* @key: an #EekKey
*
* Get the outline id of @key.
* Returns: unsigned integer
*/
guint
eek_key_get_oref (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), 0);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->oref;
}
/**
* eek_key_is_pressed:
* @key: an #EekKey
*
* Return %TRUE if key is marked as pressed.
*/
gboolean
eek_key_is_pressed (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_pressed;
}
/**
* eek_key_is_locked:
* @key: an #EekKey
*
* Return %TRUE if key is marked as locked.
*/
gboolean
eek_key_is_locked (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_locked;
}
void eek_key_set_pressed(EekKey *key, gboolean value)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->is_pressed = value;
}

93
eek/eek-key.h Normal file
View File

@ -0,0 +1,93 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_KEY_H
#define EEK_KEY_H 1
#include "eek-element.h"
#include "eek-symbol-matrix.h"
G_BEGIN_DECLS
#define EEK_TYPE_KEY (eek_key_get_type())
G_DECLARE_DERIVABLE_TYPE(EekKey, eek_key, EEK, KEY, EekElement)
/**
* EekKeyClass:
* @pressed: class handler for #EekKey::pressed signal
* @released: class handler for #EekKey::released signal
* @locked: class handler for #EekKey::locked signal
* @unlocked: class handler for #EekKey::unlocked signal
* @cancelled: class handler for #EekKey::cancelled signal
* @is_pressed: virtual function for getting whether the key is pressed
* @is_locked: virtual function for getting whether the key is locked
*/
struct _EekKeyClass
{
/*< private >*/
EekElementClass parent_class;
/*< public >*/
/* signals */
void (* locked) (EekKey *key);
void (* unlocked) (EekKey *key);
};
GType eek_key_get_type (void) G_GNUC_CONST;
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key,
gint fallback_group,
gint fallback_level);
EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level);
void eek_key_set_index (EekKey *key,
gint column,
gint row);
void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_oref (EekKey *key,
guint oref);
guint eek_key_get_oref (EekKey *key);
gboolean eek_key_is_pressed (EekKey *key);
gboolean eek_key_is_locked (EekKey *key);
void eek_key_set_pressed (EekKey *key,
gboolean value);
G_END_DECLS
#endif /* EEK_KEY_H */

219
eek/eek-keyboard-drawing.c Normal file
View File

@ -0,0 +1,219 @@
/*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_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);
}

View File

@ -1,17 +1,17 @@
/*
/*
* 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
@ -27,38 +27,771 @@
* of one or more sections of the #EekSectionClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#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"
#endif /* HAVE_CONFIG_H */
#include "eek-keyboard.h"
#include "eek-marshalers.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
void level_keyboard_deinit(LevelKeyboard *self) {
squeek_layout_free(self->layout);
}
enum {
PROP_0,
PROP_LAYOUT,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST
};
void level_keyboard_free(LevelKeyboard *self) {
level_keyboard_deinit(self);
g_free(self);
}
enum {
KEY_RELEASED,
KEY_LOCKED,
KEY_UNLOCKED,
LAST_SIGNAL
};
void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) {
self->layout = layout;
}
enum {
VIEW_LETTERS_LOWER,
VIEW_LETTERS_UPPER,
VIEW_NUMBERS,
VIEW_SYMBOLS
};
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout) {
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
level_keyboard_init(keyboard, layout);
keyboard->manager = manager;
return keyboard;
}
static guint signals[LAST_SIGNAL] = { 0, };
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
struct _EekKeyboardPrivate
{
return squeek_layout_get_current_view(keyboard->layout);
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
unsigned int old_level;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
GHashTable *names;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
EekModifierType alt_gr_mask;
};
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
EekModifierKey *
eek_modifier_key_copy (EekModifierKey *modkey)
{
return g_slice_dup (EekModifierKey, modkey);
}
void
eek_modifier_key_free (EekModifierKey *modkey)
{
g_object_unref (modkey->key);
g_slice_free (EekModifierKey, modkey);
}
static void
on_key_locked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit (keyboard, signals[KEY_LOCKED], 0, key);
}
static void
on_key_unlocked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit (keyboard, signals[KEY_UNLOCKED], 0, key);
}
static void
on_symbol_index_changed (EekSection *section,
gint group,
gint level,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "symbol-index-changed", group, level);
}
static void
section_child_added_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_insert (keyboard->priv->names,
(gpointer)name,
element);
}
static void
section_child_removed_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_remove (keyboard->priv->names,
name);
}
static EekSection *
eek_keyboard_real_create_section (EekKeyboard *self)
{
EekSection *section;
section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL);
g_signal_connect (G_OBJECT(section), "child-added",
G_CALLBACK(section_child_added_cb), self);
g_signal_connect (G_OBJECT(section), "child-removed",
G_CALLBACK(section_child_removed_cb), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
return section;
}
static void
eek_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
switch (prop_id) {
case PROP_LAYOUT:
priv->layout = g_value_get_object (value);
if (priv->layout)
g_object_ref (priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_keyboard_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
switch (prop_id) {
case PROP_LAYOUT:
g_value_set_object (value, priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
g_value_set_enum (value,
eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_level_from_modifiers (EekKeyboard *self, EekKey *key)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
/* Use the numbers/letters bit from the old level */
gint level = priv->old_level & 2;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123") == 0)
level ^= 2;
}
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
switch (priv->old_level) {
case VIEW_LETTERS_UPPER:
{
/* Redirect upper case letters to numbers instead of symbols, clearing
the shift modifier to keep the modifiers in sync with the level */
if (level == VIEW_SYMBOLS) {
level = VIEW_NUMBERS;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_SYMBOLS:
{
/* Redirect symbols to lower case letters instead of upper case,
clearing the shift modifier to keep the modifiers in sync with the
level */
if (level == VIEW_LETTERS_UPPER) {
level = VIEW_LETTERS_LOWER;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
case VIEW_NUMBERS:
default:
break;
}
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
else
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
priv->old_level = level;
eek_element_set_level (EEK_ELEMENT(self), level);
}
static void
set_modifiers_with_key (EekKeyboard *self,
EekKey *key,
EekModifierType modifiers)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
EekModifierType enabled = (priv->modifiers ^ modifiers) & modifiers;
EekModifierType disabled = (priv->modifiers ^ modifiers) & priv->modifiers;
if (enabled != 0) {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = enabled;
modifier_key->key = g_object_ref (key);
priv->locked_keys =
g_list_prepend (priv->locked_keys, modifier_key);
g_signal_emit_by_name (modifier_key->key, "locked");
}
} else {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
GList *head;
for (head = priv->locked_keys; head; ) {
EekModifierKey *modifier_key = head->data;
if (modifier_key->modifiers & disabled) {
GList *next = g_list_next (head);
priv->locked_keys =
g_list_remove_link (priv->locked_keys, head);
g_signal_emit_by_name (modifier_key->key, "unlocked");
g_list_free1 (head);
head = next;
} else
head = g_list_next (head);
}
}
}
priv->modifiers = modifiers;
}
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
eek_key_set_pressed(key, TRUE);
priv->pressed_keys = g_list_prepend (priv->pressed_keys, key);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
set_level_from_modifiers (keyboard, key);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key);
EekModifierType modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
}
void eek_keyboard_release_key( EekKeyboard *keyboard,
EekKey *key,
guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
for (GList *head = priv->pressed_keys; head; head = g_list_next (head)) {
if (head->data == key) {
priv->pressed_keys = g_list_remove_link (priv->pressed_keys, head);
g_list_free1 (head);
break;
}
}
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
switch (priv->modifier_behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
if (modifier)
set_modifiers_with_key (keyboard, key, priv->modifiers ^ modifier);
else
set_modifiers_with_key (keyboard, key,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard, key);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
}
static void
eek_keyboard_dispose (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
if (priv->layout) {
g_object_unref (priv->layout);
priv->layout = NULL;
}
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
}
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
guint i;
g_list_free (priv->pressed_keys);
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->names);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (priv->outline_array, TRUE);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
static void
eek_keyboard_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "key-locked",
G_CALLBACK(on_key_locked), self);
g_signal_connect (element, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (element, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
eek_keyboard_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_key_locked, self);
g_signal_handlers_disconnect_by_func (element, on_key_unlocked, self);
}
static void
eek_keyboard_class_init (EekKeyboardClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->create_section = eek_keyboard_real_create_section;
/* signals */
container_class->child_added = eek_keyboard_real_child_added;
container_class->child_removed = eek_keyboard_real_child_removed;
gobject_class->get_property = eek_keyboard_get_property;
gobject_class->set_property = eek_keyboard_set_property;
gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/**
* EekKeyboard:layout:
*
* The layout used to create this #EekKeyboard.
*/
pspec = g_param_spec_object ("layout",
"Layout",
"Layout used to create the keyboard",
EEK_TYPE_LAYOUT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LAYOUT,
pspec);
/**
* EekKeyboard:modifier-behavior:
*
* The modifier handling mode of #EekKeyboard.
*/
pspec = g_param_spec_enum ("modifier-behavior",
"Modifier behavior",
"Modifier handling mode of the keyboard",
EEK_TYPE_MODIFIER_BEHAVIOR,
EEK_MODIFIER_BEHAVIOR_NONE,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_MODIFIER_BEHAVIOR,
pspec);
/**
* EekKeyboard::key-locked:
* @keyboard: an #EekKeyboard
* @key: an #EekKey
*
* The ::key-locked signal is emitted each time a key in @keyboard
* is shifted to the locked state.
*/
signals[KEY_LOCKED] =
g_signal_new (I_("key-locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_locked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
/**
* EekKeyboard::key-unlocked:
* @keyboard: an #EekKeyboard
* @key: an #EekKey
*
* The ::key-unlocked signal is emitted each time a key in @keyboard
* is shifted to the unlocked state.
*/
signals[KEY_UNLOCKED] =
g_signal_new (I_("key-unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
}
static void
eek_keyboard_init (EekKeyboard *self)
{
self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
}
/**
* eek_keyboard_create_section:
* @keyboard: an #EekKeyboard
*
* Create an #EekSection instance and append it to @keyboard. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
EekSection *
eek_keyboard_create_section (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return EEK_KEYBOARD_GET_CLASS(keyboard)->create_section (keyboard);
}
/**
* eek_keyboard_find_key_by_name:
* @keyboard: an #EekKeyboard
* @name: a key name
*
* Find an #EekKey whose name is @name.
* Return value: (transfer none): #EekKey whose name is @name
*/
EekKey *
eek_keyboard_find_key_by_name (EekKeyboard *keyboard,
const gchar *name)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_hash_table_lookup (keyboard->priv->names,
name);
}
/**
* eek_keyboard_get_layout:
* @keyboard: an #EekKeyboard
*
* Get the layout used to create @keyboard.
* Returns: an #EekLayout
*/
EekLayout *
eek_keyboard_get_layout (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return keyboard->priv->layout;
}
/**
* eek_keyboard_get_size:
* @keyboard: an #EekKeyboard
* @width: width of @keyboard
* @height: height of @keyboard
*
* Get the size of @keyboard.
*/
void
eek_keyboard_get_size (EekKeyboard *keyboard,
gdouble *width,
gdouble *height)
{
EekBounds bounds;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
*width = bounds.width;
*height = bounds.height;
}
/**
* eek_keyboard_set_modifier_behavior:
* @keyboard: an #EekKeyboard
* @modifier_behavior: modifier behavior of @keyboard
*
* Set the modifier handling mode of @keyboard.
*/
void
eek_keyboard_set_modifier_behavior (EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifier_behavior = modifier_behavior;
}
/**
* eek_keyboard_get_modifier_behavior:
* @keyboard: an #EekKeyboard
*
* Get the modifier handling mode of @keyboard.
* Returns: #EekModifierBehavior
*/
EekModifierBehavior
eek_keyboard_get_modifier_behavior (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifier_behavior;
}
void
eek_keyboard_set_modifiers (EekKeyboard *keyboard,
EekModifierType modifiers)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifiers = modifiers;
set_level_from_modifiers (keyboard, NULL);
}
/**
* eek_keyboard_get_modifiers:
* @keyboard: an #EekKeyboard
*
* Get the current modifier status of @keyboard.
* Returns: #EekModifierType
*/
EekModifierType
eek_keyboard_get_modifiers (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifiers;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned integer ID of the registered outline, for
* later reference
*/
guint
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekOutline *_outline;
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
_outline = eek_outline_copy (outline);
g_array_append_val (keyboard->priv->outline_array, *_outline);
/* don't use eek_outline_free here, so as to keep _outline->points */
g_slice_free (EekOutline, _outline);
return keyboard->priv->outline_array->len - 1;
}
/**
* eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard
* @oref: ID of the outline
*
* Get an outline associated with @oref in @keyboard.
* Returns: an #EekOutline, which should not be released
*/
EekOutline *
eek_keyboard_get_outline (EekKeyboard *keyboard,
guint oref)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
if (oref > keyboard->priv->outline_array->len)
return NULL;
return &g_array_index (keyboard->priv->outline_array, EekOutline, oref);
}
/**
* eek_keyboard_get_n_outlines:
* @keyboard: an #EekKeyboard
*
* Get the number of outlines defined in @keyboard.
* Returns: integer
*/
gsize
eek_keyboard_get_n_outlines (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->outline_array->len;
}
/**
* eek_keyboard_set_num_lock_mask:
* @keyboard: an #EekKeyboard
* @num_lock_mask: an #EekModifierType
*
* Set modifier mask used as Num_Lock.
*/
void
eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard,
EekModifierType num_lock_mask)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->num_lock_mask = num_lock_mask;
}
/**
* eek_keyboard_get_num_lock_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Num_Lock.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->num_lock_mask;
}
/**
* eek_keyboard_set_alt_gr_mask:
* @keyboard: an #EekKeyboard
* @alt_gr_mask: an #EekModifierType
*
* Set modifier mask used as Alt_Gr.
*/
void
eek_keyboard_set_alt_gr_mask (EekKeyboard *keyboard,
EekModifierType alt_gr_mask)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->alt_gr_mask = alt_gr_mask;
}
/**
* eek_keyboard_get_alt_gr_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Alt_Gr.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_alt_gr_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->alt_gr_mask;
}
/**
* eek_keyboard_get_pressed_keys:
* @keyboard: an #EekKeyboard
*
* Get pressed keys.
* Returns: (transfer container) (element-type EekKey): A list of
* pressed keys.
*/
GList *
eek_keyboard_get_pressed_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->pressed_keys);
}
/**
* eek_keyboard_get_locked_keys:
* @keyboard: an #EekKeyboard
*
* Get locked keys.
* Returns: (transfer container) (element-type Eek.ModifierKey): A list
* of locked keys.
*/
GList *
eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->locked_keys);
}

View File

@ -27,32 +27,172 @@
#include <glib-object.h>
#include <xkbcommon/xkbcommon.h>
#include "eek-container.h"
#include "eek-types.h"
#include "eek-layout.h"
#include "src/layout.h"
G_BEGIN_DECLS
/// Keyboard state holder
struct _LevelKeyboard {
struct squeek_layout *layout; // owned
#define EEK_TYPE_KEYBOARD (eek_keyboard_get_type())
#define EEK_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_KEYBOARD, EekKeyboard))
#define EEK_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_KEYBOARD, EekKeyboardClass))
#define EEK_IS_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_KEYBOARD))
#define EEK_IS_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_KEYBOARD))
#define EEK_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_KEYBOARD, EekKeyboardClass))
typedef struct _EekKeyboardClass EekKeyboardClass;
typedef struct _EekKeyboardPrivate EekKeyboardPrivate;
/**
* EekKeyboard:
*
* Contains the state of the physical keyboard.
*
* Is also a graphical element...
*
* The #EekKeyboard structure contains only private data and should
* only be accessed using the provided API.
*/
struct _EekKeyboard
{
/*< private >*/
EekContainer parent;
EekKeyboardPrivate *priv;
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
guint id; // as a key to layout choices
EekboardContextService *manager; // unowned reference
};
typedef struct _LevelKeyboard LevelKeyboard;
gchar * eek_keyboard_get_keymap
(LevelKeyboard *keyboard);
/**
* EekKeyboardClass:
* @create_section: virtual function for creating a section
* @find_key_by_name: virtual function for finding a key in the
* keyboard by name
* @key_pressed: class handler for #EekKeyboard::key-pressed signal
* @key_released: class handler for #EekKeyboard::key-released signal
* @key_locked: class handler for #EekKeyboard::key-locked signal
* @key_unlocked: class handler for #EekKeyboard::key-unlocked signal
* @key_cancelled: class handler for #EekKeyboard::key-cancelled signal
*/
struct _EekKeyboardClass
{
/*< private >*/
EekContainerClass parent_class;
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard);
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout);
void level_keyboard_deinit(LevelKeyboard *self);
void level_keyboard_free(LevelKeyboard *self);
/* obsolete members moved to EekElement */
gpointer set_symbol_index;
gpointer get_symbol_index;
/*< public >*/
EekSection *(* create_section) (EekKeyboard *self);
EekKey *(* find_key_by_name) (EekKeyboard *self,
const gchar *name);
/*< private >*/
/* obsolete members moved to EekElement */
gpointer symbol_index_changed;
/*< public >*/
/* signals */
void (* key_locked) (EekKeyboard *self,
EekKey *key);
void (* key_unlocked) (EekKeyboard *self,
EekKey *key);
/*< private >*/
/* padding */
gpointer pdummy[21];
};
/**
* EekModifierKey:
* @modifiers: an #EekModifierType which @key triggers
* @key: an #EekKey
*
* Entry which associates modifier mask to a key. This is returned by
* eek_keyboard_get_locked_keys().
*/
struct _EekModifierKey {
/*< public >*/
EekModifierType modifiers;
EekKey *key;
};
typedef struct _EekModifierKey EekModifierKey;
EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
GType eek_keyboard_get_type
(void) G_GNUC_CONST;
EekLayout *eek_keyboard_get_layout
(EekKeyboard *keyboard);
void eek_keyboard_get_size
(EekKeyboard *keyboard,
gdouble *width,
gdouble *height);
void eek_keyboard_set_size
(EekKeyboard *keyboard,
gdouble width,
gdouble height);
void eek_keyboard_set_modifier_behavior
(EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior);
EekModifierBehavior eek_keyboard_get_modifier_behavior
(EekKeyboard *keyboard);
void eek_keyboard_set_modifiers
(EekKeyboard *keyboard,
EekModifierType modifiers);
EekModifierType eek_keyboard_get_modifiers
(EekKeyboard *keyboard);
EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_name
(EekKeyboard *keyboard,
const gchar *name);
guint eek_keyboard_add_outline
(EekKeyboard *keyboard,
EekOutline *outline);
EekOutline *eek_keyboard_get_outline
(EekKeyboard *keyboard,
guint oref);
gsize eek_keyboard_get_n_outlines
(EekKeyboard *keyboard);
void eek_keyboard_set_num_lock_mask
(EekKeyboard *keyboard,
EekModifierType num_lock_mask);
EekModifierType eek_keyboard_get_num_lock_mask
(EekKeyboard *keyboard);
void eek_keyboard_set_alt_gr_mask
(EekKeyboard *keyboard,
EekModifierType alt_gr_mask);
EekModifierType eek_keyboard_get_alt_gr_mask
(EekKeyboard *keyboard);
GList *eek_keyboard_get_pressed_keys
(EekKeyboard *keyboard);
GList *eek_keyboard_get_locked_keys
(EekKeyboard *keyboard);
EekModifierKey *eek_modifier_key_copy
(EekModifierKey *modkey);
void eek_modifier_key_free
(EekModifierKey *modkey);
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

350
eek/eek-keysym.c Normal file
View File

@ -0,0 +1,350 @@
/*
* 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
*/
/**
* SECTION:eek-keysym
* @short_description: an #EekSymbol represents an X keysym
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <stdlib.h>
#include "eek-keysym.h"
#include "eek-serializable.h"
/* modifier keys */
#define EEK_KEYSYM_Shift_L 0xffe1
#define EEK_KEYSYM_Shift_R 0xffe2
#define EEK_KEYSYM_ISO_Level3_Shift 0xfe03
#define EEK_KEYSYM_Caps_Lock 0xffe5
#define EEK_KEYSYM_Shift_Lock 0xffe6
#define EEK_KEYSYM_Control_L 0xffe3
#define EEK_KEYSYM_Control_R 0xffe4
#define EEK_KEYSYM_Alt_L 0xffe9
#define EEK_KEYSYM_Alt_R 0xffea
#define EEK_KEYSYM_Meta_L 0xffe7
#define EEK_KEYSYM_Meta_R 0xffe8
#define EEK_KEYSYM_Super_L 0xffeb
#define EEK_KEYSYM_Super_R 0xffec
#define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee
typedef struct _EekKeysymPrivate
{
guint xkeysym;
} EekKeysymPrivate;
struct _EekKeysymEntry {
guint xkeysym;
const gchar *name;
EekSymbolCategory category;
};
typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-special-keysym-entries.h"
#include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h"
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekKeysym)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
eek_keysym_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->xkeysym);
}
static gsize
eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->xkeysym);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keysym_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keysym_real_serialize;
iface->deserialize = eek_keysym_real_deserialize;
}
static gchar *
unichar_to_utf8 (gunichar uc)
{
if (g_unichar_isgraph (uc)) {
gchar *buf;
gint len;
len = g_unichar_to_utf8 (uc, NULL);
buf = g_malloc0 (len + 1);
g_unichar_to_utf8 (uc, buf);
return buf;
}
return g_strdup ("");
}
static int
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
{
const EekKeysymEntry *entry0 = key0, *entry1 = key1;
return (gint) (entry0->xkeysym - entry1->xkeysym);
}
static EekKeysymEntry *
find_keysym_entry_by_xkeysym (guint xkeysym,
const EekKeysymEntry *entries,
gint num_entries)
{
EekKeysymEntry key;
key.xkeysym = xkeysym;
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
keysym_entry_compare_by_xkeysym);
}
static gboolean
get_unichar (guint xkeysym, gunichar *uc) {
/* Check for Latin-1 characters (1:1 mapping) */
if ((xkeysym >= 0x0020 && xkeysym <= 0x007e) ||
(xkeysym >= 0x00a0 && xkeysym <= 0x00ff)) {
*uc = xkeysym;
return TRUE;
}
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((xkeysym & 0xff000000) == 0x01000000) {
*uc = xkeysym & 0x00ffffff;
return TRUE;
}
return FALSE;
}
G_INLINE_FUNC EekModifierType
get_modifier_mask (guint xkeysym)
{
switch (xkeysym) {
case EEK_KEYSYM_Shift_L:
case EEK_KEYSYM_Shift_R:
case EEK_KEYSYM_Caps_Lock:
case EEK_KEYSYM_Shift_Lock:
return EEK_SHIFT_MASK;
case EEK_KEYSYM_ISO_Level3_Shift:
return EEK_BUTTON1_MASK;
case EEK_KEYSYM_Control_L:
case EEK_KEYSYM_Control_R:
return EEK_CONTROL_MASK;
case EEK_KEYSYM_Alt_L:
case EEK_KEYSYM_Alt_R:
return EEK_MOD1_MASK;
case EEK_KEYSYM_Meta_L:
case EEK_KEYSYM_Meta_R:
return EEK_META_MASK;
case EEK_KEYSYM_Super_L:
case EEK_KEYSYM_Super_R:
return EEK_SUPER_MASK;
case EEK_KEYSYM_Hyper_L:
case EEK_KEYSYM_Hyper_R:
return EEK_HYPER_MASK;
}
return 0;
}
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
/* void */
}
static void
eek_keysym_init (EekKeysym *self)
{
/* void */
}
/**
* eek_keysym_new_with_modifier:
* @xkeysym: an X keysym value
* @modifier_mask: modifier assigned to @xkeysym
*
* Create an #EekKeysym with given X keysym value @xkeysym and
* modifier @modifier_mask.
*/
EekKeysym *
eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask)
{
EekKeysym *keysym;
EekKeysymPrivate *priv;
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
EekSymbolCategory category;
gunichar uc;
special_entry =
find_keysym_entry_by_xkeysym (xkeysym,
special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
xkeysym_entry =
find_keysym_entry_by_xkeysym (xkeysym,
xkeysym_keysym_entries,
G_N_ELEMENTS(xkeysym_keysym_entries));
unicode_entry =
find_keysym_entry_by_xkeysym (xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
unichar_entry = NULL;
if (get_unichar (xkeysym, &uc)) {
unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
}
/* name and category */
name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else {
name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/* label */
if (special_entry)
label = g_strdup (special_entry->name);
else if (unichar_entry)
label = g_strdup (unichar_entry->name);
else if (unicode_entry)
label = g_strdup (unicode_entry->name);
else
label = g_strdup (name);
keysym = g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name);
g_free (label);
if (unichar_entry) {
g_free ((gpointer) unichar_entry->name);
g_slice_free (EekKeysymEntry, unichar_entry);
}
priv = eek_keysym_get_instance_private (keysym);
priv->xkeysym = xkeysym;
return keysym;
}
/**
* eek_keysym_new:
* @xkeysym: an X keysym value
*
* Create an #EekKeysym with given X keysym value @xkeysym.
*/
EekKeysym *
eek_keysym_new (guint xkeysym)
{
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym));
}
/**
* eek_keysym_new_from_name:
* @name: an X keysym name
*
* Create an #EekKeysym with an X keysym value looked up by @name.
*/
EekKeysym *
eek_keysym_new_from_name (const gchar *name)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
// g_warning ("can't find keysym entry for %s", name);
return g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", name,
"category", EEK_SYMBOL_CATEGORY_UNKNOWN,
"modifier-mask", 0,
NULL);
}
/**
* eek_keysym_get_xkeysym:
* @keysym: an #EekKeysym
*
* Get an X keysym value associated with @keysym
*/
guint
eek_keysym_get_xkeysym (EekKeysym *keysym)
{
EekKeysymPrivate *priv;
g_assert (EEK_IS_KEYSYM(keysym));
priv = eek_keysym_get_instance_private (keysym);
return priv->xkeysym;
}

58
eek/eek-keysym.h Normal file
View File

@ -0,0 +1,58 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_KEYSYM_H
#define EEK_KEYSYM_H 1
#include <X11/XKBlib.h>
#include "eek-symbol.h"
G_BEGIN_DECLS
/**
* EEK_INVALID_KEYSYM:
*
* Pseudo keysym used for error reporting.
*/
#define EEK_INVALID_KEYSYM (0)
#define EEK_TYPE_KEYSYM (eek_keysym_get_type())
G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
struct _EekKeysymClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_keysym_get_type (void) G_GNUC_CONST;
EekKeysym *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekKeysym *keysym);
EekKeysym *eek_keysym_new_from_name (const gchar *name);
EekKeysym *eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask);
G_END_DECLS
#endif /* EEK_KEYSYM_H */

View File

@ -26,12 +26,13 @@
* arranges keyboard elements.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-layout.h"
#include "eek-keyboard.h"
#include "eekboard/eekboard-context-service.h"
#include "eek-xml-layout.h"
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
@ -45,3 +46,26 @@ void
eek_layout_init (EekLayout *self)
{
}
/**
* eek_keyboard_new:
* @layout: an #EekLayout
* @initial_width: initial width of the keyboard
* @initial_height: initial height of the keyboard
*
* Create a new #EekKeyboard based on @layout.
*/
EekKeyboard *
eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height)
{
g_assert (EEK_IS_LAYOUT(layout));
g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (manager,
layout,
initial_width,
initial_height);
}

View File

@ -27,7 +27,6 @@
#include <glib-object.h>
#include "eek-types.h"
#include "src/layout.h"
G_BEGIN_DECLS
@ -44,7 +43,7 @@ struct _EekLayoutClass
GObjectClass parent_class;
/*< public >*/
LevelKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height);

1
eek/eek-marshalers.list Normal file
View File

@ -0,0 +1 @@
VOID:INT,INT

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,12 @@
#ifndef EEK_RENDERER_H
#define EEK_RENDERER_H 1
#include <gtk/gtk.h>
#include <pango/pangocairo.h>
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
#include "src/layout.h"
#include "eek-theme.h"
#include "eek-theme-context.h"
G_BEGIN_DECLS
@ -36,9 +37,19 @@ struct _EekRendererClass
{
GObjectClass parent_class;
void (* render_button) (EekRenderer *self,
void (* render_key_label) (EekRenderer *self,
PangoLayout *layout,
EekKey *key);
void (* render_key_outline) (EekRenderer *self,
cairo_t *cr,
struct button_place *place,
EekKey *key,
gdouble scale,
gboolean rotate);
void (* render_key) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
@ -47,8 +58,7 @@ struct _EekRendererClass
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
const gchar *icon_name,
gint size,
gint scale);
gint size);
/*< private >*/
/* padding */
@ -56,7 +66,7 @@ struct _EekRendererClass
};
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer,
@ -65,26 +75,35 @@ void eek_renderer_set_allocation_size
void eek_renderer_get_size (EekRenderer *renderer,
gdouble *width,
gdouble *height);
void eek_renderer_get_button_bounds (EekBounds view_bounds,
struct button_place *button,
void eek_renderer_get_key_bounds (EekRenderer *renderer,
EekKey *key,
EekBounds *bounds,
gboolean rotate);
gdouble eek_renderer_get_scale (EekRenderer *renderer);
void eek_renderer_set_scale_factor (EekRenderer *renderer,
gint scale);
PangoLayout *eek_renderer_create_pango_layout
(EekRenderer *renderer);
void eek_renderer_render_button (EekRenderer *renderer,
void eek_renderer_render_key_label (EekRenderer *renderer,
PangoLayout *layout,
EekKey *key);
void eek_renderer_render_key_outline
(EekRenderer *renderer,
cairo_t *cr,
struct button_place *place,
EekKey *key,
gdouble scale,
gboolean rotate);
cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name,
gint size,
gint scale);
void eek_renderer_render_key (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
const gchar *icon_name,
gint size);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);
@ -96,19 +115,34 @@ void eek_renderer_set_default_background_color
(EekRenderer *renderer,
const EekColor *color);
void eek_renderer_get_foreground_color
(GtkStyleContext *context,
(EekRenderer *renderer,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_color
(EekRenderer *renderer,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_gradient
(EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
void eek_renderer_apply_transformation_for_button
(cairo_t *cr,
EekBounds view_bounds,
struct button_place *place,
EekKey *eek_renderer_find_key_by_position
(EekRenderer *renderer,
gdouble x,
gdouble y);
void eek_renderer_apply_transformation_for_key
(EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
struct transformation
eek_renderer_get_transformation (EekRenderer *renderer);
void eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_RENDERER_H */

567
eek/eek-section.c Normal file
View File

@ -0,0 +1,567 @@
/*
* 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
*/
/**
* SECTION:eek-section
* @short_description: Base class of a section
* @see_also: #EekKey
*
* The #EekSectionClass class represents a section, which consists
* of one or more keys of the #EekKeyClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
enum {
PROP_0,
PROP_ANGLE,
PROP_LAST
};
enum {
KEY_LOCKED,
KEY_UNLOCKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
struct _EekRow
{
gint num_columns;
EekOrientation orientation;
};
typedef struct _EekRow EekRow;
typedef struct _EekSectionPrivate
{
gint angle;
GSList *rows;
EekModifierType modifiers;
} EekSectionPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
static gint
eek_section_real_get_n_rows (EekSection *self)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
return g_slist_length (priv->rows);
}
static void
eek_section_real_add_row (EekSection *self,
gint num_columns,
EekOrientation orientation)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slice_new (EekRow);
row->num_columns = num_columns;
row->orientation = orientation;
priv->rows = g_slist_append (priv->rows, row);
}
static void
eek_section_real_get_row (EekSection *self,
gint index,
gint *num_columns,
EekOrientation *orientation)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slist_nth_data (priv->rows, index);
g_return_if_fail (row);
if (num_columns)
*num_columns = row->num_columns;
if (orientation)
*orientation = row->orientation;
}
static void
on_locked (EekKey *key,
EekSection *section)
{
g_signal_emit (section, signals[KEY_LOCKED], 0, key);
}
static void
on_unlocked (EekKey *key,
EekSection *section)
{
g_signal_emit (section, signals[KEY_UNLOCKED], 0, key);
}
static EekKey *
eek_section_real_create_key (EekSection *self,
const gchar *name,
gint keycode,
gint column_index,
gint row_index)
{
EekKey *key;
gint num_rows;
EekRow *row;
num_rows = eek_section_get_n_rows (self);
g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
row = g_slist_nth_data (priv->rows, row_index);
if (row->num_columns < column_index + 1)
row->num_columns = column_index + 1;
key = g_object_new (EEK_TYPE_KEY,
"name", name,
"keycode", keycode,
"column", column_index,
"row", row_index,
NULL);
g_return_val_if_fail (key, NULL);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
return key;
}
static void
set_level_from_modifiers (EekSection *self)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekKeyboard *keyboard;
EekModifierType num_lock_mask;
gint level = -1;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
if (priv->modifiers & num_lock_mask)
level = 1;
eek_element_set_level (EEK_ELEMENT(self), level);
}
static void
eek_section_real_key_pressed (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
priv->modifiers |= modifier;
set_level_from_modifiers (self);
}
}
static void
eek_section_real_key_released (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
switch (behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
priv->modifiers &= ~modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
break;
}
set_level_from_modifiers (self);
}
static void
eek_section_finalize (GObject *object)
{
EekSection *self = EEK_SECTION (object);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
GSList *head;
for (head = priv->rows; head; head = g_slist_next (head))
g_slice_free (EekRow, head->data);
g_slist_free (priv->rows);
G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
}
static void
eek_section_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_ANGLE:
eek_section_set_angle (EEK_SECTION(object),
g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_section_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_ANGLE:
g_value_set_int (value, eek_section_get_angle (EEK_SECTION(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_section_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "locked", G_CALLBACK(on_locked), self);
g_signal_connect (element, "unlocked", G_CALLBACK(on_unlocked), self);
}
static void
eek_section_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_locked, self);
g_signal_handlers_disconnect_by_func (element, on_unlocked, self);
}
static void
eek_section_class_init (EekSectionClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->get_n_rows = eek_section_real_get_n_rows;
klass->add_row = eek_section_real_add_row;
klass->get_row = eek_section_real_get_row;
klass->create_key = eek_section_real_create_key;
/* signals */
klass->key_pressed = eek_section_real_key_pressed;
klass->key_released = eek_section_real_key_released;
container_class->child_added = eek_section_real_child_added;
container_class->child_removed = eek_section_real_child_removed;
gobject_class->set_property = eek_section_set_property;
gobject_class->get_property = eek_section_get_property;
gobject_class->finalize = eek_section_finalize;
/**
* EekSection:angle:
*
* The rotation angle of #EekSection.
*/
pspec = g_param_spec_int ("angle",
"Angle",
"Rotation angle of the section",
-360, 360, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_ANGLE,
pspec);
/**
* EekSection::key-locked:
* @section: an #EekSection
* @key: an #EekKey
*
* The ::key-locked signal is emitted each time a key in @section
* is shifted to the locked state.
*/
signals[KEY_LOCKED] =
g_signal_new (I_("key-locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekSectionClass, key_locked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
/**
* EekSection::key-unlocked:
* @section: an #EekSection
* @key: an #EekKey
*
* The ::key-unlocked signal is emitted each time a key in @section
* is shifted to the unlocked state.
*/
signals[KEY_UNLOCKED] =
g_signal_new (I_("key-unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekSectionClass, key_unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
}
static void
eek_section_init (EekSection *self)
{
/* void */
}
/**
* eek_section_set_angle:
* @section: an #EekSection
* @angle: rotation angle
*
* Set rotation angle of @section to @angle.
*/
void
eek_section_set_angle (EekSection *section,
gint angle)
{
g_return_if_fail (EEK_IS_SECTION(section));
EekSectionPrivate *priv = eek_section_get_instance_private (section);
if (priv->angle != angle) {
priv->angle = angle;
g_object_notify (G_OBJECT(section), "angle");
}
}
/**
* eek_section_get_angle:
* @section: an #EekSection
*
* Get rotation angle of @section.
*/
gint
eek_section_get_angle (EekSection *section)
{
g_return_val_if_fail (EEK_IS_SECTION(section), -1);
EekSectionPrivate *priv = eek_section_get_instance_private (section);
return priv->angle;
}
/**
* eek_section_get_n_rows:
* @section: an #EekSection
*
* Get the number of rows in @section.
*/
gint
eek_section_get_n_rows (EekSection *section)
{
g_return_val_if_fail (EEK_IS_SECTION(section), -1);
return EEK_SECTION_GET_CLASS(section)->get_n_rows (section);
}
/**
* eek_section_add_row:
* @section: an #EekSection
* @num_columns: the number of column in the row
* @orientation: #EekOrientation of the row
*
* Add a row which has @num_columns columns and whose orientation is
* @orientation to @section.
*/
void
eek_section_add_row (EekSection *section,
gint num_columns,
EekOrientation orientation)
{
g_return_if_fail (EEK_IS_SECTION(section));
EEK_SECTION_GET_CLASS(section)->add_row (section,
num_columns,
orientation);
}
/**
* eek_section_get_row:
* @section: an #EekSection
* @index: the index of row
* @num_columns: pointer where the number of column in the row will be stored
* @orientation: pointer where #EekOrientation of the row will be stored
*
* Get the information about the @index-th row in @section.
*/
void
eek_section_get_row (EekSection *section,
gint index,
gint *num_columns,
EekOrientation *orientation)
{
g_return_if_fail (EEK_IS_SECTION(section));
EEK_SECTION_GET_CLASS(section)->get_row (section,
index,
num_columns,
orientation);
}
/**
* eek_section_create_key:
* @section: an #EekSection
* @name: a name
* @keycode: a keycode
* @column: the column index of the key
* @row: the row index of the key
*
* Create an #EekKey instance and append it to @section. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
EekKey *
eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode,
gint column,
gint row)
{
g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section,
name,
keycode,
column,
row);
}
static void keysizer(EekElement *element, gpointer user_data) {
EekKey *key = EEK_KEY(element);
EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
uint oref = eek_key_get_oref (key);
EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
if (outline && outline->num_points > 0) {
double minx = outline->points[0].x;
double maxx = minx;
double miny = outline->points[0].y;
double maxy = miny;
for (uint i = 1; i < outline->num_points; i++) {
EekPoint p = outline->points[i];
if (p.x < minx) {
minx = p.x;
} else if (p.x > maxx) {
maxx = p.x;
}
if (p.y < miny) {
miny = p.y;
} else if (p.y > maxy) {
maxy = p.y;
}
}
EekBounds key_bounds = {0};
eek_element_get_bounds(element, &key_bounds);
key_bounds.height = maxy - miny;
key_bounds.width = maxx - minx;
eek_element_set_bounds(element, &key_bounds);
}
}
struct keys_info {
uint count;
double total_width;
double biggest_height;
};
static void keycounter (EekElement *element, gpointer user_data) {
struct keys_info *data = user_data;
data->count++;
EekBounds key_bounds = {0};
eek_element_get_bounds(element, &key_bounds);
data->total_width += key_bounds.width;
if (key_bounds.height > data->biggest_height) {
data->biggest_height = key_bounds.height;
}
}
const double keyspacing = 4.0;
static void keyplacer(EekElement *element, gpointer user_data) {
double *current_offset = user_data;
EekBounds key_bounds = {0};
eek_element_get_bounds(element, &key_bounds);
key_bounds.x = *current_offset;
key_bounds.y = 0;
eek_element_set_bounds(element, &key_bounds);
*current_offset += key_bounds.width + keyspacing;
}
void eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
{
eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);
struct keys_info keyinfo = {0};
eek_container_foreach_child(EEK_CONTAINER(section), keycounter, &keyinfo);
EekBounds section_bounds = {0};
eek_element_get_bounds(EEK_ELEMENT(section), &section_bounds);
double key_offset = (section_bounds.width - (keyinfo.total_width + (keyinfo.count - 1) * keyspacing)) / 2;
eek_container_foreach_child(EEK_CONTAINER(section), keyplacer, &key_offset);
section_bounds.height = keyinfo.biggest_height;
eek_element_set_bounds(EEK_ELEMENT(section), &section_bounds);
}

114
eek/eek-section.h Normal file
View File

@ -0,0 +1,114 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_SECTION_H
#define EEK_SECTION_H 1
#include <glib-object.h>
#include "eek-container.h"
#include "eek-types.h"
G_BEGIN_DECLS
#define EEK_TYPE_SECTION (eek_section_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer)
/**
* EekSectionClass:
* @get_n_rows: virtual function for getting the number of rows in the section
* @add_row: virtual function for adding a new row to the section
* @get_row: virtual function for accessing a row in the section
* @create_key: virtual function for creating key in the section
* @key_pressed: class handler for #EekSection::key-pressed signal
* @key_released: class handler for #EekSection::key-released signal
* @key_locked: class handler for #EekSection::key-locked signal
* @key_unlocked: class handler for #EekSection::key-unlocked signal
* @key_cancelled: class handler for #EekSection::key-cancelled signal
*/
struct _EekSectionClass
{
/*< private >*/
EekContainerClass parent_class;
/*< public >*/
gint (* get_n_rows) (EekSection *self);
void (* add_row) (EekSection *self,
gint num_columns,
EekOrientation orientation);
void (* get_row) (EekSection *self,
gint index,
gint *num_columns,
EekOrientation *orientation);
EekKey *(* create_key) (EekSection *self,
const gchar *name,
gint keycode,
gint row,
gint column);
/* signals */
void (* key_pressed) (EekSection *self,
EekKey *key);
void (* key_released) (EekSection *self,
EekKey *key);
void (* key_locked) (EekSection *self,
EekKey *key);
void (* key_unlocked) (EekSection *self,
EekKey *key);
void (* key_cancelled) (EekSection *self,
EekKey *key);
/*< private >*/
/* padding */
gpointer pdummy[19];
};
GType eek_section_get_type (void) G_GNUC_CONST;
void eek_section_set_angle (EekSection *section,
gint angle);
gint eek_section_get_angle (EekSection *section);
gint eek_section_get_n_rows (EekSection *section);
void eek_section_add_row (EekSection *section,
gint num_columns,
EekOrientation orientation);
void eek_section_get_row (EekSection *section,
gint index,
gint *num_columns,
EekOrientation *orientation);
EekKey *eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode,
gint column,
gint row);
EekKey *eek_section_find_key_by_keycode (EekSection *section,
guint keycode);
void eek_section_place_keys (EekSection *section, EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_SECTION_H */

93
eek/eek-serializable.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
* Copyright (C) 2008-2010 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:eek-serializable
* @short_description: Interface which provides object serialization
* into #GVariant
*
* The #EekSerializableIface interface defines serialize/deserialize
* method.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-serializable.h"
GType
eek_serializable_get_type (void)
{
static GType iface_type = 0;
if (iface_type == 0) {
static const GTypeInfo info = {
sizeof (EekSerializableIface),
NULL,
NULL,
};
iface_type = g_type_register_static (G_TYPE_INTERFACE,
"EekSerializable",
&info, 0);
}
return iface_type;
}
GVariant *
eek_serializable_serialize (EekSerializable *object)
{
GVariantBuilder builder;
g_return_val_if_fail (EEK_IS_SERIALIZABLE (object), FALSE);
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
EEK_SERIALIZABLE_GET_IFACE (object)->serialize (object, &builder);
return g_variant_builder_end (&builder);
}
EekSerializable *
eek_serializable_deserialize (GVariant *variant)
{
gchar *type_name = NULL;
GType type;
EekSerializable *object;
gsize index = 0;
g_return_val_if_fail (variant != NULL, NULL);
g_variant_get_child (variant, index++, "&s", &type_name);
type = g_type_from_name (type_name);
g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
object = g_object_new (type, NULL);
index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
variant,
index);
if (index < 0) {
g_object_unref (object);
g_return_val_if_reached (NULL);
}
return object;
}

66
eek/eek-serializable.h Normal file
View File

@ -0,0 +1,66 @@
/*
* 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/>.
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_SERIALIZABLE_H
#define EEK_SERIALIZABLE_H 1
#include <glib-object.h>
G_BEGIN_DECLS
#define EEK_TYPE_SERIALIZABLE (eek_serializable_get_type())
#define EEK_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SERIALIZABLE, EekSerializable))
#define EEK_IS_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SERIALIZABLE))
#define EEK_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_SERIALIZABLE, EekSerializableIface))
typedef struct _EekSerializable EekSerializable;
typedef struct _EekSerializableIface EekSerializableIface;
/**
* EekSerializableIface:
*
* @serialize: virtual function for serializing object into #GVariant
* @deserialize: virtual function for deserializing object from #GVariant
*/
struct _EekSerializableIface
{
/*< private >*/
GTypeInterface parent_iface;
void (* serialize) (EekSerializable *object,
GVariantBuilder *builder);
gsize (* deserialize) (EekSerializable *object,
GVariant *variant,
gsize index);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_serializable_get_type (void);
GVariant *eek_serializable_serialize (EekSerializable *object);
EekSerializable *eek_serializable_deserialize (GVariant *variant);
G_END_DECLS
#endif /* EEK_SERIALIZABLE_H */

105
eek/eek-symbol-matrix.c Normal file
View File

@ -0,0 +1,105 @@
/*
* 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
*/
#include "eek-symbol-matrix.h"
EekSymbolMatrix *
eek_symbol_matrix_new (gint num_groups,
gint num_levels)
{
EekSymbolMatrix *matrix = g_slice_new (EekSymbolMatrix);
matrix->num_groups = num_groups;
matrix->num_levels = num_levels;
matrix->data = g_slice_alloc0 (sizeof (EekSymbol *) *
num_groups * num_levels);
return matrix;
}
EekSymbolMatrix *
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
{
EekSymbolMatrix *retval;
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
retval = g_slice_dup (EekSymbolMatrix, matrix);
retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
matrix->data);
for (i = 0; i < num_symbols; i++)
if (retval->data[i])
g_object_ref (retval->data[i]);
return retval;
}
void
eek_symbol_matrix_free (EekSymbolMatrix *matrix)
{
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
for (i = 0; i < num_symbols; i++)
if (matrix->data[i])
g_object_unref (matrix->data[i]);
g_slice_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
g_slice_free (EekSymbolMatrix, matrix);
}
GType
eek_symbol_matrix_get_type (void)
{
static GType our_type = 0;
if (our_type == 0)
our_type =
g_boxed_type_register_static ("EekSymbolMatrix",
(GBoxedCopyFunc)eek_symbol_matrix_copy,
(GBoxedFreeFunc)eek_symbol_matrix_free);
return our_type;
}
void
eek_symbol_matrix_set_symbol (EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol)
{
g_return_if_fail (group >= 0 && group < matrix->num_groups);
g_return_if_fail (level >= 0 && level < matrix->num_levels);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
}
/**
* eek_symbol_matrix_get_symbol:
* @matrix: an #EekSymbolMatrix
* @group: group index of @matrix
* @level: level index of @matrix
*
* Get an #EekSymbol stored in the cell selected by (@group, @level)
* in @matrix.
*
* Return value: (transfer none): an #EekSymbol.
*/
EekSymbol *
eek_symbol_matrix_get_symbol (EekSymbolMatrix *matrix,
gint group,
gint level)
{
g_return_val_if_fail (group >= 0 && group < matrix->num_groups, NULL);
g_return_val_if_fail (level >= 0 && level < matrix->num_levels, NULL);
return matrix->data[group * matrix->num_levels + level];
}

62
eek/eek-symbol-matrix.h Normal file
View File

@ -0,0 +1,62 @@
/*
* 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
*/
#ifndef EEK_SYMBOL_MATRIX_H
#define EEK_SYMBOL_MATRIX_H 1
#include "eek-symbol.h"
G_BEGIN_DECLS
/**
* EekSymbolMatrix:
* @data: array of symbols
* @num_groups: the number of groups (rows)
* @num_levels: the number of levels (columns)
*
* Symbol matrix of a key.
*/
struct _EekSymbolMatrix
{
/*< public >*/
gint num_groups;
gint num_levels;
EekSymbol **data;
};
#define EEK_TYPE_SYMBOL_MATRIX (eek_symbol_matrix_get_type ())
GType eek_symbol_matrix_get_type (void) G_GNUC_CONST;
EekSymbolMatrix *eek_symbol_matrix_new (gint num_groups,
gint num_levels);
EekSymbolMatrix *eek_symbol_matrix_copy (const EekSymbolMatrix *matrix);
void eek_symbol_matrix_free (EekSymbolMatrix *matrix);
void eek_symbol_matrix_set_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol);
EekSymbol *eek_symbol_matrix_get_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level);
G_END_DECLS
#endif /* EEK_SYMBOL_MATRIX_H */

524
eek/eek-symbol.c Normal file
View File

@ -0,0 +1,524 @@
/*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-symbol.h"
#include "eek-serializable.h"
#include "eek-enumtypes.h"
enum {
PROP_0,
PROP_NAME,
PROP_LABEL,
PROP_CATEGORY,
PROP_MODIFIER_MASK,
PROP_ICON_NAME,
PROP_TOOLTIP,
PROP_LAST
};
typedef struct _EekSymbolPrivate
{
gchar *name;
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
gchar *icon_name;
gchar *tooltip;
} EekSymbolPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekSymbol,
eek_symbol,
G_TYPE_OBJECT,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekSymbol)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static void
eek_symbol_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
#define NOTNULL(s) ((s) != NULL ? (s) : "")
g_variant_builder_add (builder, "s", NOTNULL(priv->name));
g_variant_builder_add (builder, "s", NOTNULL(priv->label));
g_variant_builder_add (builder, "u", priv->category);
g_variant_builder_add (builder, "u", priv->modifier_mask);
g_variant_builder_add (builder, "s", NOTNULL(priv->icon_name));
g_variant_builder_add (builder, "s", NOTNULL(priv->tooltip));
#undef NOTNULL
}
static gsize
eek_symbol_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "s", &priv->label);
g_variant_get_child (variant, index++, "u", &priv->category);
g_variant_get_child (variant, index++, "u", &priv->modifier_mask);
g_variant_get_child (variant, index++, "s", &priv->icon_name);
g_variant_get_child (variant, index++, "s", &priv->tooltip);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
iface->serialize = eek_symbol_real_serialize;
iface->deserialize = eek_symbol_real_deserialize;
}
static void
eek_symbol_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
eek_symbol_set_name (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_LABEL:
eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_CATEGORY:
eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_enum (value));
break;
case PROP_MODIFIER_MASK:
eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
g_value_get_flags (value));
break;
case PROP_ICON_NAME:
eek_symbol_set_icon_name (EEK_SYMBOL(object),
g_value_get_string (value));
break;
case PROP_TOOLTIP:
eek_symbol_set_tooltip (EEK_SYMBOL(object),
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_symbol_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_symbol_get_name (EEK_SYMBOL(object)));
break;
case PROP_LABEL:
g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object)));
break;
case PROP_CATEGORY:
g_value_set_enum (value, eek_symbol_get_category (EEK_SYMBOL(object)));
break;
case PROP_MODIFIER_MASK:
g_value_set_flags (value,
eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
break;
case PROP_ICON_NAME:
g_value_set_string (value,
eek_symbol_get_icon_name (EEK_SYMBOL(object)));
break;
case PROP_TOOLTIP:
g_value_set_string (value,
eek_symbol_get_tooltip (EEK_SYMBOL(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_symbol_finalize (GObject *object)
{
EekSymbol *self = EEK_SYMBOL (object);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
g_free (priv->name);
g_free (priv->label);
g_free (priv->icon_name);
g_free (priv->tooltip);
G_OBJECT_CLASS (eek_symbol_parent_class)->finalize (object);
}
static void
eek_symbol_class_init (EekSymbolClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_symbol_set_property;
gobject_class->get_property = eek_symbol_get_property;
gobject_class->finalize = eek_symbol_finalize;
pspec = g_param_spec_string ("name",
"Name",
"Canonical name of the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("label",
"Label",
"Text used to display the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
pspec = g_param_spec_enum ("category",
"Category",
"Category of the symbol",
EEK_TYPE_SYMBOL_CATEGORY,
EEK_SYMBOL_CATEGORY_UNKNOWN,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_CATEGORY, pspec);
pspec = g_param_spec_flags ("modifier-mask",
"Modifier mask",
"Modifier mask of the symbol",
EEK_TYPE_MODIFIER_TYPE,
0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODIFIER_MASK, pspec);
pspec = g_param_spec_string ("icon-name",
"Icon name",
"Icon name used to render the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ICON_NAME, pspec);
pspec = g_param_spec_string ("tooltip",
"Tooltip",
"Tooltip text",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TOOLTIP, pspec);
}
static void
eek_symbol_init (EekSymbol *self)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
priv->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/**
* eek_symbol_new:
* @name: name of the symbol
*
* Create a new #EekSymbol with @name.
*/
EekSymbol *
eek_symbol_new (const gchar *name)
{
return g_object_new (EEK_TYPE_SYMBOL, "name", name, NULL);
}
/**
* eek_symbol_set_name:
* @symbol: an #EekSymbol
* @name: name of the symbol
*
* Set the name of @symbol to @name.
*/
void
eek_symbol_set_name (EekSymbol *symbol,
const gchar *name)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
* eek_symbol_get_name:
* @symbol: an #EekSymbol
*
* Get the name of @symbol.
*/
const gchar *
eek_symbol_get_name (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->name == NULL || *priv->name == '\0')
return NULL;
return priv->name;
}
/**
* 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_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->label);
priv->label = g_strdup (label);
}
/**
* eek_symbol_get_label:
* @symbol: an #EekSymbol
*
* Get the label text of @symbol.
*/
const gchar *
eek_symbol_get_label (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->label == NULL || *priv->label == '\0')
return NULL;
return priv->label;
}
/**
* eek_symbol_set_category:
* @symbol: an #EekSymbol
* @category: an #EekSymbolCategory
*
* Set symbol category of @symbol to @category.
*/
void
eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->category = category;
}
/**
* eek_symbol_get_category:
* @symbol: an #EekSymbol
*
* Get symbol category of @symbol.
*/
EekSymbolCategory
eek_symbol_get_category (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->category;
}
/**
* 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)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->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)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->modifier_mask;
}
/**
* eek_symbol_is_modifier:
* @symbol: an #EekSymbol
*
* Check if @symbol is a modifier.
* Returns: %TRUE if @symbol is a modifier.
*/
gboolean
eek_symbol_is_modifier (EekSymbol *symbol)
{
return eek_symbol_get_modifier_mask (symbol) != 0;
}
/**
* eek_symbol_set_icon_name:
* @symbol: an #EekSymbol
* @icon_name: icon name of @symbol
*
* Set the icon name of @symbol to @icon_name.
*/
void
eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->icon_name);
priv->icon_name = g_strdup (icon_name);
}
/**
* eek_symbol_get_icon_name:
* @symbol: an #EekSymbol
*
* Get the icon name of @symbol.
*/
const gchar *
eek_symbol_get_icon_name (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->icon_name == NULL || *priv->icon_name == '\0')
return NULL;
return priv->icon_name;
}
/**
* eek_symbol_set_tooltip:
* @symbol: an #EekSymbol
* @tooltip: icon name of @symbol
*
* Set the tooltip text of @symbol to @tooltip.
*/
void
eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->tooltip);
priv->tooltip = g_strdup (tooltip);
}
/**
* eek_symbol_get_tooltip:
* @symbol: an #EekSymbol
*
* Get the tooltip text of @symbol.
*/
const gchar *
eek_symbol_get_tooltip (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->tooltip == NULL || *priv->tooltip == '\0')
return NULL;
return priv->tooltip;
}
static const struct {
EekSymbolCategory category;
gchar *name;
} category_names[] = {
{ EEK_SYMBOL_CATEGORY_LETTER, "letter" },
{ EEK_SYMBOL_CATEGORY_FUNCTION, "function" },
{ EEK_SYMBOL_CATEGORY_KEYNAME, "keyname" },
{ EEK_SYMBOL_CATEGORY_USER0, "user0" },
{ EEK_SYMBOL_CATEGORY_USER1, "user1" },
{ EEK_SYMBOL_CATEGORY_USER2, "user2" },
{ EEK_SYMBOL_CATEGORY_USER3, "user3" },
{ EEK_SYMBOL_CATEGORY_USER4, "user4" },
{ EEK_SYMBOL_CATEGORY_UNKNOWN, NULL }
};
const gchar *
eek_symbol_category_get_name (EekSymbolCategory category)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(category_names); i++)
if (category_names[i].category == category)
return category_names[i].name;
return NULL;
}
EekSymbolCategory
eek_symbol_category_from_name (const gchar *name)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(category_names); i++)
if (g_strcmp0 (category_names[i].name, name) == 0)
return category_names[i].category;
return EEK_SYMBOL_CATEGORY_UNKNOWN;
}

100
eek/eek-symbol.h Normal file
View File

@ -0,0 +1,100 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_SYMBOL_H
#define EEK_SYMBOL_H 1
#include "eek-types.h"
G_BEGIN_DECLS
/**
* EekSymbolCategory:
* @EEK_SYMBOL_CATEGORY_LETTER: the symbol represents an alphabet letter
* @EEK_SYMBOL_CATEGORY_FUNCTION: the symbol represents a function
* @EEK_SYMBOL_CATEGORY_KEYNAME: the symbol does not have meaning but
* have a name
* @EEK_SYMBOL_CATEGORY_USER0: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER1: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER2: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER3: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER4: reserved for future use
* @EEK_SYMBOL_CATEGORY_UNKNOWN: used for error reporting
* @EEK_SYMBOL_CATEGORY_LAST: the last symbol category
*
* Category of the key symbols.
*/
typedef enum {
EEK_SYMBOL_CATEGORY_LETTER,
EEK_SYMBOL_CATEGORY_FUNCTION,
EEK_SYMBOL_CATEGORY_KEYNAME,
EEK_SYMBOL_CATEGORY_USER0,
EEK_SYMBOL_CATEGORY_USER1,
EEK_SYMBOL_CATEGORY_USER2,
EEK_SYMBOL_CATEGORY_USER3,
EEK_SYMBOL_CATEGORY_USER4,
EEK_SYMBOL_CATEGORY_UNKNOWN,
EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
} EekSymbolCategory;
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
/**
* EekSymbolClass:
*/
struct _EekSymbolClass {
/*< private >*/
GObjectClass parent_class;
};
GType eek_symbol_get_type (void) G_GNUC_CONST;
EekSymbol *eek_symbol_new (const gchar *name);
void eek_symbol_set_name (EekSymbol *symbol,
const gchar *name);
const gchar *eek_symbol_get_name (EekSymbol *symbol);
void eek_symbol_set_label (EekSymbol *symbol,
const gchar *label);
const gchar *eek_symbol_get_label (EekSymbol *symbol);
void eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category);
EekSymbolCategory eek_symbol_get_category (EekSymbol *symbol);
EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol);
void eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask);
gboolean eek_symbol_is_modifier (EekSymbol *symbol);
void eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name);
const gchar *eek_symbol_get_icon_name (EekSymbol *symbol);
void eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip);
const gchar * eek_symbol_get_tooltip (EekSymbol *symbol);
const gchar *eek_symbol_category_get_name (EekSymbolCategory category);
EekSymbolCategory eek_symbol_category_from_name (const gchar *name);
G_END_DECLS
#endif /* EEK_SYMBOL_H */

187
eek/eek-text.c Normal file
View File

@ -0,0 +1,187 @@
/*
* 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-text
* @short_description: an #EekText represents a text symbol
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-text.h"
#include "eek-serializable.h"
enum {
PROP_0,
PROP_TEXT,
PROP_LAST
};
typedef struct _EekTextPrivate
{
gchar *text;
} EekTextPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekText,
eek_text,
EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekText)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_text_parent_serializable_iface;
static void
eek_text_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
eek_text_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "s", priv->text);
}
static gsize
eek_text_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
index = eek_text_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "s", &priv->text);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_text_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_text_real_serialize;
iface->deserialize = eek_text_real_deserialize;
}
static void
eek_text_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_free (priv->text);
priv->text = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_text_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_value_set_string (value, priv->text);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_text_finalize (GObject *object)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
g_free (priv->text);
G_OBJECT_CLASS (eek_text_parent_class)->finalize (object);
}
static void
eek_text_class_init (EekTextClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_text_set_property;
gobject_class->get_property = eek_text_get_property;
gobject_class->finalize = eek_text_finalize;
pspec = g_param_spec_string ("text",
"Text",
"Text",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
}
static void
eek_text_init (EekText *self)
{
/* void */
}
EekText *
eek_text_new (const gchar *text)
{
return g_object_new (EEK_TYPE_TEXT,
"label", text,
"category", EEK_SYMBOL_CATEGORY_FUNCTION,
"text", text,
NULL);
}
/**
* eek_text_get_text:
* @text: an #EekText
*
* Get a text value associated with @text
*/
const gchar *
eek_text_get_text (EekText *text)
{
EekTextPrivate *priv = eek_text_get_instance_private (text);
return priv->text;
}

46
eek/eek-text.h Normal file
View File

@ -0,0 +1,46 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_TEXT_H
#define EEK_TEXT_H 1
#include "eek-symbol.h"
G_BEGIN_DECLS
#define EEK_TYPE_TEXT (eek_text_get_type())
G_DECLARE_DERIVABLE_TYPE(EekText, eek_text, EEK, TEXT, EekSymbol)
struct _EekTextClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_text_get_type (void) G_GNUC_CONST;
EekText *eek_text_new (const gchar *text);
const gchar *eek_text_get_text (EekText *text);
G_END_DECLS
#endif /* EEK_TEXT_H */

289
eek/eek-theme-context.c Normal file
View File

@ -0,0 +1,289 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program 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.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-theme.h"
#include "eek-theme-context.h"
struct _EekThemeContext {
GObject parent;
double resolution;
PangoFontDescription *font;
EekThemeNode *root_node;
EekTheme *theme;
};
struct _EekThemeContextClass {
GObjectClass parent_class;
};
#define DEFAULT_RESOLUTION 96.
#define DEFAULT_FONT "sans-serif 10"
enum
{
CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
static void
eek_theme_context_finalize (GObject *object)
{
EekThemeContext *context = EEK_THEME_CONTEXT (object);
if (context->root_node)
g_object_unref (context->root_node);
if (context->theme)
g_object_unref (context->theme);
pango_font_description_free (context->font);
G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
}
static void
eek_theme_context_class_init (EekThemeContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = eek_theme_context_finalize;
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, /* no default handler slot */
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eek_theme_context_init (EekThemeContext *context)
{
context->resolution = DEFAULT_RESOLUTION;
context->font = pango_font_description_from_string (DEFAULT_FONT);
}
/**
* eek_theme_context_new:
*
* Create a new theme context.
*/
EekThemeContext *
eek_theme_context_new (void)
{
EekThemeContext *context;
context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
return context;
}
static void
eek_theme_context_changed (EekThemeContext *context)
{
EekThemeNode *old_root = context->root_node;
context->root_node = NULL;
g_signal_emit (context, signals[CHANGED], 0);
if (old_root)
g_object_unref (old_root);
}
/**
* eek_theme_context_set_theme:
* @context: an #EekThemeContext
* @theme: an #EekTheme
*
* Sets the default set of theme stylesheets for the context. This theme will
* be used for the root node and for nodes descending from it, unless some other
* style is explicitely specified.
*/
void
eek_theme_context_set_theme (EekThemeContext *context,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
if (context->theme != theme)
{
if (context->theme)
g_object_unref (context->theme);
context->theme = theme;
if (context->theme)
g_object_ref (context->theme);
eek_theme_context_changed (context);
}
}
/**
* eek_theme_context_get_theme:
* @context: a #EekThemeContext
*
* Gets the default theme for the context. See eek_theme_context_set_theme()
*
* Return value: (transfer none): the default theme for the context
*/
EekTheme *
eek_theme_context_get_theme (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->theme;
}
/**
* eek_theme_context_set_resolution:
* @context: a #EekThemeContext
* @resolution: resolution of the context (number of pixels in an "inch")
*
* Sets the resolution of the theme context. This is the scale factor
* used to convert between points and the length units pt, in, and cm.
* This does not necessarily need to correspond to the actual number
* resolution of the device. A value of 72. means that points and
* pixels are identical. The default value is 96.
*/
void
eek_theme_context_set_resolution (EekThemeContext *context,
double resolution)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (resolution == context->resolution)
return;
context->resolution = resolution;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_set_default_resolution:
* @context: a #EekThemeContext
*
* Sets the resolution of the theme context to the default value of 96.
* See eek_theme_context_set_resolution().
*/
void
eek_theme_context_set_default_resolution (EekThemeContext *context)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (context->resolution == DEFAULT_RESOLUTION)
return;
context->resolution = DEFAULT_RESOLUTION;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_resolution:
* @context: a #EekThemeContext
*
* Gets the current resolution of the theme context.
* See eek_theme_context_set_resolution().
*
* Return value: the resolution (in dots-per-"inch")
*/
double
eek_theme_context_get_resolution (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
return context->resolution;
}
/**
* eek_theme_context_set_font:
* @context: a #EekThemeContext
* @font: the default font for theme context
*
* Sets the default font for the theme context. This is the font that
* is inherited by the root node of the tree of theme nodes. If the
* font is not overriden, then this font will be used. If the font is
* partially modified (for example, with 'font-size: 110%', then that
* modification is based on this font.
*/
void
eek_theme_context_set_font (EekThemeContext *context,
const PangoFontDescription *font)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (font != NULL);
if (context->font == font ||
pango_font_description_equal (context->font, font))
return;
pango_font_description_free (context->font);
context->font = pango_font_description_copy (font);
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_font:
* @context: a #EekThemeContext
*
* Gets the default font for the theme context. See eek_theme_context_set_font().
*
* Return value: the default font for the theme context.
*/
const PangoFontDescription *
eek_theme_context_get_font (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->font;
}
/**
* eek_theme_context_get_root_node:
* @context: a #EekThemeContext
*
* Gets the root node of the tree of theme style nodes that associated with this
* context. For the node tree associated with a stage, this node represents
* styles applied to the stage itself.
*
* Return value: (transfer none): the root node of the context's style tree
*/
EekThemeNode *
eek_theme_context_get_root_node (EekThemeContext *context)
{
if (context->root_node == NULL)
context->root_node = eek_theme_node_new (context, NULL, context->theme,
G_TYPE_NONE, NULL, NULL, NULL, NULL);
return context->root_node;
}

78
eek/eek-theme-context.h Normal file
View File

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program 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.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EEK_THEME_CONTEXT_H__
#define __EEK_THEME_CONTEXT_H__
#include <pango/pango.h>
#include "eek-theme-node.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-context
* @short_description: holds global information about a tree of styled objects
*
* #EekThemeContext is responsible for managing information global to
* a tree of styled objects, such as the set of stylesheets or the
* default font.
*/
typedef struct _EekThemeContextClass EekThemeContextClass;
#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
GType eek_theme_context_get_type
(void) G_GNUC_CONST;
EekThemeContext *eek_theme_context_new
(void);
void eek_theme_context_set_theme
(EekThemeContext *context,
EekTheme *theme);
EekTheme * eek_theme_context_get_theme
(EekThemeContext *context);
void eek_theme_context_set_resolution
(EekThemeContext *context,
gdouble resolution);
void eek_theme_context_set_default_resolution
(EekThemeContext *context);
double eek_theme_context_get_resolution
(EekThemeContext *context);
void eek_theme_context_set_font
(EekThemeContext *context,
const PangoFontDescription *font);
const PangoFontDescription *eek_theme_context_get_font
(EekThemeContext *context);
EekThemeNode * eek_theme_context_get_root_node
(EekThemeContext *context);
G_END_DECLS
#endif /* __EEK_THEME_CONTEXT_H__ */

1866
eek/eek-theme-node.c Normal file

File diff suppressed because it is too large Load Diff

141
eek/eek-theme-node.h Normal file
View File

@ -0,0 +1,141 @@
/*
* 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_THEME_NODE_H__
#define __EEK_THEME_NODE_H__
#include <pango/pango.h>
#include "eek-types.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-node
* @short_description: style information for one node in a tree of
* themed objects
*
* The #EekThemeNode class represents the CSS style information (the
* set of CSS properties) for one node in a tree of themed objects. In
* typical usage, it represents the style information for a single
* #EekElement. A #EekThemeNode is immutable: attributes such as the
* CSS classes for the node are passed in at construction. If the
* attributes of the node or any parent node change, the node should
* be discarded and a new node created. #EekThemeNode has generic
* accessors to look up properties by name and specific accessors for
* standard CSS properties that add caching and handling of various
* details of the CSS specification. #EekThemeNode also has
* convenience functions to help in implementing a #EekElement with
* borders and padding.
*/
typedef enum {
EEK_SIDE_TOP,
EEK_SIDE_RIGHT,
EEK_SIDE_BOTTOM,
EEK_SIDE_LEFT
} EekSide;
typedef enum {
EEK_CORNER_TOPLEFT,
EEK_CORNER_TOPRIGHT,
EEK_CORNER_BOTTOMRIGHT,
EEK_CORNER_BOTTOMLEFT
} EekCorner;
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
typedef struct _EekThemeNodeClass EekThemeNodeClass;
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
GType eek_theme_node_get_type
(void) G_GNUC_CONST;
EekThemeNode *eek_theme_node_new (EekThemeContext *context,
EekThemeNode *parent_node,
/* can be null */ EekTheme *theme,
/* can be null */ GType element_type,
const char *element_id,
const char *element_class,
const char *pseudo_class,
const char *inline_style);
EekThemeNode *eek_theme_node_get_parent
(EekThemeNode *node);
EekTheme *eek_theme_node_get_theme
(EekThemeNode *node);
GType eek_theme_node_get_element_type
(EekThemeNode *node);
const char *eek_theme_node_get_element_id
(EekThemeNode *node);
const char *eek_theme_node_get_element_class
(EekThemeNode *node);
const char *eek_theme_node_get_pseudo_class
(EekThemeNode *node);
/* Generic getters ... these are not cached so are less efficient. The other
* reason for adding the more specific version is that we can handle the
* details of the actual CSS rules, which can be complicated, especially
* for fonts
*/
void eek_theme_node_get_color
(EekThemeNode *node,
const char *property_name,
EekColor *color);
/* Specific getters for particular properties: cached
*/
void eek_theme_node_get_background_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_foreground_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_background_gradient
(EekThemeNode *node,
EekGradientType *type,
EekColor *start,
EekColor *end);
int eek_theme_node_get_border_width
(EekThemeNode *node,
EekSide side);
int eek_theme_node_get_border_radius
(EekThemeNode *node,
EekCorner corner);
void eek_theme_node_get_border_color
(EekThemeNode *node,
EekSide side,
EekColor *color);
/* Font rule processing is pretty complicated, so we just hardcode it
* under the standard font/font-family/font-size/etc names. This means
* you can't have multiple separate styled fonts for a single item,
* but that should be OK.
*/
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
G_END_DECLS
#endif /* __EEK_THEME_NODE_H__ */

22
eek/eek-theme-private.h Normal file
View File

@ -0,0 +1,22 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __EEK_THEME_PRIVATE_H__
#define __EEK_THEME_PRIVATE_H__
#include <libcroco/libcroco.h>
#include "eek-theme.h"
G_BEGIN_DECLS
GPtrArray *_eek_theme_get_matched_properties (EekTheme *theme,
EekThemeNode *node);
/* Resolve an URL from the stylesheet to a filename */
char *_eek_theme_resolve_url (EekTheme *theme,
CRStyleSheet *base_stylesheet,
const char *url);
CRDeclaration *_eek_theme_parse_declaration_list (const char *str);
G_END_DECLS
#endif /* __EEK_THEME_PRIVATE_H__ */

1095
eek/eek-theme.c Normal file

File diff suppressed because it is too large Load Diff

49
eek/eek-theme.h Normal file
View File

@ -0,0 +1,49 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef __EEK_THEME_H__
#define __EEK_THEME_H__
#include <glib-object.h>
#include "eek-types.h"
G_BEGIN_DECLS
/**
* SECTION:EekTheme
* @short_description: a set of stylesheets
*
* #EekTheme holds a set of stylesheets. (The "cascade" of the name
* Cascading Stylesheets.) An #EekTheme can be set to apply to all the
* keyboard elements.
*/
typedef struct _EekThemeClass EekThemeClass;
#define EEK_TYPE_THEME (eek_theme_get_type())
#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
GType eek_theme_get_type (void) G_GNUC_CONST;
EekTheme *eek_theme_new (const char *application_stylesheet,
const char *theme_stylesheet,
const char *default_stylesheet);
gboolean eek_theme_load_stylesheet (EekTheme *theme,
const char *path,
GError **error);
void eek_theme_unload_stylesheet (EekTheme *theme,
const char *path);
G_END_DECLS
#endif /* __EEK_THEME_H__ */

View File

@ -24,7 +24,9 @@
* @short_description: Miscellaneous types used in Libeek
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <math.h>
@ -73,6 +75,28 @@ 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);
@ -104,3 +128,9 @@ eek_color_new (gdouble red,
return color;
}
GQuark
eek_error_quark (void)
{
return g_quark_from_static_string ("eek-error-quark");
}

View File

@ -1,7 +1,6 @@
/*
* 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
@ -34,13 +33,124 @@ 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 _EekContainer EekContainer;
typedef struct _EekKey EekKey;
typedef struct _EekSection EekSection;
typedef struct _EekKeyboard EekKeyboard;
typedef struct _EekSymbol EekSymbol;
typedef struct _EekKeysym EekKeysym;
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;
typedef struct _LevelKeyboard LevelKeyboard;
/**
* EekPoint:
@ -85,6 +195,32 @@ GType eek_bounds_get_type (void) G_GNUC_CONST;
EekBounds *eek_bounds_copy (const EekBounds *bounds);
void eek_bounds_free (EekBounds *bounds);
G_INLINE_FUNC gdouble
eek_bounds_long_side (EekBounds *bounds)
{
return bounds->width > bounds->height ? bounds->width : bounds->height;
}
/**
* 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
@ -112,10 +248,20 @@ EekColor *eek_color_new (gdouble red,
EekColor *eek_color_copy (const EekColor *color);
void eek_color_free (EekColor *color);
struct transformation {
gdouble origin_x;
gdouble origin_y;
gdouble scale;
};
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;
G_END_DECLS
#endif /* EEK_TYPES_H */

30
eek/eek-xkb-0.90.pc.in Normal file
View File

@ -0,0 +1,30 @@
# 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
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libeek-xkb
Description: A Library to Create Keyboard-like UI (XKB Support)
URL: http://fedorahosted.org/eekboard/
Version: @VERSION@
Requires: eek-@EEK_API_VERSION@ gtk+-x11-@GTK_API_VERSION@
Libs: -L${libdir} -leek-xkb
Cflags: -I${includedir}/eek-@EEK_API_VERSION@

684
eek/eek-xkb-layout.c Normal file
View File

@ -0,0 +1,684 @@
/*
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
* 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
*/
/**
* SECTION:eek-xkb-layout
* @short_description: Layout engine using XKB configuration
*
* The #EekXkbLayout inherits #EekLayout class and arranges keyboard
* elements using XKB.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-xkb-layout.h"
#include <X11/keysym.h>
#include <X11/extensions/XKBgeom.h>
#include <string.h>
#include <stdarg.h>
#include <gio/gio.h>
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-keysym.h"
#define XKB_COMPONENT_MASK (XkbGBN_GeometryMask | \
XkbGBN_KeyNamesMask | \
XkbGBN_OtherNamesMask | \
XkbGBN_SymbolsMask | \
XkbGBN_IndicatorMapMask)
static void initable_iface_init (GInitableIface *initable_iface);
enum {
PROP_0,
PROP_DISPLAY,
PROP_LAST
};
typedef struct _EekXkbLayoutPrivate
{
/* Configuration names that should synch'ed to the symbolic names
in priv->xkb->names. Since we use GLib's memory allocator,
don't store any address returned from the X server here. */
XkbComponentNamesRec names;
Display *display;
/* Actual XKB configuration of DISPLAY. */
XkbDescRec *xkb;
/* Hash table to cache orefs by shape address. */
GHashTable *shape_oref_hash;
gint scale_numerator;
gint scale_denominator;
} EekXkbLayoutPrivate;
G_DEFINE_TYPE_EXTENDED (EekXkbLayout, eek_xkb_layout, EEK_TYPE_LAYOUT,
0, /* GTypeFlags */
G_ADD_PRIVATE(EekXkbLayout)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init))
static guint find_keycode (EekXkbLayout *layout,
gchar *key_name);
static gboolean get_keyboard_from_server (EekXkbLayout *layout,
GError **error);
static gboolean get_names_from_server (EekXkbLayout *layout,
GError **error);
static void setup_scaling (EekXkbLayout *layout,
gdouble width,
gdouble height);
G_INLINE_FUNC gint
xkb_to_pixmap_coord (EekXkbLayout *layout,
gint n)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
return n * priv->scale_numerator / priv->scale_denominator;
}
G_INLINE_FUNC gdouble
xkb_to_pixmap_double (EekXkbLayout *layout,
gdouble d)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
return d * priv->scale_numerator / priv->scale_denominator;
}
static void
create_key (EekXkbLayout *layout,
EekKeyboard *keyboard,
EekSection *section,
gint column,
gint row,
gdouble x,
gdouble y,
XkbKeyRec *xkbkey)
{
XkbGeometryRec *xkbgeometry;
XkbBoundsRec *xkbbounds;
XkbShapeRec *xkbshape;
XkbOutlineRec *xkboutline;
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
EekKey *key;
EekBounds bounds;
EekSymbolMatrix *matrix = NULL;
gchar name[XkbKeyNameLength + 1];
KeyCode keycode;
gint num_groups, num_levels;
guint oref;
gpointer v;
xkbgeometry = priv->xkb->geom;
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
if (g_hash_table_lookup_extended (priv->shape_oref_hash, xkbshape,
NULL, &v)) {
oref = GPOINTER_TO_UINT(v);
} else {
EekOutline *outline;
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
xkbshape->primary;
outline = g_slice_new (EekOutline);
outline->corner_radius = xkb_to_pixmap_coord(layout,
xkboutline->corner_radius);
if (xkboutline->num_points <= 2) { /* rectangular */
gdouble x1, y1, x2, y2;
outline->num_points = 4;
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
outline->num_points);
if (xkboutline->num_points == 1) {
x1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.x1);
y1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.y1);
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
} else {
x1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
y1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].x);
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].y);
}
outline->points[0].x = outline->points[3].x = x1;
outline->points[0].y = outline->points[1].y = y1;
outline->points[1].x = outline->points[2].x = x2;
outline->points[2].y = outline->points[3].y = y2;
} else { /* polygon */
gint i;
outline->num_points = xkboutline->num_points;
outline->points = g_new0 (EekPoint, outline->num_points);
for (i = 0; i < xkboutline->num_points; i++) {
outline->points[i].x =
xkb_to_pixmap_coord(layout, xkboutline->points[i].x);
outline->points[i].y =
xkb_to_pixmap_coord(layout, xkboutline->points[i].y);
}
}
oref = eek_keyboard_add_outline (keyboard, outline);
eek_outline_free (outline);
g_hash_table_insert (priv->shape_oref_hash, xkbshape,
GUINT_TO_POINTER(oref));
}
memset (name, 0, sizeof name);
memcpy (name, xkbkey->name.name, sizeof name - 1);
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
bounds.x = xkb_to_pixmap_coord(layout, xkbbounds->x1 + x);
bounds.y = xkb_to_pixmap_coord(layout, xkbbounds->y1 + y);
bounds.width = xkb_to_pixmap_coord(layout, xkbbounds->x2 - xkbbounds->x1);
bounds.height = xkb_to_pixmap_coord(layout, xkbbounds->y2 - xkbbounds->y1);
keycode = find_keycode (layout, name);
if (keycode == EEK_INVALID_KEYCODE) {
num_groups = num_levels = 0;
matrix = eek_symbol_matrix_new (0, 0);
} else {
KeySym keysym;
gint i, j;
num_groups = XkbKeyNumGroups (priv->xkb, keycode);
num_levels = XkbKeyGroupsWidth (priv->xkb, keycode);
matrix = eek_symbol_matrix_new (num_groups, num_levels);
for (i = 0; i < num_groups; i++)
for (j = 0; j < num_levels; j++) {
EekModifierType modifier;
keysym = XkbKeySymEntry (priv->xkb, keycode, j, i);
modifier = XkbKeysymToModifiers (priv->display, keysym);
matrix->data[i * num_levels + j] =
EEK_SYMBOL(eek_keysym_new_with_modifier (keysym,
modifier));
}
}
key = eek_section_create_key (section, keycode, column, row);
eek_element_set_name (EEK_ELEMENT(key), name);
eek_element_set_bounds (EEK_ELEMENT(key), &bounds);
eek_key_set_symbol_matrix (key, matrix);
eek_symbol_matrix_free (matrix);
eek_key_set_oref (key, oref);
}
static void
create_section (EekXkbLayout *layout,
EekKeyboard *keyboard,
XkbSectionRec *xkbsection)
{
XkbGeometryRec *xkbgeometry;
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
EekSection *section;
EekBounds bounds;
gchar *name;
gfloat left, top;
gint i, j;
bounds.x = xkb_to_pixmap_coord(layout, xkbsection->left);
bounds.y = xkb_to_pixmap_coord(layout, xkbsection->top);
bounds.width = xkb_to_pixmap_coord(layout, xkbsection->width);
bounds.height = xkb_to_pixmap_coord(layout, xkbsection->height);
xkbgeometry = priv->xkb->geom;
section = eek_keyboard_create_section (keyboard);
name = XGetAtomName (priv->display, xkbsection->name);
eek_element_set_name (EEK_ELEMENT(section), name);
XFree (name);
eek_element_set_bounds (EEK_ELEMENT(section), &bounds);
eek_section_set_angle (section,
/* angle is in tenth of degree */
xkbsection->angle / 10);
for (i = 0; i < xkbsection->num_rows; i++) {
XkbRowRec *xkbrow;
xkbrow = &xkbsection->rows[i];
left = xkbrow->left;
top = xkbrow->top;
eek_section_add_row (section,
xkbrow->num_keys,
xkbrow->vertical ?
EEK_ORIENTATION_VERTICAL :
EEK_ORIENTATION_HORIZONTAL);
for (j = 0; j < xkbrow->num_keys; j++) {
XkbKeyRec *xkbkey;
XkbBoundsRec *xkbbounds;
xkbkey = &xkbrow->keys[j];
if (xkbrow->vertical)
top += xkbkey->gap;
else
left += xkbkey->gap;
create_key (layout, keyboard, section, j, i, left, top, xkbkey);
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
if (xkbrow->vertical)
top += xkbbounds->y2 - xkbbounds->y1;
else
left += xkbbounds->x2 - xkbbounds->x1;
}
}
}
static void
create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
XkbGeometryRec *xkbgeometry;
EekBounds bounds;
gint i;
g_return_if_fail (priv->xkb);
g_return_if_fail (priv->xkb->geom);
xkbgeometry = priv->xkb->geom;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
setup_scaling (EEK_XKB_LAYOUT(layout), bounds.width, bounds.height);
bounds.x = bounds.y = 0;
bounds.width = xkb_to_pixmap_coord(layout, xkbgeometry->width_mm);
bounds.height = xkb_to_pixmap_coord(layout, xkbgeometry->height_mm);
for (i = 0; i < xkbgeometry->num_sections; i++) {
XkbSectionRec *xkbsection;
xkbsection = &xkbgeometry->sections[i];
create_section (layout, keyboard, xkbsection);
}
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
}
static EekKeyboard *
eek_xkb_layout_real_create_keyboard (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height)
{
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
keyboard->manager = manager;
EekBounds bounds = {
.x = 0.0,
.y = 0.0,
.width = initial_width,
.height = initial_height
};
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
/* resolve modifiers dynamically assigned at run time */
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
EEK_XKB_LAYOUT(self));
eek_keyboard_set_num_lock_mask (keyboard,
XkbKeysymToModifiers (priv->display,
XK_Num_Lock));
eek_keyboard_set_alt_gr_mask (keyboard,
XkbKeysymToModifiers (priv->display,
XK_ISO_Level3_Shift));
if (priv->shape_oref_hash)
g_hash_table_destroy (priv->shape_oref_hash);
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
g_hash_table_destroy (priv->shape_oref_hash);
return keyboard;
}
static void
eek_xkb_layout_finalize (GObject *object)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
EEK_XKB_LAYOUT (object));
g_free (priv->names.keycodes);
g_free (priv->names.geometry);
g_free (priv->names.symbols);
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
}
static void
eek_xkb_layout_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
switch (prop_id) {
case PROP_DISPLAY:
priv->display = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkb_layout_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
switch (prop_id) {
case PROP_DISPLAY:
g_value_set_pointer (value, priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
{
EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
layout_class->create_keyboard = eek_xkb_layout_real_create_keyboard;
gobject_class->finalize = eek_xkb_layout_finalize;
gobject_class->set_property = eek_xkb_layout_set_property;
gobject_class->get_property = eek_xkb_layout_get_property;
pspec = g_param_spec_pointer ("display",
"Display",
"X Display",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (gobject_class, PROP_DISPLAY, pspec);
}
static void
eek_xkb_layout_init (EekXkbLayout *self)
{
/* void */
}
static gboolean
get_names_from_server (EekXkbLayout *layout,
GError **error)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
gchar *name;
XkbGetNames (priv->display, XkbAllNamesMask, priv->xkb);
if (priv->xkb->names->keycodes <= 0)
g_warning ("XKB keycodes setting is not loaded properly");
else {
name = XGetAtomName (priv->display, priv->xkb->names->keycodes);
if (!name)
g_warning ("Can't get the name of keycodes");
else if (!priv->names.keycodes ||
g_strcmp0 (name, priv->names.keycodes)) {
g_free (priv->names.keycodes);
priv->names.keycodes = g_strdup (name);
XFree (name);
}
}
if (priv->xkb->names->geometry <= 0)
g_warning ("XKB geometry setting is not loaded");
else {
name = XGetAtomName (priv->display, priv->xkb->names->geometry);
if (!name)
g_warning ("Can't get the name of geometry");
else if (!priv->names.geometry ||
g_strcmp0 (name, priv->names.geometry)) {
g_free (priv->names.geometry);
priv->names.geometry = g_strdup (name);
XFree (name);
}
}
if (priv->xkb->names->symbols <= 0)
g_warning ("XKB symbols setting is not loaded");
else {
name = XGetAtomName (priv->display, priv->xkb->names->symbols);
if (!name)
g_warning ("Can't get the name of symbols");
else if (!priv->names.symbols ||
g_strcmp0 (name, priv->names.symbols)) {
g_free (priv->names.symbols);
priv->names.symbols = g_strdup (name);
XFree (name);
}
}
return TRUE;
}
/**
* eek_xkb_layout_new:
*
* Create a new #EekXkbLayout.
*/
EekLayout *
eek_xkb_layout_new (Display *display,
GError **error)
{
return (EekLayout *) g_initable_new (EEK_TYPE_XKB_LAYOUT,
NULL,
error,
"display", display,
NULL);
}
/**
* eek_xkb_layout_set_names: (skip)
* @layout: an #EekXkbLayout
* @names: XKB component names
* @error: a #GError
*
* Set the XKB component names to @layout.
* Returns: %TRUE if the component names are successfully set, %FALSE otherwise
*/
gboolean
eek_xkb_layout_set_names (EekXkbLayout *layout,
XkbComponentNamesRec *names,
GError **error)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
if (g_strcmp0 (names->keycodes, priv->names.keycodes)) {
g_free (priv->names.keycodes);
priv->names.keycodes = g_strdup (names->keycodes);
}
if (g_strcmp0 (names->geometry, priv->names.geometry)) {
g_free (priv->names.geometry);
priv->names.geometry = g_strdup (names->geometry);
}
if (g_strcmp0 (names->symbols, priv->names.symbols)) {
g_free (priv->names.symbols);
priv->names.symbols = g_strdup (names->symbols);
}
return get_keyboard_from_server (layout, error);
}
static gboolean
get_keyboard_from_server (EekXkbLayout *layout,
GError **error)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
if (priv->xkb) {
XkbFreeKeyboard (priv->xkb, 0, True);
priv->xkb = NULL;
}
if (priv->names.keycodes && priv->names.geometry && priv->names.symbols) {
priv->xkb = XkbGetKeyboardByName (priv->display,
XkbUseCoreKbd,
&priv->names,
0,
XKB_COMPONENT_MASK,
False);
} else {
priv->xkb = XkbGetKeyboard (priv->display,
XKB_COMPONENT_MASK,
XkbUseCoreKbd);
if (!get_names_from_server (layout, error)) {
XkbFreeKeyboard (priv->xkb, 0, True);
priv->xkb = NULL;
}
}
if (priv->xkb == NULL) {
g_set_error (error,
EEK_ERROR,
EEK_ERROR_LAYOUT_ERROR,
"can't get keyboard from server");
g_free (priv->names.keycodes);
priv->names.keycodes = NULL;
g_free (priv->names.geometry);
priv->names.geometry = NULL;
g_free (priv->names.symbols);
priv->names.symbols = NULL;
return FALSE;
}
return TRUE;
}
static guint
find_keycode (EekXkbLayout *layout, gchar *key_name)
{
#define KEYSYM_NAME_MAX_LENGTH 4
guint keycode;
gint i, j;
XkbKeyNamePtr pkey;
XkbKeyAliasPtr palias;
guint is_name_matched;
gchar *src, *dst;
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
if (!priv->xkb)
return EEK_INVALID_KEYCODE;
pkey = priv->xkb->names->keys + priv->xkb->min_key_code;
for (keycode = priv->xkb->min_key_code;
keycode <= priv->xkb->max_key_code; keycode++) {
is_name_matched = 1;
src = key_name;
dst = pkey->name;
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
if ('\0' == *src)
break;
if (*src++ != *dst++) {
is_name_matched = 0;
break;
}
}
if (is_name_matched)
return keycode;
pkey++;
}
palias = priv->xkb->names->key_aliases;
for (j = priv->xkb->names->num_key_aliases; --j >= 0;) {
is_name_matched = 1;
src = key_name;
dst = palias->alias;
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
if ('\0' == *src)
break;
if (*src++ != *dst++) {
is_name_matched = 0;
break;
}
}
if (is_name_matched) {
keycode = find_keycode (layout, palias->real);
return keycode;
}
palias++;
}
return EEK_INVALID_KEYCODE;
}
static void
setup_scaling (EekXkbLayout *layout,
gdouble width,
gdouble height)
{
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
g_return_if_fail (priv->xkb);
g_return_if_fail (priv->xkb->geom->width_mm > 0);
g_return_if_fail (priv->xkb->geom->height_mm > 0);
if (width * priv->xkb->geom->height_mm <
height * priv->xkb->geom->width_mm) {
priv->scale_numerator = width;
priv->scale_denominator = priv->xkb->geom->width_mm;
} else {
priv->scale_numerator = height;
priv->scale_denominator = priv->xkb->geom->height_mm;
}
}
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (initable);
if (!get_keyboard_from_server (layout, error))
return FALSE;
if (!get_names_from_server (layout, error))
return FALSE;
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
initable_iface->init = initable_init;
}

55
eek/eek-xkb-layout.h Normal file
View File

@ -0,0 +1,55 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek-xkb.h> can be included directly."
#endif
#ifndef EEK_XKB_LAYOUT_H
#define EEK_XKB_LAYOUT_H 1
#include <X11/XKBlib.h>
#include "eek-layout.h"
G_BEGIN_DECLS
#define EEK_TYPE_XKB_LAYOUT (eek_xkb_layout_get_type())
G_DECLARE_DERIVABLE_TYPE (EekXkbLayout, eek_xkb_layout, EEK, XKB_LAYOUT, EekLayout)
struct _EekXkbLayoutClass
{
/*< private >*/
EekLayoutClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_xkb_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xkb_layout_new (Display *display,
GError **error);
gboolean eek_xkb_layout_set_names (EekXkbLayout *layout,
XkbComponentNamesRec *names,
GError **error);
G_END_DECLS
#endif /* #ifndef EEK_XKB_LAYOUT_H */

26
eek/eek-xkb.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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_XKB_H
#define EEK_XKB_H 1
#include "eek.h"
#include "eek-xkb-layout.h"
#endif /* EEK_XKB_H */

30
eek/eek-xkl-0.90.pc.in Normal file
View File

@ -0,0 +1,30 @@
# 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
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libeek-xkl
Description: A Library to Create Keyboard-like UI (Libxklavier Support)
URL: http://fedorahosted.org/eekboard/
Version: @VERSION@
Requires: eek-@EEK_API_VERSION@ libxklavier
Libs: -L${libdir} -leek-xkl
Cflags: -I${includedir}/eek-@EEK_API_VERSION@

662
eek/eek-xkl-layout.c Normal file
View File

@ -0,0 +1,662 @@
/*
* 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
*/
/**
* SECTION:eek-xkl-layout
* @short_description: Layout engine using Libxklavier configuration
*
* The #EekXklLayout is a simple wrapper around #EekXkbLayout class
* to use Libxklavier configuration.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <libxklavier/xklavier.h>
#include <gio/gio.h>
#include <string.h>
#include "eek-xkl-layout.h"
#define noKBDRAW_DEBUG
static GInitableIface *parent_initable_iface;
static void initable_iface_init (GInitableIface *initable_iface);
enum {
PROP_0,
PROP_MODEL,
PROP_LAYOUTS,
PROP_VARIANTS,
PROP_OPTIONS,
PROP_LAST
};
typedef struct _EekXklLayoutPrivate
{
XklEngine *engine;
XklConfigRec *config;
} EekXklLayoutPrivate;
G_DEFINE_TYPE_EXTENDED (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekXklLayout)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init))
/* from gnome-keyboard-properties-xkbpv.c:
* BAD STYLE: Taken from xklavier_private_xkb.h
* Any ideas on architectural improvements are WELCOME
*/
extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
const XklConfigRec * data,
XkbComponentNamesPtr
component_names);
extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
XkbComponentNamesPtr
component_names);
static gboolean set_xkb_component_names (EekXklLayout *layout,
XklConfigRec *config);
static void
eek_xkl_layout_dispose (GObject *object)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (
EEK_XKL_LAYOUT (object));
if (priv->config) {
g_object_unref (priv->config);
priv->config = NULL;
}
G_OBJECT_CLASS (eek_xkl_layout_parent_class)->dispose (object);
}
static void
eek_xkl_layout_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
switch (prop_id) {
case PROP_MODEL:
eek_xkl_layout_set_model (layout, g_value_get_string (value));
break;
case PROP_LAYOUTS:
eek_xkl_layout_set_layouts (layout, g_value_get_boxed (value));
break;
case PROP_VARIANTS:
eek_xkl_layout_set_variants (layout, g_value_get_boxed (value));
break;
case PROP_OPTIONS:
eek_xkl_layout_set_options (layout, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkl_layout_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
switch (prop_id) {
case PROP_MODEL:
g_value_set_string (value,
eek_xkl_layout_get_model (layout));
break;
case PROP_LAYOUTS:
g_value_set_boxed (value,
eek_xkl_layout_get_layouts (layout));
break;
case PROP_VARIANTS:
g_value_set_boxed (value,
eek_xkl_layout_get_variants (layout));
break;
case PROP_OPTIONS:
g_value_set_boxed (value,
eek_xkl_layout_get_options (layout));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkl_layout_class_init (EekXklLayoutClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->dispose = eek_xkl_layout_dispose;
gobject_class->set_property = eek_xkl_layout_set_property;
gobject_class->get_property = eek_xkl_layout_get_property;
/**
* EekXklLayout:model:
*
* The libxklavier model name of #EekXklLayout.
*/
pspec = g_param_spec_string ("model",
"Model",
"Libxklavier model",
NULL,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODEL, pspec);
/**
* EekXklLayout:layouts:
*
* The libxklavier layout names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("layouts",
"Layouts",
"Libxklavier layouts",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LAYOUTS, pspec);
/**
* EekXklLayout:variants:
*
* The libxklavier variant names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("variants",
"Variants",
"Libxklavier variants",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_VARIANTS, pspec);
/**
* EekXklLayout:options:
*
* The libxklavier option names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("options",
"Options",
"Libxklavier options",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OPTIONS, pspec);
}
static void
eek_xkl_layout_init (EekXklLayout *self)
{
/* void */
}
/**
* eek_xkl_layout_new:
*
* Create a new #EekXklLayout.
*/
EekLayout *
eek_xkl_layout_new (Display *display, GError **error)
{
return (EekLayout *) g_initable_new (EEK_TYPE_XKL_LAYOUT,
NULL,
error,
"display", display,
NULL);
}
G_INLINE_FUNC void
merge_xkl_config_rec (XklConfigRec *dst, XklConfigRec *src)
{
if (src->model) {
g_free (dst->model);
dst->model = g_strdup (src->model);
}
if (src->layouts) {
g_strfreev (dst->layouts);
dst->layouts = g_strdupv (src->layouts);
}
if (src->variants) {
g_strfreev (dst->variants);
dst->variants = g_strdupv (src->variants);
}
if (src->options) {
g_strfreev (dst->options);
dst->options = g_strdupv (src->options);
}
}
/**
* eek_xkl_layout_set_config: (skip)
* @layout: an #EekXklLayout
* @config: Libxklavier configuration
*
* Reconfigure @layout with @config.
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_config (EekXklLayout *layout,
XklConfigRec *config)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XklConfigRec *c;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
c = xkl_config_rec_new ();
merge_xkl_config_rec (c, priv->config);
merge_xkl_config_rec (c, config);
retval = set_xkb_component_names (layout, c);
g_object_unref (c);
merge_xkl_config_rec (priv->config, config);
return retval;
}
/**
* eek_xkl_layout_set_config_full:
* @layout: an #EekXklLayout
* @model: Libxklavier model name
* @layouts: Libxklavier layouts
* @variants: Libxklavier variants
* @options: Libxklavier options
*
* Reconfigure @layout with @model, @layouts, @variants, and @options.
* This function is merely a wrapper around
* eek_xkl_layout_set_config() to avoid passing a pointer of
* XklConfigRec, which is not currently available in the
* gobject-introspection repository.
*
* Returns: %TRUE if the current layout changed, %FALSE otherwise
* Since: 0.0.2
*/
gboolean
eek_xkl_layout_set_config_full (EekXklLayout *layout,
gchar *model,
gchar **layouts,
gchar **variants,
gchar **options)
{
XklConfigRec *config;
gboolean retval;
config = xkl_config_rec_new ();
config->model = g_strdup (model);
config->layouts = g_strdupv (layouts);
config->variants = g_strdupv (variants);
config->options = g_strdupv (options);
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_model:
* @layout: an #EekXklLayout
* @model: model name
*
* Set the model name of @layout configuration (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_model (EekXklLayout *layout,
const gchar *model)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->model will be freed on g_object_unref (config) */
if (model)
config->model = g_strdup (model);
else
config->model = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_layouts:
* @layout: an #EekXklLayout
* @layouts: layout names
*
* Set the layout names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_layouts (EekXklLayout *layout,
gchar **layouts)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->layouts will be freed on g_object_unref (config) */
if (layouts)
config->layouts = g_strdupv (layouts);
else
config->layouts = layouts;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_variants:
* @layout: an #EekXklLayout
* @variants: variant names
*
* Set the variant names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_variants (EekXklLayout *layout,
gchar **variants)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->variants will be freed on g_object_unref (config) */
if (variants)
config->variants = g_strdupv (variants);
else
config->variants = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_options:
* @layout: an #EekXklLayout
* @options: option names
*
* Set the option names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_options (EekXklLayout *layout,
gchar **options)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->options will be freed on g_object_unref (config) */
if (options)
config->options = options;
else
config->options = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_enable_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Set the option of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_enable_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options, **_options;
gint i, j;
options = eek_xkl_layout_get_options (layout);
for (i = 0; options && options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
return TRUE;
_options = g_new0 (gchar *, (i + 2));
for (j = 0; j < i; j++)
_options[j] = g_strdup (options[j]);
_options[i] = g_strdup (option);
/* eek_xkl_layout_set_options() will free _options and its elements. */
return eek_xkl_layout_set_options (layout, _options);
}
/**
* eek_xkl_layout_disable_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Unset the option of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_disable_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options, **_options;
gint i, j, k;
options = eek_xkl_layout_get_options (layout);
if (!options)
return TRUE;
for (i = 0, k = 0; options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
k = i;
if (options[k] == NULL)
return TRUE;
_options = g_new0 (gchar *, i);
for (j = 0; j < k; j++)
_options[j] = g_strdup (options[j]);
for (j = k + 1; j < i; j++)
_options[j] = g_strdup (options[j]);
/* eek_xkl_layout_set_options() will free _options and its elements. */
return eek_xkl_layout_set_options (layout, _options);
}
/**
* eek_xkl_layout_get_model:
* @layout: an #EekXklLayout
*
* Get the model name of @layout configuration (in the Libxklavier terminology).
*/
gchar *
eek_xkl_layout_get_model (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
g_return_val_if_fail (priv, NULL);
return g_strdup (priv->config->model);
}
/**
* eek_xkl_layout_get_layouts:
* @layout: an #EekXklLayout
*
* Get the layout names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_layouts (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->layouts);
}
/**
* eek_xkl_layout_get_variants:
* @layout: an #EekXklLayout
*
* Get the variant names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_variants (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->variants);
}
/**
* eek_xkl_layout_get_options:
* @layout: an #EekXklLayout
*
* Get the option names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_options (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->options);
}
static gboolean
set_xkb_component_names (EekXklLayout *layout, XklConfigRec *config)
{
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
XkbComponentNamesRec names;
gboolean retval = FALSE;
#if DEBUG
if (config->layouts) {
gint i;
fprintf (stderr, "layout = ");
for (i = 0; config->layouts[i] != NULL; i++)
fprintf (stderr, "\"%s\" ", config->layouts[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "layouts = NULL\n");
if (config->variants) {
gint i;
fprintf (stderr, "variant = ");
for (i = 0; config->variants[i]; i++)
fprintf (stderr, "\"%s\" ", config->variants[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "variants = NULL\n");
if (config->options) {
gint i;
fprintf (stderr, "option = ");
for (i = 0; config->options[i]; i++)
fprintf (stderr, "\"%s\" ", config->options[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "options = NULL\n");
#endif
if (xkl_xkb_config_native_prepare (priv->engine, config, &names)) {
GError *error = NULL;
retval = eek_xkb_layout_set_names (EEK_XKB_LAYOUT(layout),
&names,
&error);
if (!retval)
g_warning ("can't set XKB layout");
xkl_xkb_config_native_cleanup (priv->engine, &names);
}
return retval;
}
/**
* eek_xkl_layout_get_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Tell if the option of @layout (in the Libxklavier terminology) is set.
* Returns: %TRUE if the option is set, %FALSE otherwise
*/
gboolean
eek_xkl_layout_get_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options;
gint i;
options = eek_xkl_layout_get_options (layout);
for (i = 0; options && options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
return TRUE;
return FALSE;
}
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
EekXklLayout *layout = EEK_XKL_LAYOUT (initable);
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
Display *display;
if (!parent_initable_iface->init (initable, cancellable, error))
return FALSE;
priv->config = xkl_config_rec_new ();
g_object_get (G_OBJECT (initable),
"display", &display,
NULL);
priv->engine = xkl_engine_get_instance (display);
if (!xkl_config_rec_get_from_server (priv->config,
priv->engine)) {
g_set_error (error,
EEK_ERROR,
EEK_ERROR_LAYOUT_ERROR,
"can't load libxklavier configuration");
return FALSE;
}
set_xkb_component_names (layout, priv->config);
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
parent_initable_iface = g_type_interface_peek_parent (initable_iface);
initable_iface->init = initable_init;
}

81
eek/eek-xkl-layout.h Normal file
View File

@ -0,0 +1,81 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek-xkl.h> can be included directly."
#endif
#ifndef EEK_XKL_LAYOUT_H
#define EEK_XKL_LAYOUT_H 1
#include <libxklavier/xklavier.h>
#include "eek-xkb-layout.h"
G_BEGIN_DECLS
#define EEK_TYPE_XKL_LAYOUT (eek_xkl_layout_get_type())
G_DECLARE_DERIVABLE_TYPE (EekXklLayout, eek_xkl_layout, EEK, XKL_LAYOUT, EekLayout)
struct _EekXklLayoutClass
{
/*< private >*/
EekXkbLayoutClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_xkl_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xkl_layout_new (Display *display,
GError **error);
gboolean eek_xkl_layout_set_config (EekXklLayout *layout,
XklConfigRec *config);
gboolean eek_xkl_layout_set_config_full (EekXklLayout *layout,
gchar *model,
gchar **layouts,
gchar **variants,
gchar **options);
gboolean eek_xkl_layout_set_model (EekXklLayout *layout,
const gchar *model);
gboolean eek_xkl_layout_set_layouts (EekXklLayout *layout,
gchar **layouts);
gboolean eek_xkl_layout_set_variants (EekXklLayout *layout,
gchar **variants);
gboolean eek_xkl_layout_set_options (EekXklLayout *layout,
gchar **options);
gboolean eek_xkl_layout_enable_option (EekXklLayout *layout,
const gchar *option);
gboolean eek_xkl_layout_disable_option (EekXklLayout *layout,
const gchar *option);
gchar *eek_xkl_layout_get_model (EekXklLayout *layout);
gchar **eek_xkl_layout_get_layouts (EekXklLayout *layout);
gchar **eek_xkl_layout_get_variants (EekXklLayout *layout);
gchar **eek_xkl_layout_get_options (EekXklLayout *layout);
gboolean eek_xkl_layout_get_option (EekXklLayout *layout,
const gchar *option);
G_END_DECLS
#endif /* #ifndef EEK_XKL_LAYOUT_H */

26
eek/eek-xkl.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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_XKL_H
#define EEK_XKL_H 1
#include "eek.h"
#include "eek-xkl-layout.h"
#endif /* EEK_XKL_H */

File diff suppressed because it is too large Load Diff

View File

@ -23,14 +23,44 @@
#ifndef EEK_XML_LAYOUT_H
#define EEK_XML_LAYOUT_H 1
#include "eek-types.h"
#include "src/layout.h"
#include <gio/gio.h>
#include "eek-layout.h"
G_BEGIN_DECLS
LevelKeyboard *
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
EekboardContextService *manager,
enum squeek_arrangement_kind t);
#define EEK_TYPE_XML_LAYOUT (eek_xml_layout_get_type())
G_DECLARE_DERIVABLE_TYPE (EekXmlLayout, eek_xml_layout, EEK, XML_LAYOUT, EekLayout)
/**
* EekXmlLayoutClass:
*/
struct _EekXmlLayoutClass
{
/*< private >*/
EekLayoutClass parent_class;
/* padding */
gpointer pdummy[24];
};
struct _EekXmlKeyboardDesc
{
gchar *id;
gchar *name;
gchar *geometry;
gchar *symbols;
gchar *language;
gchar *longname;
};
typedef struct _EekXmlKeyboardDesc EekXmlKeyboardDesc;
GType eek_xml_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xml_layout_new (const gchar *id,
GError **error);
GList *eek_xml_list_keyboards (void);
EekXmlKeyboardDesc *eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc);
void eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc);
G_END_DECLS
#endif /* EEK_XML_LAYOUT_H */

317
eek/eek-xml.c Normal file
View File

@ -0,0 +1,317 @@
/*
* 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/>.
*/
/**
* SECTION: eek-xml
* @title: XML Conversion Utilities
* @short_description: #EekKeyboard to XML conversion utilities
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdarg.h>
#include <glib/gprintf.h>
#include "eek-section.h"
#include "eek-key.h"
#include "eek-xml.h"
#include "eek-keysym.h"
#include "eek-text.h"
#define g_string_append_indent(string, indent) \
{ \
gint i; \
for (i = 0; i < (indent); i++) { \
g_string_append (string, " "); \
} \
}
void
g_string_markup_printf (GString *output, const gchar *format, ...)
{
gchar *escaped_text;
va_list ap;
va_start (ap, format);
escaped_text = g_markup_vprintf_escaped (format, ap);
va_end (ap);
g_string_append (output, escaped_text);
g_free (escaped_text);
}
struct _OutputCallbackData {
GString *output;
gint indent;
GHashTable *oref_hash;
gint key_serial;
};
typedef struct _OutputCallbackData OutputCallbackData;
static void
output_bounds (GString *output, EekBounds *bounds)
{
g_string_markup_printf (output,
"<bounds>%lf,%lf,%lf,%lf</bounds>\n",
bounds->x,
bounds->y,
bounds->width,
bounds->height);
}
static void
output_symbol_attributes (GString *output,
EekSymbol *symbol)
{
if (eek_symbol_get_name (symbol) != NULL)
g_string_markup_printf (output, " name=\"%s\"",
eek_symbol_get_name (symbol));
if (eek_symbol_get_label (symbol) != NULL)
g_string_markup_printf (output, " label=\"%s\"",
eek_symbol_get_label (symbol));
if (eek_symbol_get_category (symbol) != EEK_SYMBOL_CATEGORY_UNKNOWN)
g_string_markup_printf (output, " category=\"%s\"",
eek_symbol_category_get_name (eek_symbol_get_category (symbol)));
}
static void
output_key_callback (EekElement *element, gpointer user_data)
{
OutputCallbackData *data = user_data;
EekBounds bounds;
gint i, num_symbols;
EekSymbolMatrix *matrix;
gint column, row;
guint keycode;
gchar *id;
gulong oref;
keycode = eek_key_get_keycode (EEK_KEY(element));
if (keycode == EEK_INVALID_KEYCODE)
id = g_strdup_printf ("key%d", data->key_serial);
else
id = g_strdup_printf ("keycode%d", keycode);
data->key_serial++;
eek_key_get_index (EEK_KEY(element), &column, &row);
g_string_append_indent (data->output, data->indent);
if (eek_element_get_name (element))
g_string_markup_printf (data->output,
"<key id=\"%s\" name=\"%s\" "
"column=\"%d\" row=\"%d\">\n",
id,
eek_element_get_name (element),
column,
row);
else
g_string_markup_printf (data->output,
"<key id=\"%s\" "
"column=\"%d\" row=\"%d\">\n",
id,
column,
row);
g_free (id);
eek_element_get_bounds (element, &bounds);
g_string_append_indent (data->output, data->indent + 1);
output_bounds (data->output, &bounds);
oref = eek_key_get_oref (EEK_KEY(element));
if (oref != 0) {
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output,
"<oref>outline%u</oref>\n",
oref);
if (!g_hash_table_lookup (data->oref_hash, (gpointer)oref))
g_hash_table_insert (data->oref_hash,
(gpointer)oref,
(gpointer)TRUE);
}
matrix = eek_key_get_symbol_matrix (EEK_KEY(element));
num_symbols = matrix->num_groups * matrix->num_levels;
if (num_symbols > 0) {
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output,
"<symbols groups=\"%d\" levels=\"%d\">\n",
matrix->num_groups, matrix->num_levels);
for (i = 0; i < num_symbols; i++) {
EekSymbol *symbol = matrix->data[i];
g_string_append_indent (data->output, data->indent + 2);
if (EEK_IS_KEYSYM(symbol)) {
guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
g_string_markup_printf (data->output, "<keysym");
output_symbol_attributes (data->output, symbol);
if (xkeysym != EEK_INVALID_KEYSYM)
g_string_markup_printf (data->output, " keyval=\"%u\"",
xkeysym);
g_string_markup_printf (data->output, ">%s</keysym>\n",
eek_symbol_get_name (symbol));
}
else if (EEK_IS_TEXT(symbol)) {
g_string_markup_printf (data->output, "<text");
output_symbol_attributes (data->output, symbol);
g_string_markup_printf (data->output,
">%s</text>\n",
eek_text_get_text (EEK_TEXT(symbol)));
}
else {
g_string_markup_printf (data->output, "<symbol");
output_symbol_attributes (data->output, symbol);
g_string_markup_printf (data->output,
">%s</symbol>\n",
eek_symbol_get_name (symbol));
}
}
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "</symbols>\n");
}
g_string_append_indent (data->output, data->indent);
g_string_markup_printf (data->output, "</key>\n");
}
static void
output_section_callback (EekElement *element, gpointer user_data)
{
OutputCallbackData *data = user_data;
EekBounds bounds;
gint angle, n_rows, i;
g_string_append_indent (data->output, data->indent);
if (eek_element_get_name (element))
g_string_markup_printf (data->output, "<section name=\"%s\">\n",
eek_element_get_name (element));
else
g_string_markup_printf (data->output, "<section>\n");
eek_element_get_bounds (element, &bounds);
g_string_append_indent (data->output, data->indent + 1);
output_bounds (data->output, &bounds);
angle = eek_section_get_angle (EEK_SECTION(element));
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "<angle>%d</angle>\n", angle);
n_rows = eek_section_get_n_rows (EEK_SECTION(element));
for (i = 0; i < n_rows; i++) {
gint num_columns;
EekOrientation orientation;
eek_section_get_row (EEK_SECTION(element),
i,
&num_columns,
&orientation);
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "<row>\n");
g_string_append_indent (data->output, data->indent + 2);
g_string_markup_printf (data->output, "<columns>%d</columns>\n",
num_columns);
g_string_append_indent (data->output, data->indent + 2);
g_string_markup_printf (data->output, "<orientation>%d</orientation>\n",
orientation);
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "</row>\n");
}
data->indent++;
eek_container_foreach_child (EEK_CONTAINER(element),
output_key_callback,
data);
data->indent--;
g_string_append_indent (data->output, data->indent);
g_string_markup_printf (data->output, "</section>\n");
}
/**
* eek_keyboard_output:
* @keyboard: an #EekKeyboard
* @output: a GString
* @indent: an integer
*
* Convert @keyboard into the XML format and store it into @output.
*/
void
eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
{
OutputCallbackData data;
EekBounds bounds;
gulong oref;
GHashTableIter iter;
g_assert (EEK_IS_KEYBOARD(keyboard));
g_string_append_indent (output, indent);
if (eek_element_get_name (EEK_ELEMENT(keyboard)))
g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
"<keyboard version=\"%s\" id=\"%s\">\n",
EEK_XML_SCHEMA_VERSION,
eek_element_get_name (EEK_ELEMENT(keyboard)));
else
g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
"<keyboard version=\"%s\">\n",
EEK_XML_SCHEMA_VERSION);
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
g_string_append_indent (output, indent + 1);
output_bounds (output, &bounds);
data.output = output;
data.indent = indent;
data.oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
data.key_serial = 0;
data.indent++;
eek_container_foreach_child (EEK_CONTAINER(keyboard),
output_section_callback,
&data);
data.indent--;
g_hash_table_iter_init (&iter, data.oref_hash);
while (g_hash_table_iter_next (&iter, (gpointer *)&oref, NULL)) {
EekOutline *outline;
gint j;
outline = eek_keyboard_get_outline (keyboard, oref);
g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
g_string_append_indent (output, indent + 2);
g_string_markup_printf (output, "<corner-radius>%lf</corner-radius>\n",
outline->corner_radius);
for (j = 0; j < outline->num_points; j++) {
g_string_append_indent (output, indent + 2);
g_string_markup_printf (output, "<point>%lf,%lf</point>\n",
outline->points[j].x,
outline->points[j].y);
}
g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "</outline>\n");
}
g_hash_table_destroy (data.oref_hash);
g_string_append_indent (output, indent);
g_string_markup_printf (output, "</keyboard>\n");
}

Some files were not shown because too many files have changed in this diff Show More