Compare commits

..

6 Commits

Author SHA1 Message Date
a175226ce3 Keep the build directory as an artifact 2019-07-22 20:35:18 +02:00
7c53d75718 Fix test step dependency 2019-07-22 20:12:26 +02:00
fa32a03fbf Update CI configuration to enable tests 2019-07-22 19:31:43 +02:00
53a6876830 Remove unused/unnecessary parts 2019-07-22 16:40:34 +02:00
629b15840a Add missing build file 2019-07-22 15:29:26 +02:00
ff3a7b02b6 Enable tests, fixing the existing ones to use the current API
This also involved building a static library for the application for
tests to link to. The main application executable also links to it.
2019-07-22 15:22:17 +02:00
76 changed files with 7223 additions and 3123 deletions

View File

@ -28,4 +28,6 @@ test:
dependencies:
- build_meson
script:
- export LC_ALL=C.UTF-8
- ninja -C _build test

View File

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

View File

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

View File

@ -1,122 +1,126 @@
<?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 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" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
<key name="AC11" oref="outline2" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
<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" />
</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"/>
<point x="0.000000" y="52"/>
<point x="32" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52"/>
<point x="0.000000" y="52"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52"/>
<point x="0.000000" y="52"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52"/>
<point x="0.000000" y="52"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52"/>
<point x="0.000000" y="52"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="150.5853" y="0.000000"/>
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
<point x="150.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

@ -1,105 +0,0 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<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 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">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="120.5853" y="0.000000"/>
<point x="120.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

@ -3,30 +3,37 @@
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline4" />
<key name="AD02" oref="outline4" />
<key name="AD03" oref="outline4" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline4" />
<key name="AC02" oref="outline4" />
<key name="AC03" oref="outline4" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AB01" oref="outline4" />
<key name="AB02" oref="outline4" />
<key name="AB03" oref="outline4" />
<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" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="BKSP" oref="altline" />
<key name="AB04" oref="outline4" />
<key name="RTRN" oref="altline" />
<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" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">

View File

@ -1,105 +0,0 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<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 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">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="120.5853" y="0.000000"/>
<point x="120.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

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

View File

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

View File

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

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

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

View File

@ -1,39 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<key name="AD01">
<symbol label="1">1</symbol>
</key>
<key name="AD02">
<symbol label="2">2</symbol>
</key>
<key name="AD03">
<symbol label="3">3</symbol>
</key>
<key name="AC01">
<symbol label="4">4</symbol>
</key>
<key name="AC02">
<symbol label="5">5</symbol>
</key>
<key name="AC03">
<symbol label="6">6</symbol>
</key>
<key name="AB01">
<symbol label="7">7</symbol>
</key>
<key name="AB02">
<symbol label="8">8</symbol>
</key>
<key name="AB03">
<symbol label="9">9</symbol>
</key>
<key name="AB04">
<symbol label="0">0</symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -1,60 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<key name="AD01">
<symbol label="1">1</symbol>
</key>
<key name="AD02">
<symbol label="2">2</symbol>
</key>
<key name="AD03">
<symbol label="3">3</symbol>
</key>
<key name="AD04">
<symbol label=".">period</symbol>
</key>
<key name="AD05">
<symbol label=",">comma</symbol>
</key>
<key name="AC01">
<symbol label="4">4</symbol>
</key>
<key name="AC02">
<symbol label="5">5</symbol>
</key>
<key name="AC03">
<symbol label="6">6</symbol>
</key>
<key name="AC04">
<symbol label="/">slash</symbol>
</key>
<key name="AC05">
<symbol label="*">asterisk</symbol>
</key>
<key name="AB01">
<symbol label="7">7</symbol>
</key>
<key name="AB02">
<symbol label="8">8</symbol>
</key>
<key name="AB03">
<symbol label="9">9</symbol>
</key>
<key name="AB04">
<symbol label="+">plus</symbol>
</key>
<key name="AB05">
<symbol label="-">minus</symbol>
</key>
<key name="AB06">
<symbol label="0">0</symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -1,231 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<key name="AD01">
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
<symbol label=""></symbol>
<symbol label="1">1</symbol>
</key>
<key name="AD02">
<symbol label="w">w</symbol>
<symbol label="W">W</symbol>
<symbol label=""></symbol>
<symbol label="2">2</symbol>
</key>
<key name="AD03">
<symbol label="e">e</symbol>
<symbol label="E">E</symbol>
<symbol label=""></symbol>
<symbol label="3">3</symbol>
</key>
<key name="AD04">
<symbol label="r">r</symbol>
<symbol label="R">R</symbol>
<symbol label=""></symbol>
<symbol label="4">4</symbol>
</key>
<key name="AD05">
<symbol label="t">t</symbol>
<symbol label="T">T</symbol>
<symbol label=""></symbol>
<symbol label="5">5</symbol>
</key>
<key name="AD06">
<symbol label="y">y</symbol>
<symbol label="Y">Y</symbol>
<symbol label=""></symbol>
<symbol label="6">6</symbol>
</key>
<key name="AD07">
<symbol label="u">u</symbol>
<symbol label="U">U</symbol>
<symbol label=""></symbol>
<symbol label="7">7</symbol>
</key>
<key name="AD08">
<symbol label="i">i</symbol>
<symbol label="I">I</symbol>
<symbol label=""></symbol>
<symbol label="8">8</symbol>
</key>
<key name="AD09">
<symbol label="o">o</symbol>
<symbol label="O">O</symbol>
<symbol label=""></symbol>
<symbol label="9">9</symbol>
</key>
<key name="AD10">
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label=""></symbol>
<symbol label="0">0</symbol>
</key>
<key name="AC01">
<symbol label="a">a</symbol>
<symbol label="A">A</symbol>
<symbol label="@">at</symbol>
<symbol label="~">asciitilde</symbol>
</key>
<key name="AC02">
<symbol label="s">s</symbol>
<symbol label="S">S</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="&#174;">U00AE</symbol>
</key>
<key name="AC03">
<symbol label="d">d</symbol>
<symbol label="D">D</symbol>
<symbol label="$">dollar</symbol>
<symbol label="&#163;">U00A3</symbol>
</key>
<key name="AC04">
<symbol label="f">f</symbol>
<symbol label="F">F</symbol>
<symbol label="%">percent</symbol>
<symbol label="&#8364;">EuroSign</symbol>
</key>
<key name="AC05">
<symbol label="g">g</symbol>
<symbol label="G">G</symbol>
<symbol label="&amp;">ampersand</symbol>
<symbol label="&#165;">U00A5</symbol>
</key>
<key name="AC06">
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="^">asciicircum</symbol>
</key>
<key name="AC07">
<symbol label="j">j</symbol>
<symbol label="J">J</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="+">plus</symbol>
<symbol label="=">equal</symbol>
</key>
<key name="AC09">
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
</key>
<key name="AC10">
<symbol label=""></symbol>
<symbol label=""></symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" label="123">Shift_L</keysym>
<keysym keyval="65505" label="URL">Shift_L</keysym>
</key>
<key name="AB01">
<symbol label="z">z</symbol>
<symbol label="Z">Z</symbol>
<symbol label=",">comma</symbol>
<symbol label="\">backslash</symbol>
</key>
<key name="AB02">
<symbol label="x">x</symbol>
<symbol label="X">X</symbol>
<symbol label="&quot;">quotedbl</symbol>
<symbol label="/">slash</symbol>
</key>
<key name="AB03">
<symbol label="c">c</symbol>
<symbol label="C">C</symbol>
<symbol label="'">quoteright</symbol>
<symbol label="&lt;">less</symbol>
</key>
<key name="AB04">
<symbol label="v">v</symbol>
<symbol label="V">V</symbol>
<symbol label=":">colon</symbol>
<symbol label="&gt;">greater</symbol>
</key>
<key name="AB05">
<symbol label="b">b</symbol>
<symbol label="B">B</symbol>
<symbol label=";">semicolon</symbol>
<symbol label="=">equal</symbol>
</key>
<key name="AB06">
<symbol label="n">n</symbol>
<symbol label="N">N</symbol>
<symbol label="!">exclam</symbol>
<symbol label="[">bracketleft</symbol>
</key>
<key name="AB07">
<symbol label="m">m</symbol>
<symbol label="M">M</symbol>
<symbol label="?">question</symbol>
<symbol label="]">bracketright</symbol>
</key>
<key name="AB08">
<symbol label=".">period</symbol>
</key>
<key name="ABC123">
<symbol label="URL">show-url</symbol>
<symbol label="URL">show-url</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="ABC">show-letters</symbol>
</key>
<key name="I149">
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
<!-- Extra URL mode buttons -->
<key name="AE01">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label="https">https</text>
<symbol label=""></symbol>
</key>
<key name="AE02">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label="://">://</text>
<symbol label=""></symbol>
</key>
<key name="AE03">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label="www.">www.</text>
<symbol label=""></symbol>
</key>
<key name="AE04">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label=".com">.com</text>
<symbol label=""></symbol>
</key>
<key name="AE05">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label=".org">.org</text>
<symbol label=""></symbol>
</key>
<key name="AE06">
<symbol label=""></symbol>
<symbol label=""></symbol>
<text label=".net">.net</text>
<symbol label=""></symbol>
</key>
</symbols>

