Compare commits
	
		
			112 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d5dc5c0ddf | |||
| 172ed08d40 | |||
| f27fade744 | |||
| 3085a10507 | |||
| b5f0aa423b | |||
| c8bc2c424f | |||
| 46fa6d4500 | |||
| 6002774f95 | |||
| f7f208883c | |||
| 5523b00442 | |||
| c81fdb18de | |||
| 778543c719 | |||
| 18b8972029 | |||
| fa31f8eee1 | |||
| 98a2e33d78 | |||
| 58d01bf502 | |||
| 8326bd7016 | |||
| d5f8b0d83b | |||
| e70a898af5 | |||
| df249646bc | |||
| 35ff93258e | |||
| c58d034494 | |||
| 8f1de46381 | |||
| 1846a67e83 | |||
| 35ac14806c | |||
| 4aee4915d9 | |||
| 5eeaa1c693 | |||
| 9b2fcf89e8 | |||
| e801a68f0d | |||
| ffc5628637 | |||
| 306aa89d06 | |||
| 236415cde4 | |||
| d49e0eaa1b | |||
| 107399a531 | |||
| 99a7786dc3 | |||
| d8f48cc48b | |||
| 2f0beb6d3a | |||
| 3ab3627ffe | |||
| 70895999c2 | |||
| ce311e1bf1 | |||
| e9cf572a3c | |||
| 943b2ad9f3 | |||
| f86bbb09f8 | |||
| 1246776328 | |||
| ea15f69e73 | |||
| 2e22bb5431 | |||
| a9a6e1d2b5 | |||
| 7e939c36cc | |||
| c5d2d76ab1 | |||
| 622ba6e38a | |||
| fad06348a7 | |||
| a6ee303123 | |||
| 4b66add65f | |||
| 79dce7c4c3 | |||
| aff71e0e33 | |||
| 9b10f56ba6 | |||
| 2391947b34 | |||
| e903150971 | |||
| 7495ec9bbb | |||
| e25d5a84b2 | |||
| 88ade4df1b | |||
| 00c3903672 | |||
| c801b17ba0 | |||
| 9ec8d62f3f | |||
| b1edcfcb1b | |||
| 54b0f59935 | |||
| 531b09f296 | |||
| e5b6d66d60 | |||
| a045810af6 | |||
| d68a8fef9a | |||
| 9162d4291f | |||
| 93d7699aa7 | |||
| 6eb63f6a4c | |||
| f6d4ca0387 | |||
| 7b41466a77 | |||
| 18c25084db | |||
| a5875402ef | |||
| f3ed1ba247 | |||
| 633d69baca | |||
| dbc8cc14bc | |||
| c65583b911 | |||
| 3d518b5757 | |||
| bfa72d7f61 | |||
| 373713ba54 | |||
| 068c325ee2 | |||
| 3b076e5e64 | |||
| 07d6e3a0f2 | |||
| 7690ef9a1a | |||
| 9974c385e5 | |||
| 8dafad80b1 | |||
| 93e9b2dde9 | |||
| c3a54595ea | |||
| 95ef52fe42 | |||
| c638c40a09 | |||
| 83d48d24ce | |||
| d807e43929 | |||
| 0a112be956 | |||
| 078efa2a6e | |||
| 5827827008 | |||
| f72ddc8129 | |||
| 7e9c3b40bb | |||
| a8371af9c0 | |||
| 4e11d071d9 | |||
| a7140705c4 | |||
| 69986132b4 | |||
| 3c97a3a592 | |||
| 268dda4da0 | |||
| 45f58a97b9 | |||
| bdbbaf6099 | |||
| 839968dc84 | |||
| fbdc5f4a93 | |||
| e5648a82a3 | 
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					.zanata-cache/
 | 
				
			||||||
 | 
					_build
 | 
				
			||||||
 | 
					TAGS
 | 
				
			||||||
 | 
					tags
 | 
				
			||||||
 | 
					vgdump
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					\#*#
 | 
				
			||||||
 | 
					.\#*
 | 
				
			||||||
@ -2,16 +2,30 @@ image: debian:buster
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
stages:
 | 
					stages:
 | 
				
			||||||
  - build
 | 
					  - build
 | 
				
			||||||
 | 
					  - test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tags: &tags
 | 
				
			||||||
 | 
					  tags:
 | 
				
			||||||
 | 
					    - librem5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
before_script:
 | 
					before_script:
 | 
				
			||||||
  - apt-get -y update
 | 
					  - apt-get -y update
 | 
				
			||||||
  - apt-get -y build-dep .
 | 
					  - apt-get -y build-dep .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
build_meson:
 | 
					build_meson:
 | 
				
			||||||
 | 
					  <<: *tags
 | 
				
			||||||
  stage: build
 | 
					  stage: build
 | 
				
			||||||
  tags:
 | 
					  artifacts:
 | 
				
			||||||
    - librem5
 | 
					    paths:
 | 
				
			||||||
 | 
					      - _build
 | 
				
			||||||
  script:
 | 
					  script:
 | 
				
			||||||
    - meson . _build/ -Ddepdatadir=/usr/share
 | 
					    - meson . _build/ -Ddepdatadir=/usr/share
 | 
				
			||||||
    - ninja -C _build install
 | 
					    - ninja -C _build install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test:
 | 
				
			||||||
 | 
					  <<: *tags
 | 
				
			||||||
 | 
					  stage: test
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    - build_meson
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    - xvfb-run -s -noreset ninja -C _build test
 | 
				
			||||||
 | 
				
			|||||||
@ -33,8 +33,8 @@ See `.gitlab-ci.yml`.
 | 
				
			|||||||
### Build from git repo
 | 
					### Build from git repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
$ git clone https://source.puri.sm/Librem5/eekboard.git
 | 
					$ git clone https://source.puri.sm/Librem5/squeekboard.git
 | 
				
			||||||
$ cd eekboard
 | 
					$ cd squeekboard
 | 
				
			||||||
$ mkdir ../build
 | 
					$ mkdir ../build
 | 
				
			||||||
$ meson ../build/
 | 
					$ meson ../build/
 | 
				
			||||||
$ cd ../build
 | 
					$ cd ../build
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"
 | 
					<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
 | 
				
			||||||
     version="1.1" viewBox="0 0 24 24">
 | 
					     version="1.1" viewBox="0 0 24 24">
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
    <path d="M 24,1 L 24,10 C 24,15 20,17 17,17 L 7,17 L 10,20 L 10,23
 | 
					    <path d="M 24,1 L 24,10 C 24,15 20,17 17,17 L 7,17 L 10,20 L 10,23
 | 
				
			||||||
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 388 B After Width: | Height: | Size: 388 B  | 
@ -1,6 +1,6 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"
 | 
					<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
 | 
				
			||||||
     version="1.1" viewBox="0 0 24 24">
 | 
					     version="1.1" viewBox="0 0 24 24">
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
    <path d="M 12,2 L 22,14 L 16,14 L 16,22 L 8,22 L 8,14 L 2,14 Z"
 | 
					    <path d="M 12,2 L 22,14 L 16,14 L 16,22 L 8,22 L 8,14 L 2,14 Z"
 | 
				
			||||||
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B  | 
@ -1,119 +1,120 @@
 | 
				
			|||||||
<?xml version="1.0"?>
 | 
					<?xml version="1.0"?>
 | 
				
			||||||
<geometry version="0.90">
 | 
					<geometry version="0.90">
 | 
				
			||||||
  <bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
 | 
					  <bounds x="10" y="10" width="410.0000" height="229"/>
 | 
				
			||||||
  <section angle="0">
 | 
					  <section angle="0">
 | 
				
			||||||
    <row orientation="1">
 | 
					    <row orientation="1">
 | 
				
			||||||
      <key keycode="24" name="AD01" oref="outline2" />
 | 
					      <key name="AD01" oref="outline2" />
 | 
				
			||||||
      <key keycode="25" name="AD02" oref="outline2" />
 | 
					      <key name="AD02" oref="outline2" />
 | 
				
			||||||
      <key keycode="26" name="AD03" oref="outline2" />
 | 
					      <key name="AD03" oref="outline2" />
 | 
				
			||||||
      <key keycode="27" name="AD04" oref="outline2" />
 | 
					      <key name="AD04" oref="outline2" />
 | 
				
			||||||
      <key keycode="28" name="AD05" oref="outline2" />
 | 
					      <key name="AD05" oref="outline2" />
 | 
				
			||||||
      <key keycode="29" name="AD06" oref="outline2" />
 | 
					      <key name="AD06" oref="outline2" />
 | 
				
			||||||
      <key keycode="30" name="AD07" oref="outline2" />
 | 
					      <key name="AD07" oref="outline2" />
 | 
				
			||||||
      <key keycode="31" name="AD08" oref="outline2" />
 | 
					      <key name="AD08" oref="outline2" />
 | 
				
			||||||
      <key keycode="32" name="AD09" oref="outline2" />
 | 
					      <key name="AD09" oref="outline2" />
 | 
				
			||||||
      <key keycode="33" name="AD10" oref="outline2" />
 | 
					      <key name="AD10" oref="outline2" />
 | 
				
			||||||
    </row>
 | 
					    </row>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
  <section angle="0">
 | 
					  <section angle="0">
 | 
				
			||||||
    <row orientation="1">
 | 
					    <row orientation="1">
 | 
				
			||||||
      <key keycode="38" name="AC01" oref="outline2" />
 | 
					      <key name="AC01" oref="outline2" />
 | 
				
			||||||
      <key keycode="39" name="AC02" oref="outline2" />
 | 
					      <key name="AC02" oref="outline2" />
 | 
				
			||||||
      <key keycode="40" name="AC03" oref="outline2" />
 | 
					      <key name="AC03" oref="outline2" />
 | 
				
			||||||
      <key keycode="41" name="AC04" oref="outline2" />
 | 
					      <key name="AC04" oref="outline2" />
 | 
				
			||||||
      <key keycode="42" name="AC05" oref="outline2" />
 | 
					      <key name="AC05" oref="outline2" />
 | 
				
			||||||
      <key keycode="43" name="AC06" oref="outline2" />
 | 
					      <key name="AC06" oref="outline2" />
 | 
				
			||||||
      <key keycode="44" name="AC07" oref="outline2" />
 | 
					      <key name="AC07" oref="outline2" />
 | 
				
			||||||
      <key keycode="45" name="AC08" oref="outline2" />
 | 
					      <key name="AC08" oref="outline2" />
 | 
				
			||||||
      <key keycode="46" name="AC09" oref="outline2" />
 | 
					      <key name="AC09" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC10" oref="outline2" />
 | 
				
			||||||
    </row>
 | 
					    </row>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
  <section angle="0">
 | 
					  <section angle="0">
 | 
				
			||||||
    <row orientation="1">
 | 
					    <row orientation="1">
 | 
				
			||||||
      <key keycode="50" name="LFSH" oref="altline" />
 | 
					      <key name="LFSH" oref="altline" />
 | 
				
			||||||
      <key keycode="52" name="AB01" oref="outline2" />
 | 
					      <key name="AB01" oref="outline2" />
 | 
				
			||||||
      <key keycode="53" name="AB02" oref="outline2" />
 | 
					      <key name="AB02" oref="outline2" />
 | 
				
			||||||
      <key keycode="54" name="AB03" oref="outline2" />
 | 
					      <key name="AB03" oref="outline2" />
 | 
				
			||||||
      <key keycode="55" name="AB04" oref="outline2" />
 | 
					      <key name="AB04" oref="outline2" />
 | 
				
			||||||
      <key keycode="56" name="AB05" oref="outline2" />
 | 
					      <key name="AB05" oref="outline2" />
 | 
				
			||||||
      <key keycode="57" name="AB06" oref="outline2" />
 | 
					      <key name="AB06" oref="outline2" />
 | 
				
			||||||
      <key keycode="58" name="AB07" oref="outline2" />
 | 
					      <key name="AB07" oref="outline2" />
 | 
				
			||||||
      <key keycode="22" name="BKSP" oref="altline" />
 | 
					      <key name="BKSP" oref="altline" />
 | 
				
			||||||
    </row>
 | 
					    </row>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
  <section angle="0">
 | 
					  <section angle="0">
 | 
				
			||||||
    <row orientation="1">
 | 
					    <row orientation="1">
 | 
				
			||||||
      <key keycode="0" name="ABC123" oref="altline" />
 | 
					      <key keycode="0" name="ABC123" oref="altline" />
 | 
				
			||||||
      <key keycode="150" name="I150" oref="altline" />
 | 
					      <key name="I149" oref="altline" />
 | 
				
			||||||
      <key keycode="65" name="SPCE" oref="spaceline" />
 | 
					      <key name="SPCE" oref="spaceline" />
 | 
				
			||||||
      <key keycode="60" name="AB09" oref="outline2" />
 | 
					      <key name="AB08" oref="outline2" />
 | 
				
			||||||
      <key keycode="36" name="RTRN" oref="outline7" />
 | 
					      <key name="RTRN" oref="outline7" />
 | 
				
			||||||
    </row>
 | 
					    </row>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
  <outline id="outline2" corner-radius="1.000000">
 | 
					  <outline id="outline2" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="37.46341" y="0.000000"/>
 | 
					    <point x="37.46341" y="0.000000"/>
 | 
				
			||||||
    <point x="37.46341" y="52.44877"/>
 | 
					    <point x="37.46341" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="altline" corner-radius="1.000000">
 | 
					  <outline id="altline" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="48.39024" y="0.000000"/>
 | 
					    <point x="48.39024" y="0.000000"/>
 | 
				
			||||||
    <point x="48.39024" y="52.44877"/>
 | 
					    <point x="48.39024" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline4" corner-radius="1.000000">
 | 
					  <outline id="outline4" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="59.31707" y="0.000000"/>
 | 
					    <point x="59.31707" y="0.000000"/>
 | 
				
			||||||
    <point x="59.31707" y="52.44877"/>
 | 
					    <point x="59.31707" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline5" corner-radius="1.000000">
 | 
					  <outline id="outline5" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="59.31707" y="0.000000"/>
 | 
					    <point x="59.31707" y="0.000000"/>
 | 
				
			||||||
    <point x="59.31707" y="52.44877"/>
 | 
					    <point x="59.31707" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline6" corner-radius="1.000000">
 | 
					  <outline id="outline6" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="68.68292" y="0.000000"/>
 | 
					    <point x="68.68292" y="0.000000"/>
 | 
				
			||||||
    <point x="68.68292" y="52.44877"/>
 | 
					    <point x="68.68292" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline7" corner-radius="1.000000">
 | 
					  <outline id="outline7" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="88.97561" y="0.000000"/>
 | 
					    <point x="88.97561" y="0.000000"/>
 | 
				
			||||||
    <point x="88.97561" y="52.44877"/>
 | 
					    <point x="88.97561" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline8" corner-radius="1.000000">
 | 
					  <outline id="outline8" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="88.97561" y="0.000000"/>
 | 
					    <point x="88.97561" y="0.000000"/>
 | 
				
			||||||
    <point x="88.97561" y="52.44877"/>
 | 
					    <point x="88.97561" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline9" corner-radius="1.000000">
 | 
					  <outline id="outline9" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="109.2682" y="0.000000"/>
 | 
					    <point x="109.2682" y="0.000000"/>
 | 
				
			||||||
    <point x="109.2682" y="52.44877"/>
 | 
					    <point x="109.2682" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline10" corner-radius="1.000000">
 | 
					  <outline id="outline10" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="37.46341" y="0.000000"/>
 | 
					    <point x="37.46341" y="0.000000"/>
 | 
				
			||||||
    <point x="37.46341" y="52.44877"/>
 | 
					    <point x="37.46341" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="outline13" corner-radius="1.000000">
 | 
					  <outline id="outline13" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="79.60975" y="0.000000"/>
 | 
					    <point x="79.60975" y="0.000000"/>
 | 
				
			||||||
    <point x="79.60975" y="52.44877"/>
 | 
					    <point x="79.60975" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
  <outline id="spaceline" corner-radius="1.000000">
 | 
					  <outline id="spaceline" corner-radius="1.000000">
 | 
				
			||||||
    <point x="0.000000" y="0.000000"/>
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
    <point x="150.5853" y="0.000000"/>
 | 
					    <point x="150.5853" y="0.000000"/>
 | 
				
			||||||
    <point x="150.5853" y="52.44877"/>
 | 
					    <point x="150.5853" y="52"/>
 | 
				
			||||||
    <point x="0.000000" y="52.44877"/>
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
  </outline>
 | 
					  </outline>
 | 
				
			||||||
</geometry>
 | 
					</geometry>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										122
									
								
								data/keyboards/geometry/extended.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								data/keyboards/geometry/extended.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					<?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="AD11" oref="outline2" />
 | 
				
			||||||
 | 
					    </row>
 | 
				
			||||||
 | 
					  </section>
 | 
				
			||||||
 | 
					  <section angle="0">
 | 
				
			||||||
 | 
					    <row orientation="1">
 | 
				
			||||||
 | 
					      <key name="AC01" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC02" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC03" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC04" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC05" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC06" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC07" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC08" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC09" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC10" oref="outline2" />
 | 
				
			||||||
 | 
					      <key name="AC11" oref="outline2" />
 | 
				
			||||||
 | 
					    </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="32" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="32" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="altline" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="48.39024" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="48.39024" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline4" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="59.31707" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="59.31707" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline5" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="59.31707" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="59.31707" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline6" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="68.68292" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="68.68292" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline7" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="88.97561" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="88.97561" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline8" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="88.97561" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="88.97561" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline9" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="109.2682" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="109.2682" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline10" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="37.46341" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="37.46341" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="outline13" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="79.60975" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="79.60975" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					  <outline id="spaceline" corner-radius="1.000000">
 | 
				
			||||||
 | 
					    <point x="0.000000" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="150.5853" y="0.000000"/>
 | 
				
			||||||
 | 
					    <point x="150.5853" y="52"/>
 | 
				
			||||||
 | 
					    <point x="0.000000" y="52"/>
 | 
				
			||||||
 | 
					  </outline>
 | 
				
			||||||
 | 
					</geometry>
 | 
				
			||||||
							
								
								
									
										105
									
								
								data/keyboards/geometry/number-keypad.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								data/keyboards/geometry/number-keypad.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					<?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>
 | 
				
			||||||
@ -24,6 +24,9 @@
 | 
				
			|||||||
  <keyboard id="my" name="my"
 | 
					  <keyboard id="my" name="my"
 | 
				
			||||||
	    geometry="compact" symbols="my"
 | 
						    geometry="compact" symbols="my"
 | 
				
			||||||
	    longname="Myanmar" language="my"/>
 | 
						    longname="Myanmar" language="my"/>
 | 
				
			||||||
 | 
					  <keyboard id="nb" name="nb"
 | 
				
			||||||
 | 
						    geometry="extended" symbols="nb"
 | 
				
			||||||
 | 
						    longname="Norwegian" language="nb"/>
 | 
				
			||||||
  <keyboard id="ru" name="ru"
 | 
					  <keyboard id="ru" name="ru"
 | 
				
			||||||
	    geometry="compact" symbols="us"
 | 
						    geometry="compact" symbols="us"
 | 
				
			||||||
	    longname="Russian" language="ru"/>
 | 
						    longname="Russian" language="ru"/>
 | 
				
			||||||
