Compare commits

..

120 Commits

Author SHA1 Message Date
8c0b55d7f8 Play sound on key press/release
This needs entries in the sound theme for button-{pressed,released}
which the xdg default one doesn't provide.
2019-07-17 11:57:08 +02:00
72da6d02ae build: Bump meson dep since we use '/' 2019-07-17 11:57:08 +02:00
9c61d8de72 Merge branch 'dbus-prop' into 'master'
EekboardService: Properly toggle keyboard visibility on DBus

Closes #55

See merge request Librem5/squeekboard!80
2019-07-16 13:22:53 +00:00
38133d326b Merge branch 'autogen.sh' into 'master'
Remove more files

See merge request Librem5/squeekboard!81
2019-07-16 11:06:55 +00:00
cc00fcb5c9 Remove more files
autogen.sh is for automake and the TODO refers to eekboard.
2019-07-16 11:00:59 +02:00
53f7a14717 EekboardService: Properly toggle keyboard visibility on DBus
Closes: #55
2019-07-16 10:21:59 +02:00
922495ca06 Merge branch 'remove-unused-files' into 'master'
Remove unused files and functions

See merge request Librem5/squeekboard!79
2019-07-16 07:16:29 +00:00
e5e2e08ff4 Merge branch 'fewer-redraws' into 'master'
keyboard: Schedule widget redraw instead of gdk_window_invalidate_rect

See merge request Librem5/squeekboard!75
2019-07-15 22:57:12 +00:00
c7c410210b Merge branch 'scale' into 'master'
Honor widget scale  factor

See merge request Librem5/squeekboard!56
2019-07-15 22:27:34 +00:00
cb7c214aa0 Merge branch 'fixes' into 'master'
Fixes

See merge request Librem5/squeekboard!74
2019-07-15 22:20:40 +00:00
6f5f49729c Remove unused files and functions 2019-07-15 23:45:17 +02:00
94c9442de1 keyboard: Drop now unused clip_bounds_to_dirty_rectangle() 2019-07-15 17:42:32 +02:00
8c044d0852 keyboard: Schedule widget redraw instead of gdk_window_invalidate_rect
The later would invaliate the drawn area again and again in a ::draw()
handler. This caused infinite redraws when e.g. a key was locked.  To
reproduce break e.g. on `eek_gtk_keyboard_real_draw()` and see how it is
invoked again and again.
2019-07-15 17:42:32 +02:00
1f0cc0a5f3 keyboard: Don't leak on set_keyboard()
Unref and disconnect signals before setting a new keyboard.
2019-07-15 14:12:10 +02:00
5693ce3df7 keyboard: Simplify signal disconnect
We're only keeping the signal ids around for disconnect but that only
happens in dispose so it's o.k.to just disconnect all keyboard signals
we listen to.
2019-07-15 14:12:10 +02:00
bcf04ab11e Merge branch 'exclusive-zone' into 'master'
LayerSurface: Make exclusive zone identical to height

Closes #53

See merge request Librem5/squeekboard!72
2019-07-15 11:55:41 +00:00
086f6bd772 renderer: Only scale by output scale
The original eekboard code scaled icons by a factor. That was simplified
in c529e9ed9c but we can do away with it
completely and fetch the icons at the right size making them not blurry.
2019-07-15 13:23:16 +02:00
d0fa444a0e Honor the outputs scale factor 2019-07-15 13:13:34 +02:00
cd81aeb286 get_icon_surface: Add a scale argument
This will allow us to pass the output scale around
2019-07-15 13:13:34 +02:00
7db33bc92e renderer: Add icons in resource bundle to the icon theme 2019-07-15 13:13:34 +02:00
fb6c501e44 renderer: Use gtk_icon_theme_load_surface
This will allow us to feed in the output scale.
2019-07-15 13:12:26 +02:00
ce7b398f7b LayerSurface: Make exclusive zone identical to height
Othewise we hide content beneath the keyboard.

Closes: #53
2019-07-15 12:49:11 +02:00
4d8d3a8109 Merge branch 'suppress-warnings' into 'master'
Suppress warning message

See merge request Librem5/squeekboard!70
2019-07-13 22:14:54 +00:00
a183cf8b63 Suppress warning message 2019-07-14 00:13:41 +02:00
f834edcf94 Merge branch 'fix-compiler-warnings' into 'master'
Fix use of inappropriate type

See merge request Librem5/squeekboard!69
2019-07-13 19:47:40 +00:00
17802a9408 Fix use of inappropriate type 2019-07-13 18:36:59 +02:00
ac1aad881c Merge branch '49-inconsistent-behaviour-of-shift-key-s-pressed-state' into 'master'
Resolve "Inconsistent behaviour of shift key's pressed state"

Closes #49

See merge request Librem5/squeekboard!66
2019-07-13 16:35:07 +00:00
928110a92d Merge branch 'add-missing-icon' into 'master'
Add keyboard preferences icon

See merge request Librem5/squeekboard!68
2019-07-12 21:09:49 +00:00
f6479fafe2 Add keyboard preferences icon 2019-07-12 23:07:01 +02:00
62b1c2ba84 Revert to latch behavior for letters 2019-07-12 19:54:21 +00:00
c0ac5e540f Merge branch 'add-key-icons' into 'master'
Add key icons

Closes #44

See merge request Librem5/squeekboard!65
2019-07-12 19:17:29 +00:00
fb5ec5557b Make icons smaller 2019-07-12 20:12:09 +02:00
74d94e6792 Merge branch 'remove-unused-xml' into 'master'
Remove unused XML from the US definitions

See merge request Librem5/squeekboard!64
2019-07-12 18:08:55 +00:00
63f4c6b4da Use icons for Shift and Return in the US layout 2019-07-12 20:04:50 +02:00
2774c1c988 Try to load icons from app resources first 2019-07-12 20:04:22 +02:00
469b0c0a9a Add icons to the resource manifest 2019-07-12 20:04:02 +02:00
2ddd217737 Add Enter and Shift icons 2019-07-12 19:16:21 +02:00
c4e8e34ad6 Remove unused XML from the US definitions 2019-07-12 17:15:38 +00:00
4dc18c0af4 Merge branch '27-period-should-not-change-when-caps-lock-is-active' into 'master'
Resolve "Period should not change when caps lock is active"

Closes #27

See merge request Librem5/squeekboard!63
2019-07-12 17:11:10 +00:00
55c6911b87 Remove level with > character from . key 2019-07-12 17:17:11 +02:00
9bf0da5409 Merge branch 'adjust-scaling' into 'master'
Reduce icon size to match platform guidelines

See merge request Librem5/squeekboard!62
2019-07-12 15:15:43 +00:00
7d5b2dd1de Reduce icon size to match platform guidelines 2019-07-12 16:10:31 +02:00
6091632e40 Merge branch 'simplify-geometry-xml' into 'master'
Simplify geometry XML

See merge request Librem5/squeekboard!61
2019-07-12 14:09:57 +00:00
44110fd4d9 Remove bounds for everything except the geometry element 2019-07-12 14:00:20 +00:00
74d76ebfeb Remove unused XML elements 2019-07-12 14:00:20 +00:00
760bc138b0 Test effect of setting attributes to zero 2019-07-12 14:00:20 +00:00
2a4763d4f3 Merge branch 'fix-bottom-margin' into 'master'
Include extra space in the window object

Closes #47

See merge request Librem5/squeekboard!60
2019-07-12 13:42:20 +00:00
4b92f205ef Include extra space in the window object 2019-07-12 10:30:44 +00:00
a5668fa1db Merge branch 'remove-pressed-key-popups' into 'master'
Remove pop-ups for pressed keys

See merge request Librem5/squeekboard!59
2019-07-11 23:42:34 +00:00
de39256377 Remove pop-ups for pressed keys 2019-07-11 23:39:33 +00:00
f53709c83d Merge branch 'fix-bottom-margin' into 'master'
Fix clipping issue at bottom of keyboard

Closes #47

See merge request Librem5/squeekboard!58
2019-07-11 23:07:01 +00:00
8ad0192e55 Fix clipping issue at bottom of keyboard
Closes #47.
2019-07-11 23:04:29 +00:00
791e454cb6 Merge branch 'functioning-views' into 'master'
Basic functioning views

See merge request Librem5/squeekboard!57
2019-07-11 22:58:50 +00:00
c85638be4d Use a dummy, non-emitting key to switch views 2019-07-11 19:38:02 +00:00
a61b1fdf06 Merge branch 'implement-more-view-behavior' into 'master'
Improve view behavior to more closely reflect #38

See merge request Librem5/squeekboard!55
2019-07-11 16:29:26 +00:00
07c25d1d91 Improve view behavior to more closely reflect #38 2019-07-11 16:29:26 +00:00
83dafd87a4 Merge branch 'copyright' into 'master'
Copyright

See merge request Librem5/squeekboard!6
2019-07-11 13:49:00 +00:00
25a8733957 Merge branch 'scale' into 'master'
Simplify icon rendering a bit

See merge request Librem5/squeekboard!52
2019-07-11 13:42:50 +00:00
c529e9ed9c render: Simplify drawing
Instead of doing scale guessing we know that we get a properly
sized image from GTK+ so just scale it down a bit so it gets
some border within the drawing area.
2019-07-11 15:40:18 +02:00
d6a8a85b5e render: Get foreground color only once 2019-07-11 15:40:18 +02:00
3a945535f7 render: Remove trailing white space 2019-07-11 15:40:18 +02:00
0fc4374193 gtk-renderer: Simplify 2019-07-11 15:40:18 +02:00
e350b4ab92 Merge branch 'some-bugfixes' into 'master'
MERGE these: Some bugfixes - the buildsystem is acting up again

See merge request Librem5/squeekboard!53
2019-07-11 13:39:56 +00:00
626527ee09 Merge branch 'feature-xml-resources' into 'master'
FINAL: bundle xml resources, allows running uninstalled from git repo

Closes #29 and #21

See merge request Librem5/squeekboard!49
2019-07-11 13:33:45 +00:00
c4a462c385 Merge branch 'ci' into 'master'
gitlab-ci: No need for our ci repository

See merge request Librem5/squeekboard!54
2019-07-11 13:16:32 +00:00
706a04dbfc gitlab-ci: No need for our ci repository
Just using debian buster makes things more stable.
2019-07-11 14:31:25 +02:00
7fd51af4de debian: Drop virtboard build-dependency 2019-07-11 14:31:25 +02:00
c1af9b2ba4 Add dbus protocol definition
This let's us drop the virtboard build dependency.
2019-07-11 14:31:25 +02:00
5efb4cc58d Bundle keyboard definitions
This allows running uninstalled from a git repo

Closes: #21, #29
2019-07-11 13:40:03 +02:00
4b2977d601 Plug 3 leaks 2019-07-11 13:26:04 +02:00
2f1c1c2fb1 Remove unused variable and remove damage from botched rebase
- remove bounds it is not used.

- remove the g_clear_pointer, it does the same thing as the if-block
  above, the were both there as the result of the merge, and it is
  apparently easily overlooked

- cleanup after myself (FIXMEs)
2019-07-11 13:24:48 +02:00
f47ef09a1f Merge branch 'implement-basic-views' into 'master'
Implement basic keyboard views

See merge request Librem5/squeekboard!51
2019-07-11 10:24:29 +00:00
47041b0fac Implement basic keyboard views
Use existing concepts of levels and modifier latches and locks to
implement the three view design of issue #38.

The use of a lock to switch from letter to numbers and a latch to
handle upper and lower case has side effects, but these can be
addressed in a future commit.
2019-07-10 23:33:45 +00:00
b6111b5e00 Merge branch 'fix-backspace-key' into 'master'
Specify a keyval to make the backspace key work again

Closes #45

See merge request Librem5/squeekboard!50
2019-07-10 23:12:59 +00:00
b8a2b2d7c8 Specify a keyval to make the backspace key work again 2019-07-11 01:09:04 +02:00
0765ea1b86 Merge branch 'update-symbols' into 'master'
Update symbols to more closely resemble #38

See merge request Librem5/squeekboard!48
2019-07-10 22:20:30 +00:00
64223704e0 Update symbols to more closely resemble #38 2019-07-10 23:50:34 +02:00
8c14763ea4 Merge branch 'theme-path' into 'master'
Drop now unused theme_path

See merge request Librem5/squeekboard!46
2019-07-10 17:09:58 +00:00
10cd93022a Merge branch 'update-icons' into 'master'
Use an icon for backspace

See merge request Librem5/squeekboard!47
2019-07-10 16:57:09 +00:00
d006aede6a Merge branch 'top-margin' into 'master'
Add some border at the top

Closes #28

See merge request Librem5/squeekboard!43
2019-07-10 15:46:16 +00:00
b57e1ce660 Drop now unused theme_path 2019-07-10 15:39:16 +02:00
1b59c4dad3 Use an icon for backspace 2019-07-10 14:36:19 +02:00
189c721d7e Merge branch 'use_gresource' into 'master'
Use a gresource to store the css

See merge request Librem5/squeekboard!28
2019-07-10 11:36:53 +00:00
1ff1592f24 Merge branch 'master' into 'use_gresource'
# Conflicts:
#   src/server-context-service.c
2019-07-10 11:35:40 +00:00
7f5f310bf0 Add some border at the top
Closes: #28
2019-07-10 11:31:24 +02:00
f999861228 Merge branch 'remove-more-unused-code-and-data' into 'master'
Remove unused color definitions

See merge request Librem5/squeekboard!42
2019-07-09 21:40:36 +00:00
a571bd7dca Remove unused color definitions 2019-07-09 17:55:40 +02:00
3d0d28fa01 Merge branch 'remove-unused-eekboard-context-service-code' into 'master'
Remove currently unused eekboard code

See merge request Librem5/squeekboard!41
2019-07-09 15:48:59 +00:00
4c54b49ef5 Merge branch 'remove-unused-sources' into 'master'
Remove unlisted files

See merge request Librem5/squeekboard!38
2019-07-09 14:44:00 +00:00
eb940bcf52 Remove currently unused eekboard code 2019-07-09 16:34:16 +02:00
be0e773879 Merge branch 'quick-review-fast-lane-very-speedy' into 'master'
Some cleanups, and some FIXME hints for future work (no functional changes)

See merge request Librem5/squeekboard!39
2019-07-09 14:25:45 +00:00
056e07e80e Merge branch 'prevent-warnings' into 'master'
Prevent compiler warnings by commenting out unused code

See merge request Librem5/squeekboard!37
2019-07-09 13:44:54 +00:00
83b36d07d0 Add note about unused code 2019-07-09 15:28:02 +02:00
89aaf05aff Some minor cleanups 2019-07-09 13:52:23 +02:00
2f87fd46fb Improve codeflow 2019-07-09 13:50:14 +02:00
e04276ee38 Use properly typed and named variables for user_data 2019-07-09 13:46:44 +02:00
05c3061f08 Add some FIXME hints for future work 2019-07-09 13:41:20 +02:00
c33006bcbc use g_clear_pointer with gtk_widget_destroy
brief, clear, idiomatic and grep friendly
2019-07-09 13:33:49 +02:00
4bf4500ae1 Remove unlisted files 2019-07-09 01:07:19 +02:00
e2944ff4a7 Use a macro to declare a type with private data 2019-07-09 00:46:03 +02:00
f79b5dadbb Use a macro to declare a type with private data 2019-07-09 00:41:25 +02:00
4d44129b04 Prevent compiler warnings by commenting out unused code 2019-07-09 00:24:57 +02:00
b3e1d84e6c Merge branch 'mem' into 'master'
Fix visibility-related bugs

See merge request Librem5/squeekboard!25
2019-07-08 21:25:27 +00:00
6702edaa9d Merge branch 'fix-deprecated-warnings' into 'master'
Fix deprecated warnings

See merge request Librem5/squeekboard!34
2019-07-08 21:19:57 +00:00
a3a6e5933a Merge branch 'quick-review-fast-lane-very-speedy' into 'master'
Quick review fast lane very speedy

See merge request Librem5/squeekboard!36
2019-07-08 21:01:40 +00:00
66ec95ebb0 fix-up prototypes (-Wincompatible-pointer-types) 2019-07-08 09:21:26 +02:00
a944bf85b8 remove stray const (-Wdiscarded-qualifiers) 2019-07-08 09:20:17 +02:00
1d1829f664 fix accidentally committed line (-Wincompatible-pointer-types) 2019-07-08 09:18:41 +02:00
094aa872ce Cleanups: fix deprecated g_type_class_add_private()
- use G_DECLARE_ and G_DEFINE_ macros
- move all data into ClassNamePrivate
- use _get_instance_private()

This should not introduce any functional changes or breakage.

Skipped two classes (EekKeyboard and EekboardContextService) for now in
order not to break the build.

These two classes are used in some very funky WIP code that tries to
circumvent encapsulation.

(Funky code is in eekboard/key-emitter.c and eekboard/eekboard-context-service.c)
2019-07-08 08:44:05 +02:00
eaf925e30b Cleanups: fix g_type_init() deprecation warning
None of this seems necessary anymore. This file could be axed, but leave
it for now.
2019-07-08 08:39:43 +02:00
722d3d1ad4 Cleanups: fix deprecations
gtk_widget_get_root_window()
	gdk_screen_get_monitor_at_window()
	gdk_screen_get_monitor_geometry()
2019-07-08 08:39:16 +02:00
b69b3e9409 Merge branch 'fix-uninitialized-var' into 'master'
Fix an uninitialized-variable warning, and fixes gradients (quickie)

See merge request Librem5/squeekboard!35
2019-07-07 17:37:11 +00:00
ae5eaeec93 Fix an uninitialized-variable warning, and fixes gradients 2019-07-07 18:45:56 +02:00
c393eb20be Merge branch 'improve-key-rendering' into 'master'
Improve key rendering and eliminate two deprecation warnings

See merge request Librem5/squeekboard!33
2019-07-07 11:39:12 +00:00
0e8715b4ff Improve key rendering and eliminate two deprecation warnings
- Replace two calls to deprecated gdk_cairo_create()

- Alleviate asymmetry between rendering pressed and released keys
  by consistenly clipping the same area up front to avoid
  artefacts

- make sure pressed and released keys are shown immediately by
  calling gdk_window_invalidate_rect()

- improve consistency between render_(pressed|locked|released)_key

- improve code flow
2019-07-07 11:34:24 +02:00
abf8f4daa8 eek-theme: Remove code for old croko versions
These versions aren't even in Debian's oldstable release.
2019-07-04 16:21:18 +02:00
aba242301d Use a gresource to store the css
This makes build / test faster since one can skip install. It's
also more obvious which file is being used.
2019-07-04 16:16:04 +02:00
c3ffe6ab8b visibility: Handle visibility change no-ops 2019-07-04 08:48:43 +00:00
3d1133cdb5 Fix memory corruption due to a wrong assumption 2019-07-04 07:48:46 +00:00
47026b669b Make copyright more granular 2019-06-29 10:50:30 +00:00
75 changed files with 1200 additions and 7105 deletions

View File

@ -4,10 +4,6 @@ stages:
- build
before_script:
- apt-get -y update
- apt-get -y install wget gnupg2
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
- apt-get -y update
- apt-get -y build-dep .

1
TODO
View File

@ -1 +0,0 @@
See https://github.com/ueno/eekboard/wiki/TODO

View File

@ -1,20 +0,0 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="eekboard"
(test -f $srcdir/configure.ac \
&& test -f $srcdir/README.md ) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4"
REQUIRED_AUTOMAKE_VERSION=1.10
REQUIRED_AUTOCONF_VERSION=2.60
. gnome-autogen.sh

View File

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

10
data/icons/key-enter.svg Normal file
View File

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

After

Width:  |  Height:  |  Size: 388 B

8
data/icons/key-shift.svg Normal file
View File

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

After

Width:  |  Height:  |  Size: 279 B

View File

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

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

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

View File

@ -39,61 +39,8 @@
<key keycode="96" name="FK12">
<keysym keyval="65481">F12</keysym>
</key>
<key keycode="49" name="TLDE">
<keysym keyval="96">quoteleft</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key keycode="10" name="AE01">
<keysym keyval="49">1</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key keycode="11" name="AE02">
<keysym keyval="50">2</keysym>
<keysym keyval="64">at</keysym>
</key>
<key keycode="12" name="AE03">
<keysym keyval="51">3</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key keycode="13" name="AE04">
<keysym keyval="52">4</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key keycode="14" name="AE05">
<keysym keyval="53">5</keysym>
<keysym keyval="37">percent</keysym>
<keysym keyval="8364">EuroSign</keysym>
</key>
<key keycode="15" name="AE06">
<keysym keyval="54">6</keysym>
<keysym keyval="94">asciicircum</keysym>
</key>
<key keycode="16" name="AE07">
<keysym keyval="55">7</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key keycode="17" name="AE08">
<keysym keyval="56">8</keysym>
<keysym keyval="42">asterisk</keysym>
</key>
<key keycode="18" name="AE09">
<keysym keyval="57">9</keysym>
<keysym keyval="40">parenleft</keysym>
</key>
<key keycode="19" name="AE10">
<keysym keyval="48">0</keysym>
<keysym keyval="41">parenright</keysym>
</key>
<key keycode="20" name="AE11">
<keysym keyval="45">minus</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key keycode="21" name="AE12">
<keysym keyval="61">equal</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key keycode="22" name="BKSP">
<keysym keyval="65288">BackSpace</keysym>
<keysym keyval="65288" icon="edit-clear-symbolic">backspace</keysym>
</key>
<key keycode="23" name="TAB">
<keysym keyval="65289">Tab</keysym>
@ -103,21 +50,25 @@
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
<keysym keyval="49">1</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key keycode="25" name="AD02">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
<keysym keyval="50">2</keysym>
<keysym keyval="96">quoteleft</keysym>
</key>
<key keycode="26" name="AD03">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
<keysym keyval="51">3</keysym>
<keysym keyval="124">bar</keysym>
</key>
<key keycode="27" name="AD04">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
<keysym keyval="52">4</keysym>
<keysym keyval="183">middledot</keysym>
</key>
<key keycode="28" name="AD05">
<keysym keyval="116">t</keysym>
@ -161,52 +112,64 @@
<keysym keyval="92">backslash</keysym>
<keysym keyval="124">bar</keysym>
</key>
<key keycode="66" name="ALTGR">
<keysym keyval="65027">ISO_Level3_Shift</keysym>
<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="95">underscore</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">
@ -218,45 +181,55 @@
<keysym keyval="34">quotedbl</keysym>
</key>
<key keycode="36" name="RTRN">
<keysym keyval="65293">Return</keysym>
<keysym keyval="65293" icon="key-enter">Return</keysym>
</key>
<key keycode="50" name="LFSH">
<keysym keyval="65505">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="123">Shift_L</keysym>
</key>
<key keycode="52" name="AB01">
<keysym keyval="122">z</keysym>
<keysym keyval="90">Z</keysym>
<keysym keyval="43">plus</keysym>
<keysym keyval="44">comma</keysym>
<keysym keyval="92">backslash</keysym>
</key>
<key keycode="53" name="AB02">
<keysym keyval="120">x</keysym>
<keysym keyval="88">X</keysym>
<keysym keyval="34">quotedbl</keysym>
<keysym keyval="47">slash</keysym>
</key>
<key keycode="54" name="AB03">
<keysym keyval="99">c</keysym>
<keysym keyval="67">C</keysym>
<keysym keyval="39">quoteright</keysym>
<keysym keyval="60">less</keysym>
</key>
<key keycode="55" name="AB04">
<keysym keyval="118">v</keysym>
<keysym keyval="86">V</keysym>
<keysym keyval="58">colon</keysym>
<keysym keyval="62">greater</keysym>
</key>
<key keycode="56" name="AB05">
<keysym keyval="98">b</keysym>
<keysym keyval="66">B</keysym>
<keysym keyval="59">semicolon</keysym>
<keysym keyval="61">equal</keysym>
</key>
<key keycode="57" name="AB06">
<keysym keyval="110">n</keysym>
<keysym keyval="78">N</keysym>
<keysym keyval="33">exclam</keysym>
<keysym keyval="91">bracketleft</keysym>
</key>
<key keycode="58" name="AB07">
<keysym keyval="109">m</keysym>
<keysym keyval="77">M</keysym>
<keysym keyval="63">question</keysym>
<keysym keyval="93">bracketright</keysym>
</key>
<key keycode="59" name="AB08">
<keysym keyval="44">comma</keysym>
@ -264,7 +237,6 @@
</key>
<key keycode="60" name="AB09">
<keysym keyval="46">period</keysym>
<keysym keyval="62">greater</keysym>
</key>
<key keycode="61" name="AB10">
<keysym keyval="47">slash</keysym>
@ -277,7 +249,7 @@
<symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
</key>
<key keycode="150" name="I150">
<symbol label="☺" icon="preferences-system-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key keycode="37" name="LCTL">
<keysym keyval="65507">Control_L</keysym>

View File

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

View File

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

1
debian/control vendored
View File

@ -11,7 +11,6 @@ Build-Depends:
libcroco3-dev,
libwayland-dev (>= 1.16),
rustc,
virtboard,
wayland-protocols (>= 1.14)
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard

53
debian/copyright vendored
View File

