Compare commits

..

3 Commits

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

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

Left to do: adjust it based on CSS.
2019-08-01 16:35:33 +00:00
50 changed files with 5020 additions and 1067 deletions

View File

@ -28,4 +28,4 @@ test:
dependencies: dependencies:
- build_meson - build_meson
script: script:
- ninja -C _build test - xvfb-run -s -noreset ninja -C _build test

View File

@ -1,98 +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="outline4" />
<key name="AD02" oref="outline4" />
<key name="AD03" oref="outline4" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline4" />
<key name="AC02" oref="outline4" />
<key name="AC03" oref="outline4" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AB01" oref="outline4" />
<key name="AB02" oref="outline4" />
<key name="AB03" oref="outline4" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="BKSP" oref="altline" />
<key name="AB04" oref="outline4" />
<key name="RTRN" oref="altline" />
</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,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,11 @@
longname="Telugu (Inscript)" language="te"/> longname="Telugu (Inscript)" language="te"/>
<!-- Common keyboards --> <!-- Common keyboards -->
<keyboard id="digits" name="digits"
geometry="digits" symbols="special/digits"
longname="Digits" language="all"/>
<keyboard id="number" name="number" <keyboard id="number" name="number"
geometry="number-keypad" symbols="special/number" geometry="number-keypad" symbols="special/number"
longname="Numeric keypad" language="all"/> longname="Numeric keypad" language="all"/>
<keyboard id="phone" name="phone" <keyboard id="phone" name="phone"
geometry="phone-keypad" symbols="special/phone" geometry="number-keypad" symbols="special/number"
longname="Phone keypad" language="all"/> longname="Phone keypad" language="all"/>
<keyboard id="url" name="url"
geometry="url" symbols="special/url"
longname="Uniform Resource Locator" language="all"/>
</keyboards> </keyboards>

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

@ -10,10 +10,10 @@
<symbol label="3">3</symbol> <symbol label="3">3</symbol>
</key> </key>
<key name="AD04"> <key name="AD04">
<symbol label=".">period</symbol> <symbol label="(">parenleft</symbol>
</key> </key>
<key name="AD05"> <key name="AD05">
<symbol label=",">comma</symbol> <symbol label=")">parenright</symbol>
</key> </key>
<key name="AC01"> <key name="AC01">
<symbol label="4">4</symbol> <symbol label="4">4</symbol>
@ -25,7 +25,7 @@
<symbol label="6">6</symbol> <symbol label="6">6</symbol>
</key> </key>
<key name="AC04"> <key name="AC04">
<symbol label="/">slash</symbol> <symbol label="#">numbersign</symbol>
</key> </key>
<key name="AC05"> <key name="AC05">
<symbol label="*">asterisk</symbol> <symbol label="*">asterisk</symbol>

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="(">parenleft</symbol>
</key>
<key name="AD05">
<symbol label=")">parenright</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="#">numbersign</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

@ -2,19 +2,10 @@
<gresources> <gresources>
<gresource prefix="/sm/puri/squeekboard"> <gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</file> <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/compact.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/extended.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/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/keyboards.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
<!-- Natural language keyboards -->
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ar.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ar.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/as-inscript.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/as-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/be.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/be.xml</file>
@ -44,13 +35,7 @@
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ug.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ug.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/us.xml</file> <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/us.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.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/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>icons/key-enter.svg</file> <file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file> <file>icons/key-shift.svg</file>
<file>icons/keyboard-mode-symbolic.svg</file> <file>icons/keyboard-mode-symbolic.svg</file>

View File

@ -50,7 +50,7 @@ static void
eek_container_real_add_child (EekContainer *self, eek_container_real_add_child (EekContainer *self,
EekElement *child) 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_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref (child); g_object_ref (child);

View File

@ -55,8 +55,7 @@ typedef struct _EekGtkKeyboardPrivate
{ {
EekRenderer *renderer; EekRenderer *renderer;
EekKeyboard *keyboard; EekKeyboard *keyboard;
GtkCssProvider *css_provider; EekTheme *theme;
GtkStyleContext *scontext;
GdkEventSequence *sequence; // unowned reference GdkEventSequence *sequence; // unowned reference
} EekGtkKeyboardPrivate; } EekGtkKeyboardPrivate;
@ -67,6 +66,16 @@ static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self); EekGtkKeyboard *self);
static void on_key_released (EekKey *key, static void on_key_released (EekKey *key,
EekGtkKeyboard *self); 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, static void render_pressed_key (GtkWidget *widget,
EekKey *key); EekKey *key);
static void render_locked_key (GtkWidget *widget, static void render_locked_key (GtkWidget *widget,
@ -100,9 +109,12 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
gtk_widget_get_allocation (self, &allocation); gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) { 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, eek_renderer_set_allocation_size (priv->renderer,
allocation.width, allocation.width,
@ -147,8 +159,7 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
} }
static void depress(EekGtkKeyboard *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); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y); EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
@ -162,17 +173,16 @@ static void drag(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) { gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y); 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) { if (key) {
GList *list, *head;
gboolean found = FALSE; gboolean found = FALSE;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) { for (head = list; head; head = g_list_next (head)) {
if (head->data == key) { if (head->data == key)
found = TRUE; found = TRUE;
} else { else {
eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time); eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
on_key_released(key, self); on_key_released(key, self);
} }
@ -183,12 +193,6 @@ static void drag(EekGtkKeyboard *self,
eek_keyboard_press_key(priv->keyboard, key, time); eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self); 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 +333,18 @@ eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
return; return;
if (priv->keyboard) { if (priv->keyboard) {
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
g_object_unref (priv->keyboard); g_object_unref (priv->keyboard);
} }
priv->keyboard = g_object_ref (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 static void
@ -368,6 +380,7 @@ eek_gtk_keyboard_dispose (GObject *object)
if (priv->keyboard) { if (priv->keyboard) {
GList *list, *head; GList *list, *head;
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
list = eek_keyboard_get_pressed_keys (priv->keyboard); list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) { for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed"); g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
@ -379,6 +392,11 @@ eek_gtk_keyboard_dispose (GObject *object)
priv->keyboard = NULL; priv->keyboard = NULL;
} }
if (priv->theme) {
g_object_unref (priv->theme);
priv->theme = NULL;
}
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object); G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
} }
@ -419,20 +437,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
static void static void
eek_gtk_keyboard_init (EekGtkKeyboard *self) eek_gtk_keyboard_init (EekGtkKeyboard *self)
{ {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); /* void */
/* 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);
} }
/** /**
@ -477,15 +482,27 @@ render_pressed_key (GtkWidget *widget,
{ {
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget); GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window); cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context); cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE); 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); eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_restore (cr);
*/ */
gdk_window_end_draw_frame (window, context); gdk_window_end_draw_frame (window, context);
@ -498,13 +515,21 @@ render_locked_key (GtkWidget *widget,
{ {
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds;
GdkWindow *window = gtk_widget_get_window (widget); GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window); cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context); cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE); eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
gdk_window_end_draw_frame (window, context); gdk_window_end_draw_frame (window, context);
@ -517,6 +542,7 @@ render_released_key (GtkWidget *widget,
{ {
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget); GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window); cairo_region_t *region = gdk_window_get_clip_region (window);
@ -573,3 +599,57 @@ on_key_released (EekKey *key,
NULL); NULL);
#endif #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; GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard); GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme);
G_END_DECLS G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */ #endif /* EEK_GTK_KEYBOARD_H */

View File

@ -38,6 +38,8 @@ enum {
PROP_0, PROP_0,
PROP_KEYCODE, PROP_KEYCODE,
PROP_SYMBOL_MATRIX, PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OREF, PROP_OREF,
PROP_LAST PROP_LAST
}; };
@ -54,6 +56,8 @@ typedef struct _EekKeyPrivate
{ {
guint keycode; guint keycode;
EekSymbolMatrix *symbol_matrix; EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
gulong oref; // UI outline reference gulong oref; // UI outline reference
gboolean is_pressed; gboolean is_pressed;
gboolean is_locked; gboolean is_locked;
@ -101,6 +105,8 @@ eek_key_set_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
EekSymbolMatrix *matrix; EekSymbolMatrix *matrix;
gint column, row;
switch (prop_id) { switch (prop_id) {
case PROP_KEYCODE: case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value)); 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); matrix = g_value_get_boxed (value);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix); eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break; 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: case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value)); eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break; break;
@ -124,6 +138,8 @@ eek_key_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
gint column, row;
switch (prop_id) { switch (prop_id) {
case PROP_KEYCODE: case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object))); 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, g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object))); eek_key_get_symbol_matrix (EEK_KEY(object)));
break; 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: case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object))); g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break; break;
@ -179,6 +203,30 @@ eek_key_class_init (EekKeyClass *klass)
G_PARAM_READWRITE); G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec); 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: * EekKey:oref:
* *
@ -430,6 +478,59 @@ eek_key_get_symbol_at_index (EekKey *key,
level]; 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: * eek_key_set_oref:
* @key: an #EekKey * @key: an #EekKey

