Compare commits

..

46 Commits

Author SHA1 Message Date
d5dc5c0ddf Merge branch 'dorota.czaplejewicz/squeekboard-font_size' into 'font_size'
Cast later to avoid rounding to zero

See merge request dorota.czaplejewicz/squeekboard!1
2019-08-01 17:23:09 +00:00
172ed08d40 Cast later to avoid rounding to zero 2019-08-01 17:17:44 +00:00
f27fade744 fonts: Reset font size to a constant
The font size will only be affected by the scaling factor, and not by an attempt to fit the labels into buttons.

Left to do: adjust it based on CSS.
2019-08-01 16:35:33 +00:00
3085a10507 Merge branch 'cleanup' into 'master'
xml: Remove unused file

See merge request Librem5/squeekboard!110
2019-08-01 15:06:43 +00:00
b5f0aa423b xml: Remove unused file 2019-08-01 14:16:01 +00:00
c8bc2c424f Merge branch 'errors' into 'master'
Errors

See merge request Librem5/squeekboard!107
2019-07-31 18:54:15 +00:00
46fa6d4500 Merge branch 'rust_tests' into 'master'
Rust tests

See merge request Librem5/squeekboard!106
2019-07-31 17:11:33 +00:00
6002774f95 Merge branch 'imservice_cleanups' into 'master'
Imservice cleanups

See merge request Librem5/squeekboard!105
2019-07-31 14:27:13 +00:00
f7f208883c errors: Make compilation stricter 2019-07-31 14:11:49 +00:00
5523b00442 test: Add missing gtk include 2019-07-31 14:11:35 +00:00
c81fdb18de eekelement: Fix case falling through 2019-07-31 14:11:03 +00:00
778543c719 rust: Add a call to Rust test framework 2019-07-31 11:20:57 +00:00
18b8972029 bitflags: Use absolute imports
With relative import of the bitflags crate, the macros would try to fetch nonexistent paths, preventing tests form compiling.
2019-07-31 11:13:24 +00:00
fa31f8eee1 imservice: Check pointer validity 2019-07-31 10:43:39 +00:00
98a2e33d78 imservice: Use TryFrom for u32->enum conversions 2019-07-31 10:05:35 +00:00
58d01bf502 imservice: Use discriminants in enums 2019-07-31 10:05:35 +00:00
8326bd7016 rust: Create a root file for modules
The new `lib.rs` file is created to refer to all modules written in Rust. This way, only one `rustc` call is needed to compile an arbitrary amount of modules. It also converges with the way crates are structured.
2019-07-31 10:05:27 +00:00
d5f8b0d83b Merge branch 'simplify-rendering' into 'master'
Simplify layout and rendering

See merge request Librem5/squeekboard!102
2019-07-31 09:10:57 +00:00
e70a898af5 Merge branch 'adjust-keyboard-geometry' into 'master'
Adjust keyboard geometry

See merge request Librem5/squeekboard!103
2019-07-31 06:39:45 +00:00
df249646bc Merge branch 'update-numeric-keypad' into 'master'
Rename keypad-related files

See merge request Librem5/squeekboard!101
2019-07-31 06:37:09 +00:00
35ff93258e Adjust geometry to match the compact keyboard in places 2019-07-31 00:43:39 +02:00
c58d034494 Adjust bounds of the keyboard to better fit it in the available space 2019-07-31 00:43:36 +02:00
8f1de46381 Simplify layout and rendering
Remove pre-scaling of the bounds for the keyboard and its contents.
Calculate the scale factor based on the allocation and the desired width
and height of each keyboard, using the lower value of the horizontal and
vertical scale factors.
Apply scaling in the renderer and prepare to perform centering there.
2019-07-30 21:48:36 +00:00
1846a67e83 Merge branch 'readme' into 'master'
readme: Change the clone URL

Closes #30

See merge request Librem5/squeekboard!100
2019-07-30 20:39:09 +00:00
35ac14806c Rename keypad-related files 2019-07-30 20:47:29 +02:00
4aee4915d9 Merge branch 'generate-xkb-files' into 'master'
Generate XKB keymaps from XML instead of using pre-made ones

See merge request Librem5/squeekboard!90
2019-07-30 17:38:06 +00:00
5eeaa1c693 Remove unused geometry file 2019-07-30 19:28:16 +02:00
9b2fcf89e8 Use a test-oriented init call 2019-07-30 17:20:15 +02:00
e801a68f0d Add comments to explain what empty labels do 2019-07-30 16:50:23 +02:00
ffc5628637 readme: Change the clone URL 2019-07-30 13:08:12 +00:00
306aa89d06 Merge branch 'content_type' into 'master'
Finish up imservice state

See merge request Librem5/squeekboard!93
2019-07-30 11:44:19 +00:00
236415cde4 Merge branch 'add-landscape-orientation' into 'master'
Add landscape orientation

See merge request Librem5/squeekboard!99
2019-07-30 11:19:41 +00:00
d49e0eaa1b Center the keyboard in landscape orientation 2019-07-26 22:27:56 +00:00
107399a531 Don't set the geometry of the window in normal use
Setting the geometry prevents the widget from getting the correct
allocation and prevents us from positioning it correctly in
landscape mode.
2019-07-26 22:26:02 +00:00
d8f48cc48b Merge branch 'use-button-size-for-icons' into 'master'
Use the standard button size for icons

See merge request Librem5/squeekboard!98
2019-07-26 08:04:53 +00:00
2f0beb6d3a Add a simple test of keymap generation 2019-07-25 22:25:30 +02:00
3ab3627ffe Remove unused keymaps 2019-07-25 22:25:30 +02:00
70895999c2 Generate XKB keymaps from XML instead of using pre-made ones 2019-07-25 22:25:29 +02:00
ce311e1bf1 Use the standard button size for icons 2019-07-25 20:14:32 +00:00
943b2ad9f3 Merge branch 'xkb_resource_oob_read' into 'master'
Fix out of bounds memory read in get_keymap_from_resource.

See merge request Librem5/squeekboard!97
2019-07-25 13:20:35 +00:00
f86bbb09f8 Fix out of bounds memory read in get_keymap_from_resource.
The function reads resource content into a buffer whose size matches the
size of the file contents. This buffer does not have an extra byte that
would 0 terminate this string. This is by itself is not a problem.
Unfortunately the buffer is passed to g_utf8_make_valid function with
size argument specified as -1 which means the buffer is supposed to be
NULL terminated. The end result is g_utf8_make_valid will read at least
1 byte past "contents" buffer size.

Fix this by specifying buffer size when calling g_utf8_make_valid.
2019-07-24 17:08:19 +02:00
7e939c36cc imservice: Call show/hide directly 2019-07-23 20:26:42 +00:00
c5d2d76ab1 imservice: Handle unavailable message 2019-07-23 20:26:42 +00:00
622ba6e38a imservice: Handle text change cause
Nothing is being done with this information yet
2019-07-23 20:26:42 +00:00
fad06348a7 imservice: Make imservice opaque
The structure is defined in Rust, with the intention of evaluating using Rust in this area. It's specifically not defined as repr(C), in order to encourage that. Without the repr, it was unsafe to have its members exposed in C.
2019-07-23 20:26:42 +00:00
a6ee303123 imservice: Handle content type in Rust
This adds `bitflags.rs` from the bitflags crate.
Due to not wanting to introduce Cargo as the dependency manager yet, it's slightly modified to compile as a naked module.
2019-07-23 20:25:13 +00:00
43 changed files with 2070 additions and 2221 deletions

View File