@ -3,7 +3,58 @@ Upstream-Name: evscript
Source: https://source.puri.sm/david.boddie/evscript
Files: *
Copyright: 2019 Purism SPC
Copyright: 2010-2011 Daiki Ueno <ueno@unixuser.org>
2010-2011 Red Hat, Inc.
2019 Purism SPC
License: GPL-3+
Files: eek/layersurface.c
src/wayland.c
src/key-emitter.c
meson.build
src/meson.build
po/meson.build
Copyright: 2018-2019 Purism SPC
License: GPL-3+
Files: eekboard/keymap.c
Copyright: 2000 Red Hat, Inc.
2019 Purism, SPC
License: LGPL-2+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
Files: protocols/wlr-layer-shell-unstable-v1.xml
Copytight: Copyright © 2017 Drew DeVault
License: X11
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee, provided
that the above copyright notice appear in all copies and fthat both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of the copyright holders not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. The copyright holders make
no representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
License: GPL-3+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

View File

@ -40,23 +40,19 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE (EekContainer, eek_container, EEK_TYPE_ELEMENT);
#define EEK_CONTAINER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CONTAINER, EekContainerPrivate))
struct _EekContainerPrivate
typedef struct _EekContainerPrivate
{
GList *head;
GList *last;
};
} EekContainerPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekContainer, eek_container, EEK_TYPE_ELEMENT)
static void
eek_container_real_add_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
g_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref (child);
@ -75,7 +71,7 @@ static void
eek_container_real_remove_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
g_return_if_fail (EEK_IS_ELEMENT(child));
@ -94,7 +90,7 @@ eek_container_real_foreach_child (EekContainer *self,
EekCallback callback,
gpointer user_data)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = g_list_next (head))
@ -106,7 +102,7 @@ eek_container_real_find (EekContainer *self,
EekCompareFunc func,
gpointer user_data)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
head = g_list_find_custom (priv->head, user_data, (GCompareFunc)func);
@ -118,7 +114,8 @@ eek_container_real_find (EekContainer *self,
static void
eek_container_dispose (GObject *object)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(object);
EekContainer *self = EEK_CONTAINER (object);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = priv->head) {
@ -134,9 +131,6 @@ eek_container_class_init (EekContainerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (gobject_class,
sizeof (EekContainerPrivate));
klass->add_child = eek_container_real_add_child;
klass->remove_child = eek_container_real_remove_child;
klass->foreach_child = eek_container_real_foreach_child;
@ -189,7 +183,7 @@ eek_container_class_init (EekContainerClass *klass)
static void
eek_container_init (EekContainer *self)
{
self->priv = EEK_CONTAINER_GET_PRIVATE(self);
/* void */
}
/**

View File

@ -30,14 +30,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_CONTAINER (eek_container_get_type())
#define EEK_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CONTAINER, EekContainer))
#define EEK_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CONTAINER, EekContainerClass))
#define EEK_IS_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CONTAINER))
#define EEK_IS_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CONTAINER))
#define EEK_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CONTAINER, EekContainerClass))
typedef struct _EekContainerClass EekContainerClass;
typedef struct _EekContainerPrivate EekContainerPrivate;
G_DECLARE_DERIVABLE_TYPE (EekContainer, eek_container, EEK, CONTAINER, EekElement)
/**
* EekCallback:
@ -50,14 +43,6 @@ typedef struct _EekContainerPrivate EekContainerPrivate;
typedef void (*EekCallback) (EekElement *element, gpointer user_data);
typedef gint (*EekCompareFunc) (EekElement *element, gpointer user_data);
struct _EekContainer
{
/*< private >*/
EekElement parent;
EekContainerPrivate *priv;
};
/**
* EekContainerClass:
* @foreach_child: virtual function for iterating over the container's children

View File

@ -52,20 +52,16 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE (EekElement, eek_element, G_TYPE_OBJECT);
#define EEK_ELEMENT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_ELEMENT, EekElementPrivate))
struct _EekElementPrivate
typedef struct _EekElementPrivate
{
gchar *name;
EekBounds bounds;
EekElement *parent;
gint group;
gint level;
};
} EekElementPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT)
static void
eek_element_real_symbol_index_changed (EekElement *self,
@ -78,7 +74,8 @@ eek_element_real_symbol_index_changed (EekElement *self,
static void
eek_element_finalize (GObject *object)
{
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(object);
EekElement *self = EEK_ELEMENT (object);
EekElementPrivate *priv = eek_element_get_instance_private (self);
g_free (priv->name);
G_OBJECT_CLASS (eek_element_parent_class)->finalize (object);
@ -146,9 +143,6 @@ eek_element_class_init (EekElementClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekElementPrivate));
/* signals */
klass->symbol_index_changed = eek_element_real_symbol_index_changed;
@ -238,9 +232,8 @@ eek_element_class_init (EekElementClass *klass)
static void
eek_element_init (EekElement *self)
{
EekElementPrivate *priv;
EekElementPrivate *priv = eek_element_get_instance_private (self);
priv = self->priv = EEK_ELEMENT_GET_PRIVATE(self);
priv->group = -1;
priv->level = -1;
}
@ -259,10 +252,12 @@ eek_element_set_parent (EekElement *element,
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (parent == NULL || EEK_IS_ELEMENT(parent));
if (element->priv->parent == parent)
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->parent == parent)
return;
if (element->priv->parent != NULL) {
if (priv->parent != NULL) {
/* release self-reference acquired when setting parent */
g_object_unref (element);
}
@ -271,7 +266,7 @@ eek_element_set_parent (EekElement *element,
g_object_ref (element);
}
element->priv->parent = parent;
priv->parent = parent;
}
/**
@ -285,7 +280,10 @@ EekElement *
eek_element_get_parent (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
return element->priv->parent;
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->parent;
}
/**
@ -300,8 +298,11 @@ eek_element_set_name (EekElement *element,
const gchar *name)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_free (element->priv->name);
element->priv->name = g_strdup (name);
EekElementPrivate *priv = eek_element_get_instance_private (element);
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
@ -315,7 +316,10 @@ const gchar *
eek_element_get_name (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
return element->priv->name;
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->name;
}
/**
@ -332,7 +336,10 @@ eek_element_set_bounds (EekElement *element,
EekBounds *bounds)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
memcpy (&element->priv->bounds, bounds, sizeof(EekBounds));
EekElementPrivate *priv = eek_element_get_instance_private (element);
memcpy (&priv->bounds, bounds, sizeof(EekBounds));
}
/**
@ -350,7 +357,10 @@ eek_element_get_bounds (EekElement *element,
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (bounds != NULL);
memcpy (bounds, &element->priv->bounds, sizeof(EekBounds));
EekElementPrivate *priv = eek_element_get_instance_private (element);
memcpy (bounds, &priv->bounds, sizeof(EekBounds));
}
/**
@ -486,11 +496,14 @@ eek_element_set_group (EekElement *element,
gint group)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
if (element->priv->group != group) {
element->priv->group = group;
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->group != group) {
priv->group = group;
g_object_notify (G_OBJECT(element), "group");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
group, element->priv->level);
group, priv->level);
}
}
@ -509,11 +522,14 @@ eek_element_set_level (EekElement *element,
gint level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
if (element->priv->level != level) {
element->priv->level = level;
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->level != level) {
priv->level = level;
g_object_notify (G_OBJECT(element), "level");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
element->priv->group, level);
priv->group, level);
}
}
@ -530,7 +546,10 @@ gint
eek_element_get_group (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
return element->priv->group;
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->group;
}
/**
@ -546,5 +565,8 @@ gint
eek_element_get_level (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
return element->priv->level;
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->level;
}

View File

@ -30,22 +30,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_ELEMENT (eek_element_get_type())
#define EEK_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_ELEMENT, EekElement))
#define EEK_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_ELEMENT, EekElementClass))
#define EEK_IS_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_ELEMENT))
#define EEK_IS_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_ELEMENT))
#define EEK_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_ELEMENT, EekElementClass))
typedef struct _EekElementClass EekElementClass;
typedef struct _EekElementPrivate EekElementPrivate;
struct _EekElement
{
/*< private >*/
GObject parent;
EekElementPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekElement, eek_element, EEK, ELEMENT, GObject)
struct _EekElementClass
{

View File

@ -23,14 +23,13 @@
* @short_description: a #GtkWidget displaying #EekKeyboard
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#ifdef HAVE_GSOUND
#include <gsound.h>
#endif
#include <math.h>
#include <string.h>
#include "eek-gtk-keyboard.h"
@ -46,26 +45,25 @@ enum {
PROP_LAST
};
G_DEFINE_TYPE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA);
#define EEK_GTK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_GTK_KEYBOARD, EekGtkKeyboardPrivate))
/* since 2.91.5 GDK_DRAWABLE was removed and gdk_cairo_create takes
GdkWindow as the argument */
#ifndef GDK_DRAWABLE
#define GDK_DRAWABLE(x) (x)
#endif
struct _EekGtkKeyboardPrivate
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
EekKeyboard *keyboard;
gulong key_locked_handler;
gulong key_unlocked_handler;
gulong symbol_index_changed_handler;
EekTheme *theme;
};
#ifdef HAVE_GSOUND
GSoundContext *sound_ctx;
#endif
GdkEventSequence *sequence; // unowned reference
} EekGtkKeyboardPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self);
@ -106,7 +104,8 @@ static gboolean
eek_gtk_keyboard_real_draw (GtkWidget *self,
cairo_t *cr)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
GList *list, *head;
@ -123,6 +122,8 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
eek_renderer_set_allocation_size (priv->renderer,
allocation.width,
allocation.height);
eek_renderer_set_scale_factor (priv->renderer,
gtk_widget_get_scale_factor (self));
}
eek_renderer_render_keyboard (priv->renderer, cr);
@ -148,7 +149,8 @@ static void
eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
GtkAllocation *allocation)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->renderer)
eek_renderer_set_allocation_size (priv->renderer,
@ -161,7 +163,7 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
if (key) {
eek_keyboard_press_key(priv->keyboard, key, time);
@ -171,7 +173,7 @@ static void depress(EekGtkKeyboard *self,
static void drag(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
if (key) {
@ -197,7 +199,7 @@ static void drag(EekGtkKeyboard *self,
}
static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (GList *head = list; head; head = g_list_next (head)) {
@ -242,20 +244,23 @@ eek_gtk_keyboard_real_motion_notify_event (GtkWidget *self,
// Only one touch stream at a time allowed. Others will be completely ignored.
static gboolean
handle_touch_event (GtkWidget *widget,
GdkEventTouch *event) {
EekGtkKeyboard *self = EEK_GTK_KEYBOARD(widget);
handle_touch_event (GtkWidget *widget,
GdkEventTouch *event)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
if (event->type == GDK_TOUCH_BEGIN) {
if (self->sequence) {
if (priv->sequence) {
// Ignore second and following touch points
return FALSE;
}
self->sequence = event->sequence;
priv->sequence = event->sequence;
depress(self, event->x, event->y, event->time);
return TRUE;
}
if (self->sequence != event->sequence) {
if (priv->sequence != event->sequence) {
return FALSE;
}
@ -265,16 +270,16 @@ handle_touch_event (GtkWidget *widget,
if (event->type == GDK_TOUCH_END || event->type == GDK_TOUCH_CANCEL) {
// TODO: can the event have different coords than the previous update event?
release(self, event->time);
self->sequence = NULL;
priv->sequence = NULL;
}
return TRUE;
}
static void
eek_gtk_keyboard_real_unmap (GtkWidget *self)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
if (priv->keyboard) {
GList *list, *head;
@ -301,7 +306,9 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
gboolean keyboard_tooltip,
GtkTooltip *tooltip)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key;
key = eek_renderer_find_key_by_position (priv->renderer,
@ -322,18 +329,24 @@ static void
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
if (priv->keyboard == keyboard)
return;
if (priv->keyboard) {
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
g_object_unref (priv->keyboard);
}
priv->keyboard = g_object_ref (keyboard);
priv->key_locked_handler =
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
priv->key_unlocked_handler =
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
priv->symbol_index_changed_handler =
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
@ -358,7 +371,8 @@ eek_gtk_keyboard_set_property (GObject *object,
static void
eek_gtk_keyboard_dispose (GObject *object)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(object);
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (object);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
if (priv->renderer) {
g_object_unref (priv->renderer);
@ -366,21 +380,9 @@ eek_gtk_keyboard_dispose (GObject *object)
}
if (priv->keyboard) {
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_locked_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_locked_handler);
if (g_signal_handler_is_connected (priv->keyboard,
priv->key_unlocked_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->key_unlocked_handler);
if (g_signal_handler_is_connected (priv->keyboard,
priv->symbol_index_changed_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->symbol_index_changed_handler);
GList *list, *head;
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
@ -407,9 +409,6 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekGtkKeyboardPrivate));
widget_class->realize = eek_gtk_keyboard_real_realize;
widget_class->unmap = eek_gtk_keyboard_real_unmap;
widget_class->draw = eek_gtk_keyboard_real_draw;
@ -440,7 +439,16 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
static void
eek_gtk_keyboard_init (EekGtkKeyboard *self)
{
self->priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
#if HAVE_GSOUND
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
}
/**
@ -483,96 +491,98 @@ static void
render_pressed_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
GdkWindow *window = GDK_DRAWABLE (gtk_widget_get_window (widget));
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame(
window, region
);
cairo_t *cr = gdk_drawing_context_get_cairo_context(context);
cairo_save (cr);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
/*
cairo_save (cr);
cairo_translate (cr, large_bounds.x, large_bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_restore (cr);
*/
gdk_window_end_draw_frame (window, context);
gdk_window_end_draw_frame(window, context);
cairo_region_destroy(region);
cairo_region_destroy (region);
}
static void
render_locked_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds;
cairo_t *cr;
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_destroy (cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
static void
render_released_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
cairo_t *cr;
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 2.0);
cairo_rectangle (cr,
large_bounds.x,
large_bounds.y,
large_bounds.width,
large_bounds.height);
cairo_rectangle (cr,
bounds.x,
bounds.y,
bounds.width,
bounds.height);
cairo_clip (cr);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
eek_renderer_render_keyboard (priv->renderer, cr);
cairo_destroy (cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
}
static void
on_key_pressed (EekKey *key,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_pressed_key (GTK_WIDGET(self), key);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
CA_PROP_EVENT_ID, "button-pressed",
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
NULL);
#if HAVE_GSOUND
g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
GSOUND_ATTR_EVENT_ID, "button-pressed",
GSOUND_ATTR_EVENT_DESCRIPTION, "Button pressed",
NULL);
#endif
}
@ -580,20 +590,21 @@ static void
on_key_released (EekKey *key,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_key (GTK_WIDGET(self), key);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
CA_PROP_EVENT_ID, "button-released",
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
NULL);
#if HAVE_GSOUND
g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
GSOUND_ATTR_EVENT_ID, "button-released",
GSOUND_ATTR_EVENT_DESCRIPTION, "Button released",
NULL);
#endif
}
@ -603,13 +614,14 @@ on_key_locked (EekKeyboard *keyboard,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_locked_key (widget, key);
gtk_widget_queue_draw (widget);
}
static void
@ -618,13 +630,14 @@ on_key_unlocked (EekKeyboard *keyboard,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_key (widget, key);
gtk_widget_queue_draw (GTK_WIDGET(widget));
}
static void
@ -642,11 +655,9 @@ void
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme)
{
EekGtkKeyboardPrivate *priv;
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
g_return_if_fail (EEK_IS_THEME(theme));
priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard);
priv->theme = g_object_ref (theme);
}

View File

@ -32,25 +32,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type())
#define EEK_GTK_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_GTK_KEYBOARD, EekGtkKeyboard))
#define EEK_GTK_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_GTK_KEYBOARD, EekGtkKeyboardClass))
#define EEK_IS_GTK_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_GTK_KEYBOARD))
#define EEK_IS_GTK_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_GTK_KEYBOARD))
#define EEK_GTK_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_GTK_KEYBOARD, EekGtkKeyboardClass))
typedef struct _EekGtkKeyboard EekGtkKeyboard;
typedef struct _EekGtkKeyboardClass EekGtkKeyboardClass;
typedef struct _EekGtkKeyboardPrivate EekGtkKeyboardPrivate;
struct _EekGtkKeyboard
{
/*< private >*/
GtkDrawingArea parent;
GdkEventSequence *sequence; // unowned reference
EekGtkKeyboardPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekGtkKeyboard, eek_gtk_keyboard, EEK, GTK_KEYBOARD, GtkDrawingArea)
struct _EekGtkKeyboardClass
{

View File

@ -30,52 +30,29 @@
G_DEFINE_TYPE (EekGtkRenderer, eek_gtk_renderer, EEK_TYPE_RENDERER);
static cairo_surface_t *
pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
{
cairo_surface_t *dummy_surface;
cairo_pattern_t *pattern;
cairo_surface_t *surface;
cairo_t *cr;
dummy_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cr = cairo_create (dummy_surface);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
pattern = cairo_get_source (cr);
cairo_pattern_get_surface (pattern, &surface);
cairo_surface_reference (surface);
cairo_destroy (cr);
cairo_surface_destroy (dummy_surface);
return surface;
}
static cairo_surface_t *
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
const gchar *icon_name,
gint size)
gint size,
gint scale)
{
GdkPixbuf *pixbuf;
GError *error;
GError *error = NULL;
cairo_surface_t *surface;
error = NULL;
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
icon_name,
size,
0,
&error);
if (pixbuf == NULL) {
g_warning ("can't get icon pixbuf for %s: %s",
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;
}
surface = pixbuf_to_cairo_surface (pixbuf);
g_object_unref (pixbuf);
return surface;
}
@ -90,6 +67,9 @@ eek_gtk_renderer_class_init (EekGtkRendererClass *klass)
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 *

View File

@ -54,13 +54,7 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKey, eek_key, EEK_TYPE_ELEMENT);
#define EEK_KEY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEY, EekKeyPrivate))
struct _EekKeyPrivate
typedef struct _EekKeyPrivate
{
guint keycode;
EekSymbolMatrix *symbol_matrix;
@ -69,12 +63,14 @@ struct _EekKeyPrivate
gulong oref; // UI outline reference
gboolean is_pressed;
gboolean is_locked;
};
} EekKeyPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekKey, eek_key, EEK_TYPE_ELEMENT)
static void
eek_key_real_locked (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = TRUE;
#if DEBUG
@ -85,7 +81,7 @@ eek_key_real_locked (EekKey *self)
static void
eek_key_real_unlocked (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = FALSE;
#if DEBUG
@ -96,8 +92,11 @@ eek_key_real_unlocked (EekKey *self)
static void
eek_key_finalize (GObject *object)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(object);
EekKey *self = EEK_KEY (object);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
eek_symbol_matrix_free (priv->symbol_matrix);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
@ -174,9 +173,6 @@ eek_key_class_init (EekKeyClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekKeyPrivate));
gobject_class->set_property = eek_key_set_property;
gobject_class->get_property = eek_key_get_property;
gobject_class->finalize = eek_key_finalize;
@ -285,9 +281,7 @@ eek_key_class_init (EekKeyClass *klass)
static void
eek_key_init (EekKey *self)
{
EekKeyPrivate *priv;
priv = self->priv = EEK_KEY_GET_PRIVATE(self);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
}
@ -307,7 +301,10 @@ eek_key_set_keycode (EekKey *key,
guint keycode)
{
g_return_if_fail (EEK_IS_KEY (key));
key->priv->keycode = keycode;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->keycode = keycode;
}
/**
@ -321,7 +318,10 @@ guint
eek_key_get_keycode (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), EEK_INVALID_KEYCODE);
return key->priv->keycode;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->keycode;
}
/**
@ -337,8 +337,10 @@ eek_key_set_symbol_matrix (EekKey *key,
{
g_return_if_fail (EEK_IS_KEY(key));
eek_symbol_matrix_free (key->priv->symbol_matrix);
key->priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
eek_symbol_matrix_free (priv->symbol_matrix);
priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
}
/**
@ -352,7 +354,10 @@ EekSymbolMatrix *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
return key->priv->symbol_matrix;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->symbol_matrix;
}
/**
@ -440,7 +445,7 @@ eek_key_get_symbol_at_index (EekKey *key,
gint fallback_group,
gint fallback_level)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(key);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
gint num_symbols;
g_return_val_if_fail (fallback_group >= 0, NULL);
@ -492,12 +497,14 @@ eek_key_set_index (EekKey *key,
g_return_if_fail (0 <= column);
g_return_if_fail (0 <= row);
if (key->priv->column != column) {
key->priv->column = column;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->column != column) {
priv->column = column;
g_object_notify (G_OBJECT(key), "column");
}
if (key->priv->row != row) {
key->priv->row = row;
if (priv->row != row) {
priv->row = row;
g_object_notify (G_OBJECT(key), "row");
}
}
@ -518,10 +525,12 @@ eek_key_get_index (EekKey *key,
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (column != NULL || row != NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (column != NULL)
*column = key->priv->column;
*column = priv->column;
if (row != NULL)
*row = key->priv->row;
*row = priv->row;
}
/**
@ -536,8 +545,11 @@ eek_key_set_oref (EekKey *key,
guint oref)
{
g_return_if_fail (EEK_IS_KEY(key));
if (key->priv->oref != oref) {
key->priv->oref = oref;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->oref != oref) {
priv->oref = oref;
g_object_notify (G_OBJECT(key), "oref");
}
}
@ -553,7 +565,10 @@ guint
eek_key_get_oref (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), 0);
return key->priv->oref;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->oref;
}
/**
@ -566,7 +581,10 @@ gboolean
eek_key_is_pressed (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
return key->priv->is_pressed;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_pressed;
}
/**
@ -579,11 +597,17 @@ gboolean
eek_key_is_locked (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
return key->priv->is_locked;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_locked;
}
void eek_key_set_pressed(EekKey *key, gboolean value)
{
g_return_if_fail (EEK_IS_KEY(key));
key->priv->is_pressed = value;
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->is_pressed = value;
}

View File

@ -31,31 +31,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_KEY (eek_key_get_type())
#define EEK_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_KEY, EekKey))
#define EEK_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_KEY, EekKeyClass))
#define EEK_IS_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_KEY))
#define EEK_IS_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_KEY))
#define EEK_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_KEY, EekKeyClass))
typedef struct _EekKeyClass EekKeyClass;
typedef struct _EekKeyPrivate EekKeyPrivate;
/**
* EekKey:
*
* Contains information about the state of a key.
* TODO: rewrite as a plain struct
*
* The #EekKey structure contains only private data and should only be
* accessed using the provided API.
*/
struct _EekKey
{
/*< private >*/
EekElement parent;
EekKeyPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE(EekKey, eek_key, EEK, KEY, EekElement)
/**
* EekKeyClass:

View File

@ -53,9 +53,14 @@ enum {
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
enum {
VIEW_LETTERS_LOWER,
VIEW_LETTERS_UPPER,
VIEW_NUMBERS,
VIEW_SYMBOLS
};
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
static guint signals[LAST_SIGNAL] = { 0, };
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
@ -65,6 +70,7 @@ struct _EekKeyboardPrivate
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
unsigned int old_level;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
@ -75,6 +81,8 @@ struct _EekKeyboardPrivate
EekModifierType alt_gr_mask;
};
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
@ -203,15 +211,58 @@ eek_keyboard_get_property (GObject *object,
}
static void
set_level_from_modifiers (EekKeyboard *self)
set_level_from_modifiers (EekKeyboard *self, EekKey *key)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
gint level = 0;
if (priv->modifiers & priv->alt_gr_mask)
level |= 2;
if (priv->modifiers & EEK_SHIFT_MASK)
level |= 1;
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
/* Use the numbers/letters bit from the old level */
gint level = priv->old_level & 2;
/* Handle non-emitting keys */
if (key && (eek_key_get_keycode(key) == 0)) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123") == 0)
level ^= 2;
}
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
switch (priv->old_level) {
case VIEW_LETTERS_UPPER:
{
/* Redirect upper case letters to numbers instead of symbols, clearing
the shift modifier to keep the modifiers in sync with the level */
if (level == VIEW_SYMBOLS) {
level = VIEW_NUMBERS;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_SYMBOLS:
{
/* Redirect symbols to lower case letters instead of upper case,
clearing the shift modifier to keep the modifiers in sync with the
level */
if (level == VIEW_LETTERS_UPPER) {
level = VIEW_LETTERS_LOWER;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
case VIEW_NUMBERS:
default:
break;
}
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
else
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
priv->old_level = level;
eek_element_set_level (EEK_ELEMENT(self), level);
}
@ -267,7 +318,7 @@ void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestam
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
set_level_from_modifiers (keyboard);
set_level_from_modifiers (keyboard, key);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
@ -316,7 +367,7 @@ void eek_keyboard_release_key( EekKeyboard *keyboard,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard);
set_level_from_modifiers (keyboard, key);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
@ -390,9 +441,6 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekKeyboardPrivate));
klass->create_section = eek_keyboard_real_create_section;
/* signals */
@ -585,7 +633,7 @@ eek_keyboard_set_modifiers (EekKeyboard *keyboard,
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifiers = modifiers;
set_level_from_modifiers (keyboard);
set_level_from_modifiers (keyboard, NULL);
}
/**

View File

@ -50,9 +50,10 @@
#define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee
struct _EekKeysymPrivate {
typedef struct _EekKeysymPrivate
{
guint xkeysym;
};
} EekKeysymPrivate;
struct _EekKeysymEntry {
guint xkeysym;
@ -68,12 +69,11 @@ typedef struct _EekKeysymEntry EekKeysymEntry;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEYSYM_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYSYM, EekKeysymPrivate))
G_DEFINE_TYPE_EXTENDED (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekKeysym)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
@ -81,7 +81,8 @@ static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
eek_keysym_parent_serializable_iface->serialize (self, builder);
@ -93,7 +94,8 @@ eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = EEK_KEYSYM_GET_PRIVATE(self);
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
@ -200,15 +202,13 @@ get_modifier_mask (guint xkeysym)
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (gobject_class, sizeof (EekKeysymPrivate));
/* void */
}
static void
eek_keysym_init (EekKeysym *self)
{
self->priv = EEK_KEYSYM_GET_PRIVATE(self);
/* void */
}
/**
@ -291,7 +291,7 @@ eek_keysym_new_with_modifier (guint xkeysym,
g_slice_free (EekKeysymEntry, unichar_entry);
}
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
priv = eek_keysym_get_instance_private (keysym);
priv->xkeysym = xkeysym;
return keysym;
@ -345,6 +345,6 @@ eek_keysym_get_xkeysym (EekKeysym *keysym)
EekKeysymPrivate *priv;
g_assert (EEK_IS_KEYSYM(keysym));
priv = EEK_KEYSYM_GET_PRIVATE(keysym);
priv = eek_keysym_get_instance_private (keysym);
return priv->xkeysym;
}

View File

@ -38,27 +38,7 @@ G_BEGIN_DECLS
#define EEK_INVALID_KEYSYM (0)
#define EEK_TYPE_KEYSYM (eek_keysym_get_type())
#define EEK_KEYSYM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_KEYSYM, EekKeysym))
#define EEK_KEYSYM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_KEYSYM, EekKeysymClass))
#define EEK_IS_KEYSYM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_KEYSYM))
#define EEK_IS_KEYSYM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_KEYSYM))
#define EEK_KEYSYM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_KEYSYM, EekKeysymClass))
typedef struct _EekKeysymClass EekKeysymClass;
typedef struct _EekKeysymPrivate EekKeysymPrivate;
/**
* EekKeysym:
*
* The #EekKeysym structure contains only private data and should only
* be accessed using the provided API.
*/
struct _EekKeysym {
/*< private >*/
EekSymbol parent;
EekKeysymPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
struct _EekKeysymClass {
/*< private >*/

View File

@ -34,7 +34,7 @@
#include "eek-keyboard.h"
#include "eekboard/eekboard-context-service.h"
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT);
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
static void
eek_layout_class_init (EekLayoutClass *klass)

View File

@ -31,20 +31,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_LAYOUT (eek_layout_get_type())
#define EEK_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_LAYOUT, EekLayout))
#define EEK_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_LAYOUT, EekLayoutClass))
#define EEK_IS_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_LAYOUT))
#define EEK_IS_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_LAYOUT))
#define EEK_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_LAYOUT, EekLayoutClass))
typedef struct _EekLayoutClass EekLayoutClass;
typedef struct _EekLayout EekLayout;
struct _EekLayout
{
/*< private >*/
GObject parent;
};
G_DECLARE_DERIVABLE_TYPE (EekLayout, eek_layout, EEK, LAYOUT, GObject)
/**
* EekLayoutClass:

View File

@ -1,17 +1,17 @@
/*
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
@ -36,12 +36,7 @@ enum {
PROP_LAST
};
G_DEFINE_TYPE (EekRenderer, eek_renderer, G_TYPE_OBJECT);
#define EEK_RENDERER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_RENDERER, EekRendererPrivate))
struct _EekRendererPrivate
typedef struct _EekRendererPrivate
{
EekKeyboard *keyboard;
PangoContext *pcontext;
@ -53,6 +48,7 @@ struct _EekRendererPrivate
gdouble allocation_width;
gdouble allocation_height;
gdouble scale;
gint scale_factor; /* the outputs scale factor */
PangoFontDescription *ascii_font;
PangoFontDescription *font;
@ -62,7 +58,9 @@ struct _EekRendererPrivate
gulong symbol_index_changed_handler;
EekTheme *theme;
};
} EekRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0};
static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0};
@ -106,13 +104,13 @@ create_keyboard_surface_key_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
cairo_save (data->cr);
eek_element_get_bounds (element, &bounds);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_rectangle (data->cr,
0.0,
0.0,
@ -129,7 +127,7 @@ create_keyboard_surface_section_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
gint angle;
@ -140,7 +138,7 @@ create_keyboard_surface_section_callback (EekElement *element,
angle = eek_section_get_angle (EEK_SECTION(element));
cairo_rotate (data->cr, angle * G_PI / 180);
eek_container_foreach_child (EEK_CONTAINER(element),
create_keyboard_surface_key_callback,
data);
@ -151,7 +149,7 @@ create_keyboard_surface_section_callback (EekElement *element,
static cairo_surface_t *
create_keyboard_surface (EekRenderer *renderer)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekBounds bounds;
cairo_surface_t *keyboard_surface;
CreateKeyboardSurfaceCallbackData data;
@ -165,9 +163,14 @@ create_keyboard_surface (EekRenderer *renderer)
&background);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
keyboard_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil(bounds.width * priv->scale),
ceil(bounds.height * priv->scale));
/* Create a surface that encompasses the dimensions of the keyboard as well
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;
@ -202,7 +205,7 @@ render_key_outline (EekRenderer *renderer,
EekKey *key,
gboolean active)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekOutline *outline;
EekBounds bounds;
guint oref;
@ -216,7 +219,7 @@ render_key_outline (EekRenderer *renderer,
outline = eek_keyboard_get_outline (priv->keyboard, oref);
if (outline == NULL)
return;
theme_node = g_object_get_data (G_OBJECT(key),
active ?
"theme-node-pressed" :
@ -246,7 +249,9 @@ render_key_outline (EekRenderer *renderer,
border_color.alpha = foreground.alpha;
}
eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
outline = eek_outline_copy (outline);
for (guint i = 0; i < outline->num_points; i++) {
outline->points[i].x *= priv->scale;
outline->points[i].y *= priv->scale;
@ -351,7 +356,7 @@ static void
calculate_font_size_key_callback (EekElement *element, gpointer user_data)
{
CalculateFontSizeCallbackData *data = user_data;
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
gdouble sx, sy;
PangoFontDescription *font;
PangoRectangle extents = { 0, };
@ -411,7 +416,7 @@ calculate_font_size (EekRenderer *renderer,
const PangoFontDescription *base_font,
gboolean ascii)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
CalculateFontSizeCallbackData data;
data.size = G_MAXDOUBLE;
@ -430,7 +435,7 @@ render_key (EekRenderer *self,
EekKey *key,
gboolean active)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekOutline *outline;
cairo_surface_t *outline_surface;
EekBounds bounds;
@ -460,7 +465,8 @@ render_key (EekRenderer *self,
if (!outline_surface) {
cairo_t *cr;
// Outline will be drawn on the outside of the button, so the surface needs to be bigger than the button
// Outline will be drawn on the outside of the button, so the
// surface needs to be bigger than the button
outline_surface =
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
(int)ceil(bounds.width) + 10,
@ -486,44 +492,38 @@ render_key (EekRenderer *self,
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
cairo_paint (cr);
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
/* render icon (if any) */
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
#define SCALE 0.4
if (eek_symbol_get_icon_name (symbol)) {
gint scale = priv->scale_factor;
cairo_surface_t *icon_surface =
eek_renderer_get_icon_surface (self,
eek_symbol_get_icon_name (symbol),
MIN(bounds.width, bounds.height) * 0.7);
SCALE * MIN(bounds.width, bounds.height),
scale);
if (icon_surface) {
gint width = cairo_image_surface_get_width (icon_surface);
gint height = cairo_image_surface_get_height (icon_surface);
gdouble scale;
if (width < bounds.width && height < bounds.height)
scale = 1;
else {
if (height * bounds.width / width <= bounds.height)
scale = bounds.width / width;
else if (width * bounds.height / height <= bounds.width)
scale = bounds.height / height;
else {
if (width * bounds.height < height * bounds.width)
scale = width / bounds.width;
else
scale = height / bounds.height;
}
}
cairo_save (cr);
cairo_translate (cr,
(bounds.width - width * scale) / 2,
(bounds.height - height * scale) / 2);
(bounds.width - width / scale) / 2,
(bounds.height - height / scale) / 2);
cairo_rectangle (cr, 0, 0, width, height);
cairo_clip (cr);
cairo_set_source_surface (cr, icon_surface, 0.0, 0.0);
cairo_paint (cr);
/* Draw the shape of the icon using the foreground color */
cairo_set_source_rgba (cr, foreground.red,
foreground.green,
foreground.blue,
foreground.alpha);
cairo_mask_surface (cr, icon_surface, 0.0, 0.0);
cairo_fill (cr);
cairo_restore (cr);
return;
}
@ -540,7 +540,6 @@ render_key (EekRenderer *self,
(bounds.width - extents.width / PANGO_SCALE) / 2,
(bounds.height - extents.height / PANGO_SCALE) / 2);
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
cairo_set_source_rgba (cr,
foreground.red,
foreground.green,
@ -603,7 +602,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
PangoLayout *layout,
EekKey *key)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekSymbol *symbol;
EekSymbolCategory category;
const gchar *label;
@ -696,7 +695,7 @@ static void
eek_renderer_real_render_keyboard (EekRenderer *self,
cairo_t *cr)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
cairo_pattern_t *source;
g_return_if_fail (priv->keyboard);
@ -718,7 +717,8 @@ eek_renderer_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
EekRendererPrivate *priv = eek_renderer_get_instance_private (
EEK_RENDERER(object));
switch (prop_id) {
case PROP_KEYBOARD:
@ -746,7 +746,8 @@ eek_renderer_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
EekRendererPrivate *priv = eek_renderer_get_instance_private (
EEK_RENDERER(object));
switch (prop_id) {
case PROP_KEYBOARD:
@ -761,7 +762,8 @@ eek_renderer_get_property (GObject *object,
static void
eek_renderer_dispose (GObject *object)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
EekRenderer *self = EEK_RENDERER (object);
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
if (priv->keyboard) {
if (g_signal_handler_is_connected (priv->keyboard,
@ -785,7 +787,9 @@ eek_renderer_dispose (GObject *object)
static void
eek_renderer_finalize (GObject *object)
{
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
EekRenderer *self = EEK_RENDERER(object);
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
g_hash_table_destroy (priv->outline_surface_cache);
g_hash_table_destroy (priv->active_outline_surface_cache);
pango_font_description_free (priv->ascii_font);
@ -799,9 +803,6 @@ eek_renderer_class_init (EekRendererClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekRendererPrivate));
klass->render_key_label = eek_renderer_real_render_key_label;
klass->render_key_outline = eek_renderer_real_render_key_outline;
klass->render_key = eek_renderer_real_render_key;
@ -834,9 +835,8 @@ eek_renderer_class_init (EekRendererClass *klass)
static void
eek_renderer_init (EekRenderer *self)
{
EekRendererPrivate *priv;
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
priv = self->priv = EEK_RENDERER_GET_PRIVATE(self);
priv->keyboard = NULL;
priv->pcontext = NULL;
priv->default_foreground_color = DEFAULT_FOREGROUND_COLOR;
@ -845,6 +845,7 @@ eek_renderer_init (EekRenderer *self)
priv->allocation_width = 0.0;
priv->allocation_height = 0.0;
priv->scale = 1.0;
priv->scale_factor = 1;
priv->font = NULL;
priv->outline_surface_cache =
g_hash_table_new_full (g_direct_hash,
@ -863,15 +864,17 @@ eek_renderer_init (EekRenderer *self)
static void
invalidate (EekRenderer *renderer)
{
if (renderer->priv->outline_surface_cache)
g_hash_table_remove_all (renderer->priv->outline_surface_cache);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
if (renderer->priv->active_outline_surface_cache)
g_hash_table_remove_all (renderer->priv->active_outline_surface_cache);
if (priv->outline_surface_cache)
g_hash_table_remove_all (priv->outline_surface_cache);
if (renderer->priv->keyboard_surface) {
cairo_surface_destroy (renderer->priv->keyboard_surface);
renderer->priv->keyboard_surface = NULL;
if (priv->active_outline_surface_cache)
g_hash_table_remove_all (priv->active_outline_surface_cache);
if (priv->keyboard_surface) {
cairo_surface_destroy (priv->keyboard_surface);
priv->keyboard_surface = NULL;
}
}
@ -906,10 +909,12 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (width > 0.0 && height > 0.0);
renderer->priv->allocation_width = width;
renderer->priv->allocation_height = height;
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
eek_element_get_bounds (EEK_ELEMENT(renderer->priv->keyboard), &bounds);
priv->allocation_width = width;
priv->allocation_height = height;
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (bounds.height * width / bounds.width <= height)
scale = width / bounds.width;
@ -922,8 +927,8 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
scale = bounds.height / height;
}
if (scale != renderer->priv->scale) {
renderer->priv->scale = scale;
if (scale != priv->scale) {
priv->scale = scale;
invalidate (renderer);
}
}
@ -937,11 +942,13 @@ eek_renderer_get_size (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
eek_element_get_bounds (EEK_ELEMENT(renderer->priv->keyboard), &bounds);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (width)
*width = bounds.width * renderer->priv->scale;
*width = bounds.width * priv->scale;
if (height)
*height = bounds.height * renderer->priv->scale;
*height = bounds.height * priv->scale;
}
void
@ -960,20 +967,22 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (bounds != NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
section = eek_element_get_parent (EEK_ELEMENT(key));
eek_element_get_bounds (EEK_ELEMENT(key), bounds);
eek_element_get_bounds (section, &section_bounds);
eek_element_get_bounds (EEK_ELEMENT(renderer->priv->keyboard),
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard),
&keyboard_bounds);
if (!rotate) {
bounds->x += keyboard_bounds.x + section_bounds.x;
bounds->y += keyboard_bounds.y + section_bounds.y;
bounds->x *= renderer->priv->scale;
bounds->y *= renderer->priv->scale;
bounds->width *= renderer->priv->scale;
bounds->height *= renderer->priv->scale;
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
return;
}
points[0].x = bounds->x;
@ -1005,24 +1014,39 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
bounds->y = keyboard_bounds.y + section_bounds.y + min.y;
bounds->width = (max.x - min.x);
bounds->height = (max.y - min.y);
bounds->x *= renderer->priv->scale;
bounds->y *= renderer->priv->scale;
bounds->width *= renderer->priv->scale;
bounds->height *= renderer->priv->scale;
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
}
gdouble
eek_renderer_get_scale (EekRenderer *renderer)
{
g_return_val_if_fail (EEK_IS_RENDERER(renderer), 0);
return renderer->priv->scale;
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
return priv->scale;
}
void
eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale)
{
g_return_if_fail (EEK_IS_RENDERER(renderer));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
priv->scale_factor = scale;
}
PangoLayout *
eek_renderer_create_pango_layout (EekRenderer *renderer)
{
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
return pango_layout_new (renderer->priv->pcontext);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
return pango_layout_new (priv->pcontext);
}
void
@ -1058,7 +1082,8 @@ eek_renderer_render_key_outline (EekRenderer *renderer,
cairo_surface_t *
eek_renderer_get_icon_surface (EekRenderer *renderer,
const gchar *icon_name,
gint size)
gint size,
gint scale)
{
EekRendererClass *klass;
@ -1066,7 +1091,7 @@ eek_renderer_get_icon_surface (EekRenderer *renderer,
klass = EEK_RENDERER_GET_CLASS(renderer);
if (klass->get_icon_surface)
return klass->get_icon_surface (renderer, icon_name, size);
return klass->get_icon_surface (renderer, icon_name, size, scale);
return NULL;
}
@ -1100,7 +1125,9 @@ eek_renderer_set_default_foreground_color (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
memcpy (&renderer->priv->default_foreground_color, color, sizeof(EekColor));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
memcpy (&priv->default_foreground_color, color, sizeof(EekColor));
}
void
@ -1110,7 +1137,9 @@ eek_renderer_set_default_background_color (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
memcpy (&renderer->priv->default_background_color, color, sizeof(EekColor));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
memcpy (&priv->default_background_color, color, sizeof(EekColor));
}
void
@ -1123,11 +1152,13 @@ eek_renderer_get_foreground_color (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_foreground_color (theme_node, color);
else
memcpy (color, &renderer->priv->default_foreground_color,
memcpy (color, &priv->default_foreground_color,
sizeof(EekColor));
}
@ -1141,11 +1172,13 @@ eek_renderer_get_background_color (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_background_color (theme_node, color);
else
memcpy (color, &renderer->priv->default_background_color,
memcpy (color, &priv->default_background_color,
sizeof(EekColor));
}
@ -1208,12 +1241,14 @@ find_key_by_position_key_callback (EekElement *element,
points[3].x = points[0].x;
points[3].y = points[2].y;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
for (i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], data->angle);
points[i].x += data->origin.x;
points[i].y += data->origin.y;
points[i].x *= data->renderer->priv->scale;
points[i].y *= data->renderer->priv->scale;
points[i].x *= priv->scale;
points[i].y *= priv->scale;
}
b1 = sign (&data->point, &points[0], &points[1]) < 0.0;
@ -1268,12 +1303,14 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
eek_element_get_bounds (EEK_ELEMENT(renderer->priv->keyboard), &bounds);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
if (x < bounds.x * renderer->priv->scale ||
y < bounds.y * renderer->priv->scale ||
x > bounds.width * renderer->priv->scale ||
y > bounds.height * renderer->priv->scale)
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (x < bounds.x * priv->scale ||
y < bounds.y * priv->scale ||
x > bounds.width * priv->scale ||
y > bounds.height * priv->scale)
return NULL;
data.point.x = x;
@ -1283,7 +1320,7 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
data.key = NULL;
data.renderer = renderer;
eek_container_find (EEK_CONTAINER(renderer->priv->keyboard),
eek_container_find (EEK_CONTAINER(priv->keyboard),
find_key_by_position_section_callback,
&data);
return data.key;
@ -1303,9 +1340,11 @@ create_theme_node_key_callback (EekElement *element,
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
data->renderer->priv->theme,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
@ -1318,7 +1357,7 @@ create_theme_node_key_callback (EekElement *element,
theme_node = eek_theme_node_new (data->context,
data->parent,
data->renderer->priv->theme,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
@ -1337,9 +1376,11 @@ create_theme_node_section_callback (EekElement *element,
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node, *parent;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
data->renderer->priv->theme,
priv->theme,
EEK_TYPE_SECTION,
eek_element_get_name (element),
"section",
@ -1368,22 +1409,25 @@ eek_renderer_set_theme (EekRenderer *renderer,
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_THEME(theme));
g_return_if_fail (renderer->priv->keyboard);
if (renderer->priv->theme)
g_object_unref (renderer->priv->theme);
renderer->priv->theme = g_object_ref (theme);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
g_return_if_fail (priv->keyboard);
if (priv->theme)
g_object_unref (priv->theme);
priv->theme = g_object_ref (theme);
theme_context = eek_theme_context_new ();
theme_node = eek_theme_node_new (theme_context,
NULL,
renderer->priv->theme,
priv->theme,
EEK_TYPE_KEYBOARD,
"keyboard",
"keyboard",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(renderer->priv->keyboard),
g_object_set_data_full (G_OBJECT(priv->keyboard),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
@ -1391,7 +1435,7 @@ eek_renderer_set_theme (EekRenderer *renderer,
data.context = theme_context;
data.parent = theme_node;
data.renderer = renderer;
eek_container_foreach_child (EEK_CONTAINER(renderer->priv->keyboard),
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_theme_node_section_callback,
&data);
}

View File

@ -31,21 +31,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_RENDERER (eek_renderer_get_type())
#define EEK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_RENDERER, EekRenderer))
#define EEK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_RENDERER, EekRendererClass))
#define EEK_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_RENDERER))
#define EEK_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_RENDERER))
#define EEK_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_RENDERER, EekRendererClass))
typedef struct _EekRenderer EekRenderer;
typedef struct _EekRendererClass EekRendererClass;
typedef struct _EekRendererPrivate EekRendererPrivate;
struct _EekRenderer {
GObject parent;
EekRendererPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekRenderer, eek_renderer, EEK, RENDERER, GObject)
struct _EekRendererClass
{
@ -72,7 +58,8 @@ struct _EekRendererClass
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
const gchar *icon_name,
gint size);
gint size,
gint scale);
/*< private >*/
/* padding */
@ -95,6 +82,8 @@ void eek_renderer_get_key_bounds (EekRenderer *renderer,
gboolean rotate);
gdouble eek_renderer_get_scale (EekRenderer *renderer);
void eek_renderer_set_scale_factor (EekRenderer *renderer,
gint scale);
PangoLayout *eek_renderer_create_pango_layout
(EekRenderer *renderer);
@ -117,7 +106,8 @@ void eek_renderer_render_key (EekRenderer *renderer,
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
const gchar *icon_name,
gint size);
gint size,
gint scale);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);

View File

@ -1,17 +1,17 @@
/*
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
@ -52,11 +52,6 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekSection, eek_section, EEK_TYPE_CONTAINER);
#define EEK_SECTION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SECTION, EekSectionPrivate))
struct _EekRow
{
gint num_columns;
@ -65,17 +60,19 @@ struct _EekRow
typedef struct _EekRow EekRow;
struct _EekSectionPrivate
typedef struct _EekSectionPrivate
{
gint angle;
GSList *rows;
EekModifierType modifiers;
};
} EekSectionPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
static gint
eek_section_real_get_n_rows (EekSection *self)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
return g_slist_length (priv->rows);
}
@ -85,7 +82,7 @@ eek_section_real_add_row (EekSection *self,
gint num_columns,
EekOrientation orientation)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slice_new (EekRow);
@ -100,7 +97,7 @@ eek_section_real_get_row (EekSection *self,
gint *num_columns,
EekOrientation *orientation)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slist_nth_data (priv->rows, index);
@ -129,7 +126,7 @@ static EekKey *
eek_section_real_create_key (EekSection *self,
guint keycode,
gint column_index,
guint row_index)
gint row_index)
{
EekKey *key;
gint num_rows;
@ -138,7 +135,9 @@ eek_section_real_create_key (EekSection *self,
num_rows = eek_section_get_n_rows (self);
g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
row = g_slist_nth_data (self->priv->rows, row_index);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
row = g_slist_nth_data (priv->rows, row_index);
if (row->num_columns < column_index + 1)
row->num_columns = column_index + 1;
@ -158,7 +157,7 @@ eek_section_real_create_key (EekSection *self,
static void
set_level_from_modifiers (EekSection *self)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekKeyboard *keyboard;
EekModifierType num_lock_mask;
gint level = -1;
@ -173,7 +172,7 @@ set_level_from_modifiers (EekSection *self)
static void
eek_section_real_key_pressed (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
@ -195,7 +194,7 @@ eek_section_real_key_pressed (EekSection *self, EekKey *key)
static void
eek_section_real_key_released (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
@ -225,7 +224,8 @@ eek_section_real_key_released (EekSection *self, EekKey *key)
static void
eek_section_finalize (GObject *object)
{
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(object);
EekSection *self = EEK_SECTION (object);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
GSList *head;
for (head = priv->rows; head; head = g_slist_next (head))
@ -291,8 +291,6 @@ eek_section_class_init (EekSectionClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekSectionPrivate));
klass->get_n_rows = eek_section_real_get_n_rows;
klass->add_row = eek_section_real_add_row;
klass->get_row = eek_section_real_get_row;
@ -367,7 +365,7 @@ eek_section_class_init (EekSectionClass *klass)
static void
eek_section_init (EekSection *self)
{
self->priv = EEK_SECTION_GET_PRIVATE (self);
/* void */
}
/**
@ -382,8 +380,11 @@ eek_section_set_angle (EekSection *section,
gint angle)
{
g_return_if_fail (EEK_IS_SECTION(section));
if (section->priv->angle != angle) {
section->priv->angle = angle;
EekSectionPrivate *priv = eek_section_get_instance_private (section);
if (priv->angle != angle) {
priv->angle = angle;
g_object_notify (G_OBJECT(section), "angle");
}
}
@ -398,7 +399,10 @@ gint
eek_section_get_angle (EekSection *section)
{
g_return_val_if_fail (EEK_IS_SECTION(section), -1);
return section->priv->angle;
EekSectionPrivate *priv = eek_section_get_instance_private (section);
return priv->angle;
}
/**

View File

@ -32,28 +32,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_SECTION (eek_section_get_type())
#define EEK_SECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SECTION, EekSection))
#define EEK_SECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_SECTION, EekSectionClass))
#define EEK_IS_SECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SECTION))
#define EEK_IS_SECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_SECTION))
#define EEK_SECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_SECTION, EekSectionClass))
typedef struct _EekSectionClass EekSectionClass;
typedef struct _EekSectionPrivate EekSectionPrivate;
/**
* EekSection:
*
* The #EekSection structure contains only private data and should
* only be accessed using the provided API.
*/
struct _EekSection
{
/*< private >*/
EekContainer parent;
EekSectionPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer)
/**
* EekSectionClass:

View File

@ -44,29 +44,31 @@ enum {
PROP_LAST
};
struct _EekSymbolPrivate {
typedef struct _EekSymbolPrivate
{
gchar *name;
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
gchar *icon_name;
gchar *tooltip;
};
} EekSymbolPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekSymbol, eek_symbol, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_SYMBOL_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_SYMBOL, EekSymbolPrivate))
G_DEFINE_TYPE_EXTENDED (EekSymbol,
eek_symbol,
G_TYPE_OBJECT,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekSymbol)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static void
eek_symbol_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
#define NOTNULL(s) ((s) != NULL ? (s) : "")
g_variant_builder_add (builder, "s", NOTNULL(priv->name));
g_variant_builder_add (builder, "s", NOTNULL(priv->label));
@ -82,7 +84,7 @@ eek_symbol_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(self);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "s", &priv->label);
@ -172,7 +174,8 @@ eek_symbol_get_property (GObject *object,
static void
eek_symbol_finalize (GObject *object)
{
EekSymbolPrivate *priv = EEK_SYMBOL_GET_PRIVATE(object);
EekSymbol *self = EEK_SYMBOL (object);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
g_free (priv->name);
g_free (priv->label);
@ -187,8 +190,6 @@ eek_symbol_class_init (EekSymbolClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekSymbolPrivate));
gobject_class->set_property = eek_symbol_set_property;
gobject_class->get_property = eek_symbol_get_property;
gobject_class->finalize = eek_symbol_finalize;
@ -241,9 +242,8 @@ eek_symbol_class_init (EekSymbolClass *klass)
static void
eek_symbol_init (EekSymbol *self)
{
EekSymbolPrivate *priv;
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
priv = self->priv = EEK_SYMBOL_GET_PRIVATE(self);
priv->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
@ -270,11 +270,10 @@ void
eek_symbol_set_name (EekSymbol *symbol,
const gchar *name)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->name);
priv->name = g_strdup (name);
}
@ -288,11 +287,10 @@ eek_symbol_set_name (EekSymbol *symbol,
const gchar *
eek_symbol_get_name (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->name == NULL || *priv->name == '\0')
return NULL;
return priv->name;
@ -309,11 +307,10 @@ void
eek_symbol_set_label (EekSymbol *symbol,
const gchar *label)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->label);
priv->label = g_strdup (label);
}
@ -327,11 +324,10 @@ eek_symbol_set_label (EekSymbol *symbol,
const gchar *
eek_symbol_get_label (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->label == NULL || *priv->label == '\0')
return NULL;
return priv->label;
@ -348,11 +344,10 @@ void
eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->category = category;
}
@ -365,11 +360,10 @@ eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory
eek_symbol_get_category (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->category;
}
@ -384,11 +378,10 @@ void
eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->modifier_mask = mask;
}
@ -401,11 +394,10 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType
eek_symbol_get_modifier_mask (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->modifier_mask;
}
@ -433,11 +425,10 @@ void
eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->icon_name);
priv->icon_name = g_strdup (icon_name);
}
@ -451,11 +442,10 @@ eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *
eek_symbol_get_icon_name (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->icon_name == NULL || *priv->icon_name == '\0')
return NULL;
return priv->icon_name;
@ -472,11 +462,10 @@ void
eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip)
{
EekSymbolPrivate *priv;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->tooltip);
priv->tooltip = g_strdup (tooltip);
}
@ -490,11 +479,10 @@ eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *
eek_symbol_get_tooltip (EekSymbol *symbol)
{
EekSymbolPrivate *priv;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
priv = EEK_SYMBOL_GET_PRIVATE(symbol);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->tooltip == NULL || *priv->tooltip == '\0')
return NULL;
return priv->tooltip;

View File

@ -59,27 +59,7 @@ typedef enum {
} EekSymbolCategory;
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
#define EEK_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SYMBOL, EekSymbol))
#define EEK_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_SYMBOL, EekSymbolClass))
#define EEK_IS_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SYMBOL))
#define EEK_IS_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_SYMBOL))
#define EEK_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_SYMBOL, EekSymbolClass))
typedef struct _EekSymbolClass EekSymbolClass;
typedef struct _EekSymbolPrivate EekSymbolPrivate;
/**
* EekSymbol:
*
* The #EekSymbol structure contains only private data and should only
* be accessed using the provided API.
*/
struct _EekSymbol {
/*< private >*/
GObject parent;
EekSymbolPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
/**
* EekSymbolClass:

View File

@ -36,18 +36,20 @@ enum {
PROP_LAST
};
struct _EekTextPrivate {
typedef struct _EekTextPrivate
{
gchar *text;
};
} EekTextPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekText, eek_text, EEK_TYPE_SYMBOL,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_TEXT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_TEXT, EekTextPrivate))
G_DEFINE_TYPE_EXTENDED (EekText,
eek_text,
EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekText)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_text_parent_serializable_iface;
@ -55,7 +57,7 @@ static void
eek_text_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(self);
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
eek_text_parent_serializable_iface->serialize (self, builder);
@ -67,7 +69,7 @@ eek_text_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(self);
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
index = eek_text_parent_serializable_iface->deserialize (self,
variant,
@ -93,7 +95,9 @@ eek_text_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(object);
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_free (priv->text);
@ -107,11 +111,13 @@ eek_text_set_property (GObject *object,
static void
eek_text_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(object);
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_value_set_string (value, priv->text);
@ -125,7 +131,8 @@ eek_text_get_property (GObject *object,
static void
eek_text_finalize (GObject *object)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(object);
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
g_free (priv->text);
G_OBJECT_CLASS (eek_text_parent_class)->finalize (object);
@ -137,8 +144,6 @@ eek_text_class_init (EekTextClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekTextPrivate));
gobject_class->set_property = eek_text_set_property;
gobject_class->get_property = eek_text_get_property;
gobject_class->finalize = eek_text_finalize;
@ -154,7 +159,7 @@ eek_text_class_init (EekTextClass *klass)
static void
eek_text_init (EekText *self)
{
self->priv = EEK_TEXT_GET_PRIVATE(self);
/* void */
}
EekText *
@ -176,7 +181,7 @@ eek_text_new (const gchar *text)
const gchar *
eek_text_get_text (EekText *text)
{
EekTextPrivate *priv = EEK_TEXT_GET_PRIVATE(text);
EekTextPrivate *priv = eek_text_get_instance_private (text);
return priv->text;
}

View File

@ -30,27 +30,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_TEXT (eek_text_get_type())
#define EEK_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_TEXT, EekText))
#define EEK_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_TEXT, EekTextClass))
#define EEK_IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_TEXT))
#define EEK_IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_TEXT))
#define EEK_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_TEXT, EekTextClass))
typedef struct _EekTextClass EekTextClass;
typedef struct _EekTextPrivate EekTextPrivate;
/**
* EekText:
*
* The #EekText structure contains only private data and should only
* be accessed using the provided API.
*/
struct _EekText {
/*< private >*/
EekSymbol parent;
EekTextPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE(EekText, eek_text, EEK, TEXT, EekSymbol)
struct _EekTextClass {
/*< private >*/

View File

@ -89,9 +89,6 @@ static void eek_theme_node_finalize (GObject *object);
static const EekColor BLACK_COLOR = { 0, 0, 0, 0xff };
static const EekColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
static const EekColor DEFAULT_SUCCESS_COLOR = { 0x4e, 0x9a, 0x06, 0xff };
static const EekColor DEFAULT_WARNING_COLOR = { 0xf5, 0x79, 0x3e, 0xff };
static const EekColor DEFAULT_ERROR_COLOR = { 0xcc, 0x00, 0x00, 0xff };
static void
eek_theme_node_init (EekThemeNode *self)

View File

@ -43,6 +43,7 @@
* Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
*/
#define G_LOG_DOMAIN "eek-theme"
#include <stdlib.h>
#include <string.h>
@ -166,103 +167,65 @@ eek_theme_class_init (EekThemeClass *klass)
}
/* This is a workaround for a bug in libcroco < 0.6.2 where
* function starting with 'r' (and 'u') are misparsed. We work
* around this by exploiting the fact that libcroco is incomformant
* with the CSS-spec and case sensitive and pre-convert all
* occurrences of rgba to RGBA. Then we make our own parsing
* code check for RGBA as well.
*/
#if LIBCROCO_VERSION_NUMBER < 602
static gboolean
is_identifier_character (char c)
{
/* Actual CSS rules allow for unicode > 0x00a1 and escaped
* characters, but we'll assume we won't do that in our stylesheets
* or at least not next to the string 'rgba'.
*/
return g_ascii_isalnum(c) || c == '-' || c == '_';
}
static void
convert_rgba_RGBA (char *buf)
{
char *p;
p = strstr (buf, "rgba");
while (p)
{
/* Check if this looks like a complete token; this is to
* avoiding mangling, say, a selector '.rgba-entry' */
if (!((p > buf && is_identifier_character (*(p - 1))) ||
(is_identifier_character (*(p + 4)))))
memcpy(p, "RGBA", 4);
p += 4;
p = strstr (p, "rgba");
}
}
static CRStyleSheet *
parse_stylesheet (const char *filename,
GError **error)
{
enum CRStatus status;
char *contents;
gsize length;
CRStyleSheet *stylesheet = NULL;
if (filename == NULL)
return NULL;
if (!g_file_get_contents (filename, &contents, &length, error))
return NULL;
convert_rgba_RGBA (contents);
status = cr_om_parser_simply_parse_buf ((const guchar *) contents,
length,
CR_UTF_8,
&stylesheet);
g_free (contents);
if (status != CR_OK)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error parsing stylesheet '%s'; errcode:%d", filename, status);
return NULL;
}
return stylesheet;
}
CRDeclaration *
_eek_theme_parse_declaration_list (const char *str)
{
char *copy = g_strdup (str);
CRDeclaration *result;
convert_rgba_RGBA (copy);
result = cr_declaration_parse_list_from_buf ((const guchar *)copy,
CR_UTF_8);
g_free (copy);
return result;
}
#else /* LIBCROCO_VERSION_NUMBER >= 602 */
static CRStyleSheet *
parse_stylesheet (const char *filename,
GError **error)
{
enum CRStatus status;
CRStyleSheet *stylesheet;
g_autoptr (GFileInputStream) stream = NULL;
g_autoptr (GFileInfo) info = NULL;
g_autoptr (GFile) file = NULL;
g_autofree guchar* contents = NULL;
goffset size;
gsize out = 0;
GError *err = NULL;
if (filename == NULL)
return NULL;
status = cr_om_parser_simply_parse_file ((const guchar *) filename,
CR_UTF_8,
&stylesheet);
g_debug ("Parsing %s", filename);
if (g_strcmp0 (filename, "resource://") > 0) {
file = g_file_new_for_uri (filename);
stream = g_file_read (file, NULL, &err);
if (!stream) {
g_warning ("Failed to open %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
info = g_file_input_stream_query_info (stream,
G_FILE_ATTRIBUTE_STANDARD_SIZE,
NULL,
&err);
if (!info) {
g_warning ("Failed to stat %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
size = g_file_info_get_size (info);
contents = g_malloc0 (size);
if (!g_input_stream_read_all (G_INPUT_STREAM (stream),
contents,
size,
&out,
NULL,
&err)) {
g_warning ("Failed to read %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
status = cr_om_parser_simply_parse_buf (contents,
size,
CR_UTF_8,
&stylesheet);
} else {
status = cr_om_parser_simply_parse_file ((const guchar *) filename,
CR_UTF_8,
&stylesheet);
}
if (status != CR_OK)
{
@ -280,7 +243,6 @@ _eek_theme_parse_declaration_list (const char *str)
return cr_declaration_parse_list_from_buf ((const guchar *)str,
CR_UTF_8);
}
#endif /* LIBCROCO_VERSION_NUMBER < 602 */
/* Just g_warning for now until we have something nicer to do */
static CRStyleSheet *

View File

@ -1,30 +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
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libeek-xkb
Description: A Library to Create Keyboard-like UI (XKB Support)
URL: http://fedorahosted.org/eekboard/
Version: @VERSION@
Requires: eek-@EEK_API_VERSION@ gtk+-x11-@GTK_API_VERSION@
Libs: -L${libdir} -leek-xkb
Cflags: -I${includedir}/eek-@EEK_API_VERSION@

View File

@ -1,682 +0,0 @@
/*
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
* SECTION:eek-xkb-layout
* @short_description: Layout engine using XKB configuration
*
* The #EekXkbLayout inherits #EekLayout class and arranges keyboard
* elements using XKB.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-xkb-layout.h"
#include <X11/keysym.h>
#include <X11/extensions/XKBgeom.h>
#include <string.h>
#include <stdarg.h>
#include <gio/gio.h>
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-keysym.h"
#define XKB_COMPONENT_MASK (XkbGBN_GeometryMask | \
XkbGBN_KeyNamesMask | \
XkbGBN_OtherNamesMask | \
XkbGBN_SymbolsMask | \
XkbGBN_IndicatorMapMask)
static void initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_TYPE_WITH_CODE (EekXkbLayout, eek_xkb_layout, EEK_TYPE_LAYOUT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
#define EEK_XKB_LAYOUT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutPrivate))
enum {
PROP_0,
PROP_DISPLAY,
PROP_LAST
};
struct _EekXkbLayoutPrivate
{
/* Configuration names that should synch'ed to the symbolic names
in priv->xkb->names. Since we use GLib's memory allocator,
don't store any address returned from the X server here. */
XkbComponentNamesRec names;
Display *display;
/* Actual XKB configuration of DISPLAY. */
XkbDescRec *xkb;
/* Hash table to cache orefs by shape address. */
GHashTable *shape_oref_hash;
gint scale_numerator;
gint scale_denominator;
};
static guint find_keycode (EekXkbLayout *layout,
gchar *key_name);
static gboolean get_keyboard_from_server (EekXkbLayout *layout,
GError **error);
static gboolean get_names_from_server (EekXkbLayout *layout,
GError **error);
static void setup_scaling (EekXkbLayout *layout,
gdouble width,
gdouble height);
G_INLINE_FUNC gint
xkb_to_pixmap_coord (EekXkbLayout *layout,
gint n)
{
EekXkbLayoutPrivate *priv = layout->priv;
return n * priv->scale_numerator / priv->scale_denominator;
}
G_INLINE_FUNC gdouble
xkb_to_pixmap_double (EekXkbLayout *layout,
gdouble d)
{
EekXkbLayoutPrivate *priv = layout->priv;
return d * priv->scale_numerator / priv->scale_denominator;
}
static void
create_key (EekXkbLayout *layout,
EekKeyboard *keyboard,
EekSection *section,
gint column,
gint row,
gdouble x,
gdouble y,
XkbKeyRec *xkbkey)
{
XkbGeometryRec *xkbgeometry;
XkbBoundsRec *xkbbounds;
XkbShapeRec *xkbshape;
XkbOutlineRec *xkboutline;
EekXkbLayoutPrivate *priv = layout->priv;
EekKey *key;
EekBounds bounds;
EekSymbolMatrix *matrix = NULL;
gchar name[XkbKeyNameLength + 1];
KeyCode keycode;
gint num_groups, num_levels;
guint oref;
gpointer v;
xkbgeometry = priv->xkb->geom;
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
if (g_hash_table_lookup_extended (priv->shape_oref_hash, xkbshape,
NULL, &v)) {
oref = GPOINTER_TO_UINT(v);
} else {
EekOutline *outline;
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
xkbshape->primary;
outline = g_slice_new (EekOutline);
outline->corner_radius = xkb_to_pixmap_coord(layout,
xkboutline->corner_radius);
if (xkboutline->num_points <= 2) { /* rectangular */
gdouble x1, y1, x2, y2;
outline->num_points = 4;
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
outline->num_points);
if (xkboutline->num_points == 1) {
x1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.x1);
y1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.y1);
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
} else {
x1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
y1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].x);
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].y);
}
outline->points[0].x = outline->points[3].x = x1;
outline->points[0].y = outline->points[1].y = y1;
outline->points[1].x = outline->points[2].x = x2;
outline->points[2].y = outline->points[3].y = y2;
} else { /* polygon */
gint i;
outline->num_points = xkboutline->num_points;
outline->points = g_new0 (EekPoint, outline->num_points);
for (i = 0; i < xkboutline->num_points; i++) {
outline->points[i].x =
xkb_to_pixmap_coord(layout, xkboutline->points[i].x);
outline->points[i].y =
xkb_to_pixmap_coord(layout, xkboutline->points[i].y);
}
}
oref = eek_keyboard_add_outline (keyboard, outline);
eek_outline_free (outline);
g_hash_table_insert (priv->shape_oref_hash, xkbshape,
GUINT_TO_POINTER(oref));
}
memset (name, 0, sizeof name);
memcpy (name, xkbkey->name.name, sizeof name - 1);
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
bounds.x = xkb_to_pixmap_coord(layout, xkbbounds->x1 + x);
bounds.y = xkb_to_pixmap_coord(layout, xkbbounds->y1 + y);
bounds.width = xkb_to_pixmap_coord(layout, xkbbounds->x2 - xkbbounds->x1);
bounds.height = xkb_to_pixmap_coord(layout, xkbbounds->y2 - xkbbounds->y1);
keycode = find_keycode (layout, name);
if (keycode == EEK_INVALID_KEYCODE) {
num_groups = num_levels = 0;
matrix = eek_symbol_matrix_new (0, 0);
} else {
KeySym keysym;
gint i, j;
num_groups = XkbKeyNumGroups (priv->xkb, keycode);
num_levels = XkbKeyGroupsWidth (priv->xkb, keycode);
matrix = eek_symbol_matrix_new (num_groups, num_levels);
for (i = 0; i < num_groups; i++)
for (j = 0; j < num_levels; j++) {
EekModifierType modifier;
keysym = XkbKeySymEntry (priv->xkb, keycode, j, i);
modifier = XkbKeysymToModifiers (priv->display, keysym);
matrix->data[i * num_levels + j] =
EEK_SYMBOL(eek_keysym_new_with_modifier (keysym,
modifier));
}
}
key = eek_section_create_key (section, keycode, column, row);
eek_element_set_name (EEK_ELEMENT(key), name);
eek_element_set_bounds (EEK_ELEMENT(key), &bounds);
eek_key_set_symbol_matrix (key, matrix);
eek_symbol_matrix_free (matrix);
eek_key_set_oref (key, oref);
}
static void
create_section (EekXkbLayout *layout,
EekKeyboard *keyboard,
XkbSectionRec *xkbsection)
{
XkbGeometryRec *xkbgeometry;
EekXkbLayoutPrivate *priv;
EekSection *section;
EekBounds bounds;
gchar *name;
gfloat left, top;
gint i, j;
bounds.x = xkb_to_pixmap_coord(layout, xkbsection->left);
bounds.y = xkb_to_pixmap_coord(layout, xkbsection->top);
bounds.width = xkb_to_pixmap_coord(layout, xkbsection->width);
bounds.height = xkb_to_pixmap_coord(layout, xkbsection->height);
priv = layout->priv;
xkbgeometry = priv->xkb->geom;
section = eek_keyboard_create_section (keyboard);
name = XGetAtomName (priv->display, xkbsection->name);
eek_element_set_name (EEK_ELEMENT(section), name);
XFree (name);
eek_element_set_bounds (EEK_ELEMENT(section), &bounds);
eek_section_set_angle (section,
/* angle is in tenth of degree */
xkbsection->angle / 10);
for (i = 0; i < xkbsection->num_rows; i++) {
XkbRowRec *xkbrow;
xkbrow = &xkbsection->rows[i];
left = xkbrow->left;
top = xkbrow->top;
eek_section_add_row (section,
xkbrow->num_keys,
xkbrow->vertical ?
EEK_ORIENTATION_VERTICAL :
EEK_ORIENTATION_HORIZONTAL);
for (j = 0; j < xkbrow->num_keys; j++) {
XkbKeyRec *xkbkey;
XkbBoundsRec *xkbbounds;
xkbkey = &xkbrow->keys[j];
if (xkbrow->vertical)
top += xkbkey->gap;
else
left += xkbkey->gap;
create_key (layout, keyboard, section, j, i, left, top, xkbkey);
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
if (xkbrow->vertical)
top += xkbbounds->y2 - xkbbounds->y1;
else
left += xkbbounds->x2 - xkbbounds->x1;
}
}
}
static void
create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
{
EekXkbLayoutPrivate *priv = layout->priv;
XkbGeometryRec *xkbgeometry;
EekBounds bounds;
gint i;
g_return_if_fail (priv->xkb);
g_return_if_fail (priv->xkb->geom);
xkbgeometry = priv->xkb->geom;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
setup_scaling (EEK_XKB_LAYOUT(layout), bounds.width, bounds.height);
bounds.x = bounds.y = 0;
bounds.width = xkb_to_pixmap_coord(layout, xkbgeometry->width_mm);
bounds.height = xkb_to_pixmap_coord(layout, xkbgeometry->height_mm);
for (i = 0; i < xkbgeometry->num_sections; i++) {
XkbSectionRec *xkbsection;
xkbsection = &xkbgeometry->sections[i];
create_section (layout, keyboard, xkbsection);
}
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
}
static EekKeyboard *
eek_xkb_layout_real_create_keyboard (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height)
{
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
keyboard->manager = manager;
EekBounds bounds = {
.x = 0.0,
.y = 0.0,
.width = initial_width,
.height = initial_height
};
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
/* resolve modifiers dynamically assigned at run time */
EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
eek_keyboard_set_num_lock_mask (keyboard,
XkbKeysymToModifiers (priv->display,
XK_Num_Lock));
eek_keyboard_set_alt_gr_mask (keyboard,
XkbKeysymToModifiers (priv->display,
XK_ISO_Level3_Shift));
if (priv->shape_oref_hash)
g_hash_table_destroy (priv->shape_oref_hash);
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
g_hash_table_destroy (priv->shape_oref_hash);
return keyboard;
}
static void
eek_xkb_layout_finalize (GObject *object)
{
EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (object);
g_free (priv->names.keycodes);
g_free (priv->names.geometry);
g_free (priv->names.symbols);
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
}
static void
eek_xkb_layout_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
switch (prop_id) {
case PROP_DISPLAY:
layout->priv->display = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkb_layout_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
switch (prop_id) {
case PROP_DISPLAY:
g_value_set_pointer (value, layout->priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
{
EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekXkbLayoutPrivate));
layout_class->create_keyboard = eek_xkb_layout_real_create_keyboard;
gobject_class->finalize = eek_xkb_layout_finalize;
gobject_class->set_property = eek_xkb_layout_set_property;
gobject_class->get_property = eek_xkb_layout_get_property;
pspec = g_param_spec_pointer ("display",
"Display",
"X Display",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (gobject_class, PROP_DISPLAY, pspec);
}
static void
eek_xkb_layout_init (EekXkbLayout *self)
{
self->priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
}
static gboolean
get_names_from_server (EekXkbLayout *layout,
GError **error)
{
EekXkbLayoutPrivate *priv = layout->priv;
gchar *name;
XkbGetNames (priv->display, XkbAllNamesMask, priv->xkb);
if (priv->xkb->names->keycodes <= 0)
g_warning ("XKB keycodes setting is not loaded properly");
else {
name = XGetAtomName (priv->display, priv->xkb->names->keycodes);
if (!name)
g_warning ("Can't get the name of keycodes");
else if (!priv->names.keycodes ||
g_strcmp0 (name, priv->names.keycodes)) {
g_free (priv->names.keycodes);
priv->names.keycodes = g_strdup (name);
XFree (name);
}
}
if (priv->xkb->names->geometry <= 0)
g_warning ("XKB geometry setting is not loaded");
else {
name = XGetAtomName (priv->display, priv->xkb->names->geometry);
if (!name)
g_warning ("Can't get the name of geometry");
else if (!priv->names.geometry ||
g_strcmp0 (name, priv->names.geometry)) {
g_free (priv->names.geometry);
priv->names.geometry = g_strdup (name);
XFree (name);
}
}
if (priv->xkb->names->symbols <= 0)
g_warning ("XKB symbols setting is not loaded");
else {
name = XGetAtomName (priv->display, priv->xkb->names->symbols);
if (!name)
g_warning ("Can't get the name of symbols");
else if (!priv->names.symbols ||
g_strcmp0 (name, priv->names.symbols)) {
g_free (priv->names.symbols);
priv->names.symbols = g_strdup (name);
XFree (name);
}
}
return TRUE;
}
/**
* eek_xkb_layout_new:
*
* Create a new #EekXkbLayout.
*/
EekLayout *
eek_xkb_layout_new (Display *display,
GError **error)
{
return (EekLayout *) g_initable_new (EEK_TYPE_XKB_LAYOUT,
NULL,
error,
"display", display,
NULL);
}
/**
* eek_xkb_layout_set_names: (skip)
* @layout: an #EekXkbLayout
* @names: XKB component names
* @error: a #GError
*
* Set the XKB component names to @layout.
* Returns: %TRUE if the component names are successfully set, %FALSE otherwise
*/
gboolean
eek_xkb_layout_set_names (EekXkbLayout *layout,
XkbComponentNamesRec *names,
GError **error)
{
if (g_strcmp0 (names->keycodes, layout->priv->names.keycodes)) {
g_free (layout->priv->names.keycodes);
layout->priv->names.keycodes = g_strdup (names->keycodes);
}
if (g_strcmp0 (names->geometry, layout->priv->names.geometry)) {
g_free (layout->priv->names.geometry);
layout->priv->names.geometry = g_strdup (names->geometry);
}
if (g_strcmp0 (names->symbols, layout->priv->names.symbols)) {
g_free (layout->priv->names.symbols);
layout->priv->names.symbols = g_strdup (names->symbols);
}
return get_keyboard_from_server (layout, error);
}
static gboolean
get_keyboard_from_server (EekXkbLayout *layout,
GError **error)
{
EekXkbLayoutPrivate *priv = layout->priv;
if (priv->xkb) {
XkbFreeKeyboard (priv->xkb, 0, True);
priv->xkb = NULL;
}
if (priv->names.keycodes && priv->names.geometry && priv->names.symbols) {
priv->xkb = XkbGetKeyboardByName (priv->display,
XkbUseCoreKbd,
&priv->names,
0,
XKB_COMPONENT_MASK,
False);
} else {
priv->xkb = XkbGetKeyboard (priv->display,
XKB_COMPONENT_MASK,
XkbUseCoreKbd);
if (!get_names_from_server (layout, error)) {
XkbFreeKeyboard (priv->xkb, 0, True);
priv->xkb = NULL;
}
}
if (priv->xkb == NULL) {
g_set_error (error,
EEK_ERROR,
EEK_ERROR_LAYOUT_ERROR,
"can't get keyboard from server");
g_free (priv->names.keycodes);
priv->names.keycodes = NULL;
g_free (priv->names.geometry);
priv->names.geometry = NULL;
g_free (priv->names.symbols);
priv->names.symbols = NULL;
return FALSE;
}
return TRUE;
}
static guint
find_keycode (EekXkbLayout *layout, gchar *key_name)
{
#define KEYSYM_NAME_MAX_LENGTH 4
guint keycode;
gint i, j;
XkbKeyNamePtr pkey;
XkbKeyAliasPtr palias;
guint is_name_matched;
gchar *src, *dst;
EekXkbLayoutPrivate *priv = layout->priv;
if (!priv->xkb)
return EEK_INVALID_KEYCODE;
pkey = priv->xkb->names->keys + priv->xkb->min_key_code;
for (keycode = priv->xkb->min_key_code;
keycode <= priv->xkb->max_key_code; keycode++) {
is_name_matched = 1;
src = key_name;
dst = pkey->name;
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
if ('\0' == *src)
break;
if (*src++ != *dst++) {
is_name_matched = 0;
break;
}
}
if (is_name_matched)
return keycode;
pkey++;
}
palias = priv->xkb->names->key_aliases;
for (j = priv->xkb->names->num_key_aliases; --j >= 0;) {
is_name_matched = 1;
src = key_name;
dst = palias->alias;
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
if ('\0' == *src)
break;
if (*src++ != *dst++) {
is_name_matched = 0;
break;
}
}
if (is_name_matched) {
keycode = find_keycode (layout, palias->real);
return keycode;
}
palias++;
}
return EEK_INVALID_KEYCODE;
}
static void
setup_scaling (EekXkbLayout *layout,
gdouble width,
gdouble height)
{
EekXkbLayoutPrivate *priv = layout->priv;
g_return_if_fail (priv->xkb);
g_return_if_fail (priv->xkb->geom->width_mm > 0);
g_return_if_fail (priv->xkb->geom->height_mm > 0);
if (width * priv->xkb->geom->height_mm <
height * priv->xkb->geom->width_mm) {
priv->scale_numerator = width;
priv->scale_denominator = priv->xkb->geom->width_mm;
} else {
priv->scale_numerator = height;
priv->scale_denominator = priv->xkb->geom->height_mm;
}
}
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
EekXkbLayout *layout = EEK_XKB_LAYOUT (initable);
if (!get_keyboard_from_server (layout, error))
return FALSE;
if (!get_names_from_server (layout, error))
return FALSE;
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
initable_iface->init = initable_init;
}

View File

@ -1,71 +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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek-xkb.h> can be included directly."
#endif
#ifndef EEK_XKB_LAYOUT_H
#define EEK_XKB_LAYOUT_H 1
#include <X11/XKBlib.h>
#include "eek-layout.h"
G_BEGIN_DECLS
#define EEK_TYPE_XKB_LAYOUT (eek_xkb_layout_get_type())
#define EEK_XKB_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayout))
#define EEK_XKB_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutClass))
#define EEK_IS_XKB_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_XKB_LAYOUT))
#define EEK_IS_XKB_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_XKB_LAYOUT))
#define EEK_XKB_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_XKB_LAYOUT, EekXkbLayoutClass))
typedef struct _EekXkbLayout EekXkbLayout;
typedef struct _EekXkbLayoutClass EekXkbLayoutClass;
typedef struct _EekXkbLayoutPrivate EekXkbLayoutPrivate;
struct _EekXkbLayout
{
/*< private >*/
EekLayout parent;
EekXkbLayoutPrivate *priv;
};
struct _EekXkbLayoutClass
{
/*< private >*/
EekLayoutClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_xkb_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xkb_layout_new (Display *display,
GError **error);
gboolean eek_xkb_layout_set_names (EekXkbLayout *layout,
XkbComponentNamesRec *names,
GError **error);
G_END_DECLS
#endif /* #ifndef EEK_XKB_LAYOUT_H */

View File

@ -1,26 +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_XKB_H
#define EEK_XKB_H 1
#include "eek.h"
#include "eek-xkb-layout.h"
#endif /* EEK_XKB_H */

View File

@ -1,30 +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
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libeek-xkl
Description: A Library to Create Keyboard-like UI (Libxklavier Support)
URL: http://fedorahosted.org/eekboard/
Version: @VERSION@
Requires: eek-@EEK_API_VERSION@ libxklavier
Libs: -L${libdir} -leek-xkl
Cflags: -I${includedir}/eek-@EEK_API_VERSION@

View File

@ -1,663 +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
*/
/**
* SECTION:eek-xkl-layout
* @short_description: Layout engine using Libxklavier configuration
*
* The #EekXklLayout is a simple wrapper around #EekXkbLayout class
* to use Libxklavier configuration.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <libxklavier/xklavier.h>
#include <gio/gio.h>
#include <string.h>
#include "eek-xkl-layout.h"
#define noKBDRAW_DEBUG
static GInitableIface *parent_initable_iface;
static void initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_TYPE_WITH_CODE (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
#define EEK_XKL_LAYOUT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayoutPrivate))
enum {
PROP_0,
PROP_MODEL,
PROP_LAYOUTS,
PROP_VARIANTS,
PROP_OPTIONS,
PROP_LAST
};
struct _EekXklLayoutPrivate
{
XklEngine *engine;
XklConfigRec *config;
};
/* from gnome-keyboard-properties-xkbpv.c:
* BAD STYLE: Taken from xklavier_private_xkb.h
* Any ideas on architectural improvements are WELCOME
*/
extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
const XklConfigRec * data,
XkbComponentNamesPtr
component_names);
extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
XkbComponentNamesPtr
component_names);
static gboolean set_xkb_component_names (EekXklLayout *layout,
XklConfigRec *config);
static void
eek_xkl_layout_dispose (GObject *object)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (object);
if (priv->config) {
g_object_unref (priv->config);
priv->config = NULL;
}
G_OBJECT_CLASS (eek_xkl_layout_parent_class)->dispose (object);
}
static void
eek_xkl_layout_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
switch (prop_id) {
case PROP_MODEL:
eek_xkl_layout_set_model (layout, g_value_get_string (value));
break;
case PROP_LAYOUTS:
eek_xkl_layout_set_layouts (layout, g_value_get_boxed (value));
break;
case PROP_VARIANTS:
eek_xkl_layout_set_variants (layout, g_value_get_boxed (value));
break;
case PROP_OPTIONS:
eek_xkl_layout_set_options (layout, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkl_layout_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
switch (prop_id) {
case PROP_MODEL:
g_value_set_string (value,
eek_xkl_layout_get_model (layout));
break;
case PROP_LAYOUTS:
g_value_set_boxed (value,
eek_xkl_layout_get_layouts (layout));
break;
case PROP_VARIANTS:
g_value_set_boxed (value,
eek_xkl_layout_get_variants (layout));
break;
case PROP_OPTIONS:
g_value_set_boxed (value,
eek_xkl_layout_get_options (layout));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_xkl_layout_class_init (EekXklLayoutClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekXklLayoutPrivate));
gobject_class->dispose = eek_xkl_layout_dispose;
gobject_class->set_property = eek_xkl_layout_set_property;
gobject_class->get_property = eek_xkl_layout_get_property;
/**
* EekXklLayout:model:
*
* The libxklavier model name of #EekXklLayout.
*/
pspec = g_param_spec_string ("model",
"Model",
"Libxklavier model",
NULL,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODEL, pspec);
/**
* EekXklLayout:layouts:
*
* The libxklavier layout names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("layouts",
"Layouts",
"Libxklavier layouts",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LAYOUTS, pspec);
/**
* EekXklLayout:variants:
*
* The libxklavier variant names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("variants",
"Variants",
"Libxklavier variants",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_VARIANTS, pspec);
/**
* EekXklLayout:options:
*
* The libxklavier option names of #EekXklLayout.
*/
pspec = g_param_spec_boxed ("options",
"Options",
"Libxklavier options",
G_TYPE_STRV,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OPTIONS, pspec);
}
static void
eek_xkl_layout_init (EekXklLayout *self)
{
self->priv = EEK_XKL_LAYOUT_GET_PRIVATE (self);
}
/**
* eek_xkl_layout_new:
*
* Create a new #EekXklLayout.
*/
EekLayout *
eek_xkl_layout_new (Display *display, GError **error)
{
return (EekLayout *) g_initable_new (EEK_TYPE_XKL_LAYOUT,
NULL,
error,
"display", display,
NULL);
}
G_INLINE_FUNC void
merge_xkl_config_rec (XklConfigRec *dst, XklConfigRec *src)
{
if (src->model) {
g_free (dst->model);
dst->model = g_strdup (src->model);
}
if (src->layouts) {
g_strfreev (dst->layouts);
dst->layouts = g_strdupv (src->layouts);
}
if (src->variants) {
g_strfreev (dst->variants);
dst->variants = g_strdupv (src->variants);
}
if (src->options) {
g_strfreev (dst->options);
dst->options = g_strdupv (src->options);
}
}
/**
* eek_xkl_layout_set_config: (skip)
* @layout: an #EekXklLayout
* @config: Libxklavier configuration
*
* Reconfigure @layout with @config.
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_config (EekXklLayout *layout,
XklConfigRec *config)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
XklConfigRec *c;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
c = xkl_config_rec_new ();
merge_xkl_config_rec (c, priv->config);
merge_xkl_config_rec (c, config);
retval = set_xkb_component_names (layout, c);
g_object_unref (c);
merge_xkl_config_rec (priv->config, config);
return retval;
}
/**
* eek_xkl_layout_set_config_full:
* @layout: an #EekXklLayout
* @model: Libxklavier model name
* @layouts: Libxklavier layouts
* @variants: Libxklavier variants
* @options: Libxklavier options
*
* Reconfigure @layout with @model, @layouts, @variants, and @options.
* This function is merely a wrapper around
* eek_xkl_layout_set_config() to avoid passing a pointer of
* XklConfigRec, which is not currently available in the
* gobject-introspection repository.
*
* Returns: %TRUE if the current layout changed, %FALSE otherwise
* Since: 0.0.2
*/
gboolean
eek_xkl_layout_set_config_full (EekXklLayout *layout,
gchar *model,
gchar **layouts,
gchar **variants,
gchar **options)
{
XklConfigRec *config;
gboolean retval;
config = xkl_config_rec_new ();
config->model = g_strdup (model);
config->layouts = g_strdupv (layouts);
config->variants = g_strdupv (variants);
config->options = g_strdupv (options);
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_model:
* @layout: an #EekXklLayout
* @model: model name
*
* Set the model name of @layout configuration (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_model (EekXklLayout *layout,
const gchar *model)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->model will be freed on g_object_unref (config) */
if (model)
config->model = g_strdup (model);
else
config->model = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_layouts:
* @layout: an #EekXklLayout
* @layouts: layout names
*
* Set the layout names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_layouts (EekXklLayout *layout,
gchar **layouts)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->layouts will be freed on g_object_unref (config) */
if (layouts)
config->layouts = g_strdupv (layouts);
else
config->layouts = layouts;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_variants:
* @layout: an #EekXklLayout
* @variants: variant names
*
* Set the variant names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_variants (EekXklLayout *layout,
gchar **variants)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->variants will be freed on g_object_unref (config) */
if (variants)
config->variants = g_strdupv (variants);
else
config->variants = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_set_options:
* @layout: an #EekXklLayout
* @options: option names
*
* Set the option names of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_set_options (EekXklLayout *layout,
gchar **options)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
XklConfigRec *config;
gboolean retval;
g_return_val_if_fail (priv, FALSE);
config = xkl_config_rec_new ();
/* config->options will be freed on g_object_unref (config) */
if (options)
config->options = options;
else
config->options = NULL;
retval = eek_xkl_layout_set_config (layout, config);
g_object_unref (config);
return retval;
}
/**
* eek_xkl_layout_enable_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Set the option of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_enable_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options, **_options;
gint i, j;
options = eek_xkl_layout_get_options (layout);
for (i = 0; options && options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
return TRUE;
_options = g_new0 (gchar *, (i + 2));
for (j = 0; j < i; j++)
_options[j] = g_strdup (options[j]);
_options[i] = g_strdup (option);
/* eek_xkl_layout_set_options() will free _options and its elements. */
return eek_xkl_layout_set_options (layout, _options);
}
/**
* eek_xkl_layout_disable_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Unset the option of @layout (in the Libxklavier terminology).
* Returns: %TRUE if the current layout changed, %FALSE otherwise
*/
gboolean
eek_xkl_layout_disable_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options, **_options;
gint i, j, k;
options = eek_xkl_layout_get_options (layout);
if (!options)
return TRUE;
for (i = 0, k = 0; options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
k = i;
if (options[k] == NULL)
return TRUE;
_options = g_new0 (gchar *, i);
for (j = 0; j < k; j++)
_options[j] = g_strdup (options[j]);
for (j = k + 1; j < i; j++)
_options[j] = g_strdup (options[j]);
/* eek_xkl_layout_set_options() will free _options and its elements. */
return eek_xkl_layout_set_options (layout, _options);
}
/**
* eek_xkl_layout_get_model:
* @layout: an #EekXklLayout
*
* Get the model name of @layout configuration (in the Libxklavier terminology).
*/
gchar *
eek_xkl_layout_get_model (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
g_return_val_if_fail (priv, NULL);
return g_strdup (priv->config->model);
}
/**
* eek_xkl_layout_get_layouts:
* @layout: an #EekXklLayout
*
* Get the layout names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_layouts (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->layouts);
}
/**
* eek_xkl_layout_get_variants:
* @layout: an #EekXklLayout
*
* Get the variant names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_variants (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->variants);
}
/**
* eek_xkl_layout_get_options:
* @layout: an #EekXklLayout
*
* Get the option names of @layout configuration (in the Libxklavier
* terminology).
*/
gchar **
eek_xkl_layout_get_options (EekXklLayout *layout)
{
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
g_return_val_if_fail (priv, NULL);
return g_strdupv (priv->config->options);
}
static gboolean
set_xkb_component_names (EekXklLayout *layout, XklConfigRec *config)
{
EekXklLayoutPrivate *priv = layout->priv;
XkbComponentNamesRec names;
gboolean retval = FALSE;
#if DEBUG
if (config->layouts) {
gint i;
fprintf (stderr, "layout = ");
for (i = 0; config->layouts[i] != NULL; i++)
fprintf (stderr, "\"%s\" ", config->layouts[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "layouts = NULL\n");
if (config->variants) {
gint i;
fprintf (stderr, "variant = ");
for (i = 0; config->variants[i]; i++)
fprintf (stderr, "\"%s\" ", config->variants[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "variants = NULL\n");
if (config->options) {
gint i;
fprintf (stderr, "option = ");
for (i = 0; config->options[i]; i++)
fprintf (stderr, "\"%s\" ", config->options[i]);
fputc ('\n', stderr);
} else
fprintf (stderr, "options = NULL\n");
#endif
if (xkl_xkb_config_native_prepare (priv->engine, config, &names)) {
GError *error = NULL;
retval = eek_xkb_layout_set_names (EEK_XKB_LAYOUT(layout),
&names,
&error);
if (!retval)
g_warning ("can't set XKB layout");
xkl_xkb_config_native_cleanup (priv->engine, &names);
}
return retval;
}
/**
* eek_xkl_layout_get_option:
* @layout: an #EekXklLayout
* @option: option name
*
* Tell if the option of @layout (in the Libxklavier terminology) is set.
* Returns: %TRUE if the option is set, %FALSE otherwise
*/
gboolean
eek_xkl_layout_get_option (EekXklLayout *layout,
const gchar *option)
{
gchar **options;
gint i;
options = eek_xkl_layout_get_options (layout);
for (i = 0; options && options[i]; i++)
if (g_strcmp0 (options[i], option) == 0)
return TRUE;
return FALSE;
}
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
EekXklLayout *layout = EEK_XKL_LAYOUT (initable);
Display *display;
if (!parent_initable_iface->init (initable, cancellable, error))
return FALSE;
layout->priv->config = xkl_config_rec_new ();
g_object_get (G_OBJECT (initable),
"display", &display,
NULL);
layout->priv->engine = xkl_engine_get_instance (display);
if (!xkl_config_rec_get_from_server (layout->priv->config,
layout->priv->engine)) {
g_set_error (error,
EEK_ERROR,
EEK_ERROR_LAYOUT_ERROR,
"can't load libxklavier configuration");
return FALSE;
}
set_xkb_component_names (layout, layout->priv->config);
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
parent_initable_iface = g_type_interface_peek_parent (initable_iface);
initable_iface->init = initable_init;
}

View File

@ -1,97 +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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek-xkl.h> can be included directly."
#endif
#ifndef EEK_XKL_LAYOUT_H
#define EEK_XKL_LAYOUT_H 1
#include <libxklavier/xklavier.h>
#include "eek-xkb-layout.h"
G_BEGIN_DECLS
#define EEK_TYPE_XKL_LAYOUT (eek_xkl_layout_get_type())
#define EEK_XKL_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayout))
#define EEK_XKL_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_XKL_LAYOUT, EekXklLayoutClass))
#define EEK_IS_XKL_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_XKL_LAYOUT))
#define EEK_IS_XKL_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_XKL_LAYOUT))
#define EEK_XKL_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_XKL_LAYOUT, EekXklLayoutClass))
typedef struct _EekXklLayout EekXklLayout;
typedef struct _EekXklLayoutClass EekXklLayoutClass;
typedef struct _EekXklLayoutPrivate EekXklLayoutPrivate;
struct _EekXklLayout
{
/*< private >*/
EekXkbLayout parent;
EekXklLayoutPrivate *priv;
};
struct _EekXklLayoutClass
{
/*< private >*/
EekXkbLayoutClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_xkl_layout_get_type (void) G_GNUC_CONST;
EekLayout *eek_xkl_layout_new (Display *display,
GError **error);
gboolean eek_xkl_layout_set_config (EekXklLayout *layout,
XklConfigRec *config);
gboolean eek_xkl_layout_set_config_full (EekXklLayout *layout,
gchar *model,
gchar **layouts,
gchar **variants,
gchar **options);
gboolean eek_xkl_layout_set_model (EekXklLayout *layout,
const gchar *model);
gboolean eek_xkl_layout_set_layouts (EekXklLayout *layout,
gchar **layouts);
gboolean eek_xkl_layout_set_variants (EekXklLayout *layout,
gchar **variants);
gboolean eek_xkl_layout_set_options (EekXklLayout *layout,
gchar **options);
gboolean eek_xkl_layout_enable_option (EekXklLayout *layout,
const gchar *option);
gboolean eek_xkl_layout_disable_option (EekXklLayout *layout,
const gchar *option);
gchar *eek_xkl_layout_get_model (EekXklLayout *layout);
gchar **eek_xkl_layout_get_layouts (EekXklLayout *layout);
gchar **eek_xkl_layout_get_variants (EekXklLayout *layout);
gchar **eek_xkl_layout_get_options (EekXklLayout *layout);
gboolean eek_xkl_layout_get_option (EekXklLayout *layout,
const gchar *option);
G_END_DECLS
#endif /* #ifndef EEK_XKL_LAYOUT_H */

View File

@ -1,26 +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_XKL_H
#define EEK_XKL_H 1
#include "eek.h"
#include "eek-xkl-layout.h"
#endif /* EEK_XKL_H */

View File

@ -1,7 +1,7 @@
/*
/*
* 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
@ -25,6 +25,7 @@
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <gio/gio.h> /* GResource */
#include <stdlib.h>
#include <string.h>
@ -35,6 +36,8 @@
#include "eek-keysym.h"
#include "eek-text.h"
#include "squeekboard-resources.h"
enum {
PROP_0,
PROP_ID,
@ -43,19 +46,18 @@ enum {
static void initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_TYPE_WITH_CODE (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
#define EEK_XML_LAYOUT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_XML_LAYOUT, EekXmlLayoutPrivate))
struct _EekXmlLayoutPrivate
typedef struct _EekXmlLayoutPrivate
{
gchar *id;
gchar *keyboards_dir;
EekXmlKeyboardDesc *desc;
};
} EekXmlLayoutPrivate;
G_DEFINE_TYPE_EXTENDED (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT,
0, /* GTypeFlags */
G_ADD_PRIVATE(EekXmlLayout)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init))
G_DEFINE_BOXED_TYPE(EekXmlKeyboardDesc, eek_xml_keyboard_desc, eek_xml_keyboard_desc_copy, eek_xml_keyboard_desc_free);
@ -360,8 +362,6 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
if (g_strcmp0 (data->element_stack->data, "geometry") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
else if (g_strcmp0 (data->element_stack->data, "section") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->section), &bounds);
goto out;
}
@ -452,7 +452,7 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
"corner-radius");
if (attribute != NULL)
data->corner_radius = g_strtod (attribute, NULL);
goto out;
}
@ -903,6 +903,7 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
gdouble initial_height)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (self);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
gboolean retval;
/* Create an empty keyboard to which geometry and symbols
@ -911,8 +912,8 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
keyboard->manager = manager;
/* Read geometry information. */
gchar *filename = g_strdup_printf ("%s.xml", layout->priv->desc->geometry);
gchar *path = g_build_filename (layout->priv->keyboards_dir, "geometry", filename, NULL);
gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry);
gchar *path = g_build_filename (priv->keyboards_dir, "geometry", filename, NULL);
g_free (filename);
GError *error = NULL;
@ -921,7 +922,7 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
if (!retval) {
g_object_unref (keyboard);
g_warning ("can't parse geometry file %s: %s",
layout->priv->desc->geometry,
priv->desc->geometry,
error->message);
g_error_free (error);
return NULL;
@ -929,8 +930,8 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
/* Read symbols information. */
GList *loaded = NULL;
retval = parse_symbols_with_prerequisites (layout->priv->keyboards_dir,
layout->priv->desc->symbols,
retval = parse_symbols_with_prerequisites (priv->keyboards_dir,
priv->desc->symbols,
keyboard,
&loaded,
&error);
@ -938,7 +939,7 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
if (!retval) {
g_object_unref (keyboard);
g_warning ("can't parse symbols file %s: %s",
layout->priv->desc->symbols,
priv->desc->symbols,
error->message);
g_error_free (error);
return NULL;
@ -961,10 +962,12 @@ eek_xml_layout_set_property (GObject *object,
GParamSpec *pspec)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (object);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
switch (prop_id) {
case PROP_ID:
g_free (layout->priv->id);
layout->priv->id = g_value_dup_string (value);
g_free (priv->id);
priv->id = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -979,9 +982,11 @@ eek_xml_layout_get_property (GObject *object,
GParamSpec *pspec)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (object);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
switch (prop_id) {
case PROP_ID:
g_value_set_string (value, layout->priv->id);
g_value_set_string (value, priv->id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -992,7 +997,8 @@ eek_xml_layout_get_property (GObject *object,
static void
eek_xml_layout_finalize (GObject *object)
{
EekXmlLayoutPrivate *priv = EEK_XML_LAYOUT_GET_PRIVATE (object);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (
EEK_XML_LAYOUT (object));
g_free (priv->id);
@ -1011,8 +1017,6 @@ eek_xml_layout_class_init (EekXmlLayoutClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (EekXmlLayoutPrivate));
layout_class->create_keyboard = eek_xml_layout_real_create_keyboard;
gobject_class->set_property = eek_xml_layout_set_property;
@ -1031,7 +1035,7 @@ eek_xml_layout_class_init (EekXmlLayoutClass *klass)
static void
eek_xml_layout_init (EekXmlLayout *self)
{
self->priv = EEK_XML_LAYOUT_GET_PRIVATE (self);
/* void */
}
EekLayout *
@ -1050,16 +1054,17 @@ initable_init (GInitable *initable,
GError **error)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (initable);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
GList *keyboards, *p;
gchar *path;
EekXmlKeyboardDesc *desc;
layout->priv->keyboards_dir = (gchar *) g_getenv ("EEKBOARD_KEYBOARDSDIR");
if (layout->priv->keyboards_dir == NULL)
layout->priv->keyboards_dir = KEYBOARDSDIR;
layout->priv->keyboards_dir = g_strdup (layout->priv->keyboards_dir);
priv->keyboards_dir = g_strdup ((gchar *) g_getenv ("EEKBOARD_KEYBOARDSDIR"));
path = g_build_filename (layout->priv->keyboards_dir, "keyboards.xml", NULL);
if (priv->keyboards_dir == NULL)
priv->keyboards_dir = g_strdup ("resource:///sm/puri/squeekboard/keyboards/");
path = g_build_filename (priv->keyboards_dir, "keyboards.xml", NULL);
keyboards = parse_keyboards (path, error);
g_free (path);
if (error && *error)
@ -1067,7 +1072,7 @@ initable_init (GInitable *initable,
for (p = keyboards; p; p = p->next) {
desc = p->data;
if (g_strcmp0 (desc->id, layout->priv->id) == 0)
if (g_strcmp0 (desc->id, priv->id) == 0)
break;
}
if (p == NULL) {
@ -1075,12 +1080,12 @@ initable_init (GInitable *initable,
EEK_ERROR,
EEK_ERROR_LAYOUT_ERROR,
"no such keyboard %s",
layout->priv->id);
priv->id);
return FALSE;
}
keyboards = g_list_remove_link (keyboards, p);
layout->priv->desc = p->data;
priv->desc = p->data;
g_list_free_1 (p);
g_list_free_full (keyboards, (GDestroyNotify) keyboard_desc_free);
@ -1108,7 +1113,7 @@ eek_xml_list_keyboards (void)
keyboards_dir = g_getenv ("EEKBOARD_KEYBOARDSDIR");
if (keyboards_dir == NULL)
keyboards_dir = KEYBOARDSDIR;
keyboards_dir = g_strdup ("resource:///sm/puri/squeekboard/keyboards/");
path = g_build_filename (keyboards_dir, "keyboards.xml", NULL);
keyboards = parse_keyboards (path, NULL);
g_free (path);
@ -1177,7 +1182,9 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
GFileInputStream *input;
gboolean retval;
file = g_file_new_for_path (path);
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1303,7 +1310,9 @@ parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error)
GFileInputStream *input;
gboolean retval;
file = g_file_new_for_path (path);
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1336,7 +1345,9 @@ parse_prerequisites (const gchar *path, GError **error)
GList *prerequisites;
gboolean retval;
file = g_file_new_for_path (path);
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1371,7 +1382,9 @@ parse_keyboards (const gchar *path, GError **error)
GList *keyboards;
gboolean retval;
file = g_file_new_for_path (path);
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1448,7 +1461,7 @@ static void scale_keyboard (EekKeyboard *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;

View File

@ -29,29 +29,7 @@
G_BEGIN_DECLS
#define EEK_TYPE_XML_LAYOUT (eek_xml_layout_get_type())
#define EEK_XML_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_XML_LAYOUT, EekXmlLayout))
#define EEK_XML_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_XML_LAYOUT, EekXmlLayoutClass))
#define EEK_IS_XML_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_XML_LAYOUT))
#define EEK_IS_XML_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_XML_LAYOUT))
#define EEK_XML_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_XML_LAYOUT, EekXmlLayoutClass))
typedef struct _EekXmlLayout EekXmlLayout;
typedef struct _EekXmlLayoutClass EekXmlLayoutClass;
typedef struct _EekXmlLayoutPrivate EekXmlLayoutPrivate;
/**
* EekXmlLayout:
*
* The #EekXmlLayout structure contains only private data and should
* only be accessed using the provided API.
*/
struct _EekXmlLayout
{
/*< private >*/
EekLayout parent;
EekXmlLayoutPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekXmlLayout, eek_xml_layout, EEK, XML_LAYOUT, EekLayout)
/**
* EekXmlLayoutClass:

View File

@ -38,9 +38,5 @@
void
eek_init (void)
{
g_type_init ();
g_type_class_ref (EEK_TYPE_SYMBOL);
g_type_class_ref (EEK_TYPE_KEYSYM);
g_type_class_ref (EEK_TYPE_TEXT);
/* void */
}

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@ -82,9 +82,9 @@ struct _EekboardContextServicePrivate {
GSettings *settings;
};
G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
static Display *display = NULL;
/*static Display *display = NULL; */
static EekKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
@ -150,13 +150,14 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
rules.layout = strdup(keyboard_type);
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref(context);
if (!keymap) {
g_error("Bad keymap");
}
keyboard->keymap = keymap;
char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
keyboard->keymap_len = strlen(keymap_str) + 1;
char *path = strdup("/eek_keymap-XXXXXX");
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
char *r = &path[strlen(path) - 6];
getrandom(r, 6, GRND_NONBLOCK);
for (uint i = 0; i < 6; i++) {
@ -284,6 +285,7 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
}
}
g_variant_iter_free(iter);
g_variant_unref(inputs);
}
static void
@ -356,9 +358,6 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekboardContextServicePrivate));
klass->create_keyboard = eekboard_context_service_real_create_keyboard;
klass->show_keyboard = eekboard_context_service_real_show_keyboard;
klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
@ -483,51 +482,6 @@ eekboard_context_service_init (EekboardContextService *self)
}
}
static gboolean on_repeat_timeout (EekboardContextService *context);
static gboolean
on_repeat_timeout (EekboardContextService *context)
{
guint delay = 500; // ms
// hardcoding; needs to connect to yet another settings path because
// org.gnome.desktop.input-sources doesn't control repeating
//g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
return FALSE;
}
static gboolean
on_repeat_timeout_init (EekboardContextService *context)
{
/* FIXME: clear modifiers for further key repeat; better not
depend on modifier behavior is LATCH */
eek_keyboard_set_modifiers (context->priv->keyboard, 0);
/* reschedule repeat timeout only when "repeat" option is set */
/* TODO: org.gnome.desktop.input-sources doesn't have repeat info.
* In addition, repeat is only useful when the keyboard is not in text
* input mode */
/*
if (g_settings_get_boolean (context->priv->settings, "repeat")) {
guint delay;
g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
} else */
context->priv->repeat_timeout_id = 0;
return FALSE;
}
/**
* eekboard_context_service_enable:
* @context: an #EekboardContextService
@ -569,7 +523,9 @@ eekboard_context_service_show_keyboard (EekboardContextService *context)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->show_keyboard (context);
if (!context->priv->visible) {
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->show_keyboard (context);
}
}
void
@ -577,7 +533,9 @@ eekboard_context_service_hide_keyboard (EekboardContextService *context)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->hide_keyboard (context);
if (context->priv->visible) {
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->hide_keyboard (context);
}
}
/**

View File

@ -49,18 +49,15 @@ enum {
PROP_LAST
};
G_DEFINE_TYPE (EekboardContext, eekboard_context, G_TYPE_DBUS_PROXY);
#define EEKBOARD_CONTEXT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEKBOARD_TYPE_CONTEXT, EekboardContextPrivate))
struct _EekboardContextPrivate
typedef struct _EekboardContextPrivate
{
gboolean visible;
gboolean enabled;
gboolean fullscreen;
gint group;
};
} EekboardContextPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContext, eekboard_context, G_TYPE_DBUS_PROXY)
static void
eekboard_context_real_g_signal (GDBusProxy *self,
@ -69,6 +66,7 @@ eekboard_context_real_g_signal (GDBusProxy *self,
GVariant *parameters)
{
EekboardContext *context = EEKBOARD_CONTEXT (self);
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (g_strcmp0 (signal_name, "Enabled") == 0) {
g_signal_emit (context, signals[ENABLED], 0);
@ -111,8 +109,8 @@ eekboard_context_real_g_signal (GDBusProxy *self,
gboolean visible = FALSE;
g_variant_get (parameters, "(b)", &visible);
if (visible != context->priv->visible) {
context->priv->visible = visible;
if (visible != priv->visible) {
priv->visible = visible;
g_object_notify (G_OBJECT(context), "visible");
}
return;
@ -122,8 +120,8 @@ eekboard_context_real_g_signal (GDBusProxy *self,
gint group = 0;
g_variant_get (parameters, "(i)", &group);
if (group != context->priv->group) {
context->priv->group = group;
if (group != priv->group) {
priv->group = group;
/* g_object_notify (G_OBJECT(context), "group"); */
}
return;
@ -135,13 +133,17 @@ eekboard_context_real_g_signal (GDBusProxy *self,
static void
eekboard_context_real_enabled (EekboardContext *self)
{
self->priv->enabled = TRUE;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (self);
priv->enabled = TRUE;
}
static void
eekboard_context_real_disabled (EekboardContext *self)
{
self->priv->enabled = FALSE;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (self);
priv->enabled = FALSE;
}
static void
@ -164,9 +166,11 @@ eekboard_context_get_property (GObject *object,
GParamSpec *pspec)
{
EekboardContext *context = EEKBOARD_CONTEXT(object);
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
switch (prop_id) {
case PROP_VISIBLE:
g_value_set_boolean (value, context->priv->visible);
g_value_set_boolean (value, priv->visible);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -181,9 +185,6 @@ eekboard_context_class_init (EekboardContextClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekboardContextPrivate));
klass->enabled = eekboard_context_real_enabled;
klass->disabled = eekboard_context_real_disabled;
klass->destroyed = eekboard_context_real_destroyed;
@ -288,7 +289,7 @@ eekboard_context_class_init (EekboardContextClass *klass)
static void
eekboard_context_init (EekboardContext *self)
{
self->priv = EEKBOARD_CONTEXT_GET_PRIVATE(self);
/* void */
}
static void
@ -485,7 +486,9 @@ eekboard_context_set_group (EekboardContext *context,
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->group != group) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->group != group) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"SetGroup",
g_variant_new ("(i)", group),
@ -509,7 +512,10 @@ eekboard_context_get_group (EekboardContext *context,
GCancellable *cancellable)
{
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), 0);
return context->priv->group;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
return priv->group;
}
/**
@ -526,7 +532,9 @@ eekboard_context_show_keyboard (EekboardContext *context,
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->enabled) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->enabled) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"ShowKeyboard",
NULL,
@ -551,7 +559,9 @@ eekboard_context_hide_keyboard (EekboardContext *context,
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->enabled) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->enabled) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"HideKeyboard",
NULL,
@ -578,7 +588,9 @@ eekboard_context_press_keycode (EekboardContext *context,
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->enabled) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->enabled) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"PressKeycode",
g_variant_new ("(u)", keycode),
@ -605,7 +617,9 @@ eekboard_context_release_keycode (EekboardContext *context,
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->enabled) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->enabled) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"ReleaseKeycode",
g_variant_new ("(u)", keycode),
@ -627,7 +641,10 @@ gboolean
eekboard_context_is_visible (EekboardContext *context)
{
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), FALSE);
return context->priv->enabled && context->priv->visible;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
return priv->enabled && priv->visible;
}
/**
@ -644,7 +661,10 @@ eekboard_context_set_enabled (EekboardContext *context,
gboolean enabled)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
context->priv->enabled = enabled;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
priv->enabled = enabled;
}
/**
@ -657,7 +677,10 @@ gboolean
eekboard_context_is_enabled (EekboardContext *context)
{
g_return_val_if_fail (EEKBOARD_IS_CONTEXT(context), FALSE);
return context->priv->enabled;
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
return priv->enabled;
}
/**
@ -674,7 +697,10 @@ eekboard_context_set_fullscreen (EekboardContext *context,
GCancellable *cancellable)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
if (context->priv->fullscreen != fullscreen) {
EekboardContextPrivate *priv = eekboard_context_get_instance_private (context);
if (priv->fullscreen != fullscreen) {
g_dbus_proxy_call (G_DBUS_PROXY(context),
"SetFullscreen",
g_variant_new ("(b)", fullscreen),

View File

@ -28,28 +28,7 @@
G_BEGIN_DECLS
#define EEKBOARD_TYPE_CONTEXT (eekboard_context_get_type())
#define EEKBOARD_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_CONTEXT, EekboardContext))
#define EEKBOARD_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_CONTEXT, EekboardContextClass))
#define EEKBOARD_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_CONTEXT))
#define EEKBOARD_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_CONTEXT))
#define EEKBOARD_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_CONTEXT, EekboardContextClass))
typedef struct _EekboardContext EekboardContext;
typedef struct _EekboardContextClass EekboardContextClass;
typedef struct _EekboardContextPrivate EekboardContextPrivate;
/**
* EekboardContext:
*
* The #EekboardContext structure contains only private data and
* should only be accessed using the provided API.
*/
struct _EekboardContext {
/*< private >*/
GDBusProxy parent;
EekboardContextPrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekboardContext, eekboard_context, EEKBOARD, CONTEXT, GDBusProxy)
/**
* EekboardContextClass:

View File

@ -50,10 +50,8 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
#define EEKBOARD_SERVICE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEKBOARD_TYPE_SERVICE, EekboardServicePrivate))
struct _EekboardServicePrivate {
typedef struct _EekboardServicePrivate
{
GDBusConnection *connection;
SmPuriOSK0 *dbus_interface;
GDBusNodeInfo *introspection_data;
@ -61,9 +59,9 @@ struct _EekboardServicePrivate {
char *object_path;
EekboardContextService *context; // unowned reference
};
} EekboardServicePrivate;
G_DEFINE_TYPE (EekboardService, eekboard_service, G_TYPE_OBJECT);
G_DEFINE_TYPE_WITH_PRIVATE (EekboardService, eekboard_service, G_TYPE_OBJECT)
static void
eekboard_service_set_property (GObject *object,
@ -72,19 +70,20 @@ eekboard_service_set_property (GObject *object,
GParamSpec *pspec)
{
EekboardService *service = EEKBOARD_SERVICE(object);
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
GDBusConnection *connection;
switch (prop_id) {
case PROP_OBJECT_PATH:
if (service->priv->object_path)
g_free (service->priv->object_path);
service->priv->object_path = g_value_dup_string (value);
if (priv->object_path)
g_free (priv->object_path);
priv->object_path = g_value_dup_string (value);
break;
case PROP_CONNECTION:
connection = g_value_get_object (value);
if (service->priv->connection)
g_object_unref (service->priv->connection);
service->priv->connection = g_object_ref (connection);
if (priv->connection)
g_object_unref (priv->connection);
priv->connection = g_object_ref (connection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -99,13 +98,14 @@ eekboard_service_get_property (GObject *object,
GParamSpec *pspec)
{
EekboardService *service = EEKBOARD_SERVICE(object);
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
switch (prop_id) {
case PROP_OBJECT_PATH:
g_value_set_string (value, service->priv->object_path);
g_value_set_string (value, priv->object_path);
break;
case PROP_CONNECTION:
g_value_set_object (value, service->priv->connection);
g_value_set_object (value, priv->connection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -117,20 +117,27 @@ static void
eekboard_service_dispose (GObject *object)
{
EekboardService *service = EEKBOARD_SERVICE(object);
if (service->priv->connection) {
if (service->priv->registration_id > 0) {
g_dbus_connection_unregister_object (service->priv->connection,
service->priv->registration_id);
service->priv->registration_id = 0;
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
if (priv->connection) {
if (priv->registration_id > 0) {
g_dbus_connection_unregister_object (priv->connection,
priv->registration_id);
priv->registration_id = 0;
}
g_object_unref (service->priv->connection);
service->priv->connection = NULL;
g_object_unref (priv->connection);
priv->connection = NULL;
}
if (service->priv->introspection_data) {
g_dbus_node_info_unref (service->priv->introspection_data);
service->priv->introspection_data = NULL;
if (priv->introspection_data) {
g_dbus_node_info_unref (priv->introspection_data);
priv->introspection_data = NULL;
}
if (priv->context) {
g_signal_handlers_disconnect_by_data (priv->context, service);
priv->context = NULL;
}
G_OBJECT_CLASS (eekboard_service_parent_class)->dispose (object);
@ -140,8 +147,9 @@ static void
eekboard_service_finalize (GObject *object)
{
EekboardService *service = EEKBOARD_SERVICE(object);
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
g_free (service->priv->object_path);
g_free (priv->object_path);
G_OBJECT_CLASS (eekboard_service_parent_class)->finalize (object);
}
@ -150,33 +158,51 @@ static gboolean
handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
gboolean arg_visible, gpointer user_data) {
EekboardService *service = user_data;
if (service->priv->context) {
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
if (priv->context) {
if (arg_visible) {
eekboard_context_service_show_keyboard (service->priv->context);
eekboard_context_service_show_keyboard (priv->context);
} else {
eekboard_context_service_hide_keyboard (service->priv->context);
eekboard_context_service_hide_keyboard (priv->context);
}
}
sm_puri_osk0_complete_set_visible(object, invocation);
return TRUE;
}
static void on_visible(EekboardService *service,
GParamSpec *pspec,
EekboardContextService *context)
{
gboolean visible;
EekboardServicePrivate *priv;
g_return_if_fail (EEKBOARD_IS_SERVICE (service));
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE (context));
priv = eekboard_service_get_instance_private (service);
g_object_get (context, "visible", &visible, NULL);
sm_puri_osk0_set_visible(priv->dbus_interface, visible);
}
static void
eekboard_service_constructed (GObject *object)
{
EekboardService *service = EEKBOARD_SERVICE(object);
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
service->priv->dbus_interface = sm_puri_osk0_skeleton_new();
sm_puri_osk0_set_visible(service->priv->dbus_interface, FALSE); // TODO: use actual value
g_signal_connect(service->priv->dbus_interface, "handle-set-visible",
priv->dbus_interface = sm_puri_osk0_skeleton_new();
g_signal_connect(priv->dbus_interface, "handle-set-visible",
G_CALLBACK(handle_set_visible), service);
if (service->priv->connection && service->priv->object_path) {
if (priv->connection && priv->object_path) {
GError *error = NULL;
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(service->priv->dbus_interface),
service->priv->connection,
service->priv->object_path,
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(priv->dbus_interface),
priv->connection,
priv->object_path,
&error)) {
g_warning("Error registering dbus object: %s\n", error->message);
g_clear_error(&error);
@ -190,9 +216,6 @@ eekboard_service_class_init (EekboardServiceClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekboardServicePrivate));
klass->create_context = NULL;
gobject_class->constructed = eekboard_service_constructed;
@ -250,8 +273,9 @@ eekboard_service_class_init (EekboardServiceClass *klass)
static void
eekboard_service_init (EekboardService *self)
{
self->priv = EEKBOARD_SERVICE_GET_PRIVATE(self);
self->priv->context = NULL;
EekboardServicePrivate *priv = eekboard_service_get_instance_private (self);
priv->context = NULL;
}
/**
@ -271,7 +295,16 @@ eekboard_service_new (GDBusConnection *connection,
void
eekboard_service_set_context(EekboardService *service,
EekboardContextService *context)
{
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
EekboardContextService *context) {
service->priv->context = context;
g_return_if_fail (!priv->context);
priv->context = context;
g_signal_connect_swapped (priv->context,
"notify::visible",
G_CALLBACK(on_visible),
service);
}

View File

@ -28,30 +28,7 @@ G_BEGIN_DECLS
#define EEKBOARD_SERVICE_INTERFACE "sm.puri.OSK0"
#define EEKBOARD_TYPE_SERVICE (eekboard_service_get_type())
#define EEKBOARD_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_SERVICE, EekboardService))
#define EEKBOARD_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_SERVICE, EekboardServiceClass))
#define EEKBOARD_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_SERVICE))
#define EEKBOARD_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_SERVICE))
#define EEKBOARD_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_SERVICE, EekboardServiceClass))
typedef struct _EekboardService EekboardService;
typedef struct _EekboardServiceClass EekboardServiceClass;
typedef struct _EekboardServicePrivate EekboardServicePrivate;
/**
* EekboardService:
*
* Manages DBus interaction.
*
* The #EekboardService structure contains only private data and
* should only be accessed using the provided API.
*/
struct _EekboardService {
/*< private >*/
GObject parent;
EekboardServicePrivate *priv;
};
G_DECLARE_DERIVABLE_TYPE (EekboardService, eekboard_service, EEKBOARD, SERVICE, GObject)
/**
* EekboardServiceClass:

View File

@ -1,168 +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
*/
#include <string.h>
#include "eekboard/eekboard-xklutil.h"
XklConfigRec *
eekboard_xkl_config_rec_from_string (const gchar *layouts)
{
XklConfigRec *rec;
gchar **strv, **l, **v;
gint i;
strv = g_strsplit (layouts, "/", -1);
g_return_val_if_fail (g_strv_length (strv) == 3, NULL);
l = g_strsplit (strv[1], ";", -1);
v = g_strdupv (l);
for (i = 0; l[i]; i++) {
gchar *layout = l[i], *variant = v[i],
*variant_start, *variant_end;
variant_start = strchr (layout, '(');
variant_end = strrchr (layout, ')');
if (variant_start && variant_end) {
*variant_start++ = '\0';
g_strlcpy (variant, variant_start,
variant_end - variant_start + 1);
} else
*variant = '\0';
}
rec = xkl_config_rec_new ();
rec->model = g_strdup (strv[0]);
rec->layouts = l;
rec->variants = v;
rec->options = g_strsplit (strv[2], ";", -1);
g_strfreev (strv);
return rec;
}
gchar *
eekboard_xkl_config_rec_to_string (XklConfigRec *rec)
{
gchar **strv, **sp, **lp, **vp, *p;
gint n_layouts;
GString *str;
n_layouts = g_strv_length (rec->layouts);
strv = g_malloc0_n (n_layouts + 2, sizeof (gchar *));
for (sp = strv, lp = rec->layouts, vp = rec->variants; *lp; sp++, lp++) {
if (*vp != NULL && **vp != '\0')
*sp = g_strdup_printf ("%s(%s)", *lp, *vp++);
else
*sp = g_strdup_printf ("%s", *lp);
}
/* MODEL/L0(V0);L1(V1);...;Ln(Vn)/O0;O1;...;On */
str = g_string_new (rec->model);
g_string_append_c (str, '/');
p = g_strjoinv (";", strv);
g_strfreev (strv);
g_string_append (str, p);
g_free (p);
g_string_append_c (str, '/');
p = g_strjoinv (";", rec->options);
g_string_append (str, p);
g_free (p);
return g_string_free (str,FALSE);
}
static XklConfigItem *
xkl_config_item_copy (const XklConfigItem *item)
{
XklConfigItem *_item = xkl_config_item_new ();
memcpy (_item->name,
item->name,
sizeof (item->name));
memcpy (_item->short_description,
item->short_description,
sizeof (item->short_description));
memcpy (_item->description,
item->description,
sizeof (item->description));
return _item;
}
static void
prepend_item (XklConfigRegistry *registry,
const XklConfigItem *item,
gpointer data)
{
GSList **list = data;
XklConfigItem *_item = xkl_config_item_copy (item);
*list = g_slist_prepend (*list, _item);
}
static gint
compare_item_by_name (gconstpointer a, gconstpointer b)
{
const XklConfigItem *ia = a, *ib = b;
return g_strcmp0 (ia->name, ib->name);
}
GSList *
eekboard_xkl_list_models (XklConfigRegistry *registry)
{
GSList *list = NULL;
xkl_config_registry_foreach_model (registry, prepend_item, &list);
return g_slist_sort (list, compare_item_by_name);
}
GSList *
eekboard_xkl_list_layouts (XklConfigRegistry *registry)
{
GSList *list = NULL;
xkl_config_registry_foreach_layout (registry, prepend_item, &list);
return g_slist_sort (list, compare_item_by_name);
}
GSList *
eekboard_xkl_list_option_groups (XklConfigRegistry *registry)
{
GSList *list = NULL;
xkl_config_registry_foreach_option_group (registry, prepend_item, &list);
return g_slist_sort (list, compare_item_by_name);
}
GSList *
eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
const gchar *layout)
{
GSList *list = NULL;
xkl_config_registry_foreach_layout_variant (registry,
layout,
prepend_item,
&list);
return g_slist_sort (list, compare_item_by_name);
}
GSList *
eekboard_xkl_list_options (XklConfigRegistry *registry,
const gchar *group)
{
GSList *list = NULL;
xkl_config_registry_foreach_option (registry, group, prepend_item, &list);
return g_slist_sort (list, compare_item_by_name);
}

View File

@ -1,39 +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
*/
#ifndef EEKBOARD_XKLUTIL_H
#define EEKBOARD_XKLUTIL_H 1
#include <libxklavier/xklavier.h>
G_BEGIN_DECLS
XklConfigRec *eekboard_xkl_config_rec_from_string (const gchar *layouts);
gchar *eekboard_xkl_config_rec_to_string (XklConfigRec *rec);
GSList *eekboard_xkl_list_models (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layouts (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_option_groups (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
const gchar *layout);
GSList *eekboard_xkl_list_options (XklConfigRegistry *registry,
const gchar *group);
G_END_DECLS
#endif /* EEKBOARD_XKLUTIL_H */

View File

@ -78,11 +78,12 @@ replace_keycode (SeatEmitter *emitter,
guint keycode,
guint *keysym)
{
GdkDisplay *display = gdk_display_get_default ();
//Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
/* 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,

View File

@ -3,12 +3,14 @@ project(
'c', 'rust',
version: '1.0.10',
license: 'GPLv3',
meson_version: '>=0.43.0',
meson_version: '>=0.49.0',
default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ],
)
i18n = import('i18n')
conf_data = configuration_data()
if get_option('buildtype').startswith('debug')
add_project_arguments('-DDEBUG=1', language : 'c')
endif
@ -26,6 +28,22 @@ else
endif
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 = [
'',
'------------------',
'squeekboard @0@'.format(meson.project_version()),
'',
' gsound: @0@'.format(conf_data.get('HAVE_GSOUND', false)),
'------------------',
''
]
message('\n'.join(summary))
subdir('data')
subdir('protocols')
subdir('eek')

View File

@ -11,7 +11,6 @@ gen_scanner_client_code = generator(wl_scanner,
wl_protos = [
wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir + '/unstable/text-input/text-input-unstable-v3.xml',
'wlr-layer-shell-unstable-v1.xml',
'virtual-keyboard-unstable-v1.xml',
'input-method-unstable-v2.xml',

View File

@ -1,320 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#ifdef HAVE_ATSPI
#include <dbus/dbus.h>
#include <atspi/atspi.h>
#endif /* HAVE_ATSPI */
#ifdef HAVE_IBUS
#include <ibus.h>
#endif /* HAVE_IBUS */
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "eekboard/eekboard-client.h"
#include "client.h"
static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE;
static gchar *opt_address = NULL;
static gboolean opt_focus = FALSE;
#ifdef HAVE_ATSPI
static gboolean opt_keystroke = FALSE;
#endif /* HAVE_ATSPI */
static gchar *opt_keyboards = NULL;
static gboolean opt_fullscreen = FALSE;
static const GOptionEntry options[] = {
{"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
N_("Connect to the system bus")},
{"session", 'e', 0, G_OPTION_ARG_NONE, &opt_session,
N_("Connect to the session bus")},
{"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address,
N_("Connect to the given D-Bus address")},
#if ENABLE_FOCUS_LISTENER
{"listen-focus", 'f', 0, G_OPTION_ARG_NONE, &opt_focus,
N_("Listen focus change events")},
#endif /* ENABLE_FOCUS_LISTENER */
#ifdef HAVE_ATSPI
{"listen-keystroke", 's', 0, G_OPTION_ARG_NONE, &opt_keystroke,
N_("Listen keystroke events with AT-SPI")},
#endif /* HAVE_ATSPI */
{"keyboards", 'k', 0, G_OPTION_ARG_STRING, &opt_keyboards,
N_("Specify keyboards (comma separated)")},
{"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
N_("Create window in fullscreen mode")},
{NULL}
};
static void
on_context_destroyed (EekboardContext *context,
gpointer user_data)
{
gtk_main_quit ();
}
static void
on_destroyed (EekboardClient *eekboard,
gpointer user_data)
{
gtk_main_quit ();
}
enum FocusListenerType {
FOCUS_NONE,
FOCUS_ATSPI,
FOCUS_IBUS
};
static gboolean
set_keyboards (SeatEmitter *client,
const gchar * const *keyboards)
{
if (g_strv_length ((gchar **)keyboards) == 0) {
if (!client_enable_xkl (client)) {
g_printerr ("Can't register xklavier event listeners\n");
return FALSE;
}
} else {
if (!client_set_keyboards (client, keyboards)) {
gchar *str = g_strjoinv (", ", (gchar **)keyboards);
g_printerr ("Can't set keyboards \"%s\"\n", str);
g_free (str);
return FALSE;
}
}
return TRUE;
}
int
main (int argc, char **argv)
{
SeatEmitter *client = NULL;
EekboardClient *eekboard;
EekboardContext *context;
GBusType bus_type;
GDBusConnection *connection;
GError *error;
GOptionContext *option_context;
gint focus;
GSettings *settings = NULL;
gchar **keyboards = NULL;
gint retval = 0;
if (!gtk_init_check (&argc, &argv)) {
g_printerr ("Can't init GTK\n");
exit (1);
}
eek_init ();
option_context = g_option_context_new ("eekboard-desktop-client");
g_option_context_add_main_entries (option_context, options, NULL);
g_option_context_parse (option_context, &argc, &argv, NULL);
g_option_context_free (option_context);
if (opt_system)
bus_type = G_BUS_TYPE_SYSTEM;
else if (opt_address)
bus_type = G_BUS_TYPE_NONE;
else
bus_type = G_BUS_TYPE_SESSION;
switch (bus_type) {
case G_BUS_TYPE_SYSTEM:
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (connection == NULL) {
g_printerr ("Can't connect to the system bus: %s\n",
error->message);
g_error_free (error);
exit (1);
}
break;
case G_BUS_TYPE_SESSION:
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_printerr ("Can't connect to the session bus: %s\n",
error->message);
g_error_free (error);
exit (1);
}
break;
case G_BUS_TYPE_NONE:
error = NULL;
connection = g_dbus_connection_new_for_address_sync (opt_address,
0,
NULL,
NULL,
&error);
if (connection == NULL) {
g_printerr ("Can't connect to the bus at %s: %s\n",
opt_address,
error->message);
g_error_free (error);
exit (1);
}
break;
default:
g_assert_not_reached ();
break;
}
client = client_new (connection);
g_object_unref (connection);
if (client == NULL) {
g_printerr ("Can't create a client\n");
exit (1);
}
settings = g_settings_new ("org.fedorahosted.eekboard");
focus = FOCUS_NONE;
if (opt_focus) {
gchar *focus_listener = g_settings_get_string (settings,
"focus-listener");
const struct {
const gchar *name;
enum FocusListenerType type;
} focus_listeners[] = {
#ifdef HAVE_ATSPI
{ "atspi", FOCUS_ATSPI },
#endif
#ifdef HAVE_IBUS
{ "ibus", FOCUS_IBUS },
#endif
{ NULL }
};
gint i;
focus = FOCUS_NONE;
for (i = 0; focus_listeners[i].name; i++) {
if (g_strcmp0 (focus_listener, focus_listeners[i].name) == 0)
focus = focus_listeners[i].type;
}
if (focus == FOCUS_NONE) {
g_printerr ("Unknown focus listener \"%s\". "
"Try \"atspi\" or \"ibus\"\n", focus_listener);
retval = 1;
goto out;
}
}
#ifdef HAVE_ATSPI
if (focus == FOCUS_ATSPI || opt_keystroke) {
GSettings *desktop_settings =
g_settings_new ("org.gnome.desktop.interface");
gboolean accessibility_enabled =
g_settings_get_boolean (desktop_settings, "toolkit-accessibility");
g_object_unref (desktop_settings);
if (accessibility_enabled) {
if (atspi_init () != 0) {
g_printerr ("Can't init AT-SPI 2\n");
retval = 1;
goto out;
}
if (focus == FOCUS_ATSPI &&
!client_enable_atspi_focus (client)) {
g_printerr ("Can't register AT-SPI focus change event listeners\n");
retval = 1;
goto out;
}
if (opt_keystroke &&
!client_enable_atspi_keystroke (client)) {
g_printerr ("Can't register AT-SPI keystroke event listeners\n");
retval = 1;
goto out;
}
} else {
g_printerr ("Desktop accessibility support is disabled\n");
retval = 1;
goto out;
}
}
#endif /* HAVE_ATSPI */
#ifdef HAVE_IBUS
if (focus == FOCUS_IBUS) {
ibus_init ();
if (!client_enable_ibus_focus (client)) {
g_printerr ("Can't register IBus focus change event listeners\n");
retval = 1;
goto out;
}
}
#endif /* HAVE_IBUS */
//#ifdef HAVE_XTEST
if (!client_enable_xtest (client)) {
g_printerr ("Can't init xtest\n");
g_object_unref (client);
exit (1);
}
//#endif /* HAVE_XTEST */
if (!opt_focus) {
g_object_get (client, "context", &context, NULL);
g_signal_connect (context, "destroyed",
G_CALLBACK(on_context_destroyed), NULL);
g_object_unref (context);
}
if (opt_fullscreen ||
g_settings_get_boolean (settings, "start-fullscreen")) {
g_object_get (client, "context", &context, NULL);
eekboard_context_set_fullscreen (context, TRUE, NULL);
g_object_unref (context);
}
g_object_get (client, "eekboard", &eekboard, NULL);
g_signal_connect (eekboard, "destroyed",
G_CALLBACK(on_destroyed), NULL);
g_object_unref (eekboard);
if (opt_keyboards != NULL) {
keyboards = g_strsplit (opt_keyboards, ",", -1);
if (!set_keyboards (client, (const gchar * const *)keyboards)) {
g_strfreev (keyboards);
retval = 1;
goto out;
}
g_strfreev (keyboards);
}
gtk_main ();
out:
if (client)
g_object_unref (client);
if (settings)
g_object_unref (settings);
return retval;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLIENT_H
#define CLIENT_H 1
#include <gio/gio.h>
G_BEGIN_DECLS
#define TYPE_CLIENT (client_get_type())
#define CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLIENT, Client))
#define CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLIENT, ClientClass))
#define IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLIENT))
#define IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLIENT))
#define CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CLIENT, ClientClass))
typedef struct _Client SeatEmitter;
SeatEmitter *client_new (GDBusConnection *connection);
gboolean client_set_keyboards (SeatEmitter *client,
const gchar * const *keyboard);
gboolean client_enable_xkl (SeatEmitter *client);
void client_disable_xkl (SeatEmitter *client);
gboolean client_enable_atspi_focus (SeatEmitter *client);
void client_disable_atspi_focus (SeatEmitter *client);
gboolean client_enable_atspi_keystroke (SeatEmitter *client);
void client_disable_atspi_keystroke (SeatEmitter *client);
gboolean client_enable_xtest (SeatEmitter *client);
void client_disable_xtest (SeatEmitter *client);
gboolean client_enable_ibus_focus (SeatEmitter *client);
void client_disable_ibus_focus (SeatEmitter *client);
G_END_DECLS
#endif /* CLIENT_H */

6
src/config.h.in Normal file
View File

@ -0,0 +1,6 @@
/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#mesondefine HAVE_GSOUND

View File

@ -5,8 +5,8 @@
#include "eekboard/eekboard-context-service.h"
void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method) {}
void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method) {}
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) {}

View File

@ -1,20 +1,16 @@
gnome = import('gnome')
dbus_src = gnome.gdbus_codegen(
'sm.puri.OSK0',
join_paths(dbusdir, 'sm.puri.OSK0.xml')
join_paths(meson.source_root() / 'data' / 'dbus', 'sm.puri.OSK0.xml')
)
squeek_enum_headers = [
'squeek-input-method.h',
]
squeek_enums = gnome.mkenums_simple('squeek-enumtypes', sources: squeek_enum_headers)
config_h = configure_file(input: 'config.h.in', output: 'config.h',configuration: conf_data)
sources = [
config_h,
'imservice.c',
'server-context-service.c',
'server-main.c',
'squeek-input-method.c',
'wayland.c',
'../eek/eek.c',
'../eek/eek-container.c',
@ -40,7 +36,6 @@ sources = [
'../eek/layersurface.c',
dbus_src,
enums,
squeek_enums,
keysym_entries,
marshalers,
'../eekboard/keymap.c',
@ -48,7 +43,8 @@ sources = [
'../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-context.c',
'../eekboard/eekboard-service.c',
# '../eekboard/eekboard-xklutil.c',
# '../eekboard/eekboard-xklutil.c',
squeekboard_resources,
wl_proto_sources,
]
@ -67,6 +63,7 @@ deps = [
cc.find_library('dl'),
cc.find_library('pthread'),
# dependency('libxklavier'), # FIXME remove
gsound_dep,
]
# Replacement for eekboard-server

View File

@ -1,415 +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/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <gtk/gtk.h>
#include "preferences-dialog.h"
#include <eek/eek.h>
struct _PreferencesDialog {
GtkWidget *dialog;
GtkWidget *repeat_toggle;
GtkWidget *repeat_delay_scale;
GtkWidget *repeat_speed_scale;
GtkWidget *auto_hide_toggle;
GtkWidget *auto_hide_delay_scale;
GtkWidget *selected_keyboards_treeview;
GtkWidget *up_button;
GtkWidget *down_button;
GtkWidget *add_button;
GtkWidget *remove_button;
GtkWidget *new_keyboard_dialog;
GtkWidget *available_keyboards_treeview;
GList *available_keyboards;
GSettings *settings;
};
static gboolean
get_rate (GValue *value,
GVariant *variant,
gpointer user_data)
{
int rate;
gdouble fraction;
rate = g_variant_get_uint32 (variant);
fraction = 1.0 / ((gdouble) rate / 1000.0);
g_value_set_double (value, fraction);
return TRUE;
}
static GVariant *
set_rate (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
{
gdouble rate;
int msecs;
rate = g_value_get_double (value);
msecs = (1 / rate) * 1000;
return g_variant_new_uint32 (msecs);
}
static void
add_keyboard_to_treeview (GtkTreeView *treeview,
const gchar *id,
const gchar *longname)
{
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first (model, &iter)) {
do {
gchar *_id;
gtk_tree_model_get (model, &iter, 0, &_id, -1);
if (g_strcmp0 (id, _id) == 0) {
g_free (_id);
return;
}
g_free (_id);
} while (gtk_tree_model_iter_next (model, &iter));
}
gtk_list_store_append (GTK_LIST_STORE(model),
&iter);
gtk_list_store_set (GTK_LIST_STORE(model),
&iter,
0, id,
1, longname,
-1);
}
static void
add_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
gint retval = gtk_dialog_run (GTK_DIALOG(dialog->new_keyboard_dialog));
if (retval == GTK_RESPONSE_OK) {
GtkTreeSelection *selection;
GtkTreeModel *model;
GList *rows, *p;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->available_keyboards_treeview));
rows = gtk_tree_selection_get_selected_rows (selection, &model);
for (p = rows; p; p = p->next) {
GtkTreeIter iter;
if (gtk_tree_model_get_iter (model, &iter, p->data)) {
gchar *id, *longname;
gtk_tree_model_get (model, &iter, 0, &id, 1, &longname, -1);
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->selected_keyboards_treeview),
id,
longname);
g_free (id);
g_free (longname);
}
}
}
gtk_widget_hide (dialog->new_keyboard_dialog);
}
static void
remove_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GList *rows, *p;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
rows = gtk_tree_selection_get_selected_rows (selection, &model);
for (p = rows; p; p = p->next) {
GtkTreeIter iter;
if (gtk_tree_model_get_iter (model, &iter, p->data))
gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
}
}
static void
up_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreeIter prev = iter;
if (gtk_tree_model_iter_previous (model, &prev))
gtk_list_store_swap (GTK_LIST_STORE(model), &iter, &prev);
}
}
static void
down_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreeIter next = iter;
if (gtk_tree_model_iter_next (model, &next))
gtk_list_store_swap (GTK_LIST_STORE(model), &iter, &next);
}
}
static void
selection_changed_cb (GtkTreeSelection *selection, PreferencesDialog *dialog)
{
gint count = gtk_tree_selection_count_selected_rows (selection);
if (count > 0) {
gtk_widget_set_sensitive (dialog->remove_button, TRUE);
gtk_widget_set_sensitive (dialog->up_button, TRUE);
gtk_widget_set_sensitive (dialog->down_button, TRUE);
} else {
gtk_widget_set_sensitive (dialog->remove_button, FALSE);
gtk_widget_set_sensitive (dialog->up_button, FALSE);
gtk_widget_set_sensitive (dialog->down_button, FALSE);
}
}
static gint
compare_keyboard_id (const EekXmlKeyboardDesc *desc, const char *id)
{
return g_strcmp0 (desc->id, id);
}
static void
populate_selected_keyboards (PreferencesDialog *dialog)
{
gchar **strv, **p;
strv = g_settings_get_strv (dialog->settings, "keyboards");
for (p = strv; *p != NULL; p++) {
GList *head = g_list_find_custom (dialog->available_keyboards,
*p,
(GCompareFunc) compare_keyboard_id);
if (head == NULL) {
g_warning ("unknown keyboard %s", *p);
} else {
EekXmlKeyboardDesc *desc = head->data;
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->selected_keyboards_treeview),
desc->id,
desc->longname);
}
}
g_strfreev (strv);
}
static void
populate_available_keyboards (PreferencesDialog *dialog)
{
GList *p;
for (p = dialog->available_keyboards; p; p = p->next) {
EekXmlKeyboardDesc *desc = p->data;
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->available_keyboards_treeview),
desc->id,
desc->longname);
}
}
static void
save_keyboards (PreferencesDialog *dialog)
{
GtkTreeModel *model;
GtkTreeIter iter;
GList *list = NULL, *head;
gchar **strv, **p;
model = gtk_tree_view_get_model (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_model_get_iter_first (model, &iter)) {
do {
gchar *id;
gtk_tree_model_get (model, &iter, 0, &id, -1);
list = g_list_prepend (list, id);
} while (gtk_tree_model_iter_next (model, &iter));
}
list = g_list_reverse (list);
strv = g_new0 (gchar *, g_list_length (list) + 1);
for (head = list, p = strv; head; head = head->next, p++) {
*p = head->data;
}
g_settings_set_strv (dialog->settings,
"keyboards",
(const gchar * const *)strv);
g_strfreev (strv);
g_list_free (list);
}
PreferencesDialog *
preferences_dialog_new (void)
{
PreferencesDialog *dialog;
gchar *ui_path;
GtkBuilder *builder;
GObject *object;
GError *error;
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
dialog = g_slice_new0 (PreferencesDialog);
dialog->settings = g_settings_new ("org.fedorahosted.eekboard");
builder = gtk_builder_new ();
gtk_builder_set_translation_domain (builder, "eekboard");
ui_path = g_build_filename (PKGDATADIR,
"preferences-dialog.ui",
NULL);
error = NULL;
if (gtk_builder_add_from_file (builder, ui_path, &error) == 0) {
g_warning ("can't load %s: %s", ui_path, error->message);
g_error_free (error);
}
g_free (ui_path);
object = gtk_builder_get_object (builder, "dialog");
dialog->dialog = GTK_WIDGET(object);
object = gtk_builder_get_object (builder, "repeat_toggle");
dialog->repeat_toggle = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "repeat",
dialog->repeat_toggle, "active",
G_SETTINGS_BIND_DEFAULT);
object = gtk_builder_get_object (builder, "repeat_delay_scale");
dialog->repeat_delay_scale = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "repeat-delay",
gtk_range_get_adjustment (GTK_RANGE (dialog->repeat_delay_scale)), "value",
G_SETTINGS_BIND_DEFAULT);
object = gtk_builder_get_object (builder, "repeat_speed_scale");
dialog->repeat_speed_scale = GTK_WIDGET(object);
g_settings_bind_with_mapping (dialog->settings, "repeat-interval",
gtk_range_get_adjustment (GTK_RANGE (gtk_builder_get_object (builder, "repeat_speed_scale"))), "value",
G_SETTINGS_BIND_DEFAULT,
get_rate, set_rate, NULL, NULL);
object = gtk_builder_get_object (builder, "auto_hide_toggle");
dialog->auto_hide_toggle = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "auto-hide",
dialog->auto_hide_toggle, "active",
G_SETTINGS_BIND_DEFAULT);
object = gtk_builder_get_object (builder, "auto_hide_delay_scale");
dialog->auto_hide_delay_scale = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "auto-hide-delay",
gtk_range_get_adjustment (GTK_RANGE (dialog->auto_hide_delay_scale)), "value",
G_SETTINGS_BIND_DEFAULT);
object = gtk_builder_get_object (builder,
"selected_keyboards_treeview");
dialog->selected_keyboards_treeview = GTK_WIDGET(object);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (object));
g_signal_connect (G_OBJECT(selection), "changed",
G_CALLBACK(selection_changed_cb), dialog);
renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new ());
column = gtk_tree_view_column_new_with_attributes ("Keyboard",
renderer,
"text",
1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
object = gtk_builder_get_object (builder, "up_button");
dialog->up_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(up_keyboard), dialog);
object = gtk_builder_get_object (builder, "down_button");
dialog->down_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(down_keyboard), dialog);
object = gtk_builder_get_object (builder, "add_button");
dialog->add_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(add_keyboard), dialog);
object = gtk_builder_get_object (builder, "remove_button");
dialog->remove_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(remove_keyboard), dialog);
object = gtk_builder_get_object (builder, "new_keyboard_dialog");
dialog->new_keyboard_dialog = GTK_WIDGET(object);
object = gtk_builder_get_object (builder,
"available_keyboards_treeview");
dialog->available_keyboards_treeview = GTK_WIDGET(object);
renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new ());
column = gtk_tree_view_column_new_with_attributes ("Keyboard",
renderer,
"text",
1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
object = gtk_builder_get_object (builder,
"available_keyboards_liststore");
store = GTK_LIST_STORE(object);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
1,
GTK_SORT_ASCENDING);
dialog->available_keyboards = eek_xml_list_keyboards ();
populate_selected_keyboards (dialog);
populate_available_keyboards (dialog);
g_object_unref (builder);
return dialog;
}
void
preferences_dialog_run (PreferencesDialog *dialog)
{
gtk_window_present (GTK_WINDOW(dialog->dialog));
gtk_dialog_run (GTK_DIALOG(dialog->dialog));
save_keyboards (dialog);
}
void
preferences_dialog_free (PreferencesDialog *dialog)
{
gtk_widget_destroy (dialog->dialog);
// gtk_widget_destroy (dialog->new_keyboard_dialog);
g_object_unref (dialog->settings);
g_list_free_full (dialog->available_keyboards,
(GDestroyNotify) eek_xml_keyboard_desc_free);
g_slice_free (PreferencesDialog, dialog);
}