View File

@ -115,8 +115,6 @@
<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

@ -2,19 +2,13 @@
<gresources>
<gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</file>
<!-- Keyboard layouts -->
<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/digits.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/number-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/phone-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/url.xml</file>
<!-- Keyboard definitions -->
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/numbers-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
<!-- Natural language keyboards -->
<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>
@ -44,13 +38,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>
<!-- Special purpose keyboards -->
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/digits.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/number.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/phone.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/url.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/numbers.xml</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>
<file>icons/keyboard-mode-symbolic.svg</file>

5
debian/control vendored
View File

@ -11,10 +11,7 @@ Build-Depends:
libcroco3-dev,
libwayland-dev (>= 1.16),
rustc,
wayland-protocols (>= 1.14),
# for running the tests
xvfb,
xauth,
wayland-protocols (>= 1.14)
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard

View File

@ -50,7 +50,7 @@ static void
eek_container_real_add_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = (EekContainerPrivate*)eek_container_get_instance_private (self);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
g_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref (child);

View File

@ -100,7 +100,6 @@ 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

@ -55,8 +55,7 @@ typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
EekKeyboard *keyboard;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
EekTheme *theme;
GdkEventSequence *sequence; // unowned reference
} EekGtkKeyboardPrivate;
@ -67,6 +66,16 @@ static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self);
static void on_key_released (EekKey *key,
EekGtkKeyboard *self);
static void on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
static void render_pressed_key (GtkWidget *widget,
EekKey *key);
static void render_locked_key (GtkWidget *widget,
@ -100,9 +109,12 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) {
PangoContext *pcontext = gtk_widget_get_pango_context (self);
PangoContext *pcontext;
priv->renderer = eek_renderer_new (priv->keyboard, pcontext, priv->scontext);
pcontext = gtk_widget_get_pango_context (self);
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
if (priv->theme)
eek_renderer_set_theme (priv->renderer, priv->theme);
eek_renderer_set_allocation_size (priv->renderer,
allocation.width,
@ -147,11 +159,9 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
}
static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time)
{
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
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);
@ -162,17 +172,16 @@ static void drag(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);
GList *list, *head;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
if (key) {
GList *list, *head;
gboolean found = FALSE;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
if (head->data == key) {
if (head->data == key)
found = TRUE;
} else {
else {
eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
on_key_released(key, self);
}
@ -183,12 +192,6 @@ static void drag(EekGtkKeyboard *self,
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
}
} else {
for (head = list; head; head = g_list_next (head)) {
eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
on_key_released(key, self);
}
g_list_free (list);
}
}
@ -329,10 +332,18 @@ eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
return;
if (priv->keyboard) {
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
g_object_unref (priv->keyboard);
}
priv->keyboard = g_object_ref (keyboard);
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
@ -368,6 +379,7 @@ eek_gtk_keyboard_dispose (GObject *object)
if (priv->keyboard) {
GList *list, *head;
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
@ -379,6 +391,11 @@ eek_gtk_keyboard_dispose (GObject *object)
priv->keyboard = NULL;
}
if (priv->theme) {
g_object_unref (priv->theme);
priv->theme = NULL;
}
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
}
@ -419,20 +436,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
static void
eek_gtk_keyboard_init (EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* Create a default CSS provider and load a style sheet */
priv->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (priv->css_provider,
"/sm/puri/squeekboard/style.css");
/* Apply the style to the widget */
priv->scontext = gtk_widget_get_style_context (GTK_WIDGET(self));
gtk_style_context_add_class (priv->scontext, "keyboard");
gtk_style_context_add_provider (priv->scontext,
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_style_context_set_state (priv->scontext, GTK_STATE_FLAG_NORMAL);
/* void */
}
/**
@ -477,15 +481,25 @@ render_pressed_key (GtkWidget *widget,
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
cairo_save (cr);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
/*
cairo_save (cr);
cairo_translate (cr, large_bounds.x, large_bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_restore (cr);
*/
gdk_window_end_draw_frame (window, context);
@ -498,12 +512,16 @@ render_locked_key (GtkWidget *widget,
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
gdk_window_end_draw_frame (window, context);
@ -517,12 +535,16 @@ render_released_key (GtkWidget *widget,
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
eek_renderer_render_keyboard (priv->renderer, cr);
gdk_window_end_draw_frame (window, context);
@ -573,3 +595,57 @@ on_key_released (EekKey *key,
NULL);
#endif
}
static void
on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_locked_key (widget, key);
gtk_widget_queue_draw (widget);
}
static void
on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_key (widget, key);
gtk_widget_queue_draw (GTK_WIDGET(widget));
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
GtkWidget *widget = user_data;
gtk_widget_queue_draw (widget);
}
void
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
g_return_if_fail (EEK_IS_THEME(theme));
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard);
priv->theme = g_object_ref (theme);
}

