Compare commits

..

2 Commits

Author SHA1 Message Date
e09dd2b4dc Disable and mark for expiry on July 51 2019-07-09 15:04:49 +02:00
5235b47827 Make compiler happier 2019-07-09 14:55:11 +02:00
149 changed files with 20522 additions and 5019 deletions

9
.gitignore vendored
View File

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

View File

@ -2,54 +2,20 @@ image: debian:buster
stages:
- build
- test
.tags: &tags
tags:
- librem5
before_script:
- apt-get -y update
- apt-get -y install wget ca-certificates gnupg
- apt-get -y install wget gnupg2
- 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
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
dependencies:
- build_meson
script:
- ninja -C _build test

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.2.0"
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.2.0 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
"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 /source_path '' 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 /source_path '' 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,23 +0,0 @@
#!/bin/bash
# This script manages Cargo operations
# while keeping the artifact directory within the build tree
# instead of the source tree
set -e
SOURCE_DIR="$1"
export CARGO_TARGET_DIR=`pwd`
if [ ! -z ${2} ]; then
OUT_PATH=`realpath "${2}"`
fi
cd $SOURCE_DIR
shift
shift
cargo $BUILD_ARG $@
if [ ! -z ${OUT_PATH} ]; then
cp "${CARGO_TARGET_DIR}"/debug/librs.a "${OUT_PATH}"
fi

View File

@ -1,20 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="sm.puri.OSK0">
<method name="SetVisible">
<arg name="visible" type="b" direction="in"/>
<doc:doc><doc:description>
Switch keyboard visibility
</doc:description></doc:doc>
</method>
<method name="GetVisible">
<arg name="visible" type="b" direction="out"/>
<doc:doc><doc:description>
Get keyboard visibility
</doc:description></doc:doc>
</method>
<property name="Visible" type="b" access="read">
</property>
</interface>
</node>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
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
L 7,23 L 0,15 L 7,7 L 10,7 L 10,10 L 7,13 L 17,13
C 19,13 20,12 20,10 L 20,1 Z"
stroke="none" fill="black" />
</svg>

Before

Width:  |  Height:  |  Size: 388 B

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
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"
stroke="none" fill="black" />
</svg>

Before

Width:  |  Height:  |  Size: 279 B

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg4043"
version="1.1"
viewBox="0 0 4.2333331 4.2333093"
height="4.2333093mm"
width="4.2333331mm">
<defs
id="defs4037" />
<metadata
id="metadata4040">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-86.329776,-68.097636)"
id="layer1">
<g
style="stroke-width:1.00004983;fill:#2e3436;fill-opacity:1"
transform="matrix(0.99990029,0,0,1,-7.1823833,-1.8799927)"
id="g842">
<g
style="stroke-width:1.00004983;fill:#2e3436;fill-opacity:1"
id="g836">
<path
id="path5166"
d="m 95.636719,69.978516 c -1.165869,0 -2.115235,0.949365 -2.115235,2.115234 0,1.165869 0.949366,2.117188 2.115235,2.117188 1.165869,0 2.117187,-0.951319 2.117187,-2.117188 0,-1.165869 -0.951318,-2.115234 -2.117187,-2.115234 z m 0,0.529296 c 0.879886,0 1.58789,0.706052 1.58789,1.585938 0,0.879886 -0.708004,1.587891 -1.58789,1.587891 -0.879886,0 -1.585938,-0.708005 -1.585938,-1.587891 0,-0.879886 0.706052,-1.585937 1.585938,-1.585938 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52919304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26459652;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 95.636719,70.109375 c -0.144398,0 -0.27248,0.07793 -0.373047,0.189453 -0.100567,0.111521 -0.18209,0.261405 -0.25,0.439453 -0.135821,0.356096 -0.214844,0.830395 -0.214844,1.355469 0,0.525074 0.07902,1.001326 0.214844,1.357422 0.06791,0.178048 0.149433,0.327932 0.25,0.439453 0.100567,0.111521 0.228649,0.1875 0.373047,0.1875 0.144397,0 0.27248,-0.07598 0.373047,-0.1875 0.100566,-0.111521 0.182089,-0.261405 0.25,-0.439453 0.135821,-0.356096 0.216797,-0.832348 0.216796,-1.357422 0,-0.525074 -0.08097,-0.999373 -0.216796,-1.355469 -0.06791,-0.178048 -0.149434,-0.327932 -0.25,-0.439453 -0.100567,-0.111521 -0.22865,-0.189453 -0.373047,-0.189453 z m 0,0.265625 c 0.05067,0 0.109272,0.02564 0.177734,0.101562 0.06846,0.07592 0.139293,0.198356 0.199219,0.355469 0.119851,0.314227 0.197266,0.763915 0.197266,1.261719 0,0.497804 -0.07742,0.949446 -0.197266,1.263672 -0.05993,0.157113 -0.130756,0.279549 -0.199219,0.355469 -0.06846,0.07592 -0.12706,0.101562 -0.177734,0.101562 -0.05067,0 -0.107319,-0.02564 -0.175781,-0.101562 -0.06846,-0.07592 -0.139294,-0.198356 -0.199219,-0.355469 C 95.141867,73.043196 95.0625,72.591554 95.0625,72.09375 c 0,-0.497804 0.07937,-0.947492 0.199219,-1.261719 0.05993,-0.157113 0.130756,-0.279549 0.199219,-0.355469 C 95.5294,70.400643 95.586045,70.375 95.636719,70.375 Z"
id="circle5168" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26459652;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 93.697266,71.962891 v 0.263671 h 3.96875 v -0.263671 z"
id="path5170" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,189 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0.000000" y="0.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key keycode="24" name="AD01" oref="outline2">
<bounds x="65.56097" y="42.14634" width="37.46341" height="52.44877"/>
</key>
<key keycode="25" name="AD02" oref="outline2">
<bounds x="106.1463" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="26" name="AD03" oref="outline2">
<bounds x="145.1707" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="27" name="AD04" oref="outline2">
<bounds x="185.7560" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="28" name="AD05" oref="outline2">
<bounds x="226.3414" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="29" name="AD06" oref="outline2">
<bounds x="266.9268" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="30" name="AD07" oref="outline2">
<bounds x="307.5121" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="31" name="AD08" oref="outline2">
<bounds x="348.0975" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="32" name="AD09" oref="outline2">
<bounds x="388.6829" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="33" name="AD10" oref="outline2">
<bounds x="429.2682" y="42.14634" width="37.46341" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key keycode="38" name="AC01" oref="outline2">
<bounds x="76.48780" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="39" name="AC02" oref="outline2">
<bounds x="115.5121" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="40" name="AC03" oref="outline2">
<bounds x="156.0975" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="41" name="AC04" oref="outline2">
<bounds x="196.6829" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="42" name="AC05" oref="outline2">
<bounds x="237.2682" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="43" name="AC06" oref="outline2">
<bounds x="277.8536" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="44" name="AC07" oref="outline2">
<bounds x="318.4390" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="45" name="AC08" oref="outline2">
<bounds x="359.0243" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="46" name="AC09" oref="outline2">
<bounds x="399.6097" y="82.73170" width="37.46341" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key keycode="50" name="LFSH" oref="altline">
<bounds x="3.121951" y="121.7560" width="88.97561" height="37.46341"/>
</key>
<key keycode="52" name="AB01" oref="outline2">
<bounds x="95.21951" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="53" name="AB02" oref="outline2">
<bounds x="135.8048" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="54" name="AB03" oref="outline2">
<bounds x="176.3902" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="55" name="AB04" oref="outline2">
<bounds x="215.4146" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="56" name="AB05" oref="outline2">
<bounds x="256.0000" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="57" name="AB06" oref="outline2">
<bounds x="296.5853" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="58" name="AB07" oref="outline2">
<bounds x="337.1707" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="22" name="BKSP" oref="altline">
<bounds x="529.1707" y="1.560976" width="79.60975" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key keycode="37" name="LCTL" oref="altline">
<bounds x="62.43902" y="162.3414" width="48.39024" height="37.46341"/>
</key>
<key keycode="66" name="ALTGR" oref="altline">
<bounds x="113.9512" y="162.3414" width="48.39024" height="37.46341"/>
</key>
<key keycode="65" name="SPCE" oref="spaceline">
<bounds x="165.4634" y="162.3414" width="217.5853" height="37.46341"/>
</key>
<key keycode="60" name="AB09" oref="outline2">
<bounds x="418.3414" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="36" name="RTRN" oref="outline7">
<bounds x="519.8048" y="82.73170" width="88.97561" height="37.46341"/>
</key>
</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

@ -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,179 +0,0 @@
---
bounds: { x: 0, y: 10, width: 426, height: 229 }
outlines:
default:
corner_radius: 1
bounds: { x: 0, y: 0, width: 32, height: 52 }
altline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
outline7:
corner_radius: 1
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
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: outline7
icon: "key-enter"
aring:
label: "å"
Aring:
label: "Å"
oslash:
label: "ø"
Oslash:
label: "Ø"
ae:
label: "æ"
AE:
label: "Æ"
asterisk:
label: "*"
asciitilde:
label: "~"
quoteleft:
label: "`"
bar:
label: "|"
U00B7:
label: "·"
squareroot:
label: "√"
Greek_pi:
label: "π"
division:
label: "÷"
multiply:
label: "×"
paragraph:
label: "¶"
Greek_tau:
label: "τ"
copyright:
label: "©"
numbersign:
label: "#"
U00AE:
label: "®"
at:
label: "@"
dollar:
label: "$"
U00A3:
label: "£"
percent:
label: "%"
EuroSign:
label: "€"
ampersand:
label: "&"
U00A5:
label: "¥"
minus:
label: "-"
asciicircum:
label: "^"
underscore:
label: "_"
degree:
label: "°"
plus:
label: "+"
equal:
label: "="
parenleft:
label: "("
parenright:
label: ")"
braceleft:
label: "{"
braceright:
label: "}"
comma:
label: ","
backslash:
label: "\\"
slash:
label: "/"
quotedbl:
label: "\""
quoteright:
label: "'"
less:
label: "<"
greater:
label: ">"
colon:
label: ":"
semicolon:
label: ";"
exclam:
label: "!"
question:
label: "?"
bracketleft:
label: "["
bracketright:
label: "]"

View File

@ -1,47 +0,0 @@
---
bounds: { x: 0, y: 10, width: 410, height: 229 }
outlines:
default:
corner_radius: 1
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
altline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
outline7:
corner_radius: 1
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 120.5853, height: 52 }
views:
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,304 @@
<?xml version="1.0"?>
<symbols version="0.90">
<key keycode="9" name="ESC">
<keysym keyval="65307">Escape</keysym>
</key>
<key keycode="67" name="FK01">
<keysym keyval="65470">F1</keysym>
</key>
<key keycode="68" name="FK02">
<keysym keyval="65471">F2</keysym>
</key>
<key keycode="69" name="FK03">
<keysym keyval="65472">F3</keysym>
</key>
<key keycode="70" name="FK04">
<keysym keyval="65473">F4</keysym>
</key>
<key keycode="71" name="FK05">
<keysym keyval="65474">F5</keysym>
</key>
<key keycode="72" name="FK06">
<keysym keyval="65475">F6</keysym>
</key>
<key keycode="73" name="FK07">
<keysym keyval="65476">F7</keysym>
</key>
<key keycode="74" name="FK08">
<keysym keyval="65477">F8</keysym>
</key>
<key keycode="75" name="FK09">
<keysym keyval="65478">F9</keysym>
</key>
<key keycode="76" name="FK10">
<keysym keyval="65479">F10</keysym>
</key>
<key keycode="95" name="FK11">
<keysym keyval="65480">F11</keysym>
</key>
<key keycode="96" name="FK12">
<keysym keyval="65481">F12</keysym>
</key>
<key keycode="49" name="TLDE">
<keysym keyval="96">quoteleft</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key keycode="10" name="AE01">
<keysym keyval="49">1</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key keycode="11" name="AE02">
<keysym keyval="50">2</keysym>
<keysym keyval="64">at</keysym>
</key>
<key keycode="12" name="AE03">
<keysym keyval="51">3</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key keycode="13" name="AE04">
<keysym keyval="52">4</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key keycode="14" name="AE05">
<keysym keyval="53">5</keysym>
<keysym keyval="37">percent</keysym>
<keysym keyval="8364">EuroSign</keysym>
</key>
<key keycode="15" name="AE06">
<keysym keyval="54">6</keysym>
<keysym keyval="94">asciicircum</keysym>
</key>
<key keycode="16" name="AE07">
<keysym keyval="55">7</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key keycode="17" name="AE08">
<keysym keyval="56">8</keysym>
<keysym keyval="42">asterisk</keysym>
</key>
<key keycode="18" name="AE09">
<keysym keyval="57">9</keysym>
<keysym keyval="40">parenleft</keysym>
</key>
<key keycode="19" name="AE10">
<keysym keyval="48">0</keysym>
<keysym keyval="41">parenright</keysym>
</key>
<key keycode="20" name="AE11">
<keysym keyval="45">minus</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key keycode="21" name="AE12">
<keysym keyval="61">equal</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key keycode="22" name="BKSP">
<keysym keyval="65288">BackSpace</keysym>
</key>
<key keycode="23" name="TAB">
<keysym keyval="65289">Tab</keysym>
<keysym keyval="65056">ISO_Left_Tab</keysym>
</key>
<key keycode="24" name="AD01">
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
<keysym keyval="49">1</keysym>
</key>
<key keycode="25" name="AD02">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
<keysym keyval="50">2</keysym>
</key>
<key keycode="26" name="AD03">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
<keysym keyval="51">3</keysym>
</key>
<key keycode="27" name="AD04">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
<keysym keyval="52">4</keysym>
</key>
<key keycode="28" name="AD05">
<keysym keyval="116">t</keysym>
<keysym keyval="84">T</keysym>
<keysym keyval="53">5</keysym>
</key>
<key keycode="29" name="AD06">
<keysym keyval="121">y</keysym>
<keysym keyval="89">Y</keysym>
<keysym keyval="54">6</keysym>
</key>
<key keycode="30" name="AD07">
<keysym keyval="117">u</keysym>
<keysym keyval="85">U</keysym>
<keysym keyval="55">7</keysym>
</key>
<key keycode="31" name="AD08">
<keysym keyval="105">i</keysym>
<keysym keyval="73">I</keysym>
<keysym keyval="56">8</keysym>
</key>
<key keycode="32" name="AD09">
<keysym keyval="111">o</keysym>
<keysym keyval="79">O</keysym>
<keysym keyval="57">9</keysym>
</key>
<key keycode="33" name="AD10">
<keysym keyval="112">p</keysym>
<keysym keyval="80">P</keysym>
<keysym keyval="48">0</keysym>
</key>
<key keycode="34" name="AD11">
<keysym keyval="91">bracketleft</keysym>
<keysym keyval="123">braceleft</keysym>
</key>
<key keycode="35" name="AD12">
<keysym keyval="93">bracketright</keysym>
<keysym keyval="125">braceright</keysym>
</key>
<key keycode="51" name="BKSL">
<keysym keyval="92">backslash</keysym>
<keysym keyval="124">bar</keysym>
</key>
<key keycode="66" name="ALTGR">
<keysym keyval="65027">ISO_Level3_Shift</keysym>
</key>
<key keycode="38" name="AC01">
<keysym keyval="97">a</keysym>
<keysym keyval="65">A</keysym>
<keysym keyval="64">at</keysym>
</key>
<key keycode="39" name="AC02">
<keysym keyval="115">s</keysym>
<keysym keyval="83">S</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key keycode="40" name="AC03">
<keysym keyval="100">d</keysym>
<keysym keyval="68">D</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key keycode="41" name="AC04">
<keysym keyval="102">f</keysym>
<keysym keyval="70">F</keysym>
<keysym keyval="37">percent</keysym>
</key>
<key keycode="42" name="AC05">
<keysym keyval="103">g</keysym>
<keysym keyval="71">G</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key keycode="43" name="AC06">
<keysym keyval="104">h</keysym>
<keysym keyval="72">H</keysym>
<keysym keyval="45">minus</keysym>
</key>
<key keycode="44" name="AC07">
<keysym keyval="106">j</keysym>
<keysym keyval="74">J</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key keycode="45" name="AC08">
<keysym keyval="107">k</keysym>
<keysym keyval="75">K</keysym>
<keysym keyval="123">braceleft</keysym>
</key>
<key keycode="46" name="AC09">
<keysym keyval="108">l</keysym>
<keysym keyval="76">L</keysym>
<keysym keyval="125">braceright</keysym>
</key>
<key keycode="47" name="AC10">
<keysym keyval="59">semicolon</keysym>
<keysym keyval="58">colon</keysym>
</key>
<key keycode="48" name="AC11">
<keysym keyval="39">quoteright</keysym>
<keysym keyval="34">quotedbl</keysym>
</key>
<key keycode="36" name="RTRN">
<keysym keyval="65293">Return</keysym>
</key>
<key keycode="50" name="LFSH">
<keysym keyval="65505">Shift_L</keysym>
</key>
<key keycode="52" name="AB01">
<keysym keyval="122">z</keysym>
<keysym keyval="90">Z</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key keycode="53" name="AB02">
<keysym keyval="120">x</keysym>
<keysym keyval="88">X</keysym>
<keysym keyval="34">quotedbl</keysym>
</key>
<key keycode="54" name="AB03">
<keysym keyval="99">c</keysym>
<keysym keyval="67">C</keysym>
<keysym keyval="39">quoteright</keysym>
</key>
<key keycode="55" name="AB04">
<keysym keyval="118">v</keysym>
<keysym keyval="86">V</keysym>
<keysym keyval="58">colon</keysym>
</key>
<key keycode="56" name="AB05">
<keysym keyval="98">b</keysym>
<keysym keyval="66">B</keysym>
<keysym keyval="59">semicolon</keysym>
</key>
<key keycode="57" name="AB06">
<keysym keyval="110">n</keysym>
<keysym keyval="78">N</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key keycode="58" name="AB07">
<keysym keyval="109">m</keysym>
<keysym keyval="77">M</keysym>
<keysym keyval="63">question</keysym>
</key>
<key keycode="59" name="AB08">
<keysym keyval="44">comma</keysym>
<keysym keyval="60">less</keysym>
</key>
<key keycode="60" name="AB09">
<keysym keyval="46">period</keysym>
<keysym keyval="62">greater</keysym>
</key>
<key keycode="61" name="AB10">
<keysym keyval="47">slash</keysym>
<keysym keyval="63">question</keysym>
</key>
<key keycode="62" name="RTSH">
<keysym keyval="65506">Shift_R</keysym>
</key>
<key keycode="149" name="I149">
<symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
</key>
<key keycode="150" name="I150">
<symbol label="☺" icon="preferences-system-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key keycode="37" name="LCTL">
<keysym keyval="65507">Control_L</keysym>
</key>
<key keycode="64" name="LALT">
<keysym keyval="65513">Alt_L</keysym>
<keysym keyval="65511">Meta_L</keysym>
</key>
<key keycode="65" name="SPCE">
<keysym keyval="32">space</keysym>
</key>
<key keycode="113" name="LEFT">
<keysym keyval="65361">Left</keysym>
</key>
<key keycode="111" name="UP">
<keysym keyval="65362">Up</keysym>
</key>
<key keycode="116" name="DOWN">
<keysym keyval="65364">Down</keysym>
</key>
<key keycode="114" name="RGHT">
<keysym keyval="65363">Right</keysym>
</key>
</symbols>