@ -85,4 +88,13 @@
 | 
				
			|||||||
  <keyboard id="te-inscript" name="te-inscript"
 | 
					  <keyboard id="te-inscript" name="te-inscript"
 | 
				
			||||||
	    geometry="compact" symbols="te-inscript"
 | 
						    geometry="compact" symbols="te-inscript"
 | 
				
			||||||
	    longname="Telugu (Inscript)" language="te"/>
 | 
						    longname="Telugu (Inscript)" language="te"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- Common keyboards -->
 | 
				
			||||||
 | 
					  <keyboard id="number" name="number"
 | 
				
			||||||
 | 
						    geometry="number-keypad" symbols="special/number"
 | 
				
			||||||
 | 
						    longname="Numeric keypad" language="all"/>
 | 
				
			||||||
 | 
					  <keyboard id="phone" name="phone"
 | 
				
			||||||
 | 
						    geometry="number-keypad" symbols="special/number"
 | 
				
			||||||
 | 
						    longname="Phone keypad" language="all"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</keyboards>
 | 
					</keyboards>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										206
									
								
								data/keyboards/symbols/nb.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								data/keyboards/symbols/nb.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,206 @@
 | 
				
			|||||||
 | 
					<?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="1">1</symbol>
 | 
				
			||||||
 | 
					    <symbol label="~">asciitilde</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD02">
 | 
				
			||||||
 | 
					    <symbol label="w">w</symbol>
 | 
				
			||||||
 | 
					    <symbol label="W">W</symbol>
 | 
				
			||||||
 | 
					    <symbol label="2">2</symbol>
 | 
				
			||||||
 | 
					    <symbol label="`">quoteleft</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD03">
 | 
				
			||||||
 | 
					    <symbol label="e">e</symbol>
 | 
				
			||||||
 | 
					    <symbol label="E">E</symbol>
 | 
				
			||||||
 | 
					    <symbol label="3">3</symbol>
 | 
				
			||||||
 | 
					    <symbol label="|">bar</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD04">
 | 
				
			||||||
 | 
					    <symbol label="r">r</symbol>
 | 
				
			||||||
 | 
					    <symbol label="R">R</symbol>
 | 
				
			||||||
 | 
					    <symbol label="4">4</symbol>
 | 
				
			||||||
 | 
					    <symbol label="·">U00B7</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD05">
 | 
				
			||||||
 | 
					    <symbol label="t">t</symbol>
 | 
				
			||||||
 | 
					    <symbol label="T">T</symbol>
 | 
				
			||||||
 | 
					    <symbol label="5">5</symbol>
 | 
				
			||||||
 | 
					    <symbol label="√">squareroot</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD06">
 | 
				
			||||||
 | 
					    <symbol label="y">y</symbol>
 | 
				
			||||||
 | 
					    <symbol label="Y">Y</symbol>
 | 
				
			||||||
 | 
					    <symbol label="6">6</symbol>
 | 
				
			||||||
 | 
					    <symbol label="π">Greek_pi</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD07">
 | 
				
			||||||
 | 
					    <symbol label="u">u</symbol>
 | 
				
			||||||
 | 
					    <symbol label="U">U</symbol>
 | 
				
			||||||
 | 
					    <symbol label="7">7</symbol>
 | 
				
			||||||
 | 
					    <symbol label="÷">division</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD08">
 | 
				
			||||||
 | 
					    <symbol label="i">i</symbol>
 | 
				
			||||||
 | 
					    <symbol label="I">I</symbol>
 | 
				
			||||||
 | 
					    <symbol label="8">8</symbol>
 | 
				
			||||||
 | 
					    <symbol label="×">multiply</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD09">
 | 
				
			||||||
 | 
					    <symbol label="o">o</symbol>
 | 
				
			||||||
 | 
					    <symbol label="O">O</symbol>
 | 
				
			||||||
 | 
					    <symbol label="9">9</symbol>
 | 
				
			||||||
 | 
					    <symbol label="¶">paragraph</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD10">
 | 
				
			||||||
 | 
					    <symbol label="p">p</symbol>
 | 
				
			||||||
 | 
					    <symbol label="P">P</symbol>
 | 
				
			||||||
 | 
					    <symbol label="0">0</symbol>
 | 
				
			||||||
 | 
					    <symbol label="△">U25B3</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AD11">
 | 
				
			||||||
 | 
					    <symbol keyval="229" label="å">aring</symbol>
 | 
				
			||||||
 | 
					    <symbol keyval="197" label="Å">Aring</symbol>
 | 
				
			||||||
 | 
					    <symbol label=""></symbol>
 | 
				
			||||||
 | 
					    <symbol label=""></symbol>
 | 
				
			||||||
 | 
					    <!-- Empty labels cause keys to be hidden when the level they are defined
 | 
				
			||||||
 | 
					         for is shown. -->
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC01">
 | 
				
			||||||
 | 
					    <symbol label="a">a</symbol>
 | 
				
			||||||
 | 
					    <symbol label="A">A</symbol>
 | 
				
			||||||
 | 
					    <symbol label="@">at</symbol>
 | 
				
			||||||
 | 
					    <symbol label="©">copyright</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC02">
 | 
				
			||||||
 | 
					    <symbol label="s">s</symbol>
 | 
				
			||||||
 | 
					    <symbol label="S">S</symbol>
 | 
				
			||||||
 | 
					    <symbol label="#">numbersign</symbol>
 | 
				
			||||||
 | 
					    <symbol label="®">U00AE</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC03">
 | 
				
			||||||
 | 
					    <symbol label="d">d</symbol>
 | 
				
			||||||
 | 
					    <symbol label="D">D</symbol>
 | 
				
			||||||
 | 
					    <symbol label="$">dollar</symbol>
 | 
				
			||||||
 | 
					    <symbol label="£">U00A3</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC04">
 | 
				
			||||||
 | 
					    <symbol label="f">f</symbol>
 | 
				
			||||||
 | 
					    <symbol label="F">F</symbol>
 | 
				
			||||||
 | 
					    <symbol label="%">percent</symbol>
 | 
				
			||||||
 | 
					    <symbol label="€">EuroSign</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC05">
 | 
				
			||||||
 | 
					    <symbol label="g">g</symbol>
 | 
				
			||||||
 | 
					    <symbol label="G">G</symbol>
 | 
				
			||||||
 | 
					    <symbol label="&">ampersand</symbol>
 | 
				
			||||||
 | 
					    <symbol label="¥">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="°">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 keyval="248" label="ø">oslash</symbol>
 | 
				
			||||||
 | 
					    <symbol keyval="216" label="Ø">Oslash</symbol>
 | 
				
			||||||
 | 
					    <symbol label=")">parenright</symbol>
 | 
				
			||||||
 | 
					    <symbol label="}">braceright</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AC11">
 | 
				
			||||||
 | 
					    <symbol keyval="230" label="æ">ae</symbol>
 | 
				
			||||||
 | 
					    <symbol keyval="198" label="Æ">AE</symbol>
 | 
				
			||||||
 | 
					    <symbol label=""></symbol>
 | 
				
			||||||
 | 
					    <symbol label=""></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="=/+">Shift_L</keysym>
 | 
				
			||||||
 | 
					    <keysym keyval="65505" label="123">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=""">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="<">less</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="AB04">
 | 
				
			||||||
 | 
					    <symbol label="v">v</symbol>
 | 
				
			||||||
 | 
					    <symbol label="V">V</symbol>
 | 
				
			||||||
 | 
					    <symbol label=":">colon</symbol>
 | 
				
			||||||
 | 
					    <symbol label=">">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="123">show-numbers</symbol>
 | 
				
			||||||
 | 
					    <symbol label="123">show-numbers</symbol>
 | 
				
			||||||
 | 
					    <symbol label="ABC">show-letters</symbol>
 | 
				
			||||||
 | 
					    <symbol label="ABC">show-letters</symbol>
 | 
				
			||||||
 | 
					  </key>
 | 
				
			||||||
 | 
					  <key name="I149">
 | 
				
			||||||
 | 
					    <symbol 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>
 | 
				
			||||||
 | 
					</symbols>
 | 
				
			||||||
							
								
								
									
										60
									
								
								data/keyboards/symbols/special/number.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								data/keyboards/symbols/special/number.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					<?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>
 | 
				
			||||||
@ -1,276 +1,194 @@
 | 
				
			|||||||
<?xml version="1.0"?>
 | 
					<?xml version='1.0' encoding='ASCII' standalone='yes'?>
 | 
				
			||||||
<symbols version="0.90">
 | 
					<symbols version="0.90">
 | 
				
			||||||
  <key keycode="9" name="ESC">
 | 
					  <key name="AD01">
 | 
				
			||||||
    <keysym keyval="65307">Escape</keysym>
 | 
					    <symbol label="q">q</symbol>
 | 
				
			||||||
 | 
					    <symbol label="Q">Q</symbol>
 | 
				
			||||||
 | 
					    <symbol label="1">1</symbol>
 | 
				
			||||||
 | 
					    <symbol label="~">asciitilde</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="67" name="FK01">
 | 
					  <key name="AD02">
 | 
				
			||||||
    <keysym keyval="65470">F1</keysym>
 | 
					    <symbol label="w">w</symbol>
 | 
				
			||||||
 | 
					    <symbol label="W">W</symbol>
 | 
				
			||||||
 | 
					    <symbol label="2">2</symbol>
 | 
				
			||||||
 | 
					    <symbol label="`">quoteleft</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="68" name="FK02">
 | 
					  <key name="AD03">
 | 
				
			||||||
    <keysym keyval="65471">F2</keysym>
 | 
					    <symbol label="e">e</symbol>
 | 
				
			||||||
 | 
					    <symbol label="E">E</symbol>
 | 
				
			||||||
 | 
					    <symbol label="3">3</symbol>
 | 
				
			||||||
 | 
					    <symbol label="|">bar</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="69" name="FK03">
 | 
					  <key name="AD04">
 | 
				
			||||||
    <keysym keyval="65472">F3</keysym>
 | 
					    <symbol label="r">r</symbol>
 | 
				
			||||||
 | 
					    <symbol label="R">R</symbol>
 | 
				
			||||||
 | 
					    <symbol label="4">4</symbol>
 | 
				
			||||||
 | 
					    <symbol label="·">U00B7</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="70" name="FK04">
 | 
					  <key name="AD05">
 | 
				
			||||||
    <keysym keyval="65473">F4</keysym>
 | 
					    <symbol label="t">t</symbol>
 | 
				
			||||||
 | 
					    <symbol label="T">T</symbol>
 | 
				
			||||||
 | 
					    <symbol label="5">5</symbol>
 | 
				
			||||||
 | 
					    <symbol label="√">squareroot</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="71" name="FK05">
 | 
					  <key name="AD06">
 | 
				
			||||||
    <keysym keyval="65474">F5</keysym>
 | 
					    <symbol label="y">y</symbol>
 | 
				
			||||||
 | 
					    <symbol label="Y">Y</symbol>
 | 
				
			||||||
 | 
					    <symbol label="6">6</symbol>
 | 
				
			||||||
 | 
					    <symbol label="π">Greek_pi</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="72" name="FK06">
 | 
					  <key name="AD07">
 | 
				
			||||||
    <keysym keyval="65475">F6</keysym>
 | 
					    <symbol label="u">u</symbol>
 | 
				
			||||||
 | 
					    <symbol label="U">U</symbol>
 | 
				
			||||||
 | 
					    <symbol label="7">7</symbol>
 | 
				
			||||||
 | 
					    <symbol label="÷">division</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="73" name="FK07">
 | 
					  <key name="AD08">
 | 
				
			||||||
    <keysym keyval="65476">F7</keysym>
 | 
					    <symbol label="i">i</symbol>
 | 
				
			||||||
 | 
					    <symbol label="I">I</symbol>
 | 
				
			||||||
 | 
					    <symbol label="8">8</symbol>
 | 
				
			||||||
 | 
					    <symbol label="×">multiply</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="74" name="FK08">
 | 
					  <key name="AD09">
 | 
				
			||||||
    <keysym keyval="65477">F8</keysym>
 | 
					    <symbol label="o">o</symbol>
 | 
				
			||||||
 | 
					    <symbol label="O">O</symbol>
 | 
				
			||||||
 | 
					    <symbol label="9">9</symbol>
 | 
				
			||||||
 | 
					    <symbol label="¶">paragraph</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="75" name="FK09">
 | 
					  <key name="AD10">
 | 
				
			||||||
    <keysym keyval="65478">F9</keysym>
 | 
					    <symbol label="p">p</symbol>
 | 
				
			||||||
 | 
					    <symbol label="P">P</symbol>
 | 
				
			||||||
 | 
					    <symbol label="0">0</symbol>
 | 
				
			||||||
 | 
					    <symbol label="△">U25B3</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="76" name="FK10">
 | 
					  <key name="AC01">
 | 
				
			||||||
    <keysym keyval="65479">F10</keysym>
 | 
					    <symbol label="a">a</symbol>
 | 
				
			||||||
 | 
					    <symbol label="A">A</symbol>
 | 
				
			||||||
 | 
					    <symbol label="@">at</symbol>
 | 
				
			||||||
 | 
					    <symbol label="©">copyright</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="95" name="FK11">
 | 
					  <key name="AC02">
 | 
				
			||||||
    <keysym keyval="65480">F11</keysym>
 | 
					    <symbol label="s">s</symbol>
 | 
				
			||||||
 | 
					    <symbol label="S">S</symbol>
 | 
				
			||||||
 | 
					    <symbol label="#">numbersign</symbol>
 | 
				
			||||||
 | 
					    <symbol label="®">U00AE</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="96" name="FK12">
 | 
					  <key name="AC03">
 | 
				
			||||||
    <keysym keyval="65481">F12</keysym>
 | 
					    <symbol label="d">d</symbol>
 | 
				
			||||||
 | 
					    <symbol label="D">D</symbol>
 | 
				
			||||||
 | 
					    <symbol label="$">dollar</symbol>
 | 
				
			||||||
 | 
					    <symbol label="£">U00A3</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="22" name="BKSP">
 | 
					  <key name="AC04">
 | 
				
			||||||
    <keysym keyval="65288" icon="edit-clear-symbolic">backspace</keysym>
 | 
					    <symbol label="f">f</symbol>
 | 
				
			||||||
 | 
					    <symbol label="F">F</symbol>
 | 
				
			||||||
 | 
					    <symbol label="%">percent</symbol>
 | 
				
			||||||
 | 
					    <symbol label="€">EuroSign</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="23" name="TAB">
 | 
					  <key name="AC05">
 | 
				
			||||||
    <keysym keyval="65289">Tab</keysym>
 | 
					    <symbol label="g">g</symbol>
 | 
				
			||||||
    <keysym keyval="65056">ISO_Left_Tab</keysym>
 | 
					    <symbol label="G">G</symbol>
 | 
				
			||||||
 | 
					    <symbol label="&">ampersand</symbol>
 | 
				
			||||||
 | 
					    <symbol label="¥">U00A5</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="24" name="AD01">
 | 
					  <key name="AC06">
 | 
				
			||||||
    <keysym keyval="113">q</keysym>
 | 
					    <symbol label="h">h</symbol>
 | 
				
			||||||
    <keysym keyval="81">Q</keysym>
 | 
					    <symbol label="H">H</symbol>
 | 
				
			||||||
    <keysym keyval="49">1</keysym>
 | 
					    <symbol label="-">minus</symbol>
 | 
				
			||||||
    <keysym keyval="126">asciitilde</keysym>
 | 
					    <symbol label="^">asciicircum</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="25" name="AD02">
 | 
					  <key name="AC07">
 | 
				
			||||||
    <keysym keyval="119">w</keysym>
 | 
					    <symbol label="j">j</symbol>
 | 
				
			||||||
    <keysym keyval="87">W</keysym>
 | 
					    <symbol label="J">J</symbol>
 | 
				
			||||||
    <keysym keyval="50">2</keysym>
 | 
					    <symbol label="_">underscore</symbol>
 | 
				
			||||||
    <keysym keyval="96">quoteleft</keysym>
 | 
					    <symbol label="°">degree</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="26" name="AD03">
 | 
					  <key name="AC08">
 | 
				
			||||||
    <keysym keyval="101">e</keysym>
 | 
					    <symbol label="k">k</symbol>
 | 
				
			||||||
    <keysym keyval="69">E</keysym>
 | 
					    <symbol label="K">K</symbol>
 | 
				
			||||||
    <keysym keyval="51">3</keysym>
 | 
					    <symbol label="+">plus</symbol>
 | 
				
			||||||
    <keysym keyval="124">bar</keysym>
 | 
					    <symbol label="=">equal</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="27" name="AD04">
 | 
					  <key name="AC09">
 | 
				
			||||||
    <keysym keyval="114">r</keysym>
 | 
					    <symbol label="l">l</symbol>
 | 
				
			||||||
    <keysym keyval="82">R</keysym>
 | 
					    <symbol label="L">L</symbol>
 | 
				
			||||||
    <keysym keyval="52">4</keysym>
 | 
					    <symbol label="(">parenleft</symbol>
 | 
				
			||||||
    <keysym keyval="183">middledot</keysym>
 | 
					    <symbol label="{">braceleft</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="28" name="AD05">
 | 
					  <key name="AC10">
 | 
				
			||||||
    <keysym keyval="116">t</keysym>
 | 
					    <!-- Empty labels cause keys to be hidden when the level they are defined
 | 
				
			||||||
    <keysym keyval="84">T</keysym>
 | 
					         for is shown. -->
 | 
				
			||||||
    <keysym keyval="53">5</keysym>
 | 
					    <symbol label=""></symbol>
 | 
				
			||||||
 | 
					    <symbol label=""></symbol>
 | 
				
			||||||
 | 
					    <symbol label=")">parenright</symbol>
 | 
				
			||||||
 | 
					    <symbol label="}">braceright</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="29" name="AD06">
 | 
					  <key name="RTRN">
 | 
				
			||||||
    <keysym keyval="121">y</keysym>
 | 
					    <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
				
			||||||
    <keysym keyval="89">Y</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="54">6</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="30" name="AD07">
 | 
					  <key name="LFSH">
 | 
				
			||||||
    <keysym keyval="117">u</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="85">U</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="55">7</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="31" name="AD08">
 | 
					 | 
				
			||||||
    <keysym keyval="105">i</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="73">I</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="56">8</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="32" name="AD09">
 | 
					 | 
				
			||||||
    <keysym keyval="111">o</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="79">O</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="57">9</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="33" name="AD10">
 | 
					 | 
				
			||||||
    <keysym keyval="112">p</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="80">P</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="48">0</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="34" name="AD11">
 | 
					 | 
				
			||||||
    <keysym keyval="91">bracketleft</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="123">braceleft</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="35" name="AD12">
 | 
					 | 
				
			||||||
    <keysym keyval="93">bracketright</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="125">braceright</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="51" name="BKSL">
 | 
					 | 
				
			||||||
    <keysym keyval="92">backslash</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="124">bar</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="0" name="ABC123">
 | 
					 | 
				
			||||||
    <symbol label="123">show-numbers</symbol>
 | 
					 | 
				
			||||||
    <symbol label="123">show-numbers</symbol>
 | 
					 | 
				
			||||||
    <symbol label="ABC">show-letters</symbol>
 | 
					 | 
				
			||||||
    <symbol label="ABC">show-letters</symbol>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="38" name="AC01">
 | 
					 | 
				
			||||||
    <keysym keyval="97">a</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="65">A</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="64">at</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="169">copyright</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="39" name="AC02">
 | 
					 | 
				
			||||||
    <keysym keyval="115">s</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="83">S</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="35">numbersign</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="174">registeredtrademark</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="40" name="AC03">
 | 
					 | 
				
			||||||
    <keysym keyval="100">d</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="68">D</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="36">dollar</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="163">poundsign</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="41" name="AC04">
 | 
					 | 
				
			||||||
    <keysym keyval="102">f</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="70">F</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="37">percent</keysym>
 | 
					 | 
				
			||||||
    <text>€</text>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="42" name="AC05">
 | 
					 | 
				
			||||||
    <keysym keyval="103">g</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="71">G</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="38">ampersand</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="165">yensign</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="43" name="AC06">
 | 
					 | 
				
			||||||
    <keysym keyval="104">h</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="72">H</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="45">minus</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="94">asciicircum</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="44" name="AC07">
 | 
					 | 
				
			||||||
    <keysym keyval="106">j</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="74">J</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="43">plus</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="176">degreesign</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="45" name="AC08">
 | 
					 | 
				
			||||||
    <keysym keyval="107">k</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="75">K</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="40">parenleft</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="123">braceleft</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="46" name="AC09">
 | 
					 | 
				
			||||||
    <keysym keyval="108">l</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="76">L</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="41">parenright</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="125">braceright</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="47" name="AC10">
 | 
					 | 
				
			||||||
    <keysym keyval="59">semicolon</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="58">colon</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="48" name="AC11">
 | 
					 | 
				
			||||||
    <keysym keyval="39">quoteright</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="34">quotedbl</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="36" name="RTRN">
 | 
					 | 
				
			||||||
    <keysym keyval="65293" icon="key-enter">Return</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="50" name="LFSH">
 | 
					 | 
				
			||||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
					    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
				
			||||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
					    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
				
			||||||
    <keysym keyval="65505" label="=/+">Shift_L</keysym>
 | 
					    <keysym keyval="65505" label="=/+">Shift_L</keysym>
 | 
				
			||||||
    <keysym keyval="65505" label="123">Shift_L</keysym>
 | 
					    <keysym keyval="65505" label="123">Shift_L</keysym>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="52" name="AB01">
 | 
					  <key name="AB01">
 | 
				
			||||||
    <keysym keyval="122">z</keysym>
 | 
					    <symbol label="z">z</symbol>
 | 
				
			||||||
    <keysym keyval="90">Z</keysym>
 | 
					    <symbol label="Z">Z</symbol>
 | 
				
			||||||
    <keysym keyval="44">comma</keysym>
 | 
					    <symbol label=",">comma</symbol>
 | 
				
			||||||
    <keysym keyval="92">backslash</keysym>
 | 
					    <symbol label="\">backslash</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="53" name="AB02">
 | 
					  <key name="AB02">
 | 
				
			||||||
    <keysym keyval="120">x</keysym>
 | 
					    <symbol label="x">x</symbol>
 | 
				
			||||||
    <keysym keyval="88">X</keysym>
 | 
					    <symbol label="X">X</symbol>
 | 
				
			||||||
    <keysym keyval="34">quotedbl</keysym>
 | 
					    <symbol label=""">quotedbl</symbol>
 | 
				
			||||||
    <keysym keyval="47">slash</keysym>
 | 
					    <symbol label="/">slash</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="54" name="AB03">
 | 
					  <key name="AB03">
 | 
				
			||||||
    <keysym keyval="99">c</keysym>
 | 
					    <symbol label="c">c</symbol>
 | 
				
			||||||
    <keysym keyval="67">C</keysym>
 | 
					    <symbol label="C">C</symbol>
 | 
				
			||||||
    <keysym keyval="39">quoteright</keysym>
 | 
					    <symbol label="'">quoteright</symbol>
 | 
				
			||||||
    <keysym keyval="60">less</keysym>
 | 
					    <symbol label="<">less</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="55" name="AB04">
 | 
					  <key name="AB04">
 | 
				
			||||||
    <keysym keyval="118">v</keysym>
 | 
					    <symbol label="v">v</symbol>
 | 
				
			||||||
    <keysym keyval="86">V</keysym>
 | 
					    <symbol label="V">V</symbol>
 | 
				
			||||||
    <keysym keyval="58">colon</keysym>
 | 
					    <symbol label=":">colon</symbol>
 | 
				
			||||||
    <keysym keyval="62">greater</keysym>
 | 
					    <symbol label=">">greater</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="56" name="AB05">
 | 
					  <key name="AB05">
 | 
				
			||||||
    <keysym keyval="98">b</keysym>
 | 
					    <symbol label="b">b</symbol>
 | 
				
			||||||
    <keysym keyval="66">B</keysym>
 | 
					    <symbol label="B">B</symbol>
 | 
				
			||||||
    <keysym keyval="59">semicolon</keysym>
 | 
					    <symbol label=";">semicolon</symbol>
 | 
				
			||||||
    <keysym keyval="61">equal</keysym>
 | 
					    <symbol label="=">equal</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="57" name="AB06">
 | 
					  <key name="AB06">
 | 
				
			||||||
    <keysym keyval="110">n</keysym>
 | 
					    <symbol label="n">n</symbol>
 | 
				
			||||||
    <keysym keyval="78">N</keysym>
 | 
					    <symbol label="N">N</symbol>
 | 
				
			||||||
    <keysym keyval="33">exclam</keysym>
 | 
					    <symbol label="!">exclam</symbol>
 | 
				
			||||||
    <keysym keyval="91">bracketleft</keysym>
 | 
					    <symbol label="[">bracketleft</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="58" name="AB07">
 | 
					  <key name="AB07">
 | 
				
			||||||
    <keysym keyval="109">m</keysym>
 | 
					    <symbol label="m">m</symbol>
 | 
				
			||||||
    <keysym keyval="77">M</keysym>
 | 
					    <symbol label="M">M</symbol>
 | 
				
			||||||
    <keysym keyval="63">question</keysym>
 | 
					    <symbol label="?">question</symbol>
 | 
				
			||||||
    <keysym keyval="93">bracketright</keysym>
 | 
					    <symbol label="]">bracketright</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="59" name="AB08">
 | 
					  <key name="AB08">
 | 
				
			||||||
    <keysym keyval="44">comma</keysym>
 | 
					    <symbol label=".">period</symbol>
 | 
				
			||||||
    <keysym keyval="60">less</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="60" name="AB09">
 | 
					  <key name="ABC123">
 | 
				
			||||||
    <keysym keyval="46">period</keysym>
 | 
					    <symbol label="123">show-numbers</symbol>
 | 
				
			||||||
 | 
					    <symbol label="123">show-numbers</symbol>
 | 
				
			||||||
 | 
					    <symbol label="ABC">show-letters</symbol>
 | 
				
			||||||
 | 
					    <symbol label="ABC">show-letters</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="61" name="AB10">
 | 
					  <key name="I149">
 | 
				
			||||||
    <keysym keyval="47">slash</keysym>
 | 
					    <symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
				
			||||||
    <keysym keyval="63">question</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="62" name="RTSH">
 | 
					  <key name="SPCE">
 | 
				
			||||||
    <keysym keyval="65506">Shift_R</keysym>
 | 
					    <symbol label=" ">space</symbol>
 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
  <key keycode="149" name="I149">
 | 
					  <key name="BKSP">
 | 
				
			||||||
    <symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
 | 
					    <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="150" name="I150">
 | 
					 | 
				
			||||||
    <symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="37" name="LCTL">
 | 
					 | 
				
			||||||
    <keysym keyval="65507">Control_L</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="64" name="LALT">
 | 
					 | 
				
			||||||
    <keysym keyval="65513">Alt_L</keysym>
 | 
					 | 
				
			||||||
    <keysym keyval="65511">Meta_L</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="65" name="SPCE">
 | 
					 | 
				
			||||||
    <keysym keyval="32">space</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="113" name="LEFT">
 | 
					 | 
				
			||||||
    <keysym keyval="65361">Left</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="111" name="UP">
 | 
					 | 
				
			||||||
    <keysym keyval="65362">Up</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="116" name="DOWN">
 | 
					 | 
				
			||||||
    <keysym keyval="65364">Down</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					 | 
				
			||||||
  <key keycode="114" name="RGHT">
 | 
					 | 
				
			||||||
    <keysym keyval="65363">Right</keysym>
 | 
					 | 
				
			||||||
  </key>
 | 
					  </key>
 | 
				
			||||||
</symbols>
 | 
					</symbols>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
  <gresource prefix="/sm/puri/squeekboard">
 | 
					  <gresource prefix="/sm/puri/squeekboard">
 | 
				
			||||||
   <file compressed="true">style.css</file>
 | 
					   <file compressed="true">style.css</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/compact.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/compact.xml</file>
 | 
				
			||||||
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/extended.xml</file>
 | 
				
			||||||
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/number-keypad.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ar.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/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>
 | 
				
			||||||
@ -21,6 +23,7 @@
 | 
				
			|||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ml-inscript.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ml-inscript.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mr-inscript.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mr-inscript.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/my.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/my.xml</file>
 | 
				
			||||||
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/nb.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/or-inscript.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/or-inscript.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/pa-inscript.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/pa-inscript.xml</file>
 | 
				
			||||||
   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ru.xml</file>
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ru.xml</file>
 | 
				
			||||||
@ -32,6 +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>
 | 
				
			||||||
 | 
					   <file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/number.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>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@ -11,7 +11,10 @@ Build-Depends:
 | 
				
			|||||||
 libcroco3-dev,
 | 
					 libcroco3-dev,
 | 
				
			||||||
 libwayland-dev (>= 1.16),
 | 
					 libwayland-dev (>= 1.16),
 | 
				
			||||||
 rustc,
 | 
					 rustc,
 | 
				
			||||||
 wayland-protocols (>= 1.14)
 | 
					 wayland-protocols (>= 1.14),
 | 
				
			||||||
 | 
					# for running the tests
 | 
				
			||||||
 | 
					 xvfb,
 | 
				
			||||||
 | 
					 xauth,
 | 
				
			||||||
Standards-Version: 4.1.3
 | 
					Standards-Version: 4.1.3
 | 
				
			||||||
Homepage: https://source.puri.sm/Librem5/squeekboard
 | 
					Homepage: https://source.puri.sm/Librem5/squeekboard
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,9 +26,7 @@
 | 
				
			|||||||
 * shall be used to implement #EekKeyboard and #EekSection.
 | 
					 * shall be used to implement #EekKeyboard and #EekSection.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-container.h"
 | 
					#include "eek-container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,9 +26,7 @@
 | 
				
			|||||||
 * shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
 | 
					 * shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -102,6 +100,7 @@ eek_element_set_property (GObject      *object,
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PROP_LEVEL:
 | 
					    case PROP_LEVEL:
 | 
				
			||||||
        eek_element_set_level (element, g_value_get_int (value));
 | 
					        eek_element_set_level (element, g_value_get_int (value));
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
				
			|||||||
@ -25,15 +25,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_GSOUND
 | 
					#ifdef HAVE_LIBCANBERRA
 | 
				
			||||||
#include <gsound.h>
 | 
					#include <canberra-gtk.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-gtk-keyboard.h"
 | 
					#include "eek-gtk-keyboard.h"
 | 
				
			||||||
#include "eek-gtk-renderer.h"
 | 
					#include "eek-renderer.h"
 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
#include "eek-section.h"
 | 
					#include "eek-section.h"
 | 
				
			||||||
#include "eek-key.h"
 | 
					#include "eek-key.h"
 | 
				
			||||||
@ -56,9 +56,6 @@ typedef struct _EekGtkKeyboardPrivate
 | 
				
			|||||||
    EekRenderer *renderer;
 | 
					    EekRenderer *renderer;
 | 
				
			||||||
    EekKeyboard *keyboard;
 | 
					    EekKeyboard *keyboard;
 | 
				
			||||||
    EekTheme *theme;
 | 
					    EekTheme *theme;
 | 
				
			||||||
#ifdef HAVE_GSOUND
 | 
					 | 
				
			||||||
    GSoundContext *sound_ctx;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GdkEventSequence *sequence; // unowned reference
 | 
					    GdkEventSequence *sequence; // unowned reference
 | 
				
			||||||
} EekGtkKeyboardPrivate;
 | 
					} EekGtkKeyboardPrivate;
 | 
				
			||||||