View File

@ -46,6 +46,8 @@ struct _EekGtkKeyboardClass
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */

View File

@ -38,6 +38,8 @@ enum {
PROP_0,
PROP_KEYCODE,
PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OREF,
PROP_LAST
};
@ -54,6 +56,8 @@ typedef struct _EekKeyPrivate
{
guint keycode;
EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
gulong oref; // UI outline reference
gboolean is_pressed;
gboolean is_locked;
@ -101,6 +105,8 @@ eek_key_set_property (GObject *object,
GParamSpec *pspec)
{
EekSymbolMatrix *matrix;
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
@ -109,6 +115,14 @@ eek_key_set_property (GObject *object,
matrix = g_value_get_boxed (value);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), g_value_get_int (value), row);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break;
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
@ -124,6 +138,8 @@ eek_key_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
@ -132,6 +148,14 @@ eek_key_get_property (GObject *object,
g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object)));
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, column);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row);
break;
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
@ -179,6 +203,30 @@ eek_key_class_init (EekKeyClass *klass)
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
/**
* EekKey:column:
*
* The column index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("column",
"Column",
"Column index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_COLUMN, pspec);
/**
* EekKey:row:
*
* The row index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("row",
"Row",
"Row index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/**
* EekKey:oref:
*
@ -430,6 +478,59 @@ eek_key_get_symbol_at_index (EekKey *key,
level];
}
/**
* eek_key_set_index:
* @key: an #EekKey
* @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection
*
* Set the location of @key in #EekSection with @column and @row.
*/
void
eek_key_set_index (EekKey *key,
gint column,
gint row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (0 <= column);
g_return_if_fail (0 <= row);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->column != column) {
priv->column = column;
g_object_notify (G_OBJECT(key), "column");
}
if (priv->row != row) {
priv->row = row;
g_object_notify (G_OBJECT(key), "row");
}
}
/**
* eek_key_get_index:
* @key: an #EekKey
* @column: (allow-none): pointer where the column index of @key in #EekSection will be stored
* @row: (allow-none): pointer where the row index of @key in #EekSection will be stored
*
* Get the location of @key in #EekSection.
*/
void
eek_key_get_index (EekKey *key,
gint *column,
gint *row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (column != NULL || row != NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (column != NULL)
*column = priv->column;
if (row != NULL)
*row = priv->row;
}
/**
* eek_key_set_oref:
* @key: an #EekKey

View File

@ -73,6 +73,13 @@ EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
gint fallback_group,
gint fallback_level);
void eek_key_set_index (EekKey *key,
gint column,
gint row);
void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_oref (EekKey *key,
guint oref);
guint eek_key_get_oref (EekKey *key);

View File

@ -28,7 +28,6 @@
*/
#include "config.h"
#include <glib/gprintf.h>
#include "eek-keyboard.h"
#include "eek-marshalers.h"
@ -37,7 +36,6 @@
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
enum {
PROP_0,
@ -74,11 +72,7 @@ struct _EekKeyboardPrivate
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
/* Map key names to key objects */
GHashTable *names;
/* Map characters to symbols and levels */
GHashTable *character_map;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
@ -407,7 +401,6 @@ eek_keyboard_finalize (GObject *object)
(GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->names);
g_hash_table_destroy (priv->character_map);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
@ -536,8 +529,6 @@ eek_keyboard_init (EekKeyboard *self)
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
self->priv->character_map = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, g_free);
eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
self->scale = 1.0;
}
@ -805,117 +796,3 @@ 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 < 4); ++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] = {NULL, NULL};
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);
}
/* 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;
}
void
eek_keyboard_register_symbol (EekKeyboard *keyboard,
EekSymbol *symbol,
EekKey *key,
guint level)
{
const gchar *label = eek_symbol_get_label(symbol);
if (label) {
EekKeyPress *key_press = g_malloc0 (sizeof(EekKeyPress));
key_press->key = key;
key_press->level = level;
g_hash_table_insert (keyboard->priv->character_map,
(gpointer)label,
key_press);
}
}
EekKeyPress *
eek_keyboard_get_key_press (EekKeyboard *keyboard,
gchar *ch)
{
return g_hash_table_lookup (keyboard->priv->character_map, ch);
}

View File

@ -124,11 +124,6 @@ struct _EekModifierKey {
};
typedef struct _EekModifierKey EekModifierKey;
struct _EekKeyPress {
EekKey *key;
guint level;
};
typedef struct _EekKeyPress EekKeyPress;
EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
@ -200,18 +195,5 @@ 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);
void eek_keyboard_register_symbol
(EekKeyboard *keyboard,
EekSymbol *symbol,
EekKey *key,
guint level);
EekKeyPress * eek_keyboard_get_key_press
(EekKeyboard *keyboard,
gchar *ch);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -48,9 +48,15 @@
#define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee
typedef struct _EekKeysymPrivate
{
guint xkeysym;
} EekKeysymPrivate;
struct _EekKeysymEntry {
guint xkeysym;
const gchar *name;
EekSymbolCategory category;
};
typedef struct _EekKeysymEntry EekKeysymEntry;
@ -59,6 +65,54 @@ typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h"
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekKeysym)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
eek_keysym_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->xkeysym);
}
static gsize
eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->xkeysym);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keysym_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keysym_real_serialize;
iface->deserialize = eek_keysym_real_deserialize;
}
static gchar *
unichar_to_utf8 (gunichar uc)
@ -143,6 +197,18 @@ get_modifier_mask (guint xkeysym)
return 0;
}
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
/* void */
}
static void
eek_keysym_init (EekKeysym *self)
{
/* void */
}
/**
* eek_keysym_new_with_modifier:
* @xkeysym: an X keysym value
@ -151,12 +217,16 @@ get_modifier_mask (guint xkeysym)
* Create an #EekKeysym with given X keysym value @xkeysym and
* modifier @modifier_mask.
*/
EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
EekModifierType modifier_mask)
EekKeysym *
eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask)
{
EekKeysym *keysym;
EekKeysymPrivate *priv;
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
EekSymbolCategory category;
gunichar uc;
special_entry =
@ -176,17 +246,23 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
}
/* name and category */
name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else {
name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/* label */
@ -199,10 +275,12 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
else
label = g_strdup (name);
EekSymbol *keysym = eek_symbol_new(name);
eek_symbol_set_label(keysym, label);
eek_symbol_set_modifier_mask(keysym, modifier_mask);
keysym = g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name);
g_free (label);
@ -211,7 +289,8 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
g_slice_free (EekKeysymEntry, unichar_entry);
}
keysym->xkeysym = xkeysym;
priv = eek_keysym_get_instance_private (keysym);
priv->xkeysym = xkeysym;
return keysym;
}
@ -222,7 +301,7 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
*
* Create an #EekKeysym with given X keysym value @xkeysym.
*/
EekSymbol*
EekKeysym *
eek_keysym_new (guint xkeysym)
{
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym));
@ -234,16 +313,22 @@ eek_keysym_new (guint xkeysym)
*
* Create an #EekKeysym with an X keysym value looked up by @name.
*/
EekSymbol*
EekKeysym *
eek_keysym_new_from_name (const gchar *name)
{
for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
gint i;
for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
EekSymbol *ret = eek_symbol_new(name);
eek_symbol_set_label(ret, name);
return ret;
// g_warning ("can't find keysym entry for %s", name);
return g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", name,
"category", EEK_SYMBOL_CATEGORY_UNKNOWN,
"modifier-mask", 0,
NULL);
}
/**
@ -253,10 +338,11 @@ eek_keysym_new_from_name (const gchar *name)
* Get an X keysym value associated with @keysym
*/
guint
eek_keysym_get_xkeysym (EekSymbol *keysym)
eek_keysym_get_xkeysym (EekKeysym *keysym)
{
if (keysym->xkeysym == 0) {
g_warning("Symbol %s was expected to have a valid keysym", keysym->name);
}
return keysym->xkeysym;
EekKeysymPrivate *priv;
g_assert (EEK_IS_KEYSYM(keysym));
priv = eek_keysym_get_instance_private (keysym);
return priv->xkeysym;
}