View File

@ -1,81 +0,0 @@
---
bounds: { x: 10, y: 10, width: 410, height: 229 }
outlines:
default:
corner_radius: 1
bounds: { x: 0, y: 0, width: 37.46341, height: 52 }
altline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 48.39024, height: 52 }
outline7:
corner_radius: 1
bounds: { x: 0, y: 0, width: 88.97561, height: 52 }
spaceline:
corner_radius: 1
bounds: { x: 0, y: 0, width: 150.5853, height: 52 }
views:
base:
- "q w e r t y u i o p"
- "a s d f g h j k l"
- "Shift_L z x c v b n m BackSpace"
- "show_numbers preferences space . Return"
upper:
- "Q W E R T Y U I O P"
- "A S D F G H J K L"
- "Shift_L Z X C V B N M BackSpace"
- "show_numbers preferences space . Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # $ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space . Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers \\ / < > = [ ] BackSpace"
- "show_letters preferences space . Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
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: "*/="
".":
outline: altline
space:
outline: spaceline
label: " "
Return:
outline: outline7
icon: "key-enter"
colon:
label: ":"
"\"":
keysym: "quotedbl"

View File

@ -1,12 +1,57 @@
gnome = import('gnome')
squeekboard_resources = gnome.compile_resources(
'squeekboard-resources',
'squeekboard.gresources.xml',
c_name: 'squeekboard',
install_data(
'themes/default.css',
install_dir: pkgdatadir + '/themes',
)
install_data(
'keyboards/keyboards.xml',
install_dir: pkgdatadir + '/keyboards/',
)
install_data(
'keyboards/geometry/compact.xml',
install_dir: pkgdatadir + '/keyboards/geometry/',
)
symbols = [
'ar.xml',
'as-inscript.xml',
'be.xml',
'bn-inscript.xml',
'fa.xml',
'gu-inscript.xml',
'he.xml',
'hi-inscript.xml',
'ja-kana.xml',
'kk.xml',
'kn-inscript.xml',
'ks-inscript.xml',
'ks.xml',
'mai-inscript.xml',
'ml-inscript.xml',
'mr-inscript.xml',
'my.xml',
'or-inscript.xml',
'pa-inscript.xml',
'ru.xml',
'sd-inscript.xml',
'ta-inscript.xml',
'te-inscript.xml',
'th.xml',
'ua.xml',
'ug.xml',
'us.xml',
'zh-bopomofo.xml',
]
foreach symbol: symbols
install_data(
'keyboards/symbols/' + symbol,
install_dir: pkgdatadir + '/keyboards/symbols/',
)
endforeach
desktop_file = 'sm.puri.Squeekboard.desktop'
i18n.merge_file('desktop',

View File

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

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</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>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/bn-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/fa.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/gu-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/he.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/hi-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ja-kana.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/kk.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/kn-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ks-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ks.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mai-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ml-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mr-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/my.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/or-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/pa-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ru.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/sd-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ta-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/te-inscript.xml</file>
<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/zh-bopomofo.xml</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>
<file>icons/keyboard-mode-symbolic.svg</file>
</gresource>
</gresources>

View File

@ -1,39 +0,0 @@
.keyboard {
background-color: rgba(0, 0, 0, 255);
color: #ffffff;
font-family: cantarell, sans-serif;
}
.key {
color: #deddda;
background: #464448;
border-style: solid;
border-width: 1px;
border-color: #5e5c64;
border-radius: 2px;
}
.key:active {
background: #1c71d8;
border-color: #3584e4;
}
#Return {
background: #1c71d8;
border-color: #1a5fb4
}
#Return:active {
background: #1c71d8;
border-color: #3584e4;
}
#Shift_L {
background: #2b292f;
border-color: #3e3a44
}
#Shift_L:active {
background: #1c71d8;
border-color: #3584e4;
}

18
data/themes/default.css Normal file
View File

@ -0,0 +1,18 @@
.keyboard {
background-color: rgba(0, 0, 0, 255);
color: #ffffff;
font-family: cantarell, sans-serif;
}
.key {
color: #deddda;
background: #464448;
border-width: 0.5px;
border-color: #5e5c64;
border-radius: 2px;
}
.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'

13
debian/changelog vendored
View File

@ -1,16 +1,3 @@
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

15
debian/control vendored
View File

@ -3,25 +3,16 @@ 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,
virtboard,
wayland-protocols (>= 1.14)
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard

57
debian/copyright vendored
View File

@ -1,60 +1,9 @@
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>
2010-2011 Red Hat, Inc.
2019 Purism SPC
License: GPL-3+
Files: eek/layersurface.c
src/wayland.c
src/key-emitter.c
meson.build
src/meson.build
po/meson.build
Copyright: 2018-2019 Purism SPC
License: GPL-3+
Files: eekboard/keymap.c
Copyright: 2000 Red Hat, Inc.
2019 Purism, SPC
License: LGPL-2+
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, see <http://www.gnu.org/licenses/>.
Files: protocols/wlr-layer-shell-unstable-v1.xml
Copytight: Copyright © 2017 Drew DeVault
License: X11
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee, provided
that the above copyright notice appear in all copies and fthat both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of the copyright holders not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. The copyright holders make
no representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright: 2019 Purism SPC
License: GPL-3+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

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:
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

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,13 +34,16 @@
#include <math.h>
#include <string.h>
#include "eek-renderer.h"
#include "eek-keyboard.h"
#include "eek-gtk-keyboard.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
};
@ -51,25 +56,37 @@ enum {
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
LevelKeyboard *keyboard;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
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 on_button_pressed (struct squeek_button *button, struct squeek_view *view,
EekGtkKeyboard *self);
static void on_button_released (const struct squeek_button *button,
struct squeek_view *view,
EekGtkKeyboard *self);
static void render_pressed_button (GtkWidget *widget, struct button_place *place);
static void render_locked_button (GtkWidget *widget,
struct button_place *place);
static void render_released_button (GtkWidget *widget,
const struct squeek_button *button);
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)
@ -80,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);
}
@ -93,43 +109,38 @@ 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, priv->scontext);
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));
}
eek_renderer_render_keyboard (priv->renderer, cr);
struct squeek_view *view = squeek_layout_get_current_view(priv->keyboard->layout);
/* redraw pressed key */
const GList *list = priv->keyboard->pressed_keys;
for (const GList *head = list; head; head = g_list_next (head)) {
struct button_place place = squeek_view_find_key(
view, head->data
);
if (place.button)
render_pressed_button (self, &place);
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 = priv->keyboard->locked_keys;
for (const GList *head = list; head; head = g_list_next (head)) {
struct button_place place = squeek_view_find_key(
view, ((EekModifierKey *)head->data)->key
);
if (place.button)
render_locked_button (self, &place);
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;
}
@ -151,85 +162,50 @@ 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);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
if (button) {
eek_keyboard_press_key(
priv->keyboard,
squeek_button_get_key(button),
time
);
on_button_pressed(button, view, self);
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);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
GList *list, *head;
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
list = g_list_copy(priv->keyboard->pressed_keys);
if (button) {
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)) {
struct squeek_key *key = head->data;
if (squeek_button_has_key(button, key)) {
if (head->data == key)
found = TRUE;
} else {
eek_keyboard_release_key(priv->keyboard, key, time);
// The released handler proceeds to ignore this info...
// let's do this for consistency nevertheless
struct button_place place = squeek_view_find_key(view, key);
on_button_released(place.button, view, self);
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,
squeek_button_get_key(button),
time
);
on_button_pressed(button, view, self);
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
}
} else {
for (head = list; head; head = g_list_next (head)) {
struct squeek_key *key = head->data;
eek_keyboard_release_key(priv->keyboard, key, time);
// The released handler proceeds to ignore this info...
// let's do this for consistency nevertheless
struct button_place place = squeek_view_find_key(view, key);
on_button_released(place.button, view, self);
}
g_list_free (list);
}
}
static void release(EekGtkKeyboard *self, guint32 time)
{
static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
GList *list = g_list_copy(priv->keyboard->pressed_keys);
GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (GList *head = list; head; head = g_list_next (head)) {
struct squeek_key *key = head->data;
EekKey *key = EEK_KEY(head->data);
eek_keyboard_release_key(priv->keyboard, key, time);
// The released handler proceeds to ignore this info...
// let's do this for consistency nevertheless
struct button_place place = squeek_view_find_key(view, key);
on_button_released(place.button, view, self);
on_key_released(key, self);
}
g_list_free (list);
}
@ -274,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;
}
@ -306,27 +282,80 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->keyboard) {
GList *head;
GList *list, *head;
for (head = priv->keyboard->pressed_keys; head; head = g_list_next (head)) {
/* Unlike other places where we call this, we don't call
on_button_released afterwards since we don't want to queue a
redraw. */
eek_keyboard_release_key(priv->keyboard, head->data,
gdk_event_get_time(NULL));
/* 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;
@ -342,20 +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) {
GList *head;
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);
for (head = priv->keyboard->pressed_keys; head; head = g_list_next (head)) {
eek_keyboard_release_key(priv->keyboard, head->data,
gdk_event_get_time(NULL));
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);
}
@ -364,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;
@ -375,29 +425,27 @@ 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)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* Create a default CSS provider and load a style sheet */
priv->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (priv->css_provider,
"/sm/puri/squeekboard/style.css");
/* Apply the style to the widget */
priv->scontext = gtk_widget_get_style_context (GTK_WIDGET(self));
gtk_style_context_add_class (priv->scontext, "keyboard");
gtk_style_context_add_provider (priv->scontext,
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_style_context_set_state (priv->scontext, GTK_STATE_FLAG_NORMAL);
/* void */
}
/**
@ -408,78 +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)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GtkAllocation allocation;
gdouble x, y;
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);
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);
}
eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
/*
* 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_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);
}
static void
render_locked_button (GtkWidget *widget, struct button_place *place)
render_locked_key (GtkWidget *widget,
EekKey *key)
{
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_render_button (priv->renderer, cr, place, 1.0, TRUE);
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);
}
// TODO: does it really redraw the entire keyboard?
static void
render_released_button (GtkWidget *widget,
const struct squeek_button *button)
render_released_key (GtkWidget *widget,
EekKey *key)
{
(void)button;
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);
}
static void
on_button_pressed (struct squeek_button *button,
struct squeek_view *view,
EekGtkKeyboard *self)
on_key_pressed (EekKey *key,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -487,15 +637,7 @@ on_button_pressed (struct squeek_button *button,
if (!priv->renderer)
return;
struct button_place place = {
.button = button,
.row = squeek_view_get_row(view, button),
};
if (!place.row) {
return;
}
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,
@ -507,19 +649,16 @@ on_button_pressed (struct squeek_button *button,
}
static void
on_button_released (const struct squeek_button *button,
struct squeek_view *view,
EekGtkKeyboard *self)
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,
@ -529,3 +668,55 @@ 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

@ -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 */

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

@ -0,0 +1,104 @@
/*
* 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;
cairo_surface_t *surface;
error = NULL;
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;
}
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 */

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 */

View File

@ -17,7 +17,9 @@
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <math.h>
#include <pango/pangocairo.h>

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,15 +27,56 @@
* 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/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"
enum {
PROP_0,
PROP_LAYOUT,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST
};
enum {
KEY_RELEASED,
KEY_LOCKED,
KEY_UNLOCKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
struct _EekKeyboardPrivate
{
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
GHashTable *keycodes;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
EekModifierType alt_gr_mask;
};
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
EekModifierKey *
eek_modifier_key_copy (EekModifierKey *modkey)
@ -46,107 +87,663 @@ eek_modifier_key_copy (EekModifierKey *modkey)
void
eek_modifier_key_free (EekModifierKey *modkey)
{
g_object_unref (modkey->key);
g_slice_free (EekModifierKey, modkey);
}
void
eek_keyboard_set_key_locked (LevelKeyboard *keyboard,
struct squeek_key *key)
static void
on_key_locked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = 0;
modifier_key->key = key;
keyboard->locked_keys =
g_list_prepend (keyboard->locked_keys, modifier_key);
}
/// Unlock all locked keys.
/// All locked keys will unlock at the next keypress (should be called "stuck")
/// Returns the number of handled keys
/// TODO: may need to check key type in order to chain locks
/// before pressing an "emitting" key
static int unlock_keys(LevelKeyboard *keyboard) {
int handled = 0;
for (GList *head = keyboard->locked_keys; head; ) {
EekModifierKey *modifier_key = head->data;
GList *next = g_list_next (head);
keyboard->locked_keys =
g_list_remove_link (keyboard->locked_keys, head);
//squeek_key_set_locked(squeek_button_get_key(modifier_key->button), false);
squeek_layout_set_state_from_press(keyboard->layout, keyboard, modifier_key->key);
g_list_free1 (head);
head = next;
handled++;
}
return handled;
g_signal_emit (keyboard, signals[KEY_LOCKED], 0, key);
}
static void
set_level_from_press (LevelKeyboard *keyboard, struct squeek_key *key)
on_key_unlocked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
// If the currently locked key was already handled in the unlock phase,
// then skip
if (unlock_keys(keyboard) == 0) {
squeek_layout_set_state_from_press(keyboard->layout, keyboard, key);
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)
{
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_insert (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode),
element);
}
static void
section_child_removed_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_remove (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode));
}
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;
}
}
void eek_keyboard_press_key(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp) {
squeek_key_set_pressed(key, TRUE);
keyboard->pressed_keys = g_list_prepend (keyboard->pressed_keys, key);
static void
eek_keyboard_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
// Only take action about setting level *after* the key has taken effect, i.e. on release
//set_level_from_press (keyboard, key);
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)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
gint level = 0;
if (priv->modifiers & priv->alt_gr_mask)
level |= 2;
if (priv->modifiers & EEK_SHIFT_MASK)
level |= 1;
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);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = squeek_key_get_keycode (key);
guint keycode = eek_key_get_keycode (key);
EekModifierType modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, TRUE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
}
void eek_keyboard_release_key(LevelKeyboard *keyboard,
struct squeek_key *key,
guint32 timestamp) {
for (GList *head = keyboard->pressed_keys; head; head = g_list_next (head)) {
if (squeek_key_equal(head->data, key)) {
keyboard->pressed_keys = g_list_remove_link (keyboard->pressed_keys, head);
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;
}
}
set_level_from_press (keyboard, key);
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);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = squeek_key_get_keycode (key);
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, FALSE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
}
void level_keyboard_deinit(LevelKeyboard *self) {
squeek_layout_free(self->layout);
}
void level_keyboard_free(LevelKeyboard *self) {
level_keyboard_deinit(self);
g_free(self);
}
void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) {
self->layout = layout;
}
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;
}
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
static void
eek_keyboard_dispose (GObject *object)
{
return squeek_layout_get_current_view(keyboard->layout);
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->keycodes);
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;
g_type_class_add_private (gobject_class,
sizeof (EekKeyboardPrivate));
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->keycodes = g_hash_table_new (g_direct_hash, g_direct_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_keycode:
* @keyboard: an #EekKeyboard
* @keycode: a keycode
*
* Find an #EekKey whose keycode is @keycode.
* Return value: (transfer none): #EekKey whose keycode is @keycode
*/
EekKey *
eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
guint keycode)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_hash_table_lookup (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode));
}
/**
* 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);
}
/**
* 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,56 +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
struct _EekModifierKey {
/*< public >*/
EekModifierType modifiers;
struct squeek_key *key;
};
typedef struct _EekModifierKey EekModifierKey;
#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))
/// Keyboard state holder
struct _LevelKeyboard {
struct squeek_layout *layout;
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
GList *pressed_keys; // struct squeek_key*
GList *locked_keys; // struct EekModifierKey*
guint id; // as a key to layout choices
EekboardContextService *manager; // unowned reference
};
typedef struct _LevelKeyboard LevelKeyboard;
/// Represents the path to the button within a view
struct button_place {
const struct squeek_row *row;
const struct squeek_button *button;
/**
* EekKeyboardClass:
* @create_section: virtual function for creating a section
* @find_key_by_keycode: virtual function for finding a key in the
* keyboard by keycode
* @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;
/* obsolete members moved to EekElement */
gpointer set_symbol_index;
gpointer get_symbol_index;
/*< public >*/
EekSection *(* create_section) (EekKeyboard *self);
EekKey *(* find_key_by_keycode) (EekKeyboard *self,
guint keycode);
/*< 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_keycode
(EekKeyboard *keyboard,
guint keycode);
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(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp);
void eek_keyboard_release_key(LevelKeyboard *keyboard, struct squeek_key *key, guint32 timestamp);
gchar * eek_keyboard_get_keymap
(LevelKeyboard *keyboard);
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);
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 "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,9 +66,8 @@ struct _EekRendererClass
};
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext,
GtkStyleContext *scontext);
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer,
gdouble width,
@ -66,27 +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 (EekRenderer *renderer,
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);
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,
gint scale);
gint size);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);
@ -99,18 +116,33 @@ void eek_renderer_set_default_background_color
const EekColor *color);
void eek_renderer_get_foreground_color
(EekRenderer *renderer,
GtkStyleContext *context,
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);
struct squeek_button *eek_renderer_find_button_by_position(EekRenderer *renderer, struct squeek_view *view,
EekKey *eek_renderer_find_key_by_position
(EekRenderer *renderer,
gdouble x,
gdouble y);
void eek_renderer_apply_transformation_for_button
void eek_renderer_apply_transformation_for_key
(EekRenderer *renderer,
cairo_t *cr, struct button_place *place,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_RENDERER_H */

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

@ -0,0 +1,562 @@
/*
* 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,
guint 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,
"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
* @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,
guint keycode,
gint column,
gint row)
{
g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section,
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);
}

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

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

View File

@ -25,18 +25,275 @@
* 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)
{
EekSymbol *self = g_new0(EekSymbol, 1);
self->name = g_strdup (name);
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
return self;
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;
}
/**
@ -50,8 +307,64 @@ void
eek_symbol_set_label (EekSymbol *symbol,
const gchar *label)
{
g_free (symbol->label);
symbol->label = g_strdup (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;
}
/**
@ -65,7 +378,11 @@ void
eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask)
{
symbol->modifier_mask = mask;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->modifier_mask = mask;
}
/**
@ -77,37 +394,131 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType
eek_symbol_get_modifier_mask (EekSymbol *symbol)
{
return 0;
return symbol->modifier_mask;
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_free (symbol->icon_name);
symbol->icon_name = g_strdup (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)
{
return NULL;
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_free (symbol->tooltip);
symbol->tooltip = g_strdup (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)
{
return NULL;
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
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 symbol->tooltip;
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__ */

1871
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__ */

1133
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>

View File

@ -134,7 +134,12 @@ typedef enum
#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;
@ -146,7 +151,6 @@ typedef struct _EekOutline EekOutline;
typedef struct _EekColor EekColor;
typedef struct _EekboardContextService EekboardContextService;
typedef struct _LevelKeyboard LevelKeyboard;
/**
* EekPoint:
@ -191,6 +195,12 @@ 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

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,11 +23,44 @@
#ifndef EEK_XML_LAYOUT_H
#define EEK_XML_LAYOUT_H 1
#include "eek-types.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);
#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");
}

39
eek/eek-xml.h Normal file
View File

@ -0,0 +1,39 @@
/*
* 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_XML_H
#define EEK_XML_H 1
#include <glib-object.h>
#include "eek-keyboard.h"
#include "eek-xml-layout.h"
G_BEGIN_DECLS
#define EEK_XML_SCHEMA_VERSION "0.90"
void eek_keyboard_output (EekKeyboard *keyboard,
GString *output,
gint indent);
G_END_DECLS
#endif /* EEK_XML_H */

View File

@ -23,7 +23,9 @@
* @title: Library Initialization
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek.h"

View File

@ -23,7 +23,15 @@
#define __EEK_H_INSIDE__ 1
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-layout.h"
#include "eek-symbol.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "eek-xml.h"
#include "eek-serializable.h"
#include "eek-theme.h"
void eek_init (void);

50
eek/gen-keysym-entries.py Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
# 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
# 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
import sys
import re
if len(sys.argv) > 3:
print("Usage: %s TABLE-NAME [INPUT_FILE]" % sys.argv[0], file=sys.stderr)
sys.exit(-1)
if len(sys.argv) < 3:
in_stream = sys.stdin
else:
in_stream = open(sys.argv[2])
table = dict()
for line in in_stream:
match = re.match(r'\s*(0x[0-9A-F]+)\s+(\S*)\s+(\S*)', line, re.I)
if match:
table[int(match.group(1), 16)] = (match.group(2), match.group(3))
sys.stdout.write("static const EekKeysymEntry %s[] = {\n" %
sys.argv[1])
for index, (keysym, (l, c)) in enumerate([(keysym, table[keysym])
for keysym in sorted(table.keys())]):
sys.stdout.write(" { 0x%X, %s, %s }" %
(keysym, l, c))
if index < len(table) - 1:
sys.stdout.write(",")
sys.stdout.write("\n")
sys.stdout.write("};\n")

View File

@ -65,9 +65,9 @@ static void layer_surface_configure(void *data,
uint32_t height)
{
PhoshLayerSurface *self = data;
gtk_window_resize (GTK_WINDOW (self), width, height);
zwlr_layer_surface_v1_ack_configure(surface, serial);
gtk_widget_show_all (GTK_WIDGET (self));
g_signal_emit (self, signals[CONFIGURED], 0);
}
@ -180,39 +180,22 @@ phosh_layer_surface_get_property (GObject *object,
static void
on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused)
phosh_layer_surface_constructed (GObject *object)
{
PhoshLayerSurfacePrivate *priv;
PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
GdkWindow *gdk_window;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
priv = phosh_layer_surface_get_instance_private (self);
gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
/* Realize the window so we can get the GDK window */
gtk_widget_realize(GTK_WIDGET (self));
gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
gdk_wayland_window_set_use_custom_surface (gdk_window);
priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
}
static void
on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
{
PhoshLayerSurfacePrivate *priv;
GdkWindow *gdk_window;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
priv = phosh_layer_surface_get_instance_private (self);
if (!priv->wl_surface) {
gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
gdk_wayland_window_set_use_custom_surface (gdk_window);
priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
}
g_debug ("Mapped %p", priv->wl_surface);
priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
priv->wl_surface,
priv->wl_output,
@ -226,45 +209,8 @@ on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
&layer_surface_listener,
self);
wl_surface_commit(priv->wl_surface);
/* Process all pending events, otherwise we end up sending ack configure
* to a not yet configured surface */
wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ()));
}
static void
on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
{
PhoshLayerSurfacePrivate *priv;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
priv = phosh_layer_surface_get_instance_private (self);
priv = phosh_layer_surface_get_instance_private (self);
if (priv->layer_surface) {
zwlr_layer_surface_v1_destroy(priv->layer_surface);
priv->layer_surface = NULL;
}
priv->wl_surface = NULL;
}
static void
phosh_layer_surface_constructed (GObject *object)
{
PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
g_signal_connect (self, "realize",
G_CALLBACK (on_phosh_layer_surface_realized),
NULL);
g_signal_connect (self, "map",
G_CALLBACK (on_phosh_layer_surface_mapped),
NULL);
g_signal_connect (self, "unmap",
G_CALLBACK (on_phosh_layer_surface_unmapped),
NULL);
}
static void
phosh_layer_surface_dispose (GObject *object)
{
@ -406,12 +352,6 @@ phosh_layer_surface_new (gpointer layer_shell,
"wl-output", wl_output);
}
/**
* phosh_layer_surface_get_surface:
*
* Get the layer layer surface or #NULL if the window
* is not yet realized.
*/
struct zwlr_layer_surface_v1 *
phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
{
@ -423,12 +363,6 @@ phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
}
/**
* phosh_layer_surface_get_wl_surface:
*
* Get the layer wayland surface or #NULL if the window
* is not yet realized.
*/
struct wl_surface *
phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
{

View File

@ -1,8 +1,44 @@
gnome = import('gnome')
enum_headers = [
'eek-symbol.h',
'eek-types.h',
]
enums = gnome.mkenums_simple('eek-enumtypes', sources: enum_headers)
marshalers = gnome.genmarshal(
'eek-marshalers',
sources: ['eek-marshalers.list'],
prefix: '_eek_marshal',
internal: true,
)
python = find_program('python3')
gen_keysym_entries_special = generator(
python,
arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'special_keysym_entries', '@INPUT@'],
capture: true,
output: 'eek-@BASENAME@.h',
)
gen_keysym_entries_unicode = generator(
python,
arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'unicode_keysym_entries', '@INPUT@'],
capture: true,
output: 'eek-@BASENAME@.h',
)
gen_keysym_entries_xkeysym = generator(
python,
arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'xkeysym_keysym_entries', '@INPUT@'],
capture: true,
output: 'eek-@BASENAME@.h',
)
keysym_entries = [
gen_keysym_entries_special.process('./special-keysym-entries.txt'),
gen_keysym_entries_unicode.process('./unicode-keysym-entries.txt'),
gen_keysym_entries_xkeysym.process('./xkeysym-keysym-entries.txt'),
]