@ -33,8 +33,8 @@ See `.gitlab-ci.yml`.
### Build from git repo
```
$ git clone https://source.puri.sm/Librem5/eekboard.git
$ cd eekboard
$ git clone https://source.puri.sm/Librem5/squeekboard.git
$ cd squeekboard
$ mkdir ../build
$ meson ../build/
$ cd ../build

View File

@ -1,120 +1,120 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<bounds x="10" y="10" width="410.0000" height="229"/>
<section angle="0">
<row orientation="1">
<key keycode="24" name="AD01" oref="outline2" />
<key keycode="25" name="AD02" oref="outline2" />
<key keycode="26" name="AD03" oref="outline2" />
<key keycode="27" name="AD04" oref="outline2" />
<key keycode="28" name="AD05" oref="outline2" />
<key keycode="29" name="AD06" oref="outline2" />
<key keycode="30" name="AD07" oref="outline2" />
<key keycode="31" name="AD08" oref="outline2" />
<key keycode="32" name="AD09" oref="outline2" />
<key keycode="33" name="AD10" oref="outline2" />
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="38" name="AC01" oref="outline2" />
<key keycode="39" name="AC02" oref="outline2" />
<key keycode="40" name="AC03" oref="outline2" />
<key keycode="41" name="AC04" oref="outline2" />
<key keycode="42" name="AC05" oref="outline2" />
<key keycode="43" name="AC06" oref="outline2" />
<key keycode="44" name="AC07" oref="outline2" />
<key keycode="45" name="AC08" oref="outline2" />
<key keycode="46" name="AC09" oref="outline2" />
<key keycode="47" name="AC10" oref="outline2" />
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="50" name="LFSH" oref="altline" />
<key keycode="52" name="AB01" oref="outline2" />
<key keycode="53" name="AB02" oref="outline2" />
<key keycode="54" name="AB03" oref="outline2" />
<key keycode="55" name="AB04" oref="outline2" />
<key keycode="56" name="AB05" oref="outline2" />
<key keycode="57" name="AB06" oref="outline2" />
<key keycode="58" name="AB07" oref="outline2" />
<key keycode="22" name="BKSP" oref="altline" />
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key keycode="149" name="I149" oref="altline" />
<key keycode="65" name="SPCE" oref="spaceline" />
<key keycode="59" name="AB08" oref="outline2" />
<key keycode="36" name="RTRN" oref="outline7" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="48.39024" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="68.68292" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="109.2682" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="79.60975" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
</outline>
</geometry>

View File

@ -1,126 +1,122 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<!-- Keycodes correspond to those used in /usr/share/X11/xkb/keycodes/evdev.
For Squeekboard, the values have no connection to evdev. They are only
used as indices into the keymap sent to the compositor. They must have
values in the range from 8 to 255. -->
<section angle="0">
<row orientation="1">
<key keycode="24" name="AD01" oref="outline2" />
<key keycode="25" name="AD02" oref="outline2" />
<key keycode="26" name="AD03" oref="outline2" />
<key keycode="27" name="AD04" oref="outline2" />
<key keycode="28" name="AD05" oref="outline2" />
<key keycode="29" name="AD06" oref="outline2" />
<key keycode="30" name="AD07" oref="outline2" />
<key keycode="31" name="AD08" oref="outline2" />
<key keycode="32" name="AD09" oref="outline2" />
<key keycode="33" name="AD10" oref="outline2" />
<key keycode="34" name="AD11" oref="outline2" />
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
<key name="AD11" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="38" name="AC01" oref="outline2" />
<key keycode="39" name="AC02" oref="outline2" />
<key keycode="40" name="AC03" oref="outline2" />
<key keycode="41" name="AC04" oref="outline2" />
<key keycode="42" name="AC05" oref="outline2" />
<key keycode="43" name="AC06" oref="outline2" />
<key keycode="44" name="AC07" oref="outline2" />
<key keycode="45" name="AC08" oref="outline2" />
<key keycode="46" name="AC09" oref="outline2" />
<key keycode="47" name="AC10" oref="outline2" />
<key keycode="48" name="AC11" oref="outline2" />
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
<key name="AC11" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="50" name="LFSH" oref="altline" />
<key keycode="52" name="AB01" oref="outline2" />
<key keycode="53" name="AB02" oref="outline2" />
<key keycode="54" name="AB03" oref="outline2" />
<key keycode="55" name="AB04" oref="outline2" />
<key keycode="56" name="AB05" oref="outline2" />
<key keycode="57" name="AB06" oref="outline2" />
<key keycode="58" name="AB07" oref="outline2" />
<key keycode="22" name="BKSP" oref="altline" />
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key keycode="149" name="I149" oref="altline" />
<key keycode="65" name="SPCE" oref="spaceline" />
<key keycode="59" name="AB08" oref="outline2" />
<key keycode="36" name="RTRN" oref="outline7" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="32" y="0.000000"/>
<point x="32" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
<point x="32" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="48.39024" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="68.68292" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="109.2682" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="79.60975" y="52"/>
<point x="0.000000" y="52"/>
</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"/>
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
</outline>
</geometry>

View File

@ -3,37 +3,37 @@
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key keycode="24" name="AD01" oref="outline2" />
<key keycode="25" name="AD02" oref="outline2" />
<key keycode="26" name="AD03" oref="outline2" />
<key keycode="27" name="AD04" oref="outline2" />
<key keycode="28" name="AD05" oref="outline2" />
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="38" name="AC01" oref="outline2" />
<key keycode="39" name="AC02" oref="outline2" />
<key keycode="40" name="AC03" oref="outline2" />
<key keycode="41" name="AC04" oref="outline2" />
<key keycode="42" name="AC05" oref="outline2" />
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="52" name="AB01" oref="outline2" />
<key keycode="53" name="AB02" oref="outline2" />
<key keycode="54" name="AB03" oref="outline2" />
<key keycode="55" name="AB04" oref="outline2" />
<key keycode="56" name="AB05" oref="outline2" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="22" name="BKSP" oref="altline" />
<key keycode="57" name="AB06" oref="outline2" />
<key keycode="65" name="SPCE" oref="spaceline" />
<key keycode="36" name="RTRN" oref="outline7" />
<key name="BKSP" oref="altline" />
<key name="AB06" oref="outline2" />
<key name="SPCE" oref="spaceline" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">

View File

@ -90,8 +90,11 @@
longname="Telugu (Inscript)" language="te"/>
<!-- Common keyboards -->
<keyboard id="numbers" name="numbers"
geometry="numbers-keypad" symbols="special/numbers"
<keyboard id="number" name="number"
geometry="number-keypad" symbols="special/number"
longname="Numeric keypad" language="all"/>
<keyboard id="phone" name="phone"
geometry="number-keypad" symbols="special/number"
longname="Phone keypad" language="all"/>
</keyboards>

View File

@ -1,308 +0,0 @@
xkb_keymap {
xkb_keycodes "squeekboard" {
minimum = 8;
maximum = 255;
<ESC> = 9;
<AE01> = 10;
<AE02> = 11;
<AE03> = 12;
<AE04> = 13;
<AE05> = 14;
<AE06> = 15;
<AE07> = 16;
<AE08> = 17;
<AE09> = 18;
<AE10> = 19;
<AE11> = 20;
<AE12> = 21;
<BKSP> = 22;
<TAB> = 23;
<AD01> = 24;
<AD02> = 25;
<AD03> = 26;
<AD04> = 27;
<AD05> = 28;
<AD06> = 29;
<AD07> = 30;
<AD08> = 31;
<AD09> = 32;
<AD10> = 33;
<AD11> = 34;
<AD12> = 35;
<RTRN> = 36;
<LCTL> = 37;
<AC01> = 38;
<AC02> = 39;
<AC03> = 40;
<AC04> = 41;
<AC05> = 42;
<AC06> = 43;
<AC07> = 44;
<AC08> = 45;
<AC09> = 46;
<AC10> = 47;
<AC11> = 48;
<TLDE> = 49;
<LFSH> = 50;
<BKSL> = 51;
<AB01> = 52;
<AB02> = 53;
<AB03> = 54;
<AB04> = 55;
<AB05> = 56;
<AB06> = 57;
<AB07> = 58;
<AB08> = 59;
<AB09> = 60;
<AB10> = 61;
<RTSH> = 62;
<KPMU> = 63;
<LALT> = 64;
<SPCE> = 65;
<CAPS> = 66;
<FK01> = 67;
<FK02> = 68;
<FK03> = 69;
<FK04> = 70;
<FK05> = 71;
<FK06> = 72;
<FK07> = 73;
<FK08> = 74;
<FK09> = 75;
<FK10> = 76;
<NMLK> = 77;
<SCLK> = 78;
<KP7> = 79;
<KP8> = 80;
<KP9> = 81;
<KPSU> = 82;
<KP4> = 83;
<KP5> = 84;
<KP6> = 85;
<KPAD> = 86;
<KP1> = 87;
<KP2> = 88;
<KP3> = 89;
<KP0> = 90;
<KPDL> = 91;
<LVL3> = 92;
<LSGT> = 94;
<FK11> = 95;
<FK12> = 96;
<AB11> = 97;
<KATA> = 98;
<HIRA> = 99;
<HENK> = 100;
<HKTG> = 101;
<MUHE> = 102;
<JPCM> = 103;
<KPEN> = 104;
<RCTL> = 105;
<KPDV> = 106;
<PRSC> = 107;
<RALT> = 108;
<LNFD> = 109;
<HOME> = 110;
<UP> = 111;
<PGUP> = 112;
<LEFT> = 113;
<RGHT> = 114;
<END> = 115;
<DOWN> = 116;
<PGDN> = 117;
<INS> = 118;
<DELE> = 119;
<I120> = 120;
<MUTE> = 121;
<VOL-> = 122;
<VOL+> = 123;
<POWR> = 124;
<KPEQ> = 125;
<I126> = 126;
<PAUS> = 127;
<I128> = 128;
<I129> = 129;
<HNGL> = 130;
<HJCV> = 131;
<AE13> = 132;
<LWIN> = 133;
<RWIN> = 134;
<COMP> = 135;
<STOP> = 136;
<AGAI> = 137;
<PROP> = 138;
<UNDO> = 139;
<FRNT> = 140;
<COPY> = 141;
<OPEN> = 142;
<PAST> = 143;
<FIND> = 144;
<CUT> = 145;
<HELP> = 146;
<I147> = 147;
<I148> = 148;
<I149> = 149;
<I150> = 150;
<I151> = 151;
<I152> = 152;
<I153> = 153;
<I154> = 154;
<I155> = 155;
<I156> = 156;
<I157> = 157;
<I158> = 158;
<I159> = 159;
<I160> = 160;
<I161> = 161;
<I162> = 162;
<I163> = 163;
<I164> = 164;
<I165> = 165;
<I166> = 166;
<I167> = 167;
<I168> = 168;
<I169> = 169;
<I170> = 170;
<I171> = 171;
<I172> = 172;
<I173> = 173;
<I174> = 174;
<I175> = 175;
<I176> = 176;
<I177> = 177;
<I178> = 178;
<I179> = 179;
<I180> = 180;
<I181> = 181;
<I182> = 182;
<I183> = 183;
<I184> = 184;
<I185> = 185;
<I186> = 186;
<I187> = 187;
<I188> = 188;
<I189> = 189;
<I190> = 190;
<FK13> = 191;
<FK14> = 192;
<FK15> = 193;
<FK16> = 194;
<FK17> = 195;
<FK18> = 196;
<FK19> = 197;
<FK20> = 198;
<FK21> = 199;
<FK22> = 200;
<FK23> = 201;
<FK24> = 202;
<MDSW> = 203;
<ALT> = 204;
<META> = 205;
<SUPR> = 206;
<HYPR> = 207;
<I208> = 208;
<I209> = 209;
<I210> = 210;
<I211> = 211;
<I212> = 212;
<I213> = 213;
<I214> = 214;
<I215> = 215;
<I216> = 216;
<I217> = 217;
<I218> = 218;
<I219> = 219;
<I220> = 220;
<I221> = 221;
<I222> = 222;
<I223> = 223;
<I224> = 224;
<I225> = 225;
<I226> = 226;
<I227> = 227;
<I228> = 228;
<I229> = 229;
<I230> = 230;
<I231> = 231;
<I232> = 232;
<I233> = 233;
<I234> = 234;
<I235> = 235;
<I236> = 236;
<I237> = 237;
<I238> = 238;
<I239> = 239;
<I240> = 240;
<I241> = 241;
<I242> = 242;
<I243> = 243;
<I244> = 244;
<I245> = 245;
<I246> = 246;
<I247> = 247;
<I248> = 248;
<I249> = 249;
<I250> = 250;
<I251> = 251;
<I252> = 252;
<I253> = 253;
<I254> = 254;
<I255> = 255;
};
xkb_symbols "squeekboard" {
name[Group1] = "Letters";
name[Group2] = "Numbers/Symbols";
key <AD01> { [ q, Q ], [ 1, asciitilde ] };
key <AD02> { [ w, W ], [ 2, quoteleft ] };
key <AD03> { [ e, E ], [ 3, bar ] };
key <AD04> { [ r, R ], [ 4, U00B7 ] };
key <AD05> { [ t, T ], [ 5, squareroot ] };
key <AD06> { [ y, Y ], [ 6, Greek_pi ] };
key <AD07> { [ u, U ], [ 7, division ] };
key <AD08> { [ i, I ], [ 8, multiply ] };
key <AD09> { [ o, O ], [ 9, paragraph ] };
key <AD10> { [ p, P ], [ 0, U25B3 ] };
key <AD11> { [ aring, Aring ], [ U00B1, U00A7 ] };
key <AC01> { [ a, A ], [ at, copyright ] };
key <AC02> { [ s, S ], [ numbersign, U00AE ] };
key <AC03> { [ d, D ], [ dollar, U00A3 ] };
key <AC04> { [ f, F ], [ percent, EuroSign ] };
key <AC05> { [ g, G ], [ ampersand, U00A5 ] };
key <AC06> { [ h, H ], [ minus, underscore ] };
key <AC07> { [ j, J ], [ plus, equal ] };
key <AC08> { [ k, K ], [ U00FC, asciicircum ] };
key <AC09> { [ l, L ], [ U00F6, degree ] };
key <AC10> { [ oslash, Oslash ], [ parenleft, braceleft ] };
key <AC11> { [ ae, AE ], [ parenright, braceright ] };
key <RTRN> { [ Return, Return ], [ Return, Return ] };
key <LFSH> { [ Shift_L, Shift_L ], [ Shift_L, Shift_L ] };
key <AB01> { [ z, Z ], [ comma, backslash ] };
key <AB02> { [ x, X ], [ quotedbl, slash ] };
key <AB03> { [ c, C ], [ quoteright, less ] };
key <AB04> { [ v, V ], [ colon, greater ] };
key <AB05> { [ b, B ], [ semicolon, equal ] };
key <AB06> { [ n, N ], [ exclam, bracketleft ] };
key <AB07> { [ m, M ], [ question, bracketright ] };
key <AB08> { [ period, period ], [ period, period ] };
key <I149> { [ preferences, preferences ], [ preferences, preferences ] };
key <SPCE> { [ space, space ], [ space, space ] };
key <BKSP> { [ BackSpace, BackSpace ], [ BackSpace, BackSpace ] };
};
xkb_types "squeekboard" {
type "TWO_LEVEL" {
modifiers = Shift;
map[Shift] = Level2;
level_name[Level1] = "Base";
level_name[Level2] = "Shift";
};
};
xkb_compatibility "squeekboard" {
};
};

View File

@ -1,292 +0,0 @@
xkb_keymap {
xkb_keycodes "squeekboard" {
minimum = 8;
maximum = 255;
<ESC> = 9;
<AE01> = 10;
<AE02> = 11;
<AE03> = 12;
<AE04> = 13;
<AE05> = 14;
<AE06> = 15;
<AE07> = 16;
<AE08> = 17;
<AE09> = 18;
<AE10> = 19;
<AE11> = 20;
<AE12> = 21;
<BKSP> = 22;
<TAB> = 23;
<AD01> = 24;
<AD02> = 25;
<AD03> = 26;
<AD04> = 27;
<AD05> = 28;
<AD06> = 29;
<AD07> = 30;
<AD08> = 31;
<AD09> = 32;
<AD10> = 33;
<AD11> = 34;
<AD12> = 35;
<RTRN> = 36;
<LCTL> = 37;
<AC01> = 38;
<AC02> = 39;
<AC03> = 40;
<AC04> = 41;
<AC05> = 42;
<AC06> = 43;
<AC07> = 44;
<AC08> = 45;
<AC09> = 46;
<AC10> = 47;
<AC11> = 48;
<TLDE> = 49;
<LFSH> = 50;
<BKSL> = 51;
<AB01> = 52;
<AB02> = 53;
<AB03> = 54;
<AB04> = 55;
<AB05> = 56;
<AB06> = 57;
<AB07> = 58;
<AB08> = 59;
<AB09> = 60;
<AB10> = 61;
<RTSH> = 62;
<KPMU> = 63;
<LALT> = 64;
<SPCE> = 65;
<CAPS> = 66;
<FK01> = 67;
<FK02> = 68;
<FK03> = 69;
<FK04> = 70;
<FK05> = 71;
<FK06> = 72;
<FK07> = 73;
<FK08> = 74;
<FK09> = 75;
<FK10> = 76;
<NMLK> = 77;
<SCLK> = 78;
<KP7> = 79;
<KP8> = 80;
<KP9> = 81;
<KPSU> = 82;
<KP4> = 83;
<KP5> = 84;
<KP6> = 85;
<KPAD> = 86;
<KP1> = 87;
<KP2> = 88;
<KP3> = 89;
<KP0> = 90;
<KPDL> = 91;
<LVL3> = 92;
<LSGT> = 94;
<FK11> = 95;
<FK12> = 96;
<AB11> = 97;
<KATA> = 98;
<HIRA> = 99;
<HENK> = 100;
<HKTG> = 101;
<MUHE> = 102;
<JPCM> = 103;
<KPEN> = 104;
<RCTL> = 105;
<KPDV> = 106;
<PRSC> = 107;
<RALT> = 108;
<LNFD> = 109;
<HOME> = 110;
<UP> = 111;
<PGUP> = 112;
<LEFT> = 113;
<RGHT> = 114;
<END> = 115;
<DOWN> = 116;
<PGDN> = 117;
<INS> = 118;
<DELE> = 119;
<I120> = 120;
<MUTE> = 121;
<VOL-> = 122;
<VOL+> = 123;
<POWR> = 124;
<KPEQ> = 125;
<I126> = 126;
<PAUS> = 127;
<I128> = 128;
<I129> = 129;
<HNGL> = 130;
<HJCV> = 131;
<AE13> = 132;
<LWIN> = 133;
<RWIN> = 134;
<COMP> = 135;
<STOP> = 136;
<AGAI> = 137;
<PROP> = 138;
<UNDO> = 139;
<FRNT> = 140;
<COPY> = 141;
<OPEN> = 142;
<PAST> = 143;
<FIND> = 144;
<CUT> = 145;
<HELP> = 146;
<I147> = 147;
<I148> = 148;
<I149> = 149;
<I150> = 150;
<I151> = 151;
<I152> = 152;
<I153> = 153;
<I154> = 154;
<I155> = 155;
<I156> = 156;
<I157> = 157;
<I158> = 158;
<I159> = 159;
<I160> = 160;
<I161> = 161;
<I162> = 162;
<I163> = 163;
<I164> = 164;
<I165> = 165;
<I166> = 166;
<I167> = 167;
<I168> = 168;
<I169> = 169;
<I170> = 170;
<I171> = 171;
<I172> = 172;
<I173> = 173;
<I174> = 174;
<I175> = 175;
<I176> = 176;
<I177> = 177;
<I178> = 178;
<I179> = 179;
<I180> = 180;
<I181> = 181;
<I182> = 182;
<I183> = 183;
<I184> = 184;
<I185> = 185;
<I186> = 186;
<I187> = 187;
<I188> = 188;
<I189> = 189;
<I190> = 190;
<FK13> = 191;
<FK14> = 192;
<FK15> = 193;
<FK16> = 194;
<FK17> = 195;
<FK18> = 196;
<FK19> = 197;
<FK20> = 198;
<FK21> = 199;
<FK22> = 200;
<FK23> = 201;
<FK24> = 202;
<MDSW> = 203;
<ALT> = 204;
<META> = 205;
<SUPR> = 206;
<HYPR> = 207;
<I208> = 208;
<I209> = 209;
<I210> = 210;
<I211> = 211;
<I212> = 212;
<I213> = 213;
<I214> = 214;
<I215> = 215;
<I216> = 216;
<I217> = 217;
<I218> = 218;
<I219> = 219;
<I220> = 220;
<I221> = 221;
<I222> = 222;
<I223> = 223;
<I224> = 224;
<I225> = 225;
<I226> = 226;
<I227> = 227;
<I228> = 228;
<I229> = 229;
<I230> = 230;
<I231> = 231;
<I232> = 232;
<I233> = 233;
<I234> = 234;
<I235> = 235;
<I236> = 236;
<I237> = 237;
<I238> = 238;
<I239> = 239;
<I240> = 240;
<I241> = 241;
<I242> = 242;
<I243> = 243;
<I244> = 244;
<I245> = 245;
<I246> = 246;
<I247> = 247;
<I248> = 248;
<I249> = 249;
<I250> = 250;
<I251> = 251;
<I252> = 252;
<I253> = 253;
<I254> = 254;
<I255> = 255;
};
xkb_symbols "squeekboard" {
name[Group1] = "Letters";
name[Group2] = "Numbers/Symbols";
key <AD01> { [ 1, 1 ], [ 1, 1 ] };
key <AD02> { [ 2, 2 ], [ 2, 2 ] };
key <AD03> { [ 3, 3 ], [ 3, 3 ] };
key <AD04> { [ parenleft, parenleft ], [ parenleft, parenleft ] };
key <AD05> { [ parenright, parenright ], [ parenright, parenright ] };
key <AC01> { [ 4, 4 ], [ 4, 4 ] };
key <AC02> { [ 5, 5 ], [ 5, 5 ] };
key <AC03> { [ 6, 6 ], [ 6, 6 ] };
key <AC04> { [ numbersign, numbersign ], [ numbersign, numbersign ] };
key <AC05> { [ asterisk, asterisk ], [ asterisk, asterisk ] };
key <AB01> { [ 7, 7 ], [ 7, 7 ] };
key <AB02> { [ 8, 8 ], [ 8, 8 ] };
key <AB03> { [ 9, 9 ], [ 9, 9 ] };
key <AB04> { [ plus, plus ], [ plus, plus ] };
key <AB05> { [ minus, minus ], [ minus, minus ] };
key <AB06> { [ 0, 0 ], [ 0, 0 ] };
key <RTRN> { [ Return, Return ], [ Return, Return ] };
key <SPCE> { [ space, space ], [ space, space ] };
key <BKSP> { [ BackSpace, BackSpace ], [ BackSpace, BackSpace ] };
};
xkb_types "squeekboard" {
type "TWO_LEVEL" {
modifiers = Shift;
map[Shift] = Level2;
level_name[Level1] = "Base";
level_name[Level2] = "Shift";
};
};
xkb_compatibility "squeekboard" {
};
};

View File

@ -1,306 +0,0 @@
xkb_keymap {
xkb_keycodes "squeekboard" {
minimum = 8;
maximum = 255;
<ESC> = 9;
<AE01> = 10;
<AE02> = 11;
<AE03> = 12;
<AE04> = 13;
<AE05> = 14;
<AE06> = 15;
<AE07> = 16;
<AE08> = 17;
<AE09> = 18;
<AE10> = 19;
<AE11> = 20;
<AE12> = 21;
<BKSP> = 22;
<TAB> = 23;
<AD01> = 24;
<AD02> = 25;
<AD03> = 26;
<AD04> = 27;
<AD05> = 28;
<AD06> = 29;
<AD07> = 30;
<AD08> = 31;
<AD09> = 32;
<AD10> = 33;
<AD11> = 34;
<AD12> = 35;
<RTRN> = 36;
<LCTL> = 37;
<AC01> = 38;
<AC02> = 39;
<AC03> = 40;
<AC04> = 41;
<AC05> = 42;
<AC06> = 43;
<AC07> = 44;
<AC08> = 45;
<AC09> = 46;
<AC10> = 47;
<AC11> = 48;
<TLDE> = 49;
<LFSH> = 50;
<BKSL> = 51;
<AB01> = 52;
<AB02> = 53;
<AB03> = 54;
<AB04> = 55;
<AB05> = 56;
<AB06> = 57;
<AB07> = 58;
<AB08> = 59;
<AB09> = 60;
<AB10> = 61;
<RTSH> = 62;
<KPMU> = 63;
<LALT> = 64;
<SPCE> = 65;
<CAPS> = 66;
<FK01> = 67;
<FK02> = 68;
<FK03> = 69;
<FK04> = 70;
<FK05> = 71;
<FK06> = 72;
<FK07> = 73;
<FK08> = 74;
<FK09> = 75;
<FK10> = 76;
<NMLK> = 77;
<SCLK> = 78;
<KP7> = 79;
<KP8> = 80;
<KP9> = 81;
<KPSU> = 82;
<KP4> = 83;
<KP5> = 84;
<KP6> = 85;
<KPAD> = 86;
<KP1> = 87;
<KP2> = 88;
<KP3> = 89;
<KP0> = 90;
<KPDL> = 91;
<LVL3> = 92;
<LSGT> = 94;
<FK11> = 95;
<FK12> = 96;
<AB11> = 97;
<KATA> = 98;
<HIRA> = 99;
<HENK> = 100;
<HKTG> = 101;
<MUHE> = 102;
<JPCM> = 103;
<KPEN> = 104;
<RCTL> = 105;
<KPDV> = 106;
<PRSC> = 107;
<RALT> = 108;
<LNFD> = 109;
<HOME> = 110;
<UP> = 111;
<PGUP> = 112;
<LEFT> = 113;
<RGHT> = 114;
<END> = 115;
<DOWN> = 116;
<PGDN> = 117;
<INS> = 118;
<DELE> = 119;
<I120> = 120;
<MUTE> = 121;
<VOL-> = 122;
<VOL+> = 123;
<POWR> = 124;
<KPEQ> = 125;
<I126> = 126;
<PAUS> = 127;
<I128> = 128;
<I129> = 129;
<HNGL> = 130;
<HJCV> = 131;
<AE13> = 132;
<LWIN> = 133;
<RWIN> = 134;
<COMP> = 135;
<STOP> = 136;
<AGAI> = 137;
<PROP> = 138;
<UNDO> = 139;
<FRNT> = 140;
<COPY> = 141;
<OPEN> = 142;
<PAST> = 143;
<FIND> = 144;
<CUT> = 145;
<HELP> = 146;
<I147> = 147;
<I148> = 148;
<I149> = 149;
<I150> = 150;
<I151> = 151;
<I152> = 152;
<I153> = 153;
<I154> = 154;
<I155> = 155;
<I156> = 156;
<I157> = 157;
<I158> = 158;
<I159> = 159;
<I160> = 160;
<I161> = 161;
<I162> = 162;
<I163> = 163;
<I164> = 164;
<I165> = 165;
<I166> = 166;
<I167> = 167;
<I168> = 168;
<I169> = 169;
<I170> = 170;
<I171> = 171;
<I172> = 172;
<I173> = 173;
<I174> = 174;
<I175> = 175;
<I176> = 176;
<I177> = 177;
<I178> = 178;
<I179> = 179;
<I180> = 180;
<I181> = 181;
<I182> = 182;
<I183> = 183;
<I184> = 184;
<I185> = 185;
<I186> = 186;
<I187> = 187;
<I188> = 188;
<I189> = 189;
<I190> = 190;
<FK13> = 191;
<FK14> = 192;
<FK15> = 193;
<FK16> = 194;
<FK17> = 195;
<FK18> = 196;
<FK19> = 197;
<FK20> = 198;
<FK21> = 199;
<FK22> = 200;
<FK23> = 201;
<FK24> = 202;
<MDSW> = 203;
<ALT> = 204;
<META> = 205;
<SUPR> = 206;
<HYPR> = 207;
<I208> = 208;
<I209> = 209;
<I210> = 210;
<I211> = 211;
<I212> = 212;
<I213> = 213;
<I214> = 214;
<I215> = 215;
<I216> = 216;
<I217> = 217;
<I218> = 218;
<I219> = 219;
<I220> = 220;
<I221> = 221;
<I222> = 222;
<I223> = 223;
<I224> = 224;
<I225> = 225;
<I226> = 226;
<I227> = 227;
<I228> = 228;
<I229> = 229;
<I230> = 230;
<I231> = 231;
<I232> = 232;
<I233> = 233;
<I234> = 234;
<I235> = 235;
<I236> = 236;
<I237> = 237;
<I238> = 238;
<I239> = 239;
<I240> = 240;
<I241> = 241;
<I242> = 242;
<I243> = 243;
<I244> = 244;
<I245> = 245;
<I246> = 246;
<I247> = 247;
<I248> = 248;
<I249> = 249;
<I250> = 250;
<I251> = 251;
<I252> = 252;
<I253> = 253;
<I254> = 254;
<I255> = 255;
};
xkb_symbols "squeekboard" {
name[Group1] = "Letters";
name[Group2] = "Numbers/Symbols";
key <AD01> { [ q, Q ], [ 1, asciitilde ] };
key <AD02> { [ w, W ], [ 2, quoteleft ] };
key <AD03> { [ e, E ], [ 3, bar ] };
key <AD04> { [ r, R ], [ 4, U00B7 ] };
key <AD05> { [ t, T ], [ 5, squareroot ] };
key <AD06> { [ y, Y ], [ 6, Greek_pi ] };
key <AD07> { [ u, U ], [ 7, division ] };
key <AD08> { [ i, I ], [ 8, multiply ] };
key <AD09> { [ o, O ], [ 9, paragraph ] };
key <AD10> { [ p, P ], [ 0, U25B3 ] };
key <AC01> { [ a, A ], [ at, copyright ] };
key <AC02> { [ s, S ], [ numbersign, U00AE ] };
key <AC03> { [ d, D ], [ dollar, U00A3 ] };
key <AC04> { [ f, F ], [ percent, EuroSign ] };
key <AC05> { [ g, G ], [ ampersand, U00A5 ] };
key <AC06> { [ h, H ], [ minus, asciicircum ] };
key <AC07> { [ j, J ], [ underscore, degree ] };
key <AC08> { [ k, K ], [ plus, equal ] };
key <AC09> { [ l, L ], [ parenleft, braceleft ] };
key <AC10> { [ ], [ parenright, braceright ] };
key <RTRN> { [ Return, Return ], [ Return, Return ] };
key <LFSH> { [ Shift_L, Shift_L ], [ Shift_L, Shift_L ] };
key <AB01> { [ z, Z ], [ comma, backslash ] };
key <AB02> { [ x, X ], [ quotedbl, slash ] };
key <AB03> { [ c, C ], [ quoteright, less ] };
key <AB04> { [ v, V ], [ colon, greater ] };
key <AB05> { [ b, B ], [ semicolon, equal ] };
key <AB06> { [ n, N ], [ exclam, bracketleft ] };
key <AB07> { [ m, M ], [ question, bracketright ] };
key <AB08> { [ period, period ], [ period, period ] };
key <I149> { [ preferences, preferences ], [ preferences, preferences ] };
key <SPCE> { [ space, space ], [ space, space ] };
key <BKSP> { [ BackSpace, BackSpace ], [ BackSpace, BackSpace ] };
};
xkb_types "squeekboard" {
type "TWO_LEVEL" {
modifiers = Shift;
map[Shift] = Level2;
level_name[Level1] = "Base";
level_name[Level2] = "Shift";
};
};
xkb_compatibility "squeekboard" {
};
};

View File

@ -63,8 +63,10 @@
<key name="AD11">
<symbol keyval="229" label="&#229;">aring</symbol>
<symbol keyval="197" label="&#197;">Aring</symbol>
<symbol label="&#177;">U00B1</symbol>
<symbol label="&#167;">U00A7</symbol>
<symbol label=""></symbol>
<symbol label=""></symbol>
<!-- Empty labels cause keys to be hidden when the level they are defined
for is shown. -->
</key>
<key name="AC01">
<symbol label="a">a</symbol>
@ -100,37 +102,37 @@
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="_">underscore</symbol>
<symbol label="^">asciicircum</symbol>
</key>
<key name="AC07">
<symbol label="j">j</symbol>
<symbol label="J">J</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
<symbol label="_">underscore</symbol>
<symbol label="&#176;">degree</symbol>
</key>
<key name="AC08">
<symbol label="k">k</symbol>
<symbol label="K">K</symbol>
<symbol label="&#252;">U00FC</symbol>
<symbol label="^">asciicircum</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
</key>
<key name="AC09">
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="&#246;">U00F6</symbol>
<symbol label="&#176;">degree</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
</key>
<key name="AC10">
<symbol keyval="248" label="&#248;">oslash</symbol>
<symbol keyval="216" label="&#216;">Oslash</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
</key>
<key name="AC11">
<symbol keyval="230" label="&#230;">ae</symbol>
<symbol keyval="198" label="&#198;">AE</symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
<symbol label=""></symbol>
<symbol label=""></symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>

View File

@ -115,6 +115,8 @@
<symbol label="{">braceleft</symbol>
</key>
<key name="AC10">
<!-- Empty labels cause keys to be hidden when the level they are defined
for is shown. -->
<symbol label=""></symbol>
<symbol label=""></symbol>
<symbol label=")">parenright</symbol>

View File

@ -4,11 +4,8 @@
<file compressed="true">style.css</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/compact.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/extended.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/numbers-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/number-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
<file compressed="true">keyboards/keymaps/nb.xkb</file>
<file compressed="true">keyboards/keymaps/us.xkb</file>
<file compressed="true">keyboards/keymaps/numbers.xkb</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>
@ -38,7 +35,7 @@
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ug.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/us.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/numbers.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/number.xml</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>
<file>icons/keyboard-mode-symbolic.svg</file>

View File

@ -100,6 +100,7 @@ eek_element_set_property (GObject *object,
break;
case PROP_LEVEL:
eek_element_set_level (element, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View File

@ -162,6 +162,7 @@ static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (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);
@ -487,11 +488,13 @@ render_pressed_key (GtkWidget *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);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
@ -518,11 +521,15 @@ render_locked_key (GtkWidget *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);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
gdk_window_end_draw_frame (window, context);
@ -542,9 +549,6 @@ render_released_key (GtkWidget *widget,
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);
eek_renderer_render_keyboard (priv->renderer, cr);
gdk_window_end_draw_frame (window, context);

View File

@ -28,6 +28,7 @@
*/
#include "config.h"
#include <glib/gprintf.h>
#include "eek-keyboard.h"
#include "eek-marshalers.h"
@ -36,6 +37,7 @@
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
enum {
PROP_0,
@ -72,6 +74,8 @@ struct _EekKeyboardPrivate
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
/* Map key names to key objects: */
GHashTable *names;
/* modifiers dynamically assigned at run time */
@ -796,3 +800,93 @@ 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);
}
/**
* eek_keyboard_get_keymap:
* @keyboard: an #EekKeyboard
*
* Get the keymap for the keyboard.
* Returns: a string containing the XKB keymap.
*/
gchar *
eek_keyboard_get_keymap(EekKeyboard *keyboard)
{
/* Start the keycodes and symbols sections with their respective headers. */
gchar *keycodes = g_strdup(keymap_keycodes_header);
gchar *symbols = g_strdup(keymap_symbols_header);
/* Iterate over the keys in the name-to-key hash table. */
GHashTableIter iter;
gpointer key_name, key_ptr;
g_hash_table_iter_init(&iter, keyboard->priv->names);
while (g_hash_table_iter_next(&iter, &key_name, &key_ptr)) {
gchar *current, *line;
EekKey *key = EEK_KEY(key_ptr);
int keycode = eek_key_get_keycode(key);
/* Don't include invalid keycodes in the keymap. */
if (keycode == EEK_INVALID_KEYCODE)
continue;
/* Append a key name-to-keycode definition to the keycodes section. */
current = keycodes;
line = g_strdup_printf(" <%s> = %i;\n", (char *)key_name, keycode);
keycodes = g_strconcat(current, line, NULL);
g_free(line);
g_free(current);
/* Find the symbols associated with the key. */
EekSymbolMatrix *matrix = eek_key_get_symbol_matrix(key);
EekSymbol *syms[4];
int i, j;
/* Get the symbols for all the levels defined for the key, then
pad it out with the first symbol for all levels up to the fourth. */
for (i = 0; i < matrix->num_levels; ++i)
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
while (i < 4) {
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, 0);
i++;
}
/* The four levels are split into two groups in the keymap.
Generate strings for each of these groups, where an empty group is
treated specially. */
gchar *groups[2];
for (i = 0, j = 0; i < 2; ++i, j += 2) {
if (syms[j] && syms[j + 1])
groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
eek_symbol_get_name(syms[j + 1]),
NULL);
else
groups[i] = "";
}
/* Append a key definition to the symbols section. */
current = symbols;
line = g_strdup_printf(" key <%s> { [ %s ], [ %s ] };\n",
(char *)key_name, groups[0], groups[1]);
g_free(groups[0]);
g_free(groups[1]);
symbols = g_strconcat(current, line, NULL);
g_free(line);
g_free(current);
}
/* Assemble the keymap file from the header, sections and footer. */
gchar *keymap = g_strconcat(keymap_header,
keycodes, " };\n\n",
symbols, " };\n\n",
keymap_footer, NULL);
g_free(keycodes);
g_free(symbols);
return keymap;
}

View File

@ -195,5 +195,8 @@ void eek_modifier_key_free
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
gchar * eek_keyboard_get_keymap
(EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -129,60 +129,8 @@ eek_layout_place_sections(EekKeyboard *keyboard)
eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
}
static void scale_bounds_callback (EekElement *element,
gpointer user_data);
static void
scale_bounds (EekElement *element,
gdouble scale)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.x *= scale;
bounds.y *= scale;
bounds.width *= scale;
bounds.height *= scale;
eek_element_set_bounds (element, &bounds);
if (EEK_IS_CONTAINER(element))
eek_container_foreach_child (EEK_CONTAINER(element),
scale_bounds_callback,
&scale);
}
static void
scale_bounds_callback (EekElement *element,
gpointer user_data)
{
scale_bounds (element, *(gdouble *)user_data);
}
void
eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale)
{
gsize n_outlines;
scale_bounds (EEK_ELEMENT(keyboard), scale);
n_outlines = eek_keyboard_get_n_outlines (keyboard);
for (guint i = 0; i < n_outlines; i++) {
EekOutline *outline = eek_keyboard_get_outline (keyboard, i);
gint j;
for (j = 0; j < outline->num_points; j++) {
outline->points[j].x *= scale;
outline->points[j].y *= scale;
}
}
keyboard->scale = scale;
}
void
eek_layout_update_layout(EekKeyboard *keyboard)
{
eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale);
eek_layout_place_sections(keyboard);
eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale);
}

View File

@ -57,8 +57,6 @@ GType eek_layout_get_type (void) G_GNUC_CONST;
void eek_layout_place_sections(EekKeyboard *keyboard);
void eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale);
void eek_layout_update_layout(EekKeyboard *keyboard);
G_END_DECLS

View File

@ -49,6 +49,8 @@ typedef struct _EekRendererPrivate
gdouble allocation_height;
gdouble scale;
gint scale_factor; /* the outputs scale factor */
gint origin_x;
gint origin_y;
PangoFontDescription *ascii_font;
PangoFontDescription *font;
@ -105,18 +107,17 @@ create_keyboard_surface_key_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
cairo_save (data->cr);
eek_element_get_bounds (element, &bounds);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_translate (data->cr, bounds.x, bounds.y);
cairo_rectangle (data->cr,
0.0,
0.0,
bounds.width * priv->scale + 100,
bounds.height * priv->scale + 100);
bounds.width + 100,
bounds.height + 100);
cairo_clip (data->cr);
render_key (data->renderer, data->cr, EEK_KEY(element), FALSE);
@ -128,14 +129,13 @@ create_keyboard_surface_section_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
gint angle;
cairo_save (data->cr);
eek_element_get_bounds (element, &bounds);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_translate (data->cr, bounds.x, bounds.y);
angle = eek_section_get_angle (EEK_SECTION(element));
cairo_rotate (data->cr, angle * G_PI / 180);
@ -167,7 +167,9 @@ render_keyboard_surface (EekRenderer *renderer)
data.cr = cairo_create (priv->keyboard_surface);
data.renderer = renderer;
cairo_translate (data.cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_save (data.cr);
cairo_scale (data.cr, priv->scale, priv->scale);
cairo_translate (data.cr, bounds.x, bounds.y);
/* blank background */
cairo_set_source_rgba (data.cr,
@ -187,6 +189,8 @@ render_keyboard_surface (EekRenderer *renderer)
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_keyboard_surface_section_callback,
&data);
cairo_restore (data.cr);
cairo_destroy (data.cr);
}
@ -243,14 +247,7 @@ render_key_outline (EekRenderer *renderer,
eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
outline = eek_outline_copy (outline);
for (guint i = 0; i < outline->num_points; i++) {
outline->points[i].x *= priv->scale;
outline->points[i].y *= priv->scale;
}
cairo_translate (cr,
border_width * priv->scale,
border_width * priv->scale);
cairo_translate (cr, border_width, border_width);
if (gradient_type != EEK_GRADIENT_NONE) {
cairo_pattern_t *pat;
@ -261,17 +258,17 @@ render_key_outline (EekRenderer *renderer,
pat = cairo_pattern_create_linear (0.0,
0.0,
0.0,
bounds.height * priv->scale);
bounds.height);
break;
case EEK_GRADIENT_HORIZONTAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
bounds.width * priv->scale,
bounds.width,
0.0);
break;
case EEK_GRADIENT_RADIAL:
cx = bounds.width / 2 * priv->scale;
cy = bounds.height / 2 * priv->scale;
cx = bounds.width / 2;
cy = bounds.height / 2;
pat = cairo_pattern_create_radial (cx,
cy,
0,
@ -328,98 +325,11 @@ render_key_outline (EekRenderer *renderer,
outline->num_points);
cairo_stroke (cr);
cairo_translate (cr,
-border_width * priv->scale,
-border_width * priv->scale);
cairo_translate (cr, -border_width, -border_width);
eek_outline_free (outline);
}
struct _CalculateFontSizeCallbackData {
gdouble size;
gboolean ascii;
EekRenderer *renderer;
const PangoFontDescription *base_font;
};
typedef struct _CalculateFontSizeCallbackData CalculateFontSizeCallbackData;
static void
calculate_font_size_key_callback (EekElement *element, gpointer user_data)
{
CalculateFontSizeCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
gdouble sx, sy;
PangoFontDescription *font;
PangoRectangle extents = { 0, };
PangoLayout *layout;
gdouble size;
EekBounds bounds;
const gchar *label = NULL;
if (data->ascii)
label = "M";
else {
EekSymbol *symbol;
symbol = eek_key_get_symbol (EEK_KEY(element));
if (symbol &&
eek_symbol_get_category (symbol) == EEK_SYMBOL_CATEGORY_LETTER)
label = eek_symbol_get_label (symbol);
if (!label)
label = "M";
}
font = pango_font_description_copy (data->base_font);
eek_element_get_bounds (element, &bounds);
size = eek_bounds_long_side (&bounds) * PANGO_SCALE;
pango_font_description_set_size (font, size);
layout = pango_layout_new (priv->pcontext);
pango_layout_set_font_description (layout, font);
pango_font_description_free (font);
pango_layout_set_text (layout, label, -1);
pango_layout_get_extents (layout, NULL, &extents);
g_object_unref (layout);
sx = sy = 1.0;
if (extents.width > bounds.width * PANGO_SCALE)
sx = bounds.width * PANGO_SCALE / extents.width;
if (extents.height > bounds.height * PANGO_SCALE)
sy = bounds.height * PANGO_SCALE / extents.height;
size *= MIN(sx, sy);
if (size < data->size)
data->size = size;
}
static void
calculate_font_size_section_callback (EekElement *element, gpointer user_data)
{
eek_container_foreach_child (EEK_CONTAINER(element),
calculate_font_size_key_callback,
user_data);
}
static gdouble
calculate_font_size (EekRenderer *renderer,
const PangoFontDescription *base_font,
gboolean ascii)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
CalculateFontSizeCallbackData data;
data.size = G_MAXDOUBLE;
data.ascii = ascii;
data.renderer = renderer;
data.base_font = base_font;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
calculate_font_size_section_callback,
&data);
return data.size;
}
static void
render_key (EekRenderer *self,
cairo_t *cr,
@ -447,8 +357,6 @@ render_key (EekRenderer *self,
/* render outline */
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
bounds.width *= priv->scale;
bounds.height *= priv->scale;
if (active)
outline_surface_cache = priv->active_outline_surface_cache;
@ -492,13 +400,12 @@ render_key (EekRenderer *self,
if (!symbol)
return;
#define SCALE 0.4
if (eek_symbol_get_icon_name (symbol)) {
gint scale = priv->scale_factor;
cairo_surface_t *icon_surface =
eek_renderer_get_icon_surface (self,
eek_symbol_get_icon_name (symbol),
SCALE * MIN(bounds.width, bounds.height),
16,
scale);
if (icon_surface) {
gint width = cairo_image_surface_get_width (icon_surface);
@ -582,9 +489,8 @@ get_text_property_for_category (EekSymbolCategory category)
{ EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
{ EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
};
gint i;
for (i = 0; i < G_N_ELEMENTS(props); i++)
for (uint i = 0; i < G_N_ELEMENTS(props); i++)
if (props[i].category == category)
return &props[i];
@ -624,13 +530,16 @@ eek_renderer_real_render_key_label (EekRenderer *self,
base_font = eek_theme_node_get_font (theme_node);
else
base_font = pango_context_get_font_description (priv->pcontext);
ascii_size = calculate_font_size (self, base_font, TRUE);
// FIXME: Base font size on the same size unit used for button sizing,
// and make the default about 1/3 of the current row height
ascii_size = 30000.0;
priv->ascii_font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->ascii_font, ascii_size);
pango_font_description_set_size (priv->ascii_font,
(gint)round(ascii_size));
size = calculate_font_size (self, base_font, FALSE);
size = 30000.0;
priv->font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->font, size * 0.6);
pango_font_description_set_size (priv->font, (gint)round(size * 0.6));
}
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
@ -644,8 +553,8 @@ eek_renderer_real_render_key_label (EekRenderer *self,
priv->ascii_font :
priv->font);
pango_font_description_set_size (font,
pango_font_description_get_size (font) *
prop->scale * priv->scale * scale);
(gint)round(pango_font_description_get_size (font) *
prop->scale * scale));
pango_layout_set_font_description (layout, font);
pango_font_description_free (font);
@ -654,7 +563,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
if (line->resolved_dir == PANGO_DIRECTION_RTL)
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
pango_layout_set_width (layout,
PANGO_SCALE * bounds.width * priv->scale * scale);
PANGO_SCALE * bounds.width * scale);
if (prop->ellipses)
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
}
@ -679,7 +588,10 @@ eek_renderer_real_render_key (EekRenderer *self,
gdouble scale,
gboolean rotate)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
cairo_save (cr);
cairo_translate (cr, priv->origin_x, priv->origin_y);
eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate);
render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key));
cairo_restore (cr);
@ -696,6 +608,10 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
g_return_if_fail (priv->allocation_width > 0.0);
g_return_if_fail (priv->allocation_height > 0.0);
cairo_save (cr);
cairo_translate (cr, priv->origin_x, priv->origin_y);
if (priv->keyboard_surface)
cairo_surface_destroy (priv->keyboard_surface);
@ -709,6 +625,8 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
source = cairo_get_source (cr);
cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
cairo_paint (cr);
cairo_restore (cr);
}
static void
@ -924,21 +842,19 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
priv->allocation_width = width;
priv->allocation_height = height;
/* Calculate a scale factor to use when rendering the keyboard into the
available space. */
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (bounds.height * width / bounds.width <= height)
scale = width / bounds.width;
else if (bounds.width * height / bounds.height <= width)
scale = height / bounds.height;
else {
if (bounds.width * height < bounds.height * width)
scale = bounds.width / width;
else
scale = bounds.height / height;
}
gdouble w = (bounds.x * 2) + bounds.width;
gdouble h = (bounds.y * 2) + bounds.height;
scale = MIN(width / w, height / h);
if (scale != priv->scale) {
priv->scale = scale;
priv->origin_x = 0;
priv->origin_y = 0;
invalidate (renderer);
}
}
@ -956,9 +872,9 @@ eek_renderer_get_size (EekRenderer *renderer,
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (width)
*width = bounds.width * priv->scale;
*width = bounds.width;
if (height)
*height = bounds.height * priv->scale;
*height = bounds.height;
}
void
@ -971,7 +887,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
EekBounds section_bounds, keyboard_bounds;
gint angle = 0;
EekPoint points[4], min, max;
gint i;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_KEY(key));
@ -989,10 +904,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
if (!rotate) {
bounds->x += keyboard_bounds.x + section_bounds.x;
bounds->y += keyboard_bounds.y + section_bounds.y;
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
return;
}
points[0].x = bounds->x;
@ -1009,7 +920,7 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
min = points[2];
max = points[0];
for (i = 0; i < G_N_ELEMENTS(points); i++) {
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], angle);
if (points[i].x < min.x)
min.x = points[i].x;
@ -1024,10 +935,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
bounds->y = keyboard_bounds.y + section_bounds.y + min.y;
bounds->width = (max.x - min.x);
bounds->height = (max.y - min.y);
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
}
gdouble
@ -1255,7 +1162,6 @@ find_key_by_position_key_callback (EekElement *element,
FindKeyByPositionCallbackData *data = user_data;
EekBounds bounds;
EekPoint points[4];
gint i;
gboolean b1, b2, b3;
eek_element_get_bounds (element, &bounds);
@ -1269,14 +1175,10 @@ find_key_by_position_key_callback (EekElement *element,
points[3].x = points[0].x;
points[3].y = points[2].y;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
for (i = 0; i < G_N_ELEMENTS(points); i++) {
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], data->angle);
points[i].x += data->origin.x;
points[i].y += data->origin.y;
points[i].x *= priv->scale;
points[i].y *= priv->scale;
}
b1 = sign (&data->point, &points[0], &points[1]) < 0.0;
@ -1332,13 +1234,17 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
x /= priv->scale;
y /= priv->scale;
x -= priv->origin_x;
y -= priv->origin_y;
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (x < bounds.x * priv->scale ||
y < bounds.y * priv->scale ||
x > bounds.width * priv->scale ||
y > bounds.height * priv->scale)
if (x < bounds.x ||
y < bounds.y ||
x > bounds.width ||
y > bounds.height)
return NULL;
data.point.x = x;

View File

@ -535,7 +535,8 @@ keycounter (EekElement *element, gpointer user_data)
{
EekKey *key = EEK_KEY(element);
/* Skip keys without labels for the current level. */
/* Skip keys without labels for the current level. This causes those
keys to be hidden in the visible layout. */
if (!eek_key_has_label(key))
return;

View File

@ -79,10 +79,6 @@ static gboolean parse_symbols (const gchar *path,
EekKeyboard *keyboard,
GError **error);
static void scale_keyboard (EekKeyboard *keyboard,
gdouble width,
gdouble height);
static gboolean validate (const gchar **valid_path_list,
gsize valid_path_list_len,
const gchar *element_name,
@ -247,6 +243,7 @@ struct _GeometryParseData {
gchar *name;
EekOutline outline;
gchar *oref;
gint keycode;
GHashTable *key_oref_hash;
GHashTable *oref_outline_hash;
@ -269,6 +266,7 @@ geometry_parse_data_new (EekKeyboard *keyboard)
g_str_equal,
g_free,
(GDestroyNotify)eek_outline_free);
data->keycode = 8;
return data;
}
@ -396,17 +394,6 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
if (g_strcmp0 (element_name, "key") == 0) {
guint keycode;
attribute = get_attribute (attribute_names, attribute_values,
"keycode");
if (attribute == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"keycode\" attribute for \"key\"");
return;
}
keycode = strtol (attribute, NULL, 10);
attribute = get_attribute (attribute_names, attribute_values,
"name");
if (attribute == NULL) {
@ -416,9 +403,17 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
"no \"name\" attribute for \"key\"");
return;
}
gchar *name = g_strdup (attribute);
attribute = get_attribute (attribute_names, attribute_values,
"keycode");
if (attribute != NULL)
keycode = strtol (attribute, NULL, 10);
else
keycode = data->keycode++;
data->key = eek_section_create_key (data->section,
g_strdup (attribute),
name,
keycode,
data->num_columns,
data->num_rows - 1);
@ -727,7 +722,6 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
gint levels = num_symbols / data->groups;
EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
levels);
head = data->symbols = g_slist_reverse (data->symbols);
for (i = 0; i < num_symbols; i++) {
if (head && head->data) {
@ -948,9 +942,6 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
eek_layout_place_sections(keyboard);
/* Fit keyboard in the given width and height. */
scale_keyboard (keyboard, initial_width, initial_height);
/* Use pre-defined modifier mask here. */
eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
eek_keyboard_set_alt_gr_mask (keyboard, EEK_BUTTON1_MASK);
@ -1360,23 +1351,6 @@ parse_keyboards (const gchar *path, GError **error)
return keyboards;
}
static void scale_keyboard (EekKeyboard *keyboard,
gdouble width,
gdouble height)
{
gdouble scale;
EekBounds bounds;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
if (width * bounds.height < height * bounds.width)
scale = width / bounds.width;
else
scale = height / bounds.height;
eek_layout_scale_keyboard(keyboard, scale);
}
static gboolean
validate (const gchar **valid_path_list,
gsize valid_path_list_len,

View File

@ -1,315 +0,0 @@
/*
* 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
*/
#include "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");
}

View File

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

@ -29,7 +29,6 @@
#include "eek-symbol.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "eek-xml.h"
#include "eek-serializable.h"
#include "eek-theme.h"

39
eek/keymap.h Normal file
View File

@ -0,0 +1,39 @@
#include <gdk/gdk.h>
#include <xkbcommon/xkbcommon.h>
gboolean
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
guint keyval,
GdkKeymapKey **keys,
guint *n_keys);
static const char *keymap_header = "xkb_keymap {\n\
\n";
static const char *keymap_keycodes_header = "\
xkb_keycodes \"squeekboard\" {\n\n\
minimum = 8;\n\
maximum = 255;\n\
\n";
static const char *keymap_symbols_header = "\
xkb_symbols \"squeekboard\" {\n\
\n\
name[Group1] = \"Letters\";\n\
name[Group2] = \"Numbers/Symbols\";\n\
\n";
static const char *keymap_footer = "\
xkb_types \"squeekboard\" {\n\
\n\
type \"TWO_LEVEL\" {\n\
modifiers = Shift;\n\
map[Shift] = Level2;\n\
level_name[Level1] = \"Base\";\n\
level_name[Level2] = \"Shift\";\n\
};\n\
};\n\
\n\
xkb_compatibility \"squeekboard\" {\n\
};\n\
};";

View File

@ -27,9 +27,6 @@
#include "config.h"
#include "eekboard/eekboard-context-service.h"
#include "keymap.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@ -37,10 +34,14 @@
#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 "eekboard/eekboard-xklutil.h"
//#include "eek/eek-xkl.h"
#include "eek/eek-xml-layout.h"
#include "eekboard/eekboard-context-service.h"
#define CSW 640
#define CSH 480
@ -85,55 +86,6 @@ struct _EekboardContextServicePrivate {
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
/*static Display *display = NULL; */
gchar *
get_keymap_from_resource(const gchar *keyboard_type, gboolean fallback)
{
g_autoptr (GFile) file = NULL;
g_autoptr (GFileInfo) info = NULL;
g_autoptr (GFileInputStream) stream = NULL;
goffset size = 0;
gsize bytes_read = 0;
g_autofree gchar *contents = NULL;
g_autofree gchar *path = NULL;
GError *error = NULL;
if (fallback)
g_debug ("falling back to loading a %s keymap", keyboard_type);
path = g_strconcat ("resource:///sm/puri/squeekboard/keyboards/keymaps/",
keyboard_type, ".xkb", NULL);
file = g_file_new_for_uri (path);
stream = g_file_read (file, NULL, &error);
if (!stream)
goto keymap_error;
info = g_file_input_stream_query_info (stream,
G_FILE_ATTRIBUTE_STANDARD_SIZE,
NULL,
&error);
if (!info)
goto keymap_error;
size = g_file_info_get_size (info);
contents = g_malloc0 (size);
if (!g_input_stream_read_all (G_INPUT_STREAM(stream), contents, size,
&bytes_read, NULL, &error))
goto keymap_error;
return g_utf8_make_valid (contents, -1);
keymap_error:
if (fallback)
g_error ("failed to load keymap from resource: %s", error->message);
g_error_free (error);
return NULL;
}
static EekKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
const gchar *keyboard_type)
@ -193,13 +145,8 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
if (!context) {
g_error("No context created");
}
/*
struct xkb_rule_names rules = { 0 };
rules.layout = strdup(keyboard_type);
*/
char *keymap_str = get_keymap_from_resource(keyboard_type, FALSE);
if (!keymap_str)
keymap_str = get_keymap_from_resource("us", TRUE);
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
@ -357,8 +304,14 @@ settings_update_layout(EekboardContextService *context)
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
if (priv->purpose == ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE)
keyboard_layout = g_strdup("numbers");
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;

View File

@ -28,12 +28,14 @@
#include "config.h"
#include "eekboard/eekboard-service.h"
#include "sm.puri.OSK0.h"
#include <stdio.h>
#include <gio/gio.h>
#include "eekboard/eekboard-service.h"
enum {
PROP_0,
PROP_OBJECT_PATH,

View File

@ -20,7 +20,6 @@
/* This file is responsible for managing keycode data and emitting keycodes. */
#include "eekboard/key-emitter.h"
#include "eekboard/keymap.h"
#include <gdk/gdk.h>
@ -39,98 +38,6 @@ typedef struct {
} SeatEmitter;
/* The following functions for keyboard mapping change are direct
translation of the code in Caribou (in libcaribou/xadapter.vala):
- get_replaced_keycode (Caribou: get_reserved_keycode)
- replace_keycode
- get_keycode_from_gdk_keymap (Caribou: best_keycode_keyval_match)
*/
/* Find an unused keycode where a keysym can be assigned. Restricted to Level 1 */
static guint
get_replaced_keycode (SeatEmitter *client)
{
guint keycode;
return 0; // FIXME: no xkb allocated yet
for (keycode = client->xkb->max_key_code;
keycode >= client->xkb->min_key_code;
--keycode) {
guint offset = client->xkb->map->key_sym_map[keycode].offset;
if (client->xkb->map->key_sym_map[keycode].kt_index[0] == XkbOneLevelIndex &&
client->xkb->map->syms[offset] != NoSymbol) {
return keycode;
}
}
return 0;
}
/* Replace keysym assigned to KEYCODE to KEYSYM. Both args are used
as in-out. If KEYCODE points to 0, this function picks a keycode
from the current map and replace the associated keysym to KEYSYM.
In that case, the replaced keycode is stored in KEYCODE and the old
keysym is stored in KEYSYM. If otherwise (KEYCODE points to
non-zero keycode), it simply changes the current map with the
specified KEYCODE and KEYSYM. */
static gboolean
replace_keycode (SeatEmitter *emitter,
guint keycode,
guint *keysym)
{
/* GdkDisplay *display = gdk_display_get_default ();
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
guint old_keysym;
int keysyms_per_keycode;
KeySym *syms;
*/
return TRUE; // FIXME: no xkb allocated at the moment, pretending all is fine
g_return_val_if_fail (emitter->xkb->min_key_code <= keycode &&
keycode <= emitter->xkb->max_key_code,
FALSE);
g_return_val_if_fail (keysym != NULL, FALSE);
/*
* Update keyboard mapping. Wayland receives keyboard mapping as a string, so XChangeKeyboardMapping needs to translate from the symbol tbale t the string. TODO.
*
syms = XGetKeyboardMapping (xdisplay, keycode, 1, &keysyms_per_keycode);
old_keysym = syms[0];
syms[0] = *keysym;
XChangeKeyboardMapping (xdisplay, keycode, 1, syms, 1);
XSync (xdisplay, False);
XFree (syms);
*keysym = old_keysym;
*/
return TRUE;
}
static gboolean
get_keycode_from_gdk_keymap (SeatEmitter *emitter,
guint keysym,
guint *keycode,
guint *modifiers)
{
GdkKeymapKey *keys, *best_match = NULL;
guint n_keys, i;
if (!squeek_keymap_get_entries_for_keyval (emitter->keymap, keysym, &keys, &n_keys))
return FALSE;
for (i = 0; i < n_keys; i++)
if ((guint)keys[i].group == emitter->group)
best_match = &keys[i];
if (!best_match) {
g_free (keys);
return FALSE;
}
*keycode = best_match->keycode;
*modifiers = best_match->level == 1 ? EEK_SHIFT_MASK : 0;
g_free (keys);
return TRUE;
}
int send_virtual_keyboard_key(
struct zwp_virtual_keyboard_v1 *keyboard,
unsigned int keycode,
@ -161,95 +68,6 @@ send_fake_modifiers_events (SeatEmitter *emitter,
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, emitter->group);
}
static void
send_fake_key_event (SeatEmitter *emitter,
guint xkeysym,
guint keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
EekModifierType modifiers;
guint old_keysym = xkeysym;
g_return_if_fail (xkeysym > 0);
guint keycode;
if (!get_keycode_from_gdk_keymap (emitter, xkeysym, &keycode, &modifiers)) {
keycode = get_replaced_keycode (emitter);
if (keycode == 0) {
g_warning ("no available keycode to replace");
return;
}
if (!replace_keycode (emitter, keycode, &old_keysym)) {
g_warning ("failed to lookup X keysym %X", xkeysym);
return;
}
}
/* Clear level shift modifiers */
keyboard_modifiers &= (unsigned)~EEK_SHIFT_MASK;
keyboard_modifiers &= (unsigned)~EEK_LOCK_MASK;
/* FIXME: may need to remap ISO_Level3_Shift and NumLock */
modifiers |= keyboard_modifiers;
send_fake_modifiers_events (emitter, modifiers, timestamp);
// There's something magical about subtracting/adding 8 to keycodes for some reason
send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
send_fake_modifiers_events (emitter, modifiers, timestamp);
if (old_keysym != xkeysym)
replace_keycode (emitter, keycode, &old_keysym);
}
static void
send_fake_key_events (SeatEmitter *emitter,
EekSymbol *symbol,
EekModifierType keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
/* Ignore modifier keys */
if (eek_symbol_is_modifier (symbol))
return;
/* If symbol is a text, convert chars in it to keysym */
if (EEK_IS_TEXT(symbol)) {
const gchar *utf8 = eek_text_get_text (EEK_TEXT(symbol));
printf("Attempting to send text %s\n", utf8);
/* FIXME:
glong items_written;
gunichar *ucs4 = g_utf8_to_ucs4_fast (utf8, -1, &items_written);
gint i;
for (i = 0; i < items_written; i++) {
guint xkeysym;
EekKeysym *keysym;
gchar *name;
name = g_strdup_printf ("U%04X", ucs4[i]);
xkeysym = XStringToKeysym (name); // TODO: use xkb_get_keysym_from_name
g_free (name);
keysym = eek_keysym_new (xkeysym);
send_fake_key_events (client,
EEK_SYMBOL(keysym),
keyboard_modifiers);
}
g_free (ucs4);
*/
return;
}
if (EEK_IS_KEYSYM(symbol)) {
guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
send_fake_key_event (emitter, xkeysym, keyboard_modifiers, pressed, timestamp);
}
}
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
static void
update_modifier_info (SeatEmitter *client)

View File

@ -1,66 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2000 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified for squeekboard based on GTK
*/
#include "keymap.h"
gboolean
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
guint keyval,
GdkKeymapKey **keys,
guint *n_keys)
{
GArray *retval;
guint keycode;
xkb_keycode_t min_keycode, max_keycode;
retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
max_keycode = xkb_keymap_max_keycode (xkb_keymap);
for (keycode = min_keycode; keycode < max_keycode; keycode++)
{
xkb_layout_index_t num_layouts, layout;
num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, keycode);
for (layout = 0; layout < num_layouts; layout++)
{
xkb_layout_index_t num_levels, level;
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
for (level = 0; level < num_levels; level++)
{
const xkb_keysym_t *syms;
gint num_syms, sym;
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
for (sym = 0; sym < num_syms; sym++)
{
if (syms[sym] == keyval)
{
GdkKeymapKey key;
key.keycode = keycode;
key.group = (gint)layout;
key.level = (gint)level;
g_array_append_val (retval, key);
}
}
}
}
}
*n_keys = retval->len;
*keys = (GdkKeymapKey*) g_array_free (retval, FALSE);
return TRUE;
}

View File

@ -1,8 +0,0 @@
#include <gdk/gdk.h>
#include <xkbcommon/xkbcommon.h>
gboolean
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
guint keyval,
GdkKeymapKey **keys,
guint *n_keys);

View File

@ -11,6 +11,16 @@ project(
]
)
add_project_arguments(
[
'-Werror=implicit-function-declaration',
'-Werror=implicit-fallthrough=3',
'-Werror=maybe-uninitialized',
# '-Werror=missing-field-initializers', // fix eek-unicode-keysym-entries first
],
language: 'c'
)
i18n = import('i18n')
conf_data = configuration_data()

1350
src/bitflags.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,19 +5,6 @@
#include "eekboard/eekboard-context-service.h"
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause) {}
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose)
{
struct imservice *ims = (struct imservice*)data;
EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(ims->ui_manager);
eekboard_context_service_set_hint_purpose(context, hint, purpose);
}
void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method) {}
static const struct zwp_input_method_v2_listener input_method_listener = {
.activate = imservice_handle_input_method_activate,
.deactivate = imservice_handle_input_method_deactivate,
@ -41,14 +28,16 @@ struct imservice* get_imservice(EekboardContextService *context,
return imservice;
}
void imservice_make_visible(EekboardContextService *context,
struct zwp_input_method_v2 *im) {
(void)im;
void imservice_make_visible(EekboardContextService *context) {
eekboard_context_service_show_keyboard (context);
}
void imservice_try_hide(EekboardContextService *context,
struct zwp_input_method_v2 *im) {
(void)im;
void imservice_try_hide(EekboardContextService *context) {
eekboard_context_service_hide_keyboard (context);
}
/// Declared explicitly because _destroy is inline,
/// making it unavailable in Rust
void imservice_destroy_im(struct zwp_input_method_v2 *im) {
zwp_input_method_v2_destroy(im);
}

View File

@ -4,11 +4,7 @@
#include "input-method-unstable-v2-client-protocol.h"
#include "eek/eek-types.h"
struct imservice
{
struct zwp_input_method_v2 *im;
EekboardContextService *ui_manager;
};
struct imservice;
struct imservice* get_imservice(EekboardContextService *context,
struct zwp_input_method_manager_v2 *manager,
@ -22,5 +18,8 @@ void imservice_handle_input_method_deactivate(void *data, struct zwp_input_metho
void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method,
const char *text, uint32_t cursor, uint32_t anchor);
void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method);
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose);
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause);
void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method);
#endif

View File

@ -3,6 +3,11 @@ use std::ffi::CString;
use std::num::Wrapping;
use std::string::String;
use super::bitflags;
// Traits
use std::convert::TryFrom;
/// Gathers stuff defined in C or called by C
pub mod c {
@ -18,7 +23,7 @@ pub mod c {
}
// The following defined in C
/// struct zwp_input_method_v2*
#[repr(transparent)]
pub struct InputMethod(*const c_void);
@ -29,8 +34,10 @@ pub mod c {
#[no_mangle]
extern "C" {
fn imservice_make_visible(imservice: *const UIManager);
fn imservice_try_hide(imservice: *const UIManager);
fn imservice_destroy_im(im: *mut c::InputMethod);
fn eekboard_context_service_set_hint_purpose(imservice: *const UIManager, hint: u32, purpose: u32);
fn eekboard_context_service_show_keyboard(imservice: *const UIManager);
fn eekboard_context_service_hide_keyboard(imservice: *const UIManager);
}
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
@ -54,9 +61,9 @@ pub mod c {
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_input_method_activate(imservice: *mut IMService,
_im: *const InputMethod)
im: *const InputMethod)
{
let imservice = &mut *imservice;
let imservice = check_imservice(imservice, im).unwrap();
imservice.preedit_string = String::new();
imservice.pending = IMProtocolState {
active: true,
@ -67,9 +74,9 @@ pub mod c {
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_input_method_deactivate(imservice: *mut IMService,
_im: *const InputMethod)
im: *const InputMethod)
{
let imservice = &mut *imservice;
let imservice = check_imservice(imservice, im).unwrap();
imservice.pending = IMProtocolState {
active: false,
..imservice.pending.clone()
@ -79,23 +86,65 @@ pub mod c {
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_surrounding_text(imservice: *mut IMService,
_im: *const InputMethod,
im: *const InputMethod,
text: *const c_char, cursor: u32, _anchor: u32)
{
let imservice = &mut *imservice;
let imservice = check_imservice(imservice, im).unwrap();
imservice.pending = IMProtocolState {
surrounding_text: into_cstring(text).expect("Received invalid string"),
surrounding_cursor: cursor,
..imservice.pending
..imservice.pending.clone()
};
}
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_content_type(imservice: *mut IMService,
im: *const InputMethod,
hint: u32, purpose: u32)
{
let imservice = check_imservice(imservice, im).unwrap();
imservice.pending = IMProtocolState {
content_hint: {
ContentHint::from_bits(hint).unwrap_or_else(|| {
eprintln!("Warning: received invalid hint flags");
ContentHint::NONE
})
},
content_purpose: {
ContentPurpose::try_from(purpose).unwrap_or_else(|_e| {
eprintln!("Warning: Received invalid purpose value");
ContentPurpose::Normal
})
},
..imservice.pending.clone()
};
}
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_text_change_cause(imservice: *mut IMService,
im: *const InputMethod,
cause: u32)
{
let imservice = check_imservice(imservice, im).unwrap();
imservice.pending = IMProtocolState {
text_change_cause: {
ChangeCause::try_from(cause).unwrap_or_else(|_e| {
eprintln!("Warning: received invalid cause value");
ChangeCause::InputMethod
})
},
..imservice.pending.clone()
};
}
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_commit_state(imservice: *mut IMService,
_im: *const InputMethod)
im: *const InputMethod)
{
let imservice = &mut *imservice;
let imservice = check_imservice(imservice, im).unwrap();
let active_changed = imservice.current.active ^ imservice.pending.active;
imservice.serial += Wrapping(1u32);
@ -106,27 +155,174 @@ pub mod c {
};
if active_changed {
if imservice.current.active {
imservice_make_visible(imservice.ui_manager);
eekboard_context_service_show_keyboard(imservice.ui_manager);
eekboard_context_service_set_hint_purpose(
imservice.ui_manager,
imservice.current.content_hint.bits(),
imservice.current.content_purpose.clone() as u32);
} else {
imservice_try_hide(imservice.ui_manager);
eekboard_context_service_hide_keyboard(imservice.ui_manager);
}
}
}
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_unavailable(imservice: *mut IMService,
im: *mut InputMethod)
{
let imservice = check_imservice(imservice, im).unwrap();
imservice_destroy_im(im);
// no need to care about proper double-buffering,
// the keyboard is already decommissioned
imservice.current.active = false;
eekboard_context_service_hide_keyboard(imservice.ui_manager);
}
// FIXME: destroy and deallocate
// Helpers
/// Convenience method for referencing the IMService raw pointer,
/// and for verifying that the input method passed along
/// matches the one in the `imservice`.
///
/// The lifetime of the returned value is 'static,
/// due to the fact that the lifetime of a raw pointer is undefined.
/// Care must be take
/// not to exceed the lifetime of the pointer with the reference,
/// especially not to store it.
fn check_imservice(imservice: *mut IMService, im: *const InputMethod)
-> Result<&'static mut IMService, &'static str>
{
if imservice.is_null() {
return Err("Null imservice pointer");
}
let imservice: &mut IMService = unsafe { &mut *imservice };
if im == imservice.im {
Ok(imservice)
} else {
Err("Imservice doesn't contain the input method")
}
}
}
bitflags!{
/// Map to `text_input_unstable_v3.content_hint` values
pub struct ContentHint: u32 {
const NONE = 0x0;
const COMPLETION = 0x1;
const SPELLCHECK = 0x2;
const AUTO_CAPITALIZATION = 0x4;
const LOWERCASE = 0x8;
const UPPERCASE = 0x10;
const TITLECASE = 0x20;
const HIDDEN_TEXT = 0x40;
const SENSITIVE_DATA = 0x80;
const LATIN = 0x100;
const MULTILINE = 0x200;
}
}
/// Map to `text_input_unstable_v3.content_purpose` values
///
/// ```
/// assert_eq!(ContentPurpose::Alpha as u32, 0);
/// ```
#[derive(Debug, Clone)]
pub enum ContentPurpose {
Normal = 0,
Alpha = 1,
Digits = 2,
Number = 3,
Phone = 4,
Url = 5,
Email = 6,
Name = 7,
Password = 8,
Pin = 9,
Date = 10,
Time = 11,
Datetime = 12,
Terminal = 13,
}
impl TryFrom<u32> for ContentPurpose {
// There's only one way to fail: number not in protocol,
// so no special error type is needed
type Error = ();
fn try_from(num: u32) -> Result<Self, Self::Error> {
use self::ContentPurpose::*;
match num {
0 => Ok(Normal),
1 => Ok(Alpha),
2 => Ok(Digits),
3 => Ok(Number),
4 => Ok(Phone),
5 => Ok(Url),
6 => Ok(Email),
7 => Ok(Name),
8 => Ok(Password),
9 => Ok(Pin),
10 => Ok(Date),
11 => Ok(Time),
12 => Ok(Datetime),
13 => Ok(Terminal),
_ => Err(()),
}
}
}
/// Map to `text_input_unstable_v3.change_cause` values
#[derive(Debug, Clone)]
pub enum ChangeCause {
InputMethod = 0,
Other = 1,
}
impl TryFrom<u32> for ChangeCause {
// There's only one way to fail: number not in protocol,
// so no special error type is needed
type Error = ();
fn try_from(num: u32) -> Result<Self, Self::Error> {
match num {
0 => Ok(ChangeCause::InputMethod),
1 => Ok(ChangeCause::Other),
_ => Err(())
}
}
}
/// Describes the desired state of the input method as requested by the server
#[derive(Default, Clone)]
#[derive(Clone)]
struct IMProtocolState {
surrounding_text: CString,
surrounding_cursor: u32,
content_purpose: ContentPurpose,
content_hint: ContentHint,
text_change_cause: ChangeCause,
active: bool,
}
impl Default for IMProtocolState {
fn default() -> IMProtocolState {
IMProtocolState {
surrounding_text: CString::default(),
surrounding_cursor: 0, // TODO: mark that there's no cursor
content_hint: ContentHint::NONE,
content_purpose: ContentPurpose::Normal,
text_change_cause: ChangeCause::InputMethod,
active: false,
}
}
}
pub struct IMService {
/// Owned reference (still created and destroyed in C)
im: *const c::InputMethod,
pub im: *const c::InputMethod,
/// Unowned reference. Be careful, it's shared with C at large
ui_manager: *const c::UIManager,

4
src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
#[macro_use]
mod bitflags;
mod imservice;

View File

@ -40,7 +40,6 @@ sources = [
enums,
keysym_entries,
marshalers,
'../eekboard/keymap.c',
'../eekboard/key-emitter.c',
'../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-context.c',
@ -70,10 +69,19 @@ deps = [
# Replacement for eekboard-server
rslib = static_library(
'rslib',
sources: ['imservice.rs'],
sources: ['lib.rs'],
rust_crate_type: 'staticlib'
)
rstests = executable(
'rstests',
sources: ['lib.rs'],
rust_args: ['--test'],
install: false
)
test('rstests', rstests)
libsqueekboard = static_library('libsqueekboard',
sources,
link_with: rslib,

View File

@ -174,13 +174,6 @@ set_geometry (ServerContextService *context)
gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE);
} else {
gtk_window_resize (GTK_WINDOW(context->window),
bounds.width,
bounds.height);
gtk_window_move (GTK_WINDOW(context->window),
MAX(rect.width - 20 - bounds.width, 0),
MAX(rect.height - 40 - bounds.height, 0));
}
}

View File

@ -19,6 +19,8 @@
*/
#include "eek/eek.h"
#include <gtk/gtk.h>
static void
test_create (void)
{
@ -39,7 +41,7 @@ test_create (void)
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/eek-simple-test/create", test_create);
return g_test_run ();
}

View File

@ -24,6 +24,7 @@
#include "config.h"
#include "eek/eek.h"
#include "eek/eek-xml-layout.h"
static void
test_output_parse (void)
@ -46,8 +47,7 @@ test_output_parse (void)
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
gtk_init (&argc, &argv); /* for gdk_x11_display_get_xdisplay() */
gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);