View File

@ -37,11 +37,20 @@ G_BEGIN_DECLS
*/
#define EEK_INVALID_KEYSYM (0)
EekSymbol *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekSymbol *keysym);
#define EEK_TYPE_KEYSYM (eek_keysym_get_type())
G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
EekSymbol *eek_keysym_new_from_name (const gchar *name);
EekSymbol *eek_keysym_new_with_modifier (guint xkeysym,
struct _EekKeysymClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_keysym_get_type (void) G_GNUC_CONST;
EekKeysym *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekKeysym *keysym);
EekKeysym *eek_keysym_new_from_name (const gchar *name);
EekKeysym *eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask);
G_END_DECLS

View File

@ -129,8 +129,60 @@ 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,6 +57,8 @@ 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

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,8 @@
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
#include "eek-theme.h"
#include "eek-theme-context.h"
G_BEGIN_DECLS
@ -35,6 +37,10 @@ struct _EekRendererClass
{
GObjectClass parent_class;
void (* render_key_label) (EekRenderer *self,
PangoLayout *layout,
EekKey *key);
void (* render_key_outline) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
@ -62,8 +68,7 @@ struct _EekRendererClass
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
GtkStyleContext *scontext);
PangoContext *pcontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer,
gdouble width,
@ -115,8 +120,18 @@ void eek_renderer_set_default_background_color
const EekColor *color);
void eek_renderer_get_foreground_color
(EekRenderer *renderer,
GtkStyleContext *context,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_color
(EekRenderer *renderer,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_gradient
(EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
EekKey *eek_renderer_find_key_by_position
@ -130,5 +145,8 @@ void eek_renderer_apply_transformation_for_key
gdouble scale,
gboolean rotate);
void eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_RENDERER_H */

View File

@ -61,7 +61,7 @@ typedef struct _EekRow EekRow;
typedef struct _EekSectionPrivate
{
gint angle;
EekRow row;
GSList *rows;
EekModifierType modifiers;
} EekSectionPrivate;
@ -70,7 +70,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
static gint
eek_section_real_get_n_rows (EekSection *self)
{
return 1;
EekSectionPrivate *priv = eek_section_get_instance_private (self);
return g_slist_length (priv->rows);
}
static void
@ -78,14 +80,13 @@ eek_section_real_add_row (EekSection *self,
gint num_columns,
EekOrientation orientation)
{
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
priv->row.num_columns = num_columns;
priv->row.orientation = orientation;
/*
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slice_new (EekRow);
row->num_columns = num_columns;
row->orientation = orientation;
priv->rows = g_slist_append (priv->rows, row);*/
priv->rows = g_slist_append (priv->rows, row);
}
static void
@ -94,14 +95,15 @@ eek_section_real_get_row (EekSection *self,
gint *num_columns,
EekOrientation *orientation)
{
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
EekRow *row = &priv->row;
if (num_columns) {
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slist_nth_data (priv->rows, index);
g_return_if_fail (row);
if (num_columns)
*num_columns = row->num_columns;
}
if (orientation) {
if (orientation)
*orientation = row->orientation;
}
}
static void
@ -121,17 +123,29 @@ on_unlocked (EekKey *key,
static EekKey *
eek_section_real_create_key (EekSection *self,
const gchar *name,
gint keycode)
gint keycode,
gint column_index,
gint row_index)
{
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
EekKey *key;
gint num_rows;
EekRow *row;
EekRow *row = &priv->row;
row->num_columns++;
num_rows = eek_section_get_n_rows (self);
g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY,
"name", name,
"keycode", keycode,
NULL);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
row = g_slist_nth_data (priv->rows, row_index);
if (row->num_columns < column_index + 1)
row->num_columns = column_index + 1;
key = g_object_new (EEK_TYPE_KEY,
"name", name,
"keycode", keycode,
"column", column_index,
"row", row_index,
NULL);
g_return_val_if_fail (key, NULL);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
@ -211,7 +225,12 @@ static void
eek_section_finalize (GObject *object)
{
EekSection *self = EEK_SECTION (object);
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
GSList *head;
for (head = priv->rows; head; head = g_slist_next (head))
g_slice_free (EekRow, head->data);
g_slist_free (priv->rows);
G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
}
@ -456,12 +475,16 @@ eek_section_get_row (EekSection *section,
EekKey *
eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode)
gint keycode,
gint column,
gint row)
{
g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section,
name,
keycode);
keycode,
column,
row);
}
const double keyspacing = 4.0;
@ -512,8 +535,7 @@ keycounter (EekElement *element, gpointer user_data)
{
EekKey *key = EEK_KEY(element);
/* Skip keys without labels for the current level. This causes those
keys to be hidden in the visible layout. */
/* Skip keys without labels for the current level. */
if (!eek_key_has_label(key))
return;

View File

@ -63,7 +63,9 @@ struct _EekSectionClass
EekKey *(* create_key) (EekSection *self,
const gchar *name,
gint keycode);
gint keycode,
gint row,
gint column);
/* signals */
void (* key_pressed) (EekSection *self,
@ -99,7 +101,9 @@ void eek_section_get_row (EekSection *section,
EekKey *eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode);
gint keycode,
gint column,
gint row);
EekKey *eek_section_find_key_by_keycode (EekSection *section,
guint keycode);