View File

@ -0,0 +1,62 @@
0x20 "" EEK_SYMBOL_CATEGORY_LETTER
0x8A3 "horiz\nconn" EEK_SYMBOL_CATEGORY_LETTER
0xFE50 "ˋ" EEK_SYMBOL_CATEGORY_LETTER
0xFE51 "ˊ" EEK_SYMBOL_CATEGORY_LETTER
0xFE52 "ˆ" EEK_SYMBOL_CATEGORY_LETTER
0xFE53 "~" EEK_SYMBOL_CATEGORY_LETTER
0xFE54 "ˉ" EEK_SYMBOL_CATEGORY_LETTER
0xFE55 "˘" EEK_SYMBOL_CATEGORY_LETTER
0xFE56 "˙" EEK_SYMBOL_CATEGORY_LETTER
0xFE57 "¨" EEK_SYMBOL_CATEGORY_LETTER
0xFE58 "˚" EEK_SYMBOL_CATEGORY_LETTER
0xFE59 "˝" EEK_SYMBOL_CATEGORY_LETTER
0xFE5A "ˇ" EEK_SYMBOL_CATEGORY_LETTER
0xFE5B "¸" EEK_SYMBOL_CATEGORY_LETTER
0xFE5C "˛" EEK_SYMBOL_CATEGORY_LETTER
0xFF14 "Scroll\nLock" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF20 "Compose" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF55 "Page\nUp" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF56 "Page\nDown" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF7E "AltGr" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF7F "Num\nLock" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF8D "Enter" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF95 "Home" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF96 "Left" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF97 "Up" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF98 "Right" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF99 "Down" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF9C "End" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF9D "Begin" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF9E "Ins" EEK_SYMBOL_CATEGORY_FUNCTION
0xFF9F "Del" EEK_SYMBOL_CATEGORY_FUNCTION
# aliases
0xFE03 "123" EEK_SYMBOL_CATEGORY_KEYNAME
0xFE04 "⇮" EEK_SYMBOL_CATEGORY_KEYNAME
0xFE05 "⇮" EEK_SYMBOL_CATEGORY_KEYNAME
0xFE08 "Next" EEK_SYMBOL_CATEGORY_KEYNAME
0xFE0A "Prev" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF08 "←" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF09 "⇥" EEK_SYMBOL_CATEGORY_KEYNAME
0xFE20 "⇤" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF0D "↵" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF1B "Esc" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE1 "⇧" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE2 "⇧" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE3 "Ctrl" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE4 "Ctrl" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE5 "⇪" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE9 "Alt" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFEA "Alt" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE7 "Meta" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFE8 "Meta" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFEB "Super" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFEC "Super" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFED "Hyper" EEK_SYMBOL_CATEGORY_KEYNAME
0xFFEE "Hyper" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF2A "半" EEK_SYMBOL_CATEGORY_KEYNAME
0xFF21 "漢" EEK_SYMBOL_CATEGORY_KEYNAME
0xff51 "⇠" EEK_SYMBOL_CATEGORY_KEYNAME # 1
0xff52 "⇡" EEK_SYMBOL_CATEGORY_KEYNAME # 1
0xff53 "⇢" EEK_SYMBOL_CATEGORY_KEYNAME # 1
0xff54 "⇣" EEK_SYMBOL_CATEGORY_KEYNAME # 1
0xff30 "英" EEK_SYMBOL_CATEGORY_KEYNAME

View File