View File

@ -1,32 +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/>.
*/
#ifndef PREFERENCES_DIALOG_H
#define PREFERENCES_DIALOG_H 1
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _PreferencesDialog PreferencesDialog;
PreferencesDialog *preferences_dialog_new (void);
void preferences_dialog_run (PreferencesDialog *dialog);
void preferences_dialog_free (PreferencesDialog *dialog);
G_END_DECLS
#endif /* PREFERENCES_DIALOG_H */

View File

@ -1,729 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkAction" id="action1">
<property name="stock_id">gtk-close</property>
</object>
<object class="GtkAction" id="action2">
<property name="stock_id">gtk-cancel</property>
</object>
<object class="GtkAction" id="action3">
<property name="label" translatable="yes">Select</property>
<property name="stock_id">gtk-ok</property>
</object>
<object class="GtkAdjustment" id="auto_hide_delay_adjustment">
<property name="lower">100</property>
<property name="upper">2000</property>
<property name="value">500</property>
<property name="step_increment">10</property>
<property name="page_increment">10</property>
</object>
<object class="GtkListStore" id="available_keyboards_liststore">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkDialog" id="dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Keyboard</property>
<property name="modal">True</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="related_action">action1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="keyboard_notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">10</property>
<child>
<object class="GtkVBox" id="general_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="spacing">18</property>
<child>
<object class="GtkVBox" id="vbox22">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label300">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Repeat Keys</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox19">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label43">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox100">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="repeat_toggle">
<property name="label" translatable="yes">Key presses _repeat when key is held down</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="repeat_table">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">4</property>
<child>
<object class="GtkLabel" id="repeat_speed_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Speed:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">repeat_speed_scale</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="delay_short_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="xpad">10</property>
<property name="label" translatable="yes">Short</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="repeat_slow_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="xpad">10</property>
<property name="label" translatable="yes">Slow</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkHScale" id="repeat_delay_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">repeat_delay_adjustment</property>
<property name="draw_value">False</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkHScale" id="repeat_speed_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">repeat_speed_adjustment</property>
<property name="draw_value">False</property>
<child internal-child="accessible">
<object class="AtkObject" id="repeat_speed_scale-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Repeat keys speed</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="delay_long_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Long</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="repeat_fast_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Fast</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="repeat_delay_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Delay:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">repeat_delay_scale</property>
</object>
<packing>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox230">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Focus following</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox20">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label44">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="appearances_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="auto_hide_toggle">
<property name="label" translatable="yes">Auto hide window when focus is out</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_columns">4</property>
<child>
<object class="GtkLabel" id="auto_hide_delay_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Delay:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
<property name="mnemonic_widget">auto_hide_delay_scale</property>
</object>
<packing>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="auto_hide_delay_short_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="xpad">10</property>
<property name="label" translatable="yes">Short</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkHScale" id="auto_hide_delay_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">auto_hide_delay_adjustment</property>
<property name="draw_value">False</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="auto_hide_delay_long_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Long</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.82999999999999996"/>
</attributes>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options"></property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Typing</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="keyboards_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="spacing">18</property>
<child>
<object class="GtkTreeView" id="selected_keyboards_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">selected_keyboards_liststore</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection2"/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="up_button">
<property name="label">gtk-go-up</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="down_button">
<property name="label">gtk-go-down</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="add_button">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="remove_button">
<property name="label">gtk-remove</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Keyboards</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button1</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="new_keyboard_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="default_height">430</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="transient_for">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox2">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area2">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="related_action">action2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="related_action">action3</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="available_keyboards_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">available_keyboards_liststore</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection3"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button2</action-widget>
<action-widget response="-5">button3</action-widget>
</action-widgets>
</object>
<object class="GtkAdjustment" id="repeat_delay_adjustment">
<property name="lower">100</property>
<property name="upper">2000</property>
<property name="value">500</property>
<property name="step_increment">10</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="repeat_speed_adjustment">
<property name="lower">0.5</property>
<property name="upper">50</property>
<property name="value">33.299999999999997</property>
<property name="step_increment">1</property>
<property name="page_increment">1</property>
</object>
<object class="GtkListStore" id="selected_keyboards_liststore">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
</interface>