View File

@ -36,8 +36,10 @@ eek_serializable_get_type (void)
{
static GType iface_type = 0;
if (iface_type == 0) {
static GTypeInfo info = {
.class_size = sizeof (EekSerializableIface)
static const GTypeInfo info = {
sizeof (EekSerializableIface),
NULL,
NULL,
};
iface_type = g_type_register_static (G_TYPE_INTERFACE,
"EekSerializable",

View File

@ -36,19 +36,24 @@ EekSymbolMatrix *
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
{
EekSymbolMatrix *retval;
guint num_symbols = matrix->num_groups * matrix->num_levels;
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
retval = g_slice_dup (EekSymbolMatrix, matrix);
retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
matrix->data);
// FIXME: do a deep copy over the data in EekSymbol
for (i = 0; i < num_symbols; i++)
if (retval->data[i])
g_object_ref (retval->data[i]);
return retval;
}
void
eek_symbol_matrix_free (EekSymbolMatrix *matrix)
{
guint num_symbols = matrix->num_groups * matrix->num_levels;
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
for (i = 0; i < num_symbols; i++)
if (matrix->data[i])
g_object_unref (matrix->data[i]);
g_slice_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
g_slice_free (EekSymbolMatrix, matrix);
}
@ -74,6 +79,7 @@ eek_symbol_matrix_set_symbol (EekSymbolMatrix *matrix,
{
g_return_if_fail (group >= 0 && group < matrix->num_groups);
g_return_if_fail (level >= 0 && level < matrix->num_levels);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
}

View File

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

View File

@ -58,27 +58,20 @@ typedef enum {
EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
} EekSymbolCategory;
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
typedef struct _EekSymbol
{
/// Canonical name of the symbol
gchar *name;
/// Text used to display the symbol
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
/// Icon name used to render the symbol
gchar *icon_name;
/// Tooltip text
gchar *tooltip;
/**
* EekSymbolClass:
*/
struct _EekSymbolClass {
/*< private >*/
GObjectClass parent_class;
};
// May not be present
guint xkeysym;
gchar *text;
} EekSymbol;
GType eek_symbol_get_type (void) G_GNUC_CONST;
EekSymbol *eek_symbol_new (const gchar *name);
void eek_symbol_free (EekSymbol *symbol);
void eek_symbol_set_name (EekSymbol *symbol,
const gchar *name);
const gchar *eek_symbol_get_name (EekSymbol *symbol);

View File

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

View File

@ -29,9 +29,17 @@
G_BEGIN_DECLS
#define EEK_TYPE_TEXT (eek_text_get_type())
G_DECLARE_DERIVABLE_TYPE(EekText, eek_text, EEK, TEXT, EekSymbol)
struct _EekTextClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_text_get_type (void) G_GNUC_CONST;
EekSymbol *eek_text_new (const gchar *text);
const gchar *eek_text_get_text (EekSymbol *text);
EekText *eek_text_new (const gchar *text);
const gchar *eek_text_get_text (EekText *text);
G_END_DECLS

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

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

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

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EEK_THEME_CONTEXT_H__
#define __EEK_THEME_CONTEXT_H__
#include <pango/pango.h>
#include "eek-theme-node.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-context
* @short_description: holds global information about a tree of styled objects
*
* #EekThemeContext is responsible for managing information global to
* a tree of styled objects, such as the set of stylesheets or the
* default font.
*/
typedef struct _EekThemeContextClass EekThemeContextClass;
#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
GType eek_theme_context_get_type
(void) G_GNUC_CONST;
EekThemeContext *eek_theme_context_new
(void);
void eek_theme_context_set_theme
(EekThemeContext *context,
EekTheme *theme);
EekTheme * eek_theme_context_get_theme
(EekThemeContext *context);
void eek_theme_context_set_resolution
(EekThemeContext *context,
gdouble resolution);
void eek_theme_context_set_default_resolution
(EekThemeContext *context);
double eek_theme_context_get_resolution
(EekThemeContext *context);
void eek_theme_context_set_font
(EekThemeContext *context,
const PangoFontDescription *font);
const PangoFontDescription *eek_theme_context_get_font
(EekThemeContext *context);
EekThemeNode * eek_theme_context_get_root_node
(EekThemeContext *context);
G_END_DECLS
#endif /* __EEK_THEME_CONTEXT_H__ */

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

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,141 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef __EEK_THEME_NODE_H__
#define __EEK_THEME_NODE_H__
#include <pango/pango.h>
#include "eek-types.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-node
* @short_description: style information for one node in a tree of
* themed objects
*
* The #EekThemeNode class represents the CSS style information (the
* set of CSS properties) for one node in a tree of themed objects. In
* typical usage, it represents the style information for a single
* #EekElement. A #EekThemeNode is immutable: attributes such as the
* CSS classes for the node are passed in at construction. If the
* attributes of the node or any parent node change, the node should
* be discarded and a new node created. #EekThemeNode has generic
* accessors to look up properties by name and specific accessors for
* standard CSS properties that add caching and handling of various
* details of the CSS specification. #EekThemeNode also has
* convenience functions to help in implementing a #EekElement with
* borders and padding.
*/
typedef enum {
EEK_SIDE_TOP,
EEK_SIDE_RIGHT,
EEK_SIDE_BOTTOM,
EEK_SIDE_LEFT
} EekSide;
typedef enum {
EEK_CORNER_TOPLEFT,
EEK_CORNER_TOPRIGHT,
EEK_CORNER_BOTTOMRIGHT,
EEK_CORNER_BOTTOMLEFT
} EekCorner;
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
typedef struct _EekThemeNodeClass EekThemeNodeClass;
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
GType eek_theme_node_get_type
(void) G_GNUC_CONST;
EekThemeNode *eek_theme_node_new (EekThemeContext *context,
EekThemeNode *parent_node,
/* can be null */ EekTheme *theme,
/* can be null */ GType element_type,
const char *element_id,
const char *element_class,
const char *pseudo_class,
const char *inline_style);
EekThemeNode *eek_theme_node_get_parent
(EekThemeNode *node);
EekTheme *eek_theme_node_get_theme
(EekThemeNode *node);
GType eek_theme_node_get_element_type
(EekThemeNode *node);
const char *eek_theme_node_get_element_id
(EekThemeNode *node);
const char *eek_theme_node_get_element_class
(EekThemeNode *node);
const char *eek_theme_node_get_pseudo_class
(EekThemeNode *node);
/* Generic getters ... these are not cached so are less efficient. The other
* reason for adding the more specific version is that we can handle the
* details of the actual CSS rules, which can be complicated, especially
* for fonts
*/
void eek_theme_node_get_color
(EekThemeNode *node,
const char *property_name,
EekColor *color);
/* Specific getters for particular properties: cached
*/
void eek_theme_node_get_background_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_foreground_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_background_gradient
(EekThemeNode *node,
EekGradientType *type,
EekColor *start,
EekColor *end);
int eek_theme_node_get_border_width
(EekThemeNode *node,
EekSide side);
int eek_theme_node_get_border_radius
(EekThemeNode *node,
EekCorner corner);
void eek_theme_node_get_border_color
(EekThemeNode *node,
EekSide side,
EekColor *color);
/* Font rule processing is pretty complicated, so we just hardcode it
* under the standard font/font-family/font-size/etc names. This means
* you can't have multiple separate styled fonts for a single item,
* but that should be OK.
*/
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
G_END_DECLS
#endif /* __EEK_THEME_NODE_H__ */

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

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

1095
eek/eek-theme.c Normal file

File diff suppressed because it is too large Load Diff

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

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

View File

@ -139,6 +139,7 @@ typedef struct _EekKey EekKey;
typedef struct _EekSection EekSection;
typedef struct _EekKeyboard EekKeyboard;
typedef struct _EekSymbol EekSymbol;
typedef struct _EekKeysym EekKeysym;
typedef struct _EekText EekText;
typedef struct _EekTheme EekTheme;
typedef struct _EekThemeContext EekThemeContext;

View File

@ -79,6 +79,10 @@ 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,
@ -243,7 +247,6 @@ struct _GeometryParseData {
gchar *name;
EekOutline outline;
gchar *oref;
gint keycode;
GHashTable *key_oref_hash;
GHashTable *oref_outline_hash;
@ -266,7 +269,6 @@ geometry_parse_data_new (EekKeyboard *keyboard)
g_str_equal,
g_free,
(GDestroyNotify)eek_outline_free);
data->keycode = 8;
return data;
}
@ -394,6 +396,17 @@ 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) {
@ -403,18 +416,12 @@ 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,
name,
keycode);
g_strdup (attribute),
keycode,
data->num_columns,
data->num_rows - 1);
attribute = get_attribute (attribute_names, attribute_values,
"oref");
@ -566,6 +573,7 @@ struct _SymbolsParseData {
gchar *label;
gchar *icon;
gchar *tooltip;
EekSymbolCategory category;
guint keyval;
gint groups;
};
@ -678,6 +686,13 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
"tooltip");
if (attribute != NULL)
data->tooltip = g_strdup (attribute);
attribute = get_attribute (attribute_names, attribute_values,
"category");
if (attribute != NULL)
data->category = strtoul (attribute, NULL, 10);
else
data->category = EEK_SYMBOL_CATEGORY_KEYNAME;
}
out:
@ -712,6 +727,7 @@ 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) {
@ -735,22 +751,21 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
EekSymbol *symbol;
if (g_strcmp0 (element_name, "keysym") == 0) {
EekSymbol *keysym;
EekKeysym *keysym;
if (data->keyval != EEK_INVALID_KEYSYM)
keysym = eek_keysym_new (data->keyval);
else
keysym = eek_keysym_new_from_name (text);
symbol = keysym;
symbol = EEK_SYMBOL(keysym);
} else if (g_strcmp0 (element_name, "text") == 0) {
symbol = eek_text_new (text);
symbol = EEK_SYMBOL(eek_text_new (text));
} else {
symbol = eek_symbol_new (text);
eek_symbol_set_category (symbol, EEK_SYMBOL_CATEGORY_KEYNAME);
}
if (data->label) {
eek_symbol_set_label (symbol, data->label);
eek_keyboard_register_symbol (data->keyboard, symbol, data->key,
g_slist_length (data->symbols));
g_free (data->label);
data->label = NULL;
}
@ -931,9 +946,11 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
return NULL;
}
/* Arrange the sections in the original coordinate system. */
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);
@ -1343,6 +1360,23 @@ 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,

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

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

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