@ -0,0 +1,826 @@
# This file is derived from gdkkeyuni.c in GTK+. Thanks for the
# team. The original comments are below:
# Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
# file for a list of people on the GTK+ Team. See the ChangeLog
# files for a list of changes. These files are distributed with
# GTK+ at ftp://ftp.gtk.org/pub/gtk/.
# Thanks to Markus G. Kuhn <mkuhn@acm.org> for the ksysym<->Unicode
# mapping functions, from the xterm sources.
# These tables could be compressed by contiguous ranges, but the
# benefit of doing so is smallish. It would save about ~1000 bytes
# total.
0x01a1 "Ą" EEK_SYMBOL_CATEGORY_LETTER # Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK
0x01a2 "˘" EEK_SYMBOL_CATEGORY_LETTER # breve ˘ BREVE
0x01a3 "Ł" EEK_SYMBOL_CATEGORY_LETTER # Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE
0x01a5 "Ľ" EEK_SYMBOL_CATEGORY_LETTER # Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON
0x01a6 "Ś" EEK_SYMBOL_CATEGORY_LETTER # Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE
0x01a9 "Š" EEK_SYMBOL_CATEGORY_LETTER # Scaron Š LATIN CAPITAL LETTER S WITH CARON
0x01aa "Ş" EEK_SYMBOL_CATEGORY_LETTER # Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA
0x01ab "Ť" EEK_SYMBOL_CATEGORY_LETTER # Tcaron Ť LATIN CAPITAL LETTER T WITH CARON
0x01ac "Ź" EEK_SYMBOL_CATEGORY_LETTER # Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE
0x01ae "Ž" EEK_SYMBOL_CATEGORY_LETTER # Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON
0x01af "Ż" EEK_SYMBOL_CATEGORY_LETTER # Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE
0x01b1 "ą" EEK_SYMBOL_CATEGORY_LETTER # aogonek ą LATIN SMALL LETTER A WITH OGONEK
0x01b2 "˛" EEK_SYMBOL_CATEGORY_LETTER # ogonek ˛ OGONEK
0x01b3 "ł" EEK_SYMBOL_CATEGORY_LETTER # lstroke ł LATIN SMALL LETTER L WITH STROKE
0x01b5 "ľ" EEK_SYMBOL_CATEGORY_LETTER # lcaron ľ LATIN SMALL LETTER L WITH CARON
0x01b6 "ś" EEK_SYMBOL_CATEGORY_LETTER # sacute ś LATIN SMALL LETTER S WITH ACUTE
0x01b7 "ˇ" EEK_SYMBOL_CATEGORY_LETTER # caron ˇ CARON
0x01b9 "š" EEK_SYMBOL_CATEGORY_LETTER # scaron š LATIN SMALL LETTER S WITH CARON
0x01ba "ş" EEK_SYMBOL_CATEGORY_LETTER # scedilla ş LATIN SMALL LETTER S WITH CEDILLA
0x01bb "ť" EEK_SYMBOL_CATEGORY_LETTER # tcaron ť LATIN SMALL LETTER T WITH CARON
0x01bc "ź" EEK_SYMBOL_CATEGORY_LETTER # zacute ź LATIN SMALL LETTER Z WITH ACUTE
0x01bd "˝" EEK_SYMBOL_CATEGORY_LETTER # doubleacute ˝ DOUBLE ACUTE ACCENT
0x01be "ž" EEK_SYMBOL_CATEGORY_LETTER # zcaron ž LATIN SMALL LETTER Z WITH CARON
0x01bf "ż" EEK_SYMBOL_CATEGORY_LETTER # zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE
0x01c0 "Ŕ" EEK_SYMBOL_CATEGORY_LETTER # Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE
0x01c3 "Ă" EEK_SYMBOL_CATEGORY_LETTER # Abreve Ă LATIN CAPITAL LETTER A WITH BREVE
0x01c5 "Ĺ" EEK_SYMBOL_CATEGORY_LETTER # Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE
0x01c6 "Ć" EEK_SYMBOL_CATEGORY_LETTER # Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE
0x01c8 "Č" EEK_SYMBOL_CATEGORY_LETTER # Ccaron Č LATIN CAPITAL LETTER C WITH CARON
0x01ca "Ę" EEK_SYMBOL_CATEGORY_LETTER # Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK
0x01cc "Ě" EEK_SYMBOL_CATEGORY_LETTER # Ecaron Ě LATIN CAPITAL LETTER E WITH CARON
0x01cf "Ď" EEK_SYMBOL_CATEGORY_LETTER # Dcaron Ď LATIN CAPITAL LETTER D WITH CARON
0x01d0 "Đ" EEK_SYMBOL_CATEGORY_LETTER # Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE
0x01d1 "Ń" EEK_SYMBOL_CATEGORY_LETTER # Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE
0x01d2 "Ň" EEK_SYMBOL_CATEGORY_LETTER # Ncaron Ň LATIN CAPITAL LETTER N WITH CARON
0x01d5 "Ő" EEK_SYMBOL_CATEGORY_LETTER # Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
0x01d8 "Ř" EEK_SYMBOL_CATEGORY_LETTER # Rcaron Ř LATIN CAPITAL LETTER R WITH CARON
0x01d9 "Ů" EEK_SYMBOL_CATEGORY_LETTER # Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE
0x01db "Ű" EEK_SYMBOL_CATEGORY_LETTER # Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
0x01de "Ţ" EEK_SYMBOL_CATEGORY_LETTER # Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA
0x01e0 "ŕ" EEK_SYMBOL_CATEGORY_LETTER # racute ŕ LATIN SMALL LETTER R WITH ACUTE
0x01e3 "ă" EEK_SYMBOL_CATEGORY_LETTER # abreve ă LATIN SMALL LETTER A WITH BREVE
0x01e5 "ĺ" EEK_SYMBOL_CATEGORY_LETTER # lacute ĺ LATIN SMALL LETTER L WITH ACUTE
0x01e6 "ć" EEK_SYMBOL_CATEGORY_LETTER # cacute ć LATIN SMALL LETTER C WITH ACUTE
0x01e8 "č" EEK_SYMBOL_CATEGORY_LETTER # ccaron č LATIN SMALL LETTER C WITH CARON
0x01ea "ę" EEK_SYMBOL_CATEGORY_LETTER # eogonek ę LATIN SMALL LETTER E WITH OGONEK
0x01ec "ě" EEK_SYMBOL_CATEGORY_LETTER # ecaron ě LATIN SMALL LETTER E WITH CARON
0x01ef "ď" EEK_SYMBOL_CATEGORY_LETTER # dcaron ď LATIN SMALL LETTER D WITH CARON
0x01f0 "đ" EEK_SYMBOL_CATEGORY_LETTER # dstroke đ LATIN SMALL LETTER D WITH STROKE
0x01f1 "ń" EEK_SYMBOL_CATEGORY_LETTER # nacute ń LATIN SMALL LETTER N WITH ACUTE
0x01f2 "ň" EEK_SYMBOL_CATEGORY_LETTER # ncaron ň LATIN SMALL LETTER N WITH CARON
0x01f5 "ő" EEK_SYMBOL_CATEGORY_LETTER # odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE
0x01f8 "ř" EEK_SYMBOL_CATEGORY_LETTER # rcaron ř LATIN SMALL LETTER R WITH CARON
0x01f9 "ů" EEK_SYMBOL_CATEGORY_LETTER # uring ů LATIN SMALL LETTER U WITH RING ABOVE
0x01fb "ű" EEK_SYMBOL_CATEGORY_LETTER # udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE
0x01fe "ţ" EEK_SYMBOL_CATEGORY_LETTER # tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA
0x01ff "˙" EEK_SYMBOL_CATEGORY_LETTER # abovedot ˙ DOT ABOVE
0x02a1 "Ħ" EEK_SYMBOL_CATEGORY_LETTER # Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE
0x02a6 "Ĥ" EEK_SYMBOL_CATEGORY_LETTER # Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX
0x02a9 "İ" EEK_SYMBOL_CATEGORY_LETTER # Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE
0x02ab "Ğ" EEK_SYMBOL_CATEGORY_LETTER # Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE
0x02ac "Ĵ" EEK_SYMBOL_CATEGORY_LETTER # Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX
0x02b1 "ħ" EEK_SYMBOL_CATEGORY_LETTER # hstroke ħ LATIN SMALL LETTER H WITH STROKE
0x02b6 "ĥ" EEK_SYMBOL_CATEGORY_LETTER # hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX
0x02b9 "ı" EEK_SYMBOL_CATEGORY_LETTER # idotless ı LATIN SMALL LETTER DOTLESS I
0x02bb "ğ" EEK_SYMBOL_CATEGORY_LETTER # gbreve ğ LATIN SMALL LETTER G WITH BREVE
0x02bc "ĵ" EEK_SYMBOL_CATEGORY_LETTER # jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX
0x02c5 "Ċ" EEK_SYMBOL_CATEGORY_LETTER # Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE
0x02c6 "Ĉ" EEK_SYMBOL_CATEGORY_LETTER # Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX
0x02d5 "Ġ" EEK_SYMBOL_CATEGORY_LETTER # Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE
0x02d8 "Ĝ" EEK_SYMBOL_CATEGORY_LETTER # Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX
0x02dd "Ŭ" EEK_SYMBOL_CATEGORY_LETTER # Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE
0x02de "Ŝ" EEK_SYMBOL_CATEGORY_LETTER # Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX
0x02e5 "ċ" EEK_SYMBOL_CATEGORY_LETTER # cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE
0x02e6 "ĉ" EEK_SYMBOL_CATEGORY_LETTER # ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX
0x02f5 "ġ" EEK_SYMBOL_CATEGORY_LETTER # gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE
0x02f8 "ĝ" EEK_SYMBOL_CATEGORY_LETTER # gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX
0x02fd "ŭ" EEK_SYMBOL_CATEGORY_LETTER # ubreve ŭ LATIN SMALL LETTER U WITH BREVE
0x02fe "ŝ" EEK_SYMBOL_CATEGORY_LETTER # scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX
0x03a2 "ĸ" EEK_SYMBOL_CATEGORY_LETTER # kra ĸ LATIN SMALL LETTER KRA
0x03a3 "Ŗ" EEK_SYMBOL_CATEGORY_LETTER # Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA
0x03a5 "Ĩ" EEK_SYMBOL_CATEGORY_LETTER # Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE
0x03a6 "Ļ" EEK_SYMBOL_CATEGORY_LETTER # Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA
0x03aa "Ē" EEK_SYMBOL_CATEGORY_LETTER # Emacron Ē LATIN CAPITAL LETTER E WITH MACRON
0x03ab "Ģ" EEK_SYMBOL_CATEGORY_LETTER # Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA
0x03ac "Ŧ" EEK_SYMBOL_CATEGORY_LETTER # Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE
0x03b3 "ŗ" EEK_SYMBOL_CATEGORY_LETTER # rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA
0x03b5 "ĩ" EEK_SYMBOL_CATEGORY_LETTER # itilde ĩ LATIN SMALL LETTER I WITH TILDE
0x03b6 "ļ" EEK_SYMBOL_CATEGORY_LETTER # lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA
0x03ba "ē" EEK_SYMBOL_CATEGORY_LETTER # emacron ē LATIN SMALL LETTER E WITH MACRON
0x03bb "ģ" EEK_SYMBOL_CATEGORY_LETTER # gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA
0x03bc "ŧ" EEK_SYMBOL_CATEGORY_LETTER # tslash ŧ LATIN SMALL LETTER T WITH STROKE
0x03bd "Ŋ" EEK_SYMBOL_CATEGORY_LETTER # ENG Ŋ LATIN CAPITAL LETTER ENG
0x03bf "ŋ" EEK_SYMBOL_CATEGORY_LETTER # eng ŋ LATIN SMALL LETTER ENG
0x03c0 "Ā" EEK_SYMBOL_CATEGORY_LETTER # Amacron Ā LATIN CAPITAL LETTER A WITH MACRON
0x03c7 "Į" EEK_SYMBOL_CATEGORY_LETTER # Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK
0x03cc "Ė" EEK_SYMBOL_CATEGORY_LETTER # Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE
0x03cf "Ī" EEK_SYMBOL_CATEGORY_LETTER # Imacron Ī LATIN CAPITAL LETTER I WITH MACRON
0x03d1 "Ņ" EEK_SYMBOL_CATEGORY_LETTER # Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA
0x03d2 "Ō" EEK_SYMBOL_CATEGORY_LETTER # Omacron Ō LATIN CAPITAL LETTER O WITH MACRON
0x03d3 "Ķ" EEK_SYMBOL_CATEGORY_LETTER # Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA
0x03d9 "Ų" EEK_SYMBOL_CATEGORY_LETTER # Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK
0x03dd "Ũ" EEK_SYMBOL_CATEGORY_LETTER # Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE
0x03de "Ū" EEK_SYMBOL_CATEGORY_LETTER # Umacron Ū LATIN CAPITAL LETTER U WITH MACRON
0x03e0 "ā" EEK_SYMBOL_CATEGORY_LETTER # amacron ā LATIN SMALL LETTER A WITH MACRON
0x03e7 "į" EEK_SYMBOL_CATEGORY_LETTER # iogonek į LATIN SMALL LETTER I WITH OGONEK
0x03ec "ė" EEK_SYMBOL_CATEGORY_LETTER # eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE
0x03ef "ī" EEK_SYMBOL_CATEGORY_LETTER # imacron ī LATIN SMALL LETTER I WITH MACRON
0x03f1 "ņ" EEK_SYMBOL_CATEGORY_LETTER # ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA
0x03f2 "ō" EEK_SYMBOL_CATEGORY_LETTER # omacron ō LATIN SMALL LETTER O WITH MACRON
0x03f3 "ķ" EEK_SYMBOL_CATEGORY_LETTER # kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA
0x03f9 "ų" EEK_SYMBOL_CATEGORY_LETTER # uogonek ų LATIN SMALL LETTER U WITH OGONEK
0x03fd "ũ" EEK_SYMBOL_CATEGORY_LETTER # utilde ũ LATIN SMALL LETTER U WITH TILDE
0x03fe "ū" EEK_SYMBOL_CATEGORY_LETTER # umacron ū LATIN SMALL LETTER U WITH MACRON
0x047e "‾" EEK_SYMBOL_CATEGORY_LETTER # overline ‾ OVERLINE
0x04a1 "。" EEK_SYMBOL_CATEGORY_LETTER # kana_fullstop 。 IDEOGRAPHIC FULL STOP
0x04a2 "「" EEK_SYMBOL_CATEGORY_LETTER # kana_openingbracket 「 LEFT CORNER BRACKET
0x04a3 "」" EEK_SYMBOL_CATEGORY_LETTER # kana_closingbracket 」 RIGHT CORNER BRACKET
0x04a4 "、" EEK_SYMBOL_CATEGORY_LETTER # kana_comma 、 IDEOGRAPHIC COMMA
0x04a5 "・" EEK_SYMBOL_CATEGORY_LETTER # kana_conjunctive ・ KATAKANA MIDDLE DOT
0x04a6 "ヲ" EEK_SYMBOL_CATEGORY_LETTER # kana_WO ヲ KATAKANA LETTER WO
0x04a7 "ァ" EEK_SYMBOL_CATEGORY_LETTER # kana_a ァ KATAKANA LETTER SMALL A
0x04a8 "ィ" EEK_SYMBOL_CATEGORY_LETTER # kana_i ィ KATAKANA LETTER SMALL I
0x04a9 "ゥ" EEK_SYMBOL_CATEGORY_LETTER # kana_u ゥ KATAKANA LETTER SMALL U
0x04aa "ェ" EEK_SYMBOL_CATEGORY_LETTER # kana_e ェ KATAKANA LETTER SMALL E
0x04ab "ォ" EEK_SYMBOL_CATEGORY_LETTER # kana_o ォ KATAKANA LETTER SMALL O
0x04ac "ャ" EEK_SYMBOL_CATEGORY_LETTER # kana_ya ャ KATAKANA LETTER SMALL YA
0x04ad "ュ" EEK_SYMBOL_CATEGORY_LETTER # kana_yu ュ KATAKANA LETTER SMALL YU
0x04ae "ョ" EEK_SYMBOL_CATEGORY_LETTER # kana_yo ョ KATAKANA LETTER SMALL YO
0x04af "ッ" EEK_SYMBOL_CATEGORY_LETTER # kana_tsu ッ KATAKANA LETTER SMALL TU
0x04b0 "ー" EEK_SYMBOL_CATEGORY_LETTER # prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK
0x04b1 "ア" EEK_SYMBOL_CATEGORY_LETTER # kana_A ア KATAKANA LETTER A
0x04b2 "イ" EEK_SYMBOL_CATEGORY_LETTER # kana_I イ KATAKANA LETTER I
0x04b3 "ウ" EEK_SYMBOL_CATEGORY_LETTER # kana_U ウ KATAKANA LETTER U
0x04b4 "エ" EEK_SYMBOL_CATEGORY_LETTER # kana_E エ KATAKANA LETTER E
0x04b5 "オ" EEK_SYMBOL_CATEGORY_LETTER # kana_O オ KATAKANA LETTER O
0x04b6 "カ" EEK_SYMBOL_CATEGORY_LETTER # kana_KA カ KATAKANA LETTER KA
0x04b7 "キ" EEK_SYMBOL_CATEGORY_LETTER # kana_KI キ KATAKANA LETTER KI
0x04b8 "ク" EEK_SYMBOL_CATEGORY_LETTER # kana_KU ク KATAKANA LETTER KU
0x04b9 "ケ" EEK_SYMBOL_CATEGORY_LETTER # kana_KE ケ KATAKANA LETTER KE
0x04ba "コ" EEK_SYMBOL_CATEGORY_LETTER # kana_KO コ KATAKANA LETTER KO
0x04bb "サ" EEK_SYMBOL_CATEGORY_LETTER # kana_SA サ KATAKANA LETTER SA
0x04bc "シ" EEK_SYMBOL_CATEGORY_LETTER # kana_SHI シ KATAKANA LETTER SI
0x04bd "ス" EEK_SYMBOL_CATEGORY_LETTER # kana_SU ス KATAKANA LETTER SU
0x04be "セ" EEK_SYMBOL_CATEGORY_LETTER # kana_SE セ KATAKANA LETTER SE
0x04bf "ソ" EEK_SYMBOL_CATEGORY_LETTER # kana_SO ソ KATAKANA LETTER SO
0x04c0 "タ" EEK_SYMBOL_CATEGORY_LETTER # kana_TA タ KATAKANA LETTER TA
0x04c1 "チ" EEK_SYMBOL_CATEGORY_LETTER # kana_CHI チ KATAKANA LETTER TI
0x04c2 "ツ" EEK_SYMBOL_CATEGORY_LETTER # kana_TSU ツ KATAKANA LETTER TU
0x04c3 "テ" EEK_SYMBOL_CATEGORY_LETTER # kana_TE テ KATAKANA LETTER TE
0x04c4 "ト" EEK_SYMBOL_CATEGORY_LETTER # kana_TO ト KATAKANA LETTER TO
0x04c5 "ナ" EEK_SYMBOL_CATEGORY_LETTER # kana_NA ナ KATAKANA LETTER NA
0x04c6 "ニ" EEK_SYMBOL_CATEGORY_LETTER # kana_NI ニ KATAKANA LETTER NI
0x04c7 "ヌ" EEK_SYMBOL_CATEGORY_LETTER # kana_NU ヌ KATAKANA LETTER NU
0x04c8 "ネ" EEK_SYMBOL_CATEGORY_LETTER # kana_NE ネ KATAKANA LETTER NE
0x04c9 "" EEK_SYMBOL_CATEGORY_LETTER # kana_NO KATAKANA LETTER NO
0x04ca "ハ" EEK_SYMBOL_CATEGORY_LETTER # kana_HA ハ KATAKANA LETTER HA
0x04cb "ヒ" EEK_SYMBOL_CATEGORY_LETTER # kana_HI ヒ KATAKANA LETTER HI
0x04cc "フ" EEK_SYMBOL_CATEGORY_LETTER # kana_FU フ KATAKANA LETTER HU
0x04cd "ヘ" EEK_SYMBOL_CATEGORY_LETTER # kana_HE ヘ KATAKANA LETTER HE
0x04ce "ホ" EEK_SYMBOL_CATEGORY_LETTER # kana_HO ホ KATAKANA LETTER HO
0x04cf "マ" EEK_SYMBOL_CATEGORY_LETTER # kana_MA マ KATAKANA LETTER MA
0x04d0 "ミ" EEK_SYMBOL_CATEGORY_LETTER # kana_MI ミ KATAKANA LETTER MI
0x04d1 "ム" EEK_SYMBOL_CATEGORY_LETTER # kana_MU ム KATAKANA LETTER MU
0x04d2 "メ" EEK_SYMBOL_CATEGORY_LETTER # kana_ME メ KATAKANA LETTER ME
0x04d3 "モ" EEK_SYMBOL_CATEGORY_LETTER # kana_MO モ KATAKANA LETTER MO
0x04d4 "ヤ" EEK_SYMBOL_CATEGORY_LETTER # kana_YA ヤ KATAKANA LETTER YA
0x04d5 "ユ" EEK_SYMBOL_CATEGORY_LETTER # kana_YU ユ KATAKANA LETTER YU
0x04d6 "ヨ" EEK_SYMBOL_CATEGORY_LETTER # kana_YO ヨ KATAKANA LETTER YO
0x04d7 "ラ" EEK_SYMBOL_CATEGORY_LETTER # kana_RA ラ KATAKANA LETTER RA
0x04d8 "リ" EEK_SYMBOL_CATEGORY_LETTER # kana_RI リ KATAKANA LETTER RI
0x04d9 "ル" EEK_SYMBOL_CATEGORY_LETTER # kana_RU ル KATAKANA LETTER RU
0x04da "レ" EEK_SYMBOL_CATEGORY_LETTER # kana_RE レ KATAKANA LETTER RE
0x04db "ロ" EEK_SYMBOL_CATEGORY_LETTER # kana_RO ロ KATAKANA LETTER RO
0x04dc "ワ" EEK_SYMBOL_CATEGORY_LETTER # kana_WA ワ KATAKANA LETTER WA
0x04dd "ン" EEK_SYMBOL_CATEGORY_LETTER # kana_N ン KATAKANA LETTER N
0x04de "゛" EEK_SYMBOL_CATEGORY_LETTER # voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK
0x04df "゜" EEK_SYMBOL_CATEGORY_LETTER # semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
0x05ac "،" EEK_SYMBOL_CATEGORY_LETTER # Arabic_comma ، ARABIC COMMA
0x05bb "؛" EEK_SYMBOL_CATEGORY_LETTER # Arabic_semicolon ؛ ARABIC SEMICOLON
0x05bf "؟" EEK_SYMBOL_CATEGORY_LETTER # Arabic_question_mark ؟ ARABIC QUESTION MARK
0x05c1 "ء" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hamza ء ARABIC LETTER HAMZA
0x05c2 "آ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE
0x05c3 "أ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE
0x05c4 "ؤ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE
0x05c5 "إ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW
0x05c6 "ئ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE
0x05c7 "ا" EEK_SYMBOL_CATEGORY_LETTER # Arabic_alef ا ARABIC LETTER ALEF
0x05c8 "ب" EEK_SYMBOL_CATEGORY_LETTER # Arabic_beh ب ARABIC LETTER BEH
0x05c9 "ة" EEK_SYMBOL_CATEGORY_LETTER # Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA
0x05ca "ت" EEK_SYMBOL_CATEGORY_LETTER # Arabic_teh ت ARABIC LETTER TEH
0x05cb "ث" EEK_SYMBOL_CATEGORY_LETTER # Arabic_theh ث ARABIC LETTER THEH
0x05cc "ج" EEK_SYMBOL_CATEGORY_LETTER # Arabic_jeem ج ARABIC LETTER JEEM
0x05cd "ح" EEK_SYMBOL_CATEGORY_LETTER # Arabic_hah ح ARABIC LETTER HAH
0x05ce "خ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_khah خ ARABIC LETTER KHAH
0x05cf "د" EEK_SYMBOL_CATEGORY_LETTER # Arabic_dal د ARABIC LETTER DAL
0x05d0 "ذ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_thal ذ ARABIC LETTER THAL
0x05d1 "ر" EEK_SYMBOL_CATEGORY_LETTER # Arabic_ra ر ARABIC LETTER REH
0x05d2 "ز" EEK_SYMBOL_CATEGORY_LETTER # Arabic_zain ز ARABIC LETTER ZAIN
0x05d3 "س" EEK_SYMBOL_CATEGORY_LETTER # Arabic_seen س ARABIC LETTER SEEN
0x05d4 "ش" EEK_SYMBOL_CATEGORY_LETTER # Arabic_sheen ش ARABIC LETTER SHEEN
0x05d5 "ص" EEK_SYMBOL_CATEGORY_LETTER # Arabic_sad ص ARABIC LETTER SAD
0x05d6 "ض" EEK_SYMBOL_CATEGORY_LETTER # Arabic_dad ض ARABIC LETTER DAD
0x05d7 "ط" EEK_SYMBOL_CATEGORY_LETTER # Arabic_tah ط ARABIC LETTER TAH
0x05d8 "ظ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_zah ظ ARABIC LETTER ZAH
0x05d9 "ع" EEK_SYMBOL_CATEGORY_LETTER # Arabic_ain ع ARABIC LETTER AIN
0x05da "غ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_ghain غ ARABIC LETTER GHAIN
0x05e0 "ـ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_tatweel ـ ARABIC TATWEEL
0x05e1 "ف" EEK_SYMBOL_CATEGORY_LETTER # Arabic_feh ف ARABIC LETTER FEH
0x05e2 "ق" EEK_SYMBOL_CATEGORY_LETTER # Arabic_qaf ق ARABIC LETTER QAF
0x05e3 "ك" EEK_SYMBOL_CATEGORY_LETTER # Arabic_kaf ك ARABIC LETTER KAF
0x05e4 "ل" EEK_SYMBOL_CATEGORY_LETTER # Arabic_lam ل ARABIC LETTER LAM
0x05e5 "م" EEK_SYMBOL_CATEGORY_LETTER # Arabic_meem م ARABIC LETTER MEEM
0x05e6 "ن" EEK_SYMBOL_CATEGORY_LETTER # Arabic_noon ن ARABIC LETTER NOON
0x05e7 "ه" EEK_SYMBOL_CATEGORY_LETTER # Arabic_ha ه ARABIC LETTER HEH
0x05e8 "و" EEK_SYMBOL_CATEGORY_LETTER # Arabic_waw و ARABIC LETTER WAW
0x05e9 "ى" EEK_SYMBOL_CATEGORY_LETTER # Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA
0x05ea "ي" EEK_SYMBOL_CATEGORY_LETTER # Arabic_yeh ي ARABIC LETTER YEH
0x05eb "ً" EEK_SYMBOL_CATEGORY_LETTER # Arabic_fathatan ً ARABIC FATHATAN
0x05ec "ٌ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_dammatan ٌ ARABIC DAMMATAN
0x05ed "ٍ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_kasratan ٍ ARABIC KASRATAN
0x05ee "َ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_fatha َ ARABIC FATHA
0x05ef "ُ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_damma ُ ARABIC DAMMA
0x05f0 "ِ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_kasra ِ ARABIC KASRA
0x05f1 "ّ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_shadda ّ ARABIC SHADDA
0x05f2 "ْ" EEK_SYMBOL_CATEGORY_LETTER # Arabic_sukun ْ ARABIC SUKUN
0x06a1 "ђ" EEK_SYMBOL_CATEGORY_LETTER # Serbian_dje ђ CYRILLIC SMALL LETTER DJE
0x06a2 "ѓ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE
0x06a3 "ё" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_io ё CYRILLIC SMALL LETTER IO
0x06a4 "є" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE
0x06a5 "ѕ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE
0x06a6 "і" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
0x06a7 "ї" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_yi ї CYRILLIC SMALL LETTER YI
0x06a8 "ј" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_je ј CYRILLIC SMALL LETTER JE
0x06a9 "љ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_lje љ CYRILLIC SMALL LETTER LJE
0x06aa "њ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_nje њ CYRILLIC SMALL LETTER NJE
0x06ab "ћ" EEK_SYMBOL_CATEGORY_LETTER # Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE
0x06ac "ќ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_kje ќ CYRILLIC SMALL LETTER KJE
0x06ad "ґ" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN
0x06ae "ў" EEK_SYMBOL_CATEGORY_LETTER # Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U
0x06af "џ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE
0x06b0 "№" EEK_SYMBOL_CATEGORY_LETTER # numerosign № NUMERO SIGN
0x06b1 "Ђ" EEK_SYMBOL_CATEGORY_LETTER # Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE
0x06b2 "Ѓ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE
0x06b3 "Ё" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO
0x06b4 "Є" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE
0x06b5 "Ѕ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE
0x06b6 "І" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
0x06b7 "Ї" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI
0x06b8 "Ј" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE
0x06b9 "Љ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE
0x06ba "Њ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE
0x06bb "Ћ" EEK_SYMBOL_CATEGORY_LETTER # Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE
0x06bc "Ќ" EEK_SYMBOL_CATEGORY_LETTER # Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE
0x06bd "Ґ" EEK_SYMBOL_CATEGORY_LETTER # Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN
0x06be "Ў" EEK_SYMBOL_CATEGORY_LETTER # Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U
0x06bf "Џ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE
0x06c0 "ю" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_yu ю CYRILLIC SMALL LETTER YU
0x06c1 "а" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_a а CYRILLIC SMALL LETTER A
0x06c2 "б" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_be б CYRILLIC SMALL LETTER BE
0x06c3 "ц" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_tse ц CYRILLIC SMALL LETTER TSE
0x06c4 "д" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_de д CYRILLIC SMALL LETTER DE
0x06c5 "е" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ie е CYRILLIC SMALL LETTER IE
0x06c6 "ф" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ef ф CYRILLIC SMALL LETTER EF
0x06c7 "г" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ghe г CYRILLIC SMALL LETTER GHE
0x06c8 "х" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ha х CYRILLIC SMALL LETTER HA
0x06c9 "и" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_i и CYRILLIC SMALL LETTER I
0x06ca "й" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I
0x06cb "к" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ka к CYRILLIC SMALL LETTER KA
0x06cc "л" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_el л CYRILLIC SMALL LETTER EL
0x06cd "м" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_em м CYRILLIC SMALL LETTER EM
0x06ce "н" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_en н CYRILLIC SMALL LETTER EN
0x06cf "о" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_o о CYRILLIC SMALL LETTER O
0x06d0 "п" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_pe п CYRILLIC SMALL LETTER PE
0x06d1 "я" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ya я CYRILLIC SMALL LETTER YA
0x06d2 "р" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_er р CYRILLIC SMALL LETTER ER
0x06d3 "с" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_es с CYRILLIC SMALL LETTER ES
0x06d4 "т" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_te т CYRILLIC SMALL LETTER TE
0x06d5 "у" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_u у CYRILLIC SMALL LETTER U
0x06d6 "ж" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE
0x06d7 "в" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ve в CYRILLIC SMALL LETTER VE
0x06d8 "ь" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN
0x06d9 "ы" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU
0x06da "з" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ze з CYRILLIC SMALL LETTER ZE
0x06db "ш" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_sha ш CYRILLIC SMALL LETTER SHA
0x06dc "э" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_e э CYRILLIC SMALL LETTER E
0x06dd "щ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA
0x06de "ч" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_che ч CYRILLIC SMALL LETTER CHE
0x06df "ъ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN
0x06e0 "Ю" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU
0x06e1 "А" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_A А CYRILLIC CAPITAL LETTER A
0x06e2 "Б" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE
0x06e3 "Ц" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE
0x06e4 "Д" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE
0x06e5 "Е" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE
0x06e6 "Ф" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF
0x06e7 "Г" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE
0x06e8 "Х" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA
0x06e9 "И" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_I И CYRILLIC CAPITAL LETTER I
0x06ea "Й" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I
0x06eb "К" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_KA К CYRILLIC CAPITAL LETTER KA
0x06ec "Л" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL
0x06ed "М" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_EM М CYRILLIC CAPITAL LETTER EM
0x06ee "Н" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN
0x06ef "О" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_O О CYRILLIC CAPITAL LETTER O
0x06f0 "П" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_PE П CYRILLIC CAPITAL LETTER PE
0x06f1 "Я" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA
0x06f2 "Р" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER
0x06f3 "С" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ES С CYRILLIC CAPITAL LETTER ES
0x06f4 "Т" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE
0x06f5 "У" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_U У CYRILLIC CAPITAL LETTER U
0x06f6 "Ж" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE
0x06f7 "В" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_VE В CYRILLIC CAPITAL LETTER VE
0x06f8 "Ь" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN
0x06f9 "Ы" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU
0x06fa "З" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE
0x06fb "Ш" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA
0x06fc "Э" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_E Э CYRILLIC CAPITAL LETTER E
0x06fd "Щ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA
0x06fe "Ч" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE
0x06ff "Ъ" EEK_SYMBOL_CATEGORY_LETTER # Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN
0x07a1 "Ά" EEK_SYMBOL_CATEGORY_LETTER # Geek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS
0x07a2 "Έ" EEK_SYMBOL_CATEGORY_LETTER # Geek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS
0x07a3 "Ή" EEK_SYMBOL_CATEGORY_LETTER # Geek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS
0x07a4 "Ί" EEK_SYMBOL_CATEGORY_LETTER # Geek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS
0x07a5 "Ϊ" EEK_SYMBOL_CATEGORY_LETTER # Geek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
0x07a7 "Ό" EEK_SYMBOL_CATEGORY_LETTER # Geek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS
0x07a8 "Ύ" EEK_SYMBOL_CATEGORY_LETTER # Geek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS
0x07a9 "Ϋ" EEK_SYMBOL_CATEGORY_LETTER # Geek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
0x07ab "Ώ" EEK_SYMBOL_CATEGORY_LETTER # Geek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS
0x07ae "΅" EEK_SYMBOL_CATEGORY_LETTER # Geek_accentdieresis ΅ GREEK DIALYTIKA TONOS
0x07af "―" EEK_SYMBOL_CATEGORY_LETTER # Geek_horizbar ― HORIZONTAL BAR
0x07b1 "ά" EEK_SYMBOL_CATEGORY_LETTER # Geek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS
0x07b2 "έ" EEK_SYMBOL_CATEGORY_LETTER # Geek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS
0x07b3 "ή" EEK_SYMBOL_CATEGORY_LETTER # Geek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS
0x07b4 "ί" EEK_SYMBOL_CATEGORY_LETTER # Geek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS
0x07b5 "ϊ" EEK_SYMBOL_CATEGORY_LETTER # Geek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA
0x07b6 "ΐ" EEK_SYMBOL_CATEGORY_LETTER # Geek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
0x07b7 "ό" EEK_SYMBOL_CATEGORY_LETTER # Geek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS
0x07b8 "ύ" EEK_SYMBOL_CATEGORY_LETTER # Geek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS
0x07b9 "ϋ" EEK_SYMBOL_CATEGORY_LETTER # Geek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA
0x07ba "ΰ" EEK_SYMBOL_CATEGORY_LETTER # Geek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
0x07bb "ώ" EEK_SYMBOL_CATEGORY_LETTER # Geek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS
0x07c1 "Α" EEK_SYMBOL_CATEGORY_LETTER # Geek_ALPHA Α GREEK CAPITAL LETTER ALPHA
0x07c2 "Β" EEK_SYMBOL_CATEGORY_LETTER # Geek_BETA Β GREEK CAPITAL LETTER BETA
0x07c3 "Γ" EEK_SYMBOL_CATEGORY_LETTER # Geek_GAMMA Γ GREEK CAPITAL LETTER GAMMA
0x07c4 "Δ" EEK_SYMBOL_CATEGORY_LETTER # Geek_DELTA Δ GREEK CAPITAL LETTER DELTA
0x07c5 "Ε" EEK_SYMBOL_CATEGORY_LETTER # Geek_EPSILON Ε GREEK CAPITAL LETTER EPSILON
0x07c6 "Ζ" EEK_SYMBOL_CATEGORY_LETTER # Geek_ZETA Ζ GREEK CAPITAL LETTER ZETA
0x07c7 "Η" EEK_SYMBOL_CATEGORY_LETTER # Geek_ETA Η GREEK CAPITAL LETTER ETA
0x07c8 "Θ" EEK_SYMBOL_CATEGORY_LETTER # Geek_THETA Θ GREEK CAPITAL LETTER THETA
0x07c9 "Ι" EEK_SYMBOL_CATEGORY_LETTER # Geek_IOTA Ι GREEK CAPITAL LETTER IOTA
0x07ca "Κ" EEK_SYMBOL_CATEGORY_LETTER # Geek_KAPPA Κ GREEK CAPITAL LETTER KAPPA
0x07cb "Λ" EEK_SYMBOL_CATEGORY_LETTER # Geek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA
0x07cc "Μ" EEK_SYMBOL_CATEGORY_LETTER # Geek_MU Μ GREEK CAPITAL LETTER MU
0x07cd "Ν" EEK_SYMBOL_CATEGORY_LETTER # Geek_NU Ν GREEK CAPITAL LETTER NU
0x07ce "Ξ" EEK_SYMBOL_CATEGORY_LETTER # Geek_XI Ξ GREEK CAPITAL LETTER XI
0x07cf "Ο" EEK_SYMBOL_CATEGORY_LETTER # Geek_OMICRON Ο GREEK CAPITAL LETTER OMICRON
0x07d0 "Π" EEK_SYMBOL_CATEGORY_LETTER # Geek_PI Π GREEK CAPITAL LETTER PI
0x07d1 "Ρ" EEK_SYMBOL_CATEGORY_LETTER # Geek_RHO Ρ GREEK CAPITAL LETTER RHO
0x07d2 "Σ" EEK_SYMBOL_CATEGORY_LETTER # Geek_SIGMA Σ GREEK CAPITAL LETTER SIGMA
0x07d4 "Τ" EEK_SYMBOL_CATEGORY_LETTER # Geek_TAU Τ GREEK CAPITAL LETTER TAU
0x07d5 "Υ" EEK_SYMBOL_CATEGORY_LETTER # Geek_UPSILON Υ GREEK CAPITAL LETTER UPSILON
0x07d6 "Φ" EEK_SYMBOL_CATEGORY_LETTER # Geek_PHI Φ GREEK CAPITAL LETTER PHI
0x07d7 "Χ" EEK_SYMBOL_CATEGORY_LETTER # Geek_CHI Χ GREEK CAPITAL LETTER CHI
0x07d8 "Ψ" EEK_SYMBOL_CATEGORY_LETTER # Geek_PSI Ψ GREEK CAPITAL LETTER PSI
0x07d9 "Ω" EEK_SYMBOL_CATEGORY_LETTER # Geek_OMEGA Ω GREEK CAPITAL LETTER OMEGA
0x07e1 "α" EEK_SYMBOL_CATEGORY_LETTER # Geek_alpha α GREEK SMALL LETTER ALPHA
0x07e2 "β" EEK_SYMBOL_CATEGORY_LETTER # Geek_beta β GREEK SMALL LETTER BETA
0x07e3 "γ" EEK_SYMBOL_CATEGORY_LETTER # Geek_gamma γ GREEK SMALL LETTER GAMMA
0x07e4 "δ" EEK_SYMBOL_CATEGORY_LETTER # Geek_delta δ GREEK SMALL LETTER DELTA
0x07e5 "ε" EEK_SYMBOL_CATEGORY_LETTER # Geek_epsilon ε GREEK SMALL LETTER EPSILON
0x07e6 "ζ" EEK_SYMBOL_CATEGORY_LETTER # Geek_zeta ζ GREEK SMALL LETTER ZETA
0x07e7 "η" EEK_SYMBOL_CATEGORY_LETTER # Geek_eta η GREEK SMALL LETTER ETA
0x07e8 "θ" EEK_SYMBOL_CATEGORY_LETTER # Geek_theta θ GREEK SMALL LETTER THETA
0x07e9 "ι" EEK_SYMBOL_CATEGORY_LETTER # Geek_iota ι GREEK SMALL LETTER IOTA
0x07ea "κ" EEK_SYMBOL_CATEGORY_LETTER # Geek_kappa κ GREEK SMALL LETTER KAPPA
0x07eb "λ" EEK_SYMBOL_CATEGORY_LETTER # Geek_lambda λ GREEK SMALL LETTER LAMDA
0x07ec "μ" EEK_SYMBOL_CATEGORY_LETTER # Geek_mu μ GREEK SMALL LETTER MU
0x07ed "ν" EEK_SYMBOL_CATEGORY_LETTER # Geek_nu ν GREEK SMALL LETTER NU
0x07ee "ξ" EEK_SYMBOL_CATEGORY_LETTER # Geek_xi ξ GREEK SMALL LETTER XI
0x07ef "ο" EEK_SYMBOL_CATEGORY_LETTER # Geek_omicron ο GREEK SMALL LETTER OMICRON
0x07f0 "π" EEK_SYMBOL_CATEGORY_LETTER # Geek_pi π GREEK SMALL LETTER PI
0x07f1 "ρ" EEK_SYMBOL_CATEGORY_LETTER # Geek_rho ρ GREEK SMALL LETTER RHO
0x07f2 "σ" EEK_SYMBOL_CATEGORY_LETTER # Geek_sigma σ GREEK SMALL LETTER SIGMA
0x07f3 "ς" EEK_SYMBOL_CATEGORY_LETTER # Geek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA
0x07f4 "τ" EEK_SYMBOL_CATEGORY_LETTER # Geek_tau τ GREEK SMALL LETTER TAU
0x07f5 "υ" EEK_SYMBOL_CATEGORY_LETTER # Geek_upsilon υ GREEK SMALL LETTER UPSILON
0x07f6 "φ" EEK_SYMBOL_CATEGORY_LETTER # Geek_phi φ GREEK SMALL LETTER PHI
0x07f7 "χ" EEK_SYMBOL_CATEGORY_LETTER # Geek_chi χ GREEK SMALL LETTER CHI
0x07f8 "ψ" EEK_SYMBOL_CATEGORY_LETTER # Geek_psi ψ GREEK SMALL LETTER PSI
0x07f9 "ω" EEK_SYMBOL_CATEGORY_LETTER # Geek_omega ω GREEK SMALL LETTER OMEGA
# 0x08a1 leftradical ? ???
# 0x08a2 topleftradical ? ???
# 0x08a3 horizconnector ? ???
0x08a4 "⌠" EEK_SYMBOL_CATEGORY_LETTER # topintegral ⌠ TOP HALF INTEGRAL
0x08a5 "⌡" EEK_SYMBOL_CATEGORY_LETTER # botintegral ⌡ BOTTOM HALF INTEGRAL
0x08a6 "│" EEK_SYMBOL_CATEGORY_LETTER # vertconnector │ BOX DRAWINGS LIGHT VERTICAL
# 0x08a7 topleftsqbracket ? ???
# 0x08a8 botleftsqbracket ? ???
# 0x08a9 toprightsqbracket ? ???
# 0x08aa botrightsqbracket ? ???
# 0x08ab topleftparens ? ???
# 0x08ac botleftparens ? ???
# 0x08ad toprightparens ? ???
# 0x08ae botrightparens ? ???
# 0x08af leftmiddlecurlybrace ? ???
# 0x08b0 rightmiddlecurlybrace ? ???
# 0x08b1 topleftsummation ? ???
# 0x08b2 botleftsummation ? ???
# 0x08b3 topvertsummationconnector ? ???
# 0x08b4 botvertsummationconnector ? ???
# 0x08b5 toprightsummation ? ???
# 0x08b6 botrightsummation ? ???
# 0x08b7 rightmiddlesummation ? ???
0x08bc "≤" EEK_SYMBOL_CATEGORY_LETTER # lessthanequal ≤ LESS-THAN OR EQUAL TO
0x08bd "≠" EEK_SYMBOL_CATEGORY_LETTER # notequal ≠ NOT EQUAL TO
0x08be "≥" EEK_SYMBOL_CATEGORY_LETTER # greaterthanequal ≥ GREATER-THAN OR EQUAL TO
0x08bf "∫" EEK_SYMBOL_CATEGORY_LETTER # integral ∫ INTEGRAL
0x08c0 "∴" EEK_SYMBOL_CATEGORY_LETTER # therefore ∴ THEREFORE
0x08c1 "∝" EEK_SYMBOL_CATEGORY_LETTER # variation ∝ PROPORTIONAL TO
0x08c2 "∞" EEK_SYMBOL_CATEGORY_LETTER # infinity ∞ INFINITY
0x08c5 "∇" EEK_SYMBOL_CATEGORY_LETTER # nabla ∇ NABLA
0x08c8 "≅" EEK_SYMBOL_CATEGORY_LETTER # approximate ≅ APPROXIMATELY EQUAL TO
# 0x08c9 similarequal ? ???
0x08cd "⇔" EEK_SYMBOL_CATEGORY_LETTER # ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW
0x08ce "⇒" EEK_SYMBOL_CATEGORY_LETTER # implies ⇒ RIGHTWARDS DOUBLE ARROW
0x08cf "≡" EEK_SYMBOL_CATEGORY_LETTER # identical ≡ IDENTICAL TO
0x08d6 "√" EEK_SYMBOL_CATEGORY_LETTER # radical √ SQUARE ROOT
0x08da "⊂" EEK_SYMBOL_CATEGORY_LETTER # includedin ⊂ SUBSET OF
0x08db "⊃" EEK_SYMBOL_CATEGORY_LETTER # includes ⊃ SUPERSET OF
0x08dc "∩" EEK_SYMBOL_CATEGORY_LETTER # intersection ∩ INTERSECTION
0x08dd "" EEK_SYMBOL_CATEGORY_LETTER # union UNION
0x08de "∧" EEK_SYMBOL_CATEGORY_LETTER # logicaland ∧ LOGICAL AND
0x08df "" EEK_SYMBOL_CATEGORY_LETTER # logicalor LOGICAL OR
0x08ef "∂" EEK_SYMBOL_CATEGORY_LETTER # partialderivative ∂ PARTIAL DIFFERENTIAL
0x08f6 "ƒ" EEK_SYMBOL_CATEGORY_LETTER # function ƒ LATIN SMALL LETTER F WITH HOOK
0x08fb "←" EEK_SYMBOL_CATEGORY_LETTER # leftarrow ← LEFTWARDS ARROW
0x08fc "↑" EEK_SYMBOL_CATEGORY_LETTER # uparrow ↑ UPWARDS ARROW
0x08fd "→" EEK_SYMBOL_CATEGORY_LETTER # rightarrow → RIGHTWARDS ARROW
0x08fe "↓" EEK_SYMBOL_CATEGORY_LETTER # downarrow ↓ DOWNWARDS ARROW
0x09df "␢" EEK_SYMBOL_CATEGORY_LETTER # blank ␢ BLANK SYMBOL
0x09e0 "◆" EEK_SYMBOL_CATEGORY_LETTER # soliddiamond ◆ BLACK DIAMOND
0x09e1 "▒" EEK_SYMBOL_CATEGORY_LETTER # checkerboard ▒ MEDIUM SHADE
0x09e2 "␉" EEK_SYMBOL_CATEGORY_LETTER # ht ␉ SYMBOL FOR HORIZONTAL TABULATION
0x09e3 "␌" EEK_SYMBOL_CATEGORY_LETTER # ff ␌ SYMBOL FOR FORM FEED
0x09e4 "␍" EEK_SYMBOL_CATEGORY_LETTER # cr ␍ SYMBOL FOR CARRIAGE RETURN
0x09e5 "␊" EEK_SYMBOL_CATEGORY_LETTER # lf ␊ SYMBOL FOR LINE FEED
0x09e8 "␤" EEK_SYMBOL_CATEGORY_LETTER # nl ␤ SYMBOL FOR NEWLINE
0x09e9 "␋" EEK_SYMBOL_CATEGORY_LETTER # vt ␋ SYMBOL FOR VERTICAL TABULATION
0x09ea "┘" EEK_SYMBOL_CATEGORY_LETTER # lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT
0x09eb "┐" EEK_SYMBOL_CATEGORY_LETTER # uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT
0x09ec "┌" EEK_SYMBOL_CATEGORY_LETTER # upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT
0x09ed "└" EEK_SYMBOL_CATEGORY_LETTER # lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT
0x09ee "┼" EEK_SYMBOL_CATEGORY_LETTER # crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
# 0x09ef horizlinescan1 ? ???
# 0x09f0 horizlinescan3 ? ???
0x09f1 "─" EEK_SYMBOL_CATEGORY_LETTER # horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL
# 0x09f2 horizlinescan7 ? ???
# 0x09f3 horizlinescan9 ? ???
0x09f4 "├" EEK_SYMBOL_CATEGORY_LETTER # leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT
0x09f5 "┤" EEK_SYMBOL_CATEGORY_LETTER # rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT
0x09f6 "┴" EEK_SYMBOL_CATEGORY_LETTER # bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL
0x09f7 "┬" EEK_SYMBOL_CATEGORY_LETTER # topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
0x09f8 "│" EEK_SYMBOL_CATEGORY_LETTER # vertbar │ BOX DRAWINGS LIGHT VERTICAL
0x0aa1 "" EEK_SYMBOL_CATEGORY_LETTER # emspace EM SPACE
0x0aa2 "" EEK_SYMBOL_CATEGORY_LETTER # enspace EN SPACE
0x0aa3 "" EEK_SYMBOL_CATEGORY_LETTER # em3space THREE-PER-EM SPACE
0x0aa4 "" EEK_SYMBOL_CATEGORY_LETTER # em4space FOUR-PER-EM SPACE
0x0aa5 "" EEK_SYMBOL_CATEGORY_LETTER # digitspace FIGURE SPACE
0x0aa6 "" EEK_SYMBOL_CATEGORY_LETTER # punctspace PUNCTUATION SPACE
0x0aa7 "" EEK_SYMBOL_CATEGORY_LETTER # thinspace THIN SPACE
0x0aa8 "" EEK_SYMBOL_CATEGORY_LETTER # hairspace HAIR SPACE
0x0aa9 "—" EEK_SYMBOL_CATEGORY_LETTER # emdash — EM DASH
0x0aaa "" EEK_SYMBOL_CATEGORY_LETTER # endash EN DASH
# 0x0aac signifblank ? ???
0x0aae "…" EEK_SYMBOL_CATEGORY_LETTER # ellipsis … HORIZONTAL ELLIPSIS
# 0x0aaf doubbaselinedot ? ???
0x0ab0 "⅓" EEK_SYMBOL_CATEGORY_LETTER # onethird ⅓ VULGAR FRACTION ONE THIRD
0x0ab1 "⅔" EEK_SYMBOL_CATEGORY_LETTER # twothirds ⅔ VULGAR FRACTION TWO THIRDS
0x0ab2 "⅕" EEK_SYMBOL_CATEGORY_LETTER # onefifth ⅕ VULGAR FRACTION ONE FIFTH
0x0ab3 "⅖" EEK_SYMBOL_CATEGORY_LETTER # twofifths ⅖ VULGAR FRACTION TWO FIFTHS
0x0ab4 "⅗" EEK_SYMBOL_CATEGORY_LETTER # threefifths ⅗ VULGAR FRACTION THREE FIFTHS
0x0ab5 "⅘" EEK_SYMBOL_CATEGORY_LETTER # fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS
0x0ab6 "⅙" EEK_SYMBOL_CATEGORY_LETTER # onesixth ⅙ VULGAR FRACTION ONE SIXTH
0x0ab7 "⅚" EEK_SYMBOL_CATEGORY_LETTER # fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS
0x0ab8 "℅" EEK_SYMBOL_CATEGORY_LETTER # careof ℅ CARE OF
0x0abb "" EEK_SYMBOL_CATEGORY_LETTER # figdash FIGURE DASH
0x0abc "〈" EEK_SYMBOL_CATEGORY_LETTER # leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET
0x0abd "." EEK_SYMBOL_CATEGORY_LETTER # decimalpoint . FULL STOP
0x0abe "〉" EEK_SYMBOL_CATEGORY_LETTER # rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET
# 0x0abf marker ? ???
0x0ac3 "⅛" EEK_SYMBOL_CATEGORY_LETTER # oneeighth ⅛ VULGAR FRACTION ONE EIGHTH
0x0ac4 "⅜" EEK_SYMBOL_CATEGORY_LETTER # threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS
0x0ac5 "⅝" EEK_SYMBOL_CATEGORY_LETTER # fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS
0x0ac6 "⅞" EEK_SYMBOL_CATEGORY_LETTER # seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS
0x0ac9 "™" EEK_SYMBOL_CATEGORY_LETTER # trademark ™ TRADE MARK SIGN
0x0aca "☓" EEK_SYMBOL_CATEGORY_LETTER # signaturemark ☓ SALTIRE
# 0x0acb trademarkincircle ? ???
0x0acc "◁" EEK_SYMBOL_CATEGORY_LETTER # leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE
0x0acd "▷" EEK_SYMBOL_CATEGORY_LETTER # rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE
0x0ace "○" EEK_SYMBOL_CATEGORY_LETTER # emopencircle ○ WHITE CIRCLE
0x0acf "□" EEK_SYMBOL_CATEGORY_LETTER # emopenrectangle □ WHITE SQUARE
0x0ad0 "" EEK_SYMBOL_CATEGORY_LETTER # leftsinglequotemark LEFT SINGLE QUOTATION MARK
0x0ad1 "" EEK_SYMBOL_CATEGORY_LETTER # rightsinglequotemark RIGHT SINGLE QUOTATION MARK
0x0ad2 "“" EEK_SYMBOL_CATEGORY_LETTER # leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK
0x0ad3 "”" EEK_SYMBOL_CATEGORY_LETTER # rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK
0x0ad4 "℞" EEK_SYMBOL_CATEGORY_LETTER # prescription ℞ PRESCRIPTION TAKE
0x0ad6 "" EEK_SYMBOL_CATEGORY_LETTER # minutes PRIME
0x0ad7 "″" EEK_SYMBOL_CATEGORY_LETTER # seconds ″ DOUBLE PRIME
0x0ad9 "✝" EEK_SYMBOL_CATEGORY_LETTER # latincross ✝ LATIN CROSS
# 0x0ada hexagram ? ???
0x0adb "▬" EEK_SYMBOL_CATEGORY_LETTER # filledrectbullet ▬ BLACK RECTANGLE
0x0adc "◀" EEK_SYMBOL_CATEGORY_LETTER # filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE
0x0add "▶" EEK_SYMBOL_CATEGORY_LETTER # filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE
0x0ade "●" EEK_SYMBOL_CATEGORY_LETTER # emfilledcircle ● BLACK CIRCLE
0x0adf "■" EEK_SYMBOL_CATEGORY_LETTER # emfilledrect ■ BLACK SQUARE
0x0ae0 "◦" EEK_SYMBOL_CATEGORY_LETTER # enopencircbullet ◦ WHITE BULLET
0x0ae1 "▫" EEK_SYMBOL_CATEGORY_LETTER # enopensquarebullet ▫ WHITE SMALL SQUARE
0x0ae2 "▭" EEK_SYMBOL_CATEGORY_LETTER # openrectbullet ▭ WHITE RECTANGLE
0x0ae3 "△" EEK_SYMBOL_CATEGORY_LETTER # opentribulletup △ WHITE UP-POINTING TRIANGLE
0x0ae4 "▽" EEK_SYMBOL_CATEGORY_LETTER # opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE
0x0ae5 "☆" EEK_SYMBOL_CATEGORY_LETTER # openstar ☆ WHITE STAR
0x0ae6 "•" EEK_SYMBOL_CATEGORY_LETTER # enfilledcircbullet • BULLET
0x0ae7 "▪" EEK_SYMBOL_CATEGORY_LETTER # enfilledsqbullet ▪ BLACK SMALL SQUARE
0x0ae8 "▲" EEK_SYMBOL_CATEGORY_LETTER # filledtribulletup ▲ BLACK UP-POINTING TRIANGLE
0x0ae9 "▼" EEK_SYMBOL_CATEGORY_LETTER # filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE
0x0aea "☜" EEK_SYMBOL_CATEGORY_LETTER # leftpointer ☜ WHITE LEFT POINTING INDEX
0x0aeb "☞" EEK_SYMBOL_CATEGORY_LETTER # rightpointer ☞ WHITE RIGHT POINTING INDEX
0x0aec "♣" EEK_SYMBOL_CATEGORY_LETTER # club ♣ BLACK CLUB SUIT
0x0aed "♦" EEK_SYMBOL_CATEGORY_LETTER # diamond ♦ BLACK DIAMOND SUIT
0x0aee "♥" EEK_SYMBOL_CATEGORY_LETTER # heart ♥ BLACK HEART SUIT
0x0af0 "✠" EEK_SYMBOL_CATEGORY_LETTER # maltesecross ✠ MALTESE CROSS
0x0af1 "†" EEK_SYMBOL_CATEGORY_LETTER # dagger † DAGGER
0x0af2 "‡" EEK_SYMBOL_CATEGORY_LETTER # doubledagger ‡ DOUBLE DAGGER
0x0af3 "✓" EEK_SYMBOL_CATEGORY_LETTER # checkmark ✓ CHECK MARK
0x0af4 "✗" EEK_SYMBOL_CATEGORY_LETTER # ballotcross ✗ BALLOT X
0x0af5 "♯" EEK_SYMBOL_CATEGORY_LETTER # musicalsharp ♯ MUSIC SHARP SIGN
0x0af6 "♭" EEK_SYMBOL_CATEGORY_LETTER # musicalflat ♭ MUSIC FLAT SIGN
0x0af7 "♂" EEK_SYMBOL_CATEGORY_LETTER # malesymbol ♂ MALE SIGN
0x0af8 "♀" EEK_SYMBOL_CATEGORY_LETTER # femalesymbol ♀ FEMALE SIGN
0x0af9 "☎" EEK_SYMBOL_CATEGORY_LETTER # telephone ☎ BLACK TELEPHONE
0x0afa "⌕" EEK_SYMBOL_CATEGORY_LETTER # telephonerecorder ⌕ TELEPHONE RECORDER
0x0afb "℗" EEK_SYMBOL_CATEGORY_LETTER # phonographcopyright ℗ SOUND RECORDING COPYRIGHT
0x0afc "‸" EEK_SYMBOL_CATEGORY_LETTER # caret ‸ CARET
0x0afd "" EEK_SYMBOL_CATEGORY_LETTER # singlelowquotemark SINGLE LOW-9 QUOTATION MARK
0x0afe "„" EEK_SYMBOL_CATEGORY_LETTER # doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK
# 0x0aff cursor ? ???
0x0ba3 "<" EEK_SYMBOL_CATEGORY_LETTER # leftcaret < LESS-THAN SIGN
0x0ba6 ">" EEK_SYMBOL_CATEGORY_LETTER # rightcaret > GREATER-THAN SIGN
0x0ba8 "" EEK_SYMBOL_CATEGORY_LETTER # downcaret LOGICAL OR
0x0ba9 "∧" EEK_SYMBOL_CATEGORY_LETTER # upcaret ∧ LOGICAL AND
0x0bc0 "¯" EEK_SYMBOL_CATEGORY_LETTER # overbar ¯ MACRON
0x0bc2 "" EEK_SYMBOL_CATEGORY_LETTER # downtack DOWN TACK
0x0bc3 "∩" EEK_SYMBOL_CATEGORY_LETTER # upshoe ∩ INTERSECTION
0x0bc4 "⌊" EEK_SYMBOL_CATEGORY_LETTER # downstile ⌊ LEFT FLOOR
0x0bc6 "_" EEK_SYMBOL_CATEGORY_LETTER # underbar _ LOW LINE
0x0bca "∘" EEK_SYMBOL_CATEGORY_LETTER # jot ∘ RING OPERATOR
0x0bcc "⎕" EEK_SYMBOL_CATEGORY_LETTER # quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0)
0x0bce "⊥" EEK_SYMBOL_CATEGORY_LETTER # uptack ⊥ UP TACK
0x0bcf "○" EEK_SYMBOL_CATEGORY_LETTER # circle ○ WHITE CIRCLE
0x0bd3 "⌈" EEK_SYMBOL_CATEGORY_LETTER # upstile ⌈ LEFT CEILING
0x0bd6 "" EEK_SYMBOL_CATEGORY_LETTER # downshoe UNION
0x0bd8 "⊃" EEK_SYMBOL_CATEGORY_LETTER # rightshoe ⊃ SUPERSET OF
0x0bda "⊂" EEK_SYMBOL_CATEGORY_LETTER # leftshoe ⊂ SUBSET OF
0x0bdc "⊣" EEK_SYMBOL_CATEGORY_LETTER # lefttack ⊣ LEFT TACK
0x0bfc "⊢" EEK_SYMBOL_CATEGORY_LETTER # righttack ⊢ RIGHT TACK
0x0cdf "‗" EEK_SYMBOL_CATEGORY_LETTER # hebrew_doublelowline ‗ DOUBLE LOW LINE
0x0ce0 "א" EEK_SYMBOL_CATEGORY_LETTER # hebrew_aleph א HEBREW LETTER ALEF
0x0ce1 "ב" EEK_SYMBOL_CATEGORY_LETTER # hebrew_bet ב HEBREW LETTER BET
0x0ce2 "ג" EEK_SYMBOL_CATEGORY_LETTER # hebrew_gimel ג HEBREW LETTER GIMEL
0x0ce3 "ד" EEK_SYMBOL_CATEGORY_LETTER # hebrew_dalet ד HEBREW LETTER DALET
0x0ce4 "ה" EEK_SYMBOL_CATEGORY_LETTER # hebrew_he ה HEBREW LETTER HE
0x0ce5 "ו" EEK_SYMBOL_CATEGORY_LETTER # hebrew_waw ו HEBREW LETTER VAV
0x0ce6 "ז" EEK_SYMBOL_CATEGORY_LETTER # hebrew_zain ז HEBREW LETTER ZAYIN
0x0ce7 "ח" EEK_SYMBOL_CATEGORY_LETTER # hebrew_chet ח HEBREW LETTER HET
0x0ce8 "ט" EEK_SYMBOL_CATEGORY_LETTER # hebrew_tet ט HEBREW LETTER TET
0x0ce9 "י" EEK_SYMBOL_CATEGORY_LETTER # hebrew_yod י HEBREW LETTER YOD
0x0cea "ך" EEK_SYMBOL_CATEGORY_LETTER # hebrew_finalkaph ך HEBREW LETTER FINAL KAF
0x0ceb "כ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_kaph כ HEBREW LETTER KAF
0x0cec "ל" EEK_SYMBOL_CATEGORY_LETTER # hebrew_lamed ל HEBREW LETTER LAMED
0x0ced "ם" EEK_SYMBOL_CATEGORY_LETTER # hebrew_finalmem ם HEBREW LETTER FINAL MEM
0x0cee "מ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_mem מ HEBREW LETTER MEM
0x0cef "ן" EEK_SYMBOL_CATEGORY_LETTER # hebrew_finalnun ן HEBREW LETTER FINAL NUN
0x0cf0 "נ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_nun נ HEBREW LETTER NUN
0x0cf1 "ס" EEK_SYMBOL_CATEGORY_LETTER # hebrew_samech ס HEBREW LETTER SAMEKH
0x0cf2 "ע" EEK_SYMBOL_CATEGORY_LETTER # hebrew_ayin ע HEBREW LETTER AYIN
0x0cf3 "ף" EEK_SYMBOL_CATEGORY_LETTER # hebrew_finalpe ף HEBREW LETTER FINAL PE
0x0cf4 "פ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_pe פ HEBREW LETTER PE
0x0cf5 "ץ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_finalzade ץ HEBREW LETTER FINAL TSADI
0x0cf6 "צ" EEK_SYMBOL_CATEGORY_LETTER # hebrew_zade צ HEBREW LETTER TSADI
0x0cf7 "ק" EEK_SYMBOL_CATEGORY_LETTER # hebrew_qoph ק HEBREW LETTER QOF
0x0cf8 "ר" EEK_SYMBOL_CATEGORY_LETTER # hebrew_resh ר HEBREW LETTER RESH
0x0cf9 "ש" EEK_SYMBOL_CATEGORY_LETTER # hebrew_shin ש HEBREW LETTER SHIN
0x0cfa "ת" EEK_SYMBOL_CATEGORY_LETTER # hebrew_taw ת HEBREW LETTER TAV
0x0da1 "ก" EEK_SYMBOL_CATEGORY_LETTER # Thai_kokai ก THAI CHARACTER KO KAI
0x0da2 "ข" EEK_SYMBOL_CATEGORY_LETTER # Thai_khokhai ข THAI CHARACTER KHO KHAI
0x0da3 "ฃ" EEK_SYMBOL_CATEGORY_LETTER # Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT
0x0da4 "ค" EEK_SYMBOL_CATEGORY_LETTER # Thai_khokhwai ค THAI CHARACTER KHO KHWAI
0x0da5 "ฅ" EEK_SYMBOL_CATEGORY_LETTER # Thai_khokhon ฅ THAI CHARACTER KHO KHON
0x0da6 "ฆ" EEK_SYMBOL_CATEGORY_LETTER # Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG
0x0da7 "ง" EEK_SYMBOL_CATEGORY_LETTER # Thai_ngongu ง THAI CHARACTER NGO NGU
0x0da8 "จ" EEK_SYMBOL_CATEGORY_LETTER # Thai_chochan จ THAI CHARACTER CHO CHAN
0x0da9 "ฉ" EEK_SYMBOL_CATEGORY_LETTER # Thai_choching ฉ THAI CHARACTER CHO CHING
0x0daa "ช" EEK_SYMBOL_CATEGORY_LETTER # Thai_chochang ช THAI CHARACTER CHO CHANG
0x0dab "ซ" EEK_SYMBOL_CATEGORY_LETTER # Thai_soso ซ THAI CHARACTER SO SO
0x0dac "ฌ" EEK_SYMBOL_CATEGORY_LETTER # Thai_chochoe ฌ THAI CHARACTER CHO CHOE
0x0dad "ญ" EEK_SYMBOL_CATEGORY_LETTER # Thai_yoying ญ THAI CHARACTER YO YING
0x0dae "ฎ" EEK_SYMBOL_CATEGORY_LETTER # Thai_dochada ฎ THAI CHARACTER DO CHADA
0x0daf "ฏ" EEK_SYMBOL_CATEGORY_LETTER # Thai_topatak ฏ THAI CHARACTER TO PATAK
0x0db0 "ฐ" EEK_SYMBOL_CATEGORY_LETTER # Thai_thothan ฐ THAI CHARACTER THO THAN
0x0db1 "ฑ" EEK_SYMBOL_CATEGORY_LETTER # Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO
0x0db2 "ฒ" EEK_SYMBOL_CATEGORY_LETTER # Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO
0x0db3 "ณ" EEK_SYMBOL_CATEGORY_LETTER # Thai_nonen ณ THAI CHARACTER NO NEN
0x0db4 "ด" EEK_SYMBOL_CATEGORY_LETTER # Thai_dodek ด THAI CHARACTER DO DEK
0x0db5 "ต" EEK_SYMBOL_CATEGORY_LETTER # Thai_totao ต THAI CHARACTER TO TAO
0x0db6 "ถ" EEK_SYMBOL_CATEGORY_LETTER # Thai_thothung ถ THAI CHARACTER THO THUNG
0x0db7 "ท" EEK_SYMBOL_CATEGORY_LETTER # Thai_thothahan ท THAI CHARACTER THO THAHAN
0x0db8 "ธ" EEK_SYMBOL_CATEGORY_LETTER # Thai_thothong ธ THAI CHARACTER THO THONG
0x0db9 "น" EEK_SYMBOL_CATEGORY_LETTER # Thai_nonu น THAI CHARACTER NO NU
0x0dba "บ" EEK_SYMBOL_CATEGORY_LETTER # Thai_bobaimai บ THAI CHARACTER BO BAIMAI
0x0dbb "ป" EEK_SYMBOL_CATEGORY_LETTER # Thai_popla ป THAI CHARACTER PO PLA
0x0dbc "ผ" EEK_SYMBOL_CATEGORY_LETTER # Thai_phophung ผ THAI CHARACTER PHO PHUNG
0x0dbd "ฝ" EEK_SYMBOL_CATEGORY_LETTER # Thai_fofa ฝ THAI CHARACTER FO FA
0x0dbe "พ" EEK_SYMBOL_CATEGORY_LETTER # Thai_phophan พ THAI CHARACTER PHO PHAN
0x0dbf "ฟ" EEK_SYMBOL_CATEGORY_LETTER # Thai_fofan ฟ THAI CHARACTER FO FAN
0x0dc0 "ภ" EEK_SYMBOL_CATEGORY_LETTER # Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO
0x0dc1 "ม" EEK_SYMBOL_CATEGORY_LETTER # Thai_moma ม THAI CHARACTER MO MA
0x0dc2 "ย" EEK_SYMBOL_CATEGORY_LETTER # Thai_yoyak ย THAI CHARACTER YO YAK
0x0dc3 "ร" EEK_SYMBOL_CATEGORY_LETTER # Thai_rorua ร THAI CHARACTER RO RUA
0x0dc4 "ฤ" EEK_SYMBOL_CATEGORY_LETTER # Thai_ru ฤ THAI CHARACTER RU
0x0dc5 "ล" EEK_SYMBOL_CATEGORY_LETTER # Thai_loling ล THAI CHARACTER LO LING
0x0dc6 "ฦ" EEK_SYMBOL_CATEGORY_LETTER # Thai_lu ฦ THAI CHARACTER LU
0x0dc7 "ว" EEK_SYMBOL_CATEGORY_LETTER # Thai_wowaen ว THAI CHARACTER WO WAEN
0x0dc8 "ศ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sosala ศ THAI CHARACTER SO SALA
0x0dc9 "ษ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sorusi ษ THAI CHARACTER SO RUSI
0x0dca "ส" EEK_SYMBOL_CATEGORY_LETTER # Thai_sosua ส THAI CHARACTER SO SUA
0x0dcb "ห" EEK_SYMBOL_CATEGORY_LETTER # Thai_hohip ห THAI CHARACTER HO HIP
0x0dcc "ฬ" EEK_SYMBOL_CATEGORY_LETTER # Thai_lochula ฬ THAI CHARACTER LO CHULA
0x0dcd "อ" EEK_SYMBOL_CATEGORY_LETTER # Thai_oang อ THAI CHARACTER O ANG
0x0dce "ฮ" EEK_SYMBOL_CATEGORY_LETTER # Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK
0x0dcf "ฯ" EEK_SYMBOL_CATEGORY_LETTER # Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI
0x0dd0 "ะ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraa ะ THAI CHARACTER SARA A
0x0dd1 "ั" EEK_SYMBOL_CATEGORY_LETTER # Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT
0x0dd2 "า" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraaa า THAI CHARACTER SARA AA
0x0dd3 "ำ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraam ำ THAI CHARACTER SARA AM
0x0dd4 "ิ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarai ิ THAI CHARACTER SARA I
0x0dd5 "ี" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraii ี THAI CHARACTER SARA II
0x0dd6 "ึ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraue ึ THAI CHARACTER SARA UE
0x0dd7 "ื" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarauee ื THAI CHARACTER SARA UEE
0x0dd8 "ุ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarau ุ THAI CHARACTER SARA U
0x0dd9 "ู" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarauu ู THAI CHARACTER SARA UU
0x0dda "ฺ" EEK_SYMBOL_CATEGORY_LETTER # Thai_phinthu ฺ THAI CHARACTER PHINTHU
0x0dde "฾" EEK_SYMBOL_CATEGORY_LETTER # Thai_maihanakat_maitho ฾ ???
0x0ddf "฿" EEK_SYMBOL_CATEGORY_LETTER # Thai_baht ฿ THAI CURRENCY SYMBOL BAHT
0x0de0 "เ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarae เ THAI CHARACTER SARA E
0x0de1 "แ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraae แ THAI CHARACTER SARA AE
0x0de2 "โ" EEK_SYMBOL_CATEGORY_LETTER # Thai_sarao โ THAI CHARACTER SARA O
0x0de3 "ใ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN
0x0de4 "ไ" EEK_SYMBOL_CATEGORY_LETTER # Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI
0x0de5 "ๅ" EEK_SYMBOL_CATEGORY_LETTER # Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO
0x0de6 "ๆ" EEK_SYMBOL_CATEGORY_LETTER # Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK
0x0de7 "็" EEK_SYMBOL_CATEGORY_LETTER # Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU
0x0de8 "่" EEK_SYMBOL_CATEGORY_LETTER # Thai_maiek ่ THAI CHARACTER MAI EK
0x0de9 "้" EEK_SYMBOL_CATEGORY_LETTER # Thai_maitho ้ THAI CHARACTER MAI THO
0x0dea "๊" EEK_SYMBOL_CATEGORY_LETTER # Thai_maitri ๊ THAI CHARACTER MAI TRI
0x0deb "๋" EEK_SYMBOL_CATEGORY_LETTER # Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA
0x0dec "์" EEK_SYMBOL_CATEGORY_LETTER # Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT
0x0ded "ํ" EEK_SYMBOL_CATEGORY_LETTER # Thai_nikhahit ํ THAI CHARACTER NIKHAHIT
0x0df0 "" EEK_SYMBOL_CATEGORY_LETTER # Thai_leksun THAI DIGIT ZERO
0x0df1 "๑" EEK_SYMBOL_CATEGORY_LETTER # Thai_leknung ๑ THAI DIGIT ONE
0x0df2 "๒" EEK_SYMBOL_CATEGORY_LETTER # Thai_leksong ๒ THAI DIGIT TWO
0x0df3 "๓" EEK_SYMBOL_CATEGORY_LETTER # Thai_leksam ๓ THAI DIGIT THREE
0x0df4 "๔" EEK_SYMBOL_CATEGORY_LETTER # Thai_leksi ๔ THAI DIGIT FOUR
0x0df5 "๕" EEK_SYMBOL_CATEGORY_LETTER # Thai_lekha ๕ THAI DIGIT FIVE
0x0df6 "๖" EEK_SYMBOL_CATEGORY_LETTER # Thai_lekhok ๖ THAI DIGIT SIX
0x0df7 "๗" EEK_SYMBOL_CATEGORY_LETTER # Thai_lekchet ๗ THAI DIGIT SEVEN
0x0df8 "๘" EEK_SYMBOL_CATEGORY_LETTER # Thai_lekpaet ๘ THAI DIGIT EIGHT
0x0df9 "๙" EEK_SYMBOL_CATEGORY_LETTER # Thai_lekkao ๙ THAI DIGIT NINE
0x0ea1 "ㄱ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK
0x0ea2 "ㄲ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK
0x0ea3 "ㄳ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS
0x0ea4 "ㄴ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Nieun ㄴ HANGUL LETTER NIEUN
0x0ea5 "ㄵ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC
0x0ea6 "ㄶ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH
0x0ea7 "ㄷ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT
0x0ea8 "ㄸ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT
0x0ea9 "ㄹ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Rieul ㄹ HANGUL LETTER RIEUL
0x0eaa "ㄺ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK
0x0eab "ㄻ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM
0x0eac "ㄼ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP
0x0ead "ㄽ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS
0x0eae "ㄾ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH
0x0eaf "ㄿ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH
0x0eb0 "ㅀ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH
0x0eb1 "ㅁ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Mieum ㅁ HANGUL LETTER MIEUM
0x0eb2 "ㅂ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Pieub ㅂ HANGUL LETTER PIEUP
0x0eb3 "ㅃ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP
0x0eb4 "ㅄ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS
0x0eb5 "ㅅ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Sios ㅅ HANGUL LETTER SIOS
0x0eb6 "ㅆ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS
0x0eb7 "ㅇ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Ieung ㅇ HANGUL LETTER IEUNG
0x0eb8 "ㅈ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Jieuj ㅈ HANGUL LETTER CIEUC
0x0eb9 "ㅉ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC
0x0eba "ㅊ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH
0x0ebb "ㅋ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH
0x0ebc "ㅌ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Tieut ㅌ HANGUL LETTER THIEUTH
0x0ebd "ㅍ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH
0x0ebe "ㅎ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_Hieuh ㅎ HANGUL LETTER HIEUH
0x0ebf "ㅏ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_A ㅏ HANGUL LETTER A
0x0ec0 "ㅐ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_AE ㅐ HANGUL LETTER AE
0x0ec1 "ㅑ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YA ㅑ HANGUL LETTER YA
0x0ec2 "ㅒ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YAE ㅒ HANGUL LETTER YAE
0x0ec3 "ㅓ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_EO ㅓ HANGUL LETTER EO
0x0ec4 "ㅔ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_E ㅔ HANGUL LETTER E
0x0ec5 "ㅕ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YEO ㅕ HANGUL LETTER YEO
0x0ec6 "ㅖ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YE ㅖ HANGUL LETTER YE
0x0ec7 "ㅗ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_O ㅗ HANGUL LETTER O
0x0ec8 "ㅘ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_WA ㅘ HANGUL LETTER WA
0x0ec9 "ㅙ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_WAE ㅙ HANGUL LETTER WAE
0x0eca "ㅚ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_OE ㅚ HANGUL LETTER OE
0x0ecb "ㅛ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YO ㅛ HANGUL LETTER YO
0x0ecc "ㅜ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_U ㅜ HANGUL LETTER U
0x0ecd "ㅝ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_WEO ㅝ HANGUL LETTER WEO
0x0ece "ㅞ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_WE ㅞ HANGUL LETTER WE
0x0ecf "ㅟ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_WI ㅟ HANGUL LETTER WI
0x0ed0 "ㅠ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YU ㅠ HANGUL LETTER YU
0x0ed1 "ㅡ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_EU ㅡ HANGUL LETTER EU
0x0ed2 "ㅢ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YI ㅢ HANGUL LETTER YI
0x0ed3 "ㅣ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_I ㅣ HANGUL LETTER I
0x0ed4 "ᆨ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK
0x0ed5 "ᆩ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK
0x0ed6 "ᆪ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS
0x0ed7 "ᆫ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN
0x0ed8 "ᆬ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC
0x0ed9 "ᆭ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH
0x0eda "ᆮ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT
0x0edb "ᆯ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL
0x0edc "ᆰ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK
0x0edd "ᆱ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM
0x0ede "ᆲ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP
0x0edf "ᆳ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS
0x0ee0 "ᆴ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH
0x0ee1 "ᆵ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH
0x0ee2 "ᆶ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH
0x0ee3 "ᆷ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM
0x0ee4 "ᆸ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP
0x0ee5 "ᆹ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS
0x0ee6 "ᆺ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS
0x0ee7 "ᆻ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS
0x0ee8 "ᆼ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG
0x0ee9 "ᆽ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC
0x0eea "ᆾ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH
0x0eeb "ᆿ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH
0x0eec "ᇀ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH
0x0eed "ᇁ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH
0x0eee "ᇂ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH
0x0eef "ㅭ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH
0x0ef0 "ㅱ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM
0x0ef1 "ㅸ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP
0x0ef2 "ㅿ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_PanSios ㅿ HANGUL LETTER PANSIOS
# 0x0ef3 Hangul_KkogjiDalrinIeung ? ???
0x0ef4 "ㆄ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH
0x0ef5 "ㆆ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH
0x0ef6 "ㆍ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_AraeA ㆍ HANGUL LETTER ARAEA
0x0ef7 "ㆎ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE
0x0ef8 "ᇫ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS
# 0x0ef9 Hangul_J_KkogjiDalrinIeung ? ???
0x0efa "ᇹ" EEK_SYMBOL_CATEGORY_LETTER # Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH
0x0eff "₩" EEK_SYMBOL_CATEGORY_LETTER # Korean_Won ₩ WON SIGN
0x13bc "Œ" EEK_SYMBOL_CATEGORY_LETTER # OE Œ LATIN CAPITAL LIGATURE OE
0x13bd "œ" EEK_SYMBOL_CATEGORY_LETTER # oe œ LATIN SMALL LIGATURE OE
0x13be "Ÿ" EEK_SYMBOL_CATEGORY_LETTER # Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS
0x20a0 "₠" EEK_SYMBOL_CATEGORY_LETTER # EcuSign ₠ EURO-CURRENCY SIGN
0x20a1 "₡" EEK_SYMBOL_CATEGORY_LETTER # ColonSign ₡ COLON SIGN
0x20a2 "₢" EEK_SYMBOL_CATEGORY_LETTER # CruzeiroSign ₢ CRUZEIRO SIGN
0x20a3 "₣" EEK_SYMBOL_CATEGORY_LETTER # FFrancSign ₣ FRENCH FRANC SIGN
0x20a4 "₤" EEK_SYMBOL_CATEGORY_LETTER # LiraSign ₤ LIRA SIGN
0x20a5 "₥" EEK_SYMBOL_CATEGORY_LETTER # MillSign ₥ MILL SIGN
0x20a6 "₦" EEK_SYMBOL_CATEGORY_LETTER # NairaSign ₦ NAIRA SIGN
0x20a7 "₧" EEK_SYMBOL_CATEGORY_LETTER # PesetaSign ₧ PESETA SIGN
0x20a8 "₨" EEK_SYMBOL_CATEGORY_LETTER # RupeeSign ₨ RUPEE SIGN
0x20a9 "₩" EEK_SYMBOL_CATEGORY_LETTER # WonSign ₩ WON SIGN
0x20aa "₪" EEK_SYMBOL_CATEGORY_LETTER # NewSheqelSign ₪ NEW SHEQEL SIGN
0x20ab "₫" EEK_SYMBOL_CATEGORY_LETTER # DongSign ₫ DONG SIGN
0x20ac "€" EEK_SYMBOL_CATEGORY_LETTER # EuroSign € EURO SIGN
# Following items added to GTK, not in the xterm table
# Numeric keypad
# 0xFF80 # Space *
0xFFAA "*" EEK_SYMBOL_CATEGORY_LETTER # Multiply *
0xFFAB "+" EEK_SYMBOL_CATEGORY_LETTER # Add *
0xFFAC "," EEK_SYMBOL_CATEGORY_LETTER # Separator *
0xFFAD "-" EEK_SYMBOL_CATEGORY_LETTER # Subtract *
0xFFAE "." EEK_SYMBOL_CATEGORY_LETTER # Decimal *
0xFFAF "/" EEK_SYMBOL_CATEGORY_LETTER # Divide *
0xFFB0 "0" EEK_SYMBOL_CATEGORY_LETTER # 0 *
0xFFB1 "1" EEK_SYMBOL_CATEGORY_LETTER # 1 *
0xFFB2 "2" EEK_SYMBOL_CATEGORY_LETTER # 2 *
0xFFB3 "3" EEK_SYMBOL_CATEGORY_LETTER # 3 *
0xFFB4 "4" EEK_SYMBOL_CATEGORY_LETTER # 4 *
0xFFB5 "5" EEK_SYMBOL_CATEGORY_LETTER # 5 *
0xFFB6 "6" EEK_SYMBOL_CATEGORY_LETTER # 6 *
0xFFB7 "7" EEK_SYMBOL_CATEGORY_LETTER # 7 *
0xFFB8 "8" EEK_SYMBOL_CATEGORY_LETTER # 8 *
0xFFB9 "9" EEK_SYMBOL_CATEGORY_LETTER # 9 *
0xFFBD "=" EEK_SYMBOL_CATEGORY_LETTER # Equal *
# End numeric keypad