View File

@ -73,6 +73,13 @@ EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
gint fallback_group, gint fallback_group,
gint fallback_level); 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, void eek_key_set_oref (EekKey *key,
guint oref); guint oref);
guint eek_key_get_oref (EekKey *key); guint eek_key_get_oref (EekKey *key);

View File

@ -75,10 +75,8 @@ struct _EekKeyboardPrivate
GList *locked_keys; GList *locked_keys;
GArray *outline_array; GArray *outline_array;
/* Map key names to key objects */ /* Map key names to key objects: */
GHashTable *names; GHashTable *names;
/* Map characters to symbols and levels */
GHashTable *character_map;
/* modifiers dynamically assigned at run time */ /* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask; EekModifierType num_lock_mask;
@ -407,7 +405,6 @@ eek_keyboard_finalize (GObject *object)
(GDestroyNotify) eek_modifier_key_free); (GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->names); g_hash_table_destroy (priv->names);
g_hash_table_destroy (priv->character_map);
for (i = 0; i < priv->outline_array->len; i++) { for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array, EekOutline *outline = &g_array_index (priv->outline_array,
@ -536,8 +533,6 @@ eek_keyboard_init (EekKeyboard *self)
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE; self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); 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->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); eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
self->scale = 1.0; self->scale = 1.0;
} }
@ -850,7 +845,7 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
/* Get the symbols for all the levels defined for the key, then /* 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. */ pad it out with the first symbol for all levels up to the fourth. */
for (i = 0; (i < matrix->num_levels) && (i < 4); ++i) for (i = 0; i < matrix->num_levels; ++i)
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i); syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
while (i < 4) { while (i < 4) {
@ -862,12 +857,14 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
Generate strings for each of these groups, where an empty group is Generate strings for each of these groups, where an empty group is
treated specially. */ treated specially. */
gchar *groups[2] = {NULL, NULL}; gchar *groups[2];
for (i = 0, j = 0; i < 2; ++i, j += 2) { for (i = 0, j = 0; i < 2; ++i, j += 2) {
if (syms[j] && syms[j + 1]) if (syms[j] && syms[j + 1])
groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]), groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
eek_symbol_get_name(syms[j + 1]), eek_symbol_get_name(syms[j + 1]),
NULL); NULL);
else
groups[i] = "";
} }
/* Append a key definition to the symbols section. */ /* Append a key definition to the symbols section. */
@ -893,29 +890,3 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
g_free(symbols); g_free(symbols);
return keymap; 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; typedef struct _EekModifierKey EekModifierKey;
struct _EekKeyPress {
EekKey *key;
guint level;
};
typedef struct _EekKeyPress EekKeyPress;
EekKeyboard *eek_keyboard_new (EekboardContextService *manager, EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout, EekLayout *layout,
@ -203,15 +198,5 @@ void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timest
gchar * eek_keyboard_get_keymap gchar * eek_keyboard_get_keymap
(EekKeyboard *keyboard); (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 G_END_DECLS
#endif /* EEK_KEYBOARD_H */ #endif /* EEK_KEYBOARD_H */

View File

@ -48,9 +48,15 @@
#define EEK_KEYSYM_Hyper_L 0xffed #define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee #define EEK_KEYSYM_Hyper_R 0xffee
typedef struct _EekKeysymPrivate
{
guint xkeysym;
} EekKeysymPrivate;
struct _EekKeysymEntry { struct _EekKeysymEntry {
guint xkeysym; guint xkeysym;
const gchar *name; const gchar *name;
EekSymbolCategory category;
}; };
typedef struct _EekKeysymEntry EekKeysymEntry; typedef struct _EekKeysymEntry EekKeysymEntry;
@ -59,6 +65,54 @@ typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-unicode-keysym-entries.h" #include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-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 * static gchar *
unichar_to_utf8 (gunichar uc) unichar_to_utf8 (gunichar uc)
@ -143,6 +197,18 @@ get_modifier_mask (guint xkeysym)
return 0; return 0;
} }
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
/* void */
}
static void
eek_keysym_init (EekKeysym *self)
{
/* void */
}
/** /**
* eek_keysym_new_with_modifier: * eek_keysym_new_with_modifier:
* @xkeysym: an X keysym value * @xkeysym: an X keysym value
@ -151,12 +217,16 @@ get_modifier_mask (guint xkeysym)
* Create an #EekKeysym with given X keysym value @xkeysym and * Create an #EekKeysym with given X keysym value @xkeysym and
* modifier @modifier_mask. * modifier @modifier_mask.
*/ */
EekSymbol *eek_keysym_new_with_modifier(guint xkeysym, EekKeysym *
eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask) EekModifierType modifier_mask)
{ {
EekKeysym *keysym;
EekKeysymPrivate *priv;
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry, EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry; *unichar_entry;
gchar *name, *label; gchar *name, *label;
EekSymbolCategory category;
gunichar uc; gunichar uc;
special_entry = special_entry =
@ -176,17 +246,23 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
unichar_entry = g_slice_new (EekKeysymEntry); unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym; unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc); unichar_entry->name = unichar_to_utf8 (uc);
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
} }
/* name and category */
name = NULL; name = NULL;
if (xkeysym_entry) { if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name); name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) { } else if (unichar_entry) {
name = g_strdup (unichar_entry->name); name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) { } else if (unicode_entry) {
name = g_strdup (unicode_entry->name); name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else { } else {
name = g_strdup (""); name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
} }
/* label */ /* label */
@ -199,10 +275,12 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
else else
label = g_strdup (name); label = g_strdup (name);
EekSymbol *keysym = eek_symbol_new(name); keysym = g_object_new (EEK_TYPE_KEYSYM,
eek_symbol_set_label(keysym, label); "name", name,
eek_symbol_set_modifier_mask(keysym, modifier_mask); "label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name); g_free (name);
g_free (label); g_free (label);
@ -211,7 +289,8 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
g_slice_free (EekKeysymEntry, unichar_entry); g_slice_free (EekKeysymEntry, unichar_entry);
} }
keysym->xkeysym = xkeysym; priv = eek_keysym_get_instance_private (keysym);
priv->xkeysym = xkeysym;
return keysym; return keysym;
} }
@ -222,7 +301,7 @@ EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
* *
* Create an #EekKeysym with given X keysym value @xkeysym. * Create an #EekKeysym with given X keysym value @xkeysym.
*/ */
EekSymbol* EekKeysym *
eek_keysym_new (guint xkeysym) eek_keysym_new (guint xkeysym)
{ {
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (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. * Create an #EekKeysym with an X keysym value looked up by @name.
*/ */
EekSymbol* EekKeysym *
eek_keysym_new_from_name (const gchar *name) 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) if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym); return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
EekSymbol *ret = eek_symbol_new(name); // g_warning ("can't find keysym entry for %s", name);
eek_symbol_set_label(ret, name); return g_object_new (EEK_TYPE_KEYSYM,
return ret; "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 * Get an X keysym value associated with @keysym
*/ */
guint guint
eek_keysym_get_xkeysym (EekSymbol *keysym) eek_keysym_get_xkeysym (EekKeysym *keysym)
{ {
if (keysym->xkeysym == 0) { EekKeysymPrivate *priv;
g_warning("Symbol %s was expected to have a valid keysym", keysym->name);
} g_assert (EEK_IS_KEYSYM(keysym));
return keysym->xkeysym; priv = eek_keysym_get_instance_private (keysym);
return priv->xkeysym;
} }

View File

@ -37,11 +37,20 @@ G_BEGIN_DECLS
*/ */
#define EEK_INVALID_KEYSYM (0) #define EEK_INVALID_KEYSYM (0)
EekSymbol *eek_keysym_new (guint xkeysym); #define EEK_TYPE_KEYSYM (eek_keysym_get_type())
guint eek_keysym_get_xkeysym (EekSymbol *keysym); G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
EekSymbol *eek_keysym_new_from_name (const gchar *name); struct _EekKeysymClass {
EekSymbol *eek_keysym_new_with_modifier (guint xkeysym, /*< 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); EekModifierType modifier_mask);
G_END_DECLS G_END_DECLS

View File

@ -33,7 +33,6 @@ enum {
PROP_0, PROP_0,
PROP_KEYBOARD, PROP_KEYBOARD,
PROP_PCONTEXT, PROP_PCONTEXT,
PROP_STYLE_CONTEXT,
PROP_LAST PROP_LAST
}; };
@ -41,9 +40,6 @@ typedef struct _EekRendererPrivate
{ {
EekKeyboard *keyboard; EekKeyboard *keyboard;
PangoContext *pcontext; PangoContext *pcontext;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
GtkStyleContext *key_context;
EekColor default_foreground_color; EekColor default_foreground_color;
EekColor default_background_color; EekColor default_background_color;
@ -64,6 +60,7 @@ typedef struct _EekRendererPrivate
cairo_surface_t *keyboard_surface; cairo_surface_t *keyboard_surface;
gulong symbol_index_changed_handler; gulong symbol_index_changed_handler;
EekTheme *theme;
} EekRendererPrivate; } EekRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT) G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
@ -71,6 +68,14 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0}; static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0};
static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0}; static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0};
struct _TextProperty {
gint category;
gboolean ascii;
gdouble scale;
gboolean ellipses;
};
typedef struct _TextProperty TextProperty;
/* eek-keyboard-drawing.c */ /* eek-keyboard-drawing.c */
extern void _eek_rounded_polygon (cairo_t *cr, extern void _eek_rounded_polygon (cairo_t *cr,
gdouble radius, gdouble radius,
@ -148,25 +153,32 @@ render_keyboard_surface (EekRenderer *renderer)
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekBounds bounds; EekBounds bounds;
CreateKeyboardSurfaceCallbackData data; CreateKeyboardSurfaceCallbackData data;
EekColor foreground; EekColor foreground, background;
eek_renderer_get_foreground_color (renderer, priv->scontext, &foreground); eek_renderer_get_foreground_color (renderer,
EEK_ELEMENT(priv->keyboard),
&foreground);
eek_renderer_get_background_color (renderer,
EEK_ELEMENT(priv->keyboard),
&background);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
data.cr = cairo_create (priv->keyboard_surface); data.cr = cairo_create (priv->keyboard_surface);
data.renderer = renderer; data.renderer = renderer;
/* Paint the background covering the entire widget area */
gtk_render_background (priv->scontext,
data.cr,
0, 0,
priv->allocation_width, priv->allocation_height);
cairo_save (data.cr); cairo_save (data.cr);
cairo_scale (data.cr, priv->scale, priv->scale); cairo_scale (data.cr, priv->scale, priv->scale);
cairo_translate (data.cr, bounds.x, bounds.y); cairo_translate (data.cr, bounds.x, bounds.y);
/* blank background */
cairo_set_source_rgba (data.cr,
background.red,
background.green,
background.blue,
background.alpha);
cairo_paint (data.cr);
cairo_set_source_rgba (data.cr, cairo_set_source_rgba (data.cr,
foreground.red, foreground.red,
foreground.green, foreground.green,
@ -192,6 +204,7 @@ render_key_outline (EekRenderer *renderer,
EekOutline *outline; EekOutline *outline;
EekBounds bounds; EekBounds bounds;
guint oref; guint oref;
EekThemeNode *theme_node;
EekColor foreground, background, gradient_start, gradient_end, border_color; EekColor foreground, background, gradient_start, gradient_end, border_color;
EekGradientType gradient_type; EekGradientType gradient_type;
gint border_width; gint border_width;
@ -202,14 +215,119 @@ render_key_outline (EekRenderer *renderer,
if (outline == NULL) if (outline == NULL)
return; return;
theme_node = g_object_get_data (G_OBJECT(key),
active ?
"theme-node-pressed" :
"theme-node");
if (theme_node) {
eek_theme_node_get_foreground_color (theme_node, &foreground);
eek_theme_node_get_background_color (theme_node, &background);
eek_theme_node_get_background_gradient (theme_node,
&gradient_type,
&gradient_start,
&gradient_end);
border_width = eek_theme_node_get_border_width (theme_node,
EEK_SIDE_TOP);
border_radius = eek_theme_node_get_border_radius (theme_node,
EEK_CORNER_TOPLEFT);
eek_theme_node_get_border_color (theme_node, EEK_SIDE_TOP,
&border_color);
} else {
foreground = priv->default_foreground_color;
background = priv->default_background_color;
gradient_type = EEK_GRADIENT_NONE;
border_width = (gint)round(priv->border_width);
border_radius = -1;
border_color.red = ABS(background.red - foreground.red) * 0.7;
border_color.green = ABS(background.green - foreground.green) * 0.7;
border_color.blue = ABS(background.blue - foreground.blue) * 0.7;
border_color.alpha = foreground.alpha;
}
eek_element_get_bounds(EEK_ELEMENT(key), &bounds); eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
gtk_style_context_set_state(priv->key_context, outline = eek_outline_copy (outline);
active ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
gtk_render_background (priv->key_context, cairo_translate (cr, border_width, border_width);
cr, 0, 0, bounds.width, bounds.height);
gtk_style_context_set_state(priv->key_context, GTK_STATE_FLAG_NORMAL); if (gradient_type != EEK_GRADIENT_NONE) {
cairo_pattern_t *pat;
gdouble cx, cy;
switch (gradient_type) {
case EEK_GRADIENT_VERTICAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
0.0,
bounds.height);
break;
case EEK_GRADIENT_HORIZONTAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
bounds.width,
0.0);
break;
case EEK_GRADIENT_RADIAL:
cx = bounds.width / 2;
cy = bounds.height / 2;
pat = cairo_pattern_create_radial (cx,
cy,
0,
cx,
cy,
MIN(cx, cy));
break;
default:
g_assert_not_reached ();
break;
}
cairo_pattern_add_color_stop_rgba (pat,
1,
gradient_start.red * 0.5,
gradient_start.green * 0.5,
gradient_start.blue * 0.5,
gradient_start.alpha);
cairo_pattern_add_color_stop_rgba (pat,
0,
gradient_end.red,
gradient_end.green,
gradient_end.blue,
gradient_end.alpha);
cairo_set_source (cr, pat);
cairo_pattern_destroy (pat);
} else {
cairo_set_source_rgba (cr,
background.red,
background.green,
background.blue,
background.alpha);
}
_eek_rounded_polygon (cr,
border_radius >= 0 ? border_radius : outline->corner_radius,
outline->points,
outline->num_points);
cairo_fill (cr);
/* paint the border */
cairo_set_line_width (cr, border_width);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_source_rgba (cr,
border_color.red,
border_color.green,
border_color.blue,
border_color.alpha);
_eek_rounded_polygon (cr,
border_radius >= 0 ? border_radius : outline->corner_radius,
outline->points,
outline->num_points);
cairo_stroke (cr);
cairo_translate (cr, -border_width, -border_width);
eek_outline_free (outline);
} }
static void static void
@ -276,7 +394,7 @@ render_key (EekRenderer *self,
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0); cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
cairo_paint (cr); cairo_paint (cr);
eek_renderer_get_foreground_color (self, priv->key_context, &foreground); eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
/* render icon (if any) */ /* render icon (if any) */
symbol = eek_key_get_symbol_with_fallback (key, 0, 0); symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol) if (!symbol)
@ -287,7 +405,7 @@ render_key (EekRenderer *self,
cairo_surface_t *icon_surface = cairo_surface_t *icon_surface =
eek_renderer_get_icon_surface (self, eek_renderer_get_icon_surface (self,
eek_symbol_get_icon_name (symbol), eek_symbol_get_icon_name (symbol),
16 / priv->scale, 16,
scale); scale);
if (icon_surface) { if (icon_surface) {
gint width = cairo_image_surface_get_width (icon_surface); gint width = cairo_image_surface_get_width (icon_surface);
@ -314,7 +432,7 @@ render_key (EekRenderer *self,
/* render label */ /* render label */
layout = pango_cairo_create_layout (cr); layout = pango_cairo_create_layout (cr);
eek_renderer_real_render_key_label (self, layout, key); eek_renderer_render_key_label (self, layout, key);
pango_layout_get_extents (layout, NULL, &extents); pango_layout_get_extents (layout, NULL, &extents);
cairo_save (cr); cairo_save (cr);
@ -334,21 +452,6 @@ render_key (EekRenderer *self,
g_object_unref (layout); g_object_unref (layout);
} }
/**
* eek_renderer_apply_transformation_for_key:
* @self: The renderer used to render the key
* @cr: The Cairo rendering context used for rendering
* @key: The key to be transformed
* @scale: The factor used to scale the key bounds before rendering
* @rotate: Whether to rotate the key by the angle defined for the key's
* in its section definition
*
* Applies a transformation, consisting of scaling and rotation, to the
* current rendering context using the bounds for the given key. The scale
* factor is separate to the normal scale factor for the keyboard as a whole
* and is applied cumulatively. It is typically used to render larger than
* normal keys for popups.
*/
void void
eek_renderer_apply_transformation_for_key (EekRenderer *self, eek_renderer_apply_transformation_for_key (EekRenderer *self,
cairo_t *cr, cairo_t *cr,
@ -378,6 +481,22 @@ eek_renderer_apply_transformation_for_key (EekRenderer *self,
} }
} }
static const TextProperty *
get_text_property_for_category (EekSymbolCategory category)
{
static const TextProperty props[EEK_SYMBOL_CATEGORY_LAST] = {
{ EEK_SYMBOL_CATEGORY_LETTER, FALSE, 1.0, FALSE },
{ EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
{ EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
};
for (uint i = 0; i < G_N_ELEMENTS(props); i++)
if (props[i].category == category)
return &props[i];
g_return_val_if_reached (NULL);
}
static void static void
eek_renderer_real_render_key_label (EekRenderer *self, eek_renderer_real_render_key_label (EekRenderer *self,
PangoLayout *layout, PangoLayout *layout,
@ -385,8 +504,10 @@ eek_renderer_real_render_key_label (EekRenderer *self,
{ {
EekRendererPrivate *priv = eek_renderer_get_instance_private (self); EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekSymbol *symbol; EekSymbol *symbol;
EekSymbolCategory category;
const gchar *label; const gchar *label;
EekBounds bounds; EekBounds bounds;
const TextProperty *prop;
PangoFontDescription *font; PangoFontDescription *font;
PangoLayoutLine *line; PangoLayoutLine *line;
gdouble scale; gdouble scale;
@ -402,7 +523,12 @@ eek_renderer_real_render_key_label (EekRenderer *self,
if (!priv->font) { if (!priv->font) {
const PangoFontDescription *base_font; const PangoFontDescription *base_font;
gdouble ascii_size, size; gdouble ascii_size, size;
EekThemeNode *theme_node;
theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
if (theme_node)
base_font = eek_theme_node_get_font (theme_node);
else
base_font = pango_context_get_font_description (priv->pcontext); base_font = pango_context_get_font_description (priv->pcontext);
// FIXME: Base font size on the same size unit used for button sizing, // FIXME: Base font size on the same size unit used for button sizing,
// and make the default about 1/3 of the current row height // and make the default about 1/3 of the current row height
@ -420,9 +546,15 @@ eek_renderer_real_render_key_label (EekRenderer *self,
scale = MIN((bounds.width - priv->border_width) / bounds.width, scale = MIN((bounds.width - priv->border_width) / bounds.width,
(bounds.height - priv->border_width) / bounds.height); (bounds.height - priv->border_width) / bounds.height);
font = pango_font_description_copy (priv->font); category = eek_symbol_get_category (symbol);
prop = get_text_property_for_category (category);
font = pango_font_description_copy (prop->ascii ?
priv->ascii_font :
priv->font);
pango_font_description_set_size (font, pango_font_description_set_size (font,
(gint)round(pango_font_description_get_size (font) * scale)); (gint)round(pango_font_description_get_size (font) *
prop->scale * scale));
pango_layout_set_font_description (layout, font); pango_layout_set_font_description (layout, font);
pango_font_description_free (font); pango_font_description_free (font);
@ -432,6 +564,8 @@ eek_renderer_real_render_key_label (EekRenderer *self,
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
pango_layout_set_width (layout, pango_layout_set_width (layout,
PANGO_SCALE * bounds.width * scale); PANGO_SCALE * bounds.width * scale);
if (prop->ellipses)
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
} }
static void static void
@ -447,17 +581,6 @@ eek_renderer_real_render_key_outline (EekRenderer *self,
cairo_restore (cr); cairo_restore (cr);
} }
/*
* eek_renderer_real_render_key:
* @self: The renderer used to render the key
* @cr: The Cairo rendering context used for rendering
* @key: The key to be transformed
* @scale: The factor used to scale the key bounds before rendering
* @rotate: Whether to rotate the key by the angle defined for the key's
* in its section definition
*
* Renders a key separately from the normal keyboard rendering.
*/
static void static void
eek_renderer_real_render_key (EekRenderer *self, eek_renderer_real_render_key (EekRenderer *self,
cairo_t *cr, cairo_t *cr,
@ -466,17 +589,9 @@ eek_renderer_real_render_key (EekRenderer *self,
gboolean rotate) gboolean rotate)
{ {
EekRendererPrivate *priv = eek_renderer_get_instance_private (self); EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekBounds bounds;
eek_renderer_get_key_bounds (self, key, &bounds, rotate);
cairo_save (cr); cairo_save (cr);
/* Because this function is called separately from the keyboard rendering
function, the transformation for the context needs to be set up */
cairo_translate (cr, priv->origin_x, priv->origin_y); cairo_translate (cr, priv->origin_x, priv->origin_y);
cairo_scale (cr, priv->scale, priv->scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate); eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate);
render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key)); render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key));
cairo_restore (cr); cairo_restore (cr);
@ -537,10 +652,6 @@ eek_renderer_set_property (GObject *object,
priv->pcontext = g_value_get_object (value); priv->pcontext = g_value_get_object (value);
g_object_ref (priv->pcontext); g_object_ref (priv->pcontext);
break; break;
case PROP_STYLE_CONTEXT:
priv->scontext = g_value_get_object (value);
g_object_ref (priv->scontext);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -612,6 +723,7 @@ eek_renderer_class_init (EekRendererClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec; GParamSpec *pspec;
klass->render_key_label = eek_renderer_real_render_key_label;
klass->render_key_outline = eek_renderer_real_render_key_outline; klass->render_key_outline = eek_renderer_real_render_key_outline;
klass->render_key = eek_renderer_real_render_key; klass->render_key = eek_renderer_real_render_key;
klass->render_keyboard = eek_renderer_real_render_keyboard; klass->render_keyboard = eek_renderer_real_render_keyboard;
@ -638,15 +750,6 @@ eek_renderer_class_init (EekRendererClass *klass)
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_PCONTEXT, PROP_PCONTEXT,
pspec); pspec);
pspec = g_param_spec_object ("style-context",
"GTK Style Context",
"GTK Style Context",
GTK_TYPE_STYLE_CONTEXT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_STYLE_CONTEXT,
pspec);
} }
static void static void
@ -684,24 +787,6 @@ eek_renderer_init (EekRenderer *self)
g_str_equal, g_str_equal,
g_free, g_free,
(GDestroyNotify)cairo_surface_destroy); (GDestroyNotify)cairo_surface_destroy);
/* 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");
/* Create a style context for keys */
priv->key_context = gtk_style_context_new ();
gtk_style_context_add_class (priv->key_context, "key");
gtk_style_context_add_provider (priv->key_context,
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
g_autoptr (GtkWidgetPath) path = NULL;
path = gtk_widget_path_new ();
gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
gtk_style_context_set_path (priv->key_context, path);
gtk_style_context_set_state (priv->key_context, GTK_STATE_FLAG_NORMAL);
} }
static void static void
@ -733,13 +818,11 @@ on_symbol_index_changed (EekKeyboard *keyboard,
EekRenderer * EekRenderer *
eek_renderer_new (EekKeyboard *keyboard, eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext, PangoContext *pcontext)
GtkStyleContext *scontext)
{ {
return g_object_new (EEK_TYPE_RENDERER, return g_object_new (EEK_TYPE_RENDERER,
"keyboard", keyboard, "keyboard", keyboard,
"pango-context", pcontext, "pango-context", pcontext,
"style-context", scontext,
NULL); NULL);
} }
@ -768,12 +851,13 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
scale = MIN(width / w, height / h); scale = MIN(width / w, height / h);
if (scale != priv->scale) {
priv->scale = scale; priv->scale = scale;
/* Set the rendering offset in widget coordinates to center the keyboard */ priv->origin_x = 0;
priv->origin_x = (width - (scale * w)) / 2; priv->origin_y = 0;
priv->origin_y = (height - (scale * h)) / 2;
invalidate (renderer); invalidate (renderer);
} }
}
void void
eek_renderer_get_size (EekRenderer *renderer, eek_renderer_get_size (EekRenderer *renderer,
@ -882,6 +966,18 @@ eek_renderer_create_pango_layout (EekRenderer *renderer)
return pango_layout_new (priv->pcontext); return pango_layout_new (priv->pcontext);
} }
void
eek_renderer_render_key_label (EekRenderer *renderer,
PangoLayout *layout,
EekKey *key)
{
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_KEY(key));
EEK_RENDERER_GET_CLASS(renderer)->
render_key_label (renderer, layout, key);
}
void void
eek_renderer_render_key_outline (EekRenderer *renderer, eek_renderer_render_key_outline (EekRenderer *renderer,
cairo_t *cr, cairo_t *cr,
@ -983,21 +1079,64 @@ eek_renderer_set_default_background_color (EekRenderer *renderer,
void void
eek_renderer_get_foreground_color (EekRenderer *renderer, eek_renderer_get_foreground_color (EekRenderer *renderer,
GtkStyleContext *context, EekElement *element,
EekColor *color) EekColor *color)
{ {
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer)); g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color); g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;
GdkRGBA gcolor;
gtk_style_context_get_color (context, flags, &gcolor); theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
color->red = gcolor.red; if (theme_node)
color->green = gcolor.green; eek_theme_node_get_foreground_color (theme_node, color);
color->blue = gcolor.blue; else
color->alpha = gcolor.alpha; memcpy (color, &priv->default_foreground_color,
sizeof(EekColor));
}
void
eek_renderer_get_background_color (EekRenderer *renderer,
EekElement *element,
EekColor *color)
{
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_background_color (theme_node, color);
else
memcpy (color, &priv->default_background_color,
sizeof(EekColor));
}
void
eek_renderer_get_background_gradient (EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end)
{
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (type);
g_return_if_fail (start);
g_return_if_fail (end);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_background_gradient (theme_node, type, start, end);
else
*type = EEK_GRADIENT_NONE;
} }
struct _FindKeyByPositionCallbackData { struct _FindKeyByPositionCallbackData {
@ -1048,7 +1187,6 @@ find_key_by_position_key_callback (EekElement *element,
if (b1 == b2 && b2 == b3) { if (b1 == b2 && b2 == b3) {
data->key = EEK_KEY(element); data->key = EEK_KEY(element);
if (eek_key_has_label(data->key))
return 0; return 0;
} }
@ -1058,7 +1196,6 @@ find_key_by_position_key_callback (EekElement *element,
if (b1 == b2 && b2 == b3) { if (b1 == b2 && b2 == b3) {
data->key = EEK_KEY(element); data->key = EEK_KEY(element);
if (eek_key_has_label(data->key))
return 0; return 0;
} }
@ -1086,15 +1223,6 @@ find_key_by_position_section_callback (EekElement *element,
return data->key ? 0 : -1; return data->key ? 0 : -1;
} }
/**
* eek_renderer_find_key_by_position:
* @renderer: The renderer normally used to render the key
* @x: The horizontal widget coordinate of the position to test for a key
* @y: The vertical widget coordinate of the position to test for a key
*
* Return value: the key located at the position x, y in widget coordinates, or
* NULL if no key can be found at that location
**/
EekKey * EekKey *
eek_renderer_find_key_by_position (EekRenderer *renderer, eek_renderer_find_key_by_position (EekRenderer *renderer,
gdouble x, gdouble x,
@ -1106,22 +1234,23 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL); g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
x /= priv->scale;
y /= priv->scale;
x -= priv->origin_x;
y -= priv->origin_y;
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
/* Transform from widget coordinates to keyboard coordinates */ if (x < bounds.x ||
x = (x - priv->origin_x)/priv->scale - bounds.x; y < bounds.y ||
y = (y - priv->origin_y)/priv->scale - bounds.y;
if (x < 0 ||
y < 0 ||
x > bounds.width || x > bounds.width ||
y > bounds.height) y > bounds.height)
return NULL; return NULL;
data.point.x = x; data.point.x = x;
data.point.y = y; data.point.y = y;
data.origin.x = 0; data.origin.x = bounds.x;
data.origin.y = 0; data.origin.y = bounds.y;
data.key = NULL; data.key = NULL;
data.renderer = renderer; data.renderer = renderer;
@ -1130,3 +1259,117 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
&data); &data);
return data.key; return data.key;
} }
struct _CreateThemeNodeData {
EekThemeContext *context;
EekThemeNode *parent;
EekRenderer *renderer;
};
typedef struct _CreateThemeNodeData CreateThemeNodeData;
void
create_theme_node_key_callback (EekElement *element,
gpointer user_data)
{
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
"active",
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node-pressed",
theme_node,
(GDestroyNotify)g_object_unref);
}
void
create_theme_node_section_callback (EekElement *element,
gpointer user_data)
{
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node, *parent;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_SECTION,
eek_element_get_name (element),
"section",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
parent = data->parent;
data->parent = theme_node;
eek_container_foreach_child (EEK_CONTAINER(element),
create_theme_node_key_callback,
data);
data->parent = parent;
}
void
eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme)
{
EekThemeContext *theme_context;
EekThemeNode *theme_node;
CreateThemeNodeData data;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_THEME(theme));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
g_return_if_fail (priv->keyboard);
if (priv->theme)
g_object_unref (priv->theme);
priv->theme = g_object_ref (theme);
theme_context = eek_theme_context_new ();
theme_node = eek_theme_node_new (theme_context,
NULL,
priv->theme,
EEK_TYPE_KEYBOARD,
"keyboard",
"keyboard",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(priv->keyboard),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
data.context = theme_context;
data.parent = theme_node;
data.renderer = renderer;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_theme_node_section_callback,
&data);
}

View File

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

View File

@ -61,7 +61,7 @@ typedef struct _EekRow EekRow;
typedef struct _EekSectionPrivate typedef struct _EekSectionPrivate
{ {
gint angle; gint angle;
EekRow row; GSList *rows;
EekModifierType modifiers; EekModifierType modifiers;
} EekSectionPrivate; } EekSectionPrivate;
@ -70,7 +70,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
static gint static gint
eek_section_real_get_n_rows (EekSection *self) 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 static void
@ -78,14 +80,13 @@ eek_section_real_add_row (EekSection *self,
gint num_columns, gint num_columns,
EekOrientation orientation) EekOrientation orientation)
{ {
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self); EekSectionPrivate *priv = eek_section_get_instance_private (self);
priv->row.num_columns = num_columns; EekRow *row;
priv->row.orientation = orientation;
/*
row = g_slice_new (EekRow); row = g_slice_new (EekRow);
row->num_columns = num_columns; row->num_columns = num_columns;
row->orientation = orientation; row->orientation = orientation;
priv->rows = g_slist_append (priv->rows, row);*/ priv->rows = g_slist_append (priv->rows, row);
} }
static void static void
@ -94,15 +95,16 @@ eek_section_real_get_row (EekSection *self,
gint *num_columns, gint *num_columns,
EekOrientation *orientation) EekOrientation *orientation)
{ {
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self); EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row = &priv->row; EekRow *row;
if (num_columns) {
row = g_slist_nth_data (priv->rows, index);
g_return_if_fail (row);
if (num_columns)
*num_columns = row->num_columns; *num_columns = row->num_columns;
} if (orientation)
if (orientation) {
*orientation = row->orientation; *orientation = row->orientation;
} }
}
static void static void
on_locked (EekKey *key, on_locked (EekKey *key,
@ -121,16 +123,28 @@ on_unlocked (EekKey *key,
static EekKey * static EekKey *
eek_section_real_create_key (EekSection *self, eek_section_real_create_key (EekSection *self,
const gchar *name, 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; num_rows = eek_section_get_n_rows (self);
row->num_columns++; g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY, 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, "name", name,
"keycode", keycode, "keycode", keycode,
"column", column_index,
"row", row_index,
NULL); NULL);
g_return_val_if_fail (key, NULL); g_return_val_if_fail (key, NULL);
@ -211,7 +225,12 @@ static void
eek_section_finalize (GObject *object) eek_section_finalize (GObject *object)
{ {
EekSection *self = EEK_SECTION (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); G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
} }
@ -456,12 +475,16 @@ eek_section_get_row (EekSection *section,
EekKey * EekKey *
eek_section_create_key (EekSection *section, eek_section_create_key (EekSection *section,
const gchar *name, const gchar *name,
gint keycode) gint keycode,
gint column,
gint row)
{ {
g_return_val_if_fail (EEK_IS_SECTION(section), NULL); g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section, return EEK_SECTION_GET_CLASS(section)->create_key (section,
name, name,
keycode); keycode,
column,
row);
} }
const double keyspacing = 4.0; const double keyspacing = 4.0;

View File

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

View File

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

View File

@ -36,19 +36,24 @@ EekSymbolMatrix *
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix) eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
{ {
EekSymbolMatrix *retval; 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 = g_slice_dup (EekSymbolMatrix, matrix);
retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols, retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
matrix->data); 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; return retval;
} }
void void
eek_symbol_matrix_free (EekSymbolMatrix *matrix) 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_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
g_slice_free (EekSymbolMatrix, matrix); 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 (group >= 0 && group < matrix->num_groups);
g_return_if_fail (level >= 0 && level < matrix->num_levels); 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); matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
} }