@ -115,7 +112,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
				
			|||||||
        PangoContext *pcontext;
 | 
					        PangoContext *pcontext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pcontext = gtk_widget_get_pango_context (self);
 | 
					        pcontext = gtk_widget_get_pango_context (self);
 | 
				
			||||||
        priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
 | 
					        priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
 | 
				
			||||||
        if (priv->theme)
 | 
					        if (priv->theme)
 | 
				
			||||||
            eek_renderer_set_theme (priv->renderer, priv->theme);
 | 
					            eek_renderer_set_theme (priv->renderer, priv->theme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -165,6 +162,7 @@ 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (key) {
 | 
					    if (key) {
 | 
				
			||||||
        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);
 | 
				
			||||||
@ -439,16 +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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if HAVE_GSOUND
 | 
					    /* void */
 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					 | 
				
			||||||
    GError *err = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    priv->sound_ctx = gsound_context_new(NULL, &err);
 | 
					 | 
				
			||||||
    if (!priv->sound_ctx) {
 | 
					 | 
				
			||||||
        g_warning ("GSound init failed: %s", err->message);
 | 
					 | 
				
			||||||
        g_clear_error (&err);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -499,11 +488,13 @@ render_pressed_key (GtkWidget *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);
 | 
					    eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
 | 
				
			||||||
    magnify_bounds (widget, &bounds, &large_bounds, 1.5);
 | 
					    magnify_bounds (widget, &bounds, &large_bounds, 1.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save (cr);
 | 
					    cairo_save (cr);
 | 
				
			||||||
 | 
					    cairo_scale (cr, scale, scale);
 | 
				
			||||||
    cairo_translate (cr, bounds.x, bounds.y);
 | 
					    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_restore (cr);
 | 
				
			||||||
@ -530,11 +521,15 @@ render_locked_key (GtkWidget *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);
 | 
					    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);
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -554,9 +549,6 @@ render_released_key (GtkWidget *widget,
 | 
				
			|||||||
    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
 | 
					 | 
				
			||||||
    magnify_bounds (widget, &bounds, &large_bounds, 1.5);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
					    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdk_window_end_draw_frame (window, context);
 | 
					    gdk_window_end_draw_frame (window, context);
 | 
				
			||||||
@ -577,12 +569,12 @@ on_key_pressed (EekKey      *key,
 | 
				
			|||||||
    render_pressed_key (GTK_WIDGET(self), key);
 | 
					    render_pressed_key (GTK_WIDGET(self), key);
 | 
				
			||||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
					    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if HAVE_GSOUND
 | 
					#if HAVE_LIBCANBERRA
 | 
				
			||||||
    g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
 | 
					    ca_gtk_play_for_widget (widget, 0,
 | 
				
			||||||
    gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
 | 
					                            CA_PROP_EVENT_ID, "button-pressed",
 | 
				
			||||||
                               GSOUND_ATTR_EVENT_ID, "button-pressed",
 | 
					                            CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
 | 
				
			||||||
                               GSOUND_ATTR_EVENT_DESCRIPTION, "Button pressed",
 | 
					                            CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
 | 
				
			||||||
                               NULL);
 | 
					                            NULL);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -599,12 +591,12 @@ on_key_released (EekKey      *key,
 | 
				
			|||||||
    render_released_key (GTK_WIDGET(self), key);
 | 
					    render_released_key (GTK_WIDGET(self), key);
 | 
				
			||||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
					    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if HAVE_GSOUND
 | 
					#if HAVE_LIBCANBERRA
 | 
				
			||||||
    g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
 | 
					    ca_gtk_play_for_widget (widget, 0,
 | 
				
			||||||
    gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
 | 
					                            CA_PROP_EVENT_ID, "button-released",
 | 
				
			||||||
                               GSOUND_ATTR_EVENT_ID, "button-released",
 | 
					                            CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
 | 
				
			||||||
                               GSOUND_ATTR_EVENT_DESCRIPTION, "Button released",
 | 
					                            CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
 | 
				
			||||||
                               NULL);
 | 
					                            NULL);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,84 +0,0 @@
 | 
				
			|||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
					 | 
				
			||||||
 * as published by the Free Software Foundation; either version 2 of
 | 
					 | 
				
			||||||
 * the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This library is distributed in the hope that it will be useful, but
 | 
					 | 
				
			||||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
					 | 
				
			||||||
 * Lesser General Public License for more details.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Lesser General Public
 | 
					 | 
				
			||||||
 * License along with this library; if not, write to the Free Software
 | 
					 | 
				
			||||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
					 | 
				
			||||||
 * 02110-1301 USA
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eek-gtk-renderer.h"
 | 
					 | 
				
			||||||
#include "eek-key.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_DEFINE_TYPE (EekGtkRenderer, eek_gtk_renderer, EEK_TYPE_RENDERER);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static cairo_surface_t *
 | 
					 | 
				
			||||||
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
 | 
					 | 
				
			||||||
                                        const gchar *icon_name,
 | 
					 | 
				
			||||||
                                        gint size,
 | 
					 | 
				
			||||||
                                        gint scale)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GError *error = NULL;
 | 
					 | 
				
			||||||
    cairo_surface_t *surface;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
 | 
					 | 
				
			||||||
                                           icon_name,
 | 
					 | 
				
			||||||
                                           size,
 | 
					 | 
				
			||||||
                                           scale,
 | 
					 | 
				
			||||||
                                           NULL,
 | 
					 | 
				
			||||||
                                           0,
 | 
					 | 
				
			||||||
                                           &error);
 | 
					 | 
				
			||||||
    if (surface == NULL) {
 | 
					 | 
				
			||||||
        g_warning ("can't get icon surface for %s: %s",
 | 
					 | 
				
			||||||
                   icon_name,
 | 
					 | 
				
			||||||
                   error->message);
 | 
					 | 
				
			||||||
        g_error_free (error);
 | 
					 | 
				
			||||||
        return NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return surface;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
eek_gtk_renderer_class_init (EekGtkRendererClass *klass)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererClass *renderer_class = EEK_RENDERER_CLASS (klass);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    renderer_class->get_icon_surface = eek_gtk_renderer_real_get_icon_surface;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
eek_gtk_renderer_init (EekGtkRenderer *self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GtkIconTheme *theme = gtk_icon_theme_get_default ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EekRenderer *
 | 
					 | 
				
			||||||
eek_gtk_renderer_new (EekKeyboard  *keyboard,
 | 
					 | 
				
			||||||
                      PangoContext *pcontext,
 | 
					 | 
				
			||||||
                      GtkWidget    *widget)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return g_object_new (EEK_TYPE_GTK_RENDERER,
 | 
					 | 
				
			||||||
                         "keyboard", keyboard,
 | 
					 | 
				
			||||||
                         "pango-context", pcontext,
 | 
					 | 
				
			||||||
                         NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,61 +0,0 @@
 | 
				
			|||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
					 | 
				
			||||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
					 | 
				
			||||||
 * as published by the Free Software Foundation; either version 2 of
 | 
					 | 
				
			||||||
 * the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This library is distributed in the hope that it will be useful, but
 | 
					 | 
				
			||||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
					 | 
				
			||||||
 * Lesser General Public License for more details.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Lesser General Public
 | 
					 | 
				
			||||||
 * License along with this library; if not, write to the Free Software
 | 
					 | 
				
			||||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
					 | 
				
			||||||
 * 02110-1301 USA
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef EEK_GTK_RENDERER_H
 | 
					 | 
				
			||||||
#define EEK_GTK_RENDERER_H 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gtk/gtk.h>
 | 
					 | 
				
			||||||
#include "eek-renderer.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_BEGIN_DECLS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EEK_TYPE_GTK_RENDERER (eek_gtk_renderer_get_type())
 | 
					 | 
				
			||||||
#define EEK_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRenderer))
 | 
					 | 
				
			||||||
#define EEK_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
 | 
					 | 
				
			||||||
#define EEK_IS_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_GTK_RENDERER))
 | 
					 | 
				
			||||||
#define EEK_IS_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_GTK_RENDERER))
 | 
					 | 
				
			||||||
#define EEK_GTK_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct _EekGtkRenderer EekGtkRenderer;
 | 
					 | 
				
			||||||
typedef struct _EekGtkRendererClass EekGtkRendererClass;
 | 
					 | 
				
			||||||
typedef struct _EekGtkRendererPrivate EekGtkRendererPrivate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _EekGtkRenderer {
 | 
					 | 
				
			||||||
    EekRenderer parent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekGtkRendererPrivate *priv;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _EekGtkRendererClass
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererClass parent_class;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*< private >*/
 | 
					 | 
				
			||||||
    /* padding */
 | 
					 | 
				
			||||||
    gpointer pdummy[24];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GType        eek_gtk_renderer_get_type (void) G_GNUC_CONST;
 | 
					 | 
				
			||||||
EekRenderer *eek_gtk_renderer_new      (EekKeyboard  *keyboard,
 | 
					 | 
				
			||||||
                                        PangoContext *pcontext,
 | 
					 | 
				
			||||||
                                        GtkWidget *widget);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_END_DECLS
 | 
					 | 
				
			||||||
#endif  /* EEK_GTK_RENDERER_H */
 | 
					 | 
				
			||||||
@ -25,9 +25,7 @@
 | 
				
			|||||||
 * The #EekKeyClass class represents a key.
 | 
					 * The #EekKeyClass class represents a key.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -611,3 +609,11 @@ void eek_key_set_pressed(EekKey *key, gboolean value)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    priv->is_pressed = value;
 | 
					    priv->is_pressed = value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					eek_key_has_label(EekKey *key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekSymbol *symbol = eek_key_get_symbol(key);
 | 
				
			||||||
 | 
					    return (eek_symbol_get_label(symbol) != NULL) ||
 | 
				
			||||||
 | 
					           (eek_symbol_get_icon_name(symbol) != NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -89,5 +89,7 @@ gboolean         eek_key_is_locked           (EekKey          *key);
 | 
				
			|||||||
void             eek_key_set_pressed         (EekKey          *key,
 | 
					void             eek_key_set_pressed         (EekKey          *key,
 | 
				
			||||||
                                              gboolean         value);
 | 
					                                              gboolean         value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean         eek_key_has_label           (EekKey          *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEK_KEY_H */
 | 
					#endif  /* EEK_KEY_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -17,9 +17,7 @@
 | 
				
			|||||||
 * Boston, MA 02111-1307, USA.
 | 
					 * Boston, MA 02111-1307, USA.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <pango/pangocairo.h>
 | 
					#include <pango/pangocairo.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -27,9 +27,8 @@
 | 
				
			|||||||
 * of one or more sections of the #EekSectionClass class.
 | 
					 * of one or more sections of the #EekSectionClass class.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					#include <glib/gprintf.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
#include "eek-marshalers.h"
 | 
					#include "eek-marshalers.h"
 | 
				
			||||||
@ -38,6 +37,7 @@
 | 
				
			|||||||
#include "eek-symbol.h"
 | 
					#include "eek-symbol.h"
 | 
				
			||||||
#include "eek-enumtypes.h"
 | 
					#include "eek-enumtypes.h"
 | 
				
			||||||
#include "eekboard/key-emitter.h"
 | 
					#include "eekboard/key-emitter.h"
 | 
				
			||||||
 | 
					#include "keymap.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    PROP_0,
 | 
					    PROP_0,
 | 
				
			||||||
@ -74,7 +74,9 @@ struct _EekKeyboardPrivate
 | 
				
			|||||||
    GList *pressed_keys;
 | 
					    GList *pressed_keys;
 | 
				
			||||||
    GList *locked_keys;
 | 
					    GList *locked_keys;
 | 
				
			||||||
    GArray *outline_array;
 | 
					    GArray *outline_array;
 | 
				
			||||||
    GHashTable *keycodes;
 | 
					
 | 
				
			||||||
 | 
					    /* Map key names to key objects: */
 | 
				
			||||||
 | 
					    GHashTable *names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* modifiers dynamically assigned at run time */
 | 
					    /* modifiers dynamically assigned at run time */
 | 
				
			||||||
    EekModifierType num_lock_mask;
 | 
					    EekModifierType num_lock_mask;
 | 
				
			||||||
@ -129,9 +131,9 @@ section_child_added_cb (EekContainer *container,
 | 
				
			|||||||
                        EekElement   *element,
 | 
					                        EekElement   *element,
 | 
				
			||||||
                        EekKeyboard  *keyboard)
 | 
					                        EekKeyboard  *keyboard)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    guint keycode = eek_key_get_keycode (EEK_KEY(element));
 | 
					    const gchar *name = eek_element_get_name(element);
 | 
				
			||||||
    g_hash_table_insert (keyboard->priv->keycodes,
 | 
					    g_hash_table_insert (keyboard->priv->names,
 | 
				
			||||||
                         GUINT_TO_POINTER(keycode),
 | 
					                         (gpointer)name,
 | 
				
			||||||
                         element);
 | 
					                         element);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,9 +142,9 @@ section_child_removed_cb (EekContainer *container,
 | 
				
			|||||||
                          EekElement   *element,
 | 
					                          EekElement   *element,
 | 
				
			||||||
                          EekKeyboard  *keyboard)
 | 
					                          EekKeyboard  *keyboard)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    guint keycode = eek_key_get_keycode (EEK_KEY(element));
 | 
					    const gchar *name = eek_element_get_name(element);
 | 
				
			||||||
    g_hash_table_remove (keyboard->priv->keycodes,
 | 
					    g_hash_table_remove (keyboard->priv->names,
 | 
				
			||||||
                         GUINT_TO_POINTER(keycode));
 | 
					                         name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static EekSection *
 | 
					static EekSection *
 | 
				
			||||||
@ -221,7 +223,7 @@ set_level_from_modifiers (EekKeyboard *self, EekKey *key)
 | 
				
			|||||||
    gint level = priv->old_level & 2;
 | 
					    gint level = priv->old_level & 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Handle non-emitting keys */
 | 
					    /* Handle non-emitting keys */
 | 
				
			||||||
    if (key && (eek_key_get_keycode(key) == 0)) {
 | 
					    if (key) {
 | 
				
			||||||
        const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
 | 
					        const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
 | 
				
			||||||
        if (g_strcmp0(name, "ABC123") == 0)
 | 
					        if (g_strcmp0(name, "ABC123") == 0)
 | 
				
			||||||
            level ^= 2;
 | 
					            level ^= 2;
 | 
				
			||||||
@ -264,6 +266,8 @@ set_level_from_modifiers (EekKeyboard *self, EekKey *key)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    priv->old_level = level;
 | 
					    priv->old_level = level;
 | 
				
			||||||
    eek_element_set_level (EEK_ELEMENT(self), level);
 | 
					    eek_element_set_level (EEK_ELEMENT(self), level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eek_layout_update_layout(self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -400,7 +404,7 @@ eek_keyboard_finalize (GObject *object)
 | 
				
			|||||||
    g_list_free_full (priv->locked_keys,
 | 
					    g_list_free_full (priv->locked_keys,
 | 
				
			||||||
                      (GDestroyNotify) eek_modifier_key_free);
 | 
					                      (GDestroyNotify) eek_modifier_key_free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_hash_table_destroy (priv->keycodes);
 | 
					    g_hash_table_destroy (priv->names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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,
 | 
				
			||||||
@ -528,8 +532,9 @@ eek_keyboard_init (EekKeyboard *self)
 | 
				
			|||||||
    self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
 | 
					    self->priv = EEK_KEYBOARD_GET_PRIVATE(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->keycodes = g_hash_table_new (g_direct_hash, g_direct_equal);
 | 
					    self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
 | 
				
			||||||
    eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
 | 
					    eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
 | 
				
			||||||
 | 
					    self->scale = 1.0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -548,20 +553,20 @@ eek_keyboard_create_section (EekKeyboard *keyboard)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * eek_keyboard_find_key_by_keycode:
 | 
					 * eek_keyboard_find_key_by_name:
 | 
				
			||||||
 * @keyboard: an #EekKeyboard
 | 
					 * @keyboard: an #EekKeyboard
 | 
				
			||||||
 * @keycode: a keycode
 | 
					 * @name: a key name
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Find an #EekKey whose keycode is @keycode.
 | 
					 * Find an #EekKey whose name is @name.
 | 
				
			||||||
 * Return value: (transfer none): #EekKey whose keycode is @keycode
 | 
					 * Return value: (transfer none): #EekKey whose name is @name
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
EekKey *
 | 
					EekKey *
 | 
				
			||||||
eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
 | 
					eek_keyboard_find_key_by_name (EekKeyboard *keyboard,
 | 
				
			||||||
                                  guint        keycode)
 | 
					                               const gchar *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
					    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
				
			||||||
    return g_hash_table_lookup (keyboard->priv->keycodes,
 | 
					    return g_hash_table_lookup (keyboard->priv->names,
 | 
				
			||||||
                                GUINT_TO_POINTER(keycode));
 | 
					                                name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -795,3 +800,93 @@ eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
 | 
				
			|||||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
					    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
				
			||||||
    return g_list_copy (keyboard->priv->locked_keys);
 | 
					    return g_list_copy (keyboard->priv->locked_keys);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * eek_keyboard_get_keymap:
 | 
				
			||||||
 | 
					 * @keyboard: an #EekKeyboard
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the keymap for the keyboard.
 | 
				
			||||||
 | 
					 * Returns: a string containing the XKB keymap.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					gchar *
 | 
				
			||||||
 | 
					eek_keyboard_get_keymap(EekKeyboard *keyboard)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Start the keycodes and symbols sections with their respective headers. */
 | 
				
			||||||
 | 
					    gchar *keycodes = g_strdup(keymap_keycodes_header);
 | 
				
			||||||
 | 
					    gchar *symbols = g_strdup(keymap_symbols_header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Iterate over the keys in the name-to-key hash table. */
 | 
				
			||||||
 | 
					    GHashTableIter iter;
 | 
				
			||||||
 | 
					    gpointer key_name, key_ptr;
 | 
				
			||||||
 | 
					    g_hash_table_iter_init(&iter, keyboard->priv->names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (g_hash_table_iter_next(&iter, &key_name, &key_ptr)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gchar *current, *line;
 | 
				
			||||||
 | 
					        EekKey *key = EEK_KEY(key_ptr);
 | 
				
			||||||
 | 
					        int keycode = eek_key_get_keycode(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Don't include invalid keycodes in the keymap. */
 | 
				
			||||||
 | 
					        if (keycode == EEK_INVALID_KEYCODE)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Append a key name-to-keycode definition to the keycodes section. */
 | 
				
			||||||
 | 
					        current = keycodes;
 | 
				
			||||||
 | 
					        line = g_strdup_printf("        <%s> = %i;\n", (char *)key_name, keycode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        keycodes = g_strconcat(current, line, NULL);
 | 
				
			||||||
 | 
					        g_free(line);
 | 
				
			||||||
 | 
					        g_free(current);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Find the symbols associated with the key. */
 | 
				
			||||||
 | 
					        EekSymbolMatrix *matrix = eek_key_get_symbol_matrix(key);
 | 
				
			||||||
 | 
					        EekSymbol *syms[4];
 | 
				
			||||||
 | 
					        int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Get the symbols for all the levels defined for the key, then
 | 
				
			||||||
 | 
					           pad it out with the first symbol for all levels up to the fourth. */
 | 
				
			||||||
 | 
					        for (i = 0; i < matrix->num_levels; ++i)
 | 
				
			||||||
 | 
					            syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (i < 4) {
 | 
				
			||||||
 | 
					            syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, 0);
 | 
				
			||||||
 | 
					            i++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* The four levels are split into two groups in the keymap.
 | 
				
			||||||
 | 
					           Generate strings for each of these groups, where an empty group is
 | 
				
			||||||
 | 
					           treated specially. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gchar *groups[2];
 | 
				
			||||||
 | 
					        for (i = 0, j = 0; i < 2; ++i, j += 2) {
 | 
				
			||||||
 | 
					            if (syms[j] && syms[j + 1])
 | 
				
			||||||
 | 
					                groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
 | 
				
			||||||
 | 
					                                            eek_symbol_get_name(syms[j + 1]),
 | 
				
			||||||
 | 
					                                            NULL);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                groups[i] = "";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Append a key definition to the symbols section. */
 | 
				
			||||||
 | 
					        current = symbols;
 | 
				
			||||||
 | 
					        line = g_strdup_printf("        key <%s> { [ %s ], [ %s ] };\n",
 | 
				
			||||||
 | 
					                               (char *)key_name, groups[0], groups[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_free(groups[0]);
 | 
				
			||||||
 | 
					        g_free(groups[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        symbols = g_strconcat(current, line, NULL);
 | 
				
			||||||
 | 
					        g_free(line);
 | 
				
			||||||
 | 
					        g_free(current);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Assemble the keymap file from the header, sections and footer. */
 | 
				
			||||||
 | 
					    gchar *keymap = g_strconcat(keymap_header,
 | 
				
			||||||
 | 
					                                keycodes, "    };\n\n",
 | 
				
			||||||
 | 
					                                symbols, "    };\n\n",
 | 
				
			||||||
 | 
					                                keymap_footer, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_free(keycodes);
 | 
				
			||||||
 | 
					    g_free(symbols);
 | 
				
			||||||
 | 
					    return keymap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -62,6 +62,7 @@ struct _EekKeyboard
 | 
				
			|||||||
    struct xkb_keymap *keymap;
 | 
					    struct xkb_keymap *keymap;
 | 
				
			||||||
    int keymap_fd; // keymap formatted as XKB string
 | 
					    int keymap_fd; // keymap formatted as XKB string
 | 
				
			||||||
    size_t keymap_len; // length of the data inside keymap_fd
 | 
					    size_t keymap_len; // length of the data inside keymap_fd
 | 
				
			||||||
 | 
					    double scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekboardContextService *manager; // unowned reference
 | 
					    EekboardContextService *manager; // unowned reference
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -69,8 +70,8 @@ struct _EekKeyboard
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * EekKeyboardClass:
 | 
					 * EekKeyboardClass:
 | 
				
			||||||
 * @create_section: virtual function for creating a section
 | 
					 * @create_section: virtual function for creating a section
 | 
				
			||||||
 * @find_key_by_keycode: virtual function for finding a key in the
 | 
					 * @find_key_by_name: virtual function for finding a key in the
 | 
				
			||||||
 * keyboard by keycode
 | 
					 * keyboard by name
 | 
				
			||||||
 * @key_pressed: class handler for #EekKeyboard::key-pressed signal
 | 
					 * @key_pressed: class handler for #EekKeyboard::key-pressed signal
 | 
				
			||||||
 * @key_released: class handler for #EekKeyboard::key-released signal
 | 
					 * @key_released: class handler for #EekKeyboard::key-released signal
 | 
				
			||||||
 * @key_locked: class handler for #EekKeyboard::key-locked signal
 | 
					 * @key_locked: class handler for #EekKeyboard::key-locked signal
 | 
				
			||||||
@ -89,8 +90,8 @@ struct _EekKeyboardClass
 | 
				
			|||||||
    /*< public >*/
 | 
					    /*< public >*/
 | 
				
			||||||
    EekSection *(* create_section)      (EekKeyboard *self);
 | 
					    EekSection *(* create_section)      (EekKeyboard *self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekKey     *(* find_key_by_keycode) (EekKeyboard *self,
 | 
					    EekKey     *(* find_key_by_name)    (EekKeyboard *self,
 | 
				
			||||||
                                         guint        keycode);
 | 
					                                         const gchar *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    /* obsolete members moved to EekElement */
 | 
					    /* obsolete members moved to EekElement */
 | 
				
			||||||
@ -155,9 +156,9 @@ EekModifierType     eek_keyboard_get_modifiers
 | 
				
			|||||||
EekSection         *eek_keyboard_create_section
 | 
					EekSection         *eek_keyboard_create_section
 | 
				
			||||||
                                     (EekKeyboard        *keyboard);
 | 
					                                     (EekKeyboard        *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EekKey             *eek_keyboard_find_key_by_keycode
 | 
					EekKey             *eek_keyboard_find_key_by_name
 | 
				
			||||||
                                     (EekKeyboard        *keyboard,
 | 
					                                     (EekKeyboard        *keyboard,
 | 
				
			||||||
                                      guint               keycode);
 | 
					                                      const gchar        *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
guint               eek_keyboard_add_outline
 | 
					guint               eek_keyboard_add_outline
 | 
				
			||||||
                                     (EekKeyboard        *keyboard,
 | 
					                                     (EekKeyboard        *keyboard,
 | 
				
			||||||
@ -194,5 +195,8 @@ void                eek_modifier_key_free
 | 
				
			|||||||
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
					void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
				
			||||||
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
					void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gchar *             eek_keyboard_get_keymap
 | 
				
			||||||
 | 
					                                     (EekKeyboard        *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEK_KEYBOARD_H */
 | 
					#endif  /* EEK_KEYBOARD_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -23,9 +23,7 @@
 | 
				
			|||||||
 * @short_description: an #EekSymbol represents an X keysym
 | 
					 * @short_description: an #EekSymbol represents an X keysym
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -26,9 +26,7 @@
 | 
				
			|||||||
 * arranges keyboard elements.
 | 
					 * arranges keyboard elements.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-layout.h"
 | 
					#include "eek-layout.h"
 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
@ -69,3 +67,70 @@ eek_keyboard_new (EekboardContextService *manager,
 | 
				
			|||||||
                                                          initial_width,
 | 
					                                                          initial_width,
 | 
				
			||||||
                                                          initial_height);
 | 
					                                                          initial_height);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const double section_spacing = 7.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct place_data {
 | 
				
			||||||
 | 
					    double desired_width;
 | 
				
			||||||
 | 
					    double current_offset;
 | 
				
			||||||
 | 
					    EekKeyboard *keyboard;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					section_placer(EekElement *element, gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct place_data *data = (struct place_data*)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EekBounds section_bounds = {0};
 | 
				
			||||||
 | 
					    eek_element_get_bounds(element, §ion_bounds);
 | 
				
			||||||
 | 
					    section_bounds.width = data->desired_width;
 | 
				
			||||||
 | 
					    eek_element_set_bounds(element, §ion_bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Sections are rows now. Gather up all the keys and adjust their bounds.
 | 
				
			||||||
 | 
					    eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eek_element_get_bounds(element, §ion_bounds);
 | 
				
			||||||
 | 
					    section_bounds.y = data->current_offset;
 | 
				
			||||||
 | 
					    eek_element_set_bounds(element, §ion_bounds);
 | 
				
			||||||
 | 
					    data->current_offset += section_bounds.height + section_spacing;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					section_counter(EekElement *element, gpointer user_data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double *total_height = user_data;
 | 
				
			||||||
 | 
					    EekBounds section_bounds = {0};
 | 
				
			||||||
 | 
					    eek_element_get_bounds(element, §ion_bounds);
 | 
				
			||||||
 | 
					    *total_height += section_bounds.height + section_spacing;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					eek_layout_place_sections(EekKeyboard *keyboard)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Order rows */
 | 
				
			||||||
 | 
					    // This needs to be done after outlines, because outlines define key sizes
 | 
				
			||||||
 | 
					    // TODO: do this only for rows without bounds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The keyboard width is given by the user via screen size. The height will be given dynamically.
 | 
				
			||||||
 | 
					    // TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
 | 
				
			||||||
 | 
					    EekBounds keyboard_bounds = {0};
 | 
				
			||||||
 | 
					    eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct place_data placer_data = {
 | 
				
			||||||
 | 
					        .desired_width = keyboard_bounds.width,
 | 
				
			||||||
 | 
					        .current_offset = 0,
 | 
				
			||||||
 | 
					        .keyboard = keyboard,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double total_height = 0;
 | 
				
			||||||
 | 
					    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
 | 
				
			||||||
 | 
					    keyboard_bounds.height = total_height;
 | 
				
			||||||
 | 
					    eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					eek_layout_update_layout(EekKeyboard *keyboard)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    eek_layout_place_sections(keyboard);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -55,5 +55,9 @@ struct _EekLayoutClass
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GType        eek_layout_get_type  (void) G_GNUC_CONST;
 | 
					GType        eek_layout_get_type  (void) G_GNUC_CONST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void         eek_layout_place_sections(EekKeyboard *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void         eek_layout_update_layout(EekKeyboard *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEK_LAYOUT_H */
 | 
					#endif  /* EEK_LAYOUT_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -18,12 +18,12 @@
 | 
				
			|||||||
 * 02110-1301 USA
 | 
					 * 02110-1301 USA
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
				
			||||||
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-key.h"
 | 
					#include "eek-key.h"
 | 
				
			||||||
#include "eek-section.h"
 | 
					#include "eek-section.h"
 | 
				
			||||||
@ -49,11 +49,14 @@ typedef struct _EekRendererPrivate
 | 
				
			|||||||
    gdouble allocation_height;
 | 
					    gdouble allocation_height;
 | 
				
			||||||
    gdouble scale;
 | 
					    gdouble scale;
 | 
				
			||||||
    gint scale_factor; /* the outputs scale factor */
 | 
					    gint scale_factor; /* the outputs scale factor */
 | 
				
			||||||
 | 
					    gint origin_x;
 | 
				
			||||||
 | 
					    gint origin_y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PangoFontDescription *ascii_font;
 | 
					    PangoFontDescription *ascii_font;
 | 
				
			||||||
    PangoFontDescription *font;
 | 
					    PangoFontDescription *font;
 | 
				
			||||||
    GHashTable *outline_surface_cache;
 | 
					    GHashTable *outline_surface_cache;
 | 
				
			||||||
    GHashTable *active_outline_surface_cache;
 | 
					    GHashTable *active_outline_surface_cache;
 | 
				
			||||||
 | 
					    GHashTable *icons;
 | 
				
			||||||
    cairo_surface_t *keyboard_surface;
 | 
					    cairo_surface_t *keyboard_surface;
 | 
				
			||||||
    gulong symbol_index_changed_handler;
 | 
					    gulong symbol_index_changed_handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,18 +107,17 @@ create_keyboard_surface_key_callback (EekElement *element,
 | 
				
			|||||||
                                      gpointer    user_data)
 | 
					                                      gpointer    user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
					    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					    EekBounds bounds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save (data->cr);
 | 
					    cairo_save (data->cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					    eek_element_get_bounds (element, &bounds);
 | 
				
			||||||
    cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
 | 
					    cairo_translate (data->cr, bounds.x, bounds.y);
 | 
				
			||||||
    cairo_rectangle (data->cr,
 | 
					    cairo_rectangle (data->cr,
 | 
				
			||||||
                     0.0,
 | 
					                     0.0,
 | 
				
			||||||
                     0.0,
 | 
					                     0.0,
 | 
				
			||||||
                     bounds.width * priv->scale + 100,
 | 
					                     bounds.width + 100,
 | 
				
			||||||
                     bounds.height * priv->scale + 100);
 | 
					                     bounds.height + 100);
 | 
				
			||||||
    cairo_clip (data->cr);
 | 
					    cairo_clip (data->cr);
 | 
				
			||||||
    render_key (data->renderer, data->cr, EEK_KEY(element), FALSE);
 | 
					    render_key (data->renderer, data->cr, EEK_KEY(element), FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -127,14 +129,13 @@ create_keyboard_surface_section_callback (EekElement *element,
 | 
				
			|||||||
                                          gpointer    user_data)
 | 
					                                          gpointer    user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
					    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					    EekBounds bounds;
 | 
				
			||||||
    gint angle;
 | 
					    gint angle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save (data->cr);
 | 
					    cairo_save (data->cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					    eek_element_get_bounds (element, &bounds);
 | 
				
			||||||
    cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
 | 
					    cairo_translate (data->cr, bounds.x, bounds.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    angle = eek_section_get_angle (EEK_SECTION(element));
 | 
					    angle = eek_section_get_angle (EEK_SECTION(element));
 | 
				
			||||||
    cairo_rotate (data->cr, angle * G_PI / 180);
 | 
					    cairo_rotate (data->cr, angle * G_PI / 180);
 | 
				
			||||||
@ -146,12 +147,11 @@ create_keyboard_surface_section_callback (EekElement *element,
 | 
				
			|||||||
    cairo_restore (data->cr);
 | 
					    cairo_restore (data->cr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static cairo_surface_t *
 | 
					void
 | 
				
			||||||
create_keyboard_surface (EekRenderer *renderer)
 | 
					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;
 | 
				
			||||||
    cairo_surface_t *keyboard_surface;
 | 
					 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData data;
 | 
					    CreateKeyboardSurfaceCallbackData data;
 | 
				
			||||||
    EekColor foreground, background;
 | 
					    EekColor foreground, background;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -164,17 +164,12 @@ create_keyboard_surface (EekRenderer *renderer)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Create a surface that encompasses the dimensions of the keyboard as well
 | 
					    data.cr = cairo_create (priv->keyboard_surface);
 | 
				
			||||||
       as the margin around the edge. */
 | 
					 | 
				
			||||||
    keyboard_surface = cairo_image_surface_create (
 | 
					 | 
				
			||||||
        CAIRO_FORMAT_ARGB32,
 | 
					 | 
				
			||||||
        ceil(((bounds.x * 2) + bounds.width) * priv->scale),
 | 
					 | 
				
			||||||
        ceil(((bounds.y * 2) + bounds.height) * priv->scale));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.cr = cairo_create (keyboard_surface);
 | 
					 | 
				
			||||||
    data.renderer = renderer;
 | 
					    data.renderer = renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_translate (data.cr, bounds.x * priv->scale, bounds.y * priv->scale);
 | 
					    cairo_save (data.cr);
 | 
				
			||||||
 | 
					    cairo_scale (data.cr, priv->scale, priv->scale);
 | 
				
			||||||
 | 
					    cairo_translate (data.cr, bounds.x, bounds.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* blank background */
 | 
					    /* blank background */
 | 
				
			||||||
    cairo_set_source_rgba (data.cr,
 | 
					    cairo_set_source_rgba (data.cr,
 | 
				
			||||||
@ -194,9 +189,9 @@ create_keyboard_surface (EekRenderer *renderer)
 | 
				
			|||||||
    eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
 | 
					    eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
 | 
				
			||||||
                                 create_keyboard_surface_section_callback,
 | 
					                                 create_keyboard_surface_section_callback,
 | 
				
			||||||
                                 &data);
 | 
					                                 &data);
 | 
				
			||||||
    cairo_destroy (data.cr);
 | 
					    cairo_restore (data.cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return keyboard_surface;
 | 
					    cairo_destroy (data.cr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -252,14 +247,7 @@ render_key_outline (EekRenderer *renderer,
 | 
				
			|||||||
    eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
 | 
					    eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
 | 
				
			||||||
    outline = eek_outline_copy (outline);
 | 
					    outline = eek_outline_copy (outline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (guint i = 0; i < outline->num_points; i++) {
 | 
					    cairo_translate (cr, border_width, border_width);
 | 
				
			||||||
        outline->points[i].x *= priv->scale;
 | 
					 | 
				
			||||||
        outline->points[i].y *= priv->scale;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_translate (cr,
 | 
					 | 
				
			||||||
                     border_width * priv->scale,
 | 
					 | 
				
			||||||
                     border_width * priv->scale);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (gradient_type != EEK_GRADIENT_NONE) {
 | 
					    if (gradient_type != EEK_GRADIENT_NONE) {
 | 
				
			||||||
        cairo_pattern_t *pat;
 | 
					        cairo_pattern_t *pat;
 | 
				
			||||||
@ -270,17 +258,17 @@ render_key_outline (EekRenderer *renderer,
 | 
				
			|||||||
            pat = cairo_pattern_create_linear (0.0,
 | 
					            pat = cairo_pattern_create_linear (0.0,
 | 
				
			||||||
                                               0.0,
 | 
					                                               0.0,
 | 
				
			||||||
                                               0.0,
 | 
					                                               0.0,
 | 
				
			||||||
                                               bounds.height * priv->scale);
 | 
					                                               bounds.height);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case EEK_GRADIENT_HORIZONTAL:
 | 
					        case EEK_GRADIENT_HORIZONTAL:
 | 
				
			||||||
            pat = cairo_pattern_create_linear (0.0,
 | 
					            pat = cairo_pattern_create_linear (0.0,
 | 
				
			||||||
                                               0.0,
 | 
					                                               0.0,
 | 
				
			||||||
                                               bounds.width * priv->scale,
 | 
					                                               bounds.width,
 | 
				
			||||||
                                               0.0);
 | 
					                                               0.0);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case EEK_GRADIENT_RADIAL:
 | 
					        case EEK_GRADIENT_RADIAL:
 | 
				
			||||||
            cx = bounds.width / 2 * priv->scale;
 | 
					            cx = bounds.width / 2;
 | 
				
			||||||
            cy = bounds.height / 2 * priv->scale;
 | 
					            cy = bounds.height / 2;
 | 
				
			||||||
            pat = cairo_pattern_create_radial (cx,
 | 
					            pat = cairo_pattern_create_radial (cx,
 | 
				
			||||||
                                               cy,
 | 
					                                               cy,
 | 
				
			||||||
                                               0,
 | 
					                                               0,
 | 
				
			||||||
@ -337,98 +325,11 @@ render_key_outline (EekRenderer *renderer,
 | 
				
			|||||||
                          outline->num_points);
 | 
					                          outline->num_points);
 | 
				
			||||||
    cairo_stroke (cr);
 | 
					    cairo_stroke (cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_translate (cr,
 | 
					    cairo_translate (cr, -border_width, -border_width);
 | 
				
			||||||
                     -border_width * priv->scale,
 | 
					 | 
				
			||||||
                     -border_width * priv->scale);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_outline_free (outline);
 | 
					    eek_outline_free (outline);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _CalculateFontSizeCallbackData {
 | 
					 | 
				
			||||||
    gdouble size;
 | 
					 | 
				
			||||||
    gboolean ascii;
 | 
					 | 
				
			||||||
    EekRenderer *renderer;
 | 
					 | 
				
			||||||
    const PangoFontDescription *base_font;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
typedef struct _CalculateFontSizeCallbackData CalculateFontSizeCallbackData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
calculate_font_size_key_callback (EekElement *element, gpointer user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    CalculateFontSizeCallbackData *data = user_data;
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
 | 
					 | 
				
			||||||
    gdouble sx, sy;
 | 
					 | 
				
			||||||
    PangoFontDescription *font;
 | 
					 | 
				
			||||||
    PangoRectangle extents = { 0, };
 | 
					 | 
				
			||||||
    PangoLayout *layout;
 | 
					 | 
				
			||||||
    gdouble size;
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
    const gchar *label = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (data->ascii)
 | 
					 | 
				
			||||||
        label = "M";
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        EekSymbol *symbol;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        symbol = eek_key_get_symbol (EEK_KEY(element));
 | 
					 | 
				
			||||||
        if (symbol &&
 | 
					 | 
				
			||||||
            eek_symbol_get_category (symbol) == EEK_SYMBOL_CATEGORY_LETTER)
 | 
					 | 
				
			||||||
            label = eek_symbol_get_label (symbol);
 | 
					 | 
				
			||||||
        if (!label)
 | 
					 | 
				
			||||||
            label = "M";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    font = pango_font_description_copy (data->base_font);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					 | 
				
			||||||
    size = eek_bounds_long_side (&bounds) * PANGO_SCALE;
 | 
					 | 
				
			||||||
    pango_font_description_set_size (font, size);
 | 
					 | 
				
			||||||
    layout = pango_layout_new (priv->pcontext);
 | 
					 | 
				
			||||||
    pango_layout_set_font_description (layout, font);
 | 
					 | 
				
			||||||
    pango_font_description_free (font);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pango_layout_set_text (layout, label, -1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pango_layout_get_extents (layout, NULL, &extents);
 | 
					 | 
				
			||||||
    g_object_unref (layout);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sx = sy = 1.0;
 | 
					 | 
				
			||||||
    if (extents.width > bounds.width * PANGO_SCALE)
 | 
					 | 
				
			||||||
        sx = bounds.width * PANGO_SCALE / extents.width;
 | 
					 | 
				
			||||||
    if (extents.height > bounds.height * PANGO_SCALE)
 | 
					 | 
				
			||||||
        sy = bounds.height * PANGO_SCALE / extents.height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size *= MIN(sx, sy);
 | 
					 | 
				
			||||||
    if (size < data->size)
 | 
					 | 
				
			||||||
        data->size = size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
calculate_font_size_section_callback (EekElement *element, gpointer user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    eek_container_foreach_child (EEK_CONTAINER(element),
 | 
					 | 
				
			||||||
                                 calculate_font_size_key_callback,
 | 
					 | 
				
			||||||
                                 user_data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gdouble
 | 
					 | 
				
			||||||
calculate_font_size (EekRenderer                *renderer,
 | 
					 | 
				
			||||||
                     const PangoFontDescription *base_font,
 | 
					 | 
				
			||||||
                     gboolean                    ascii)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					 | 
				
			||||||
    CalculateFontSizeCallbackData data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.size = G_MAXDOUBLE;
 | 
					 | 
				
			||||||
    data.ascii = ascii;
 | 
					 | 
				
			||||||
    data.renderer = renderer;
 | 
					 | 
				
			||||||
    data.base_font = base_font;
 | 
					 | 
				
			||||||
    eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
 | 
					 | 
				
			||||||
                                 calculate_font_size_section_callback,
 | 
					 | 
				
			||||||
                                 &data);
 | 
					 | 
				
			||||||
    return data.size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
render_key (EekRenderer *self,
 | 
					render_key (EekRenderer *self,
 | 
				
			||||||
            cairo_t     *cr,
 | 
					            cairo_t     *cr,
 | 
				
			||||||
@ -446,6 +347,9 @@ render_key (EekRenderer *self,
 | 
				
			|||||||
    PangoRectangle extents = { 0, };
 | 
					    PangoRectangle extents = { 0, };
 | 
				
			||||||
    EekColor foreground;
 | 
					    EekColor foreground;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!eek_key_has_label(key))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    oref = eek_key_get_oref (key);
 | 
					    oref = eek_key_get_oref (key);
 | 
				
			||||||
    outline = eek_keyboard_get_outline (priv->keyboard, oref);
 | 
					    outline = eek_keyboard_get_outline (priv->keyboard, oref);
 | 
				
			||||||
    if (outline == NULL)
 | 
					    if (outline == NULL)
 | 
				
			||||||
@ -453,8 +357,6 @@ render_key (EekRenderer *self,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* render outline */
 | 
					    /* render outline */
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
 | 
				
			||||||
    bounds.width *= priv->scale;
 | 
					 | 
				
			||||||
    bounds.height *= priv->scale;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (active)
 | 
					    if (active)
 | 
				
			||||||
        outline_surface_cache = priv->active_outline_surface_cache;
 | 
					        outline_surface_cache = priv->active_outline_surface_cache;
 | 
				
			||||||
@ -498,13 +400,12 @@ render_key (EekRenderer *self,
 | 
				
			|||||||
    if (!symbol)
 | 
					    if (!symbol)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 #define SCALE 0.4
 | 
					 | 
				
			||||||
    if (eek_symbol_get_icon_name (symbol)) {
 | 
					    if (eek_symbol_get_icon_name (symbol)) {
 | 
				
			||||||
        gint scale = priv->scale_factor;
 | 
					        gint scale = priv->scale_factor;
 | 
				
			||||||
        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),
 | 
				
			||||||
                                           SCALE * MIN(bounds.width, bounds.height),
 | 
					                                           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);
 | 
				
			||||||
@ -588,9 +489,8 @@ get_text_property_for_category (EekSymbolCategory category)
 | 
				
			|||||||
        { EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
 | 
					        { EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
 | 
				
			||||||
        { EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
 | 
					        { EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    gint i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < G_N_ELEMENTS(props); i++)
 | 
					    for (uint i = 0; i < G_N_ELEMENTS(props); i++)
 | 
				
			||||||
        if (props[i].category == category)
 | 
					        if (props[i].category == category)
 | 
				
			||||||
            return &props[i];
 | 
					            return &props[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -630,13 +530,16 @@ eek_renderer_real_render_key_label (EekRenderer *self,
 | 
				
			|||||||
            base_font = eek_theme_node_get_font (theme_node);
 | 
					            base_font = eek_theme_node_get_font (theme_node);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            base_font = pango_context_get_font_description (priv->pcontext);
 | 
					            base_font = pango_context_get_font_description (priv->pcontext);
 | 
				
			||||||
        ascii_size = calculate_font_size (self, base_font, TRUE);
 | 
					        // FIXME: Base font size on the same size unit used for button sizing,
 | 
				
			||||||
 | 
					        // and make the default about 1/3 of the current row height
 | 
				
			||||||
 | 
					        ascii_size = 30000.0;
 | 
				
			||||||
        priv->ascii_font = pango_font_description_copy (base_font);
 | 
					        priv->ascii_font = pango_font_description_copy (base_font);
 | 
				
			||||||
        pango_font_description_set_size (priv->ascii_font, ascii_size);
 | 
					        pango_font_description_set_size (priv->ascii_font,
 | 
				
			||||||
 | 
					                                         (gint)round(ascii_size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size = calculate_font_size (self, base_font, FALSE);
 | 
					        size = 30000.0;
 | 
				
			||||||
        priv->font = pango_font_description_copy (base_font);
 | 
					        priv->font = pango_font_description_copy (base_font);
 | 
				
			||||||
        pango_font_description_set_size (priv->font, size * 0.6);
 | 
					        pango_font_description_set_size (priv->font, (gint)round(size * 0.6));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
 | 
				
			||||||
@ -650,8 +553,8 @@ eek_renderer_real_render_key_label (EekRenderer *self,
 | 
				
			|||||||
                                        priv->ascii_font :
 | 
					                                        priv->ascii_font :
 | 
				
			||||||
                                        priv->font);
 | 
					                                        priv->font);
 | 
				
			||||||
    pango_font_description_set_size (font,
 | 
					    pango_font_description_set_size (font,
 | 
				
			||||||
                                     pango_font_description_get_size (font) *
 | 
					                                     (gint)round(pango_font_description_get_size (font) *
 | 
				
			||||||
                                     prop->scale * priv->scale * scale);
 | 
					                                     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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -660,7 +563,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
 | 
				
			|||||||
    if (line->resolved_dir == PANGO_DIRECTION_RTL)
 | 
					    if (line->resolved_dir == PANGO_DIRECTION_RTL)
 | 
				
			||||||
        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 * priv->scale * scale);
 | 
					                            PANGO_SCALE * bounds.width * scale);
 | 
				
			||||||
    if (prop->ellipses)
 | 
					    if (prop->ellipses)
 | 
				
			||||||
        pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
 | 
					        pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -685,7 +588,10 @@ eek_renderer_real_render_key (EekRenderer *self,
 | 
				
			|||||||
                              gdouble      scale,
 | 
					                              gdouble      scale,
 | 
				
			||||||
                              gboolean     rotate)
 | 
					                              gboolean     rotate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save (cr);
 | 
					    cairo_save (cr);
 | 
				
			||||||
 | 
					    cairo_translate (cr, priv->origin_x, priv->origin_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);
 | 
				
			||||||
@ -702,13 +608,25 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
 | 
				
			|||||||
    g_return_if_fail (priv->allocation_width > 0.0);
 | 
					    g_return_if_fail (priv->allocation_width > 0.0);
 | 
				
			||||||
    g_return_if_fail (priv->allocation_height > 0.0);
 | 
					    g_return_if_fail (priv->allocation_height > 0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!priv->keyboard_surface)
 | 
					    cairo_save (cr);
 | 
				
			||||||
        priv->keyboard_surface = create_keyboard_surface (self);
 | 
					
 | 
				
			||||||
 | 
					    cairo_translate (cr, priv->origin_x, priv->origin_y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->keyboard_surface)
 | 
				
			||||||
 | 
					        cairo_surface_destroy (priv->keyboard_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv->keyboard_surface = cairo_surface_create_for_rectangle (
 | 
				
			||||||
 | 
					        cairo_get_target (cr), 0, 0,
 | 
				
			||||||
 | 
					        priv->allocation_width, priv->allocation_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render_keyboard_surface (self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0);
 | 
					    cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0);
 | 
				
			||||||
    source = cairo_get_source (cr);
 | 
					    source = cairo_get_source (cr);
 | 
				
			||||||
    cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
 | 
					    cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
 | 
				
			||||||
    cairo_paint (cr);
 | 
					    cairo_paint (cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cairo_restore (cr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -778,6 +696,8 @@ eek_renderer_dispose (GObject *object)
 | 
				
			|||||||
        priv->pcontext = NULL;
 | 
					        priv->pcontext = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_clear_pointer (&priv->icons, g_hash_table_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* this will release all allocated surfaces and font if any */
 | 
					    /* this will release all allocated surfaces and font if any */
 | 
				
			||||||
    invalidate (EEK_RENDERER(object));
 | 
					    invalidate (EEK_RENDERER(object));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -859,6 +779,14 @@ eek_renderer_init (EekRenderer *self)
 | 
				
			|||||||
                               (GDestroyNotify)cairo_surface_destroy);
 | 
					                               (GDestroyNotify)cairo_surface_destroy);
 | 
				
			||||||
    priv->keyboard_surface = NULL;
 | 
					    priv->keyboard_surface = NULL;
 | 
				
			||||||
    priv->symbol_index_changed_handler = 0;
 | 
					    priv->symbol_index_changed_handler = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GtkIconTheme *theme = gtk_icon_theme_get_default ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
 | 
				
			||||||
 | 
					    priv->icons = g_hash_table_new_full (g_str_hash,
 | 
				
			||||||
 | 
					                                         g_str_equal,
 | 
				
			||||||
 | 
					                                         g_free,
 | 
				
			||||||
 | 
					                                         (GDestroyNotify)cairo_surface_destroy);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -914,21 +842,19 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
 | 
				
			|||||||
    priv->allocation_width = width;
 | 
					    priv->allocation_width = width;
 | 
				
			||||||
    priv->allocation_height = height;
 | 
					    priv->allocation_height = height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Calculate a scale factor to use when rendering the keyboard into the
 | 
				
			||||||
 | 
					       available space. */
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bounds.height * width / bounds.width <= height)
 | 
					    gdouble w = (bounds.x * 2) + bounds.width;
 | 
				
			||||||
        scale = width / bounds.width;
 | 
					    gdouble h = (bounds.y * 2) + bounds.height;
 | 
				
			||||||
    else if (bounds.width * height / bounds.height <= width)
 | 
					
 | 
				
			||||||
        scale = height / bounds.height;
 | 
					    scale = MIN(width / w, height / h);
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        if (bounds.width * height < bounds.height * width)
 | 
					 | 
				
			||||||
            scale = bounds.width / width;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            scale = bounds.height / height;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (scale != priv->scale) {
 | 
					    if (scale != priv->scale) {
 | 
				
			||||||
        priv->scale = scale;
 | 
					        priv->scale = scale;
 | 
				
			||||||
 | 
					        priv->origin_x = 0;
 | 
				
			||||||
 | 
					        priv->origin_y = 0;
 | 
				
			||||||
        invalidate (renderer);
 | 
					        invalidate (renderer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -946,9 +872,9 @@ eek_renderer_get_size (EekRenderer *renderer,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
 | 
				
			||||||
    if (width)
 | 
					    if (width)
 | 
				
			||||||
        *width = bounds.width * priv->scale;
 | 
					        *width = bounds.width;
 | 
				
			||||||
    if (height)
 | 
					    if (height)
 | 
				
			||||||
        *height = bounds.height * priv->scale;
 | 
					        *height = bounds.height;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@ -961,7 +887,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
 | 
				
			|||||||
    EekBounds section_bounds, keyboard_bounds;
 | 
					    EekBounds section_bounds, keyboard_bounds;
 | 
				
			||||||
    gint angle = 0;
 | 
					    gint angle = 0;
 | 
				
			||||||
    EekPoint points[4], min, max;
 | 
					    EekPoint points[4], min, max;
 | 
				
			||||||
    gint i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
					    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
				
			||||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
					    g_return_if_fail (EEK_IS_KEY(key));
 | 
				
			||||||
@ -979,10 +904,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
 | 
				
			|||||||
    if (!rotate) {
 | 
					    if (!rotate) {
 | 
				
			||||||
        bounds->x += keyboard_bounds.x + section_bounds.x;
 | 
					        bounds->x += keyboard_bounds.x + section_bounds.x;
 | 
				
			||||||
        bounds->y += keyboard_bounds.y + section_bounds.y;
 | 
					        bounds->y += keyboard_bounds.y + section_bounds.y;
 | 
				
			||||||
        bounds->x *= priv->scale;
 | 
					 | 
				
			||||||
        bounds->y *= priv->scale;
 | 
					 | 
				
			||||||
        bounds->width *= priv->scale;
 | 
					 | 
				
			||||||
        bounds->height *= priv->scale;
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    points[0].x = bounds->x;
 | 
					    points[0].x = bounds->x;
 | 
				
			||||||
@ -999,7 +920,7 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    min = points[2];
 | 
					    min = points[2];
 | 
				
			||||||
    max = points[0];
 | 
					    max = points[0];
 | 
				
			||||||
    for (i = 0; i < G_N_ELEMENTS(points); i++) {
 | 
					    for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
 | 
				
			||||||
        eek_point_rotate (&points[i], angle);
 | 
					        eek_point_rotate (&points[i], angle);
 | 
				
			||||||
        if (points[i].x < min.x)
 | 
					        if (points[i].x < min.x)
 | 
				
			||||||
            min.x = points[i].x;
 | 
					            min.x = points[i].x;
 | 
				
			||||||
@ -1014,10 +935,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
 | 
				
			|||||||
    bounds->y = keyboard_bounds.y + section_bounds.y + min.y;
 | 
					    bounds->y = keyboard_bounds.y + section_bounds.y + min.y;
 | 
				
			||||||
    bounds->width = (max.x - min.x);
 | 
					    bounds->width = (max.x - min.x);
 | 
				
			||||||
    bounds->height = (max.y - min.y);
 | 
					    bounds->height = (max.y - min.y);
 | 
				
			||||||
    bounds->x *= priv->scale;
 | 
					 | 
				
			||||||
    bounds->y *= priv->scale;
 | 
					 | 
				
			||||||
    bounds->width *= priv->scale;
 | 
					 | 
				
			||||||
    bounds->height *= priv->scale;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gdouble
 | 
					gdouble
 | 
				
			||||||
@ -1085,14 +1002,32 @@ eek_renderer_get_icon_surface (EekRenderer *renderer,
 | 
				
			|||||||
                               gint size,
 | 
					                               gint size,
 | 
				
			||||||
                               gint scale)
 | 
					                               gint scale)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    EekRendererClass *klass;
 | 
					    GError *error = NULL;
 | 
				
			||||||
 | 
					    cairo_surface_t *surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
 | 
					    g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    klass = EEK_RENDERER_GET_CLASS(renderer);
 | 
					    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
				
			||||||
    if (klass->get_icon_surface)
 | 
					
 | 
				
			||||||
        return klass->get_icon_surface (renderer, icon_name, size, scale);
 | 
					    surface = g_hash_table_lookup (priv->icons, icon_name);
 | 
				
			||||||
    return NULL;
 | 
					    if (!surface) {
 | 
				
			||||||
 | 
					        surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
 | 
				
			||||||
 | 
					                                               icon_name,
 | 
				
			||||||
 | 
					                                               size,
 | 
				
			||||||
 | 
					                                               scale,
 | 
				
			||||||
 | 
					                                               NULL,
 | 
				
			||||||
 | 
					                                               0,
 | 
				
			||||||
 | 
					                                               &error);
 | 
				
			||||||
 | 
					        g_hash_table_insert (priv->icons, g_strdup(icon_name), surface);
 | 
				
			||||||
 | 
					        if (surface == NULL) {
 | 
				
			||||||
 | 
					            g_warning ("can't get icon surface for %s: %s",
 | 
				
			||||||
 | 
					                       icon_name,
 | 
				
			||||||
 | 
					                       error->message);
 | 
				
			||||||
 | 
					            g_error_free (error);
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@ -1227,7 +1162,6 @@ find_key_by_position_key_callback (EekElement *element,
 | 
				
			|||||||
    FindKeyByPositionCallbackData *data = user_data;
 | 
					    FindKeyByPositionCallbackData *data = user_data;
 | 
				
			||||||
    EekBounds bounds;
 | 
					    EekBounds bounds;
 | 
				
			||||||
    EekPoint points[4];
 | 
					    EekPoint points[4];
 | 
				
			||||||
    gint i;
 | 
					 | 
				
			||||||
    gboolean b1, b2, b3;
 | 
					    gboolean b1, b2, b3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					    eek_element_get_bounds (element, &bounds);
 | 
				
			||||||
@ -1241,14 +1175,10 @@ find_key_by_position_key_callback (EekElement *element,
 | 
				
			|||||||
    points[3].x = points[0].x;
 | 
					    points[3].x = points[0].x;
 | 
				
			||||||
    points[3].y = points[2].y;
 | 
					    points[3].y = points[2].y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
 | 
					    for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < G_N_ELEMENTS(points); i++) {
 | 
					 | 
				
			||||||
        eek_point_rotate (&points[i], data->angle);
 | 
					        eek_point_rotate (&points[i], data->angle);
 | 
				
			||||||
        points[i].x += data->origin.x;
 | 
					        points[i].x += data->origin.x;
 | 
				
			||||||
        points[i].y += data->origin.y;
 | 
					        points[i].y += data->origin.y;
 | 
				
			||||||
        points[i].x *= priv->scale;
 | 
					 | 
				
			||||||
        points[i].y *= priv->scale;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    b1 = sign (&data->point, &points[0], &points[1]) < 0.0;
 | 
					    b1 = sign (&data->point, &points[0], &points[1]) < 0.0;
 | 
				
			||||||
@ -1304,13 +1234,17 @@ 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (x < bounds.x * priv->scale ||
 | 
					    if (x < bounds.x ||
 | 
				
			||||||
        y < bounds.y * priv->scale ||
 | 
					        y < bounds.y ||
 | 
				
			||||||
        x > bounds.width * priv->scale ||
 | 
					        x > bounds.width ||
 | 
				
			||||||
        y > bounds.height * priv->scale)
 | 
					        y > bounds.height)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data.point.x = x;
 | 
					    data.point.x = x;
 | 
				
			||||||
 | 
				
			|||||||
@ -27,9 +27,7 @@
 | 
				
			|||||||
 * of one or more keys of the #EekKeyClass class.
 | 
					 * of one or more keys of the #EekKeyClass class.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,7 +122,8 @@ on_unlocked (EekKey     *key,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static EekKey *
 | 
					static EekKey *
 | 
				
			||||||
eek_section_real_create_key (EekSection *self,
 | 
					eek_section_real_create_key (EekSection *self,
 | 
				
			||||||
                             guint       keycode,
 | 
					                             const gchar *name,
 | 
				
			||||||
 | 
					                             gint        keycode,
 | 
				
			||||||
                             gint        column_index,
 | 
					                             gint        column_index,
 | 
				
			||||||
                             gint        row_index)
 | 
					                             gint        row_index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -142,6 +141,7 @@ eek_section_real_create_key (EekSection *self,
 | 
				
			|||||||
        row->num_columns = column_index + 1;
 | 
					        row->num_columns = column_index + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    key = g_object_new (EEK_TYPE_KEY,
 | 
					    key = g_object_new (EEK_TYPE_KEY,
 | 
				
			||||||
 | 
					                        "name", name,
 | 
				
			||||||
                        "keycode", keycode,
 | 
					                        "keycode", keycode,
 | 
				
			||||||
                        "column", column_index,
 | 
					                        "column", column_index,
 | 
				
			||||||
                        "row", row_index,
 | 
					                        "row", row_index,
 | 
				
			||||||
@ -463,6 +463,7 @@ eek_section_get_row (EekSection     *section,
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * eek_section_create_key:
 | 
					 * eek_section_create_key:
 | 
				
			||||||
 * @section: an #EekSection
 | 
					 * @section: an #EekSection
 | 
				
			||||||
 | 
					 * @name: a name
 | 
				
			||||||
 * @keycode: a keycode
 | 
					 * @keycode: a keycode
 | 
				
			||||||
 * @column: the column index of the key
 | 
					 * @column: the column index of the key
 | 
				
			||||||
 * @row: the row index of the key
 | 
					 * @row: the row index of the key
 | 
				
			||||||
@ -473,19 +474,32 @@ eek_section_get_row (EekSection     *section,
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
EekKey *
 | 
					EekKey *
 | 
				
			||||||
eek_section_create_key (EekSection *section,
 | 
					eek_section_create_key (EekSection *section,
 | 
				
			||||||
                        guint       keycode,
 | 
					                        const gchar *name,
 | 
				
			||||||
 | 
					                        gint        keycode,
 | 
				
			||||||
                        gint        column,
 | 
					                        gint        column,
 | 
				
			||||||
                        gint        row)
 | 
					                        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,
 | 
				
			||||||
                                                       keycode,
 | 
					                                                       keycode,
 | 
				
			||||||
                                                       column,
 | 
					                                                       column,
 | 
				
			||||||
                                                       row);
 | 
					                                                       row);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void keysizer(EekElement *element, gpointer user_data) {
 | 
					const double keyspacing = 4.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct keys_info {
 | 
				
			||||||
 | 
					    uint count;
 | 
				
			||||||
 | 
					    double total_width;
 | 
				
			||||||
 | 
					    double biggest_height;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					keysizer(EekElement *element, gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    EekKey *key = EEK_KEY(element);
 | 
					    EekKey *key = EEK_KEY(element);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
 | 
					    EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
 | 
				
			||||||
    uint oref = eek_key_get_oref (key);
 | 
					    uint oref = eek_key_get_oref (key);
 | 
				
			||||||
    EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
 | 
					    EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
 | 
				
			||||||
@ -516,13 +530,16 @@ static void keysizer(EekElement *element, gpointer user_data) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct keys_info {
 | 
					static void
 | 
				
			||||||
    uint count;
 | 
					keycounter (EekElement *element, gpointer user_data)
 | 
				
			||||||
    double total_width;
 | 
					{
 | 
				
			||||||
    double biggest_height;
 | 
					    EekKey *key = EEK_KEY(element);
 | 
				
			||||||
};
 | 
					
 | 
				
			||||||
 | 
					    /* Skip keys without labels for the current level. This causes those
 | 
				
			||||||
 | 
					       keys to be hidden in the visible layout. */
 | 
				
			||||||
 | 
					    if (!eek_key_has_label(key))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void keycounter (EekElement *element, gpointer user_data) {
 | 
					 | 
				
			||||||
    struct keys_info *data = user_data;
 | 
					    struct keys_info *data = user_data;
 | 
				
			||||||
    data->count++;
 | 
					    data->count++;
 | 
				
			||||||
    EekBounds key_bounds = {0};
 | 
					    EekBounds key_bounds = {0};
 | 
				
			||||||
@ -533,9 +550,15 @@ static void keycounter (EekElement *element, gpointer user_data) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const double keyspacing = 4.0;
 | 
					static void
 | 
				
			||||||
 | 
					keyplacer(EekElement *element, gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekKey *key = EEK_KEY(element);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Skip keys without labels for the current level. */
 | 
				
			||||||
 | 
					    if (!eek_key_has_label(key))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void keyplacer(EekElement *element, gpointer user_data) {
 | 
					 | 
				
			||||||
    double *current_offset = user_data;
 | 
					    double *current_offset = user_data;
 | 
				
			||||||
    EekBounds key_bounds = {0};
 | 
					    EekBounds key_bounds = {0};
 | 
				
			||||||
    eek_element_get_bounds(element, &key_bounds);
 | 
					    eek_element_get_bounds(element, &key_bounds);
 | 
				
			||||||
@ -545,7 +568,8 @@ static void keyplacer(EekElement *element, gpointer user_data) {
 | 
				
			|||||||
    *current_offset += key_bounds.width + keyspacing;
 | 
					    *current_offset += key_bounds.width + keyspacing;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
 | 
					void
 | 
				
			||||||
 | 
					eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);
 | 
					    eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -62,7 +62,8 @@ struct _EekSectionClass
 | 
				
			|||||||
                                     EekOrientation *orientation);
 | 
					                                     EekOrientation *orientation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekKey *(* create_key)          (EekSection     *self,
 | 
					    EekKey *(* create_key)          (EekSection     *self,
 | 
				
			||||||
                                     guint           keycode,
 | 
					                                     const gchar    *name,
 | 
				
			||||||
 | 
					                                     gint            keycode,
 | 
				
			||||||
                                     gint            row,
 | 
					                                     gint            row,
 | 
				
			||||||
                                     gint            column);
 | 
					                                     gint            column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,7 +100,8 @@ void    eek_section_get_row              (EekSection     *section,
 | 
				
			|||||||
                                          EekOrientation *orientation);
 | 
					                                          EekOrientation *orientation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EekKey *eek_section_create_key           (EekSection     *section,
 | 
					EekKey *eek_section_create_key           (EekSection     *section,
 | 
				
			||||||
                                          guint           keycode,
 | 
					                                          const gchar    *name,
 | 
				
			||||||
 | 
					                                          gint            keycode,
 | 
				
			||||||
                                          gint            column,
 | 
					                                          gint            column,
 | 
				
			||||||
                                          gint            row);
 | 
					                                          gint            row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,9 +27,7 @@
 | 
				
			|||||||
 * method.
 | 
					 * method.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-serializable.h"
 | 
					#include "eek-serializable.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,9 +25,7 @@
 | 
				
			|||||||
 * The #EekSymbolClass class represents a symbol assigned to a key.
 | 
					 * The #EekSymbolClass class represents a symbol assigned to a key.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-symbol.h"
 | 
					#include "eek-symbol.h"
 | 
				
			||||||
#include "eek-serializable.h"
 | 
					#include "eek-serializable.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -23,9 +23,7 @@
 | 
				
			|||||||
 * @short_description: an #EekText represents a text symbol
 | 
					 * @short_description: an #EekText represents a text symbol
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-text.h"
 | 
					#include "eek-text.h"
 | 
				
			||||||
#include "eek-serializable.h"
 | 
					#include "eek-serializable.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -19,9 +19,7 @@
 | 
				
			|||||||
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-theme.h"
 | 
					#include "eek-theme.h"
 | 
				
			||||||
#include "eek-theme-context.h"
 | 
					#include "eek-theme-context.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -23,9 +23,7 @@
 | 
				
			|||||||
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -24,9 +24,7 @@
 | 
				
			|||||||
 * @short_description: Miscellaneous types used in Libeek
 | 
					 * @short_description: Miscellaneous types used in Libeek
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -21,9 +21,7 @@
 | 
				
			|||||||
 * @short_description: Layout engine which loads layout information from XML
 | 
					 * @short_description: Layout engine which loads layout information from XML
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gio/gio.h> /* GResource */
 | 
					#include <gio/gio.h> /* GResource */
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
@ -81,10 +79,6 @@ static gboolean      parse_symbols   (const gchar         *path,
 | 
				
			|||||||
                                      EekKeyboard         *keyboard,
 | 
					                                      EekKeyboard         *keyboard,
 | 
				
			||||||
                                      GError             **error);
 | 
					                                      GError             **error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void          scale_keyboard  (EekKeyboard         *keyboard,
 | 
					 | 
				
			||||||
                                      gdouble              width,
 | 
					 | 
				
			||||||
                                      gdouble              height);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean      validate        (const gchar        **valid_path_list,
 | 
					static gboolean      validate        (const gchar        **valid_path_list,
 | 
				
			||||||
                                      gsize                valid_path_list_len,
 | 
					                                      gsize                valid_path_list_len,
 | 
				
			||||||
                                      const gchar         *element_name,
 | 
					                                      const gchar         *element_name,
 | 
				
			||||||
@ -249,6 +243,7 @@ struct _GeometryParseData {
 | 
				
			|||||||
    gchar *name;
 | 
					    gchar *name;
 | 
				
			||||||
    EekOutline outline;
 | 
					    EekOutline outline;
 | 
				
			||||||
    gchar *oref;
 | 
					    gchar *oref;
 | 
				
			||||||
 | 
					    gint keycode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GHashTable *key_oref_hash;
 | 
					    GHashTable *key_oref_hash;
 | 
				
			||||||
    GHashTable *oref_outline_hash;
 | 
					    GHashTable *oref_outline_hash;
 | 
				
			||||||
@ -271,6 +266,7 @@ geometry_parse_data_new (EekKeyboard *keyboard)
 | 
				
			|||||||
                               g_str_equal,
 | 
					                               g_str_equal,
 | 
				
			||||||
                               g_free,
 | 
					                               g_free,
 | 
				
			||||||
                               (GDestroyNotify)eek_outline_free);
 | 
					                               (GDestroyNotify)eek_outline_free);
 | 
				
			||||||
 | 
					    data->keycode = 8;
 | 
				
			||||||
    return data;
 | 
					    return data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -399,26 +395,29 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
 | 
				
			|||||||
        guint keycode;
 | 
					        guint keycode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
					        attribute = get_attribute (attribute_names, attribute_values,
 | 
				
			||||||
                                   "keycode");
 | 
					                                   "name");
 | 
				
			||||||
        if (attribute == NULL) {
 | 
					        if (attribute == NULL) {
 | 
				
			||||||
            g_set_error (error,
 | 
					            g_set_error (error,
 | 
				
			||||||
                         G_MARKUP_ERROR,
 | 
					                         G_MARKUP_ERROR,
 | 
				
			||||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
					                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
				
			||||||
                         "no \"keycode\" attribute for \"key\"");
 | 
					                         "no \"name\" attribute for \"key\"");
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        keycode = strtoul (attribute, NULL, 10);
 | 
					        gchar *name = g_strdup (attribute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        attribute = get_attribute (attribute_names, attribute_values,
 | 
				
			||||||
 | 
					                                   "keycode");
 | 
				
			||||||
 | 
					        if (attribute != NULL)
 | 
				
			||||||
 | 
					            keycode = strtol (attribute, NULL, 10);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            keycode = data->keycode++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data->key = eek_section_create_key (data->section,
 | 
					        data->key = eek_section_create_key (data->section,
 | 
				
			||||||
 | 
					                                            name,
 | 
				
			||||||
                                            keycode,
 | 
					                                            keycode,
 | 
				
			||||||
                                            data->num_columns,
 | 
					                                            data->num_columns,
 | 
				
			||||||
                                            data->num_rows - 1);
 | 
					                                            data->num_rows - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
					 | 
				
			||||||
                                   "name");
 | 
					 | 
				
			||||||
        if (attribute != NULL)
 | 
					 | 
				
			||||||
            eek_element_set_name (EEK_ELEMENT(data->key), attribute);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
					        attribute = get_attribute (attribute_names, attribute_values,
 | 
				
			||||||
                                   "oref");
 | 
					                                   "oref");
 | 
				
			||||||
        if (attribute == NULL) {
 | 
					        if (attribute == NULL) {
 | 
				
			||||||
@ -622,28 +621,25 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (g_strcmp0 (element_name, "key") == 0) {
 | 
					    if (g_strcmp0 (element_name, "key") == 0) {
 | 
				
			||||||
        guint keycode;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
					        attribute = get_attribute (attribute_names, attribute_values,
 | 
				
			||||||
                                   "keycode");
 | 
					                                   "name");
 | 
				
			||||||
        if (attribute == NULL) {
 | 
					        if (attribute == NULL) {
 | 
				
			||||||
            g_set_error (error,
 | 
					            g_set_error (error,
 | 
				
			||||||
                         G_MARKUP_ERROR,
 | 
					                         G_MARKUP_ERROR,
 | 
				
			||||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
					                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
				
			||||||
                         "no \"keycode\" attribute for \"key\"");
 | 
					                         "no \"name\" attribute for \"key\"");
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        keycode = strtoul (attribute, NULL, 10);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data->key = eek_keyboard_find_key_by_keycode (data->keyboard,
 | 
					        data->key = eek_keyboard_find_key_by_name (data->keyboard,
 | 
				
			||||||
                                                      keycode);
 | 
					                                                   attribute);
 | 
				
			||||||
        /*if (data->key == NULL) {
 | 
					        if (data->key == NULL) {
 | 
				
			||||||
            g_set_error (error,
 | 
					            g_set_error (error,
 | 
				
			||||||
                         G_MARKUP_ERROR,
 | 
					                         G_MARKUP_ERROR,
 | 
				
			||||||
                         G_MARKUP_ERROR_INVALID_CONTENT,
 | 
					                         G_MARKUP_ERROR_INVALID_CONTENT,
 | 
				
			||||||
                         "no such keycode %u", keycode);
 | 
					                         "no such key %s", attribute);
 | 
				
			||||||
            return;
 | 
					        }
 | 
				
			||||||
        }*/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
					        attribute = get_attribute (attribute_names, attribute_values,
 | 
				
			||||||
                                   "groups");
 | 
					                                   "groups");
 | 
				
			||||||
@ -726,7 +722,6 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
 | 
				
			|||||||
        gint levels = num_symbols / data->groups;
 | 
					        gint levels = num_symbols / data->groups;
 | 
				
			||||||
        EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
 | 
					        EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
 | 
				
			||||||
                                                         levels);
 | 
					                                                         levels);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        head = data->symbols = g_slist_reverse (data->symbols);
 | 
					        head = data->symbols = g_slist_reverse (data->symbols);
 | 
				
			||||||
        for (i = 0; i < num_symbols; i++) {
 | 
					        for (i = 0; i < num_symbols; i++) {
 | 
				
			||||||
            if (head && head->data) {
 | 
					            if (head && head->data) {
 | 
				
			||||||
@ -945,8 +940,7 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Fit keyboard in the given width and hight. */
 | 
					    eek_layout_place_sections(keyboard);
 | 
				
			||||||
    scale_keyboard (keyboard, initial_width, initial_height);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Use pre-defined modifier mask here. */
 | 
					    /* Use pre-defined modifier mask here. */
 | 
				
			||||||
    eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
 | 
					    eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
 | 
				
			||||||
@ -1138,38 +1132,6 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc)
 | 
				
			|||||||
    g_slice_free (EekXmlKeyboardDesc, desc);
 | 
					    g_slice_free (EekXmlKeyboardDesc, desc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct place_data {
 | 
					 | 
				
			||||||
    double desired_width;
 | 
					 | 
				
			||||||
    double current_offset;
 | 
					 | 
				
			||||||
    EekKeyboard *keyboard;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const double section_spacing = 7.0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void section_placer(EekElement *element, gpointer user_data) {
 | 
					 | 
				
			||||||
    struct place_data *data = (struct place_data*)user_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds section_bounds = {0};
 | 
					 | 
				
			||||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
					 | 
				
			||||||
    section_bounds.width = data->desired_width;
 | 
					 | 
				
			||||||
    eek_element_set_bounds(element, §ion_bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Sections are rows now. Gather up all the keys and adjust their bounds.
 | 
					 | 
				
			||||||
    eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
					 | 
				
			||||||
    section_bounds.y = data->current_offset;
 | 
					 | 
				
			||||||
    eek_element_set_bounds(element, §ion_bounds);
 | 
					 | 
				
			||||||
    data->current_offset += section_bounds.height + section_spacing;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void section_counter(EekElement *element, gpointer user_data) {
 | 
					 | 
				
			||||||
    double *total_height = user_data;
 | 
					 | 
				
			||||||
    EekBounds section_bounds = {0};
 | 
					 | 
				
			||||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
					 | 
				
			||||||
    *total_height += section_bounds.height + section_spacing;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					static gboolean
 | 
				
			||||||
parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
 | 
					parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -1224,27 +1186,6 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    g_hash_table_destroy (oref_hash);
 | 
					    g_hash_table_destroy (oref_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Order rows */
 | 
					 | 
				
			||||||
    // This needs to be done after outlines, because outlines define key sizes
 | 
					 | 
				
			||||||
    // TODO: do this only for rows without bounds
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // The keyboard width is given by the user via screen size. The height will be given dynamically.
 | 
					 | 
				
			||||||
    // TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
 | 
					 | 
				
			||||||
    EekBounds keyboard_bounds = {0};
 | 
					 | 
				
			||||||
    eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    struct place_data placer_data = {
 | 
					 | 
				
			||||||
        .desired_width = keyboard_bounds.width,
 | 
					 | 
				
			||||||
        .current_offset = 0,
 | 
					 | 
				
			||||||
        .keyboard = keyboard,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    double total_height = 0;
 | 
					 | 
				
			||||||
    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
 | 
					 | 
				
			||||||
    keyboard_bounds.height = total_height;
 | 
					 | 
				
			||||||
    eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    geometry_parse_data_free (data);
 | 
					    geometry_parse_data_free (data);
 | 
				
			||||||
    return TRUE;
 | 
					    return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1410,65 +1351,6 @@ parse_keyboards (const gchar *path, GError **error)
 | 
				
			|||||||
    return keyboards;
 | 
					    return keyboards;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void scale_bounds_callback (EekElement *element,
 | 
					 | 
				
			||||||
                                   gpointer    user_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
scale_bounds (EekElement *element,
 | 
					 | 
				
			||||||
              gdouble     scale)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					 | 
				
			||||||
    bounds.x *= scale;
 | 
					 | 
				
			||||||
    bounds.y *= scale;
 | 
					 | 
				
			||||||
    bounds.width *= scale;
 | 
					 | 
				
			||||||
    bounds.height *= scale;
 | 
					 | 
				
			||||||
    eek_element_set_bounds (element, &bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (EEK_IS_CONTAINER(element))
 | 
					 | 
				
			||||||
        eek_container_foreach_child (EEK_CONTAINER(element),
 | 
					 | 
				
			||||||
                                     scale_bounds_callback,
 | 
					 | 
				
			||||||
                                     &scale);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
scale_bounds_callback (EekElement *element,
 | 
					 | 
				
			||||||
                       gpointer    user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    scale_bounds (element, *(gdouble *)user_data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scale_keyboard (EekKeyboard *keyboard,
 | 
					 | 
				
			||||||
                            gdouble      width,
 | 
					 | 
				
			||||||
                            gdouble      height)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    gdouble scale;
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
    gsize n_outlines;
 | 
					 | 
				
			||||||
    guint i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (width * bounds.height < height * bounds.width)
 | 
					 | 
				
			||||||
        scale = width / bounds.width;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        scale = height / bounds.height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    scale_bounds (EEK_ELEMENT(keyboard), scale);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    n_outlines = eek_keyboard_get_n_outlines (keyboard);
 | 
					 | 
				
			||||||
    for (i = 0; i < n_outlines; i++) {
 | 
					 | 
				
			||||||
        EekOutline *outline = eek_keyboard_get_outline (keyboard, i);
 | 
					 | 
				
			||||||
        gint j;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (j = 0; j < outline->num_points; j++) {
 | 
					 | 
				
			||||||
            outline->points[j].x *= scale;
 | 
					 | 
				
			||||||
            outline->points[j].y *= scale;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					static gboolean
 | 
				
			||||||
validate (const gchar **valid_path_list,
 | 
					validate (const gchar **valid_path_list,
 | 
				
			||||||
          gsize         valid_path_list_len,
 | 
					          gsize         valid_path_list_len,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										317
									
								
								eek/eek-xml.c
									
									
									
									
									
								
							
							
						
						
									
										317
									
								
								eek/eek-xml.c
									
									
									
									
									
								
							@ -1,317 +0,0 @@
 | 
				
			|||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * SECTION: eek-xml
 | 
					 | 
				
			||||||
 * @title: XML Conversion Utilities
 | 
					 | 
				
			||||||
 * @short_description: #EekKeyboard to XML conversion utilities
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdarg.h>
 | 
					 | 
				
			||||||
#include <glib/gprintf.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eek-section.h"
 | 
					 | 
				
			||||||
#include "eek-key.h"
 | 
					 | 
				
			||||||
#include "eek-xml.h"
 | 
					 | 
				
			||||||
#include "eek-keysym.h"
 | 
					 | 
				
			||||||
#include "eek-text.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define g_string_append_indent(string, indent)  \
 | 
					 | 
				
			||||||
    {                                           \
 | 
					 | 
				
			||||||
        gint i;                                 \
 | 
					 | 
				
			||||||
        for (i = 0; i < (indent); i++) {        \
 | 
					 | 
				
			||||||
            g_string_append (string, "    ");   \
 | 
					 | 
				
			||||||
        }                                       \
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
g_string_markup_printf (GString *output, const gchar *format, ...)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    gchar *escaped_text;
 | 
					 | 
				
			||||||
    va_list ap;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    va_start (ap, format);
 | 
					 | 
				
			||||||
    escaped_text = g_markup_vprintf_escaped (format, ap);
 | 
					 | 
				
			||||||
    va_end (ap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_string_append (output, escaped_text);
 | 
					 | 
				
			||||||
    g_free (escaped_text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _OutputCallbackData {
 | 
					 | 
				
			||||||
    GString *output;
 | 
					 | 
				
			||||||
    gint indent;
 | 
					 | 
				
			||||||
    GHashTable *oref_hash;
 | 
					 | 
				
			||||||
    gint key_serial;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
typedef struct _OutputCallbackData OutputCallbackData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
output_bounds (GString *output, EekBounds *bounds)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_string_markup_printf (output,
 | 
					 | 
				
			||||||
                            "<bounds>%lf,%lf,%lf,%lf</bounds>\n",
 | 
					 | 
				
			||||||
                            bounds->x,
 | 
					 | 
				
			||||||
                            bounds->y,
 | 
					 | 
				
			||||||
                            bounds->width,
 | 
					 | 
				
			||||||
                            bounds->height);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
output_symbol_attributes (GString   *output,
 | 
					 | 
				
			||||||
                          EekSymbol *symbol)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (eek_symbol_get_name (symbol) != NULL)
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, " name=\"%s\"",
 | 
					 | 
				
			||||||
                                eek_symbol_get_name (symbol));
 | 
					 | 
				
			||||||
    if (eek_symbol_get_label (symbol) != NULL)
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, " label=\"%s\"",
 | 
					 | 
				
			||||||
                                eek_symbol_get_label (symbol));
 | 
					 | 
				
			||||||
    if (eek_symbol_get_category (symbol) != EEK_SYMBOL_CATEGORY_UNKNOWN)
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, " category=\"%s\"",
 | 
					 | 
				
			||||||
                                eek_symbol_category_get_name (eek_symbol_get_category (symbol)));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
output_key_callback (EekElement *element, gpointer user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    OutputCallbackData *data = user_data;
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
    gint i, num_symbols;
 | 
					 | 
				
			||||||
    EekSymbolMatrix *matrix;
 | 
					 | 
				
			||||||
    gint column, row;
 | 
					 | 
				
			||||||
    guint keycode;
 | 
					 | 
				
			||||||
    gchar *id;
 | 
					 | 
				
			||||||
    gulong oref;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    keycode = eek_key_get_keycode (EEK_KEY(element));
 | 
					 | 
				
			||||||
    if (keycode == EEK_INVALID_KEYCODE)
 | 
					 | 
				
			||||||
        id = g_strdup_printf ("key%d", data->key_serial);
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        id = g_strdup_printf ("keycode%d", keycode);
 | 
					 | 
				
			||||||
    data->key_serial++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_key_get_index (EEK_KEY(element), &column, &row);
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent);
 | 
					 | 
				
			||||||
    if (eek_element_get_name (element))
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                "<key id=\"%s\" name=\"%s\" "
 | 
					 | 
				
			||||||
                                "column=\"%d\" row=\"%d\">\n",
 | 
					 | 
				
			||||||
                                id,
 | 
					 | 
				
			||||||
                                eek_element_get_name (element),
 | 
					 | 
				
			||||||
                                column,
 | 
					 | 
				
			||||||
                                row);
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                "<key id=\"%s\" "
 | 
					 | 
				
			||||||
                                "column=\"%d\" row=\"%d\">\n",
 | 
					 | 
				
			||||||
                                id,
 | 
					 | 
				
			||||||
                                column,
 | 
					 | 
				
			||||||
                                row);
 | 
					 | 
				
			||||||
    g_free (id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
    output_bounds (data->output, &bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    oref = eek_key_get_oref (EEK_KEY(element));
 | 
					 | 
				
			||||||
    if (oref != 0) {
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                "<oref>outline%u</oref>\n",
 | 
					 | 
				
			||||||
                                oref);
 | 
					 | 
				
			||||||
        if (!g_hash_table_lookup (data->oref_hash, (gpointer)oref))
 | 
					 | 
				
			||||||
            g_hash_table_insert (data->oref_hash,
 | 
					 | 
				
			||||||
                                 (gpointer)oref,
 | 
					 | 
				
			||||||
                                 (gpointer)TRUE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    matrix = eek_key_get_symbol_matrix (EEK_KEY(element));
 | 
					 | 
				
			||||||
    num_symbols = matrix->num_groups * matrix->num_levels;
 | 
					 | 
				
			||||||
    if (num_symbols > 0) {
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                "<symbols groups=\"%d\" levels=\"%d\">\n",
 | 
					 | 
				
			||||||
                                matrix->num_groups, matrix->num_levels);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (i = 0; i < num_symbols; i++) {
 | 
					 | 
				
			||||||
            EekSymbol *symbol = matrix->data[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            g_string_append_indent (data->output, data->indent + 2);
 | 
					 | 
				
			||||||
            if (EEK_IS_KEYSYM(symbol)) {
 | 
					 | 
				
			||||||
                guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output, "<keysym");
 | 
					 | 
				
			||||||
                output_symbol_attributes (data->output, symbol);
 | 
					 | 
				
			||||||
                if (xkeysym != EEK_INVALID_KEYSYM)
 | 
					 | 
				
			||||||
                    g_string_markup_printf (data->output, " keyval=\"%u\"",
 | 
					 | 
				
			||||||
                                            xkeysym);
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output, ">%s</keysym>\n",
 | 
					 | 
				
			||||||
                                        eek_symbol_get_name (symbol));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (EEK_IS_TEXT(symbol)) {
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output, "<text");
 | 
					 | 
				
			||||||
                output_symbol_attributes (data->output, symbol);
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                        ">%s</text>\n",
 | 
					 | 
				
			||||||
                                        eek_text_get_text (EEK_TEXT(symbol)));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output, "<symbol");
 | 
					 | 
				
			||||||
                output_symbol_attributes (data->output, symbol);
 | 
					 | 
				
			||||||
                g_string_markup_printf (data->output,
 | 
					 | 
				
			||||||
                                        ">%s</symbol>\n",
 | 
					 | 
				
			||||||
                                        eek_symbol_get_name (symbol));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "</symbols>\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent);
 | 
					 | 
				
			||||||
    g_string_markup_printf (data->output, "</key>\n");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
output_section_callback (EekElement *element, gpointer user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    OutputCallbackData *data = user_data;
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
    gint angle, n_rows, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent);
 | 
					 | 
				
			||||||
    if (eek_element_get_name (element))
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "<section name=\"%s\">\n",
 | 
					 | 
				
			||||||
                                eek_element_get_name (element));
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "<section>\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (element, &bounds);
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
    output_bounds (data->output, &bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    angle = eek_section_get_angle (EEK_SECTION(element));
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
    g_string_markup_printf (data->output, "<angle>%d</angle>\n", angle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    n_rows = eek_section_get_n_rows (EEK_SECTION(element));
 | 
					 | 
				
			||||||
    for (i = 0; i < n_rows; i++) {
 | 
					 | 
				
			||||||
        gint num_columns;
 | 
					 | 
				
			||||||
        EekOrientation orientation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        eek_section_get_row (EEK_SECTION(element),
 | 
					 | 
				
			||||||
                             i,
 | 
					 | 
				
			||||||
                             &num_columns,
 | 
					 | 
				
			||||||
                             &orientation);
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "<row>\n");
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 2);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "<columns>%d</columns>\n",
 | 
					 | 
				
			||||||
                                num_columns);
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 2);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "<orientation>%d</orientation>\n",
 | 
					 | 
				
			||||||
                                orientation);
 | 
					 | 
				
			||||||
        g_string_append_indent (data->output, data->indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (data->output, "</row>\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    data->indent++;
 | 
					 | 
				
			||||||
    eek_container_foreach_child (EEK_CONTAINER(element),
 | 
					 | 
				
			||||||
                                 output_key_callback,
 | 
					 | 
				
			||||||
                                 data);
 | 
					 | 
				
			||||||
    data->indent--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_string_append_indent (data->output, data->indent);
 | 
					 | 
				
			||||||
    g_string_markup_printf (data->output, "</section>\n");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * eek_keyboard_output:
 | 
					 | 
				
			||||||
 * @keyboard: an #EekKeyboard
 | 
					 | 
				
			||||||
 * @output: a GString
 | 
					 | 
				
			||||||
 * @indent: an integer
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Convert @keyboard into the XML format and store it into @output.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    OutputCallbackData data;
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
    gulong oref;
 | 
					 | 
				
			||||||
    GHashTableIter iter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_assert (EEK_IS_KEYBOARD(keyboard));
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
    g_string_append_indent (output, indent);
 | 
					 | 
				
			||||||
    if (eek_element_get_name (EEK_ELEMENT(keyboard)))
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
 | 
					 | 
				
			||||||
                                "<keyboard version=\"%s\" id=\"%s\">\n",
 | 
					 | 
				
			||||||
                                EEK_XML_SCHEMA_VERSION,
 | 
					 | 
				
			||||||
                                eek_element_get_name (EEK_ELEMENT(keyboard)));
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
 | 
					 | 
				
			||||||
                                "<keyboard version=\"%s\">\n",
 | 
					 | 
				
			||||||
                                EEK_XML_SCHEMA_VERSION);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
					 | 
				
			||||||
    g_string_append_indent (output, indent + 1);
 | 
					 | 
				
			||||||
    output_bounds (output, &bounds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.output = output;
 | 
					 | 
				
			||||||
    data.indent = indent;
 | 
					 | 
				
			||||||
    data.oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
 | 
					 | 
				
			||||||
    data.key_serial = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.indent++;
 | 
					 | 
				
			||||||
    eek_container_foreach_child (EEK_CONTAINER(keyboard),
 | 
					 | 
				
			||||||
                                 output_section_callback,
 | 
					 | 
				
			||||||
                                 &data);
 | 
					 | 
				
			||||||
    data.indent--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_hash_table_iter_init (&iter, data.oref_hash);
 | 
					 | 
				
			||||||
    while (g_hash_table_iter_next (&iter, (gpointer *)&oref, NULL)) {
 | 
					 | 
				
			||||||
        EekOutline *outline;
 | 
					 | 
				
			||||||
        gint j;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        outline = eek_keyboard_get_outline (keyboard, oref);
 | 
					 | 
				
			||||||
        g_string_append_indent (output, indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
 | 
					 | 
				
			||||||
        g_string_append_indent (output, indent + 2);
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, "<corner-radius>%lf</corner-radius>\n",
 | 
					 | 
				
			||||||
                                outline->corner_radius);
 | 
					 | 
				
			||||||
        for (j = 0; j < outline->num_points; j++) {
 | 
					 | 
				
			||||||
            g_string_append_indent (output, indent + 2);
 | 
					 | 
				
			||||||
            g_string_markup_printf (output, "<point>%lf,%lf</point>\n",
 | 
					 | 
				
			||||||
                                    outline->points[j].x,
 | 
					 | 
				
			||||||
                                    outline->points[j].y);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        g_string_append_indent (output, indent + 1);
 | 
					 | 
				
			||||||
        g_string_markup_printf (output, "</outline>\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    g_hash_table_destroy (data.oref_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_string_append_indent (output, indent);
 | 
					 | 
				
			||||||
    g_string_markup_printf (output, "</keyboard>\n");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,39 +0,0 @@
 | 
				
			|||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
					 | 
				
			||||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
					 | 
				
			||||||
#error "Only <eek/eek.h> can be included directly."
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef EEK_XML_H
 | 
					 | 
				
			||||||
#define EEK_XML_H 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <glib-object.h>
 | 
					 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					 | 
				
			||||||
#include "eek-xml-layout.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_BEGIN_DECLS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EEK_XML_SCHEMA_VERSION "0.90"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void eek_keyboard_output (EekKeyboard *keyboard,
 | 
					 | 
				
			||||||
                          GString     *output,
 | 
					 | 
				
			||||||
                          gint         indent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_END_DECLS
 | 
					 | 
				
			||||||
#endif  /* EEK_XML_H */
 | 
					 | 
				
			||||||
@ -23,9 +23,7 @@
 | 
				
			|||||||
 * @title: Library Initialization
 | 
					 * @title: Library Initialization
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek.h"
 | 
					#include "eek.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,6 @@
 | 
				
			|||||||
#include "eek-symbol.h"
 | 
					#include "eek-symbol.h"
 | 
				
			||||||
#include "eek-keysym.h"
 | 
					#include "eek-keysym.h"
 | 
				
			||||||
#include "eek-text.h"
 | 
					#include "eek-text.h"
 | 
				
			||||||
#include "eek-xml.h"
 | 
					 | 
				
			||||||
#include "eek-serializable.h"
 | 
					#include "eek-serializable.h"
 | 
				
			||||||
#include "eek-theme.h"
 | 
					#include "eek-theme.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										39
									
								
								eek/keymap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								eek/keymap.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					#include <gdk/gdk.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					squeek_keymap_get_entries_for_keyval (struct xkb_keymap     *xkb_keymap,
 | 
				
			||||||
 | 
					                                      guint          keyval,
 | 
				
			||||||
 | 
					                                      GdkKeymapKey **keys,
 | 
				
			||||||
 | 
					                                      guint          *n_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *keymap_header = "xkb_keymap {\n\
 | 
				
			||||||
 | 
					\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *keymap_keycodes_header = "\
 | 
				
			||||||
 | 
					    xkb_keycodes \"squeekboard\" {\n\n\
 | 
				
			||||||
 | 
					        minimum = 8;\n\
 | 
				
			||||||
 | 
					        maximum = 255;\n\
 | 
				
			||||||
 | 
					\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *keymap_symbols_header = "\
 | 
				
			||||||
 | 
					    xkb_symbols \"squeekboard\" {\n\
 | 
				
			||||||
 | 
					\n\
 | 
				
			||||||
 | 
					        name[Group1] = \"Letters\";\n\
 | 
				
			||||||
 | 
					        name[Group2] = \"Numbers/Symbols\";\n\
 | 
				
			||||||
 | 
					\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *keymap_footer = "\
 | 
				
			||||||
 | 
					    xkb_types \"squeekboard\" {\n\
 | 
				
			||||||
 | 
					\n\
 | 
				
			||||||
 | 
						type \"TWO_LEVEL\" {\n\
 | 
				
			||||||
 | 
					            modifiers = Shift;\n\
 | 
				
			||||||
 | 
					            map[Shift] = Level2;\n\
 | 
				
			||||||
 | 
					            level_name[Level1] = \"Base\";\n\
 | 
				
			||||||
 | 
					            level_name[Level2] = \"Shift\";\n\
 | 
				
			||||||
 | 
						};\n\
 | 
				
			||||||
 | 
					    };\n\
 | 
				
			||||||
 | 
					\n\
 | 
				
			||||||
 | 
					    xkb_compatibility \"squeekboard\" {\n\
 | 
				
			||||||
 | 
					    };\n\
 | 
				
			||||||
 | 
					};";
 | 
				
			||||||
@ -65,9 +65,9 @@ static void layer_surface_configure(void                         *data,
 | 
				
			|||||||
                                    uint32_t                      height)
 | 
					                                    uint32_t                      height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PhoshLayerSurface *self = data;
 | 
					  PhoshLayerSurface *self = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  gtk_window_resize (GTK_WINDOW (self), width, height);
 | 
					  gtk_window_resize (GTK_WINDOW (self), width, height);
 | 
				
			||||||
  zwlr_layer_surface_v1_ack_configure(surface, serial);
 | 
					  zwlr_layer_surface_v1_ack_configure(surface, serial);
 | 
				
			||||||
  gtk_widget_show_all (GTK_WIDGET (self));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_signal_emit (self, signals[CONFIGURED], 0);
 | 
					  g_signal_emit (self, signals[CONFIGURED], 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -180,22 +180,39 @@ phosh_layer_surface_get_property (GObject    *object,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
phosh_layer_surface_constructed (GObject *object)
 | 
					on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
 | 
					  PhoshLayerSurfacePrivate *priv;
 | 
				
			||||||
  PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
 | 
					 | 
				
			||||||
  GdkWindow *gdk_window;
 | 
					  GdkWindow *gdk_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
 | 
					  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
 | 
					  priv = phosh_layer_surface_get_instance_private (self);
 | 
				
			||||||
  /* Realize the window so we can get the GDK window */
 | 
					 | 
				
			||||||
  gtk_widget_realize(GTK_WIDGET (self));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
 | 
					  gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
 | 
				
			||||||
  gdk_wayland_window_set_use_custom_surface (gdk_window);
 | 
					  gdk_wayland_window_set_use_custom_surface (gdk_window);
 | 
				
			||||||
  priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
 | 
					  priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PhoshLayerSurfacePrivate *priv;
 | 
				
			||||||
 | 
					  GdkWindow *gdk_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
 | 
				
			||||||
 | 
					  priv = phosh_layer_surface_get_instance_private (self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!priv->wl_surface) {
 | 
				
			||||||
 | 
					      gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
 | 
				
			||||||
 | 
					      gdk_wayland_window_set_use_custom_surface (gdk_window);
 | 
				
			||||||
 | 
					      priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  g_debug ("Mapped %p", priv->wl_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
 | 
					  priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
 | 
				
			||||||
                                                              priv->wl_surface,
 | 
					                                                              priv->wl_surface,
 | 
				
			||||||
                                                              priv->wl_output,
 | 
					                                                              priv->wl_output,
 | 
				
			||||||
@ -209,8 +226,45 @@ phosh_layer_surface_constructed (GObject *object)
 | 
				
			|||||||
                                     &layer_surface_listener,
 | 
					                                     &layer_surface_listener,
 | 
				
			||||||
                                     self);
 | 
					                                     self);
 | 
				
			||||||
  wl_surface_commit(priv->wl_surface);
 | 
					  wl_surface_commit(priv->wl_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Process all pending events, otherwise we end up sending ack configure
 | 
				
			||||||
 | 
					   * to a not yet configured surface */
 | 
				
			||||||
 | 
					  wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PhoshLayerSurfacePrivate *priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
 | 
				
			||||||
 | 
					  priv = phosh_layer_surface_get_instance_private (self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  priv = phosh_layer_surface_get_instance_private (self);
 | 
				
			||||||
 | 
					  if (priv->layer_surface) {
 | 
				
			||||||
 | 
					    zwlr_layer_surface_v1_destroy(priv->layer_surface);
 | 
				
			||||||
 | 
					    priv->layer_surface = NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  priv->wl_surface = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					phosh_layer_surface_constructed (GObject *object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_signal_connect (self, "realize",
 | 
				
			||||||
 | 
					                    G_CALLBACK (on_phosh_layer_surface_realized),
 | 
				
			||||||
 | 
					                    NULL);
 | 
				
			||||||
 | 
					  g_signal_connect (self, "map",
 | 
				
			||||||
 | 
					                    G_CALLBACK (on_phosh_layer_surface_mapped),
 | 
				
			||||||
 | 
					                    NULL);
 | 
				
			||||||
 | 
					  g_signal_connect (self, "unmap",
 | 
				
			||||||
 | 
					                    G_CALLBACK (on_phosh_layer_surface_unmapped),
 | 
				
			||||||
 | 
					                    NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
phosh_layer_surface_dispose (GObject *object)
 | 
					phosh_layer_surface_dispose (GObject *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -352,6 +406,12 @@ phosh_layer_surface_new (gpointer layer_shell,
 | 
				
			|||||||
                       "wl-output", wl_output);
 | 
					                       "wl-output", wl_output);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * phosh_layer_surface_get_surface:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the layer layer surface or #NULL if the window
 | 
				
			||||||
 | 
					 * is not yet realized.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
struct zwlr_layer_surface_v1 *
 | 
					struct zwlr_layer_surface_v1 *
 | 
				
			||||||
phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
 | 
					phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -363,6 +423,12 @@ phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * phosh_layer_surface_get_wl_surface:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get the layer wayland surface or #NULL if the window
 | 
				
			||||||
 | 
					 * is not yet realized.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
struct wl_surface *
 | 
					struct wl_surface *
 | 
				
			||||||
phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
 | 
					phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -25,11 +25,7 @@
 | 
				
			|||||||
 * implementation of eekboard input context service.
 | 
					 * implementation of eekboard input context service.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eekboard/eekboard-context-service.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@ -38,10 +34,14 @@
 | 
				
			|||||||
#include <sys/random.h> // TODO: this is Linux-specific
 | 
					#include <sys/random.h> // TODO: this is Linux-specific
 | 
				
			||||||
#include <xkbcommon/xkbcommon.h>
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gio/gio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eekboard/key-emitter.h"
 | 
					#include "eekboard/key-emitter.h"
 | 
				
			||||||
#include "wayland.h"
 | 
					#include "wayland.h"
 | 
				
			||||||
//#include "eekboard/eekboard-xklutil.h"
 | 
					
 | 
				
			||||||
//#include "eek/eek-xkl.h"
 | 
					#include "eek/eek-xml-layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eekboard/eekboard-context-service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CSW 640
 | 
					#define CSW 640
 | 
				
			||||||
#define CSH 480
 | 
					#define CSH 480
 | 
				
			||||||
@ -80,12 +80,12 @@ struct _EekboardContextServicePrivate {
 | 
				
			|||||||
    gboolean repeat_triggered;
 | 
					    gboolean repeat_triggered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GSettings *settings;
 | 
					    GSettings *settings;
 | 
				
			||||||
 | 
					    uint32_t hint;
 | 
				
			||||||
 | 
					    uint32_t purpose;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
 | 
					G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*static Display *display = NULL; */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static EekKeyboard *
 | 
					static EekKeyboard *
 | 
				
			||||||
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
					eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
				
			||||||
                                               const gchar            *keyboard_type)
 | 
					                                               const gchar            *keyboard_type)
 | 
				
			||||||
@ -146,17 +146,22 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
				
			|||||||
        g_error("No context created");
 | 
					        g_error("No context created");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct xkb_rule_names rules = { 0 };
 | 
					    gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
 | 
				
			||||||
    rules.layout = strdup(keyboard_type);
 | 
					
 | 
				
			||||||
    struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules,
 | 
					    struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
 | 
				
			||||||
        XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
					        XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(keymap_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xkb_context_unref(context);
 | 
					    xkb_context_unref(context);
 | 
				
			||||||
    if (!keymap) {
 | 
					    if (!keymap) {
 | 
				
			||||||
        g_error("Bad keymap");
 | 
					        g_error("Bad keymap");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    keyboard->keymap = keymap;
 | 
					    keyboard->keymap = keymap;
 | 
				
			||||||
    char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
 | 
					
 | 
				
			||||||
 | 
					    keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
 | 
				
			||||||
    keyboard->keymap_len = strlen(keymap_str) + 1;
 | 
					    keyboard->keymap_len = strlen(keymap_str) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_autofree char *path = strdup("/eek_keymap-XXXXXX");
 | 
					    g_autofree char *path = strdup("/eek_keymap-XXXXXX");
 | 
				
			||||||
    char *r = &path[strlen(path) - 6];
 | 
					    char *r = &path[strlen(path) - 6];
 | 
				
			||||||
    getrandom(r, 6, GRND_NONBLOCK);
 | 
					    getrandom(r, 6, GRND_NONBLOCK);
 | 
				
			||||||
@ -212,12 +217,7 @@ eekboard_context_service_set_property (GObject      *object,
 | 
				
			|||||||
        context->priv->keyboard = g_value_get_object (value);
 | 
					        context->priv->keyboard = g_value_get_object (value);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PROP_VISIBLE:
 | 
					    case PROP_VISIBLE:
 | 
				
			||||||
        /*if (context->priv->keyboard) {
 | 
					        context->priv->visible = g_value_get_boolean (value);
 | 
				
			||||||
            if (g_value_get_boolean (value))
 | 
					 | 
				
			||||||
                eekboard_context_service_show_keyboard (context);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                eekboard_context_service_hide_keyboard (context);
 | 
					 | 
				
			||||||
        }*/
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PROP_FULLSCREEN:
 | 
					    case PROP_FULLSCREEN:
 | 
				
			||||||
        context->priv->fullscreen = g_value_get_boolean (value);
 | 
					        context->priv->fullscreen = g_value_get_boolean (value);
 | 
				
			||||||
@ -289,7 +289,8 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
settings_update_layout(EekboardContextService *context) {
 | 
					settings_update_layout(EekboardContextService *context)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    g_autofree gchar *keyboard_type = NULL;
 | 
					    g_autofree gchar *keyboard_type = NULL;
 | 
				
			||||||
    g_autofree gchar *keyboard_layout = NULL;
 | 
					    g_autofree gchar *keyboard_layout = NULL;
 | 
				
			||||||
    settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
 | 
					    settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
 | 
				
			||||||
@ -301,6 +302,17 @@ settings_update_layout(EekboardContextService *context) {
 | 
				
			|||||||
        keyboard_layout = g_strdup("undefined");
 | 
					        keyboard_layout = g_strdup("undefined");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (priv->purpose) {
 | 
				
			||||||
 | 
					    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
 | 
				
			||||||
 | 
					    case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
 | 
				
			||||||
 | 
					        keyboard_layout = g_strdup("number");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // generic part follows
 | 
					    // generic part follows
 | 
				
			||||||
    static guint keyboard_id = 0;
 | 
					    static guint keyboard_id = 0;
 | 
				
			||||||
    EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
 | 
					    EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
 | 
				
			||||||
@ -588,3 +600,15 @@ void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
				
			|||||||
        WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 | 
					        WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 | 
				
			||||||
        keyboard->keymap_fd, keyboard->keymap_len);
 | 
					        keyboard->keymap_fd, keyboard->keymap_len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
 | 
				
			||||||
 | 
					                                               uint32_t hint, uint32_t purpose)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->hint != hint || priv->purpose != purpose) {
 | 
				
			||||||
 | 
					        priv->hint = hint;
 | 
				
			||||||
 | 
					        priv->purpose = purpose;
 | 
				
			||||||
 | 
					        settings_update_layout(context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,7 @@
 | 
				
			|||||||
#include <eek/eek.h>
 | 
					#include <eek/eek.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
					#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
				
			||||||
 | 
					#include "text-input-unstable-v3-client-protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,5 +105,9 @@ gboolean      eekboard_context_service_get_fullscreen
 | 
				
			|||||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
					void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
				
			||||||
                                         const EekKeyboard *keyboard);
 | 
					                                         const EekKeyboard *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
 | 
				
			||||||
 | 
					                                               uint32_t hint,
 | 
				
			||||||
 | 
					                                               uint32_t purpose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEKBOARD_CONTEXT_SERVICE_H */
 | 
					#endif  /* EEKBOARD_CONTEXT_SERVICE_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -24,9 +24,7 @@
 | 
				
			|||||||
 * context.
 | 
					 * context.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eekboard/eekboard-context.h"
 | 
					#include "eekboard/eekboard-context.h"
 | 
				
			||||||
//#include "eekboard/eekboard-marshalers.h"
 | 
					//#include "eekboard/eekboard-marshalers.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -26,16 +26,16 @@
 | 
				
			|||||||
 * implementation of eekboard service.
 | 
					 * implementation of eekboard service.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eekboard/eekboard-service.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "sm.puri.OSK0.h"
 | 
					#include "sm.puri.OSK0.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gio/gio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eekboard/eekboard-service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    PROP_0,
 | 
					    PROP_0,
 | 
				
			||||||
    PROP_OBJECT_PATH,
 | 
					    PROP_OBJECT_PATH,
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,6 @@
 | 
				
			|||||||
/* This file is responsible for managing keycode data and emitting keycodes. */
 | 
					/* This file is responsible for managing keycode data and emitting keycodes. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eekboard/key-emitter.h"
 | 
					#include "eekboard/key-emitter.h"
 | 
				
			||||||
#include "eekboard/keymap.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gdk/gdk.h>
 | 
					#include <gdk/gdk.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,98 +38,6 @@ typedef struct {
 | 
				
			|||||||
} SeatEmitter;
 | 
					} SeatEmitter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The following functions for keyboard mapping change are direct
 | 
					 | 
				
			||||||
   translation of the code in Caribou (in libcaribou/xadapter.vala):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   - get_replaced_keycode (Caribou: get_reserved_keycode)
 | 
					 | 
				
			||||||
   - replace_keycode
 | 
					 | 
				
			||||||
   - get_keycode_from_gdk_keymap (Caribou: best_keycode_keyval_match)
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Find an unused keycode where a keysym can be assigned. Restricted to Level 1 */
 | 
					 | 
				
			||||||
static guint
 | 
					 | 
				
			||||||
get_replaced_keycode (SeatEmitter *client)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    guint keycode;
 | 
					 | 
				
			||||||
return 0; // FIXME: no xkb allocated yet
 | 
					 | 
				
			||||||
    for (keycode = client->xkb->max_key_code;
 | 
					 | 
				
			||||||
         keycode >= client->xkb->min_key_code;
 | 
					 | 
				
			||||||
         --keycode) {
 | 
					 | 
				
			||||||
        guint offset = client->xkb->map->key_sym_map[keycode].offset;
 | 
					 | 
				
			||||||
        if (client->xkb->map->key_sym_map[keycode].kt_index[0] == XkbOneLevelIndex &&
 | 
					 | 
				
			||||||
            client->xkb->map->syms[offset] != NoSymbol) {
 | 
					 | 
				
			||||||
            return keycode;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Replace keysym assigned to KEYCODE to KEYSYM.  Both args are used
 | 
					 | 
				
			||||||
   as in-out.  If KEYCODE points to 0, this function picks a keycode
 | 
					 | 
				
			||||||
   from the current map and replace the associated keysym to KEYSYM.
 | 
					 | 
				
			||||||
   In that case, the replaced keycode is stored in KEYCODE and the old
 | 
					 | 
				
			||||||
   keysym is stored in KEYSYM.  If otherwise (KEYCODE points to
 | 
					 | 
				
			||||||
   non-zero keycode), it simply changes the current map with the
 | 
					 | 
				
			||||||
   specified KEYCODE and KEYSYM. */
 | 
					 | 
				
			||||||
static gboolean
 | 
					 | 
				
			||||||
replace_keycode (SeatEmitter *emitter,
 | 
					 | 
				
			||||||
                 guint   keycode,
 | 
					 | 
				
			||||||
                 guint  *keysym)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
/*  GdkDisplay *display = gdk_display_get_default ();
 | 
					 | 
				
			||||||
    Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
 | 
					 | 
				
			||||||
    guint old_keysym;
 | 
					 | 
				
			||||||
    int keysyms_per_keycode;
 | 
					 | 
				
			||||||
    KeySym *syms;
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
return TRUE; // FIXME: no xkb allocated at the moment, pretending all is fine
 | 
					 | 
				
			||||||
    g_return_val_if_fail (emitter->xkb->min_key_code <= keycode &&
 | 
					 | 
				
			||||||
                          keycode <= emitter->xkb->max_key_code,
 | 
					 | 
				
			||||||
                          FALSE);
 | 
					 | 
				
			||||||
    g_return_val_if_fail (keysym != NULL, FALSE);
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Update keyboard mapping. Wayland receives keyboard mapping as a string, so XChangeKeyboardMapping needs to translate from the symbol tbale t the string. TODO.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
    syms = XGetKeyboardMapping (xdisplay, keycode, 1, &keysyms_per_keycode);
 | 
					 | 
				
			||||||
    old_keysym = syms[0];
 | 
					 | 
				
			||||||
    syms[0] = *keysym;
 | 
					 | 
				
			||||||
    XChangeKeyboardMapping (xdisplay, keycode, 1, syms, 1);
 | 
					 | 
				
			||||||
    XSync (xdisplay, False);
 | 
					 | 
				
			||||||
    XFree (syms);
 | 
					 | 
				
			||||||
    *keysym = old_keysym;
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
    return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					 | 
				
			||||||
get_keycode_from_gdk_keymap (SeatEmitter *emitter,
 | 
					 | 
				
			||||||
                             guint           keysym,
 | 
					 | 
				
			||||||
                             guint          *keycode,
 | 
					 | 
				
			||||||
                             guint          *modifiers)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GdkKeymapKey *keys, *best_match = NULL;
 | 
					 | 
				
			||||||
    guint n_keys, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!squeek_keymap_get_entries_for_keyval (emitter->keymap, keysym, &keys, &n_keys))
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < n_keys; i++)
 | 
					 | 
				
			||||||
        if ((guint)keys[i].group == emitter->group)
 | 
					 | 
				
			||||||
            best_match = &keys[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!best_match) {
 | 
					 | 
				
			||||||
        g_free (keys);
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    *keycode = best_match->keycode;
 | 
					 | 
				
			||||||
    *modifiers = best_match->level == 1 ? EEK_SHIFT_MASK : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_free (keys);
 | 
					 | 
				
			||||||
    return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int send_virtual_keyboard_key(
 | 
					int send_virtual_keyboard_key(
 | 
				
			||||||
    struct zwp_virtual_keyboard_v1 *keyboard,
 | 
					    struct zwp_virtual_keyboard_v1 *keyboard,
 | 
				
			||||||
    unsigned int keycode,
 | 
					    unsigned int keycode,
 | 
				
			||||||
@ -143,8 +50,8 @@ int send_virtual_keyboard_key(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
send_fake_modifiers_events (SeatEmitter         *emitter,
 | 
					send_fake_modifiers_events (SeatEmitter         *emitter,
 | 
				
			||||||
                              EekModifierType modifiers,
 | 
					                            EekModifierType      modifiers,
 | 
				
			||||||
                              uint32_t        timestamp)
 | 
					                            uint32_t             timestamp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    (void)timestamp;
 | 
					    (void)timestamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,95 +68,6 @@ send_fake_modifiers_events (SeatEmitter         *emitter,
 | 
				
			|||||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, emitter->group);
 | 
					    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, emitter->group);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
send_fake_key_event (SeatEmitter *emitter,
 | 
					 | 
				
			||||||
                     guint    xkeysym,
 | 
					 | 
				
			||||||
                     guint    keyboard_modifiers,
 | 
					 | 
				
			||||||
                     gboolean pressed,
 | 
					 | 
				
			||||||
                     uint32_t timestamp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekModifierType modifiers;
 | 
					 | 
				
			||||||
    guint old_keysym = xkeysym;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_return_if_fail (xkeysym > 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guint keycode;
 | 
					 | 
				
			||||||
    if (!get_keycode_from_gdk_keymap (emitter, xkeysym, &keycode, &modifiers)) {
 | 
					 | 
				
			||||||
        keycode = get_replaced_keycode (emitter);
 | 
					 | 
				
			||||||
        if (keycode == 0) {
 | 
					 | 
				
			||||||
            g_warning ("no available keycode to replace");
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!replace_keycode (emitter, keycode, &old_keysym)) {
 | 
					 | 
				
			||||||
            g_warning ("failed to lookup X keysym %X", xkeysym);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /* Clear level shift modifiers */
 | 
					 | 
				
			||||||
    keyboard_modifiers &= (unsigned)~EEK_SHIFT_MASK;
 | 
					 | 
				
			||||||
    keyboard_modifiers &= (unsigned)~EEK_LOCK_MASK;
 | 
					 | 
				
			||||||
    /* FIXME: may need to remap ISO_Level3_Shift and NumLock */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    modifiers |= keyboard_modifiers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    send_fake_modifiers_events (emitter, modifiers, timestamp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // There's something magical about subtracting/adding 8 to keycodes for some reason
 | 
					 | 
				
			||||||
    send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
 | 
					 | 
				
			||||||
    send_fake_modifiers_events (emitter, modifiers, timestamp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (old_keysym != xkeysym)
 | 
					 | 
				
			||||||
        replace_keycode (emitter, keycode, &old_keysym);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
send_fake_key_events (SeatEmitter *emitter,
 | 
					 | 
				
			||||||
                      EekSymbol *symbol,
 | 
					 | 
				
			||||||
                      EekModifierType      keyboard_modifiers,
 | 
					 | 
				
			||||||
                      gboolean   pressed,
 | 
					 | 
				
			||||||
                      uint32_t   timestamp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* Ignore modifier keys */
 | 
					 | 
				
			||||||
    if (eek_symbol_is_modifier (symbol))
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* If symbol is a text, convert chars in it to keysym */
 | 
					 | 
				
			||||||
    if (EEK_IS_TEXT(symbol)) {
 | 
					 | 
				
			||||||
        const gchar *utf8 = eek_text_get_text (EEK_TEXT(symbol));
 | 
					 | 
				
			||||||
        printf("Attempting to send text %s\n", utf8);
 | 
					 | 
				
			||||||
        /* FIXME:
 | 
					 | 
				
			||||||
        glong items_written;
 | 
					 | 
				
			||||||
        gunichar *ucs4 = g_utf8_to_ucs4_fast (utf8, -1, &items_written);
 | 
					 | 
				
			||||||
        gint i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (i = 0; i < items_written; i++) {
 | 
					 | 
				
			||||||
            guint xkeysym;
 | 
					 | 
				
			||||||
            EekKeysym *keysym;
 | 
					 | 
				
			||||||
            gchar *name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            name = g_strdup_printf ("U%04X", ucs4[i]);
 | 
					 | 
				
			||||||
            xkeysym = XStringToKeysym (name); // TODO: use xkb_get_keysym_from_name
 | 
					 | 
				
			||||||
            g_free (name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            keysym = eek_keysym_new (xkeysym);
 | 
					 | 
				
			||||||
            send_fake_key_events (client,
 | 
					 | 
				
			||||||
                                  EEK_SYMBOL(keysym),
 | 
					 | 
				
			||||||
                                  keyboard_modifiers);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        g_free (ucs4);
 | 
					 | 
				
			||||||
        */
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (EEK_IS_KEYSYM(symbol)) {
 | 
					 | 
				
			||||||
        guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
 | 
					 | 
				
			||||||
        send_fake_key_event (emitter, xkeysym, keyboard_modifiers, pressed, timestamp);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
 | 
					/* 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)
 | 
				
			||||||
@ -284,6 +102,26 @@ update_modifier_info (SeatEmitter *client)
 | 
				
			|||||||
    }*/
 | 
					    }*/
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					send_fake_key (SeatEmitter *emitter,
 | 
				
			||||||
 | 
					               EekKeyboard *keyboard,
 | 
				
			||||||
 | 
					               guint    keycode,
 | 
				
			||||||
 | 
					               guint    keyboard_modifiers,
 | 
				
			||||||
 | 
					               gboolean pressed,
 | 
				
			||||||
 | 
					               uint32_t timestamp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t proto_modifiers = 0;
 | 
				
			||||||
 | 
					    guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
 | 
				
			||||||
 | 
					    uint32_t group = (level / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (keyboard_modifiers & EEK_SHIFT_MASK)
 | 
				
			||||||
 | 
					        proto_modifiers |= 1<<MOD_IDX_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
 | 
				
			||||||
 | 
					    send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
 | 
				
			||||||
 | 
					    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
emit_key_activated (EekboardContextService *manager,
 | 
					emit_key_activated (EekboardContextService *manager,
 | 
				
			||||||
                    EekKeyboard     *keyboard,
 | 
					                    EekKeyboard     *keyboard,
 | 
				
			||||||
@ -324,5 +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_events (&emitter, symbol, modifiers, pressed, timestamp);
 | 
					    send_fake_key (&emitter, keyboard, keycode, modifiers, pressed, timestamp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include <X11/XKBlib.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek/eek.h"
 | 
					#include "eek/eek.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,66 +0,0 @@
 | 
				
			|||||||
/* GDK - The GIMP Drawing Kit
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 Red Hat, Inc.
 | 
					 | 
				
			||||||
 * Copyright (C) 2019 Purism, SPC
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU Lesser General Public
 | 
					 | 
				
			||||||
 * License as published by the Free Software Foundation; either
 | 
					 | 
				
			||||||
 * version 2 of the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
 | 
					 | 
				
			||||||
 * Lesser General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Lesser General Public
 | 
					 | 
				
			||||||
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Modified for squeekboard based on GTK
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "keymap.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gboolean
 | 
					 | 
				
			||||||
squeek_keymap_get_entries_for_keyval (struct xkb_keymap     *xkb_keymap,
 | 
					 | 
				
			||||||
                                      guint          keyval,
 | 
					 | 
				
			||||||
                                      GdkKeymapKey **keys,
 | 
					 | 
				
			||||||
                                      guint          *n_keys)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  GArray *retval;
 | 
					 | 
				
			||||||
  guint keycode;
 | 
					 | 
				
			||||||
  xkb_keycode_t min_keycode, max_keycode;
 | 
					 | 
				
			||||||
  retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
 | 
					 | 
				
			||||||
  min_keycode = xkb_keymap_min_keycode (xkb_keymap);
 | 
					 | 
				
			||||||
  max_keycode = xkb_keymap_max_keycode (xkb_keymap);
 | 
					 | 
				
			||||||
  for (keycode = min_keycode; keycode < max_keycode; keycode++)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      xkb_layout_index_t num_layouts, layout;
 | 
					 | 
				
			||||||
      num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, keycode);
 | 
					 | 
				
			||||||
      for (layout = 0; layout < num_layouts; layout++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          xkb_layout_index_t num_levels, level;
 | 
					 | 
				
			||||||
          num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
 | 
					 | 
				
			||||||
          for (level = 0; level < num_levels; level++)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              const xkb_keysym_t *syms;
 | 
					 | 
				
			||||||
              gint num_syms, sym;
 | 
					 | 
				
			||||||
              num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
 | 
					 | 
				
			||||||
              for (sym = 0; sym < num_syms; sym++)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                  if (syms[sym] == keyval)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                      GdkKeymapKey key;
 | 
					 | 
				
			||||||
                      key.keycode = keycode;
 | 
					 | 
				
			||||||
                      key.group = (gint)layout;
 | 
					 | 
				
			||||||
                      key.level = (gint)level;
 | 
					 | 
				
			||||||
                      g_array_append_val (retval, key);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  *n_keys = retval->len;
 | 
					 | 
				
			||||||
  *keys = (GdkKeymapKey*) g_array_free (retval, FALSE);
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,8 +0,0 @@
 | 
				
			|||||||
#include <gdk/gdk.h>
 | 
					 | 
				
			||||||
#include <xkbcommon/xkbcommon.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gboolean
 | 
					 | 
				
			||||||
squeek_keymap_get_entries_for_keyval (struct xkb_keymap     *xkb_keymap,
 | 
					 | 
				
			||||||
                                      guint          keyval,
 | 
					 | 
				
			||||||
                                      GdkKeymapKey **keys,
 | 
					 | 
				
			||||||
                                      guint          *n_keys);
 | 
					 | 
				
			||||||
							
								
								
									
										23
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								meson.build
									
									
									
									
									
								
							@ -4,7 +4,21 @@ project(
 | 
				
			|||||||
    version: '1.0.10',
 | 
					    version: '1.0.10',
 | 
				
			||||||
    license: 'GPLv3',
 | 
					    license: 'GPLv3',
 | 
				
			||||||
    meson_version: '>=0.49.0',
 | 
					    meson_version: '>=0.49.0',
 | 
				
			||||||
    default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ],
 | 
					    default_options: [
 | 
				
			||||||
 | 
					        'warning_level=1',
 | 
				
			||||||
 | 
					        'buildtype=debugoptimized',
 | 
				
			||||||
 | 
					        'c_std=gnu11'
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_project_arguments(
 | 
				
			||||||
 | 
					  [
 | 
				
			||||||
 | 
					    '-Werror=implicit-function-declaration',
 | 
				
			||||||
 | 
					    '-Werror=implicit-fallthrough=3',
 | 
				
			||||||
 | 
					    '-Werror=maybe-uninitialized',
 | 
				
			||||||
 | 
					#    '-Werror=missing-field-initializers', // fix eek-unicode-keysym-entries first
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  language: 'c'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i18n = import('i18n')
 | 
					i18n = import('i18n')
 | 
				
			||||||
@ -28,17 +42,11 @@ else
 | 
				
			|||||||
endif
 | 
					endif
 | 
				
			||||||
dbusdir = join_paths(depdatadir, 'dbus-1/interfaces')
 | 
					dbusdir = join_paths(depdatadir, 'dbus-1/interfaces')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsound_dep = dependency('gsound', required : false)
 | 
					 | 
				
			||||||
if gsound_dep.found()
 | 
					 | 
				
			||||||
  conf_data.set10('HAVE_GSOUND', true)
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
summary = [
 | 
					summary = [
 | 
				
			||||||
        '',
 | 
					        '',
 | 
				
			||||||
        '------------------',
 | 
					        '------------------',
 | 
				
			||||||
        'squeekboard @0@'.format(meson.project_version()),
 | 
					        'squeekboard @0@'.format(meson.project_version()),
 | 
				
			||||||
        '',
 | 
					        '',
 | 
				
			||||||
        '   gsound: @0@'.format(conf_data.get('HAVE_GSOUND', false)),
 | 
					 | 
				
			||||||
        '------------------',
 | 
					        '------------------',
 | 
				
			||||||
        ''
 | 
					        ''
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@ -49,3 +57,4 @@ subdir('protocols')
 | 
				
			|||||||
subdir('eek')
 | 
					subdir('eek')
 | 
				
			||||||
subdir('src')
 | 
					subdir('src')
 | 
				
			||||||
subdir('po')
 | 
					subdir('po')
 | 
				
			||||||
 | 
					subdir('tests')
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1,8 @@
 | 
				
			|||||||
option('depdatadir', type : 'string', value : '', description : 'System data path. Will be searched for definitions instead of datadir when provided')
 | 
					option('depdatadir',
 | 
				
			||||||
 | 
					       type : 'string',
 | 
				
			||||||
 | 
					       value : '',
 | 
				
			||||||
 | 
					       description : 'System data path. Will be searched for definitions instead of datadir when provided')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option('tests',
 | 
				
			||||||
 | 
					       type: 'boolean', value: true,
 | 
				
			||||||
 | 
					       description: 'Whether to compile unit tests')
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ wl_protos = [
 | 
				
			|||||||
  'wlr-layer-shell-unstable-v1.xml',
 | 
					  'wlr-layer-shell-unstable-v1.xml',
 | 
				
			||||||
  'virtual-keyboard-unstable-v1.xml',
 | 
					  'virtual-keyboard-unstable-v1.xml',
 | 
				
			||||||
  'input-method-unstable-v2.xml',
 | 
					  'input-method-unstable-v2.xml',
 | 
				
			||||||
 | 
					  'text-input-unstable-v3.xml'
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
wl_proto_sources = []
 | 
					wl_proto_sources = []
 | 
				
			||||||
foreach proto: wl_protos
 | 
					foreach proto: wl_protos
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										441
									
								
								protocols/text-input-unstable-v3.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								protocols/text-input-unstable-v3.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,441 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<protocol name="text_input_unstable_v3">
 | 
				
			||||||
 | 
					  <copyright>
 | 
				
			||||||
 | 
					    Copyright © 2012, 2013 Intel Corporation
 | 
				
			||||||
 | 
					    Copyright © 2015, 2016 Jan Arne Petersen
 | 
				
			||||||
 | 
					    Copyright © 2017, 2018 Red Hat, Inc.
 | 
				
			||||||
 | 
					    Copyright © 2018       Purism SPC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Permission to use, copy, modify, distribute, and sell this
 | 
				
			||||||
 | 
					    software and its documentation for any purpose is hereby granted
 | 
				
			||||||
 | 
					    without fee, provided that the above copyright notice appear in
 | 
				
			||||||
 | 
					    all copies and that both that copyright notice and this permission
 | 
				
			||||||
 | 
					    notice appear in supporting documentation, and that the name of
 | 
				
			||||||
 | 
					    the copyright holders not be used in advertising or publicity
 | 
				
			||||||
 | 
					    pertaining to distribution of the software without specific,
 | 
				
			||||||
 | 
					    written prior permission.  The copyright holders make no
 | 
				
			||||||
 | 
					    representations about the suitability of this software for any
 | 
				
			||||||
 | 
					    purpose.  It is provided "as is" without express or implied
 | 
				
			||||||
 | 
					    warranty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 | 
				
			||||||
 | 
					    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
				
			||||||
 | 
					    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | 
				
			||||||
 | 
					    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | 
				
			||||||
 | 
					    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
				
			||||||
 | 
					    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
				
			||||||
 | 
					    THIS SOFTWARE.
 | 
				
			||||||
 | 
					  </copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <description summary="Protocol for composing text">
 | 
				
			||||||
 | 
					    This protocol allows compositors to act as input methods and to send text
 | 
				
			||||||
 | 
					    to applications. A text input object is used to manage state of what are
 | 
				
			||||||
 | 
					    typically text entry fields in the application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This document adheres to the RFC 2119 when using words like "must",
 | 
				
			||||||
 | 
					    "should", "may", etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Warning! The protocol described in this file is experimental and
 | 
				
			||||||
 | 
					    backward incompatible changes may be made. Backward compatible changes
 | 
				
			||||||
 | 
					    may be added together with the corresponding interface version bump.
 | 
				
			||||||
 | 
					    Backward incompatible changes are done by bumping the version number in
 | 
				
			||||||
 | 
					    the protocol and interface names and resetting the interface version.
 | 
				
			||||||
 | 
					    Once the protocol is to be declared stable, the 'z' prefix and the
 | 
				
			||||||
 | 
					    version number in the protocol and interface names are removed and the
 | 
				
			||||||
 | 
					    interface version number is reset.
 | 
				
			||||||
 | 
					  </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="zwp_text_input_v3" version="1">
 | 
				
			||||||
 | 
					    <description summary="text input">
 | 
				
			||||||
 | 
					      The zwp_text_input_v3 interface represents text input and input methods
 | 
				
			||||||
 | 
					      associated with a seat. It provides enter/leave events to follow the
 | 
				
			||||||
 | 
					      text input focus for a seat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Requests are used to enable/disable the text-input object and set
 | 
				
			||||||
 | 
					      state information like surrounding and selected text or the content type.
 | 
				
			||||||
 | 
					      The information about the entered text is sent to the text-input object
 | 
				
			||||||
 | 
					      via the preedit_string and commit_string events.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices
 | 
				
			||||||
 | 
					      must not point to middle bytes inside a code point: they must either
 | 
				
			||||||
 | 
					      point to the first byte of a code point or to the end of the buffer.
 | 
				
			||||||
 | 
					      Lengths must be measured between two valid indices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Focus moving throughout surfaces will result in the emission of
 | 
				
			||||||
 | 
					      zwp_text_input_v3.enter and zwp_text_input_v3.leave events. The focused
 | 
				
			||||||
 | 
					      surface must commit zwp_text_input_v3.enable and
 | 
				
			||||||
 | 
					      zwp_text_input_v3.disable requests as the keyboard focus moves across
 | 
				
			||||||
 | 
					      editable and non-editable elements of the UI. Those two requests are not
 | 
				
			||||||
 | 
					      expected to be paired with each other, the compositor must be able to
 | 
				
			||||||
 | 
					      handle consecutive series of the same request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      State is sent by the state requests (set_surrounding_text,
 | 
				
			||||||
 | 
					      set_content_type and set_cursor_rectangle) and a commit request. After an
 | 
				
			||||||
 | 
					      enter event or disable request all state information is invalidated and
 | 
				
			||||||
 | 
					      needs to be resent by the client.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="Destroy the wp_text_input">
 | 
				
			||||||
 | 
					        Destroy the wp_text_input object. Also disables all surfaces enabled
 | 
				
			||||||
 | 
					        through this wp_text_input object.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="enable">
 | 
				
			||||||
 | 
					      <description summary="Request text input to be enabled">
 | 
				
			||||||
 | 
					        Requests text input on the surface previously obtained from the enter
 | 
				
			||||||
 | 
					        event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This request must be issued every time the active text input changes
 | 
				
			||||||
 | 
					        to a new one, including within the current surface. Use
 | 
				
			||||||
 | 
					        zwp_text_input_v3.disable when there is no longer any input focus on
 | 
				
			||||||
 | 
					        the current surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This request resets all state associated with previous enable, disable,
 | 
				
			||||||
 | 
					        set_surrounding_text, set_text_change_cause, set_content_type, and
 | 
				
			||||||
 | 
					        set_cursor_rectangle requests, as well as the state associated with
 | 
				
			||||||
 | 
					        preedit_string, commit_string, and delete_surrounding_text events.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The set_surrounding_text, set_content_type and set_cursor_rectangle
 | 
				
			||||||
 | 
					        requests must follow if the text input supports the necessary
 | 
				
			||||||
 | 
					        functionality.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        State set with this request is double-buffered. It will get applied on
 | 
				
			||||||
 | 
					        the next zwp_text_input_v3.commit request, and stay valid until the
 | 
				
			||||||
 | 
					        next committed enable or disable request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The changes must be applied by the compositor after issuing a
 | 
				
			||||||
 | 
					        zwp_text_input_v3.commit request.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="disable">
 | 
				
			||||||
 | 
					      <description summary="Disable text input on a surface">
 | 
				
			||||||
 | 
					        Explicitly disable text input on the current surface (typically when
 | 
				
			||||||
 | 
					        there is no focus on any text entry inside the surface).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        State set with this request is double-buffered. It will get applied on
 | 
				
			||||||
 | 
					        the next zwp_text_input_v3.commit request.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_surrounding_text">
 | 
				
			||||||
 | 
					      <description summary="sets the surrounding text">
 | 
				
			||||||
 | 
					        Sets the surrounding plain text around the input, excluding the preedit
 | 
				
			||||||
 | 
					        text.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The client should notify the compositor of any changes in any of the
 | 
				
			||||||
 | 
					        values carried with this request, including changes caused by handling
 | 
				
			||||||
 | 
					        incoming text-input events as well as changes caused by other
 | 
				
			||||||
 | 
					        mechanisms like keyboard typing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the client is unaware of the text around the cursor, it should not
 | 
				
			||||||
 | 
					        issue this request, to signify lack of support to the compositor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Text is UTF-8 encoded, and should include the cursor position, the
 | 
				
			||||||
 | 
					        complete selection and additional characters before and after them.
 | 
				
			||||||
 | 
					        There is a maximum length of wayland messages, so text can not be
 | 
				
			||||||
 | 
					        longer than 4000 bytes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cursor is the byte offset of the cursor within text buffer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Anchor is the byte offset of the selection anchor within text buffer.
 | 
				
			||||||
 | 
					        If there is no selected text, anchor is the same as cursor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If any preedit text is present, it is replaced with a cursor for the
 | 
				
			||||||
 | 
					        purpose of this event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this request are double-buffered. They will get applied
 | 
				
			||||||
 | 
					        on the next zwp_text_input_v3.commit request, and stay valid until the
 | 
				
			||||||
 | 
					        next committed enable or disable request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial state for affected fields is empty, meaning that the text
 | 
				
			||||||
 | 
					        input does not support sending surrounding text. If the empty values
 | 
				
			||||||
 | 
					        get applied, subsequent attempts to change them may have no effect.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="text" type="string"/>
 | 
				
			||||||
 | 
					      <arg name="cursor" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="anchor" type="int"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="change_cause">
 | 
				
			||||||
 | 
					      <description summary="text change reason">
 | 
				
			||||||
 | 
					        Reason for the change of surrounding text or cursor posision.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <entry name="input_method" value="0" summary="input method caused the change"/>
 | 
				
			||||||
 | 
					      <entry name="other" value="1" summary="something else than the input method caused the change"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_text_change_cause">
 | 
				
			||||||
 | 
					      <description summary="indicates the cause of surrounding text change">
 | 
				
			||||||
 | 
					        Tells the compositor why the text surrounding the cursor changed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Whenever the client detects an external change in text, cursor, or
 | 
				
			||||||
 | 
					        anchor posision, it must issue this request to the compositor. This
 | 
				
			||||||
 | 
					        request is intended to give the input method a chance to update the
 | 
				
			||||||
 | 
					        preedit text in an appropriate way, e.g. by removing it when the user
 | 
				
			||||||
 | 
					        starts typing with a keyboard.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cause describes the source of the change.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The value set with this request is double-buffered. It must be applied
 | 
				
			||||||
 | 
					        and reset to initial at the next zwp_text_input_v3.commit request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial value of cause is input_method.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="cause" type="uint" enum="change_cause"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="content_hint" bitfield="true">
 | 
				
			||||||
 | 
					      <description summary="content hint">
 | 
				
			||||||
 | 
					        Content hint is a bitmask to allow to modify the behavior of the text
 | 
				
			||||||
 | 
					        input.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <entry name="none" value="0x0" summary="no special behavior"/>
 | 
				
			||||||
 | 
					      <entry name="completion" value="0x1" summary="suggest word completions"/>
 | 
				
			||||||
 | 
					      <entry name="spellcheck" value="0x2" summary="suggest word corrections"/>
 | 
				
			||||||
 | 
					      <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
 | 
				
			||||||
 | 
					      <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
 | 
				
			||||||
 | 
					      <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
 | 
				
			||||||
 | 
					      <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
 | 
				
			||||||
 | 
					      <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
 | 
				
			||||||
 | 
					      <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
 | 
				
			||||||
 | 
					      <entry name="latin" value="0x100" summary="just Latin characters should be entered"/>
 | 
				
			||||||
 | 
					      <entry name="multiline" value="0x200" summary="the text input is multiline"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <enum name="content_purpose">
 | 
				
			||||||
 | 
					      <description summary="content purpose">
 | 
				
			||||||
 | 
					        The content purpose allows to specify the primary purpose of a text
 | 
				
			||||||
 | 
					        input.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This allows an input method to show special purpose input panels with
 | 
				
			||||||
 | 
					        extra characters or to disallow some characters.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <entry name="normal" value="0" summary="default input, allowing all characters"/>
 | 
				
			||||||
 | 
					      <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
 | 
				
			||||||
 | 
					      <entry name="digits" value="2" summary="allow only digits"/>
 | 
				
			||||||
 | 
					      <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
 | 
				
			||||||
 | 
					      <entry name="phone" value="4" summary="input a phone number"/>
 | 
				
			||||||
 | 
					      <entry name="url" value="5" summary="input an URL"/>
 | 
				
			||||||
 | 
					      <entry name="email" value="6" summary="input an email address"/>
 | 
				
			||||||
 | 
					      <entry name="name" value="7" summary="input a name of a person"/>
 | 
				
			||||||
 | 
					      <entry name="password" value="8" summary="input a password (combine with sensitive_data hint)"/>
 | 
				
			||||||
 | 
					      <entry name="pin" value="9" summary="input is a numeric password (combine with sensitive_data hint)"/>
 | 
				
			||||||
 | 
					      <entry name="date" value="10" summary="input a date"/>
 | 
				
			||||||
 | 
					      <entry name="time" value="11" summary="input a time"/>
 | 
				
			||||||
 | 
					      <entry name="datetime" value="12" summary="input a date and time"/>
 | 
				
			||||||
 | 
					      <entry name="terminal" value="13" summary="input for a terminal"/>
 | 
				
			||||||
 | 
					    </enum>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_content_type">
 | 
				
			||||||
 | 
					      <description summary="set content purpose and hint">
 | 
				
			||||||
 | 
					        Sets the content purpose and content hint. While the purpose is the
 | 
				
			||||||
 | 
					        basic purpose of an input field, the hint flags allow to modify some of
 | 
				
			||||||
 | 
					        the behavior.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this request are double-buffered. They will get applied
 | 
				
			||||||
 | 
					        on the next zwp_text_input_v3.commit request.
 | 
				
			||||||
 | 
					        Subsequent attempts to update them may have no effect. The values
 | 
				
			||||||
 | 
					        remain valid until the next committed enable or disable request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial value for hint is none, and the initial value for purpose
 | 
				
			||||||
 | 
					        is normal.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="hint" type="uint" enum="content_hint"/>
 | 
				
			||||||
 | 
					      <arg name="purpose" type="uint" enum="content_purpose"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="set_cursor_rectangle">
 | 
				
			||||||
 | 
					      <description summary="set cursor position">
 | 
				
			||||||
 | 
					        Marks an area around the cursor as a x, y, width, height rectangle in
 | 
				
			||||||
 | 
					        surface local coordinates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Allows the compositor to put a window with word suggestions near the
 | 
				
			||||||
 | 
					        cursor, without obstructing the text being input.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If the client is unaware of the position of edited text, it should not
 | 
				
			||||||
 | 
					        issue this request, to signify lack of support to the compositor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this request are double-buffered. They will get applied
 | 
				
			||||||
 | 
					        on the next zwp_text_input_v3.commit request, and stay valid until the
 | 
				
			||||||
 | 
					        next committed enable or disable request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial values describing a cursor rectangle are empty. That means
 | 
				
			||||||
 | 
					        the text input does not support describing the cursor area. If the
 | 
				
			||||||
 | 
					        empty values get applied, subsequent attempts to change them may have
 | 
				
			||||||
 | 
					        no effect.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="x" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="y" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="width" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="height" type="int"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="commit">
 | 
				
			||||||
 | 
					      <description summary="commit state">
 | 
				
			||||||
 | 
					        Atomically applies state changes recently sent to the compositor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The commit request establishes and updates the state of the client, and
 | 
				
			||||||
 | 
					        must be issued after any changes to apply them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Text input state (enabled status, content purpose, content hint,
 | 
				
			||||||
 | 
					        surrounding text and change cause, cursor rectangle) is conceptually
 | 
				
			||||||
 | 
					        double-buffered within the context of a text input, i.e. between a
 | 
				
			||||||
 | 
					        committed enable request and the following committed enable or disable
 | 
				
			||||||
 | 
					        request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Protocol requests modify the pending state, as opposed to the current
 | 
				
			||||||
 | 
					        state in use by the input method. A commit request atomically applies
 | 
				
			||||||
 | 
					        all pending state, replacing the current state. After commit, the new
 | 
				
			||||||
 | 
					        pending state is as documented for each related request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Requests are applied in the order of arrival.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Neither current nor pending state are modified unless noted otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The compositor must count the number of commit requests coming from
 | 
				
			||||||
 | 
					        each zwp_text_input_v3 object and use the count as the serial in done
 | 
				
			||||||
 | 
					        events.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="enter">
 | 
				
			||||||
 | 
					      <description summary="enter event">
 | 
				
			||||||
 | 
					        Notification that this seat's text-input focus is on a certain surface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        When the seat has the keyboard capability the text-input focus follows
 | 
				
			||||||
 | 
					        the keyboard focus. This event sets the current surface for the
 | 
				
			||||||
 | 
					        text-input object.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="surface" type="object" interface="wl_surface"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="leave">
 | 
				
			||||||
 | 
					      <description summary="leave event">
 | 
				
			||||||
 | 
					        Notification that this seat's text-input focus is no longer on a
 | 
				
			||||||
 | 
					        certain surface. The client should reset any preedit string previously
 | 
				
			||||||
 | 
					        set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The leave notification clears the current surface. It is sent before
 | 
				
			||||||
 | 
					        the enter notification for the new focus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        When the seat has the keyboard capability the text-input focus follows
 | 
				
			||||||
 | 
					        the keyboard focus.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="surface" type="object" interface="wl_surface"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="preedit_string">
 | 
				
			||||||
 | 
					      <description summary="pre-edit">
 | 
				
			||||||
 | 
					        Notify when a new composing text (pre-edit) should be set at the
 | 
				
			||||||
 | 
					        current cursor position. Any previously set composing text must be
 | 
				
			||||||
 | 
					        removed. Any previously existing selected text must be removed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The argument text contains the pre-edit string buffer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The parameters cursor_begin and cursor_end are counted in bytes
 | 
				
			||||||
 | 
					        relative to the beginning of the submitted text buffer. Cursor should
 | 
				
			||||||
 | 
					        be hidden when both are equal to -1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        They could be represented by the client as a line if both values are
 | 
				
			||||||
 | 
					        the same, or as a text highlight otherwise.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this event are double-buffered. They must be applied
 | 
				
			||||||
 | 
					        and reset to initial on the next zwp_text_input_v3.done event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial value of text is an empty string, and cursor_begin,
 | 
				
			||||||
 | 
					        cursor_end and cursor_hidden are all 0.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="text" type="string" allow-null="true"/>
 | 
				
			||||||
 | 
					      <arg name="cursor_begin" type="int"/>
 | 
				
			||||||
 | 
					      <arg name="cursor_end" type="int"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="commit_string">
 | 
				
			||||||
 | 
					      <description summary="text commit">
 | 
				
			||||||
 | 
					        Notify when text should be inserted into the editor widget. The text to
 | 
				
			||||||
 | 
					        commit could be either just a single character after a key press or the
 | 
				
			||||||
 | 
					        result of some composing (pre-edit).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this event are double-buffered. They must be applied
 | 
				
			||||||
 | 
					        and reset to initial on the next zwp_text_input_v3.done event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial value of text is an empty string.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="text" type="string" allow-null="true"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="delete_surrounding_text">
 | 
				
			||||||
 | 
					      <description summary="delete surrounding text">
 | 
				
			||||||
 | 
					        Notify when the text around the current cursor position should be
 | 
				
			||||||
 | 
					        deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Before_length and after_length are the number of bytes before and after
 | 
				
			||||||
 | 
					        the current cursor index (excluding the selection) to delete.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        If a preedit text is present, in effect before_length is counted from
 | 
				
			||||||
 | 
					        the beginning of it, and after_length from its end (see done event
 | 
				
			||||||
 | 
					        sequence).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Values set with this event are double-buffered. They must be applied
 | 
				
			||||||
 | 
					        and reset to initial on the next zwp_text_input_v3.done event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The initial values of both before_length and after_length are 0.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="before_length" type="uint" summary="length of text before current cursor position"/>
 | 
				
			||||||
 | 
					      <arg name="after_length" type="uint" summary="length of text after current cursor position"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="done">
 | 
				
			||||||
 | 
					      <description summary="apply changes">
 | 
				
			||||||
 | 
					        Instruct the application to apply changes to state requested by the
 | 
				
			||||||
 | 
					        preedit_string, commit_string and delete_surrounding_text events. The
 | 
				
			||||||
 | 
					        state relating to these events is double-buffered, and each one
 | 
				
			||||||
 | 
					        modifies the pending state. This event replaces the current state with
 | 
				
			||||||
 | 
					        the pending state.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The application must proceed by evaluating the changes in the following
 | 
				
			||||||
 | 
					        order:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        1. Replace existing preedit string with the cursor.
 | 
				
			||||||
 | 
					        2. Delete requested surrounding text.
 | 
				
			||||||
 | 
					        3. Insert commit string with the cursor at its end.
 | 
				
			||||||
 | 
					        4. Calculate surrounding text to send.
 | 
				
			||||||
 | 
					        5. Insert new preedit text in cursor position.
 | 
				
			||||||
 | 
					        6. Place cursor inside preedit text.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        The serial number reflects the last state of the zwp_text_input_v3
 | 
				
			||||||
 | 
					        object known to the compositor. The value of the serial argument must
 | 
				
			||||||
 | 
					        be equal to the number of commit requests already issued on that object.
 | 
				
			||||||
 | 
					        When the client receives a done event with a serial different than the
 | 
				
			||||||
 | 
					        number of past commit requests, it must proceed as normal, except it
 | 
				
			||||||
 | 
					        should not change the current state of the zwp_text_input_v3 object.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="serial" type="uint"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="zwp_text_input_manager_v3" version="1">
 | 
				
			||||||
 | 
					    <description summary="text input manager">
 | 
				
			||||||
 | 
					      A factory for text-input objects. This object is a global singleton.
 | 
				
			||||||
 | 
					    </description>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor">
 | 
				
			||||||
 | 
					      <description summary="Destroy the wp_text_input_manager">
 | 
				
			||||||
 | 
					        Destroy the wp_text_input_manager object.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="get_text_input">
 | 
				
			||||||
 | 
					      <description summary="create a new text input object">
 | 
				
			||||||
 | 
					        Creates a new text-input object for a given seat.
 | 
				
			||||||
 | 
					      </description>
 | 
				
			||||||
 | 
					      <arg name="id" type="new_id" interface="zwp_text_input_v3"/>
 | 
				
			||||||
 | 
					      <arg name="seat" type="object" interface="wl_seat"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					</protocol>
 | 
				
			||||||
							
								
								
									
										1350
									
								
								src/bitflags.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1350
									
								
								src/bitflags.rs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -2,5 +2,3 @@
 | 
				
			|||||||
 * Autogenerated by the Meson build system.
 | 
					 * Autogenerated by the Meson build system.
 | 
				
			||||||
 * Do not edit, your changes will be lost.
 | 
					 * Do not edit, your changes will be lost.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
#mesondefine HAVE_GSOUND
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,6 @@
 | 
				
			|||||||
#include "eekboard/eekboard-context-service.h"
 | 
					#include "eekboard/eekboard-context-service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause) {}
 | 
					 | 
				
			||||||
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose) {}
 | 
					 | 
				
			||||||
void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct zwp_input_method_v2_listener input_method_listener = {
 | 
					static const struct zwp_input_method_v2_listener input_method_listener = {
 | 
				
			||||||
    .activate = imservice_handle_input_method_activate,
 | 
					    .activate = imservice_handle_input_method_activate,
 | 
				
			||||||
    .deactivate = imservice_handle_input_method_deactivate,
 | 
					    .deactivate = imservice_handle_input_method_deactivate,
 | 
				
			||||||
@ -25,19 +20,24 @@ struct imservice* get_imservice(EekboardContextService *context,
 | 
				
			|||||||
                                struct wl_seat *seat) {
 | 
					                                struct wl_seat *seat) {
 | 
				
			||||||
    struct zwp_input_method_v2 *im = zwp_input_method_manager_v2_get_input_method(manager, seat);
 | 
					    struct zwp_input_method_v2 *im = zwp_input_method_manager_v2_get_input_method(manager, seat);
 | 
				
			||||||
    struct imservice *imservice = imservice_new(im, context);
 | 
					    struct imservice *imservice = imservice_new(im, context);
 | 
				
			||||||
    zwp_input_method_v2_add_listener(im,
 | 
					
 | 
				
			||||||
        &input_method_listener, imservice);
 | 
					    /* Add a listener, passing the imservice instance to make it available to
 | 
				
			||||||
 | 
					       callbacks. */
 | 
				
			||||||
 | 
					    zwp_input_method_v2_add_listener(im, &input_method_listener, imservice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return imservice;
 | 
					    return imservice;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void imservice_make_visible(EekboardContextService *context,
 | 
					void imservice_make_visible(EekboardContextService *context) {
 | 
				
			||||||
                            struct zwp_input_method_v2 *im) {
 | 
					 | 
				
			||||||
    (void)im;
 | 
					 | 
				
			||||||
    eekboard_context_service_show_keyboard (context);
 | 
					    eekboard_context_service_show_keyboard (context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void imservice_try_hide(EekboardContextService *context,
 | 
					void imservice_try_hide(EekboardContextService *context) {
 | 
				
			||||||
                        struct zwp_input_method_v2 *im) {
 | 
					 | 
				
			||||||
    (void)im;
 | 
					 | 
				
			||||||
    eekboard_context_service_hide_keyboard (context);
 | 
					    eekboard_context_service_hide_keyboard (context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Declared explicitly because _destroy is inline,
 | 
				
			||||||
 | 
					/// making it unavailable in Rust
 | 
				
			||||||
 | 
					void imservice_destroy_im(struct zwp_input_method_v2 *im) {
 | 
				
			||||||
 | 
					    zwp_input_method_v2_destroy(im);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,5 +18,8 @@ void imservice_handle_input_method_deactivate(void *data, struct zwp_input_metho
 | 
				
			|||||||
void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method,
 | 
					void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method,
 | 
				
			||||||
                                       const char *text, uint32_t cursor, uint32_t anchor);
 | 
					                                       const char *text, uint32_t cursor, uint32_t anchor);
 | 
				
			||||||
void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method);
 | 
					void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method);
 | 
				
			||||||
 | 
					void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose);
 | 
				
			||||||
 | 
					void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause);
 | 
				
			||||||
 | 
					void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										226
									
								
								src/imservice.rs
									
									
									
									
									
								
							
							
						
						
									
										226
									
								
								src/imservice.rs
									
									
									
									
									
								
							@ -3,6 +3,11 @@ use std::ffi::CString;
 | 
				
			|||||||
use std::num::Wrapping;
 | 
					use std::num::Wrapping;
 | 
				
			||||||
use std::string::String;
 | 
					use std::string::String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::bitflags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Traits
 | 
				
			||||||
 | 
					use std::convert::TryFrom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Gathers stuff defined in C or called by C
 | 
					/// Gathers stuff defined in C or called by C
 | 
				
			||||||
pub mod c {
 | 
					pub mod c {
 | 
				
			||||||
@ -29,8 +34,10 @@ pub mod c {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    extern "C" {
 | 
					    extern "C" {
 | 
				
			||||||
        fn imservice_make_visible(imservice: *const UIManager);
 | 
					        fn imservice_destroy_im(im: *mut c::InputMethod);
 | 
				
			||||||
        fn imservice_try_hide(imservice: *const UIManager);
 | 
					        fn eekboard_context_service_set_hint_purpose(imservice: *const UIManager, hint: u32, purpose: u32);
 | 
				
			||||||
 | 
					        fn eekboard_context_service_show_keyboard(imservice: *const UIManager);
 | 
				
			||||||
 | 
					        fn eekboard_context_service_hide_keyboard(imservice: *const UIManager);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
					    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
				
			||||||
@ -54,9 +61,9 @@ pub mod c {
 | 
				
			|||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C"
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
    fn imservice_handle_input_method_activate(imservice: *mut IMService,
 | 
					    fn imservice_handle_input_method_activate(imservice: *mut IMService,
 | 
				
			||||||
        _im: *const InputMethod)
 | 
					        im: *const InputMethod)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let imservice = &mut *imservice;
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
        imservice.preedit_string = String::new();
 | 
					        imservice.preedit_string = String::new();
 | 
				
			||||||
        imservice.pending = IMProtocolState {
 | 
					        imservice.pending = IMProtocolState {
 | 
				
			||||||
            active: true,
 | 
					            active: true,
 | 
				
			||||||
@ -67,9 +74,9 @@ pub mod c {
 | 
				
			|||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C"
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
    fn imservice_handle_input_method_deactivate(imservice: *mut IMService,
 | 
					    fn imservice_handle_input_method_deactivate(imservice: *mut IMService,
 | 
				
			||||||
        _im: *const InputMethod)
 | 
					        im: *const InputMethod)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let imservice = &mut *imservice;
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
        imservice.pending = IMProtocolState {
 | 
					        imservice.pending = IMProtocolState {
 | 
				
			||||||
            active: false,
 | 
					            active: false,
 | 
				
			||||||
            ..imservice.pending.clone()
 | 
					            ..imservice.pending.clone()
 | 
				
			||||||
@ -79,23 +86,65 @@ pub mod c {
 | 
				
			|||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C"
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
    fn imservice_handle_surrounding_text(imservice: *mut IMService,
 | 
					    fn imservice_handle_surrounding_text(imservice: *mut IMService,
 | 
				
			||||||
        _im: *const InputMethod,
 | 
					        im: *const InputMethod,
 | 
				
			||||||
        text: *const c_char, cursor: u32, _anchor: u32)
 | 
					        text: *const c_char, cursor: u32, _anchor: u32)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let imservice = &mut *imservice;
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
        imservice.pending = IMProtocolState {
 | 
					        imservice.pending = IMProtocolState {
 | 
				
			||||||
            surrounding_text: into_cstring(text).expect("Received invalid string"),
 | 
					            surrounding_text: into_cstring(text).expect("Received invalid string"),
 | 
				
			||||||
            surrounding_cursor: cursor,
 | 
					            surrounding_cursor: cursor,
 | 
				
			||||||
            ..imservice.pending
 | 
					            ..imservice.pending.clone()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
 | 
					    fn imservice_handle_content_type(imservice: *mut IMService,
 | 
				
			||||||
 | 
					        im: *const InputMethod,
 | 
				
			||||||
 | 
					        hint: u32, purpose: u32)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
 | 
					        imservice.pending = IMProtocolState {
 | 
				
			||||||
 | 
					            content_hint: {
 | 
				
			||||||
 | 
					                ContentHint::from_bits(hint).unwrap_or_else(|| {
 | 
				
			||||||
 | 
					                    eprintln!("Warning: received invalid hint flags");
 | 
				
			||||||
 | 
					                    ContentHint::NONE
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            content_purpose: {
 | 
				
			||||||
 | 
					                ContentPurpose::try_from(purpose).unwrap_or_else(|_e| {
 | 
				
			||||||
 | 
					                    eprintln!("Warning: Received invalid purpose value");
 | 
				
			||||||
 | 
					                    ContentPurpose::Normal
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            ..imservice.pending.clone()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
 | 
					    fn imservice_handle_text_change_cause(imservice: *mut IMService,
 | 
				
			||||||
 | 
					        im: *const InputMethod,
 | 
				
			||||||
 | 
					        cause: u32)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
 | 
					        imservice.pending = IMProtocolState {
 | 
				
			||||||
 | 
					            text_change_cause: {
 | 
				
			||||||
 | 
					                ChangeCause::try_from(cause).unwrap_or_else(|_e| {
 | 
				
			||||||
 | 
					                    eprintln!("Warning: received invalid cause value");
 | 
				
			||||||
 | 
					                    ChangeCause::InputMethod
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            ..imservice.pending.clone()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C"
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
    fn imservice_handle_commit_state(imservice: *mut IMService,
 | 
					    fn imservice_handle_commit_state(imservice: *mut IMService,
 | 
				
			||||||
        _im: *const InputMethod)
 | 
					        im: *const InputMethod)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let imservice = &mut *imservice;
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
        let active_changed = imservice.current.active ^ imservice.pending.active;
 | 
					        let active_changed = imservice.current.active ^ imservice.pending.active;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        imservice.serial += Wrapping(1u32);
 | 
					        imservice.serial += Wrapping(1u32);
 | 
				
			||||||
@ -106,27 +155,174 @@ pub mod c {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        if active_changed {
 | 
					        if active_changed {
 | 
				
			||||||
            if imservice.current.active {
 | 
					            if imservice.current.active {
 | 
				
			||||||
                imservice_make_visible(imservice.ui_manager);
 | 
					                eekboard_context_service_show_keyboard(imservice.ui_manager);
 | 
				
			||||||
 | 
					                eekboard_context_service_set_hint_purpose(
 | 
				
			||||||
 | 
					                    imservice.ui_manager,
 | 
				
			||||||
 | 
					                    imservice.current.content_hint.bits(),
 | 
				
			||||||
 | 
					                    imservice.current.content_purpose.clone() as u32);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                imservice_try_hide(imservice.ui_manager);
 | 
					                eekboard_context_service_hide_keyboard(imservice.ui_manager);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C"
 | 
				
			||||||
 | 
					    fn imservice_handle_unavailable(imservice: *mut IMService,
 | 
				
			||||||
 | 
					        im: *mut InputMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let imservice = check_imservice(imservice, im).unwrap();
 | 
				
			||||||
 | 
					        imservice_destroy_im(im);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // no need to care about proper double-buffering,
 | 
				
			||||||
 | 
					        // the keyboard is already decommissioned
 | 
				
			||||||
 | 
					        imservice.current.active = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        eekboard_context_service_hide_keyboard(imservice.ui_manager);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // FIXME: destroy and deallocate
 | 
					    // FIXME: destroy and deallocate
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Helpers
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Convenience method for referencing the IMService raw pointer,
 | 
				
			||||||
 | 
					    /// and for verifying that the input method passed along
 | 
				
			||||||
 | 
					    /// matches the one in the `imservice`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The lifetime of the returned value is 'static,
 | 
				
			||||||
 | 
					    /// due to the fact that the lifetime of a raw pointer is undefined.
 | 
				
			||||||
 | 
					    /// Care must be take
 | 
				
			||||||
 | 
					    /// not to exceed the lifetime of the pointer with the reference,
 | 
				
			||||||
 | 
					    /// especially not to store it.
 | 
				
			||||||
 | 
					    fn check_imservice(imservice: *mut IMService, im: *const InputMethod)
 | 
				
			||||||
 | 
					        -> Result<&'static mut IMService, &'static str>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if imservice.is_null() {
 | 
				
			||||||
 | 
					            return Err("Null imservice pointer");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let imservice: &mut IMService = unsafe { &mut *imservice };
 | 
				
			||||||
 | 
					        if im == imservice.im {
 | 
				
			||||||
 | 
					            Ok(imservice)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err("Imservice doesn't contain the input method")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bitflags!{
 | 
				
			||||||
 | 
					    /// Map to `text_input_unstable_v3.content_hint` values
 | 
				
			||||||
 | 
					    pub struct ContentHint: u32 {
 | 
				
			||||||
 | 
					        const NONE = 0x0;
 | 
				
			||||||
 | 
					        const COMPLETION = 0x1;
 | 
				
			||||||
 | 
					        const SPELLCHECK = 0x2;
 | 
				
			||||||
 | 
					        const AUTO_CAPITALIZATION = 0x4;
 | 
				
			||||||
 | 
					        const LOWERCASE = 0x8;
 | 
				
			||||||
 | 
					        const UPPERCASE = 0x10;
 | 
				
			||||||
 | 
					        const TITLECASE = 0x20;
 | 
				
			||||||
 | 
					        const HIDDEN_TEXT = 0x40;
 | 
				
			||||||
 | 
					        const SENSITIVE_DATA = 0x80;
 | 
				
			||||||
 | 
					        const LATIN = 0x100;
 | 
				
			||||||
 | 
					        const MULTILINE = 0x200;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Map to `text_input_unstable_v3.content_purpose` values
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// assert_eq!(ContentPurpose::Alpha as u32, 0);
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub enum ContentPurpose {
 | 
				
			||||||
 | 
					    Normal = 0,
 | 
				
			||||||
 | 
					    Alpha = 1,
 | 
				
			||||||
 | 
					    Digits = 2,
 | 
				
			||||||
 | 
					    Number = 3,
 | 
				
			||||||
 | 
					    Phone = 4,
 | 
				
			||||||
 | 
					    Url = 5,
 | 
				
			||||||
 | 
					    Email = 6,
 | 
				
			||||||
 | 
					    Name = 7,
 | 
				
			||||||
 | 
					    Password = 8,
 | 
				
			||||||
 | 
					    Pin = 9,
 | 
				
			||||||
 | 
					    Date = 10,
 | 
				
			||||||
 | 
					    Time = 11,
 | 
				
			||||||
 | 
					    Datetime = 12,
 | 
				
			||||||
 | 
					    Terminal = 13,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl TryFrom<u32> for ContentPurpose {
 | 
				
			||||||
 | 
					    // There's only one way to fail: number not in protocol,
 | 
				
			||||||
 | 
					    // so no special error type is needed
 | 
				
			||||||
 | 
					    type Error = ();
 | 
				
			||||||
 | 
					    fn try_from(num: u32) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        use self::ContentPurpose::*;
 | 
				
			||||||
 | 
					        match num {
 | 
				
			||||||
 | 
					            0 => Ok(Normal),
 | 
				
			||||||
 | 
					            1 => Ok(Alpha),
 | 
				
			||||||
 | 
					            2 => Ok(Digits),
 | 
				
			||||||
 | 
					            3 => Ok(Number),
 | 
				
			||||||
 | 
					            4 => Ok(Phone),
 | 
				
			||||||
 | 
					            5 => Ok(Url),
 | 
				
			||||||
 | 
					            6 => Ok(Email),
 | 
				
			||||||
 | 
					            7 => Ok(Name),
 | 
				
			||||||
 | 
					            8 => Ok(Password),
 | 
				
			||||||
 | 
					            9 => Ok(Pin),
 | 
				
			||||||
 | 
					            10 => Ok(Date),
 | 
				
			||||||
 | 
					            11 => Ok(Time),
 | 
				
			||||||
 | 
					            12 => Ok(Datetime),
 | 
				
			||||||
 | 
					            13 => Ok(Terminal),
 | 
				
			||||||
 | 
					            _ => Err(()),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Map to `text_input_unstable_v3.change_cause` values
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub enum ChangeCause {
 | 
				
			||||||
 | 
					    InputMethod = 0,
 | 
				
			||||||
 | 
					    Other = 1,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl TryFrom<u32> for ChangeCause {
 | 
				
			||||||
 | 
					    // There's only one way to fail: number not in protocol,
 | 
				
			||||||
 | 
					    // so no special error type is needed
 | 
				
			||||||
 | 
					    type Error = ();
 | 
				
			||||||
 | 
					    fn try_from(num: u32) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        match num {
 | 
				
			||||||
 | 
					            0 => Ok(ChangeCause::InputMethod),
 | 
				
			||||||
 | 
					            1 => Ok(ChangeCause::Other),
 | 
				
			||||||
 | 
					            _ => Err(())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Describes the desired state of the input method as requested by the server
 | 
					/// Describes the desired state of the input method as requested by the server
 | 
				
			||||||
#[derive(Default, Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
struct IMProtocolState {
 | 
					struct IMProtocolState {
 | 
				
			||||||
    surrounding_text: CString,
 | 
					    surrounding_text: CString,
 | 
				
			||||||
    surrounding_cursor: u32,
 | 
					    surrounding_cursor: u32,
 | 
				
			||||||
 | 
					    content_purpose: ContentPurpose,
 | 
				
			||||||
 | 
					    content_hint: ContentHint,
 | 
				
			||||||
 | 
					    text_change_cause: ChangeCause,
 | 
				
			||||||
    active: bool,
 | 
					    active: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Default for IMProtocolState {
 | 
				
			||||||
 | 
					    fn default() -> IMProtocolState {
 | 
				
			||||||
 | 
					        IMProtocolState {
 | 
				
			||||||
 | 
					            surrounding_text: CString::default(),
 | 
				
			||||||
 | 
					            surrounding_cursor: 0, // TODO: mark that there's no cursor
 | 
				
			||||||
 | 
					            content_hint: ContentHint::NONE,
 | 
				
			||||||
 | 
					            content_purpose: ContentPurpose::Normal,
 | 
				
			||||||
 | 
					            text_change_cause: ChangeCause::InputMethod,
 | 
				
			||||||
 | 
					            active: false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct IMService {
 | 
					pub struct IMService {
 | 
				
			||||||
    /// Owned reference (still created and destroyed in C)
 | 
					    /// Owned reference (still created and destroyed in C)
 | 
				
			||||||
    im: *const c::InputMethod,
 | 
					    pub im: *const c::InputMethod,
 | 
				
			||||||
    /// Unowned reference. Be careful, it's shared with C at large
 | 
					    /// Unowned reference. Be careful, it's shared with C at large
 | 
				
			||||||
    ui_manager: *const c::UIManager,
 | 
					    ui_manager: *const c::UIManager,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					#[macro_use]
 | 
				
			||||||
 | 
					mod bitflags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod imservice;
 | 
				
			||||||
@ -4,19 +4,21 @@ dbus_src = gnome.gdbus_codegen(
 | 
				
			|||||||
    join_paths(meson.source_root() / 'data' / 'dbus', 'sm.puri.OSK0.xml')
 | 
					    join_paths(meson.source_root() / 'data' / 'dbus', 'sm.puri.OSK0.xml')
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config_h = configure_file(input: 'config.h.in', output: 'config.h',configuration: conf_data)
 | 
					config_h = configure_file(
 | 
				
			||||||
 | 
					    input: 'config.h.in',
 | 
				
			||||||
 | 
					    output: 'config.h',
 | 
				
			||||||
 | 
					    configuration: conf_data
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sources = [
 | 
					sources = [
 | 
				
			||||||
  config_h,
 | 
					  config_h,
 | 
				
			||||||
  'imservice.c',
 | 
					  'imservice.c',
 | 
				
			||||||
  'server-context-service.c',
 | 
					  'server-context-service.c',
 | 
				
			||||||
  'server-main.c',
 | 
					 | 
				
			||||||
  'wayland.c',
 | 
					  'wayland.c',
 | 
				
			||||||
  '../eek/eek.c',
 | 
					  '../eek/eek.c',
 | 
				
			||||||
  '../eek/eek-container.c',
 | 
					  '../eek/eek-container.c',
 | 
				
			||||||
  '../eek/eek-element.c',
 | 
					  '../eek/eek-element.c',
 | 
				
			||||||
  '../eek/eek-gtk-keyboard.c',
 | 
					  '../eek/eek-gtk-keyboard.c',
 | 
				
			||||||
  '../eek/eek-gtk-renderer.c',
 | 
					 | 
				
			||||||
  '../eek/eek-key.c',
 | 
					  '../eek/eek-key.c',
 | 
				
			||||||
  '../eek/eek-keyboard.c',
 | 
					  '../eek/eek-keyboard.c',
 | 
				
			||||||
  '../eek/eek-keyboard-drawing.c',
 | 
					  '../eek/eek-keyboard-drawing.c',
 | 
				
			||||||
@ -38,7 +40,6 @@ sources = [
 | 
				
			|||||||
  enums,
 | 
					  enums,
 | 
				
			||||||
  keysym_entries,
 | 
					  keysym_entries,
 | 
				
			||||||
  marshalers,
 | 
					  marshalers,
 | 
				
			||||||
  '../eekboard/keymap.c',
 | 
					 | 
				
			||||||
  '../eekboard/key-emitter.c',
 | 
					  '../eekboard/key-emitter.c',
 | 
				
			||||||
  '../eekboard/eekboard-context-service.c',
 | 
					  '../eekboard/eekboard-context-service.c',
 | 
				
			||||||
  '../eekboard/eekboard-context.c',
 | 
					  '../eekboard/eekboard-context.c',
 | 
				
			||||||
@ -63,21 +64,43 @@ deps = [
 | 
				
			|||||||
  cc.find_library('dl'),
 | 
					  cc.find_library('dl'),
 | 
				
			||||||
  cc.find_library('pthread'),
 | 
					  cc.find_library('pthread'),
 | 
				
			||||||
#  dependency('libxklavier'), # FIXME remove
 | 
					#  dependency('libxklavier'), # FIXME remove
 | 
				
			||||||
  gsound_dep,
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Replacement for eekboard-server
 | 
					# Replacement for eekboard-server
 | 
				
			||||||
rslib = static_library(
 | 
					rslib = static_library(
 | 
				
			||||||
  'rslib',
 | 
					  'rslib',
 | 
				
			||||||
  sources: ['imservice.rs'],
 | 
					  sources: ['lib.rs'],
 | 
				
			||||||
  rust_crate_type: 'staticlib'
 | 
					  rust_crate_type: 'staticlib'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
squeekboard = executable('squeekboard',
 | 
					rstests = executable(
 | 
				
			||||||
 | 
					  'rstests',
 | 
				
			||||||
 | 
					  sources: ['lib.rs'],
 | 
				
			||||||
 | 
					  rust_args: ['--test'],
 | 
				
			||||||
 | 
					  install: false
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('rstests', rstests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libsqueekboard = static_library('libsqueekboard',
 | 
				
			||||||
  sources,
 | 
					  sources,
 | 
				
			||||||
  link_with: rslib,
 | 
					  link_with: rslib,
 | 
				
			||||||
  include_directories: [include_directories('..'), include_directories('../eek')],
 | 
					  include_directories: [include_directories('..'), include_directories('../eek')],
 | 
				
			||||||
  dependencies: deps,
 | 
					  dependencies: deps,
 | 
				
			||||||
 | 
					  c_args: [
 | 
				
			||||||
 | 
					    '-DTHEMESDIR="' + pkgdatadir + '/themes"',
 | 
				
			||||||
 | 
					    '-DKEYBOARDSDIR="' + pkgdatadir + '/keyboards"',
 | 
				
			||||||
 | 
					    '-DEEKBOARD_COMPILATION=1',
 | 
				
			||||||
 | 
					    '-DEEK_COMPILATION=1'],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					squeekboard = executable('squeekboard',
 | 
				
			||||||
 | 
					  'server-main.c',
 | 
				
			||||||
 | 
					  wl_proto_sources,
 | 
				
			||||||
 | 
					  squeekboard_resources,
 | 
				
			||||||
 | 
					  link_with: libsqueekboard,
 | 
				
			||||||
 | 
					  include_directories: [include_directories('..'), include_directories('../eek')],
 | 
				
			||||||
 | 
					  dependencies: deps,
 | 
				
			||||||
  install: true,
 | 
					  install: true,
 | 
				
			||||||
  c_args: [
 | 
					  c_args: [
 | 
				
			||||||
    '-DTHEMESDIR="' + pkgdatadir + '/themes"',
 | 
					    '-DTHEMESDIR="' + pkgdatadir + '/themes"',
 | 
				
			||||||
@ -85,4 +108,3 @@ squeekboard = executable('squeekboard',
 | 
				
			|||||||
    '-DEEKBOARD_COMPILATION=1',
 | 
					    '-DEEKBOARD_COMPILATION=1',
 | 
				
			||||||
    '-DEEK_COMPILATION=1'],
 | 
					    '-DEEK_COMPILATION=1'],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -15,15 +15,11 @@
 | 
				
			|||||||
 * You should have received a copy of the GNU General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gtk/gtk.h>
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
#include <glib/gi18n.h>
 | 
					#include <glib/gi18n.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gdk/gdkx.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eek/eek-gtk.h"
 | 
					#include "eek/eek-gtk.h"
 | 
				
			||||||
#include "eek/layersurface.h"
 | 
					#include "eek/layersurface.h"
 | 
				
			||||||
#include "wayland.h"
 | 
					#include "wayland.h"
 | 
				
			||||||
@ -42,13 +38,9 @@ typedef struct _ServerContextServiceClass ServerContextServiceClass;
 | 
				
			|||||||
struct _ServerContextService {
 | 
					struct _ServerContextService {
 | 
				
			||||||
    EekboardContextService parent;
 | 
					    EekboardContextService parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gboolean was_visible;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GtkWidget *window;
 | 
					    GtkWidget *window;
 | 
				
			||||||
    GtkWidget *widget;
 | 
					    GtkWidget *widget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gulong notify_visible_handler;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gdouble size_constraint_landscape[2];
 | 
					    gdouble size_constraint_landscape[2];
 | 
				
			||||||
    gdouble size_constraint_portrait[2];
 | 
					    gdouble size_constraint_portrait[2];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -59,10 +51,7 @@ struct _ServerContextServiceClass {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE (ServerContextService, server_context_service, EEKBOARD_TYPE_CONTEXT_SERVICE);
 | 
					G_DEFINE_TYPE (ServerContextService, server_context_service, EEKBOARD_TYPE_CONTEXT_SERVICE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_widget (ServerContextService *context);
 | 
					 | 
				
			||||||
static void set_geometry  (ServerContextService *context);
 | 
					static void set_geometry  (ServerContextService *context);
 | 
				
			||||||
static void set_dock      (GtkWidget            *widget,
 | 
					 | 
				
			||||||
                           GtkAllocation        *allocation);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
on_monitors_changed (GdkScreen            *screen,
 | 
					on_monitors_changed (GdkScreen            *screen,
 | 
				
			||||||
@ -86,6 +75,9 @@ on_destroy (GtkWidget *widget, gpointer user_data)
 | 
				
			|||||||
    eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
 | 
					    eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					make_widget (ServerContextService *context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
on_notify_keyboard (GObject              *object,
 | 
					on_notify_keyboard (GObject              *object,
 | 
				
			||||||
                    GParamSpec           *spec,
 | 
					                    GParamSpec           *spec,
 | 
				
			||||||
@ -104,22 +96,16 @@ on_notify_keyboard (GObject              *object,
 | 
				
			|||||||
    eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context),
 | 
					    eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context),
 | 
				
			||||||
                                        keyboard);
 | 
					                                        keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (context->window) {
 | 
					    /* Recreate the keyboard widget to keep in sync with the keymap. */
 | 
				
			||||||
        if (keyboard == NULL) {
 | 
					    if (context->window)
 | 
				
			||||||
            gtk_widget_hide (context->window);
 | 
					        make_widget(context);
 | 
				
			||||||
            g_clear_pointer (&context->widget, gtk_widget_destroy);
 | 
					
 | 
				
			||||||
        } else {
 | 
					    gboolean visible;
 | 
				
			||||||
            gboolean was_visible = gtk_widget_get_visible (context->window);
 | 
					    g_object_get (context, "visible", &visible, NULL);
 | 
				
			||||||
            /* avoid to send KeyboardVisibilityChanged */
 | 
					
 | 
				
			||||||
            g_signal_handler_block (context->window,
 | 
					    if (visible) {
 | 
				
			||||||
                                    context->notify_visible_handler);
 | 
					        eekboard_context_service_hide_keyboard(EEKBOARD_CONTEXT_SERVICE(context));
 | 
				
			||||||
            update_widget (context);
 | 
					        eekboard_context_service_show_keyboard(EEKBOARD_CONTEXT_SERVICE(context));
 | 
				
			||||||
            if (was_visible) {
 | 
					 | 
				
			||||||
                gtk_widget_show_all (context->window);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            g_signal_handler_unblock (context->window,
 | 
					 | 
				
			||||||
                                      context->notify_visible_handler);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -133,81 +119,20 @@ on_notify_fullscreen (GObject              *object,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
on_notify_visible (GObject    *object,
 | 
					on_notify_map (GObject    *object,
 | 
				
			||||||
                   GParamSpec *spec,
 | 
					               ServerContextService *context)
 | 
				
			||||||
                   ServerContextService *context)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gboolean visible;
 | 
					    g_object_set (context, "visible", TRUE, NULL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_object_get (object, "visible", &visible, NULL);
 | 
					 | 
				
			||||||
    g_object_set (context, "visible", visible, NULL);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
set_dock (GtkWidget *widget, GtkAllocation *allocation)
 | 
					on_notify_unmap (GObject    *object,
 | 
				
			||||||
 | 
					                 ServerContextService *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef HAVE_XDOCK
 | 
					    g_object_set (context, "visible", FALSE, NULL);
 | 
				
			||||||
    GdkWindow *window = gtk_widget_get_window (widget);
 | 
					 | 
				
			||||||
    long vals[12];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* set window type to dock */
 | 
					 | 
				
			||||||
    gdk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_DOCK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vals[0] = 0;
 | 
					 | 
				
			||||||
    vals[1] = 0;
 | 
					 | 
				
			||||||
    vals[2] = 0;
 | 
					 | 
				
			||||||
    vals[3] = allocation->height;
 | 
					 | 
				
			||||||
    vals[4] = 0;
 | 
					 | 
				
			||||||
    vals[5] = 0;
 | 
					 | 
				
			||||||
    vals[6] = 0;
 | 
					 | 
				
			||||||
    vals[7] = 0;
 | 
					 | 
				
			||||||
    vals[8] = 0;
 | 
					 | 
				
			||||||
    vals[9] = 0;
 | 
					 | 
				
			||||||
    vals[10] = allocation->x;
 | 
					 | 
				
			||||||
    vals[11] = allocation->x + allocation->width;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    XChangeProperty (GDK_WINDOW_XDISPLAY (window),
 | 
					 | 
				
			||||||
                     GDK_WINDOW_XID (window),
 | 
					 | 
				
			||||||
                     XInternAtom (GDK_WINDOW_XDISPLAY (window),
 | 
					 | 
				
			||||||
                                  "_NET_WM_STRUT_PARTIAL", False),
 | 
					 | 
				
			||||||
                     XA_CARDINAL, 32, PropModeReplace,
 | 
					 | 
				
			||||||
                     (guchar *)vals, 12);
 | 
					 | 
				
			||||||
#endif  /* HAVE_XDOCK */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
on_realize_set_dock (GtkWidget *widget,
 | 
					 | 
				
			||||||
                     gpointer   user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GtkAllocation allocation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gtk_widget_get_allocation (widget, &allocation);
 | 
					 | 
				
			||||||
    set_dock (widget, &allocation);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
on_size_allocate_set_dock (GtkWidget *widget,
 | 
					 | 
				
			||||||
                           GdkRectangle *allocation,
 | 
					 | 
				
			||||||
                           gpointer user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (gtk_widget_get_realized (widget))
 | 
					 | 
				
			||||||
        set_dock (widget, allocation);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
on_realize_set_non_maximizable (GtkWidget            *widget,
 | 
					 | 
				
			||||||
                                ServerContextService *context)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_assert (context && context->window == widget);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* make the window not maximizable */
 | 
					 | 
				
			||||||
    gdk_window_set_functions (gtk_widget_get_window (widget),
 | 
					 | 
				
			||||||
                              GDK_FUNC_RESIZE |
 | 
					 | 
				
			||||||
                              GDK_FUNC_MOVE |
 | 
					 | 
				
			||||||
                              GDK_FUNC_MINIMIZE |
 | 
					 | 
				
			||||||
                              GDK_FUNC_CLOSE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
set_geometry (ServerContextService *context)
 | 
					set_geometry (ServerContextService *context)
 | 
				
			||||||
@ -224,13 +149,6 @@ set_geometry (ServerContextService *context)
 | 
				
			|||||||
    gdk_monitor_get_geometry (monitor, &rect);
 | 
					    gdk_monitor_get_geometry (monitor, &rect);
 | 
				
			||||||
    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
					    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_signal_handlers_disconnect_by_func (context->window,
 | 
					 | 
				
			||||||
                                          on_realize_set_dock,
 | 
					 | 
				
			||||||
                                          context);
 | 
					 | 
				
			||||||
    g_signal_handlers_disconnect_by_func (context->window,
 | 
					 | 
				
			||||||
                                          on_realize_set_non_maximizable,
 | 
					 | 
				
			||||||
                                          context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
 | 
					    if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
 | 
				
			||||||
        gint width  = rect.width;
 | 
					        gint width  = rect.width;
 | 
				
			||||||
        gint height = rect.height;
 | 
					        gint height = rect.height;
 | 
				
			||||||
@ -256,22 +174,6 @@ set_geometry (ServerContextService *context)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
 | 
					        gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
 | 
				
			||||||
        gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE);
 | 
					        gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE);
 | 
				
			||||||
        g_signal_connect_after (context->window, "realize",
 | 
					 | 
				
			||||||
                                G_CALLBACK(on_realize_set_dock),
 | 
					 | 
				
			||||||
                                context);
 | 
					 | 
				
			||||||
        g_signal_connect_after (context->window, "size-allocate",
 | 
					 | 
				
			||||||
                                G_CALLBACK(on_size_allocate_set_dock),
 | 
					 | 
				
			||||||
                                context);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        gtk_window_resize (GTK_WINDOW(context->window),
 | 
					 | 
				
			||||||
                           bounds.width,
 | 
					 | 
				
			||||||
                           bounds.height);
 | 
					 | 
				
			||||||
        gtk_window_move (GTK_WINDOW(context->window),
 | 
					 | 
				
			||||||
                         MAX(rect.width - 20 - bounds.width, 0),
 | 
					 | 
				
			||||||
                         MAX(rect.height - 40 - bounds.height, 0));
 | 
					 | 
				
			||||||
        g_signal_connect_after (context->window, "realize",
 | 
					 | 
				
			||||||
                                G_CALLBACK(on_realize_set_non_maximizable),
 | 
					 | 
				
			||||||
                                context);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,18 +195,15 @@ make_window (ServerContextService *context)
 | 
				
			|||||||
        "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
 | 
					        "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
 | 
				
			||||||
        "kbd-interactivity", FALSE,
 | 
					        "kbd-interactivity", FALSE,
 | 
				
			||||||
        "exclusive-zone", KEYBOARD_HEIGHT,
 | 
					        "exclusive-zone", KEYBOARD_HEIGHT,
 | 
				
			||||||
        //"namespace", "phosh home",
 | 
					        "namespace", "osk",
 | 
				
			||||||
        NULL
 | 
					        NULL
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_signal_connect (context->window, "destroy",
 | 
					    g_object_connect (context->window,
 | 
				
			||||||
                      G_CALLBACK(on_destroy),
 | 
					                      "signal::destroy", G_CALLBACK(on_destroy), context,
 | 
				
			||||||
                      context);
 | 
					                      "signal::map", G_CALLBACK(on_notify_map), context,
 | 
				
			||||||
 | 
					                      "signal::unmap", G_CALLBACK(on_notify_unmap), context,
 | 
				
			||||||
    context->notify_visible_handler =
 | 
					                      NULL);
 | 
				
			||||||
        g_signal_connect (context->window, "notify::visible",
 | 
					 | 
				
			||||||
                          G_CALLBACK(on_notify_visible),
 | 
					 | 
				
			||||||
                          context);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The properties below are just to make hacking easier.
 | 
					    // The properties below are just to make hacking easier.
 | 
				
			||||||
    // The way we use layer-shell overrides some,
 | 
					    // The way we use layer-shell overrides some,
 | 
				
			||||||
@ -322,17 +221,18 @@ make_window (ServerContextService *context)
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
destroy_window (ServerContextService *context)
 | 
					destroy_window (ServerContextService *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    gtk_widget_destroy (GTK_WIDGET (context->window));
 | 
				
			||||||
    context->window = NULL;
 | 
					    context->window = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
update_widget (ServerContextService *context)
 | 
					make_widget (ServerContextService *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    EekKeyboard *keyboard;
 | 
					    EekKeyboard *keyboard;
 | 
				
			||||||
    EekTheme *theme;
 | 
					    EekTheme *theme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (context->widget) {
 | 
					    if (context->widget) {
 | 
				
			||||||
        gtk_widget_destroy (context->widget);
 | 
					        gtk_widget_destroy(context->widget);
 | 
				
			||||||
        context->widget = NULL;
 | 
					        context->widget = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -349,6 +249,7 @@ update_widget (ServerContextService *context)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    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);
 | 
				
			||||||
    set_geometry (context);
 | 
					    set_geometry (context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -357,11 +258,14 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
					    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    make_window (context);
 | 
					    if (!context->window)
 | 
				
			||||||
    update_widget (context);
 | 
					        make_window (context);
 | 
				
			||||||
 | 
					    if (!context->widget)
 | 
				
			||||||
 | 
					        make_widget (context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
 | 
					    EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
 | 
				
			||||||
        show_keyboard (_context);
 | 
					        show_keyboard (_context);
 | 
				
			||||||
 | 
					    gtk_widget_show (context->window);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -370,34 +274,11 @@ server_context_service_real_hide_keyboard (EekboardContextService *_context)
 | 
				
			|||||||
    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
					    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gtk_widget_hide (context->window);
 | 
					    gtk_widget_hide (context->window);
 | 
				
			||||||
    g_clear_pointer (&context->widget, gtk_widget_destroy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    destroy_window (context);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
 | 
					    EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
 | 
				
			||||||
        hide_keyboard (_context);
 | 
					        hide_keyboard (_context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
server_context_service_real_enabled (EekboardContextService *_context)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (context->was_visible && context->window)
 | 
					 | 
				
			||||||
        gtk_widget_show_all (context->window);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
server_context_service_real_disabled (EekboardContextService *_context)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (context->window) {
 | 
					 | 
				
			||||||
        context->was_visible = gtk_widget_get_visible (context->window);
 | 
					 | 
				
			||||||
        gtk_widget_hide (context->window);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
server_context_service_real_destroyed (EekboardContextService *_context)
 | 
					server_context_service_real_destroyed (EekboardContextService *_context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -437,7 +318,7 @@ server_context_service_dispose (GObject *object)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
 | 
					    ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_clear_pointer (&context->window, gtk_widget_destroy);
 | 
					    destroy_window (context);
 | 
				
			||||||
    context->widget = NULL;
 | 
					    context->widget = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
 | 
					    G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
 | 
				
			||||||
@ -452,8 +333,6 @@ server_context_service_class_init (ServerContextServiceClass *klass)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    context_class->show_keyboard = server_context_service_real_show_keyboard;
 | 
					    context_class->show_keyboard = server_context_service_real_show_keyboard;
 | 
				
			||||||
    context_class->hide_keyboard = server_context_service_real_hide_keyboard;
 | 
					    context_class->hide_keyboard = server_context_service_real_hide_keyboard;
 | 
				
			||||||
    context_class->enabled = server_context_service_real_enabled;
 | 
					 | 
				
			||||||
    context_class->disabled = server_context_service_real_disabled;
 | 
					 | 
				
			||||||
    context_class->destroyed = server_context_service_real_destroyed;
 | 
					    context_class->destroyed = server_context_service_real_destroyed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gobject_class->set_property = server_context_service_set_property;
 | 
					    gobject_class->set_property = server_context_service_set_property;
 | 
				
			||||||
 | 
				
			|||||||
@ -23,13 +23,7 @@
 | 
				
			|||||||
#include <gtk/gtk.h>
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
#include <glib/gi18n.h>
 | 
					#include <glib/gi18n.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if HAVE_CLUTTER_GTK
 | 
					 | 
				
			||||||
#include <clutter-gtk/clutter-gtk.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eekboard/eekboard-service.h"
 | 
					#include "eekboard/eekboard-service.h"
 | 
				
			||||||
#include "eek/eek.h"
 | 
					#include "eek/eek.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#include "eek/eek.h"
 | 
					#include "eek/eek.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
test_create (void)
 | 
					test_create (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -30,17 +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, 1, 0, 0);
 | 
					    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, 2, 1, 0);
 | 
					    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_type_init ();
 | 
					    gtk_test_init (&argc, &argv, NULL);
 | 
				
			||||||
    g_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 ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,11 +21,10 @@
 | 
				
			|||||||
/* For gdk_x11_display_get_xdisplay().  See main(). */
 | 
					/* For gdk_x11_display_get_xdisplay().  See main(). */
 | 
				
			||||||
#include <gtk/gtk.h>
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#endif  /* HAVE_CONFIG_H */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek/eek.h"
 | 
					#include "eek/eek.h"
 | 
				
			||||||
 | 
					#include "eek/eek-xml-layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
test_output_parse (void)
 | 
					test_output_parse (void)
 | 
				
			||||||
@ -38,7 +37,9 @@ test_output_parse (void)
 | 
				
			|||||||
    layout = eek_xml_layout_new ("us", &error);
 | 
					    layout = eek_xml_layout_new ("us", &error);
 | 
				
			||||||
    g_assert_no_error (error);
 | 
					    g_assert_no_error (error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    keyboard = eek_keyboard_new (layout, 640, 480);
 | 
					    /* We don't need the context service to parse an XML file, so we can pass
 | 
				
			||||||
 | 
					       NULL when creating a keyboard. */
 | 
				
			||||||
 | 
					    keyboard = eek_keyboard_new (NULL, layout, 640, 480);
 | 
				
			||||||
    g_object_unref (layout);
 | 
					    g_object_unref (layout);
 | 
				
			||||||
    g_object_unref (keyboard);
 | 
					    g_object_unref (keyboard);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -46,9 +47,7 @@ test_output_parse (void)
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
main (int argc, char **argv)
 | 
					main (int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_type_init ();
 | 
					    gtk_test_init (&argc, &argv, NULL);
 | 
				
			||||||
    g_test_init (&argc, &argv, NULL);
 | 
					 | 
				
			||||||
    gtk_init (&argc, &argv);  /* for gdk_x11_display_get_xdisplay() */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);
 | 
					    g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										50
									
								
								tests/meson.build
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tests/meson.build
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					if get_option('tests')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_env = [
 | 
				
			||||||
 | 
					  'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
 | 
				
			||||||
 | 
					  'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
 | 
				
			||||||
 | 
					  'G_DEBUG=gc-friendly,fatal-warnings',
 | 
				
			||||||
 | 
					  'GSETTINGS_BACKEND=memory',
 | 
				
			||||||
 | 
					  'MALLOC_CHECK_=2'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_cflags = [
 | 
				
			||||||
 | 
					  '-I@0@/../src'.format(meson.current_source_dir()),
 | 
				
			||||||
 | 
					  '-I@0@/../src'.format(meson.current_build_dir()),
 | 
				
			||||||
 | 
					  '-DEEK_COMPILATION',
 | 
				
			||||||
 | 
					  '-DEEKBOARD_COMPILATION'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_link_args = [
 | 
				
			||||||
 | 
					  '-fPIC',
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests = [
 | 
				
			||||||
 | 
					  'eek-simple-test',
 | 
				
			||||||
 | 
					  'eek-xml-test',
 | 
				
			||||||
 | 
					  'test-keymap-generation'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach name : tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test_sources = [name + '.c']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    t = executable(
 | 
				
			||||||
 | 
					        name,
 | 
				
			||||||
 | 
					        test_sources,
 | 
				
			||||||
 | 
					        squeekboard_resources,
 | 
				
			||||||
 | 
					        link_with: libsqueekboard,
 | 
				
			||||||
 | 
					        c_args : test_cflags,
 | 
				
			||||||
 | 
					        link_args: test_link_args,
 | 
				
			||||||
 | 
					        dependencies: deps,       # from src/meson.build
 | 
				
			||||||
 | 
					        include_directories: [
 | 
				
			||||||
 | 
					            include_directories('..'),
 | 
				
			||||||
 | 
					            include_directories('../eek')
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test(name, t, env: test_env)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endforeach
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
@ -1,181 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0"?>
 | 
					 | 
				
			||||||
<keyboard version="0.90">
 | 
					 | 
				
			||||||
    <bounds>0.000000,0.000000,124.000000,149.000000</bounds>
 | 
					 | 
				
			||||||
    <section name="Keypad">
 | 
					 | 
				
			||||||
        <bounds>10.000000,10.000000,104.000000,129.000000</bounds>
 | 
					 | 
				
			||||||
        <angle>0</angle>
 | 
					 | 
				
			||||||
        <row>
 | 
					 | 
				
			||||||
            <columns>4</columns>
 | 
					 | 
				
			||||||
            <orientation>1</orientation>
 | 
					 | 
				
			||||||
        </row>
 | 
					 | 
				
			||||||
        <row>
 | 
					 | 
				
			||||||
            <columns>4</columns>
 | 
					 | 
				
			||||||
            <orientation>1</orientation>
 | 
					 | 
				
			||||||
        </row>
 | 
					 | 
				
			||||||
        <row>
 | 
					 | 
				
			||||||
            <columns>3</columns>
 | 
					 | 
				
			||||||
            <orientation>1</orientation>
 | 
					 | 
				
			||||||
        </row>
 | 
					 | 
				
			||||||
        <row>
 | 
					 | 
				
			||||||
            <columns>4</columns>
 | 
					 | 
				
			||||||
            <orientation>1</orientation>
 | 
					 | 
				
			||||||
        </row>
 | 
					 | 
				
			||||||
        <row>
 | 
					 | 
				
			||||||
            <columns>2</columns>
 | 
					 | 
				
			||||||
            <orientation>1</orientation>
 | 
					 | 
				
			||||||
        </row>
 | 
					 | 
				
			||||||
        <key id="keycode91" name="KPDL" column="1" row="4">
 | 
					 | 
				
			||||||
            <bounds>54.000000,104.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65439">KP_Delete</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65454">KP_Decimal</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode90" name="KP0" column="0" row="4">
 | 
					 | 
				
			||||||
            <bounds>2.000000,104.000000,50.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline1</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65438">KP_Insert</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65456">KP_0</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode108" name="KPEN" column="3" row="3">
 | 
					 | 
				
			||||||
            <bounds>80.000000,78.000000,24.000000,50.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline2</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="1">
 | 
					 | 
				
			||||||
                <keysym keyval="65421">KP_Enter</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode89" name="KP3" column="2" row="3">
 | 
					 | 
				
			||||||
            <bounds>54.000000,78.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65435">KP_Next</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65459">KP_3</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode88" name="KP2" column="1" row="3">
 | 
					 | 
				
			||||||
            <bounds>28.000000,78.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65433">KP_Down</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65458">KP_2</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode87" name="KP1" column="0" row="3">
 | 
					 | 
				
			||||||
            <bounds>2.000000,78.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65436">KP_End</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65457">KP_1</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode85" name="KP6" column="2" row="2">
 | 
					 | 
				
			||||||
            <bounds>54.000000,53.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65432">KP_Right</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65462">KP_6</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode84" name="KP5" column="1" row="2">
 | 
					 | 
				
			||||||
            <bounds>28.000000,53.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65437">KP_Begin</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65461">KP_5</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode83" name="KP4" column="0" row="2">
 | 
					 | 
				
			||||||
            <bounds>2.000000,53.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65430">KP_Left</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65460">KP_4</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode86" name="KPAD" column="3" row="1">
 | 
					 | 
				
			||||||
            <bounds>80.000000,27.000000,24.000000,50.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline2</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65451">KP_Add</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="269024802"></keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode81" name="KP9" column="2" row="1">
 | 
					 | 
				
			||||||
            <bounds>54.000000,27.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65434">KP_Prior</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65465">KP_9</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode80" name="KP8" column="1" row="1">
 | 
					 | 
				
			||||||
            <bounds>28.000000,27.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65431">KP_Up</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65464">KP_8</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode79" name="KP7" column="0" row="1">
 | 
					 | 
				
			||||||
            <bounds>2.000000,27.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65429">KP_Home</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65463">KP_7</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode82" name="KPSU" column="3" row="0">
 | 
					 | 
				
			||||||
            <bounds>80.000000,1.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65453">KP_Subtract</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="269024803"></keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode63" name="KPMU" column="2" row="0">
 | 
					 | 
				
			||||||
            <bounds>54.000000,1.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65450">KP_Multiply</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="269024801"></keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode112" name="KPDV" column="1" row="0">
 | 
					 | 
				
			||||||
            <bounds>28.000000,1.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65455">KP_Divide</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="269024800"></keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
        <key id="keycode77" name="NMLK" column="0" row="0">
 | 
					 | 
				
			||||||
            <bounds>2.000000,1.000000,24.000000,24.000000</bounds>
 | 
					 | 
				
			||||||
            <outline-ref>outline0</outline-ref>
 | 
					 | 
				
			||||||
            <symbols groups="1" levels="2">
 | 
					 | 
				
			||||||
                <keysym keyval="65407">Num_Lock</keysym>
 | 
					 | 
				
			||||||
                <keysym keyval="65273">Pointer_EnableKeys</keysym>
 | 
					 | 
				
			||||||
            </symbols>
 | 
					 | 
				
			||||||
        </key>
 | 
					 | 
				
			||||||
    </section>
 | 
					 | 
				
			||||||
    <outline id="outline0">
 | 
					 | 
				
			||||||
        <point>0.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>24.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>24.000000,24.000000</point>
 | 
					 | 
				
			||||||
        <point>0.000000,24.000000</point>
 | 
					 | 
				
			||||||
    </outline>
 | 
					 | 
				
			||||||
    <outline id="outline1">
 | 
					 | 
				
			||||||
        <point>0.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>50.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>50.000000,24.000000</point>
 | 
					 | 
				
			||||||
        <point>0.000000,24.000000</point>
 | 
					 | 
				
			||||||
    </outline>
 | 
					 | 
				
			||||||
    <outline id="outline2">
 | 
					 | 
				
			||||||
        <point>0.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>24.000000,0.000000</point>
 | 
					 | 
				
			||||||
        <point>24.000000,50.000000</point>
 | 
					 | 
				
			||||||
        <point>0.000000,50.000000</point>
 | 
					 | 
				
			||||||
    </outline>
 | 
					 | 
				
			||||||
</keyboard>
 | 
					 | 
				
			||||||
							
								
								
									
										72
									
								
								tests/test-keymap-generation.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/test-keymap-generation.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
				
			||||||
 | 
					 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 Purism SPC
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Lesser General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful, but
 | 
				
			||||||
 | 
					 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License along with this library; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
				
			||||||
 | 
					 * 02110-1301 USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* For gdk_x11_display_get_xdisplay().  See main(). */
 | 
				
			||||||
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eek/eek.h"
 | 
				
			||||||
 | 
					#include "eek/eek-xml-layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					test_check_xkb (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EekLayout *layout;
 | 
				
			||||||
 | 
					    EekKeyboard *keyboard;
 | 
				
			||||||
 | 
					    GError *error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    error = NULL;
 | 
				
			||||||
 | 
					    layout = eek_xml_layout_new ("us", &error);
 | 
				
			||||||
 | 
					    g_assert_no_error (error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    keyboard = eek_keyboard_new (NULL, layout, 640, 480);
 | 
				
			||||||
 | 
					    gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 | 
				
			||||||
 | 
					    if (!context) {
 | 
				
			||||||
 | 
					        g_error("No context created");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
 | 
				
			||||||
 | 
					        XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(keymap_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    xkb_context_unref(context);
 | 
				
			||||||
 | 
					    if (!keymap) {
 | 
				
			||||||
 | 
					        g_error("Bad keymap");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_object_unref (layout);
 | 
				
			||||||
 | 
					    g_object_unref (keyboard);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					main (int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gtk_test_init (&argc, &argv, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return g_test_run ();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user