@ -0,0 +1,39 @@
/*
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_XML_H
#define EEK_XML_H 1
#include <glib-object.h>
#include "eek-keyboard.h"
#include "eek-xml-layout.h"
G_BEGIN_DECLS
#define EEK_XML_SCHEMA_VERSION "0.90"
void eek_keyboard_output (EekKeyboard *keyboard,
GString *output,
gint indent);
G_END_DECLS
#endif /* EEK_XML_H */

View File

@ -29,7 +29,9 @@
#include "eek-symbol.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "eek-xml.h"
#include "eek-serializable.h"
#include "eek-theme.h"
void eek_init (void);

View File

@ -33,7 +33,7 @@ else:
table = dict()
for line in in_stream:
match = re.match(r'\s*(0x[0-9A-F]+)\s+"(.*)"\s+(\S*)', line, re.I)
match = re.match(r'\s*(0x[0-9A-F]+)\s+(\S*)\s+(\S*)', line, re.I)
if match:
table[int(match.group(1), 16)] = (match.group(2), match.group(3))
@ -42,8 +42,8 @@ sys.stdout.write("static const EekKeysymEntry %s[] = {\n" %
for index, (keysym, (l, c)) in enumerate([(keysym, table[keysym])
for keysym in sorted(table.keys())]):
sys.stdout.write(" { 0x%X, \"%s\" }" %
(keysym, l))
sys.stdout.write(" { 0x%X, %s, %s }" %
(keysym, l, c))
if index < len(table) - 1:
sys.stdout.write(",")
sys.stdout.write("\n")

View File

@ -1,39 +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);
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,6 +27,9 @@
#include "config.h"
#include "eekboard/eekboard-context-service.h"
#include "keymap.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@ -34,14 +37,10 @@
#include <sys/random.h> // TODO: this is Linux-specific
#include <xkbcommon/xkbcommon.h>
#include <gio/gio.h>
#include "eekboard/key-emitter.h"
#include "wayland.h"
#include "eek/eek-xml-layout.h"
#include "eekboard/eekboard-context-service.h"
//#include "eekboard/eekboard-xklutil.h"
//#include "eek/eek-xkl.h"
#define CSW 640
#define CSH 480
@ -86,6 +85,55 @@ 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)
@ -145,8 +193,13 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
if (!context) {
g_error("No context created");
}
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
/*
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);
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
@ -304,24 +357,8 @@ settings_update_layout(EekboardContextService *context)
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
switch (priv->purpose) {
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS:
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN:
keyboard_layout = g_strdup("digits");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
keyboard_layout = g_strdup("number");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("phone");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL:
keyboard_layout = g_strdup("url");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL:
default:
;
}
if (priv->purpose == ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE)
keyboard_layout = g_strdup("numbers");
// generic part follows
static guint keyboard_id = 0;

View File

@ -35,6 +35,7 @@ enum {
ENABLED,
DISABLED,
DESTROYED,
KEY_ACTIVATED,
LAST_SIGNAL
};
@ -80,6 +81,28 @@ eekboard_context_real_g_signal (GDBusProxy *self,
return;
}
if (g_strcmp0 (signal_name, "KeyActivated") == 0) {
guint keycode;
GVariant *variant = NULL;
guint modifiers = 0;
EekSerializable *serializable;
g_variant_get (parameters, "(uvu)",
&keycode, &variant, &modifiers);
g_return_if_fail (variant != NULL);
serializable = eek_serializable_deserialize (variant);
g_variant_unref (variant);
g_return_if_fail (EEK_IS_SYMBOL(serializable));
g_signal_emit (context, signals[KEY_ACTIVATED], 0,
keycode, EEK_SYMBOL(serializable), modifiers);
g_object_unref (serializable);
return;
}
if (g_strcmp0 (signal_name, "VisibilityChanged") == 0) {
gboolean visible = FALSE;
@ -126,6 +149,14 @@ eekboard_context_real_destroyed (EekboardContext *self)
{
}
static void
eekboard_context_real_key_activated (EekboardContext *self,
guint keycode,
EekSymbol *symbol,
guint modifiers)
{
}
static void
eekboard_context_get_property (GObject *object,
guint prop_id,
@ -155,6 +186,7 @@ eekboard_context_class_init (EekboardContextClass *klass)
klass->enabled = eekboard_context_real_enabled;
klass->disabled = eekboard_context_real_disabled;
klass->destroyed = eekboard_context_real_destroyed;
klass->key_activated = eekboard_context_real_key_activated;
proxy_class->g_signal = eekboard_context_real_g_signal;
@ -208,6 +240,31 @@ eekboard_context_class_init (EekboardContextClass *klass)
G_TYPE_NONE,
0);
/**
* EekboardContext::key-activated:
* @context: an #EekboardContext
* @keycode: a keycode
* @symbol: an #EekSymbol
* @modifiers: modifiers
*
* The ::key-activated signal is emitted each time a key is
* pressed in @context.
*/
/*
signals[KEY_ACTIVATED] =
g_signal_new (I_("key-activated"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekboardContextClass, key_activated),
NULL,
NULL,
_eekboard_marshal_VOID__UINT_OBJECT_UINT,
G_TYPE_NONE,
3,
G_TYPE_UINT,
G_TYPE_OBJECT,
G_TYPE_UINT);
*/
/**
* EekboardContext::destroyed:
* @context: an #EekboardContext

View File

@ -47,6 +47,11 @@ struct _EekboardContextClass {
void (*disabled) (EekboardContext *self);
void (*destroyed) (EekboardContext *self);
void (*key_activated) (EekboardContext *self,
guint keycode,
EekSymbol *symbol,
guint modifiers);
/*< private >*/
/* padding */
gpointer pdummy[24];