View File

@ -28,42 +28,270 @@
#include "config.h" #include "config.h"
#include "eek-symbol.h" #include "eek-symbol.h"
#include "eek-serializable.h"
#include "eek-enumtypes.h" #include "eek-enumtypes.h"
void enum {
eek_symbol_destroy (EekSymbol *priv) 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->name);
g_free (priv->label); g_free (priv->label);
g_free (priv->icon_name); g_free (priv->icon_name);
g_free (priv->tooltip); g_free (priv->tooltip);
g_free(priv->text); G_OBJECT_CLASS (eek_symbol_parent_class)->finalize (object);
g_free(priv);
} }
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 * EekSymbol *
eek_symbol_new (const gchar *name) eek_symbol_new (const gchar *name)
{ {
EekSymbol *self = g_new0(EekSymbol, 1); return g_object_new (EEK_TYPE_SYMBOL, "name", name, NULL);
eek_symbol_set_name(self, name);
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
return self;
} }
/**
* eek_symbol_set_name:
* @symbol: an #EekSymbol
* @name: name of the symbol
*
* Set the name of @symbol to @name.
*/
void void
eek_symbol_set_name (EekSymbol *symbol, eek_symbol_set_name (EekSymbol *symbol,
const gchar *name) const gchar *name)
{ {
g_free (symbol->name); g_return_if_fail (EEK_IS_SYMBOL(symbol));
symbol->name = g_strdup (name);
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 * const gchar *
eek_symbol_get_name (EekSymbol *symbol) 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 NULL;
return symbol->name; return priv->name;
} }
/** /**
@ -77,8 +305,12 @@ void
eek_symbol_set_label (EekSymbol *symbol, eek_symbol_set_label (EekSymbol *symbol,
const gchar *label) const gchar *label)
{ {
g_free (symbol->label); g_return_if_fail (EEK_IS_SYMBOL(symbol));
symbol->label = g_strdup (label);
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 * const gchar *
eek_symbol_get_label (EekSymbol *symbol) 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 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, eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask) 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 EekModifierType
eek_symbol_get_modifier_mask (EekSymbol *symbol) 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 gboolean
eek_symbol_is_modifier (EekSymbol *symbol) eek_symbol_is_modifier (EekSymbol *symbol)
{ {
return eek_symbol_get_modifier_mask (symbol) != 0; 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 void
eek_symbol_set_icon_name (EekSymbol *symbol, eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name) const gchar *icon_name)
{ {
g_free (symbol->icon_name); g_return_if_fail (EEK_IS_SYMBOL(symbol));
symbol->icon_name = g_strdup (icon_name);
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 * const gchar *
eek_symbol_get_icon_name (EekSymbol *symbol) 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 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 void
eek_symbol_set_tooltip (EekSymbol *symbol, eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip) const gchar *tooltip)
{ {
g_free (symbol->tooltip); g_return_if_fail (EEK_IS_SYMBOL(symbol));
symbol->tooltip = g_strdup (tooltip);
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 * const gchar *
eek_symbol_get_tooltip (EekSymbol *symbol) 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 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 EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
} EekSymbolCategory; } EekSymbolCategory;
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
typedef struct _EekSymbol /**
{ * EekSymbolClass:
/// Canonical name of the symbol */
gchar *name; struct _EekSymbolClass {
/// Text used to display the symbol /*< private >*/
gchar *label; GObjectClass parent_class;
EekSymbolCategory category; };
EekModifierType modifier_mask;
/// Icon name used to render the symbol
gchar *icon_name;
/// Tooltip text
gchar *tooltip;
// May not be present GType eek_symbol_get_type (void) G_GNUC_CONST;
guint xkeysym;
gchar *text;
} EekSymbol;
EekSymbol *eek_symbol_new (const gchar *name); EekSymbol *eek_symbol_new (const gchar *name);
void eek_symbol_free (EekSymbol *symbol);
void eek_symbol_set_name (EekSymbol *symbol, void eek_symbol_set_name (EekSymbol *symbol,
const gchar *name); const gchar *name);
const gchar *eek_symbol_get_name (EekSymbol *symbol); const gchar *eek_symbol_get_name (EekSymbol *symbol);