View File

@ -21,7 +21,8 @@ test_link_args = [
tests = [
'eek-simple-test',
'eek-xml-test'
'eek-xml-test',
'test-keymap-generation'
]
foreach name : tests

View File

@ -1,181 +0,0 @@
<?xml version="1.0"?>
<keyboard version="0.90">
<bounds>0.000000,0.000000,124.000000,149.000000</bounds>
<section name="Keypad">
<bounds>10.000000,10.000000,104.000000,129.000000</bounds>
<angle>0</angle>
<row>
<columns>4</columns>
<orientation>1</orientation>
</row>
<row>
<columns>4</columns>
<orientation>1</orientation>
</row>
<row>
<columns>3</columns>
<orientation>1</orientation>
</row>
<row>
<columns>4</columns>
<orientation>1</orientation>
</row>
<row>
<columns>2</columns>
<orientation>1</orientation>
</row>
<key id="keycode91" name="KPDL" column="1" row="4">
<bounds>54.000000,104.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65439">KP_Delete</keysym>
<keysym keyval="65454">KP_Decimal</keysym>
</symbols>
</key>
<key id="keycode90" name="KP0" column="0" row="4">
<bounds>2.000000,104.000000,50.000000,24.000000</bounds>
<outline-ref>outline1</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65438">KP_Insert</keysym>
<keysym keyval="65456">KP_0</keysym>
</symbols>
</key>
<key id="keycode108" name="KPEN" column="3" row="3">
<bounds>80.000000,78.000000,24.000000,50.000000</bounds>
<outline-ref>outline2</outline-ref>
<symbols groups="1" levels="1">
<keysym keyval="65421">KP_Enter</keysym>
</symbols>
</key>
<key id="keycode89" name="KP3" column="2" row="3">
<bounds>54.000000,78.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65435">KP_Next</keysym>
<keysym keyval="65459">KP_3</keysym>
</symbols>
</key>
<key id="keycode88" name="KP2" column="1" row="3">
<bounds>28.000000,78.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65433">KP_Down</keysym>
<keysym keyval="65458">KP_2</keysym>
</symbols>
</key>
<key id="keycode87" name="KP1" column="0" row="3">
<bounds>2.000000,78.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65436">KP_End</keysym>
<keysym keyval="65457">KP_1</keysym>
</symbols>
</key>
<key id="keycode85" name="KP6" column="2" row="2">
<bounds>54.000000,53.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65432">KP_Right</keysym>
<keysym keyval="65462">KP_6</keysym>
</symbols>
</key>
<key id="keycode84" name="KP5" column="1" row="2">
<bounds>28.000000,53.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65437">KP_Begin</keysym>
<keysym keyval="65461">KP_5</keysym>
</symbols>
</key>
<key id="keycode83" name="KP4" column="0" row="2">
<bounds>2.000000,53.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65430">KP_Left</keysym>
<keysym keyval="65460">KP_4</keysym>
</symbols>
</key>
<key id="keycode86" name="KPAD" column="3" row="1">
<bounds>80.000000,27.000000,24.000000,50.000000</bounds>
<outline-ref>outline2</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65451">KP_Add</keysym>
<keysym keyval="269024802"></keysym>
</symbols>
</key>
<key id="keycode81" name="KP9" column="2" row="1">
<bounds>54.000000,27.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65434">KP_Prior</keysym>
<keysym keyval="65465">KP_9</keysym>
</symbols>
</key>
<key id="keycode80" name="KP8" column="1" row="1">
<bounds>28.000000,27.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65431">KP_Up</keysym>
<keysym keyval="65464">KP_8</keysym>
</symbols>
</key>
<key id="keycode79" name="KP7" column="0" row="1">
<bounds>2.000000,27.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65429">KP_Home</keysym>
<keysym keyval="65463">KP_7</keysym>
</symbols>
</key>
<key id="keycode82" name="KPSU" column="3" row="0">
<bounds>80.000000,1.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65453">KP_Subtract</keysym>
<keysym keyval="269024803"></keysym>
</symbols>
</key>
<key id="keycode63" name="KPMU" column="2" row="0">
<bounds>54.000000,1.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65450">KP_Multiply</keysym>
<keysym keyval="269024801"></keysym>
</symbols>
</key>
<key id="keycode112" name="KPDV" column="1" row="0">
<bounds>28.000000,1.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65455">KP_Divide</keysym>
<keysym keyval="269024800"></keysym>
</symbols>
</key>
<key id="keycode77" name="NMLK" column="0" row="0">
<bounds>2.000000,1.000000,24.000000,24.000000</bounds>
<outline-ref>outline0</outline-ref>
<symbols groups="1" levels="2">
<keysym keyval="65407">Num_Lock</keysym>
<keysym keyval="65273">Pointer_EnableKeys</keysym>
</symbols>
</key>
</section>
<outline id="outline0">
<point>0.000000,0.000000</point>
<point>24.000000,0.000000</point>
<point>24.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline1">
<point>0.000000,0.000000</point>
<point>50.000000,0.000000</point>
<point>50.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline2">
<point>0.000000,0.000000</point>
<point>24.000000,0.000000</point>
<point>24.000000,50.000000</point>
<point>0.000000,50.000000</point>
</outline>
</keyboard>

View File

@ -0,0 +1,72 @@
/*
* 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
*/
/* For gdk_x11_display_get_xdisplay(). See main(). */
#include <gtk/gtk.h>
#include <xkbcommon/xkbcommon.h>
#include "config.h"
#include "eek/eek.h"
#include "eek/eek-xml-layout.h"
static void
test_check_xkb (void)
{
EekLayout *layout;
EekKeyboard *keyboard;
GError *error;
error = NULL;
layout = eek_xml_layout_new ("us", &error);
g_assert_no_error (error);
keyboard = eek_keyboard_new (NULL, layout, 640, 480);
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!context) {
g_error("No context created");
}
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
free(keymap_str);
xkb_context_unref(context);
if (!keymap) {
g_error("Bad keymap");
}
g_object_unref (layout);
g_object_unref (keyboard);
}
int
main (int argc, char **argv)
{
gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb);
return g_test_run ();
}