View File

@ -1,7 +1,7 @@
/*
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@ -65,10 +65,10 @@ static void set_dock (GtkWidget *widget,
GtkAllocation *allocation);
static void
on_monitors_changed (GdkScreen *screen,
gpointer user_data)
on_monitors_changed (GdkScreen *screen,
ServerContextService *context)
{
ServerContextService *context = user_data;
if (context->window)
set_geometry (context);
}
@ -87,18 +87,16 @@ on_destroy (GtkWidget *widget, gpointer user_data)
}
static void
on_notify_keyboard (GObject *object,
GParamSpec *spec,
gpointer user_data)
on_notify_keyboard (GObject *object,
GParamSpec *spec,
ServerContextService *context)
{
ServerContextService *context = user_data;
const EekKeyboard *keyboard;
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
if (!keyboard) {
if (!keyboard)
g_error("Programmer error: keyboard layout was unset!");
}
// The keymap will get set even if the window is hidden.
// It's not perfect,
@ -109,8 +107,7 @@ on_notify_keyboard (GObject *object,
if (context->window) {
if (keyboard == NULL) {
gtk_widget_hide (context->window);
gtk_widget_destroy (context->widget);
context->widget = NULL;
g_clear_pointer (&context->widget, gtk_widget_destroy);
} else {
gboolean was_visible = gtk_widget_get_visible (context->window);
/* avoid to send KeyboardVisibilityChanged */
@ -125,21 +122,21 @@ on_notify_keyboard (GObject *object,
}
}
}
static void
on_notify_fullscreen (GObject *object,
GParamSpec *spec,
gpointer user_data)
on_notify_fullscreen (GObject *object,
GParamSpec *spec,
ServerContextService *context)
{
ServerContextService *context = user_data;
if (context->window)
set_geometry (context);
}
static void
on_notify_visible (GObject *object, GParamSpec *spec, gpointer user_data)
on_notify_visible (GObject *object,
GParamSpec *spec,
ServerContextService *context)
{
ServerContextService *context = user_data;
gboolean visible;
g_object_get (object, "visible", &visible, NULL);
@ -155,7 +152,7 @@ set_dock (GtkWidget *widget, GtkAllocation *allocation)
/* 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;
@ -198,10 +195,9 @@ on_size_allocate_set_dock (GtkWidget *widget,
}
static void
on_realize_set_non_maximizable (GtkWidget *widget,
gpointer user_data)
on_realize_set_non_maximizable (GtkWidget *widget,
ServerContextService *context)
{
ServerContextService *context = user_data;
g_assert (context && context->window == widget);
@ -216,18 +212,16 @@ on_realize_set_non_maximizable (GtkWidget *widget,
static void
set_geometry (ServerContextService *context)
{
GdkScreen *screen;
GdkWindow *root;
gint monitor;
GdkScreen *screen = gdk_screen_get_default ();
GdkWindow *root = gdk_screen_get_root_window (screen);
GdkDisplay *display = gdk_display_get_default ();
GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, root);
EekKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
GdkRectangle rect;
const EekKeyboard *keyboard;
EekBounds bounds;
screen = gdk_screen_get_default ();
root = gtk_widget_get_root_window (context->window);
monitor = gdk_screen_get_monitor_at_window (screen, root);
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
gdk_monitor_get_geometry (monitor, &rect);
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
g_signal_handlers_disconnect_by_func (context->window,
@ -238,14 +232,14 @@ set_geometry (ServerContextService *context)
context);
if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
gint width = rect.width;
gint width = rect.width;
gint height = rect.height;
if (width > height) {
width *= context->size_constraint_landscape[0];
width *= context->size_constraint_landscape[0];
height *= context->size_constraint_landscape[1];
} else {
width *= context->size_constraint_portrait[0];
width *= context->size_constraint_portrait[0];
height *= context->size_constraint_portrait[1];
}
@ -281,31 +275,36 @@ set_geometry (ServerContextService *context)
}
}
#define KEYBOARD_HEIGHT 210
static void
make_window (ServerContextService *context) {
if (context->window) {
make_window (ServerContextService *context)
{
if (context->window)
g_error("Window already present");
return;
}
context->window = GTK_WIDGET(g_object_new (
context->window = g_object_new (
PHOSH_TYPE_LAYER_SURFACE,
"layer-shell", squeek_wayland->layer_shell,
"wl-output", g_ptr_array_index(squeek_wayland->outputs, 0), // TODO: select output as needed,
"height", 200,
"height", KEYBOARD_HEIGHT,
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
"kbd-interactivity", FALSE,
"exclusive-zone", 200,
"exclusive-zone", KEYBOARD_HEIGHT,
//"namespace", "phosh home",
NULL
));
);
g_signal_connect (context->window, "destroy",
G_CALLBACK(on_destroy), context);
G_CALLBACK(on_destroy),
context);
context->notify_visible_handler =
g_signal_connect (context->window, "notify::visible",
G_CALLBACK(on_notify_visible), context);
G_CALLBACK(on_notify_visible),
context);
// The properties below are just to make hacking easier.
// The way we use layer-shell overrides some,
@ -321,7 +320,8 @@ make_window (ServerContextService *context) {
}
static void
destroy_window (ServerContextService *context) {
destroy_window (ServerContextService *context)
{
context->window = NULL;
}
@ -329,25 +329,23 @@ static void
update_widget (ServerContextService *context)
{
EekKeyboard *keyboard;
EekBounds bounds;
gchar *theme_path;
EekTheme *theme;
if (context->widget) {
gtk_widget_destroy (context->widget);
context->widget = NULL;
}
theme_path = g_build_filename (THEMESDIR, "default.css", NULL);
theme = eek_theme_new (theme_path, NULL, NULL);
g_free (theme_path);
theme = eek_theme_new ("resource:///sm/puri/squeekboard/style.css",
NULL,
NULL);
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
context->widget = eek_gtk_keyboard_new (keyboard);
eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(context->widget), theme);
g_object_unref (theme);
g_clear_object (&theme);
gtk_widget_set_has_tooltip (context->widget, TRUE);
gtk_container_add (GTK_CONTAINER(context->window), context->widget);
@ -372,7 +370,8 @@ server_context_service_real_hide_keyboard (EekboardContextService *_context)
ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
gtk_widget_hide (context->window);
gtk_container_remove(GTK_CONTAINER(context->window), context->widget);
g_clear_pointer (&context->widget, gtk_widget_destroy);
destroy_window (context);
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
@ -394,8 +393,7 @@ 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);
context->was_visible = gtk_widget_get_visible (context->window);
gtk_widget_hide (context->window);
}
}
@ -439,10 +437,8 @@ server_context_service_dispose (GObject *object)
{
ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
if (context->window) {
gtk_widget_destroy (context->window);
context->window = NULL;
}
g_clear_pointer (&context->window, gtk_widget_destroy);
context->widget = NULL;
G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
}
@ -487,9 +483,8 @@ server_context_service_class_init (ServerContextServiceClass *klass)
static void
server_context_service_init (ServerContextService *context)
{
GdkScreen *screen;
GdkScreen *screen = gdk_screen_get_default ();
screen = gdk_screen_get_default ();
g_signal_connect (screen,
"monitors-changed",
G_CALLBACK(on_monitors_changed),
@ -498,6 +493,7 @@ server_context_service_init (ServerContextService *context)
"notify::keyboard",
G_CALLBACK(on_notify_keyboard),
context);
g_signal_connect (context,
"notify::fullscreen",
G_CALLBACK(on_notify_fullscreen),
@ -507,6 +503,5 @@ server_context_service_init (ServerContextService *context)
EekboardContextService *
server_context_service_new ()
{
return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE,
NULL));
return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL));
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2012 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2012 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/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "preferences-dialog.h"
#include <gtk/gtk.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
PreferencesDialog *dialog;
if (!gtk_init_check (&argc, &argv)) {
g_printerr ("Can't init GTK\n");
return EXIT_FAILURE;
}
dialog = preferences_dialog_new ();
preferences_dialog_run (dialog);
preferences_dialog_free (dialog);
return EXIT_SUCCESS;
}

View File

@ -1,544 +0,0 @@
/* squeek-input-method.c */
#include "squeek-input-method.h"
#include <stdio.h>
typedef struct _SqueekInputMethodPrivate {
struct zwp_input_method_v2 *input_method;
gchar *surrounding_text;
gchar *preedit_string;
guint serial;
guint cursor;
guint anchor;
guint hint;
guint purpose;
gboolean active : 1;
gboolean available : 1;
} SqueekInputMethodPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(SqueekInputMethod, squeek_input_method, G_TYPE_OBJECT)
/*
* TODO:
* - implement signals for 'done' and ... (?)
* - take it for a spin
* - fix things
* - look at 'zwp_input_popup_surface_v2' and think about it for a while
* ....
* - add some gir documentation
* - double check: everyting
*
* - MOVE ON
*/
enum {
PROP_0,
PROP_AVAILABLE,
PROP_ACTIVE,
PROP_CURSOR_POSITION,
PROP_ANCHOR_POSITION,
PROP_CONTENT_HINT,
PROP_CONTENT_PURPOSE,
PROP_SURROUNDING_TEXT,
PROP_PREEDIT_STRING,
LAST_PROP
};
static GParamSpec *properties[LAST_PROP];
/* input-method signals */
static void
squeek_input_method_activate(SqueekInputMethod *self)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
if (!priv->active) {
priv->active = TRUE;
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_ACTIVE]);
}
}
static void
squeek_input_method_deactivate(SqueekInputMethod *self)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
if (priv->active) {
priv->active = FALSE;
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_ACTIVE]);
}
}
static void
squeek_input_method_surrounding_text(SqueekInputMethod *self,
const gchar *text,
guint cursor,
guint anchor)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
g_clear_pointer(&priv->surrounding_text, g_free);
priv->surrounding_text = g_strdup(text);
priv->cursor = cursor;
priv->anchor = anchor;
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_SURROUNDING_TEXT]);
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_CURSOR_POSITION]);
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_ANCHOR_POSITION]);
}
static void
squeek_input_method_text_change_cause(SqueekInputMethod *self,
guint cause)
{
fprintf(stderr, "%s: not implemented\n", __func__);
}
static void
squeek_input_method_content_type(SqueekInputMethod *self,
guint hint,
guint purpose)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
priv->hint = hint;
priv->purpose = purpose;
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_CONTENT_HINT]);
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_CONTENT_PURPOSE]);
}
static void
squeek_input_method_done(SqueekInputMethod *self)
{
/*
Atomically applies state changes recently sent to the client.
The done event establishes and updates the state of the client, and
must be issued after any changes to apply them.
Text input state (content purpose, content hint, surrounding text, and
change cause) is conceptually double-buffered within an input method
context.
Events modify the pending state, as opposed to the current state in use
by the input method. A done event atomically applies all pending state,
replacing the current state. After done, the new pending state is as
documented for each related request.
Events must be applied in the order of arrival.
Neither current nor pending state are modified unless noted otherwise.
*/
fprintf(stderr, "%s: not implemented\n", __func__);
}
static void
squeek_input_method_unavailable(SqueekInputMethod *self)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
priv->available = FALSE;
g_clear_pointer(&priv->input_method, zwp_input_method_v2_destroy);
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_AVAILABLE]);
}
static void
imservice_handle_input_method_activate(void *data,
struct zwp_input_method_v2 *input_method)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->activate(data);
}
static void
imservice_handle_input_method_deactivate(void *data,
struct zwp_input_method_v2 *input_method)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->deactivate(data);
}
static void
imservice_handle_surrounding_text(void *data,
struct zwp_input_method_v2 *input_method,
const char *text,
uint32_t cursor,
uint32_t anchor)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->surrounding_text(data, text, cursor, anchor);
}
static void
imservice_handle_text_change_cause(void *data,
struct zwp_input_method_v2 *input_method,
uint32_t cause)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->text_change_cause(data, cause);
}
static void
imservice_handle_content_type(void *data,
struct zwp_input_method_v2 *input_method,
uint32_t hint,
uint32_t purpose)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->content_type(data, hint, purpose);
}
static void
imservice_handle_done(void *data,
struct zwp_input_method_v2 *input_method)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->done(data);
}
static void
imservice_handle_unavailable(void *data,
struct zwp_input_method_v2 *input_method)
{
g_return_if_fail(data && SQUEEK_IS_INPUT_METHOD(data));
SQUEEK_INPUT_METHOD_GET_CLASS(data)->unavailable(data);
}
static const struct zwp_input_method_v2_listener input_method_listener = {
.activate = imservice_handle_input_method_activate,
.deactivate = imservice_handle_input_method_deactivate,
.surrounding_text = imservice_handle_surrounding_text,
.text_change_cause = imservice_handle_text_change_cause,
.content_type = imservice_handle_content_type,
.done = imservice_handle_done,
.unavailable = imservice_handle_unavailable,
};
/* input-method requests */
static void
squeek_input_method_real_commit_string(SqueekInputMethod *self,
const gchar *string)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
zwp_input_method_v2_commit_string(priv->input_method,
string);
}
void
squeek_input_method_commit_string(SqueekInputMethod *self,
const gchar *string)
{
g_return_if_fail(self && SQUEEK_IS_INPUT_METHOD(self));
SQUEEK_INPUT_METHOD_GET_CLASS(self)->commit_string(self,
string);
}
static void
squeek_input_method_real_preedit_string(SqueekInputMethod *self,
const gchar *text,
gint cursor_begin,
gint cursor_end)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
g_clear_pointer(&priv->preedit_string, g_free);
priv->preedit_string = g_strdup(text);
/* TODO: think about cursor_[begin|end] */
zwp_input_method_v2_preedit_string(priv->input_method,
priv->preedit_string,
cursor_begin,
cursor_end);
g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_PREEDIT_STRING]);
}
void
squeek_input_method_preedit_string(SqueekInputMethod *self,
const gchar *text,
gint cursor_begin,
gint cursor_end)
{
g_return_if_fail(self && SQUEEK_IS_INPUT_METHOD(self));
SQUEEK_INPUT_METHOD_GET_CLASS(self)->preedit_string(self,
text,
cursor_begin,
cursor_end);
}
static void
squeek_input_method_real_delete_surrounding_text(SqueekInputMethod *self,
guint before_length,
guint after_length)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
zwp_input_method_v2_delete_surrounding_text(priv->input_method,
before_length,
after_length);
}
void
squeek_input_method_delete_surrounding_text(SqueekInputMethod *self,
guint before_length,
guint after_length)
{
g_return_if_fail(self && SQUEEK_IS_INPUT_METHOD(self));
SQUEEK_INPUT_METHOD_GET_CLASS(self)->delete_surrounding_text(self,
before_length,
after_length);
}
static void
squeek_input_method_real_commit(SqueekInputMethod *self)
{
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
g_return_if_fail(priv->available);
zwp_input_method_v2_commit(priv->input_method,
priv->serial++);
}
void
squeek_input_method_commit(SqueekInputMethod *self)
{
g_return_if_fail(self && SQUEEK_IS_INPUT_METHOD(self));
SQUEEK_INPUT_METHOD_GET_CLASS(self)->commit(self);
}
static void
squeek_input_method_dispose(GObject *object)
{
SqueekInputMethod *self = SQUEEK_INPUT_METHOD(object);
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
priv->active = FALSE;
priv->available = FALSE;
g_clear_pointer(&priv->input_method, zwp_input_method_v2_destroy);
G_OBJECT_CLASS(squeek_input_method_parent_class)->dispose(object);
}
static void
squeek_input_method_init(SqueekInputMethod *self)
{
}
static void
squeek_input_method_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SqueekInputMethod *self = SQUEEK_INPUT_METHOD(object);
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
switch (prop_id) {
case PROP_AVAILABLE:
g_value_set_boolean(value, priv->available);
break;
case PROP_ACTIVE:
g_value_set_boolean(value, priv->active);
break;
case PROP_CURSOR_POSITION:
g_value_set_uint(value, priv->cursor);
break;
case PROP_ANCHOR_POSITION:
g_value_set_uint(value, priv->anchor);
break;
case PROP_CONTENT_HINT:
g_value_set_flags(value, priv->hint);
break;
case PROP_CONTENT_PURPOSE:
g_value_set_enum(value, priv->purpose);
break;
case PROP_SURROUNDING_TEXT:
g_value_set_string(value, priv->surrounding_text);
break;
case PROP_PREEDIT_STRING:
g_value_set_string(value, priv->preedit_string);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
squeek_input_method_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SqueekInputMethod *self = SQUEEK_INPUT_METHOD(object);
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
switch (prop_id) {
case PROP_ACTIVE:
priv->active = g_value_get_boolean(value);
break;
/* FIXME: should preedit string be writable without setting cursor? */
case PROP_PREEDIT_STRING:
g_clear_pointer(&priv->preedit_string, g_free);
priv->preedit_string = g_strdup(g_value_get_string(value));
break;
case PROP_AVAILABLE:
/* fall-through: not writable */
case PROP_CURSOR_POSITION:
/* fall-through: not writable */
case PROP_ANCHOR_POSITION:
/* fall-through: not writable */
case PROP_CONTENT_HINT:
/* fall-through: not writable */
case PROP_CONTENT_PURPOSE:
/* fall-through: not writable */
case PROP_SURROUNDING_TEXT:
/* fall-through: not writable */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
squeek_input_method_class_init(SqueekInputMethodClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->dispose = squeek_input_method_dispose;
object_class->get_property = squeek_input_method_get_property;
object_class->set_property = squeek_input_method_set_property;
/* events */
klass->activate = squeek_input_method_activate;
klass->deactivate = squeek_input_method_deactivate;
klass->surrounding_text = squeek_input_method_surrounding_text;
klass->text_change_cause = squeek_input_method_text_change_cause;
klass->content_type = squeek_input_method_content_type;
klass->done = squeek_input_method_done;
klass->unavailable = squeek_input_method_unavailable;
/* requests */
klass->commit_string = squeek_input_method_real_commit_string;
klass->preedit_string = squeek_input_method_real_preedit_string;
klass->delete_surrounding_text = squeek_input_method_real_delete_surrounding_text;
klass->commit = squeek_input_method_real_commit;
properties[PROP_AVAILABLE] =
g_param_spec_boolean("available",
"available",
"Availability of this input method (destroy if FALSE)",
FALSE,
G_PARAM_READABLE);
properties[PROP_ACTIVE] =
g_param_spec_boolean("active",
"active",
"This input method is active",
FALSE,
G_PARAM_READWRITE);
properties[PROP_CURSOR_POSITION] =
g_param_spec_uint("cursor-position",
"cursor-position",
"The position of the cursor in characters",
0, G_MAXUINT, 0,
G_PARAM_READABLE);
properties[PROP_ANCHOR_POSITION] =
g_param_spec_uint("anchor-position",
"anchor-position",
"Offset where the current selection starts, or the same as cursor-position",
0, G_MAXUINT, 0,
G_PARAM_READABLE);
properties[PROP_CONTENT_HINT] =
g_param_spec_flags("content-hint",
"content-hint",
"Hint to guide the behaviour of the input method",
SQUEEK_TYPE_INPUT_METHOD_HINT,
SQUEEK_INPUT_METHOD_HINT_NONE,
G_PARAM_READABLE);
properties[PROP_CONTENT_PURPOSE] =
g_param_spec_enum("content-purpose",
"content-purpose",
"The purpose of a text input",
SQUEEK_TYPE_INPUT_METHOD_PURPOSE,
SQUEEK_INPUT_METHOD_PURPOSE_NORMAL,
G_PARAM_READABLE);
properties[PROP_SURROUNDING_TEXT] =
g_param_spec_string("surrounding-text",
"surrounding-text",
"The text surrounding the cursor",
"",
G_PARAM_READABLE);
properties[PROP_PREEDIT_STRING] =
g_param_spec_string("preedit-string",
"preedit-string",
"Pre-edit string",
"",
G_PARAM_READWRITE);
g_object_class_install_properties(object_class, LAST_PROP, properties);
}
SqueekInputMethod *
squeek_input_method_new(struct zwp_input_method_manager_v2 *manager,
struct wl_seat *seat)
{
SqueekInputMethod *self = g_object_new(SQUEEK_TYPE_INPUT_METHOD, NULL);
SqueekInputMethodPrivate *priv = squeek_input_method_get_instance_private(self);
priv->input_method = zwp_input_method_manager_v2_get_input_method(manager, seat);
zwp_input_method_v2_add_listener(priv->input_method, &input_method_listener, self);
return self;
}

View File

@ -1,181 +0,0 @@
#pragma once
#include <glib-object.h>
#include "input-method-unstable-v2-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
#include "squeek-enumtypes.h"
G_BEGIN_DECLS
#define SQUEEK_TYPE_INPUT_METHOD (squeek_input_method_get_type())
G_DECLARE_DERIVABLE_TYPE(SqueekInputMethod, squeek_input_method, SQUEEK, INPUT_METHOD, GObject)
typedef enum {
/**
* no special behavior
*/
SQUEEK_INPUT_METHOD_HINT_NONE = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
/**
* suggest word completions
*/
SQUEEK_INPUT_METHOD_HINT_COMPLETION = ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION,
/**
* suggest word corrections
*/
SQUEEK_INPUT_METHOD_HINT_SPELLCHECK = ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK,
/**
* switch to uppercase letters at the start of a sentence
*/
SQUEEK_INPUT_METHOD_HINT_AUTO_CAPITALIZATION = ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION,
/**
* prefer lowercase letters
*/
SQUEEK_INPUT_METHOD_HINT_LOWERCASE = ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE,
/**
* prefer uppercase letters
*/
SQUEEK_INPUT_METHOD_HINT_UPPERCASE = ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE,
/**
* prefer casing for titles and headings (can be language dependent)
*/
SQUEEK_INPUT_METHOD_HINT_TITLECASE = ZWP_TEXT_INPUT_V3_CONTENT_HINT_TITLECASE,
/**
* characters should be hidden
*/
SQUEEK_INPUT_METHOD_HINT_HIDDEN_TEXT = ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT,
/**
* typed text should not be stored
*/
SQUEEK_INPUT_METHOD_HINT_SENSITIVE_DATA = ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA,
/**
* just Latin characters should be entered
*/
SQUEEK_INPUT_METHOD_HINT_LATIN = ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN,
/**
* the text input is multiline
*/
SQUEEK_INPUT_METHOD_HINT_MULTILINE = ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE,
} SqueekInputMethodHint;
typedef enum {
/**
* default input, allowing all characters
*/
SQUEEK_INPUT_METHOD_PURPOSE_NORMAL = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL,
/**
* allow only alphabetic characters
*/
SQUEEK_INPUT_METHOD_PURPOSE_ALPHA = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA,
/**
* allow only digits
*/
SQUEEK_INPUT_METHOD_PURPOSE_DIGITS = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS,
/**
* input a number (including decimal separator and sign)
*/
SQUEEK_INPUT_METHOD_PURPOSE_NUMBER = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER,
/**
* input a phone number
*/
SQUEEK_INPUT_METHOD_PURPOSE_PHONE = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE,
/**
* input an URL
*/
SQUEEK_INPUT_METHOD_PURPOSE_URL = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL,
/**
* input an email address
*/
SQUEEK_INPUT_METHOD_PURPOSE_EMAIL = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL,
/**
* input a name of a person
*/
SQUEEK_INPUT_METHOD_PURPOSE_NAME = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME,
/**
* input a password (combine with sensitive_data hint)
*/
SQUEEK_INPUT_METHOD_PURPOSE_PASSWORD = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD,
/**
* input is a numeric password (combine with sensitive_data hint)
*/
SQUEEK_INPUT_METHOD_PURPOSE_PIN = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN,
/**
* input a date
*/
SQUEEK_INPUT_METHOD_PURPOSE_DATE = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE,
/**
* input a time
*/
SQUEEK_INPUT_METHOD_PURPOSE_TIME = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME,
/**
* input a date and time
*/
SQUEEK_INPUT_METHOD_PURPOSE_DATETIME = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME,
/**
* input for a terminal
*/
SQUEEK_INPUT_METHOD_PURPOSE_TERMINAL = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL,
} SqueekInputMethodPurpose;
struct _SqueekInputMethodClass {
GObjectClass parent_class;
/* input-method signals */
void (*activate) (SqueekInputMethod *self);
void (*deactivate) (SqueekInputMethod *self);
void (*surrounding_text) (SqueekInputMethod *self,
const gchar *text,
guint cursor,
guint anchor);
void (*text_change_cause) (SqueekInputMethod *self,
guint cause);
void (*content_type) (SqueekInputMethod *self,
guint hint,
guint purpose);
void (*done) (SqueekInputMethod *self);
void (*unavailable) (SqueekInputMethod *self);
/* input-method requests */
void (*commit_string) (SqueekInputMethod *self,
const gchar *string);
void (*preedit_string) (SqueekInputMethod *self,
const gchar *text,
gint cursor_begin,
gint cursor_end);
void (*delete_surrounding_text) (SqueekInputMethod *self,
guint before_length,
guint after_length);
void (*commit) (SqueekInputMethod *self);
};
void squeek_input_method_commit_string (SqueekInputMethod *self,
const gchar *string);
void squeek_input_method_preedit_string (SqueekInputMethod *self,
const gchar *text,
gint cursor_begin,
gint cursor_end);
void squeek_input_method_delete_surrounding_text(SqueekInputMethod *self,
guint before_length,
guint after_length);
void squeek_input_method_commit (SqueekInputMethod *self);
SqueekInputMethod *squeek_input_method_new (struct zwp_input_method_manager_v2 *manager,
struct wl_seat *seat);
G_END_DECLS