View File

@ -26,18 +26,160 @@
#include "config.h" #include "config.h"
#include "eek-text.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) eek_text_new (const gchar *text)
{ {
EekSymbol *ret = eek_symbol_new(""); return g_object_new (EEK_TYPE_TEXT,
eek_symbol_set_label(ret, text); "label", text,
ret->text = g_strdup (text); "category", EEK_SYMBOL_CATEGORY_FUNCTION,
return ret; "text", text,
NULL);
} }
/**
* eek_text_get_text:
* @text: an #EekText
*
* Get a text value associated with @text
*/
const gchar * 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 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; GType eek_text_get_type (void) G_GNUC_CONST;
EekSymbol *eek_text_new (const gchar *text); EekText *eek_text_new (const gchar *text);
const gchar *eek_text_get_text (EekSymbol *text); const gchar *eek_text_get_text (EekText *text);
G_END_DECLS 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 _EekSection EekSection;
typedef struct _EekKeyboard EekKeyboard; typedef struct _EekKeyboard EekKeyboard;
typedef struct _EekSymbol EekSymbol; typedef struct _EekSymbol EekSymbol;
typedef struct _EekKeysym EekKeysym;
typedef struct _EekText EekText; typedef struct _EekText EekText;
typedef struct _EekTheme EekTheme; typedef struct _EekTheme EekTheme;
typedef struct _EekThemeContext EekThemeContext; typedef struct _EekThemeContext EekThemeContext;