File diff suppressed because it is too large Load Diff

404
eekboard/eekboard-client.c Normal file
View File

@ -0,0 +1,404 @@
/*
* 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:eekboard-client
* @short_description: client interface of eekboard service
*
* The #EekboardClient class provides a client side access to eekboard-server.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eekboard/eekboard-client.h"
enum {
DESTROYED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekboardClientPrivate
{
GHashTable *context_hash;
} EekboardClientPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekboardClient, eekboard_client, G_TYPE_DBUS_PROXY)
static void send_destroy_context (EekboardClient *client,
EekboardContext *context,
GCancellable *cancellable);
static void
eekboard_client_real_destroyed (EekboardClient *self)
{
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
// g_debug ("eekboard_client_real_destroyed");
g_hash_table_remove_all (priv->context_hash);
}
static void
eekboard_client_dispose (GObject *object)
{
EekboardClient *client = EEKBOARD_CLIENT(object);
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
if (priv->context_hash) {
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, priv->context_hash);
while (g_hash_table_iter_next (&iter, &key, &value)) {
send_destroy_context (client, (EekboardContext *)value, NULL);
g_hash_table_iter_remove (&iter);
}
g_hash_table_destroy (priv->context_hash);
priv->context_hash = NULL;
}
G_OBJECT_CLASS (eekboard_client_parent_class)->dispose (object);
}
static void
eekboard_client_class_init (EekboardClientClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->destroyed = eekboard_client_real_destroyed;
gobject_class->dispose = eekboard_client_dispose;
/**
* EekboardClient::destroyed:
* @eekboard: an #EekboardClient
*
* The ::destroyed signal is emitted each time the name of remote
* end is vanished.
*/
signals[DESTROYED] =
g_signal_new (I_("destroyed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekboardClientClass, destroyed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static void
eekboard_client_init (EekboardClient *self)
{
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
priv->context_hash =
g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_object_unref);
}
static void
eekboard_name_vanished_callback (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
EekboardClient *client = user_data;
g_signal_emit_by_name (client, "destroyed", NULL);
}
/**
* eekboard_client_new:
* @connection: a #GDBusConnection
* @cancellable: a #GCancellable
*
* Create a client.
*/
EekboardClient *
eekboard_client_new (GDBusConnection *connection,
GCancellable *cancellable)
{
GInitable *initable;
GError *error;
g_assert (G_IS_DBUS_CONNECTION(connection));
error = NULL;
initable =
g_initable_new (EEKBOARD_TYPE_CLIENT,
cancellable,
&error,
"g-connection", connection,
"g-name", "org.fedorahosted.Eekboard",
"g-interface-name", "org.fedorahosted.Eekboard",
"g-object-path", "/org/fedorahosted/Eekboard",
NULL);
if (initable != NULL) {
EekboardClient *client = EEKBOARD_CLIENT (initable);
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(client));
if (name_owner == NULL) {
g_object_unref (client);
return NULL;
}
/* the vanished callback is called when the server is disconnected */
g_bus_watch_name_on_connection (connection,
name_owner,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL,
eekboard_name_vanished_callback,
client,
NULL);
g_free (name_owner);
return client;
}
g_warning ("can't create client: %s", error->message);
g_error_free (error);
return NULL;
}
static void
on_context_destroyed (EekboardContext *context,
gpointer user_data)
{
EekboardClient *client = user_data;
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
g_hash_table_remove (priv->context_hash,
g_dbus_proxy_get_object_path (G_DBUS_PROXY(context)));
}
/**
* eekboard_client_create_context:
* @eekboard: an #EekboardClient
* @client_name: name of the client
* @cancellable: a #GCancellable
*
* Create a new input context.
*
* Return value: (transfer full): a newly created #EekboardContext.
*/
EekboardContext *
eekboard_client_create_context (EekboardClient *client,
const gchar *client_name,
GCancellable *cancellable)
{
GVariant *variant;
const gchar *object_path;
EekboardContext *context;
GError *error;
GDBusConnection *connection;
g_assert (EEKBOARD_IS_CLIENT(client));
g_assert (client_name);
error = NULL;
variant = g_dbus_proxy_call_sync (G_DBUS_PROXY(client),
"CreateContext",
g_variant_new ("(s)", client_name),
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
&error);
if (!variant) {
g_warning ("failed to call CreateContext: %s", error->message);
g_error_free (error);
return NULL;
}
g_variant_get (variant, "(&s)", &object_path);
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY(client));
context = eekboard_context_new (connection, object_path, cancellable);
if (!context) {
g_variant_unref (variant);
return NULL;
}
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
g_hash_table_insert (priv->context_hash,
g_strdup (object_path),
g_object_ref (context));
g_signal_connect (context, "destroyed",
G_CALLBACK(on_context_destroyed), client);
return context;
}
static void
eekboard_async_ready_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *result;
result = g_dbus_proxy_call_finish (G_DBUS_PROXY(source_object),
res,
&error);
if (result)
g_variant_unref (result);
else {
g_warning ("error in D-Bus proxy call: %s", error->message);
g_error_free (error);
}
}
/**
* eekboard_client_push_context:
* @eekboard: an #EekboardClient
* @context: an #EekboardContext
* @cancellable: a #GCancellable
*
* Enable the input context @context and disable the others.
*/
void
eekboard_client_push_context (EekboardClient *client,
EekboardContext *context,
GCancellable *cancellable)
{
const gchar *object_path;
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
context = g_hash_table_lookup (priv->context_hash,
object_path);
if (!context)
return;
eekboard_context_set_enabled (context, TRUE);
g_dbus_proxy_call (G_DBUS_PROXY(client),
"PushContext",
g_variant_new ("(s)", object_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
eekboard_async_ready_callback,
NULL);
}
/**
* eekboard_client_pop_context:
* @eekboard: an #EekboardClient
* @cancellable: a #GCancellable
*
* Disable the current input context and enable the previous one.
*/
void
eekboard_client_pop_context (EekboardClient *client,
GCancellable *cancellable)
{
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
g_dbus_proxy_call (G_DBUS_PROXY(client),
"PopContext",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
eekboard_async_ready_callback,
NULL);
}
void
eekboard_client_show_keyboard (EekboardClient *client,
GCancellable *cancellable)
{
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
g_dbus_proxy_call (G_DBUS_PROXY(client),
"ShowKeyboard",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
eekboard_async_ready_callback,
NULL);
}
void
eekboard_client_hide_keyboard (EekboardClient *client,
GCancellable *cancellable)
{
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
g_dbus_proxy_call (G_DBUS_PROXY(client),
"HideKeyboard",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
eekboard_async_ready_callback,
NULL);
}
static void
send_destroy_context (EekboardClient *client,
EekboardContext *context,
GCancellable *cancellable)
{
const gchar *object_path;
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
g_dbus_proxy_call (G_DBUS_PROXY(client),
"DestroyContext",
g_variant_new ("(s)", object_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
eekboard_async_ready_callback,
NULL);
}
/**
* eekboard_client_destroy_context:
* @eekboard: an #EekboardClient
* @context: an #EekboardContext
* @cancellable: a #GCancellable
*
* Remove @context from @eekboard.
*/
void
eekboard_client_destroy_context (EekboardClient *client,
EekboardContext *context,
GCancellable *cancellable)
{
const gchar *object_path;
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
g_hash_table_remove (priv->context_hash, object_path);
send_destroy_context (client, context, cancellable);
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EEKBOARD_CLIENT_H
#define EEKBOARD_CLIENT_H 1
#define __EEKBOARD_CLIENT_H_INSIDE__ 1
#include <gio/gio.h>
#include "eekboard/eekboard-context.h"
G_BEGIN_DECLS
#define EEKBOARD_TYPE_CLIENT (eekboard_client_get_type())
G_DECLARE_DERIVABLE_TYPE (EekboardClient, eekboard_client, EEKBOARD, CLIENT, GDBusProxy)
struct _EekboardClientClass {
/*< private >*/
GDBusProxyClass parent_class;
/* signals */
void (* destroyed) (EekboardClient *self);
/*< private >*/
/* padding */
gpointer pdummy[23];
};
GType eekboard_client_get_type (void) G_GNUC_CONST;
EekboardClient *eekboard_client_new (GDBusConnection *connection,
GCancellable *cancellable);
EekboardContext *eekboard_client_create_context (EekboardClient *eekboard,
const gchar *client_name,
GCancellable *cancellable);
void eekboard_client_push_context (EekboardClient *eekboard,
EekboardContext *context,
GCancellable *cancellable);
void eekboard_client_pop_context (EekboardClient *eekboard,
GCancellable *cancellable);
void eekboard_client_show_keyboard (EekboardClient *eekboard,
GCancellable *cancellable);
void eekboard_client_hide_keyboard (EekboardClient *eekboard,
GCancellable *cancellable);
void eekboard_client_destroy_context (EekboardClient *eekboard,
EekboardContext *context,
GCancellable *cancellable);
G_END_DECLS
#endif /* EEKBOARD_CLIENT_H */

View File

@ -25,24 +25,23 @@
* implementation of eekboard input context service.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eekboard/eekboard-context-service.h"
#include <fcntl.h>
#include <stdio.h>
#define _XOPEN_SOURCE 500
#include <string.h>
#include <sys/mman.h>
#include <sys/random.h> // TODO: this is Linux-specific
#include <xkbcommon/xkbcommon.h>
#include <gio/gio.h>
#include "eekboard/key-emitter.h"
#include "wayland.h"
#include "eek/eek-xml-layout.h"
#include "eekboard/eekboard-context-service.h"
//#include "eekboard/eekboard-xklutil.h"
//#include "eek/eek-xkl.h"
#define CSW 640
#define CSH 480
@ -72,52 +71,97 @@ struct _EekboardContextServicePrivate {
gboolean visible;
gboolean fullscreen;
LevelKeyboard *keyboard; // currently used keyboard
EekKeyboard *keyboard; // currently used keyboard
GHashTable *keyboard_hash; // a table of available keyboards, per layout
// TODO: make use of repeating buttons
EekKey *repeat_key;
guint repeat_timeout_id;
gboolean repeat_triggered;
GSettings *settings;
uint32_t hint;
uint32_t purpose;
};
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
static LevelKeyboard *
#if 0 // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-variable =====
static Display *display = NULL;
#endif // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-variable =====
static EekKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
const gchar *keyboard_type)
{
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self);
EekKeyboard *keyboard;
EekLayout *layout;
GError *error;
if (g_str_has_prefix (keyboard_type, "xkb:")) {
/* TODO: Depends on xklavier
XklConfigRec *rec =
eekboard_xkl_config_rec_from_string (&keyboard_type[4]);
if (display == NULL)
//display = XOpenDisplay (NULL);
return NULL; // FIXME: replace with wl display
error = NULL;
layout = eek_xkl_layout_new (display, &error);
if (layout == NULL) {
g_warning ("can't create keyboard %s: %s",
keyboard_type, error->message);
g_error_free (error);
return NULL;
}
if (!eek_xkl_layout_set_config (EEK_XKL_LAYOUT(layout), rec)) {
g_object_unref (layout);
return NULL;
}
*/
return NULL;
} else {
error = NULL;
layout = eek_xml_layout_new (keyboard_type, &error);
if (layout == NULL) {
g_warning ("can't create keyboard %s: %s",
keyboard_type, error->message);
g_error_free (error);
keyboard_type = "us";
error = NULL;
layout = eek_xml_layout_new (keyboard_type, &error);
if (layout == NULL) {
g_error ("failed to create fallback layout: %s", error->message);
g_error_free (error);
return NULL;
}
}
}
keyboard = eek_keyboard_new (self, layout, CSW, CSH);
if (!keyboard) {
g_error("Failed to create a keyboard");
}
g_object_unref (layout);
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!context) {
g_error("No context created");
}
const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout);
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!keymap)
g_error("Bad keymap:\n%s", keymap_str);
xkb_context_unref(context);
struct xkb_rule_names rules = { 0 };
rules.layout = strdup(keyboard_type);
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!keymap) {
g_error("Bad keymap");
}
keyboard->keymap = keymap;
keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
keyboard->keymap_len = strlen(keymap_str) + 1;
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
char *path = strdup("/eek_keymap-XXXXXX");
char *r = &path[strlen(path) - 6];
getrandom(r, 6, GRND_NONBLOCK);
for (unsigned i = 0; i < 6; i++) {
for (uint i = 0; i < 6; i++) {
r[i] = (r[i] & 0b1111111) | 0b1000000; // A-z
r[i] = r[i] > 'z' ? '?' : r[i]; // The randomizer doesn't need to be good...
}
@ -135,8 +179,9 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
if ((void*)ptr == (void*)-1) {
g_error("Failed to set up mmap");
}
strncpy(ptr, keymap_str, keyboard->keymap_len);
strcpy(ptr, keymap_str);
munmap(ptr, keyboard->keymap_len);
free(keymap_str);
return keyboard;
}
@ -168,7 +213,12 @@ eekboard_context_service_set_property (GObject *object,
context->priv->keyboard = g_value_get_object (value);
break;
case PROP_VISIBLE:
context->priv->visible = g_value_get_boolean (value);
/*if (context->priv->keyboard) {
if (g_value_get_boolean (value))
eekboard_context_service_show_keyboard (context);
else
eekboard_context_service_hide_keyboard (context);
}*/
break;
case PROP_FULLSCREEN:
context->priv->fullscreen = g_value_get_boolean (value);
@ -236,12 +286,10 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
}
}
g_variant_iter_free(iter);
g_variant_unref(inputs);
}
static void
settings_update_layout(EekboardContextService *context)
{
settings_update_layout(EekboardContextService *context) {
g_autofree gchar *keyboard_type = NULL;
g_autofree gchar *keyboard_layout = NULL;
settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
@ -253,29 +301,23 @@ settings_update_layout(EekboardContextService *context)
keyboard_layout = g_strdup("undefined");
}
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
switch (priv->purpose) {
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("number");
break;
default:
;
}
// generic part follows
static guint keyboard_id = 0;
LevelKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id));
// create a keyboard
if (!keyboard) {
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
EekboardContextServiceClass *klass = EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context);
keyboard = klass->create_keyboard (context, keyboard_layout);
eek_keyboard_set_modifier_behavior (keyboard,
EEK_MODIFIER_BEHAVIOR_LATCH);
g_hash_table_insert (context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id),
keyboard);
keyboard->id = keyboard_id;
g_object_set_data (G_OBJECT(keyboard),
"keyboard-id",
GUINT_TO_POINTER(keyboard_id));
keyboard_id++;
}
// set as current
@ -316,6 +358,10 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekboardContextServicePrivate));
klass->create_keyboard = eekboard_context_service_real_create_keyboard;
klass->show_keyboard = eekboard_context_service_real_show_keyboard;
klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
@ -380,9 +426,10 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
*
* An #EekKeyboard currently active in this context.
*/
pspec = g_param_spec_pointer("keyboard",
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
@ -438,6 +485,55 @@ eekboard_context_service_init (EekboardContextService *self)
}
}
#if 0 // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-function =====
static gboolean on_repeat_timeout (EekboardContextService *context);
static gboolean
on_repeat_timeout (EekboardContextService *context)
{
guint delay = 500; // ms
// hardcoding; needs to connect to yet another settings path because
// org.gnome.desktop.input-sources doesn't control repeating
//g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
return FALSE;
}
#endif // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-function =====
#if 0 // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-function =====
static gboolean
on_repeat_timeout_init (EekboardContextService *context)
{
/* FIXME: clear modifiers for further key repeat; better not
depend on modifier behavior is LATCH */
eek_keyboard_set_modifiers (context->priv->keyboard, 0);
/* reschedule repeat timeout only when "repeat" option is set */
/* TODO: org.gnome.desktop.input-sources doesn't have repeat info.
* In addition, repeat is only useful when the keyboard is not in text
* input mode */
/*
if (g_settings_get_boolean (context->priv->settings, "repeat")) {
guint delay;
g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
} else */
context->priv->repeat_timeout_id = 0;
return FALSE;
}
#endif // ===== REMOVAL NOTICE ==== expires by: 2019-08-20 -Wunused-function =====
/**
* eekboard_context_service_enable:
* @context: an #EekboardContextService
@ -518,7 +614,7 @@ eekboard_context_service_destroy (EekboardContextService *context)
* Get keyboard currently active in @context.
* Returns: (transfer none): an #EekKeyboard
*/
LevelKeyboard *
EekKeyboard *
eekboard_context_service_get_keyboard (EekboardContextService *context)
{
return context->priv->keyboard;
@ -538,21 +634,9 @@ eekboard_context_service_get_fullscreen (EekboardContextService *context)
}
void eekboard_context_service_set_keymap(EekboardContextService *context,
const LevelKeyboard *keyboard)
const EekKeyboard *keyboard)
{
zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
keyboard->keymap_fd, keyboard->keymap_len);
}
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint, uint32_t purpose)
{
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
if (priv->hint != hint || priv->purpose != purpose) {
priv->hint = hint;
priv->purpose = purpose;
settings_update_layout(context);
}
}

View File

@ -25,7 +25,6 @@
#include <eek/eek.h>
#include "virtual-keyboard-unstable-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
G_BEGIN_DECLS
@ -73,7 +72,7 @@ struct _EekboardContextServiceClass {
GObjectClass parent_class;
/*< public >*/
struct squeek_view *(*create_keyboard) (EekboardContextService *self,
EekKeyboard *(*create_keyboard) (EekboardContextService *self,
const gchar *keyboard_type);
void (*show_keyboard) (EekboardContextService *self);
void (*hide_keyboard) (EekboardContextService *self);
@ -97,16 +96,13 @@ void eekboard_context_service_show_keyboard
void eekboard_context_service_hide_keyboard
(EekboardContextService *context);
void eekboard_context_service_destroy (EekboardContextService *context);
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
EekKeyboard *eekboard_context_service_get_keyboard
(EekboardContextService *context);
gboolean eekboard_context_service_get_fullscreen
(EekboardContextService *context);
void eekboard_context_service_set_keymap(EekboardContextService *context,
const LevelKeyboard *keyboard);
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint,
uint32_t purpose);
const EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEKBOARD_CONTEXT_SERVICE_H */

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