View File

@ -28,14 +28,12 @@
#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,6 +20,7 @@
/* This file is responsible for managing keycode data and emitting keycodes. */
#include "eekboard/key-emitter.h"
#include "eekboard/keymap.h"
#include <gdk/gdk.h>
@ -38,6 +39,98 @@ 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,
@ -48,6 +141,115 @@ int send_virtual_keyboard_key(
return 0;
}
static void
send_fake_modifiers_events (SeatEmitter *emitter,
EekModifierType modifiers,
uint32_t timestamp)
{
(void)timestamp;
uint32_t proto_modifiers = 0;
if (modifiers & EEK_SHIFT_MASK) {
proto_modifiers |= 1<<MOD_IDX_SHIFT;
}
if (modifiers & EEK_CONTROL_MASK) {
proto_modifiers |= 1<<MOD_IDX_CTRL;
}
if (modifiers & EEK_MOD1_MASK) {
proto_modifiers |= 1<<MOD_IDX_ALT;
}
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)
@ -84,13 +286,14 @@ update_modifier_info (SeatEmitter *client)
static void
send_fake_key (SeatEmitter *emitter,
guint level,
EekKeyboard *keyboard,
guint keycode,
guint keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
uint32_t proto_modifiers = 0;
guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
uint32_t group = (level / 2);
if (keyboard_modifiers & EEK_SHIFT_MASK)
@ -101,38 +304,6 @@ send_fake_key (SeatEmitter *emitter,
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
}
static void
send_fake_text (SeatEmitter *emitter,
EekKeyboard *keyboard,
const gchar *text,
uint32_t timestamp)
{
gchar *ptr = (gchar *)text;
while (*ptr) {
gchar buf[7];
gunichar c = g_utf8_get_char(ptr);
int n = g_unichar_to_utf8(c, buf);
*(buf + n) = 0;
EekKeyPress *key_press = eek_keyboard_get_key_press(keyboard, buf);
if (key_press) {
EekKey *key = key_press->key;
send_fake_key (emitter, key_press->level, eek_key_get_keycode(key),
(key_press->level % 2) == 1 ? EEK_SHIFT_MASK : 0,
1, timestamp);
send_fake_key (emitter, key_press->level, eek_key_get_keycode(key),
(key_press->level % 2) == 1 ? EEK_SHIFT_MASK : 0,
0, timestamp);
}
ptr = g_utf8_find_next_char(ptr, NULL);
}
}
void
emit_key_activated (EekboardContextService *manager,
EekKeyboard *keyboard,
@ -173,12 +344,5 @@ emit_key_activated (EekboardContextService *manager,
emitter.virtual_keyboard = manager->virtual_keyboard;
emitter.keymap = keyboard->keymap;
update_modifier_info (&emitter);
const gchar *text = (gchar *)eek_text_get_text(symbol);
if (text && pressed) {
send_fake_text (&emitter, keyboard, text, timestamp);
} else {
guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
send_fake_key (&emitter, level, keycode, modifiers, pressed, timestamp);
}
send_fake_key (&emitter, keyboard, keycode, modifiers, pressed, timestamp);
}

66
eekboard/keymap.c Normal file
View File

@ -0,0 +1,66 @@
/* 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;
}

8
eekboard/keymap.h Normal file
View File

@ -0,0 +1,8 @@
#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,16 +11,6 @@ project(
]
)
add_project_arguments(
[
'-Werror=implicit-function-declaration',
'-Werror=implicit-fallthrough=3',
'-Werror=maybe-uninitialized',
'-Werror=missing-field-initializers',
],
language: 'c'
)
i18n = import('i18n')
conf_data = configuration_data()

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,19 @@
#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,
@ -28,16 +41,14 @@ struct imservice* get_imservice(EekboardContextService *context,
return imservice;
}
void imservice_make_visible(EekboardContextService *context) {
void imservice_make_visible(EekboardContextService *context,
struct zwp_input_method_v2 *im) {
(void)im;
eekboard_context_service_show_keyboard (context);
}
void imservice_try_hide(EekboardContextService *context) {
void imservice_try_hide(EekboardContextService *context,
struct zwp_input_method_v2 *im) {
(void)im;
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,7 +4,11 @@
#include "input-method-unstable-v2-client-protocol.h"
#include "eek/eek-types.h"
struct imservice;
struct imservice
{
struct zwp_input_method_v2 *im;
EekboardContextService *ui_manager;
};
struct imservice* get_imservice(EekboardContextService *context,
struct zwp_input_method_manager_v2 *manager,
@ -18,8 +22,5 @@ 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,11 +3,6 @@ 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 {
@ -23,7 +18,7 @@ pub mod c {
}
// The following defined in C
/// struct zwp_input_method_v2*
#[repr(transparent)]
pub struct InputMethod(*const c_void);
@ -34,10 +29,8 @@ pub mod c {
#[no_mangle]
extern "C" {
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);
fn imservice_make_visible(imservice: *const UIManager);
fn imservice_try_hide(imservice: *const UIManager);
}
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
@ -61,9 +54,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 = check_imservice(imservice, im).unwrap();
let imservice = &mut *imservice;
imservice.preedit_string = String::new();
imservice.pending = IMProtocolState {
active: true,
@ -74,9 +67,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 = check_imservice(imservice, im).unwrap();
let imservice = &mut *imservice;
imservice.pending = IMProtocolState {
active: false,
..imservice.pending.clone()
@ -86,65 +79,23 @@ 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 = check_imservice(imservice, im).unwrap();
let imservice = &mut *imservice;
imservice.pending = IMProtocolState {
surrounding_text: into_cstring(text).expect("Received invalid string"),
surrounding_cursor: cursor,
..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()
..imservice.pending
};
}
#[no_mangle]
pub unsafe extern "C"
fn imservice_handle_commit_state(imservice: *mut IMService,
im: *const InputMethod)
_im: *const InputMethod)
{
let imservice = check_imservice(imservice, im).unwrap();
let imservice = &mut *imservice;
let active_changed = imservice.current.active ^ imservice.pending.active;
imservice.serial += Wrapping(1u32);
@ -155,174 +106,27 @@ pub mod c {
};
if active_changed {
if imservice.current.active {
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);
imservice_make_visible(imservice.ui_manager);
} else {
eekboard_context_service_hide_keyboard(imservice.ui_manager);
imservice_try_hide(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(Clone)]
#[derive(Default, 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)
pub im: *const c::InputMethod,
im: *const c::InputMethod,
/// Unowned reference. Be careful, it's shared with C at large
ui_manager: *const c::UIManager,

View File

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

View File

@ -30,6 +30,9 @@ sources = [
'../eek/eek-symbol.c',
'../eek/eek-symbol-matrix.c',
'../eek/eek-text.c',
'../eek/eek-theme.c',
'../eek/eek-theme-context.c',
'../eek/eek-theme-node.c',
'../eek/eek-types.c',
'../eek/eek-xml-layout.c',
'../eek/layersurface.c',
@ -37,6 +40,7 @@ sources = [
enums,
keysym_entries,
marshalers,
'../eekboard/keymap.c',
'../eekboard/key-emitter.c',
'../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-context.c',
@ -66,19 +70,10 @@ deps = [
# Replacement for eekboard-server
rslib = static_library(
'rslib',
sources: ['lib.rs'],
sources: ['imservice.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,
@ -94,7 +89,6 @@ libsqueekboard = static_library('libsqueekboard',
squeekboard = executable('squeekboard',
'server-main.c',
wl_proto_sources,
squeekboard_resources,
link_with: libsqueekboard,
include_directories: [include_directories('..'), include_directories('../eek')],
dependencies: deps,

View File

@ -75,9 +75,6 @@ on_destroy (GtkWidget *widget, gpointer user_data)
eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
}
static void
make_widget (ServerContextService *context);
static void
on_notify_keyboard (GObject *object,
GParamSpec *spec,
@ -97,9 +94,6 @@ on_notify_keyboard (GObject *object,
keyboard);
/* Recreate the keyboard widget to keep in sync with the keymap. */
if (context->window)
make_widget(context);
gboolean visible;
g_object_get (context, "visible", &visible, NULL);
@ -174,6 +168,13 @@ 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));
}
}
@ -229,16 +230,20 @@ static void
make_widget (ServerContextService *context)
{
EekKeyboard *keyboard;
EekTheme *theme;
if (context->widget) {
gtk_widget_destroy(context->widget);
context->widget = NULL;
}
g_return_if_fail (!context->widget);
theme = eek_theme_new ("resource:///sm/puri/squeekboard/style.css",
NULL,
NULL);
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
context->widget = eek_gtk_keyboard_new (keyboard);
eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(context->widget), theme);
g_clear_object (&theme);
gtk_widget_set_has_tooltip (context->widget, TRUE);
gtk_container_add (GTK_CONTAINER(context->window), context->widget);
gtk_widget_show (context->widget);
@ -252,8 +257,12 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
if (!context->window)
make_window (context);
if (!context->widget)
make_widget (context);
if (context->widget) {
gtk_widget_destroy(context->widget);
context->widget = NULL;
}
make_widget (context);
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
show_keyboard (_context);

View File

@ -19,8 +19,6 @@
*/
#include "eek/eek.h"
#include <gtk/gtk.h>
static void
test_create (void)
{
@ -32,9 +30,9 @@ test_create (void)
section = eek_keyboard_create_section (keyboard);
g_assert (EEK_IS_SECTION(section));
eek_section_add_row (section, 2, EEK_ORIENTATION_HORIZONTAL);
key0 = eek_section_create_key (section, "key0", 1);
key0 = eek_section_create_key (section, "key0", 1, 0, 0);
g_assert (EEK_IS_KEY(key0));
key1 = eek_section_create_key (section, "key1", 2);
key1 = eek_section_create_key (section, "key1", 2, 1, 0);
g_assert (EEK_IS_KEY(key1));
}

View File

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

View File

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

181
tests/test-keyboard.xml Normal file
View File

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

@ -1,72 +0,0 @@
/*
* 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)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb);
return g_test_run ();
}