View File

@ -414,7 +414,9 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
data->key = eek_section_create_key (data->section, data->key = eek_section_create_key (data->section,
name, name,
keycode); keycode,
data->num_columns,
data->num_rows - 1);
attribute = get_attribute (attribute_names, attribute_values, attribute = get_attribute (attribute_names, attribute_values,
"oref"); "oref");
@ -566,6 +568,7 @@ struct _SymbolsParseData {
gchar *label; gchar *label;
gchar *icon; gchar *icon;
gchar *tooltip; gchar *tooltip;
EekSymbolCategory category;
guint keyval; guint keyval;
gint groups; gint groups;
}; };
@ -678,6 +681,13 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
"tooltip"); "tooltip");
if (attribute != NULL) if (attribute != NULL)
data->tooltip = g_strdup (attribute); 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: out:
@ -735,22 +745,21 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
EekSymbol *symbol; EekSymbol *symbol;
if (g_strcmp0 (element_name, "keysym") == 0) { if (g_strcmp0 (element_name, "keysym") == 0) {
EekSymbol *keysym; EekKeysym *keysym;
if (data->keyval != EEK_INVALID_KEYSYM) if (data->keyval != EEK_INVALID_KEYSYM)
keysym = eek_keysym_new (data->keyval); keysym = eek_keysym_new (data->keyval);
else else
keysym = eek_keysym_new_from_name (text); keysym = eek_keysym_new_from_name (text);
symbol = keysym; symbol = EEK_SYMBOL(keysym);
} else if (g_strcmp0 (element_name, "text") == 0) { } else if (g_strcmp0 (element_name, "text") == 0) {
symbol = eek_text_new (text); symbol = EEK_SYMBOL(eek_text_new (text));
} else { } else {
symbol = eek_symbol_new (text); symbol = eek_symbol_new (text);
eek_symbol_set_category (symbol, EEK_SYMBOL_CATEGORY_KEYNAME);
} }
if (data->label) { if (data->label) {
eek_symbol_set_label (symbol, 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); g_free (data->label);
data->label = NULL; data->label = NULL;
} }
@ -931,7 +940,6 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
return NULL; return NULL;
} }
/* Arrange the sections in the original coordinate system. */
eek_layout_place_sections(keyboard); eek_layout_place_sections(keyboard);
/* Use pre-defined modifier mask here. */ /* Use pre-defined modifier mask here. */

View File

@ -30,6 +30,7 @@
#include "eek-keysym.h" #include "eek-keysym.h"
#include "eek-text.h" #include "eek-text.h"
#include "eek-serializable.h" #include "eek-serializable.h"
#include "eek-theme.h"
void eek_init (void); void eek_init (void);

View File

@ -33,7 +33,7 @@ else:
table = dict() table = dict()
for line in in_stream: 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: if match:
table[int(match.group(1), 16)] = (match.group(2), match.group(3)) 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 index, (keysym, (l, c)) in enumerate([(keysym, table[keysym])
for keysym in sorted(table.keys())]): for keysym in sorted(table.keys())]):
sys.stdout.write(" { 0x%X, \"%s\" }" % sys.stdout.write(" { 0x%X, %s, %s }" %
(keysym, l)) (keysym, l, c))
if index < len(table) - 1: if index < len(table) - 1:
sys.stdout.write(",") sys.stdout.write(",")
sys.stdout.write("\n") sys.stdout.write("\n")

View File

@ -305,20 +305,10 @@ settings_update_layout(EekboardContextService *context)
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context); EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
switch (priv->purpose) { 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: case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("number"); keyboard_layout = g_strdup("number");
break; 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: default:
; ;
} }

View File

@ -35,6 +35,7 @@ enum {
ENABLED, ENABLED,
DISABLED, DISABLED,
DESTROYED, DESTROYED,
KEY_ACTIVATED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -80,6 +81,28 @@ eekboard_context_real_g_signal (GDBusProxy *self,
return; 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) { if (g_strcmp0 (signal_name, "VisibilityChanged") == 0) {
gboolean visible = FALSE; 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 static void
eekboard_context_get_property (GObject *object, eekboard_context_get_property (GObject *object,
guint prop_id, guint prop_id,
@ -155,6 +186,7 @@ eekboard_context_class_init (EekboardContextClass *klass)
klass->enabled = eekboard_context_real_enabled; klass->enabled = eekboard_context_real_enabled;
klass->disabled = eekboard_context_real_disabled; klass->disabled = eekboard_context_real_disabled;
klass->destroyed = eekboard_context_real_destroyed; klass->destroyed = eekboard_context_real_destroyed;
klass->key_activated = eekboard_context_real_key_activated;
proxy_class->g_signal = eekboard_context_real_g_signal; proxy_class->g_signal = eekboard_context_real_g_signal;
@ -208,6 +240,31 @@ eekboard_context_class_init (EekboardContextClass *klass)
G_TYPE_NONE, G_TYPE_NONE,
0); 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: * EekboardContext::destroyed:
* @context: an #EekboardContext * @context: an #EekboardContext

View File

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

View File

@ -48,6 +48,26 @@ int send_virtual_keyboard_key(
return 0; 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);
}
/* Finds the first key code for each modifier and saves it in modifier_keycodes */ /* Finds the first key code for each modifier and saves it in modifier_keycodes */
static void static void
update_modifier_info (SeatEmitter *client) update_modifier_info (SeatEmitter *client)
@ -84,13 +104,14 @@ update_modifier_info (SeatEmitter *client)
static void static void
send_fake_key (SeatEmitter *emitter, send_fake_key (SeatEmitter *emitter,
guint level, EekKeyboard *keyboard,
guint keycode, guint keycode,
guint keyboard_modifiers, guint keyboard_modifiers,
gboolean pressed, gboolean pressed,
uint32_t timestamp) uint32_t timestamp)
{ {
uint32_t proto_modifiers = 0; uint32_t proto_modifiers = 0;
guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
uint32_t group = (level / 2); uint32_t group = (level / 2);
if (keyboard_modifiers & EEK_SHIFT_MASK) if (keyboard_modifiers & EEK_SHIFT_MASK)
@ -101,38 +122,6 @@ send_fake_key (SeatEmitter *emitter,
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group); 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 void
emit_key_activated (EekboardContextService *manager, emit_key_activated (EekboardContextService *manager,
EekKeyboard *keyboard, EekKeyboard *keyboard,
@ -173,12 +162,5 @@ emit_key_activated (EekboardContextService *manager,
emitter.virtual_keyboard = manager->virtual_keyboard; emitter.virtual_keyboard = manager->virtual_keyboard;
emitter.keymap = keyboard->keymap; emitter.keymap = keyboard->keymap;
update_modifier_info (&emitter); update_modifier_info (&emitter);
send_fake_key (&emitter, keyboard, keycode, modifiers, pressed, timestamp);
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);
}
} }

View File

@ -16,7 +16,7 @@ add_project_arguments(
'-Werror=implicit-function-declaration', '-Werror=implicit-function-declaration',
'-Werror=implicit-fallthrough=3', '-Werror=implicit-fallthrough=3',
'-Werror=maybe-uninitialized', '-Werror=maybe-uninitialized',
'-Werror=missing-field-initializers', # '-Werror=missing-field-initializers', // fix eek-unicode-keysym-entries first
], ],
language: 'c' language: 'c'
) )

View File

@ -30,6 +30,9 @@ sources = [
'../eek/eek-symbol.c', '../eek/eek-symbol.c',
'../eek/eek-symbol-matrix.c', '../eek/eek-symbol-matrix.c',
'../eek/eek-text.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-types.c',
'../eek/eek-xml-layout.c', '../eek/eek-xml-layout.c',
'../eek/layersurface.c', '../eek/layersurface.c',

View File

@ -229,16 +229,24 @@ static void
make_widget (ServerContextService *context) make_widget (ServerContextService *context)
{ {
EekKeyboard *keyboard; EekKeyboard *keyboard;
EekTheme *theme;
if (context->widget) { if (context->widget) {
gtk_widget_destroy(context->widget); gtk_widget_destroy(context->widget);
context->widget = NULL; context->widget = NULL;
} }
theme = eek_theme_new ("resource:///sm/puri/squeekboard/style.css",
NULL,
NULL);
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context)); keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
context->widget = eek_gtk_keyboard_new (keyboard); 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_widget_set_has_tooltip (context->widget, TRUE);
gtk_container_add (GTK_CONTAINER(context->window), context->widget); gtk_container_add (GTK_CONTAINER(context->window), context->widget);
gtk_widget_show (context->widget); gtk_widget_show (context->widget);

View File

@ -32,16 +32,16 @@ test_create (void)
section = eek_keyboard_create_section (keyboard); section = eek_keyboard_create_section (keyboard);
g_assert (EEK_IS_SECTION(section)); g_assert (EEK_IS_SECTION(section));
eek_section_add_row (section, 2, EEK_ORIENTATION_HORIZONTAL); 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)); 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)); g_assert (EEK_IS_KEY(key1));
} }
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
g_test_init (&argc, &argv, NULL); gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/eek-simple-test/create", test_create); g_test_add_func ("/eek-simple-test/create", test_create);
return g_test_run (); return g_test_run ();
} }

View File

@ -47,7 +47,7 @@ test_output_parse (void)
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
g_test_init (&argc, &argv, NULL); gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/eek-xml-test/output-parse", test_output_parse); g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);

View File

@ -64,7 +64,7 @@ test_check_xkb (void)
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
g_test_init (&argc, &argv, NULL); gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb); g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb);